Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merge 9.0 |
|---|---|
| Timelines: | family | ancestors | descendants | both | tip-626 |
| Files: | files | file ages | folders |
| SHA3-256: |
d4eee66f60bbd3dafaa345694552f8f4 |
| User & Date: | jan.nijtmans 2024-04-01 20:48:23.462 |
Context
|
2024-04-14
| ||
| 14:05 | Merge 9.0 check-in: 1861587f45 user: jan.nijtmans tags: tip-626 | |
|
2024-04-01
| ||
| 20:48 | Merge 9.0 check-in: d4eee66f60 user: jan.nijtmans tags: tip-626 | |
| 20:07 | Oops, ckalloc -> Tcl_Alloc check-in: 0fe2f4f3ca user: jan.nijtmans tags: trunk, main | |
|
2024-03-20
| ||
| 14:27 | Merge 9.0 check-in: 4271f3b52a user: jan.nijtmans tags: tip-626 | |
Changes
Changes to doc/clock.n.
| ︙ | ︙ | |||
97 98 99 100 101 102 103 104 105 106 107 108 109 110 | 1 January 1970, 00:00 UTC. Note that the count of seconds does not include any leap seconds; seconds are counted as if each UTC day has exactly 86400 seconds. Tcl responds to leap seconds by speeding or slowing its clock by a tiny fraction for some minutes until it is back in sync with UTC; its data model does not represent minutes that have 59 or 61 seconds. .TP \fIunit\fR . One of the words, \fBseconds\fR, \fBminutes\fR, \fBhours\fR, \fBdays\fR, \fBweekdays\fR, \fBweeks\fR, \fBmonths\fR, or \fByears\fR. Used in conjunction with \fIcount\fR to identify an interval of time, for example, \fI3 seconds\fR or \fI1 year\fR. .SS "OPTIONS" | > > > > > > > > > | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | 1 January 1970, 00:00 UTC. Note that the count of seconds does not include any leap seconds; seconds are counted as if each UTC day has exactly 86400 seconds. Tcl responds to leap seconds by speeding or slowing its clock by a tiny fraction for some minutes until it is back in sync with UTC; its data model does not represent minutes that have 59 or 61 seconds. .TP \fI\-now\fR Instead of \fItimeVal\fR a non-integer option \fI\-now\fR can be used as replacement for today, which is simply interpolated to the runt-time as value of \fBclock seconds\fR. For example: .sp \fBclock format -now -f %a; # current day of the week\fR .sp \fBclock add -now 1 month; # next month\fR .TP \fIunit\fR . One of the words, \fBseconds\fR, \fBminutes\fR, \fBhours\fR, \fBdays\fR, \fBweekdays\fR, \fBweeks\fR, \fBmonths\fR, or \fByears\fR. Used in conjunction with \fIcount\fR to identify an interval of time, for example, \fI3 seconds\fR or \fI1 year\fR. .SS "OPTIONS" |
| ︙ | ︙ | |||
409 410 411 412 413 414 415 | .PP The date is determined according to the fields that are present in the preprocessed format string. In order of preference: .IP [1] If the string contains a \fB%s\fR format group, representing seconds from the epoch, that group is used to determine the date. .IP [2] | | > | > > > | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | .PP The date is determined according to the fields that are present in the preprocessed format string. In order of preference: .IP [1] If the string contains a \fB%s\fR format group, representing seconds from the epoch, that group is used to determine the date. .IP [2] If the string contains a \fB%J\fR, \fB%EJ\fR or \fB%Ej\fR format groups, representing the Calendar or Astronomical Julian Day Number, that groups are used to determine the date. Note, that in case of \fB%EJ\fR or \fB%Ej\fR format groups, representing the Julian Date with time fraction, this groups may be used to determine the date and time. .IP [3] If the string contains a complete set of format groups specifying century, year, month, and day of month; century, year, and day of year; or ISO8601 fiscal year, week of year, and day of week; those groups are combined and used to determine the date. If more than one complete set is present, the one at the rightmost position in the string is used. |
| ︙ | ︙ | |||
548 549 550 551 552 553 554 555 556 557 558 559 560 561 | On output, produces the string \fBB.C.E.\fR or \fBC.E.\fR, or a string of the same meaning in the locale, to indicate whether \fB%Y\fR refers to years before or after Year 1 of the Common Era. On input, accepts the string \fBB.C.E.\fR, \fBB.C.\fR, \fBC.E.\fR, \fBA.D.\fR, or the abbreviation appropriate to the current locale, and uses it to fix whether \fB%Y\fR refers to years before or after Year 1 of the Common Era. .IP \fB%Ex\fR On output, produces a locale-dependent representation of the date in the locale's alternative calendar. On input, matches whatever \fB%Ex\fR produces. The locale's alternative calendar need not be the Gregorian calendar. .IP \fB%EX\fR On output, produces a locale-dependent representation of the | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 | On output, produces the string \fBB.C.E.\fR or \fBC.E.\fR, or a string of the same meaning in the locale, to indicate whether \fB%Y\fR refers to years before or after Year 1 of the Common Era. On input, accepts the string \fBB.C.E.\fR, \fBB.C.\fR, \fBC.E.\fR, \fBA.D.\fR, or the abbreviation appropriate to the current locale, and uses it to fix whether \fB%Y\fR refers to years before or after Year 1 of the Common Era. .IP \fB%Ej\fR On output, produces a string of digits giving the Astronomical Julian Date or Astronomical Julian Day Number (JDN/JD). In opposite to calendar julian day \fB%J\fR, it starts the day at noon. On input, accepts a string of digits (or floating point with the time fraction) and interprets it as an Astronomical Julian Day Number (JDN/JD). The Astronomical Julian Date is a count of the number of calendar days that have elapsed since 1 January, 4713 BCE of the proleptic Julian calendar, which contains also the time fraktion (after floating point). The epoch time of 1 January 1970 corresponds to Astronomical JDN 2440587.5. This value corresponds the julian day used in sqlite-database, and is the same as result of \fBselect julianday(:seconds, 'unixepoch')\fR. .IP \fB%EJ\fR On output, produces a string of digits giving the Calendar Julian Date. In opposite to julian day \fB%J\fR format group, it produces float number. In opposite to astronomical julian day \fB%Ej\fR group, it starts at midnight. On input, accepts a string of digits (or floating point with the time fraction) and interprets it as a Calendar Julian Day Number. The Calendar Julian Date is a count of the number of calendar days that have elapsed since 1 January, 4713 BCE of the proleptic Julian calendar, which contains also the time fraktion (after floating point). The epoch time of 1 January 1970 corresponds to Astronomical JDN 2440588. .IP \fB%Es\fR This affects similar to \fB%s\fR, but in opposition to \fB%s\fR it parses or formats local seconds (not the posix seconds). Because \fB%s\fR has the same precedence as \fB%s\fR (uniquely determines a point in time), it overrides all other input formats. .IP \fB%Ex\fR On output, produces a locale-dependent representation of the date in the locale's alternative calendar. On input, matches whatever \fB%Ex\fR produces. The locale's alternative calendar need not be the Gregorian calendar. .IP \fB%EX\fR On output, produces a locale-dependent representation of the |
| ︙ | ︙ | |||
587 588 589 590 591 592 593 | .IP \fB%I\fR On output, produces a two-digit number giving the hour of the day (12-11) on a 12-hour clock. On input, accepts such a number. .IP \fB%j\fR On output, produces a three-digit number giving the day of the year (001-366). On input, accepts such a number. .IP \fB%J\fR | | | 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 | .IP \fB%I\fR On output, produces a two-digit number giving the hour of the day (12-11) on a 12-hour clock. On input, accepts such a number. .IP \fB%j\fR On output, produces a three-digit number giving the day of the year (001-366). On input, accepts such a number. .IP \fB%J\fR On output, produces a string of digits giving the calendar Julian Day Number. On input, accepts a string of digits and interprets it as a Julian Day Number. The Julian Day Number is a count of the number of calendar days that have elapsed since 1 January, 4713 BCE of the proleptic Julian calendar. The epoch time of 1 January 1970 corresponds to Julian Day Number 2440588. .IP \fB%k\fR On output, produces a one- or two-digit number giving the hour of the day |
| ︙ | ︙ | |||
708 709 710 711 712 713 714 | accepts four digits and may be used to determine calendar date. Note that \fB%Y\fR does not yield a year appropriate for use with the ISO8601 week number \fB%V\fR; programs should use \fB%G\fR for that purpose. .IP \fB%z\fR On output, produces the current time zone, expressed in hours and minutes east (+hhmm) or west (\-hhmm) of Greenwich. On input, accepts a time zone specifier (see \fBTIME ZONES\fR below) that will be used to | | > > | | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 | accepts four digits and may be used to determine calendar date. Note that \fB%Y\fR does not yield a year appropriate for use with the ISO8601 week number \fB%V\fR; programs should use \fB%G\fR for that purpose. .IP \fB%z\fR On output, produces the current time zone, expressed in hours and minutes east (+hhmm) or west (\-hhmm) of Greenwich. On input, accepts a time zone specifier (see \fBTIME ZONES\fR below) that will be used to determine the time zone (this token is optionally applicable on input, so the value is not mandatory and can be missing in input). .IP \fB%Z\fR On output, produces the current time zone's name, possibly translated to the given locale. On input, accepts a time zone specifier (see \fBTIME ZONES\fR below) that will be used to determine the time zone (token is also like \fB%z\fR optionally applicable on input). This option should, in general, be used on input only when parsing RFC822 dates. Other uses are fraught with ambiguity; for instance, the string \fBBST\fR may represent British Summer Time or Brazilian Standard Time. It is recommended that date/time strings for use by computers use numeric time zones instead. .IP \fB%%\fR On output, produces a literal .QW \fB%\fR |
| ︙ | ︙ | |||
918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 | Using that time as the base, day-of-week specifications are added. Next, relative specifications are used. If a date or day is specified, and no absolute or relative time is given, midnight is used. Finally, a correction is applied so that the correct hour of the day is produced after allowing for daylight savings time differences and the correct date is given when going from the end of a long month to a short month. .SH "SEE ALSO" msgcat(n) .SH KEYWORDS clock, date, time .SH "COPYRIGHT" Copyright \(co 2004 Kevin B. Kenny <kennykb@acm.org>. All rights reserved. '\" Local Variables: '\" mode: nroff '\" End: | > > > > > > > > > > > > > > > > > > | 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 | Using that time as the base, day-of-week specifications are added. Next, relative specifications are used. If a date or day is specified, and no absolute or relative time is given, midnight is used. Finally, a correction is applied so that the correct hour of the day is produced after allowing for daylight savings time differences and the correct date is given when going from the end of a long month to a short month. .PP The precedence of the applying of single tokens resp. which sequence will be used by calculating of the time is complex, e. g. heavily dependent on the precision of type of the token. .sp In example below the second date-string contains "next January", therefore it results in next year but in January. And third date-string besides "January" contains also additionally "Fri", so it results in the nearest Friday. Thus both win before "385 days" resp. make it more precise, because of higher precision of this token types. .CS % clock format [clock scan "5 years 18 months 385 days" -base 0 -gmt 1] -gmt 1 Thu Jul 21 00:00:00 GMT 1977 % clock format [clock scan "5 years 18 months 385 days next January" -base 0 -gmt 1] -gmt 1 Sat Jan 21 00:00:00 GMT 1978 % clock format [clock scan "5 years 18 months 385 days next January Fri" -base 0 -gmt 1] -gmt 1 Fri Jan 27 00:00:00 GMT 1978 .CE .SH "SEE ALSO" msgcat(n) .SH KEYWORDS clock, date, time .SH "COPYRIGHT" Copyright \(co 2004 Kevin B. Kenny <kennykb@acm.org>. All rights reserved. '\" Local Variables: '\" mode: nroff '\" End: |
Changes to doc/file.n.
| ︙ | ︙ | |||
69 70 71 72 73 74 75 | On Windows, \fB\-archive\fR gives the value or sets or clears the archive attribute of the file. \fB\-hidden\fR gives the value or sets or clears the hidden attribute of the file. \fB\-longname\fR will expand each path element to its long version. This attribute cannot be set. \fB\-readonly\fR gives the value or sets or clears the readonly attribute of the file. \fB\-shortname\fR gives a string where every path element is replaced with its short (8.3) version of the | > > | | | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | On Windows, \fB\-archive\fR gives the value or sets or clears the archive attribute of the file. \fB\-hidden\fR gives the value or sets or clears the hidden attribute of the file. \fB\-longname\fR will expand each path element to its long version. This attribute cannot be set. \fB\-readonly\fR gives the value or sets or clears the readonly attribute of the file. \fB\-shortname\fR gives a string where every path element is replaced with its short (8.3) version of the name if possible. For path elements that cannot be mapped to short names, the long name is retained. This attribute cannot be set. \fB\-system\fR gives or sets or clears the value of the system attribute of the file. .PP On Mac OS X and Darwin, \fB\-creator\fR gives or sets the Finder creator type of the file. \fB\-hidden\fR gives or sets or clears the hidden attribute of the file. \fB\-readonly\fR gives or sets or clears the readonly attribute of the file. \fB\-rsrclength\fR gives the length of the resource fork of the file, this attribute can only be set to the value 0, which results in the resource fork being stripped |
| ︙ | ︙ |
Changes to generic/tclArithSeries.c.
| ︙ | ︙ | |||
915 916 917 918 919 920 921 |
} else {
objv = NULL;
}
*objvPtr = objv;
*objcPtr = objc;
} else {
if (interp != NULL) {
| | | 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 |
} else {
objv = NULL;
}
*objvPtr = objv;
*objcPtr = objc;
} else {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("value is not an arithseries", TCL_INDEX_NONE));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "UNKNOWN", (void *)NULL);
}
return TCL_ERROR;
}
return TCL_OK;
}
|
| ︙ | ︙ |
Changes to generic/tclBinary.c.
| ︙ | ︙ | |||
508 509 510 511 512 513 514 |
unsigned char *dst = byteArrayPtr->bytes;
unsigned char *dstEnd = dst + numBytes;
const char *srcEnd = src + length;
int proper = 1;
for (; src < srcEnd && dst < dstEnd; ) {
int ch;
| | | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 |
unsigned char *dst = byteArrayPtr->bytes;
unsigned char *dstEnd = dst + numBytes;
const char *srcEnd = src + length;
int proper = 1;
for (; src < srcEnd && dst < dstEnd; ) {
int ch;
int count = TclUtfToUniChar(src, &ch);
if (ch > 255) {
proper = 0;
if (demandProper) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected byte sequence but character %"
|
| ︙ | ︙ | |||
2509 2510 2511 2512 2513 2514 2515 |
}
}
TclNewObj(resultObj);
data = Tcl_GetBytesFromObj(NULL, objv[objc - 1], &count);
if (data == NULL) {
pure = 0;
| | | 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 |
}
}
TclNewObj(resultObj);
data = Tcl_GetBytesFromObj(NULL, objv[objc - 1], &count);
if (data == NULL) {
pure = 0;
data = (unsigned char *)TclGetStringFromObj(objv[objc - 1], &count);
}
datastart = data;
dataend = data + count;
size = (count + 1) / 2;
begin = cursor = Tcl_SetByteArrayLength(resultObj, size);
while (data < dataend) {
value = 0;
|
| ︙ | ︙ | |||
2559 2560 2561 2562 2563 2564 2565 |
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
badChar:
if (pure) {
ucs4 = c;
} else {
| | | 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 |
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
badChar:
if (pure) {
ucs4 = c;
} else {
TclUtfToUniChar((const char *)(data - 1), &ucs4);
}
TclDecrRefCount(resultObj);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"invalid hexadecimal digit \"%c\" (U+%06X) at position %"
TCL_Z_MODIFIER "u", ucs4, ucs4, data - datastart - 1));
Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", (void *)NULL);
return TCL_ERROR;
|
| ︙ | ︙ | |||
2767 2768 2769 2770 2771 2772 2773 | Tcl_SetErrorCode(interp, "TCL", "BINARY", "ENCODE", "LINE_LENGTH", (void *)NULL); return TCL_ERROR; } lineLength = ((lineLength - 1) & -4) + 1; /* 5, 9, 13 ... */ break; case OPT_WRAPCHAR: | | | 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 |
Tcl_SetErrorCode(interp, "TCL", "BINARY", "ENCODE",
"LINE_LENGTH", (void *)NULL);
return TCL_ERROR;
}
lineLength = ((lineLength - 1) & -4) + 1; /* 5, 9, 13 ... */
break;
case OPT_WRAPCHAR:
wrapchar = (const unsigned char *)TclGetStringFromObj(
objv[i + 1], &wrapcharlen);
{
const unsigned char *p = wrapchar;
Tcl_Size numBytes = wrapcharlen;
while (numBytes) {
switch (*p) {
|
| ︙ | ︙ | |||
3023 3024 3025 3026 3027 3028 3029 |
TclDecrRefCount(resultObj);
return TCL_ERROR;
badUu:
if (pure) {
ucs4 = c;
} else {
| | | 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 |
TclDecrRefCount(resultObj);
return TCL_ERROR;
badUu:
if (pure) {
ucs4 = c;
} else {
TclUtfToUniChar((const char *)(data - 1), &ucs4);
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"invalid uuencode character \"%c\" (U+%06X) at position %"
TCL_Z_MODIFIER "u", ucs4, ucs4, data - datastart - 1));
Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", (void *)NULL);
TclDecrRefCount(resultObj);
return TCL_ERROR;
|
| ︙ | ︙ | |||
3198 3199 3200 3201 3202 3203 3204 |
ucs4 = c;
} else {
/* The decoder is byte-oriented. If we saw a byte that's not a
* valid member of the base64 alphabet, it could be the lead byte
* of a multi-byte character. */
/* Safe because we know data is NUL-terminated */
| | | 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 |
ucs4 = c;
} else {
/* The decoder is byte-oriented. If we saw a byte that's not a
* valid member of the base64 alphabet, it could be the lead byte
* of a multi-byte character. */
/* Safe because we know data is NUL-terminated */
TclUtfToUniChar((const char *)(data - 1), &ucs4);
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"invalid base64 character \"%c\" (U+%06X) at position %"
TCL_Z_MODIFIER "u", ucs4, ucs4, data - datastart - 1));
Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", (void *)NULL);
TclDecrRefCount(resultObj);
|
| ︙ | ︙ |
Changes to generic/tclClock.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | /* * tclClock.c -- * * Contains the time and date related commands. This code is derived from * the time and date facilities of TclX, by Mark Diekhans and Karl * Lehenbauer. * * Copyright © 1991-1995 Karl Lehenbauer & Mark Diekhans. * Copyright © 1995 Sun Microsystems, Inc. * Copyright © 2004 Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclTomMath.h" /* * Windows has mktime. The configurators do not check. */ #ifdef _WIN32 #define HAVE_MKTIME 1 #endif | > > > < < < < < < < < < < < < < < < > > > > < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < | < < | < | < < < > < < < < < < < < < < < < < < < < < < < < < | > | | | > | | < < < > > > > > > | > > > > > > > > | > > > | > | > > > > > > | > > | > | | | | < > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
/*
* tclClock.c --
*
* Contains the time and date related commands. This code is derived from
* the time and date facilities of TclX, by Mark Diekhans and Karl
* Lehenbauer.
*
* Copyright © 1991-1995 Karl Lehenbauer & Mark Diekhans.
* Copyright © 1995 Sun Microsystems, Inc.
* Copyright © 2004 Kevin B. Kenny. All rights reserved.
* Copyright © 2015 Sergey G. Brester aka sebres. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
#include "tclTomMath.h"
#include "tclStrIdxTree.h"
#include "tclDate.h"
/*
* Windows has mktime. The configurators do not check.
*/
#ifdef _WIN32
#define HAVE_MKTIME 1
#endif
/*
* Table of the days in each month, leap and common years
*/
static const int hath[2][12] = {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
static const int daysInPriorMonths[2][13] = {
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
};
/*
* Enumeration of the string literals used in [clock]
*/
CLOCK_LITERAL_ARRAY(Literals);
/* Msgcat literals for exact match (mcKey) */
CLOCK_LOCALE_LITERAL_ARRAY(MsgCtLiterals, "");
/* Msgcat index literals prefixed with _IDX_, used for quick dictionary search */
CLOCK_LOCALE_LITERAL_ARRAY(MsgCtLitIdxs, "_IDX_");
static const char *const eras[] = { "CE", "BCE", NULL };
/*
* Thread specific data block holding a 'struct tm' for the 'gmtime' and
* 'localtime' library calls.
*/
static Tcl_ThreadDataKey tmKey;
/*
* Mutex protecting 'gmtime', 'localtime' and 'mktime' calls and the statics
* in the date parsing code.
*/
TCL_DECLARE_MUTEX(clockMutex)
/*
* Function prototypes for local procedures in this file:
*/
static int ConvertUTCToLocalUsingTable(Tcl_Interp *,
TclDateFields *, Tcl_Size, Tcl_Obj *const[],
Tcl_WideInt *rangesVal);
static int ConvertUTCToLocalUsingC(Tcl_Interp *,
TclDateFields *, int);
static int ConvertLocalToUTC(void *clientData, Tcl_Interp *,
TclDateFields *, Tcl_Obj *timezoneObj, int);
static int ConvertLocalToUTCUsingTable(Tcl_Interp *,
TclDateFields *, int, Tcl_Obj *const[],
Tcl_WideInt *rangesVal);
static int ConvertLocalToUTCUsingC(Tcl_Interp *,
TclDateFields *, int);
static int ClockConfigureObjCmd(void *clientData,
Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]);
static void GetYearWeekDay(TclDateFields *, int);
static void GetGregorianEraYearDay(TclDateFields *, int);
static void GetMonthDay(TclDateFields *);
static Tcl_WideInt WeekdayOnOrBefore(int, Tcl_WideInt);
static Tcl_ObjCmdProc2 ClockClicksObjCmd;
static Tcl_ObjCmdProc2 ClockConvertlocaltoutcObjCmd;
static int ClockGetDateFields(void *clientData,
Tcl_Interp *interp, TclDateFields *fields,
Tcl_Obj *timezoneObj, int changeover);
static Tcl_ObjCmdProc2 ClockGetdatefieldsObjCmd;
static Tcl_ObjCmdProc2 ClockGetjuliandayfromerayearmonthdayObjCmd;
static Tcl_ObjCmdProc2 ClockGetjuliandayfromerayearweekdayObjCmd;
static Tcl_ObjCmdProc2 ClockGetenvObjCmd;
static Tcl_ObjCmdProc2 ClockMicrosecondsObjCmd;
static Tcl_ObjCmdProc2 ClockMillisecondsObjCmd;
static Tcl_ObjCmdProc2 ClockSecondsObjCmd;
static Tcl_ObjCmdProc2 ClockFormatObjCmd;
static Tcl_ObjCmdProc2 ClockScanObjCmd;
static int ClockScanCommit(
DateInfo *info,
ClockFmtScnCmdArgs *opts);
static int ClockFreeScan(
DateInfo *info,
Tcl_Obj *strObj, ClockFmtScnCmdArgs *opts);
static int ClockCalcRelTime(
DateInfo *info);
static Tcl_ObjCmdProc2 ClockAddObjCmd;
static int ClockValidDate(
DateInfo *,
ClockFmtScnCmdArgs *, int stage);
static struct tm * ThreadSafeLocalTime(const time_t *);
static size_t TzsetIfNecessary(void);
static void ClockDeleteCmdProc(void *);
static Tcl_ObjCmdProc2 ClockSafeCatchCmd;
/*
* Structure containing description of "native" clock commands to create.
*/
struct ClockCommand {
const char *name; /* The tail of the command name. The full name
* is "::tcl::clock::<name>". When NULL marks
* the end of the table. */
Tcl_ObjCmdProc2 *objCmdProc; /* Function that implements the command. This
* will always have the ClockClientData sent
* to it, but may well ignore this data. */
CompileProc *compileProc; /* The compiler for the command. */
void *clientData; /* Any clientData to give the command (if NULL
* a reference to ClockClientData will be sent) */
};
static const struct ClockCommand clockCommands[] = {
{"add", ClockAddObjCmd, TclCompileBasicMin1ArgCmd, NULL},
{"clicks", ClockClicksObjCmd, TclCompileClockClicksCmd, NULL},
{"format", ClockFormatObjCmd, TclCompileBasicMin1ArgCmd, NULL},
{"getenv", ClockGetenvObjCmd, TclCompileBasicMin1ArgCmd, NULL},
{"microseconds", ClockMicrosecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(1)},
{"milliseconds", ClockMillisecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(2)},
{"scan", ClockScanObjCmd, TclCompileBasicMin1ArgCmd, NULL},
{"seconds", ClockSecondsObjCmd, TclCompileClockReadingCmd, INT2PTR(3)},
{"ConvertLocalToUTC", ClockConvertlocaltoutcObjCmd, NULL, NULL},
{"GetDateFields", ClockGetdatefieldsObjCmd, NULL, NULL},
{"GetJulianDayFromEraYearMonthDay",
ClockGetjuliandayfromerayearmonthdayObjCmd, NULL, NULL},
{"GetJulianDayFromEraYearWeekDay",
ClockGetjuliandayfromerayearweekdayObjCmd, NULL, NULL},
{"catch", ClockSafeCatchCmd, TclCompileBasicMin1ArgCmd, NULL},
{NULL, NULL, NULL, NULL}
};
/*
*----------------------------------------------------------------------
*
* TclClockInit --
*
|
| ︙ | ︙ | |||
219 220 221 222 223 224 225 226 |
TclClockInit(
Tcl_Interp *interp) /* Tcl interpreter */
{
const struct ClockCommand *clockCmdPtr;
char cmdName[50]; /* Buffer large enough to hold the string
*::tcl::clock::GetJulianDayFromEraYearMonthDay
* plus a terminating NUL. */
ClockClientData *data;
| > | < < < < < < < < < < < < < > > > > > > > > > > > > | > > > > > > > > > > > > | > > > > > > > > > > | > > > > > < > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 |
TclClockInit(
Tcl_Interp *interp) /* Tcl interpreter */
{
const struct ClockCommand *clockCmdPtr;
char cmdName[50]; /* Buffer large enough to hold the string
*::tcl::clock::GetJulianDayFromEraYearMonthDay
* plus a terminating NUL. */
Command *cmdPtr;
ClockClientData *data;
Tcl_Size i;
/*
* Safe interps get [::clock] as alias to a parent, so do not need their
* own copies of the support routines.
*/
if (Tcl_IsSafe(interp)) {
return;
}
/*
* Create the client data, which is a refcounted literal pool.
*/
data = (ClockClientData *)Tcl_Alloc(sizeof(ClockClientData));
data->refCount = 0;
data->literals = (Tcl_Obj **)Tcl_Alloc(LIT__END * sizeof(Tcl_Obj*));
for (i = 0; i < LIT__END; ++i) {
TclInitObjRef(data->literals[i], Tcl_NewStringObj(Literals[i], -1));
}
data->mcLiterals = NULL;
data->mcLitIdxs = NULL;
data->mcDicts = NULL;
data->lastTZEpoch = 0;
data->currentYearCentury = ClockDefaultYearCentury;
data->yearOfCenturySwitch = ClockDefaultCenturySwitch;
data->validMinYear = INT_MIN;
data->validMaxYear = INT_MAX;
/* corresponds max of JDN in sqlite - 9999-12-31 23:59:59 per default */
data->maxJDN = 5373484.499999994;
data->systemTimeZone = NULL;
data->systemSetupTZData = NULL;
data->gmtSetupTimeZoneUnnorm = NULL;
data->gmtSetupTimeZone = NULL;
data->gmtSetupTZData = NULL;
data->gmtTZName = NULL;
data->lastSetupTimeZoneUnnorm = NULL;
data->lastSetupTimeZone = NULL;
data->lastSetupTZData = NULL;
data->prevSetupTimeZoneUnnorm = NULL;
data->prevSetupTimeZone = NULL;
data->prevSetupTZData = NULL;
data->defaultLocale = NULL;
data->defaultLocaleDict = NULL;
data->currentLocale = NULL;
data->currentLocaleDict = NULL;
data->lastUsedLocaleUnnorm = NULL;
data->lastUsedLocale = NULL;
data->lastUsedLocaleDict = NULL;
data->prevUsedLocaleUnnorm = NULL;
data->prevUsedLocale = NULL;
data->prevUsedLocaleDict = NULL;
data->lastBase.timezoneObj = NULL;
memset(&data->lastTZOffsCache, 0, sizeof(data->lastTZOffsCache));
data->defFlags = 0;
/*
* Install the commands.
*/
#define TCL_CLOCK_PREFIX_LEN 14 /* == strlen("::tcl::clock::") */
memcpy(cmdName, "::tcl::clock::", TCL_CLOCK_PREFIX_LEN);
for (clockCmdPtr=clockCommands ; clockCmdPtr->name!=NULL ; clockCmdPtr++) {
void *clientData;
strcpy(cmdName + TCL_CLOCK_PREFIX_LEN, clockCmdPtr->name);
if (!(clientData = clockCmdPtr->clientData)) {
clientData = data;
data->refCount++;
}
cmdPtr = (Command *)Tcl_CreateObjCommand2(interp, cmdName,
clockCmdPtr->objCmdProc, clientData,
clockCmdPtr->clientData ? NULL : ClockDeleteCmdProc);
cmdPtr->compileProc = clockCmdPtr->compileProc ?
clockCmdPtr->compileProc : TclCompileBasicMin0ArgCmd;
}
cmdPtr = (Command *)Tcl_CreateObjCommand2(interp,
"::tcl::unsupported::clock::configure",
ClockConfigureObjCmd, data, ClockDeleteCmdProc);
data->refCount++;
cmdPtr->compileProc = TclCompileBasicMin0ArgCmd;
}
/*
*----------------------------------------------------------------------
*
* ClockConfigureClear --
*
* Clean up cached resp. run-time storages used in clock commands.
*
* Shared usage for clean-up (ClockDeleteCmdProc) and "configure -clear".
*
* Results:
* None.
*
*----------------------------------------------------------------------
*/
static void
ClockConfigureClear(
ClockClientData *data)
{
ClockFrmScnClearCaches();
data->lastTZEpoch = 0;
TclUnsetObjRef(data->systemTimeZone);
TclUnsetObjRef(data->systemSetupTZData);
TclUnsetObjRef(data->gmtSetupTimeZoneUnnorm);
TclUnsetObjRef(data->gmtSetupTimeZone);
TclUnsetObjRef(data->gmtSetupTZData);
TclUnsetObjRef(data->gmtTZName);
TclUnsetObjRef(data->lastSetupTimeZoneUnnorm);
TclUnsetObjRef(data->lastSetupTimeZone);
TclUnsetObjRef(data->lastSetupTZData);
TclUnsetObjRef(data->prevSetupTimeZoneUnnorm);
TclUnsetObjRef(data->prevSetupTimeZone);
TclUnsetObjRef(data->prevSetupTZData);
TclUnsetObjRef(data->defaultLocale);
data->defaultLocaleDict = NULL;
TclUnsetObjRef(data->currentLocale);
data->currentLocaleDict = NULL;
TclUnsetObjRef(data->lastUsedLocaleUnnorm);
TclUnsetObjRef(data->lastUsedLocale);
data->lastUsedLocaleDict = NULL;
TclUnsetObjRef(data->prevUsedLocaleUnnorm);
TclUnsetObjRef(data->prevUsedLocale);
data->prevUsedLocaleDict = NULL;
TclUnsetObjRef(data->lastBase.timezoneObj);
TclUnsetObjRef(data->lastTZOffsCache[0].timezoneObj);
TclUnsetObjRef(data->lastTZOffsCache[0].tzName);
TclUnsetObjRef(data->lastTZOffsCache[1].timezoneObj);
TclUnsetObjRef(data->lastTZOffsCache[1].tzName);
TclUnsetObjRef(data->mcDicts);
}
/*
*----------------------------------------------------------------------
*
* ClockDeleteCmdProc --
*
* Remove a reference to the clock client data, and clean up memory
* when it's all gone.
*
* Results:
* None.
*
*----------------------------------------------------------------------
*/
static void
ClockDeleteCmdProc(
void *clientData) /* Opaque pointer to the client data */
{
ClockClientData *data = (ClockClientData *)clientData;
Tcl_Size i;
if (data->refCount-- <= 1) {
for (i = 0; i < LIT__END; ++i) {
Tcl_DecrRefCount(data->literals[i]);
}
if (data->mcLiterals != NULL) {
for (i = 0; i < MCLIT__END; ++i) {
Tcl_DecrRefCount(data->mcLiterals[i]);
}
data->mcLiterals = NULL;
}
if (data->mcLitIdxs != NULL) {
for (i = 0; i < MCLIT__END; ++i) {
Tcl_DecrRefCount(data->mcLitIdxs[i]);
}
data->mcLitIdxs = NULL;
}
ClockConfigureClear(data);
Tcl_Free(data->literals);
Tcl_Free(data);
}
}
/*
*----------------------------------------------------------------------
*
* SavePrevTimezoneObj --
*
* Used to store previously used/cached time zone (makes it reusable).
*
* This enables faster switch between time zones (e. g. to convert from one to another).
*
* Results:
* None.
*
*----------------------------------------------------------------------
*/
static inline void
SavePrevTimezoneObj(
ClockClientData *dataPtr) /* Client data containing literal pool */
{
Tcl_Obj *timezoneObj = dataPtr->lastSetupTimeZone;
if (timezoneObj && timezoneObj != dataPtr->prevSetupTimeZone) {
TclSetObjRef(dataPtr->prevSetupTimeZoneUnnorm, dataPtr->lastSetupTimeZoneUnnorm);
TclSetObjRef(dataPtr->prevSetupTimeZone, timezoneObj);
TclSetObjRef(dataPtr->prevSetupTZData, dataPtr->lastSetupTZData);
}
}
/*
*----------------------------------------------------------------------
*
* NormTimezoneObj --
*
* Normalizes the timezone object (used for caching puposes).
*
* If already cached time zone could be found, returns this
* object (last setup or last used, system (current) or gmt).
*
* Results:
* Normalized tcl object pointer.
*
*----------------------------------------------------------------------
*/
static Tcl_Obj *
NormTimezoneObj(
ClockClientData *dataPtr, /* Client data containing literal pool */
Tcl_Obj *timezoneObj, /* Name of zone to find */
int *loaded) /* Used to recognized TZ was loaded */
{
const char *tz;
*loaded = 1;
if ( timezoneObj == dataPtr->lastSetupTimeZoneUnnorm
&& dataPtr->lastSetupTimeZone != NULL
) {
return dataPtr->lastSetupTimeZone;
}
if ( timezoneObj == dataPtr->prevSetupTimeZoneUnnorm
&& dataPtr->prevSetupTimeZone != NULL
) {
return dataPtr->prevSetupTimeZone;
}
if (timezoneObj == dataPtr->gmtSetupTimeZoneUnnorm
&& dataPtr->gmtSetupTimeZone != NULL
) {
return dataPtr->literals[LIT_GMT];
}
if ( timezoneObj == dataPtr->lastSetupTimeZone
|| timezoneObj == dataPtr->prevSetupTimeZone
|| timezoneObj == dataPtr->gmtSetupTimeZone
|| timezoneObj == dataPtr->systemTimeZone
) {
return timezoneObj;
}
tz = TclGetString(timezoneObj);
if (dataPtr->lastSetupTimeZone != NULL &&
strcmp(tz, TclGetString(dataPtr->lastSetupTimeZone)) == 0
) {
TclSetObjRef(dataPtr->lastSetupTimeZoneUnnorm, timezoneObj);
return dataPtr->lastSetupTimeZone;
}
if (dataPtr->prevSetupTimeZone != NULL &&
strcmp(tz, TclGetString(dataPtr->prevSetupTimeZone)) == 0
) {
TclSetObjRef(dataPtr->prevSetupTimeZoneUnnorm, timezoneObj);
return dataPtr->prevSetupTimeZone;
}
if (dataPtr->systemTimeZone != NULL &&
strcmp(tz, TclGetString(dataPtr->systemTimeZone)) == 0
) {
return dataPtr->systemTimeZone;
}
if (strcmp(tz, Literals[LIT_GMT]) == 0) {
TclSetObjRef(dataPtr->gmtSetupTimeZoneUnnorm, timezoneObj);
if (dataPtr->gmtSetupTimeZone == NULL) {
*loaded = 0;
}
return dataPtr->literals[LIT_GMT];
}
/* unknown/unloaded tz - recache/revalidate later as last-setup if needed */
*loaded = 0;
return timezoneObj;
}
/*
*----------------------------------------------------------------------
*
* ClockGetSystemLocale --
*
* Returns system locale.
*
* Executes ::tcl::clock::GetSystemLocale in given interpreter.
*
* Results:
* Returns system locale tcl object.
*
*----------------------------------------------------------------------
*/
static inline Tcl_Obj *
ClockGetSystemLocale(
ClockClientData *dataPtr, /* Opaque pointer to literal pool, etc. */
Tcl_Interp *interp) /* Tcl interpreter */
{
if (Tcl_EvalObjv(interp, 1, &dataPtr->literals[LIT_GETSYSTEMLOCALE], 0) != TCL_OK) {
return NULL;
}
return Tcl_GetObjResult(interp);
}
/*
*----------------------------------------------------------------------
*
* ClockGetCurrentLocale --
*
* Returns current locale.
*
* Executes ::tcl::clock::mclocale in given interpreter.
*
* Results:
* Returns current locale tcl object.
*
*----------------------------------------------------------------------
*/
static inline Tcl_Obj *
ClockGetCurrentLocale(
ClockClientData *dataPtr, /* Client data containing literal pool */
Tcl_Interp *interp) /* Tcl interpreter */
{
if (Tcl_EvalObjv(interp, 1, &dataPtr->literals[LIT_GETCURRENTLOCALE], 0) != TCL_OK) {
return NULL;
}
TclSetObjRef(dataPtr->currentLocale, Tcl_GetObjResult(interp));
dataPtr->currentLocaleDict = NULL;
Tcl_ResetResult(interp);
return dataPtr->currentLocale;
}
/*
*----------------------------------------------------------------------
*
* SavePrevLocaleObj --
*
* Used to store previously used/cached locale (makes it reusable).
*
* This enables faster switch between locales (e. g. to convert from one to another).
*
* Results:
* None.
*
*----------------------------------------------------------------------
*/
static inline void
SavePrevLocaleObj(
ClockClientData *dataPtr) /* Client data containing literal pool */
{
Tcl_Obj *localeObj = dataPtr->lastUsedLocale;
if (localeObj && localeObj != dataPtr->prevUsedLocale) {
TclSetObjRef(dataPtr->prevUsedLocaleUnnorm, dataPtr->lastUsedLocaleUnnorm);
TclSetObjRef(dataPtr->prevUsedLocale, localeObj);
/* mcDicts owns reference to dict */
dataPtr->prevUsedLocaleDict = dataPtr->lastUsedLocaleDict;
}
}
/*
*----------------------------------------------------------------------
*
* NormLocaleObj --
*
* Normalizes the locale object (used for caching puposes).
*
* If already cached locale could be found, returns this
* object (current, system (OS) or last used locales).
*
* Results:
* Normalized tcl object pointer.
*
*----------------------------------------------------------------------
*/
static Tcl_Obj *
NormLocaleObj(
ClockClientData *dataPtr, /* Client data containing literal pool */
Tcl_Interp *interp, /* Tcl interpreter */
Tcl_Obj *localeObj,
Tcl_Obj **mcDictObj)
{
const char *loc, *loc2;
if ( localeObj == NULL
|| localeObj == dataPtr->literals[LIT_C]
|| localeObj == dataPtr->defaultLocale
) {
*mcDictObj = dataPtr->defaultLocaleDict;
return dataPtr->defaultLocale ?
dataPtr->defaultLocale : dataPtr->literals[LIT_C];
}
if ( localeObj == dataPtr->currentLocale
|| localeObj == dataPtr->literals[LIT_CURRENT]
) {
if (dataPtr->currentLocale == NULL) {
ClockGetCurrentLocale(dataPtr, interp);
}
*mcDictObj = dataPtr->currentLocaleDict;
return dataPtr->currentLocale;
}
if ( localeObj == dataPtr->lastUsedLocale
|| localeObj == dataPtr->lastUsedLocaleUnnorm
) {
*mcDictObj = dataPtr->lastUsedLocaleDict;
return dataPtr->lastUsedLocale;
}
if ( localeObj == dataPtr->prevUsedLocale
|| localeObj == dataPtr->prevUsedLocaleUnnorm
) {
*mcDictObj = dataPtr->prevUsedLocaleDict;
return dataPtr->prevUsedLocale;
}
loc = TclGetString(localeObj);
if ( dataPtr->currentLocale != NULL
&& ( localeObj == dataPtr->currentLocale
|| (localeObj->length == dataPtr->currentLocale->length
&& strcasecmp(loc, TclGetString(dataPtr->currentLocale)) == 0
)
)
) {
*mcDictObj = dataPtr->currentLocaleDict;
return dataPtr->currentLocale;
}
if ( dataPtr->lastUsedLocale != NULL
&& ( localeObj == dataPtr->lastUsedLocale
|| (localeObj->length == dataPtr->lastUsedLocale->length
&& strcasecmp(loc, TclGetString(dataPtr->lastUsedLocale)) == 0
)
)
) {
*mcDictObj = dataPtr->lastUsedLocaleDict;
TclSetObjRef(dataPtr->lastUsedLocaleUnnorm, localeObj);
return dataPtr->lastUsedLocale;
}
if ( dataPtr->prevUsedLocale != NULL
&& ( localeObj == dataPtr->prevUsedLocale
|| (localeObj->length == dataPtr->prevUsedLocale->length
&& strcasecmp(loc, TclGetString(dataPtr->prevUsedLocale)) == 0
)
)
) {
*mcDictObj = dataPtr->prevUsedLocaleDict;
TclSetObjRef(dataPtr->prevUsedLocaleUnnorm, localeObj);
return dataPtr->prevUsedLocale;
}
if (
(localeObj->length == 1 /* C */
&& strcasecmp(loc, Literals[LIT_C]) == 0)
|| (dataPtr->defaultLocale && (loc2 = TclGetString(dataPtr->defaultLocale))
&& localeObj->length == dataPtr->defaultLocale->length
&& strcasecmp(loc, loc2) == 0)
) {
*mcDictObj = dataPtr->defaultLocaleDict;
return dataPtr->defaultLocale ?
dataPtr->defaultLocale : dataPtr->literals[LIT_C];
}
if ( localeObj->length == 7 /* current */
&& strcasecmp(loc, Literals[LIT_CURRENT]) == 0
) {
if (dataPtr->currentLocale == NULL) {
ClockGetCurrentLocale(dataPtr, interp);
}
*mcDictObj = dataPtr->currentLocaleDict;
return dataPtr->currentLocale;
}
if (
(localeObj->length == 6 /* system */
&& strcasecmp(loc, Literals[LIT_SYSTEM]) == 0)
) {
SavePrevLocaleObj(dataPtr);
TclSetObjRef(dataPtr->lastUsedLocaleUnnorm, localeObj);
localeObj = ClockGetSystemLocale(dataPtr, interp);
TclSetObjRef(dataPtr->lastUsedLocale, localeObj);
*mcDictObj = NULL;
return localeObj;
}
*mcDictObj = NULL;
return localeObj;
}
/*
*----------------------------------------------------------------------
*
* ClockMCDict --
*
* Retrieves a localized storage dictionary object for the given
* locale object.
*
* This corresponds with call `::tcl::clock::mcget locale`.
* Cached representation stored in options (for further access).
*
* Results:
* Tcl-object contains smart reference to msgcat dictionary.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
ClockMCDict(ClockFmtScnCmdArgs *opts)
{
ClockClientData *dataPtr = (ClockClientData *)opts->clientData;
/* if dict not yet retrieved */
if (opts->mcDictObj == NULL) {
/* if locale was not yet used */
if ( !(opts->flags & CLF_LOCALE_USED) ) {
opts->localeObj = NormLocaleObj((ClockClientData *)opts->clientData, opts->interp,
opts->localeObj, &opts->mcDictObj);
if (opts->localeObj == NULL) {
Tcl_SetObjResult(opts->interp,
Tcl_NewStringObj("locale not specified and no default locale set", -1));
Tcl_SetErrorCode(opts->interp, "CLOCK", "badOption", (char *)NULL);
return NULL;
}
opts->flags |= CLF_LOCALE_USED;
/* check locale literals already available (on demand creation) */
if (dataPtr->mcLiterals == NULL) {
Tcl_Size i;
dataPtr->mcLiterals = (Tcl_Obj **)Tcl_Alloc(MCLIT__END * sizeof(Tcl_Obj*));
for (i = 0; i < MCLIT__END; ++i) {
TclInitObjRef(dataPtr->mcLiterals[i],
Tcl_NewStringObj(MsgCtLiterals[i], -1));
}
}
}
/* check or obtain mcDictObj (be sure it's modifiable) */
if (opts->mcDictObj == NULL || opts->mcDictObj->refCount > 1) {
int ref = 1;
/* first try to find locale catalog dict */
if (dataPtr->mcDicts == NULL) {
TclSetObjRef(dataPtr->mcDicts, Tcl_NewDictObj());
}
Tcl_DictObjGet(NULL, dataPtr->mcDicts,
opts->localeObj, &opts->mcDictObj);
if (opts->mcDictObj == NULL) {
/* get msgcat dictionary - ::tcl::clock::mcget locale */
Tcl_Obj *callargs[2];
callargs[0] = dataPtr->literals[LIT_MCGET];
callargs[1] = opts->localeObj;
if (Tcl_EvalObjv(opts->interp, 2, callargs, 0) != TCL_OK) {
return NULL;
}
opts->mcDictObj = Tcl_GetObjResult(opts->interp);
Tcl_ResetResult(opts->interp);
ref = 0; /* new object is not yet referenced */
}
/* be sure that object reference doesn't increase (dict changeable) */
if (opts->mcDictObj->refCount > ref) {
/* smart reference (shared dict as object with no ref-counter) */
opts->mcDictObj = TclDictObjSmartRef(opts->interp,
opts->mcDictObj);
}
/* create exactly one reference to catalog / make it searchable for future */
Tcl_DictObjPut(NULL, dataPtr->mcDicts, opts->localeObj,
opts->mcDictObj);
if ( opts->localeObj == dataPtr->literals[LIT_C]
|| opts->localeObj == dataPtr->defaultLocale
) {
dataPtr->defaultLocaleDict = opts->mcDictObj;
}
if ( opts->localeObj == dataPtr->currentLocale ) {
dataPtr->currentLocaleDict = opts->mcDictObj;
} else if ( opts->localeObj == dataPtr->lastUsedLocale ) {
dataPtr->lastUsedLocaleDict = opts->mcDictObj;
} else {
SavePrevLocaleObj(dataPtr);
TclSetObjRef(dataPtr->lastUsedLocale, opts->localeObj);
TclUnsetObjRef(dataPtr->lastUsedLocaleUnnorm);
dataPtr->lastUsedLocaleDict = opts->mcDictObj;
}
}
}
return opts->mcDictObj;
}
/*
*----------------------------------------------------------------------
*
* ClockMCGet --
*
* Retrieves a msgcat value for the given literal integer mcKey
* from localized storage (corresponding given locale object)
* by mcLiterals[mcKey] (e. g. MONTHS_FULL).
*
* Results:
* Tcl-object contains localized value.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
ClockMCGet(
ClockFmtScnCmdArgs *opts,
int mcKey)
{
ClockClientData *dataPtr = (ClockClientData *)opts->clientData;
Tcl_Obj *valObj = NULL;
if (opts->mcDictObj == NULL) {
ClockMCDict(opts);
if (opts->mcDictObj == NULL)
return NULL;
}
Tcl_DictObjGet(opts->interp, opts->mcDictObj,
dataPtr->mcLiterals[mcKey], &valObj);
return valObj; /* or NULL in obscure case if Tcl_DictObjGet failed */
}
/*
*----------------------------------------------------------------------
*
* ClockMCGetIdx --
*
* Retrieves an indexed msgcat value for the given literal integer mcKey
* from localized storage (corresponding given locale object)
* by mcLitIdxs[mcKey] (e. g. _IDX_MONTHS_FULL).
*
* Results:
* Tcl-object contains localized indexed value.
*
*----------------------------------------------------------------------
*/
MODULE_SCOPE Tcl_Obj *
ClockMCGetIdx(
ClockFmtScnCmdArgs *opts,
int mcKey)
{
ClockClientData *dataPtr = (ClockClientData *)opts->clientData;
Tcl_Obj *valObj = NULL;
if (opts->mcDictObj == NULL) {
ClockMCDict(opts);
if (opts->mcDictObj == NULL)
return NULL;
}
/* try to get indices object */
if (dataPtr->mcLitIdxs == NULL) {
return NULL;
}
if (Tcl_DictObjGet(NULL, opts->mcDictObj,
dataPtr->mcLitIdxs[mcKey], &valObj) != TCL_OK
) {
return NULL;
}
return valObj;
}
/*
*----------------------------------------------------------------------
*
* ClockMCSetIdx --
*
* Sets an indexed msgcat value for the given literal integer mcKey
* in localized storage (corresponding given locale object)
* by mcLitIdxs[mcKey] (e. g. _IDX_MONTHS_FULL).
*
* Results:
* Returns a standard Tcl result.
*
*----------------------------------------------------------------------
*/
int
ClockMCSetIdx(
ClockFmtScnCmdArgs *opts,
int mcKey, Tcl_Obj *valObj)
{
ClockClientData *dataPtr = (ClockClientData *)opts->clientData;
if (opts->mcDictObj == NULL) {
ClockMCDict(opts);
if (opts->mcDictObj == NULL)
return TCL_ERROR;
}
/* if literal storage for indices not yet created */
if (dataPtr->mcLitIdxs == NULL) {
Tcl_Size i;
dataPtr->mcLitIdxs = (Tcl_Obj **)Tcl_Alloc(MCLIT__END * sizeof(Tcl_Obj*));
for (i = 0; i < MCLIT__END; ++i) {
TclInitObjRef(dataPtr->mcLitIdxs[i],
Tcl_NewStringObj(MsgCtLitIdxs[i], -1));
}
}
return Tcl_DictObjPut(opts->interp, opts->mcDictObj,
dataPtr->mcLitIdxs[mcKey], valObj);
}
static void
TimezoneLoaded(
ClockClientData *dataPtr,
Tcl_Obj *timezoneObj, /* Name of zone was loaded */
Tcl_Obj *tzUnnormObj) /* Name of zone was loaded */
{
/* don't overwrite last-setup with GMT (special case) */
if (timezoneObj == dataPtr->literals[LIT_GMT]) {
/* mark GMT zone loaded */
if (dataPtr->gmtSetupTimeZone == NULL) {
TclSetObjRef(dataPtr->gmtSetupTimeZone,
dataPtr->literals[LIT_GMT]);
}
TclSetObjRef(dataPtr->gmtSetupTimeZoneUnnorm, tzUnnormObj);
return;
}
/* last setup zone loaded */
if (dataPtr->lastSetupTimeZone != timezoneObj) {
SavePrevTimezoneObj(dataPtr);
TclSetObjRef(dataPtr->lastSetupTimeZone, timezoneObj);
TclUnsetObjRef(dataPtr->lastSetupTZData);
}
TclSetObjRef(dataPtr->lastSetupTimeZoneUnnorm, tzUnnormObj);
}
/*
*----------------------------------------------------------------------
*
* ClockConfigureObjCmd --
*
* This function is invoked to process the Tcl "::clock::configure" (internal) command.
*
* Usage:
* ::tcl::unsupported::clock::configure ?-option ?value??
*
* Results:
* Returns a standard Tcl result.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
ClockConfigureObjCmd(
void *clientData, /* Client data containing literal pool */
Tcl_Interp *interp, /* Tcl interpreter */
Tcl_Size objc, /* Parameter count */
Tcl_Obj *const objv[]) /* Parameter vector */
{
ClockClientData *dataPtr = (ClockClientData *)clientData;
static const char *const options[] = {
"-system-tz", "-setup-tz", "-default-locale", "-current-locale",
"-clear",
"-year-century", "-century-switch",
"-min-year", "-max-year", "-max-jdn", "-validate",
"-init-complete",
NULL
};
enum optionInd {
CLOCK_SYSTEM_TZ, CLOCK_SETUP_TZ, CLOCK_DEFAULT_LOCALE, CLOCK_CURRENT_LOCALE,
CLOCK_CLEAR_CACHE,
CLOCK_YEAR_CENTURY, CLOCK_CENTURY_SWITCH,
CLOCK_MIN_YEAR, CLOCK_MAX_YEAR, CLOCK_MAX_JDN, CLOCK_VALIDATE,
CLOCK_INIT_COMPLETE
};
int optionIndex; /* Index of an option. */
Tcl_Size i;
for (i = 1; i < objc; i++) {
if (Tcl_GetIndexFromObj(interp, objv[i++], options,
"option", 0, &optionIndex) != TCL_OK) {
Tcl_SetErrorCode(interp, "CLOCK", "badOption",
Tcl_GetString(objv[i-1]), (char *)NULL);
return TCL_ERROR;
}
switch (optionIndex) {
case CLOCK_SYSTEM_TZ: {
/* validate current tz-epoch */
size_t lastTZEpoch = TzsetIfNecessary();
if (i < objc) {
if (dataPtr->systemTimeZone != objv[i]) {
TclSetObjRef(dataPtr->systemTimeZone, objv[i]);
TclUnsetObjRef(dataPtr->systemSetupTZData);
}
dataPtr->lastTZEpoch = lastTZEpoch;
}
if (i+1 >= objc && dataPtr->systemTimeZone != NULL
&& dataPtr->lastTZEpoch == lastTZEpoch) {
Tcl_SetObjResult(interp, dataPtr->systemTimeZone);
}
}
break;
case CLOCK_SETUP_TZ:
if (i < objc) {
int loaded;
Tcl_Obj *timezoneObj = NormTimezoneObj(dataPtr, objv[i], &loaded);
if (!loaded) {
TimezoneLoaded(dataPtr, timezoneObj, objv[i]);
}
Tcl_SetObjResult(interp, timezoneObj);
}
else
if (i+1 >= objc && dataPtr->lastSetupTimeZone != NULL) {
Tcl_SetObjResult(interp, dataPtr->lastSetupTimeZone);
}
break;
case CLOCK_DEFAULT_LOCALE:
if (i < objc) {
if (dataPtr->defaultLocale != objv[i]) {
TclSetObjRef(dataPtr->defaultLocale, objv[i]);
dataPtr->defaultLocaleDict = NULL;
}
}
if (i+1 >= objc) {
Tcl_SetObjResult(interp, dataPtr->defaultLocale ?
dataPtr->defaultLocale : dataPtr->literals[LIT_C]);
}
break;
case CLOCK_CURRENT_LOCALE:
if (i < objc) {
if (dataPtr->currentLocale != objv[i]) {
TclSetObjRef(dataPtr->currentLocale, objv[i]);
dataPtr->currentLocaleDict = NULL;
}
}
if (i+1 >= objc && dataPtr->currentLocale != NULL) {
Tcl_SetObjResult(interp, dataPtr->currentLocale);
}
break;
case CLOCK_YEAR_CENTURY:
if (i < objc) {
int year;
if (TclGetIntFromObj(interp, objv[i], &year) != TCL_OK) {
return TCL_ERROR;
}
dataPtr->currentYearCentury = year;
if (i+1 >= objc) {
Tcl_SetObjResult(interp, objv[i]);
}
continue;
}
if (i+1 >= objc) {
Tcl_SetObjResult(interp,
Tcl_NewWideIntObj(dataPtr->currentYearCentury));
}
break;
case CLOCK_CENTURY_SWITCH:
if (i < objc) {
int year;
if (TclGetIntFromObj(interp, objv[i], &year) != TCL_OK) {
return TCL_ERROR;
}
dataPtr->yearOfCenturySwitch = year;
Tcl_SetObjResult(interp, objv[i]);
continue;
}
if (i+1 >= objc) {
Tcl_SetObjResult(interp,
Tcl_NewWideIntObj(dataPtr->yearOfCenturySwitch));
}
break;
case CLOCK_MIN_YEAR:
if (i < objc) {
int year;
if (TclGetIntFromObj(interp, objv[i], &year) != TCL_OK) {
return TCL_ERROR;
}
dataPtr->validMinYear = year;
Tcl_SetObjResult(interp, objv[i]);
continue;
}
if (i+1 >= objc) {
Tcl_SetObjResult(interp,
Tcl_NewWideIntObj(dataPtr->validMinYear));
}
break;
case CLOCK_MAX_YEAR:
if (i < objc) {
int year;
if (TclGetIntFromObj(interp, objv[i], &year) != TCL_OK) {
return TCL_ERROR;
}
dataPtr->validMaxYear = year;
Tcl_SetObjResult(interp, objv[i]);
continue;
}
if (i+1 >= objc) {
Tcl_SetObjResult(interp,
Tcl_NewWideIntObj(dataPtr->validMaxYear));
}
break;
case CLOCK_MAX_JDN:
if (i < objc) {
double jd;
if (Tcl_GetDoubleFromObj(interp, objv[i], &jd) != TCL_OK) {
return TCL_ERROR;
}
dataPtr->maxJDN = jd;
Tcl_SetObjResult(interp, objv[i]);
continue;
}
if (i+1 >= objc) {
Tcl_SetObjResult(interp,
Tcl_NewDoubleObj(dataPtr->maxJDN));
}
break;
case CLOCK_VALIDATE:
if (i < objc) {
int val;
if (Tcl_GetBooleanFromObj(interp, objv[i], &val) != TCL_OK) {
return TCL_ERROR;
}
if (val) {
dataPtr->defFlags |= CLF_VALIDATE;
} else {
dataPtr->defFlags &= ~CLF_VALIDATE;
}
}
if (i+1 >= objc) {
Tcl_SetObjResult(interp,
Tcl_NewWideIntObj(dataPtr->defFlags & CLF_VALIDATE ? 1 : 0));
}
break;
case CLOCK_CLEAR_CACHE:
ClockConfigureClear(dataPtr);
break;
case CLOCK_INIT_COMPLETE:
{
/*
* Init completed.
* Compile clock ensemble (performance purposes).
*/
Tcl_Command token = Tcl_FindCommand(interp, "::clock",
NULL, TCL_GLOBAL_ONLY);
if (!token) {
return TCL_ERROR;
}
int ensFlags = 0;
if (Tcl_GetEnsembleFlags(interp, token, &ensFlags) != TCL_OK) {
return TCL_ERROR;
}
ensFlags |= ENSEMBLE_COMPILE;
if (Tcl_SetEnsembleFlags(interp, token, ensFlags) != TCL_OK) {
return TCL_ERROR;
}
}
break;
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ClockGetTZData --
*
* Retrieves tzdata table for given normalized timezone.
*
* Results:
* Returns a tcl object with tzdata.
*
* Side effects:
* The tzdata can be cached in ClockClientData structure.
*
*----------------------------------------------------------------------
*/
static inline Tcl_Obj *
ClockGetTZData(
void *clientData, /* Opaque pointer to literal pool, etc. */
Tcl_Interp *interp, /* Tcl interpreter */
Tcl_Obj *timezoneObj) /* Name of the timezone */
{
ClockClientData *dataPtr = (ClockClientData *)clientData;
Tcl_Obj *ret, **out = NULL;
/* if cached (if already setup this one) */
if ( timezoneObj == dataPtr->lastSetupTimeZone
|| timezoneObj == dataPtr->lastSetupTimeZoneUnnorm
) {
if (dataPtr->lastSetupTZData != NULL) {
return dataPtr->lastSetupTZData;
}
out = &dataPtr->lastSetupTZData;
}
/* differentiate GMT and system zones, because used often */
/* simple caching, because almost used the tz-data of last timezone
*/
if (timezoneObj == dataPtr->systemTimeZone) {
if (dataPtr->systemSetupTZData != NULL) {
return dataPtr->systemSetupTZData;
}
out = &dataPtr->systemSetupTZData;
}
else
if ( timezoneObj == dataPtr->literals[LIT_GMT]
|| timezoneObj == dataPtr->gmtSetupTimeZoneUnnorm
) {
if (dataPtr->gmtSetupTZData != NULL) {
return dataPtr->gmtSetupTZData;
}
out = &dataPtr->gmtSetupTZData;
}
else
if ( timezoneObj == dataPtr->prevSetupTimeZone
|| timezoneObj == dataPtr->prevSetupTimeZoneUnnorm
) {
if (dataPtr->prevSetupTZData != NULL) {
return dataPtr->prevSetupTZData;
}
out = &dataPtr->prevSetupTZData;
}
ret = Tcl_ObjGetVar2(interp, dataPtr->literals[LIT_TZDATA],
timezoneObj, TCL_LEAVE_ERR_MSG);
/* cache using corresponding slot and as last used */
if (out != NULL) {
TclSetObjRef(*out, ret);
}
else
if (dataPtr->lastSetupTimeZone != timezoneObj) {
SavePrevTimezoneObj(dataPtr);
TclSetObjRef(dataPtr->lastSetupTimeZone, timezoneObj);
TclUnsetObjRef(dataPtr->lastSetupTimeZoneUnnorm);
TclSetObjRef(dataPtr->lastSetupTZData, ret);
}
return ret;
}
/*
*----------------------------------------------------------------------
*
* ClockGetSystemTimeZone --
*
* Returns system (current) timezone.
*
* If system zone not yet cached, it executes ::tcl::clock::GetSystemTimeZone
* in given interpreter and caches its result.
*
* Results:
* Returns normalized timezone object.
*
*----------------------------------------------------------------------
*/
static Tcl_Obj *
ClockGetSystemTimeZone(
void *clientData, /* Opaque pointer to literal pool, etc. */
Tcl_Interp *interp) /* Tcl interpreter */
{
ClockClientData *dataPtr = (ClockClientData *)clientData;
/* if known (cached and same epoch) - return now */
if (dataPtr->systemTimeZone != NULL
&& dataPtr->lastTZEpoch == TzsetIfNecessary()) {
return dataPtr->systemTimeZone;
}
TclUnsetObjRef(dataPtr->systemTimeZone);
TclUnsetObjRef(dataPtr->systemSetupTZData);
if (Tcl_EvalObjv(interp, 1, &dataPtr->literals[LIT_GETSYSTEMTIMEZONE], 0) != TCL_OK) {
return NULL;
}
if (dataPtr->systemTimeZone == NULL) {
TclSetObjRef(dataPtr->systemTimeZone, Tcl_GetObjResult(interp));
}
Tcl_ResetResult(interp);
return dataPtr->systemTimeZone;
}
/*
*----------------------------------------------------------------------
*
* ClockSetupTimeZone --
*
* Sets up the timezone. Loads tzdata, etc.
*
* Results:
* Returns normalized timezone object.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
ClockSetupTimeZone(
void *clientData, /* Opaque pointer to literal pool, etc. */
Tcl_Interp *interp, /* Tcl interpreter */
Tcl_Obj *timezoneObj)
{
ClockClientData *dataPtr = (ClockClientData *)clientData;
int loaded;
Tcl_Obj *callargs[2];
/* if cached (if already setup this one) */
if ( timezoneObj == dataPtr->literals[LIT_GMT]
&& dataPtr->gmtSetupTZData != NULL
) {
return timezoneObj;
}
if ( ( timezoneObj == dataPtr->lastSetupTimeZone
|| timezoneObj == dataPtr->lastSetupTimeZoneUnnorm
) && dataPtr->lastSetupTimeZone != NULL
) {
return dataPtr->lastSetupTimeZone;
}
if ( ( timezoneObj == dataPtr->prevSetupTimeZone
|| timezoneObj == dataPtr->prevSetupTimeZoneUnnorm
) && dataPtr->prevSetupTimeZone != NULL
) {
return dataPtr->prevSetupTimeZone;
}
/* differentiate normalized (last, GMT and system) zones, because used often and already set */
callargs[1] = NormTimezoneObj(dataPtr, timezoneObj, &loaded);
/* if loaded (setup already called for this TZ) */
if (loaded) {
return callargs[1];
}
/* before setup just take a look in TZData variable */
if (Tcl_ObjGetVar2(interp, dataPtr->literals[LIT_TZDATA], timezoneObj, 0)) {
/* put it to last slot and return normalized */
TimezoneLoaded(dataPtr, callargs[1], timezoneObj);
return callargs[1];
}
/* setup now */
callargs[0] = dataPtr->literals[LIT_SETUPTIMEZONE];
if (Tcl_EvalObjv(interp, 2, callargs, 0) == TCL_OK) {
/* save unnormalized last used */
TclSetObjRef(dataPtr->lastSetupTimeZoneUnnorm, timezoneObj);
return callargs[1];
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* ClockFormatNumericTimeZone --
*
* Formats a time zone as +hhmmss
*
* Parameters:
* z - Time zone in seconds east of Greenwich
*
* Results:
* Returns the time zone object (formatted in a numeric form)
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
ClockFormatNumericTimeZone(int z) {
char buf[12+1], *p;
if ( z < 0 ) {
z = -z;
*buf = '-';
} else {
*buf = '+';
}
TclItoAw(buf+1, z / 3600, '0', 2); z %= 3600;
p = TclItoAw(buf+3, z / 60, '0', 2); z %= 60;
if (z != 0) {
p = TclItoAw(buf+5, z, '0', 2);
}
return Tcl_NewStringObj(buf, p - buf);
}
/*
*----------------------------------------------------------------------
*
* ClockConvertlocaltoutcObjCmd --
*
* Tcl command that converts a UTC time to a local time by whatever means
* is available.
*
* Usage:
* ::tcl::clock::ConvertUTCToLocal dictionary timezone changeover
*
* Parameters:
* dict - Dictionary containing a 'localSeconds' entry.
* timezone - Time zone
* changeover - Julian Day of the adoption of the Gregorian calendar.
*
* Results:
* Returns a standard Tcl result.
*
* Side effects:
* On success, sets the interpreter result to the given dictionary
|
| ︙ | ︙ | |||
317 318 319 320 321 322 323 324 325 326 327 328 |
Tcl_Obj *secondsObj;
Tcl_Obj *dict;
int changeover;
TclDateFields fields;
int created = 0;
int status;
/*
* Check params and convert time.
*/
if (objc != 4) {
| > | | | 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 |
Tcl_Obj *secondsObj;
Tcl_Obj *dict;
int changeover;
TclDateFields fields;
int created = 0;
int status;
fields.tzName = NULL;
/*
* Check params and convert time.
*/
if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv, "dict timezone changeover");
return TCL_ERROR;
}
dict = objv[1];
if (Tcl_DictObjGet(interp, dict, data->literals[LIT_LOCALSECONDS],
&secondsObj)!= TCL_OK) {
return TCL_ERROR;
}
if (secondsObj == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("key \"localseconds\" not "
"found in dictionary", -1));
return TCL_ERROR;
}
if ((TclGetWideIntFromObj(interp, secondsObj,
&fields.localSeconds) != TCL_OK)
|| (TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK)
|| ConvertLocalToUTC(clientData, interp, &fields, objv[2], changeover)) {
return TCL_ERROR;
}
/*
* Copy-on-write; set the 'seconds' field in the dictionary and place the
* modified dictionary in the interpreter result.
*/
|
| ︙ | ︙ | |||
372 373 374 375 376 377 378 | * * ClockGetdatefieldsObjCmd -- * * Tcl command that determines the values that [clock format] will use in * formatting a date, and populates a dictionary with them. * * Usage: | | | < | 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 | * * ClockGetdatefieldsObjCmd -- * * Tcl command that determines the values that [clock format] will use in * formatting a date, and populates a dictionary with them. * * Usage: * ::tcl::clock::GetDateFields seconds timezone changeover * * Parameters: * seconds - Time expressed in seconds from the Posix epoch. * timezone - Time zone in which time is to be expressed. * changeover - Julian Day Number at which the current locale adopted * the Gregorian calendar * * Results: * Returns a dictonary populated with the fields: * seconds - Seconds from the Posix epoch * localSeconds - Nominal seconds from the Posix epoch in the |
| ︙ | ︙ | |||
406 407 408 409 410 411 412 413 414 415 416 417 |
{
TclDateFields fields;
Tcl_Obj *dict;
ClockClientData *data = (ClockClientData *)clientData;
Tcl_Obj *const *lit = data->literals;
int changeover;
/*
* Check params.
*/
if (objc != 4) {
| > > | | < < > | < < < < | < < < < < < < < < < < | 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 |
{
TclDateFields fields;
Tcl_Obj *dict;
ClockClientData *data = (ClockClientData *)clientData;
Tcl_Obj *const *lit = data->literals;
int changeover;
fields.tzName = NULL;
/*
* Check params.
*/
if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv, "seconds timezone changeover");
return TCL_ERROR;
}
if (TclGetWideIntFromObj(interp, objv[1], &fields.seconds) != TCL_OK
|| TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK) {
return TCL_ERROR;
}
/*
* fields.seconds could be an unsigned number that overflowed. Make sure
* that it isn't.
*/
if (TclHasInternalRep(objv[1], &tclBignumType)) {
Tcl_SetObjResult(interp, lit[LIT_INTEGER_VALUE_TOO_LARGE]);
return TCL_ERROR;
}
/* Extract fields */
if (ClockGetDateFields(clientData, interp, &fields, objv[2],
changeover) != TCL_OK) {
return TCL_ERROR;
}
/* Make dict of fields */
dict = Tcl_NewDictObj();
Tcl_DictObjPut(NULL, dict, lit[LIT_LOCALSECONDS],
Tcl_NewWideIntObj(fields.localSeconds));
Tcl_DictObjPut(NULL, dict, lit[LIT_SECONDS],
Tcl_NewWideIntObj(fields.seconds));
Tcl_DictObjPut(NULL, dict, lit[LIT_TZNAME], fields.tzName);
|
| ︙ | ︙ | |||
485 486 487 488 489 490 491 492 493 494 495 496 497 498 |
Tcl_NewWideIntObj(fields.iso8601Year));
Tcl_DictObjPut(NULL, dict, lit[LIT_ISO8601WEEK],
Tcl_NewWideIntObj(fields.iso8601Week));
Tcl_DictObjPut(NULL, dict, lit[LIT_DAYOFWEEK],
Tcl_NewWideIntObj(fields.dayOfWeek));
Tcl_SetObjResult(interp, dict);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ClockGetjuliandayfromerayearmonthdayObjCmd --
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 |
Tcl_NewWideIntObj(fields.iso8601Year));
Tcl_DictObjPut(NULL, dict, lit[LIT_ISO8601WEEK],
Tcl_NewWideIntObj(fields.iso8601Week));
Tcl_DictObjPut(NULL, dict, lit[LIT_DAYOFWEEK],
Tcl_NewWideIntObj(fields.dayOfWeek));
Tcl_SetObjResult(interp, dict);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ClockGetDateFields --
*
* Converts given UTC time (seconds in a TclDateFields structure)
* to local time and determines the values that clock routines will
* use in scanning or formatting a date.
*
* Results:
* Date-time values are stored in structure "fields".
* Returns a standard Tcl result.
*
*----------------------------------------------------------------------
*/
int
ClockGetDateFields(
void *clientData, /* Client data of the interpreter */
Tcl_Interp *interp, /* Tcl interpreter */
TclDateFields *fields, /* Pointer to result fields, where
* fields->seconds contains date to extract */
Tcl_Obj *timezoneObj, /* Time zone object or NULL for gmt */
int changeover) /* Julian Day Number */
{
/*
* Convert UTC time to local.
*/
if (ConvertUTCToLocal(clientData, interp, fields, timezoneObj,
changeover) != TCL_OK) {
return TCL_ERROR;
}
/*
* Extract Julian day and seconds of the day.
*/
ClockExtractJDAndSODFromSeconds(fields->julianDay, fields->secondOfDay,
fields->localSeconds);
/*
* Convert to Julian or Gregorian calendar.
*/
GetGregorianEraYearDay(fields, changeover);
GetMonthDay(fields);
GetYearWeekDay(fields, changeover);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ClockGetjuliandayfromerayearmonthdayObjCmd --
|
| ︙ | ︙ | |||
564 565 566 567 568 569 570 571 572 573 574 575 576 577 |
Tcl_Obj *dict;
ClockClientData *data = (ClockClientData *)clientData;
Tcl_Obj *const *lit = data->literals;
int changeover;
int copied = 0;
int status;
int isBce = 0;
/*
* Check params.
*/
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "dict changeover");
| > > | 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 |
Tcl_Obj *dict;
ClockClientData *data = (ClockClientData *)clientData;
Tcl_Obj *const *lit = data->literals;
int changeover;
int copied = 0;
int status;
int isBce = 0;
fields.tzName = NULL;
/*
* Check params.
*/
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "dict changeover");
|
| ︙ | ︙ | |||
649 650 651 652 653 654 655 656 657 658 659 660 661 662 |
ClockClientData *data = (ClockClientData *)clientData;
Tcl_Obj *const *lit = data->literals;
int changeover;
int copied = 0;
int status;
int isBce = 0;
/*
* Check params.
*/
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "dict changeover");
return TCL_ERROR;
| > > | 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 |
ClockClientData *data = (ClockClientData *)clientData;
Tcl_Obj *const *lit = data->literals;
int changeover;
int copied = 0;
int status;
int isBce = 0;
fields.tzName = NULL;
/*
* Check params.
*/
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "dict changeover");
return TCL_ERROR;
|
| ︙ | ︙ | |||
716 717 718 719 720 721 722 723 724 |
* in the interpreter result on failure.
*
*----------------------------------------------------------------------
*/
static int
ConvertLocalToUTC(
Tcl_Interp *interp, /* Tcl interpreter */
TclDateFields *fields, /* Fields of the time */
| > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 |
* in the interpreter result on failure.
*
*----------------------------------------------------------------------
*/
static int
ConvertLocalToUTC(
void *clientData, /* Client data of the interpreter */
Tcl_Interp *interp, /* Tcl interpreter */
TclDateFields *fields, /* Fields of the time */
Tcl_Obj *timezoneObj, /* Time zone */
int changeover) /* Julian Day of the Gregorian transition */
{
ClockClientData *dataPtr = (ClockClientData *)clientData;
Tcl_Obj *tzdata; /* Time zone data */
Tcl_Size rowc; /* Number of rows in tzdata */
Tcl_Obj **rowv; /* Pointers to the rows */
Tcl_WideInt seconds;
ClockLastTZOffs * ltzoc = NULL;
/* fast phase-out for shared GMT-object (don't need to convert UTC 2 UTC) */
if (timezoneObj == dataPtr->literals[LIT_GMT]) {
fields->seconds = fields->localSeconds;
fields->tzOffset = 0;
return TCL_OK;
}
/*
* Check cacheable conversion could be used
* (last-period UTC2Local cache within the same TZ and seconds)
*/
for (rowc = 0; rowc < 2; rowc++) {
ltzoc = &dataPtr->lastTZOffsCache[rowc];
if (timezoneObj != ltzoc->timezoneObj || changeover != ltzoc->changeover) {
ltzoc = NULL;
continue;
}
seconds = fields->localSeconds - ltzoc->tzOffset;
if ( seconds >= ltzoc->rangesVal[0]
&& seconds < ltzoc->rangesVal[1]
) {
/* the same time zone and offset (UTC time inside the last minute) */
fields->tzOffset = ltzoc->tzOffset;
fields->seconds = seconds;
return TCL_OK;
}
/* in the DST-hole (because of the check above) - correct localSeconds */
if (fields->localSeconds == ltzoc->localSeconds) {
/* the same time zone and offset (but we'll shift local-time) */
fields->tzOffset = ltzoc->tzOffset;
fields->seconds = seconds;
goto dstHole;
}
}
/*
* Unpack the tz data.
*/
tzdata = ClockGetTZData(clientData, interp, timezoneObj);
if (tzdata == NULL) {
return TCL_ERROR;
}
if (TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK) {
return TCL_ERROR;
}
/*
* Special case: If the time zone is :localtime, the tzdata will be empty.
* Use 'mktime' to convert the time to local
*/
if (rowc == 0) {
if (ConvertLocalToUTCUsingC(interp, fields, changeover) != TCL_OK) {
return TCL_ERROR;
};
/* we cannot cache (ranges unknown yet) - todo: check later the DST-hole here */
return TCL_OK;
} else {
Tcl_WideInt rangesVal[2];
if (ConvertLocalToUTCUsingTable(interp, fields, rowc, rowv,
rangesVal) != TCL_OK) {
return TCL_ERROR;
};
seconds = fields->seconds;
/* Cache the last conversion */
if (ltzoc != NULL) { /* slot was found above */
/* timezoneObj and changeover are the same */
TclSetObjRef(ltzoc->tzName, fields->tzName); /* may be NULL */
} else {
/* no TZ in cache - just move second slot down and use the first one */
ltzoc = &dataPtr->lastTZOffsCache[0];
TclUnsetObjRef(dataPtr->lastTZOffsCache[1].timezoneObj);
TclUnsetObjRef(dataPtr->lastTZOffsCache[1].tzName);
memcpy(&dataPtr->lastTZOffsCache[1], ltzoc, sizeof(*ltzoc));
TclInitObjRef(ltzoc->timezoneObj, timezoneObj);
ltzoc->changeover = changeover;
TclInitObjRef(ltzoc->tzName, fields->tzName); /* may be NULL */
}
ltzoc->localSeconds = fields->localSeconds;
ltzoc->rangesVal[0] = rangesVal[0];
ltzoc->rangesVal[1] = rangesVal[1];
ltzoc->tzOffset = fields->tzOffset;
}
/* check DST-hole: if retrieved seconds is out of range */
if ( ltzoc->rangesVal[0] > seconds || seconds >= ltzoc->rangesVal[1] ) {
dstHole:
#if 0
printf("given local-time is outside the time-zone (in DST-hole): "
"%d - offs %d => %d <= %d < %d\n",
(int)fields->localSeconds, fields->tzOffset,
(int)ltzoc->rangesVal[0], (int)seconds, (int)ltzoc->rangesVal[1]);
#endif
/* because we don't know real TZ (we're outsize), just invalidate local
* time (which could be verified in ClockValidDate later) */
fields->localSeconds = TCL_INV_SECONDS; /* not valid seconds */
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ConvertLocalToUTCUsingTable --
*
|
| ︙ | ︙ | |||
766 767 768 769 770 771 772 |
*----------------------------------------------------------------------
*/
static int
ConvertLocalToUTCUsingTable(
Tcl_Interp *interp, /* Tcl interpreter */
TclDateFields *fields, /* Time to convert, with 'seconds' filled in */
| | | > > > > | | < < | | > < | | | < < | | | > | < > > | > > | 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 |
*----------------------------------------------------------------------
*/
static int
ConvertLocalToUTCUsingTable(
Tcl_Interp *interp, /* Tcl interpreter */
TclDateFields *fields, /* Time to convert, with 'seconds' filled in */
int rowc, /* Number of points at which time changes */
Tcl_Obj *const rowv[], /* Points at which time changes */
Tcl_WideInt *rangesVal) /* Return bounds for time period */
{
Tcl_Obj *row;
Tcl_Size cellc;
Tcl_Obj **cellv;
struct {
Tcl_Obj *tzName;
int tzOffset;
} have[8];
int nHave = 0;
Tcl_Size i;
/*
* Perform an initial lookup assuming that local == UTC, and locate the
* last time conversion prior to that time. Get the offset from that row,
* and look up again. Continue until we find an offset that we found
* before. This definition, rather than "the same offset" ensures that we
* don't enter an endless loop, as would otherwise happen when trying to
* convert a non-existent time such as 02:30 during the US Spring Daylight
* Saving Time transition.
*/
fields->tzOffset = 0;
fields->seconds = fields->localSeconds;
while (1) {
row = LookupLastTransition(interp, fields->seconds, rowc, rowv,
rangesVal);
if ((row == NULL)
|| TclListObjGetElements(interp, row, &cellc,
&cellv) != TCL_OK
|| TclGetIntFromObj(interp, cellv[1],
&fields->tzOffset) != TCL_OK) {
return TCL_ERROR;
}
for (i = 0; i < nHave; ++i) {
if (have[i].tzOffset == fields->tzOffset) {
goto found;
}
}
if (nHave == 8) {
Tcl_Panic("loop in ConvertLocalToUTCUsingTable");
}
have[nHave].tzName = cellv[3];
have[nHave++].tzOffset = fields->tzOffset;
fields->seconds = fields->localSeconds - fields->tzOffset;
}
found:
fields->tzOffset = have[i].tzOffset;
fields->seconds = fields->localSeconds - fields->tzOffset;
TclSetObjRef(fields->tzName, have[i].tzName);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ConvertLocalToUTCUsingC --
|
| ︙ | ︙ | |||
846 847 848 849 850 851 852 |
Tcl_Interp *interp, /* Tcl interpreter */
TclDateFields *fields, /* Time to convert, with 'seconds' filled in */
int changeover) /* Julian Day of the Gregorian transition */
{
struct tm timeVal;
int localErrno;
int secondOfDay;
| < < | < < < | | | 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 |
Tcl_Interp *interp, /* Tcl interpreter */
TclDateFields *fields, /* Time to convert, with 'seconds' filled in */
int changeover) /* Julian Day of the Gregorian transition */
{
struct tm timeVal;
int localErrno;
int secondOfDay;
/*
* Convert the given time to a date.
*/
ClockExtractJDAndSODFromSeconds(fields->julianDay, secondOfDay,
fields->localSeconds);
GetGregorianEraYearDay(fields, changeover);
GetMonthDay(fields);
/*
* Convert the date/time to a 'struct tm'.
*/
|
| ︙ | ︙ | |||
917 918 919 920 921 922 923 | * * Side effects: * Populates the 'tzName' and 'tzOffset' fields. * *---------------------------------------------------------------------- */ | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > | > > | > > > > > > > > > > > > > > > > > > > > > > > > > | 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 |
*
* Side effects:
* Populates the 'tzName' and 'tzOffset' fields.
*
*----------------------------------------------------------------------
*/
int
ConvertUTCToLocal(
void *clientData, /* Client data of the interpreter */
Tcl_Interp *interp, /* Tcl interpreter */
TclDateFields *fields, /* Fields of the time */
Tcl_Obj *timezoneObj, /* Time zone */
int changeover) /* Julian Day of the Gregorian transition */
{
ClockClientData *dataPtr = (ClockClientData *)clientData;
Tcl_Obj *tzdata; /* Time zone data */
Tcl_Size rowc; /* Number of rows in tzdata */
Tcl_Obj **rowv; /* Pointers to the rows */
ClockLastTZOffs * ltzoc = NULL;
/* fast phase-out for shared GMT-object (don't need to convert UTC 2 UTC) */
if (timezoneObj == dataPtr->literals[LIT_GMT]) {
fields->localSeconds = fields->seconds;
fields->tzOffset = 0;
if (dataPtr->gmtTZName == NULL) {
Tcl_Obj *tzName;
tzdata = ClockGetTZData(clientData, interp, timezoneObj);
if ( TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK
|| Tcl_ListObjIndex(interp, rowv[0], 3, &tzName) != TCL_OK) {
return TCL_ERROR;
}
TclSetObjRef(dataPtr->gmtTZName, tzName);
}
TclSetObjRef(fields->tzName, dataPtr->gmtTZName);
return TCL_OK;
}
/*
* Check cacheable conversion could be used
* (last-period UTC2Local cache within the same TZ and seconds)
*/
for (rowc = 0; rowc < 2; rowc++) {
ltzoc = &dataPtr->lastTZOffsCache[rowc];
if (timezoneObj != ltzoc->timezoneObj || changeover != ltzoc->changeover) {
ltzoc = NULL;
continue;
}
if ( fields->seconds >= ltzoc->rangesVal[0]
&& fields->seconds < ltzoc->rangesVal[1]
) {
/* the same time zone and offset (UTC time inside the last minute) */
fields->tzOffset = ltzoc->tzOffset;
fields->localSeconds = fields->seconds + fields->tzOffset;
TclSetObjRef(fields->tzName, ltzoc->tzName);
return TCL_OK;
}
}
/*
* Unpack the tz data.
*/
tzdata = ClockGetTZData(clientData, interp, timezoneObj);
if (tzdata == NULL) {
return TCL_ERROR;
}
if (TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK) {
return TCL_ERROR;
}
/*
* Special case: If the time zone is :localtime, the tzdata will be empty.
* Use 'localtime' to convert the time to local
*/
if (rowc == 0) {
if (ConvertUTCToLocalUsingC(interp, fields, changeover) != TCL_OK) {
return TCL_ERROR;
}
/* signal we need to revalidate TZ epoch next time fields gets used. */
fields->flags |= CLF_CTZ;
/* we cannot cache (ranges unknown yet) */
} else {
Tcl_WideInt rangesVal[2];
if (ConvertUTCToLocalUsingTable(interp, fields, rowc, rowv,
rangesVal) != TCL_OK) {
return TCL_ERROR;
}
/* converted using table (TZ isn't :localtime) */
fields->flags &= ~CLF_CTZ;
/* Cache the last conversion */
if (ltzoc != NULL) { /* slot was found above */
/* timezoneObj and changeover are the same */
TclSetObjRef(ltzoc->tzName, fields->tzName);
} else {
/* no TZ in cache - just move second slot down and use the first one */
ltzoc = &dataPtr->lastTZOffsCache[0];
TclUnsetObjRef(dataPtr->lastTZOffsCache[1].timezoneObj);
TclUnsetObjRef(dataPtr->lastTZOffsCache[1].tzName);
memcpy(&dataPtr->lastTZOffsCache[1], ltzoc, sizeof(*ltzoc));
TclInitObjRef(ltzoc->timezoneObj, timezoneObj);
ltzoc->changeover = changeover;
TclInitObjRef(ltzoc->tzName, fields->tzName);
}
ltzoc->localSeconds = fields->localSeconds;
ltzoc->rangesVal[0] = rangesVal[0];
ltzoc->rangesVal[1] = rangesVal[1];
ltzoc->tzOffset = fields->tzOffset;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ConvertUTCToLocalUsingTable --
*
|
| ︙ | ︙ | |||
971 972 973 974 975 976 977 |
static int
ConvertUTCToLocalUsingTable(
Tcl_Interp *interp, /* Tcl interpreter */
TclDateFields *fields, /* Fields of the date */
Tcl_Size rowc, /* Number of rows in the conversion table
* (>= 1) */
| | > | | < | 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 |
static int
ConvertUTCToLocalUsingTable(
Tcl_Interp *interp, /* Tcl interpreter */
TclDateFields *fields, /* Fields of the date */
Tcl_Size rowc, /* Number of rows in the conversion table
* (>= 1) */
Tcl_Obj *const rowv[], /* Rows of the conversion table */
Tcl_WideInt *rangesVal) /* Return bounds for time period */
{
Tcl_Obj *row; /* Row containing the current information */
Tcl_Size cellc; /* Count of cells in the row (must be 4) */
Tcl_Obj **cellv; /* Pointers to the cells */
/*
* Look up the nearest transition time.
*/
row = LookupLastTransition(interp, fields->seconds, rowc, rowv, rangesVal);
if (row == NULL ||
TclListObjGetElements(interp, row, &cellc, &cellv) != TCL_OK ||
TclGetIntFromObj(interp, cellv[1], &fields->tzOffset) != TCL_OK) {
return TCL_ERROR;
}
/*
* Convert the time.
*/
TclSetObjRef(fields->tzName, cellv[3]);
fields->localSeconds = fields->seconds + fields->tzOffset;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
1026 1027 1028 1029 1030 1031 1032 |
Tcl_Interp *interp, /* Tcl interpreter */
TclDateFields *fields, /* Time to convert, with 'seconds' filled in */
int changeover) /* Julian Day of the Gregorian transition */
{
time_t tock;
struct tm *timeVal; /* Time after conversion */
int diff; /* Time zone diff local-Greenwich */
| | | 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 |
Tcl_Interp *interp, /* Tcl interpreter */
TclDateFields *fields, /* Time to convert, with 'seconds' filled in */
int changeover) /* Julian Day of the Gregorian transition */
{
time_t tock;
struct tm *timeVal; /* Time after conversion */
int diff; /* Time zone diff local-Greenwich */
char buffer[16], *p; /* Buffer for time zone name */
/*
* Use 'localtime' to determine local year, month, day, time of day.
*/
tock = (time_t) fields->seconds;
if ((Tcl_WideInt) tock != fields->seconds) {
|
| ︙ | ︙ | |||
1063 1064 1065 1066 1067 1068 1069 |
fields->dayOfMonth = timeVal->tm_mday;
GetJulianDayFromEraYearMonthDay(fields, changeover);
/*
* Convert that value to seconds.
*/
| | < | < | | | | < | | > | | | > > > > > > > > > > > | 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 |
fields->dayOfMonth = timeVal->tm_mday;
GetJulianDayFromEraYearMonthDay(fields, changeover);
/*
* Convert that value to seconds.
*/
fields->localSeconds = (((fields->julianDay * 24LL
+ timeVal->tm_hour) * 60 + timeVal->tm_min) * 60
+ timeVal->tm_sec) - JULIAN_SEC_POSIX_EPOCH;
/*
* Determine a time zone offset and name; just use +hhmm for the name.
*/
diff = (int) (fields->localSeconds - fields->seconds);
fields->tzOffset = diff;
if (diff < 0) {
*buffer = '-';
diff = -diff;
} else {
*buffer = '+';
}
TclItoAw(buffer+1, diff / 3600, '0', 2); diff %= 3600;
p = TclItoAw(buffer+3, diff / 60, '0', 2); diff %= 60;
if (diff != 0) {
p = TclItoAw(buffer+5, diff, '0', 2);
}
TclSetObjRef(fields->tzName, Tcl_NewStringObj(buffer, p - buffer));
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* LookupLastTransition --
*
* Given a UTC time and a tzdata array, looks up the last transition on
* or before the given time.
*
* Results:
* Returns a pointer to the row, or NULL if an error occurs.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
LookupLastTransition(
Tcl_Interp *interp, /* Interpreter for error messages */
Tcl_WideInt tick, /* Time from the epoch */
Tcl_Size rowc, /* Number of rows of tzdata */
Tcl_Obj *const *rowv, /* Rows in tzdata */
Tcl_WideInt *rangesVal) /* Return bounds for time period */
{
Tcl_Size l, u;
Tcl_Obj *compObj;
Tcl_WideInt compVal, fromVal = LLONG_MIN, toVal = LLONG_MAX;
/*
* Examine the first row to make sure we're in bounds.
*/
if (Tcl_ListObjIndex(interp, rowv[0], 0, &compObj) != TCL_OK
|| TclGetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
return NULL;
}
/*
* Bizarre case - first row doesn't begin at MIN_WIDE_INT. Return it
* anyway.
*/
if (tick < (fromVal = compVal)) {
if (rangesVal) {
rangesVal[0] = fromVal;
rangesVal[1] = toVal;
}
return rowv[0];
}
/*
* Binary-search to find the transition.
*/
l = 0;
u = rowc-1;
while (l < u) {
Tcl_Size m = (l + u + 1) / 2;
if (Tcl_ListObjIndex(interp, rowv[m], 0, &compObj) != TCL_OK ||
TclGetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
return NULL;
}
if (tick >= compVal) {
l = m;
fromVal = compVal;
} else {
u = m-1;
toVal = compVal;
}
}
if (rangesVal) {
rangesVal[0] = fromVal;
rangesVal[1] = toVal;
}
return rowv[l];
}
/*
*----------------------------------------------------------------------
*
* GetYearWeekDay --
|
| ︙ | ︙ | |||
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 |
GetYearWeekDay(
TclDateFields *fields, /* Date to convert, must have 'julianDay' */
int changeover) /* Julian Day Number of the Gregorian
* transition */
{
TclDateFields temp;
int dayOfFiscalYear;
/*
* Find the given date, minus three days, plus one year. That date's
* iso8601 year is an upper bound on the ISO8601 year of the given date.
*/
temp.julianDay = fields->julianDay - 3;
| > > | 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 |
GetYearWeekDay(
TclDateFields *fields, /* Date to convert, must have 'julianDay' */
int changeover) /* Julian Day Number of the Gregorian
* transition */
{
TclDateFields temp;
int dayOfFiscalYear;
temp.tzName = NULL;
/*
* Find the given date, minus three days, plus one year. That date's
* iso8601 year is an upper bound on the ISO8601 year of the given date.
*/
temp.julianDay = fields->julianDay - 3;
|
| ︙ | ︙ | |||
1405 1406 1407 1408 1409 1410 1411 | * * Side effects: * Stores 'julianDay' in the fields. * *---------------------------------------------------------------------- */ | | > > | 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 |
*
* Side effects:
* Stores 'julianDay' in the fields.
*
*----------------------------------------------------------------------
*/
void
GetJulianDayFromEraYearWeekDay(
TclDateFields *fields, /* Date to convert */
int changeover) /* Julian Day Number of the Gregorian
* transition */
{
Tcl_WideInt firstMonday; /* Julian day number of week 1, day 1 in the
* given year */
TclDateFields firstWeek;
firstWeek.tzName = NULL;
/*
* Find January 4 in the ISO8601 year, which will always be in week 1.
*/
firstWeek.isBce = fields->isBce;
firstWeek.year = fields->iso8601Year;
|
| ︙ | ︙ | |||
1456 1457 1458 1459 1460 1461 1462 | * * Side effects: * Stores day number in 'julianDay' * *---------------------------------------------------------------------- */ | | | 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 |
*
* Side effects:
* Stores day number in 'julianDay'
*
*----------------------------------------------------------------------
*/
void
GetJulianDayFromEraYearMonthDay(
TclDateFields *fields, /* Date to convert */
int changeover) /* Gregorian transition date as a Julian Day */
{
Tcl_WideInt year, ym1, ym1o4, ym1o100, ym1o400;
int month, mm1, q, r;
|
| ︙ | ︙ | |||
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 |
+ ym1o4;
}
}
/*
*----------------------------------------------------------------------
*
* IsGregorianLeapYear --
*
* Tests whether a given year is a leap year, in either Julian or
* Gregorian calendar.
*
* Results:
* Returns 1 for a leap year, 0 otherwise.
*
*----------------------------------------------------------------------
*/
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 |
+ ym1o4;
}
}
/*
*----------------------------------------------------------------------
*
* GetJulianDayFromEraYearDay --
*
* Given era, year, and dayOfYear (in TclDateFields), and the
* Gregorian transition date, computes the Julian Day Number.
*
* Results:
* None.
*
* Side effects:
* Stores day number in 'julianDay'
*
*----------------------------------------------------------------------
*/
void
GetJulianDayFromEraYearDay(
TclDateFields *fields, /* Date to convert */
int changeover) /* Gregorian transition date as a Julian Day */
{
Tcl_WideInt year, ym1;
/* Get absolute year number from the civil year */
if (fields->isBce) {
year = 1 - fields->year;
} else {
year = fields->year;
}
ym1 = year - 1;
/* Try the Gregorian calendar first. */
fields->gregorian = 1;
fields->julianDay =
1721425
+ fields->dayOfYear
+ ( 365 * ym1 )
+ ( ym1 / 4 )
- ( ym1 / 100 )
+ ( ym1 / 400 );
/* If the date is before the Gregorian change, use the Julian calendar. */
if ( fields->julianDay < changeover ) {
fields->gregorian = 0;
fields->julianDay =
1721423
+ fields->dayOfYear
+ ( 365 * ym1 )
+ ( ym1 / 4 );
}
}
/*
*----------------------------------------------------------------------
*
* IsGregorianLeapYear --
*
* Tests whether a given year is a leap year, in either Julian or
* Gregorian calendar.
*
* Results:
* Returns 1 for a leap year, 0 otherwise.
*
*----------------------------------------------------------------------
*/
int
IsGregorianLeapYear(
TclDateFields *fields) /* Date to test */
{
Tcl_WideInt year = fields->year;
if (fields->isBce) {
year = 1 - year;
|
| ︙ | ︙ | |||
1763 1764 1765 1766 1767 1768 1769 |
case 2:
if (Tcl_GetIndexFromObj(interp, objv[1], clicksSwitches, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
break;
default:
| | | | 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 |
case 2:
if (Tcl_GetIndexFromObj(interp, objv[1], clicksSwitches, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
break;
default:
Tcl_WrongNumArgs(interp, 0, objv, "clock clicks ?-switch?");
return TCL_ERROR;
}
switch (index) {
case CLICKS_MILLIS:
Tcl_GetTime(&now);
clicks = now.sec * 1000LL + now.usec / 1000;
break;
case CLICKS_NATIVE:
#ifdef TCL_WIDE_CLICKS
clicks = TclpGetWideClicks();
#else
clicks = (Tcl_WideInt)TclpGetClicks();
#endif
|
| ︙ | ︙ | |||
1817 1818 1819 1820 1821 1822 1823 |
Tcl_Size objc, /* Parameter count */
Tcl_Obj *const *objv) /* Parameter values */
{
Tcl_Time now;
Tcl_Obj *timeObj;
if (objc != 1) {
| | | 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 |
Tcl_Size objc, /* Parameter count */
Tcl_Obj *const *objv) /* Parameter values */
{
Tcl_Time now;
Tcl_Obj *timeObj;
if (objc != 1) {
Tcl_WrongNumArgs(interp, 0, objv, "clock milliseconds");
return TCL_ERROR;
}
Tcl_GetTime(&now);
TclNewUIntObj(timeObj, (Tcl_WideUInt)
now.sec * 1000 + now.usec / 1000);
Tcl_SetObjResult(interp, timeObj);
return TCL_OK;
|
| ︙ | ︙ | |||
1853 1854 1855 1856 1857 1858 1859 |
ClockMicrosecondsObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Tcl interpreter */
Tcl_Size objc, /* Parameter count */
Tcl_Obj *const *objv) /* Parameter values */
{
if (objc != 1) {
| | > > > > > > > > > > > | | > > > > | | < < < < | < < < < < > > | > > > > > > > > > > > | < < < < < | | | | | < | < < < | < < | | | > > > < < < > > > > > > > > | | | > > > > > > > > > | < > > | > > > | | | | | | > > > > > > > > > > | > > > > > > > > | < < < | | | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | > | > > | > | > > > | > > | 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 |
ClockMicrosecondsObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Tcl interpreter */
Tcl_Size objc, /* Parameter count */
Tcl_Obj *const *objv) /* Parameter values */
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 0, objv, "clock microseconds");
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(TclpGetMicroseconds()));
return TCL_OK;
}
static inline void
ClockInitFmtScnArgs(
void *clientData,
Tcl_Interp *interp,
ClockFmtScnCmdArgs *opts)
{
memset(opts, 0, sizeof(*opts));
opts->clientData = clientData;
opts->interp = interp;
}
/*
*-----------------------------------------------------------------------------
*
* ClockParseFmtScnArgs --
*
* Parses the arguments for sub-commands "scan", "format" and "add".
*
* Note: common options table used here, because for the options often used
* the same literals (objects), so it avoids permanent "recompiling" of
* option object representation to indexType with another table.
*
* Results:
* Returns a standard Tcl result, and stores parsed options
* (format, the locale, timezone and base) in structure "opts".
*
*-----------------------------------------------------------------------------
*/
#define CLC_FMT_ARGS (0)
#define CLC_SCN_ARGS (1 << 0)
#define CLC_ADD_ARGS (1 << 1)
static int
ClockParseFmtScnArgs(
ClockFmtScnCmdArgs *opts, /* Result vector: format, locale, timezone... */
TclDateFields *date, /* Extracted date-time corresponding base
* (by scan or add) resp. clockval (by format) */
Tcl_Size objc, /* Parameter count */
Tcl_Obj *const objv[], /* Parameter vector */
int flags, /* Flags, differentiates between format, scan, add */
const char *syntax /* Syntax of the current command */
) {
Tcl_Interp *interp = opts->interp;
ClockClientData *dataPtr = (ClockClientData *)opts->clientData;
int gmtFlag = 0;
static const char *const options[] = {
"-base", "-format", "-gmt", "-locale", "-timezone", "-validate", NULL
};
enum optionInd {
CLC_ARGS_BASE, CLC_ARGS_FORMAT, CLC_ARGS_GMT, CLC_ARGS_LOCALE,
CLC_ARGS_TIMEZONE, CLC_ARGS_VALIDATE
};
int optionIndex; /* Index of an option. */
int saw = 0; /* Flag == 1 if option was seen already. */
Tcl_Size i;
Tcl_WideInt baseVal; /* Base time, expressed in seconds from the Epoch */
if ( flags & (CLC_SCN_ARGS) ) {
/* default flags (from configure) */
opts->flags |= dataPtr->defFlags & (CLF_VALIDATE);
} else {
/* clock value (as current base) */
opts->baseObj = objv[1];
saw |= (1 << CLC_ARGS_BASE);
}
/*
* Extract values for the keywords.
*/
for (i = 2; i < objc; i+=2) {
/* bypass integers (offsets) by "clock add" */
if (flags & CLC_ADD_ARGS) {
Tcl_WideInt num;
if (TclGetWideIntFromObj(NULL, objv[i], &num) == TCL_OK) {
continue;
}
}
/* get option */
if (Tcl_GetIndexFromObj(interp, objv[i], options,
"option", 0, &optionIndex) != TCL_OK) {
goto badOptionMsg;
}
/* if already specified */
if (saw & (1 << optionIndex)) {
if ( !(flags & CLC_SCN_ARGS)
&& optionIndex == CLC_ARGS_BASE) {
goto badOptionMsg;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad option \"%s\": doubly present",
TclGetString(objv[i]))
);
goto badOption;
}
switch (optionIndex) {
case CLC_ARGS_FORMAT:
if (flags & CLC_ADD_ARGS) {
goto badOptionMsg;
}
opts->formatObj = objv[i+1];
break;
case CLC_ARGS_GMT:
if (Tcl_GetBooleanFromObj(interp, objv[i+1], &gmtFlag) != TCL_OK){
return TCL_ERROR;
}
break;
case CLC_ARGS_LOCALE:
opts->localeObj = objv[i+1];
break;
case CLC_ARGS_TIMEZONE:
opts->timezoneObj = objv[i+1];
break;
case CLC_ARGS_BASE:
opts->baseObj = objv[i+1];
break;
case CLC_ARGS_VALIDATE:
if ( !(flags & CLC_SCN_ARGS) ) {
goto badOptionMsg;
} else {
int val;
if (Tcl_GetBooleanFromObj(interp, objv[i+1], &val) != TCL_OK) {
return TCL_ERROR;
}
if (val) {
opts->flags |= CLF_VALIDATE;
} else {
opts->flags &= ~CLF_VALIDATE;
}
}
break;
}
saw |= (1 << optionIndex);
}
/*
* Check options.
*/
if ((saw & (1 << CLC_ARGS_GMT))
&& (saw & (1 << CLC_ARGS_TIMEZONE))) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot use -gmt and -timezone in same call", -1));
Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", (char *)NULL);
return TCL_ERROR;
}
if (gmtFlag) {
opts->timezoneObj = dataPtr->literals[LIT_GMT];
}
else
/* If time zone not specified use system time zone */
if ( opts->timezoneObj == NULL
|| TclGetString(opts->timezoneObj) == NULL
|| opts->timezoneObj->length == 0
) {
opts->timezoneObj = ClockGetSystemTimeZone(opts->clientData, interp);
if (opts->timezoneObj == NULL) {
return TCL_ERROR;
}
}
/* Setup timezone (normalize object if needed and load TZ on demand) */
opts->timezoneObj = ClockSetupTimeZone(opts->clientData, interp, opts->timezoneObj);
if (opts->timezoneObj == NULL) {
return TCL_ERROR;
}
/* Base (by scan or add) or clock value (by format) */
if (opts->baseObj != NULL) {
Tcl_Obj *baseObj = opts->baseObj;
/* bypass integer recognition if looks like option "-now" */
if (
(baseObj->length == 4 && baseObj->bytes && *(baseObj->bytes+1) == 'n') ||
TclGetWideIntFromObj(NULL, baseObj, &baseVal) != TCL_OK
) {
/* we accept "-now" as current date-time */
static const char *const nowOpts[] = {
"-now", NULL
};
int idx;
if (Tcl_GetIndexFromObj(NULL, baseObj, nowOpts, "seconds or -now",
TCL_EXACT, &idx) == TCL_OK
) {
goto baseNow;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected integer but got \"%s\"",
Tcl_GetString(baseObj)));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (char *)NULL);
i = 1;
goto badOption;
}
/*
* Seconds could be an unsigned number that overflowed. Make sure
* that it isn't. Additionally it may be too complex to calculate
* julianday etc (forwards/backwards) by too large/small values, thus
* just let accept a bit shorter values to avoid overflow.
* Note the year is currently an integer, thus avoid to overflow it also.
*/
if ( baseObj->typePtr == &tclBignumType
|| baseVal < TCL_MIN_SECONDS || baseVal > TCL_MAX_SECONDS
) {
Tcl_SetObjResult(interp, dataPtr->literals[LIT_INTEGER_VALUE_TOO_LARGE]);
return TCL_ERROR;
}
} else {
baseNow:
{
Tcl_Time now;
Tcl_GetTime(&now);
baseVal = (Tcl_WideInt) now.sec;
}
}
/*
* Extract year, month and day from the base time for the parser to use as
* defaults
*/
/* check base fields already cached (by TZ, last-second cache) */
if ( dataPtr->lastBase.timezoneObj == opts->timezoneObj
&& dataPtr->lastBase.date.seconds == baseVal
&& (!(dataPtr->lastBase.date.flags & CLF_CTZ)
|| dataPtr->lastTZEpoch == TzsetIfNecessary())
) {
memcpy(date, &dataPtr->lastBase.date, ClockCacheableDateFieldsSize);
} else {
/* extact fields from base */
date->seconds = baseVal;
if (ClockGetDateFields(opts->clientData, interp, date, opts->timezoneObj,
GREGORIAN_CHANGE_DATE) != TCL_OK) { /* TODO - GREGORIAN_CHANGE_DATE should be locale-dependent */
return TCL_ERROR;
}
/* cache last base */
memcpy(&dataPtr->lastBase.date, date, ClockCacheableDateFieldsSize);
TclSetObjRef(dataPtr->lastBase.timezoneObj, opts->timezoneObj);
}
return TCL_OK;
badOptionMsg:
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad option \"%s\": must be %s",
TclGetString(objv[i]), syntax)
);
badOption:
Tcl_SetErrorCode(interp, "CLOCK", "badOption",
(i < objc) ? Tcl_GetString(objv[i]) : (char *)NULL, (char *)NULL);
return TCL_ERROR;
}
/*----------------------------------------------------------------------
*
* ClockFormatObjCmd -- , clock format --
*
* This function is invoked to process the Tcl "clock format" command.
*
* Formats a count of seconds since the Posix Epoch as a time of day.
*
* The 'clock format' command formats times of day for output. Refer
* to the user documentation to see what it does.
*
* Results:
* Returns a standard Tcl result.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
ClockFormatObjCmd(
void *clientData, /* Client data containing literal pool */
Tcl_Interp *interp, /* Tcl interpreter */
Tcl_Size objc, /* Parameter count */
Tcl_Obj *const objv[]) /* Parameter values */
{
ClockClientData *dataPtr = (ClockClientData *)clientData;
static const char *syntax = "clock format clockval|-now "
"?-format string? "
"?-gmt boolean? "
"?-locale LOCALE? ?-timezone ZONE?";
int ret;
ClockFmtScnCmdArgs opts; /* Format, locale, timezone and base */
DateFormat dateFmt; /* Common structure used for formatting */
/* even number of arguments */
if ((objc & 1) == 1) {
Tcl_WrongNumArgs(interp, 0, objv, syntax);
Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", (char *)NULL);
return TCL_ERROR;
}
memset(&dateFmt, 0, sizeof(dateFmt));
/*
* Extract values for the keywords.
*/
ClockInitFmtScnArgs(clientData, interp, &opts);
ret = ClockParseFmtScnArgs(&opts, &dateFmt.date, objc, objv,
CLC_FMT_ARGS, "-format, -gmt, -locale, or -timezone");
if (ret != TCL_OK) {
goto done;
}
/* Default format */
if (opts.formatObj == NULL) {
opts.formatObj = dataPtr->literals[LIT__DEFAULT_FORMAT];
}
/* Use compiled version of Format - */
ret = ClockFormat(&dateFmt, &opts);
done:
TclUnsetObjRef(dateFmt.date.tzName);
if (ret != TCL_OK) {
return ret;
}
return TCL_OK;
}
/*----------------------------------------------------------------------
*
* ClockScanObjCmd -- , clock scan --
*
* This function is invoked to process the Tcl "clock scan" command.
*
* Inputs a count of seconds since the Posix Epoch as a time of day.
*
* The 'clock scan' command scans times of day on input. Refer to the
* user documentation to see what it does.
*
* Results:
* Returns a standard Tcl result.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
ClockScanObjCmd(
void *clientData, /* Client data containing literal pool */
Tcl_Interp *interp, /* Tcl interpreter */
Tcl_Size objc, /* Parameter count */
Tcl_Obj *const objv[]) /* Parameter values */
{
static const char *syntax = "clock scan string "
"?-base seconds? "
"?-format string? "
"?-gmt boolean? "
"?-locale LOCALE? ?-timezone ZONE? ?-validate boolean?";
int ret;
ClockFmtScnCmdArgs opts; /* Format, locale, timezone and base */
DateInfo yy; /* Common structure used for parsing */
DateInfo *info = &yy;
/* even number of arguments */
if ((objc & 1) == 1) {
Tcl_WrongNumArgs(interp, 0, objv, syntax);
Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", (char *)NULL);
return TCL_ERROR;
}
ClockInitDateInfo(&yy);
/*
* Extract values for the keywords.
*/
ClockInitFmtScnArgs(clientData, interp, &opts);
ret = ClockParseFmtScnArgs(&opts, &yy.date, objc, objv,
CLC_SCN_ARGS, "-base, -format, -gmt, -locale, -timezone or -validate");
if (ret != TCL_OK) {
goto done;
}
/* seconds are in localSeconds (relative base date), so reset time here */
yyHour = yyMinutes = yySeconds = yySecondOfDay = 0; yyMeridian = MER24;
/* If free scan */
if (opts.formatObj == NULL) {
/* Use compiled version of FreeScan - */
/* [SB] TODO: Perhaps someday we'll localize the legacy code. Right now, it's not localized. */
if (opts.localeObj != NULL) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("legacy [clock scan] does not support -locale", -1));
Tcl_SetErrorCode(interp, "CLOCK", "flagWithLegacyFormat", (char *)NULL);
ret = TCL_ERROR;
goto done;
}
ret = ClockFreeScan(&yy, objv[1], &opts);
}
else {
/* Use compiled version of Scan - */
ret = ClockScan(&yy, objv[1], &opts);
}
if (ret != TCL_OK) {
goto done;
}
/*
* If no GMT and not free-scan (where valid stage 1 is done in-between),
* validate with stage 1 before local time conversion, otherwise it may
* adjust date/time tokens to valid values
*/
if ( (opts.flags & CLF_VALIDATE_S1) &&
info->flags & (CLF_ASSEMBLE_SECONDS|CLF_LOCALSEC)
) {
ret = ClockValidDate(&yy, &opts, CLF_VALIDATE_S1);
if (ret != TCL_OK) {
goto done;
}
}
/* Convert date info structure into UTC seconds */
ret = ClockScanCommit(&yy, &opts);
if (ret != TCL_OK) {
goto done;
}
/* Apply remaining validation rules, if expected */
if ( (opts.flags & CLF_VALIDATE) ) {
ret = ClockValidDate(&yy, &opts, opts.flags & CLF_VALIDATE);
if (ret != TCL_OK) {
goto done;
}
}
done:
TclUnsetObjRef(yy.date.tzName);
if (ret != TCL_OK) {
return ret;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(yy.date.seconds));
return TCL_OK;
}
/*----------------------------------------------------------------------
*
* ClockScanCommit --
*
* Converts date info structure into UTC seconds.
*
* Results:
* Returns a standard Tcl result.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
ClockScanCommit(
DateInfo *info, /* Clock scan info structure */
ClockFmtScnCmdArgs *opts) /* Format, locale, timezone and base */
{
/* If needed assemble julianDay using year, month, etc. */
if (info->flags & CLF_ASSEMBLE_JULIANDAY) {
if ((info->flags & CLF_ISO8601WEAK)) {
GetJulianDayFromEraYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE);
}
else
if ( !(info->flags & CLF_DAYOFYEAR) /* no day of year */
|| (info->flags & (CLF_DAYOFMONTH|CLF_MONTH)) /* yymmdd over yyddd */
== (CLF_DAYOFMONTH|CLF_MONTH)
) {
GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
} else {
GetJulianDayFromEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);
}
info->flags |= CLF_ASSEMBLE_SECONDS;
info->flags &= ~CLF_ASSEMBLE_JULIANDAY;
}
/* some overflow checks */
if (info->flags & CLF_JULIANDAY) {
ClockClientData *dataPtr = (ClockClientData *)opts->clientData;
double curJDN = (double)yydate.julianDay
+ ((double)yySecondOfDay - SECONDS_PER_DAY/2) / SECONDS_PER_DAY;
if (curJDN > dataPtr->maxJDN) {
Tcl_SetObjResult(opts->interp, Tcl_NewStringObj(
"requested date too large to represent", -1));
Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", (char *)NULL);
return TCL_ERROR;
}
}
/* Local seconds to UTC (stored in yydate.seconds) */
if (info->flags & (CLF_ASSEMBLE_SECONDS)) {
yydate.localSeconds =
-210866803200LL
+ ( SECONDS_PER_DAY * yydate.julianDay )
+ ( yySecondOfDay % SECONDS_PER_DAY );
}
if (info->flags & (CLF_ASSEMBLE_SECONDS|CLF_LOCALSEC)) {
if (ConvertLocalToUTC(opts->clientData, opts->interp, &yydate,
opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) {
return TCL_ERROR;
}
}
/* Increment UTC seconds with relative time */
yydate.seconds += yyRelSeconds;
return TCL_OK;
}
/*----------------------------------------------------------------------
*
* ClockValidDate --
*
* Validate date info structure for wrong data (e. g. out of ranges).
*
* Results:
* Returns a standard Tcl result.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
ClockValidDate(
DateInfo *info, /* Clock scan info structure */
ClockFmtScnCmdArgs *opts, /* Scan options */
int stage) /* Stage to validate (1, 2 or 3 for both) */
{
const char *errMsg = "", *errCode = "";
TclDateFields temp;
int tempCpyFlg = 0;
ClockClientData *dataPtr = (ClockClientData *)opts->clientData;
#if 0
printf("yyMonth %d, yyDay %d, yyDayOfYear %d, yyHour %d, yyMinutes %d, yySeconds %d, "
"yySecondOfDay %d, sec %d, daySec %d, tzOffset %d\n",
yyMonth, yyDay, yydate.dayOfYear, yyHour, yyMinutes, yySeconds,
yySecondOfDay, (int)yydate.localSeconds, (int)(yydate.localSeconds % SECONDS_PER_DAY),
yydate.tzOffset);
#endif
if (!(stage & CLF_VALIDATE_S1) || !(opts->flags & CLF_VALIDATE_S1)) {
goto stage_2;
}
opts->flags &= ~CLF_VALIDATE_S1; /* stage 1 is done */
/* first year (used later in hath / daysInPriorMonths) */
if ((info->flags & (CLF_YEAR|CLF_ISO8601YEAR))) {
if ((info->flags & CLF_ISO8601YEAR)) {
if ( yydate.iso8601Year < dataPtr->validMinYear
|| yydate.iso8601Year > dataPtr->validMaxYear ) {
errMsg = "invalid iso year"; errCode = "iso year"; goto error;
}
}
if (info->flags & CLF_YEAR) {
if ( yyYear < dataPtr->validMinYear
|| yyYear > dataPtr->validMaxYear ) {
errMsg = "invalid year"; errCode = "year"; goto error;
}
} else if ((info->flags & CLF_ISO8601YEAR)) {
yyYear = yydate.iso8601Year; /* used to recognize leap */
}
if ((info->flags & (CLF_ISO8601YEAR|CLF_YEAR))
== (CLF_ISO8601YEAR|CLF_YEAR)) {
if (yyYear != yydate.iso8601Year) {
errMsg = "ambiguous year"; errCode = "year"; goto error;
}
}
}
/* and month (used later in hath) */
if (info->flags & CLF_MONTH) {
if ( yyMonth < 1 || yyMonth > 12 ) {
errMsg = "invalid month"; errCode = "month"; goto error;
}
}
/* day of month */
if (info->flags & (CLF_DAYOFMONTH|CLF_DAYOFWEEK)) {
if ( yyDay < 1 || yyDay > 31 ) {
errMsg = "invalid day"; errCode = "day"; goto error;
}
else
if ( (info->flags & CLF_MONTH) ) {
const int *h = hath[IsGregorianLeapYear(&yydate)];
if ( yyDay > h[yyMonth-1] ) {
errMsg = "invalid day"; goto error;
}
}
}
if (info->flags & CLF_DAYOFYEAR) {
if ( yydate.dayOfYear < 1
|| yydate.dayOfYear > daysInPriorMonths[IsGregorianLeapYear(&yydate)][12] ) {
errMsg = "invalid day of year"; errCode = "day of year"; goto error;
}
}
/* mmdd !~ ddd */
if ((info->flags & (CLF_DAYOFYEAR|CLF_DAYOFMONTH|CLF_MONTH))
== (CLF_DAYOFYEAR|CLF_DAYOFMONTH|CLF_MONTH)) {
if (!tempCpyFlg) {
memcpy(&temp, &yydate, sizeof(temp));
tempCpyFlg = 1;
}
GetJulianDayFromEraYearDay(&temp, GREGORIAN_CHANGE_DATE);
if (temp.julianDay != yydate.julianDay) {
errMsg = "ambiguous day"; errCode = "day"; goto error;
}
}
if (info->flags & CLF_TIME) {
/* hour */
if ( yyHour < 0 || yyHour > ((yyMeridian == MER24) ? 23 : 12) ) {
errMsg = "invalid time (hour)"; errCode = "hour"; goto error;
}
/* minutes */
if ( yyMinutes < 0 || yyMinutes > 59 ) {
errMsg = "invalid time (minutes)"; errCode = "minutes"; goto error;
}
/* oldscan could return secondOfDay (parsedTime) -1 by invalid time (ex.: 25:00:00) */
if ( yySeconds < 0 || yySeconds > 59 || yySecondOfDay <= -1 ) {
errMsg = "invalid time"; errCode = "seconds"; goto error;
}
}
if (!(stage & CLF_VALIDATE_S2) || !(opts->flags & CLF_VALIDATE_S2)) {
return TCL_OK;
}
opts->flags &= ~CLF_VALIDATE_S2; /* stage 2 is done */
/*
* Further tests expected ready calculated julianDay (inclusive relative),
* and time-zone conversion (local to UTC time).
*/
stage_2:
/* time, regarding the modifications by the time-zone (looks for given time
* in between DST-time hole, so does not exist in this time-zone) */
if (info->flags & CLF_TIME) {
/*
* we don't need to do the backwards time-conversion (UTC to local) and
* compare results, because the after conversion (local to UTC) we
* should have valid localSeconds (was not invalidated to TCL_INV_SECONDS),
* so if it was invalidated - invalid time, outside the time-zone (in DST-hole)
*/
if ( yydate.localSeconds == TCL_INV_SECONDS ) {
errMsg = "invalid time (does not exist in this time-zone)";
errCode = "out-of-time"; goto error;
}
}
/* day of week */
if (info->flags & CLF_DAYOFWEEK) {
if (!tempCpyFlg) {
memcpy(&temp, &yydate, sizeof(temp));
tempCpyFlg = 1;
}
GetYearWeekDay(&temp, GREGORIAN_CHANGE_DATE);
if (temp.dayOfWeek != yyDayOfWeek) {
errMsg = "invalid day of week"; errCode = "day of week"; goto error;
}
}
return TCL_OK;
error:
Tcl_SetObjResult(opts->interp,
Tcl_ObjPrintf("unable to convert input string: %s", errMsg));
Tcl_SetErrorCode(opts->interp, "CLOCK", "invInpStr", errCode, (char *)NULL);
return TCL_ERROR;
}
/*----------------------------------------------------------------------
*
* ClockFreeScan --
*
* Used by ClockScanObjCmd for free scanning without format.
*
* Results:
* Returns a standard Tcl result.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
ClockFreeScan(
DateInfo *info, /* Date fields used for parsing & converting
* simultaneously a yy-parse structure of the
* TclClockFreeScan */
Tcl_Obj *strObj, /* String containing the time to scan */
ClockFmtScnCmdArgs *opts) /* Command options */
{
Tcl_Interp *interp = opts->interp;
ClockClientData *dataPtr = (ClockClientData *)opts->clientData;
int ret = TCL_ERROR;
/*
* Parse the date. The parser will fill a structure "info" with date,
* time, time zone, relative month/day/seconds, relative weekday, ordinal
* month.
* Notice that many yy-defines point to values in the "info" or "date"
* structure, e. g. yySecondOfDay -> info->date.secondOfDay or
* yyMonth -> info->date.month (same as yydate.month)
*/
yyInput = Tcl_GetString(strObj);
if (TclClockFreeScan(interp, info) != TCL_OK) {
Tcl_Obj *msg;
TclNewObj(msg);
Tcl_AppendPrintfToObj(msg, "unable to convert date-time string \"%s\": %s",
Tcl_GetString(strObj), TclGetString(Tcl_GetObjResult(interp)));
Tcl_SetObjResult(interp, msg);
goto done;
}
/*
* If the caller supplied a date in the string, update the date with
* the value. If the caller didn't specify a time with the date, default to
* midnight.
*/
if (info->flags & CLF_YEAR) {
if (yyYear < 100) {
if (yyYear >= dataPtr->yearOfCenturySwitch) {
yyYear -= 100;
}
yyYear += dataPtr->currentYearCentury;
}
yydate.isBce = 0;
info->flags |= CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS;
}
/*
* If the caller supplied a time zone in the string, make it into a time
* zone indicator of +-hhmm and setup this time zone.
*/
if (info->flags & CLF_ZONE) {
if (yyTimezone || !yyDSTmode) {
/* Real time zone from numeric zone */
Tcl_Obj *tzObjStor = NULL;
int minEast = -yyTimezone;
int dstFlag = 1 - yyDSTmode;
tzObjStor = ClockFormatNumericTimeZone(
60 * minEast + 3600 * dstFlag);
Tcl_IncrRefCount(tzObjStor);
opts->timezoneObj = ClockSetupTimeZone(dataPtr, interp, tzObjStor);
Tcl_DecrRefCount(tzObjStor);
} else {
/* simplest case - GMT / UTC */
opts->timezoneObj = ClockSetupTimeZone(dataPtr, interp,
dataPtr->literals[LIT_GMT]);
}
if (opts->timezoneObj == NULL) {
goto done;
}
// TclSetObjRef(yydate.tzName, opts->timezoneObj);
info->flags |= CLF_ASSEMBLE_SECONDS;
}
/*
* For freescan apply validation rules (stage 1) before mixed with
* relative time (otherwise always valid recalculated date & time).
*/
if ( (opts->flags & CLF_VALIDATE) ) {
if (ClockValidDate(info, opts, CLF_VALIDATE_S1) != TCL_OK) {
goto done;
}
}
/*
* Assemble date, time, zone into seconds-from-epoch
*/
if ((info->flags & (CLF_TIME|CLF_HAVEDATE)) == CLF_HAVEDATE) {
yySecondOfDay = 0;
info->flags |= CLF_ASSEMBLE_SECONDS;
}
else
if (info->flags & CLF_TIME) {
yySecondOfDay = ToSeconds(yyHour, yyMinutes,
yySeconds, yyMeridian);
info->flags |= CLF_ASSEMBLE_SECONDS;
}
else
if ( (info->flags & (CLF_DAYOFWEEK|CLF_HAVEDATE)) == CLF_DAYOFWEEK
|| (info->flags & CLF_ORDINALMONTH)
|| ( (info->flags & CLF_RELCONV)
&& ( yyRelMonth != 0
|| yyRelDay != 0 ) )
) {
yySecondOfDay = 0;
info->flags |= CLF_ASSEMBLE_SECONDS;
}
else {
yySecondOfDay = yydate.localSeconds % SECONDS_PER_DAY;
}
/*
* Do relative times
*/
ret = ClockCalcRelTime(info);
/* Free scanning completed - date ready */
done:
return ret;
}
/*----------------------------------------------------------------------
*
* ClockCalcRelTime --
*
* Used for calculating of relative times.
*
* Results:
* Returns a standard Tcl result.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
ClockCalcRelTime(
DateInfo *info) /* Date fields used for converting */
{
int prevDayOfWeek = yyDayOfWeek; /* preserve unchanged day of week */
/*
* Because some calculations require in-between conversion of the
* julian day, we can repeat this processing multiple times
*/
repeat_rel:
if (info->flags & CLF_RELCONV) {
/*
* Relative conversion normally possible in UTC time only, because
* of possible wrong local time increment if ignores in-between DST-hole.
* (see test-cases clock-34.53, clock-34.54).
* So increment date in julianDay, but time inside day in UTC (seconds).
*/
/* add months (or years in months) */
if (yyRelMonth != 0) {
int m, h;
/* if needed extract year, month, etc. again */
if (info->flags & CLF_ASSEMBLE_DATE) {
GetGregorianEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);
GetMonthDay(&yydate);
GetYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE);
info->flags &= ~CLF_ASSEMBLE_DATE;
}
/* add the requisite number of months */
yyMonth += yyRelMonth - 1;
yyYear += yyMonth / 12;
m = yyMonth % 12;
/* compiler fix for negative offs - wrap y, m = (0, -1) -> (-1, 11) */
if (m < 0) {
yyYear--;
m = 12 + m;
}
yyMonth = m + 1;
/* if the day doesn't exist in the current month, repair it */
h = hath[IsGregorianLeapYear(&yydate)][m];
if (yyDay > h) {
yyDay = h;
}
/* on demand (lazy) assemble julianDay using new year, month, etc. */
info->flags |= CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS;
yyRelMonth = 0;
}
/* add days (or other parts aligned to days) */
if (yyRelDay) {
/* assemble julianDay using new year, month, etc. */
if (info->flags & CLF_ASSEMBLE_JULIANDAY) {
GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
info->flags &= ~CLF_ASSEMBLE_JULIANDAY;
}
yydate.julianDay += yyRelDay;
/* julianDay was changed, on demand (lazy) extract year, month, etc. again */
info->flags |= CLF_ASSEMBLE_DATE|CLF_ASSEMBLE_SECONDS;
yyRelDay = 0;
}
/* relative time (seconds), if exceeds current date, do the day conversion and
* leave rest of the increment in yyRelSeconds to add it hereafter in UTC seconds */
if (yyRelSeconds) {
Tcl_WideInt newSecs = yySecondOfDay + yyRelSeconds;
/* if seconds increment outside of current date, increment day */
if (newSecs / SECONDS_PER_DAY != yySecondOfDay / SECONDS_PER_DAY) {
yyRelDay += newSecs / SECONDS_PER_DAY;
yySecondOfDay = 0;
yyRelSeconds = newSecs % SECONDS_PER_DAY;
goto repeat_rel;
}
}
info->flags &= ~CLF_RELCONV;
}
/*
* Do relative (ordinal) month
*/
if (info->flags & CLF_ORDINALMONTH) {
int monthDiff;
/* if needed extract year, month, etc. again */
if (info->flags & CLF_ASSEMBLE_DATE) {
GetGregorianEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);
GetMonthDay(&yydate);
GetYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE);
info->flags &= ~CLF_ASSEMBLE_DATE;
}
if (yyMonthOrdinalIncr > 0) {
monthDiff = yyMonthOrdinal - yyMonth;
if (monthDiff <= 0) {
monthDiff += 12;
}
yyMonthOrdinalIncr--;
} else {
monthDiff = yyMonth - yyMonthOrdinal;
if (monthDiff >= 0) {
monthDiff -= 12;
}
yyMonthOrdinalIncr++;
}
/* process it further via relative times */
yyYear += yyMonthOrdinalIncr;
yyRelMonth += monthDiff;
info->flags &= ~CLF_ORDINALMONTH;
info->flags |= CLF_RELCONV|CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS;
goto repeat_rel;
}
/*
* Do relative weekday
*/
if ((info->flags & (CLF_DAYOFWEEK|CLF_HAVEDATE)) == CLF_DAYOFWEEK) {
/* restore scanned day of week */
yyDayOfWeek = prevDayOfWeek;
/* if needed assemble julianDay now */
if (info->flags & CLF_ASSEMBLE_JULIANDAY) {
GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
info->flags &= ~CLF_ASSEMBLE_JULIANDAY;
}
yydate.isBce = 0;
yydate.julianDay = WeekdayOnOrBefore(yyDayOfWeek, yydate.julianDay + 6)
+ 7 * yyDayOrdinal;
if (yyDayOrdinal > 0) {
yydate.julianDay -= 7;
}
info->flags |= CLF_ASSEMBLE_DATE|CLF_ASSEMBLE_SECONDS;
}
return TCL_OK;
}
/*----------------------------------------------------------------------
*
* ClockWeekdaysOffs --
*
* Get offset in days for the number of week days corresponding the
* given day of week (skipping Saturdays and Sundays).
*
*
* Results:
* Returns a day increment adjusted the given weekdays
*
*----------------------------------------------------------------------
*/
static inline int
ClockWeekdaysOffs(
int dayOfWeek,
int offs)
{
int weeks, resDayOfWeek;
/* offset in days */
weeks = offs / 5;
offs = offs % 5;
/* compiler fix for negative offs - wrap (0, -1) -> (-1, 4) */
if (offs < 0) {
weeks--;
offs = 5 + offs;
}
offs += 7 * weeks;
/* resulting day of week */
{
int day = (offs % 7);
/* compiler fix for negative offs - wrap (0, -1) -> (-1, 6) */
if (day < 0) {
day = 7 + day;
}
resDayOfWeek = dayOfWeek + day;
}
/* adjust if we start from a weekend */
if (dayOfWeek > 5) {
int adj = 5 - dayOfWeek;
offs += adj;
resDayOfWeek += adj;
}
/* adjust if we end up on a weekend */
if (resDayOfWeek > 5) {
offs += 2;
}
return offs;
}
/*----------------------------------------------------------------------
*
* ClockAddObjCmd -- , clock add --
*
* Adds an offset to a given time.
*
* Refer to the user documentation to see what it exactly does.
*
* Syntax:
* clock add clockval ?count unit?... ?-option value?
*
* Parameters:
* clockval -- Starting time value
* count -- Amount of a unit of time to add
* unit -- Unit of time to add, must be one of:
* years year months month weeks week
* days day hours hour minutes minute
* seconds second
*
* Options:
* -gmt BOOLEAN
* Flag synonymous with '-timezone :GMT'
* -timezone ZONE
* Name of the time zone in which calculations are to be done.
* -locale NAME
* Name of the locale in which calculations are to be done.
* Used to determine the Gregorian change date.
*
* Results:
* Returns a standard Tcl result with the given time adjusted
* by the given offset(s) in order.
*
* Notes:
* It is possible that adding a number of months or years will adjust the
* day of the month as well. For instance, the time at one month after
* 31 January is either 28 or 29 February, because February has fewer
* than 31 days.
*
*----------------------------------------------------------------------
*/
int
ClockAddObjCmd(
void *clientData, /* Client data containing literal pool */
Tcl_Interp *interp, /* Tcl interpreter */
Tcl_Size objc, /* Parameter count */
Tcl_Obj *const objv[]) /* Parameter values */
{
static const char *syntax = "clock add clockval|-now ?number units?..."
"?-gmt boolean? "
"?-locale LOCALE? ?-timezone ZONE?";
ClockClientData *dataPtr = (ClockClientData *)clientData;
int ret;
ClockFmtScnCmdArgs opts; /* Format, locale, timezone and base */
DateInfo yy; /* Common structure used for parsing */
DateInfo *info = &yy;
/* add "week" to units also (because otherwise ambiguous) */
static const char *const units[] = {
"years", "months", "week", "weeks",
"days", "weekdays",
"hours", "minutes", "seconds",
NULL
};
enum unitInd {
CLC_ADD_YEARS, CLC_ADD_MONTHS, CLC_ADD_WEEK, CLC_ADD_WEEKS,
CLC_ADD_DAYS, CLC_ADD_WEEKDAYS,
CLC_ADD_HOURS, CLC_ADD_MINUTES, CLC_ADD_SECONDS
};
int unitIndex; /* Index of an option. */
Tcl_Size i;
Tcl_WideInt offs;
/* even number of arguments */
if ((objc & 1) == 1) {
Tcl_WrongNumArgs(interp, 0, objv, syntax);
Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", (char *)NULL);
return TCL_ERROR;
}
ClockInitDateInfo(&yy);
/*
* Extract values for the keywords.
*/
ClockInitFmtScnArgs(clientData, interp, &opts);
ret = ClockParseFmtScnArgs(&opts, &yy.date, objc, objv,
CLC_ADD_ARGS, "-gmt, -locale, or -timezone");
if (ret != TCL_OK) {
goto done;
}
/* time together as seconds of the day */
yySecondOfDay = yySeconds = yydate.localSeconds % SECONDS_PER_DAY;
/* seconds are in localSeconds (relative base date), so reset time here */
yyHour = 0; yyMinutes = 0; yyMeridian = MER24;
ret = TCL_ERROR;
/*
* Find each offset and process date increment
*/
for (i = 2; i < objc; i+=2) {
/* bypass not integers (options, allready processed above in ClockParseFmtScnArgs) */
if (TclGetWideIntFromObj(NULL, objv[i], &offs) != TCL_OK) {
continue;
}
/* get unit */
if (Tcl_GetIndexFromObj(interp, objv[i+1], units, "unit", 0,
&unitIndex) != TCL_OK) {
goto done;
}
if (objv[i]->typePtr == &tclBignumType
|| offs > (unitIndex < CLC_ADD_HOURS ? 0x7fffffff : TCL_MAX_SECONDS)
|| offs < (unitIndex < CLC_ADD_HOURS ? -0x7fffffff : TCL_MIN_SECONDS)
) {
Tcl_SetObjResult(interp, dataPtr->literals[LIT_INTEGER_VALUE_TOO_LARGE]);
goto done;
}
/* nothing to do if zero quantity */
if (!offs) {
continue;
}
/* if in-between conversion needed (already have relative date/time),
* correct date info, because the date may be changed,
* so refresh it now */
if ( (info->flags & CLF_RELCONV)
&& ( unitIndex == CLC_ADD_WEEKDAYS
/* some months can be shorter as another */
|| yyRelMonth || yyRelDay
/* day changed */
|| yySeconds + yyRelSeconds > SECONDS_PER_DAY
|| yySeconds + yyRelSeconds < 0
)
) {
if (ClockCalcRelTime(info) != TCL_OK) {
goto done;
}
}
/* process increment by offset + unit */
info->flags |= CLF_RELCONV;
switch (unitIndex) {
case CLC_ADD_YEARS:
yyRelMonth += offs * 12;
break;
case CLC_ADD_MONTHS:
yyRelMonth += offs;
break;
case CLC_ADD_WEEK:
case CLC_ADD_WEEKS:
yyRelDay += offs * 7;
break;
case CLC_ADD_DAYS:
yyRelDay += offs;
break;
case CLC_ADD_WEEKDAYS:
/* add number of week days (skipping Saturdays and Sundays)
* to a relative days value. */
offs = ClockWeekdaysOffs(yy.date.dayOfWeek, offs);
yyRelDay += offs;
break;
case CLC_ADD_HOURS:
yyRelSeconds += offs * 60 * 60;
break;
case CLC_ADD_MINUTES:
yyRelSeconds += offs * 60;
break;
case CLC_ADD_SECONDS:
yyRelSeconds += offs;
break;
}
}
/*
* Do relative times (if not yet already processed interim):
*/
if (info->flags & CLF_RELCONV) {
if (ClockCalcRelTime(info) != TCL_OK) {
goto done;
}
}
/* Convert date info structure into UTC seconds */
ret = ClockScanCommit(&yy, &opts);
done:
TclUnsetObjRef(yy.date.tzName);
if (ret != TCL_OK) {
return ret;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(yy.date.seconds));
return TCL_OK;
}
/*----------------------------------------------------------------------
*
* ClockSecondsObjCmd -
*
* Returns a count of microseconds since the epoch.
|
| ︙ | ︙ | |||
2007 2008 2009 2010 2011 2012 2013 |
Tcl_Size objc, /* Parameter count */
Tcl_Obj *const *objv) /* Parameter values */
{
Tcl_Time now;
Tcl_Obj *timeObj;
if (objc != 1) {
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 |
Tcl_Size objc, /* Parameter count */
Tcl_Obj *const *objv) /* Parameter values */
{
Tcl_Time now;
Tcl_Obj *timeObj;
if (objc != 1) {
Tcl_WrongNumArgs(interp, 0, objv, "clock seconds");
return TCL_ERROR;
}
Tcl_GetTime(&now);
TclNewUIntObj(timeObj, (Tcl_WideUInt)now.sec);
Tcl_SetObjResult(interp, timeObj);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ClockSafeCatchCmd --
*
* Same as "::catch" command but avoids overwriting of interp state.
*
* See [554117edde] for more info (and proper solution).
*
*----------------------------------------------------------------------
*/
int
ClockSafeCatchCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_Size objc,
Tcl_Obj *const objv[])
{
typedef struct {
int status; /* return code status */
int flags; /* Each remaining field saves the */
int returnLevel; /* corresponding field of the Interp */
int returnCode; /* struct. These fields taken together are */
Tcl_Obj *errorInfo; /* the "state" of the interp. */
Tcl_Obj *errorCode;
Tcl_Obj *returnOpts;
Tcl_Obj *objResult;
Tcl_Obj *errorStack;
int resetErrorStack;
} InterpState;
Interp *iPtr = (Interp *)interp;
int ret, flags = 0;
InterpState *statePtr;
if (objc == 1) {
/* wrong # args : */
return Tcl_CatchObjCmd(NULL, interp, objc, objv);
}
statePtr = (InterpState *)Tcl_SaveInterpState(interp, 0);
if (!statePtr->errorInfo) {
/* todo: avoid traced get of errorInfo here */
TclInitObjRef(statePtr->errorInfo,
Tcl_ObjGetVar2(interp, iPtr->eiVar, NULL, 0));
flags |= ERR_LEGACY_COPY;
}
if (!statePtr->errorCode) {
/* todo: avoid traced get of errorCode here */
TclInitObjRef(statePtr->errorCode,
Tcl_ObjGetVar2(interp, iPtr->ecVar, NULL, 0));
flags |= ERR_LEGACY_COPY;
}
/* original catch */
ret = Tcl_CatchObjCmd(NULL, interp, objc, objv);
if (ret == TCL_ERROR) {
Tcl_DiscardInterpState((Tcl_InterpState)statePtr);
return TCL_ERROR;
}
/* overwrite result in state with catch result */
TclSetObjRef(statePtr->objResult, Tcl_GetObjResult(interp));
/* set result (together with restore state) to interpreter */
(void) Tcl_RestoreInterpState(interp, (Tcl_InterpState)statePtr);
/* todo: unless ERR_LEGACY_COPY not set in restore (branch [bug-554117edde] not merged yet) */
iPtr->flags |= (flags & ERR_LEGACY_COPY);
return ret;
}
/*
*----------------------------------------------------------------------
*
* TzsetIfNecessary --
*
* Calls the tzset() library function if the contents of the TZ
|
| ︙ | ︙ | |||
2043 2044 2045 2046 2047 2048 2049 | #else #define WCHAR char #define wcslen strlen #define wcscmp strcmp #define wcscpy strcpy #endif | | > | > > > | > > > | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 |
#else
#define WCHAR char
#define wcslen strlen
#define wcscmp strcmp
#define wcscpy strcpy
#endif
static size_t
TzsetIfNecessary(void)
{
static WCHAR* tzWas = (WCHAR *)INT2PTR(-1); /* Previous value of TZ, protected by
* clockMutex. */
static long long tzLastRefresh = 0; /* Used for latency before next refresh */
static size_t tzWasEpoch = 0; /* Epoch, signals that TZ changed */
static size_t tzEnvEpoch = 0; /* Last env epoch, for faster signaling,
that TZ changed via TCL */
const WCHAR *tzIsNow; /* Current value of TZ */
/*
* Prevent performance regression on some platforms by resolving of system time zone:
* small latency for check whether environment was changed (once per second)
* no latency if environment was changed with tcl-env (compare both epoch values)
*/
Tcl_Time now;
Tcl_GetTime(&now);
if (now.sec == tzLastRefresh && tzEnvEpoch == TclEnvEpoch) {
return tzWasEpoch;
}
tzEnvEpoch = TclEnvEpoch;
tzLastRefresh = now.sec;
/* check in lock */
Tcl_MutexLock(&clockMutex);
tzIsNow = getenv("TCL_TZ");
if (tzIsNow == NULL) {
tzIsNow = getenv("TZ");
}
if (tzIsNow != NULL && (tzWas == NULL || tzWas == (WCHAR *)INT2PTR(-1)
|| wcscmp(tzIsNow, tzWas) != 0)) {
tzset();
if (tzWas != NULL && tzWas != (WCHAR *)INT2PTR(-1)) {
Tcl_Free(tzWas);
}
tzWas = (WCHAR *)Tcl_Alloc(sizeof(WCHAR) * (wcslen(tzIsNow) + 1));
wcscpy(tzWas, tzIsNow);
tzWasEpoch++;
} else if (tzIsNow == NULL && tzWas != NULL) {
tzset();
if (tzWas != (WCHAR *)INT2PTR(-1)) {
Tcl_Free(tzWas);
}
tzWas = NULL;
tzWasEpoch++;
}
Tcl_MutexUnlock(&clockMutex);
return tzWasEpoch;
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
|
Added generic/tclClockFmt.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 |
/*
* tclClockFmt.c --
*
* Contains the date format (and scan) routines. This code is back-ported
* from the time and date facilities of tclSE engine, by Serg G. Brester.
*
* Copyright (c) 2015 by Sergey G. Brester aka sebres. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
#include "tclStrIdxTree.h"
#include "tclDate.h"
/*
* Miscellaneous forward declarations and functions used within this file
*/
static void
ClockFmtObj_DupInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void
ClockFmtObj_FreeInternalRep(Tcl_Obj *objPtr);
static int
ClockFmtObj_SetFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static void
ClockFmtObj_UpdateString(Tcl_Obj *objPtr);
TCL_DECLARE_MUTEX(ClockFmtMutex); /* Serializes access to common format list. */
static void ClockFmtScnStorageDelete(ClockFmtScnStorage *fss);
static void ClockFrmScnFinalize(void *clientData);
/*
* Clock scan and format facilities.
*/
/*
*----------------------------------------------------------------------
*
* _str2int -- , _str2wideInt --
*
* Fast inline-convertion of string to signed int or wide int by given
* start/end.
*
* The given string should contain numbers chars only (because already
* pre-validated within parsing routines)
*
* Results:
* Returns a standard Tcl result.
* TCL_OK - by successful conversion, TCL_ERROR by (wide) int overflow
*
*----------------------------------------------------------------------
*/
static inline void
_str2int_no(
int *out,
const char *p,
const char *e,
int sign)
{
/* assert(e <= p+10); */
int val = 0;
/* overflow impossible for 10 digits ("9..9"), so no needs to check at all */
while (p < e) { /* never overflows */
val = val * 10 + (*p++ - '0');
}
if (sign < 0) { val = -val; }
*out = val;
}
static inline void
_str2wideInt_no(
Tcl_WideInt *out,
const char *p,
const char *e,
int sign)
{
/* assert(e <= p+18); */
Tcl_WideInt val = 0;
/* overflow impossible for 18 digits ("9..9"), so no needs to check at all */
while (p < e) { /* never overflows */
val = val * 10 + (*p++ - '0');
}
if (sign < 0) { val = -val; }
*out = val;
}
/* int & Tcl_WideInt overflows may happens here (expected case) */
#if defined(__GNUC__) || defined(__GNUG__)
# pragma GCC optimize("no-trapv")
#endif
static inline int
_str2int(
int *out,
const char *p,
const char *e,
int sign)
{
int val = 0;
/* overflow impossible for 10 digits ("9..9"), so no needs to check before */
const char *eNO = p+10;
if (eNO > e) {
eNO = e;
}
while (p < eNO) { /* never overflows */
val = val * 10 + (*p++ - '0');
}
if (sign >= 0) {
while (p < e) { /* check for overflow */
int prev = val;
val = val * 10 + (*p++ - '0');
if (val / 10 < prev) {
return TCL_ERROR;
}
}
} else {
val = -val;
while (p < e) { /* check for overflow */
int prev = val;
val = val * 10 - (*p++ - '0');
if (val / 10 > prev) {
return TCL_ERROR;
}
}
}
*out = val;
return TCL_OK;
}
static inline int
_str2wideInt(
Tcl_WideInt *out,
const char *p,
const char *e,
int sign)
{
Tcl_WideInt val = 0;
/* overflow impossible for 18 digits ("9..9"), so no needs to check before */
const char *eNO = p+18;
if (eNO > e) {
eNO = e;
}
while (p < eNO) { /* never overflows */
val = val * 10 + (*p++ - '0');
}
if (sign >= 0) {
while (p < e) { /* check for overflow */
Tcl_WideInt prev = val;
val = val * 10 + (*p++ - '0');
if (val / 10 < prev) {
return TCL_ERROR;
}
}
} else {
val = -val;
while (p < e) { /* check for overflow */
Tcl_WideInt prev = val;
val = val * 10 - (*p++ - '0');
if (val / 10 > prev) {
return TCL_ERROR;
}
}
}
*out = val;
return TCL_OK;
}
int
TclAtoWIe(
Tcl_WideInt *out,
const char *p,
const char *e,
int sign)
{
return _str2wideInt(out, p, e, sign);
}
#if defined(__GNUC__) || defined(__GNUG__)
# pragma GCC reset_options
#endif
/*
*----------------------------------------------------------------------
*
* _itoaw -- , _witoaw --
*
* Fast inline-convertion of signed int or wide int to string, using
* given padding with specified padchar and width (or without padding).
*
* This is a very fast replacement for sprintf("%02d").
*
* Results:
* Returns position in buffer after end of conversion result.
*
*----------------------------------------------------------------------
*/
static inline char *
_itoaw(
char *buf,
int val,
char padchar,
unsigned short int width)
{
char *p;
static int wrange[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
/* positive integer */
if (val >= 0)
{
/* check resp. recalculate width */
while (width <= 9 && val >= wrange[width]) {
width++;
}
/* number to string backwards */
p = buf + width;
*p-- = '\0';
do {
char c = (val % 10); val /= 10;
*p-- = '0' + c;
} while (val > 0);
/* fulling with pad-char */
while (p >= buf) {
*p-- = padchar;
}
return buf + width;
}
/* negative integer */
if (!width) width++;
/* check resp. recalculate width (regarding sign) */
width--;
while (width <= 9 && val <= -wrange[width]) {
width++;
}
width++;
/* number to string backwards */
p = buf + width;
*p-- = '\0';
/* differentiate platforms with -1 % 10 == 1 and -1 % 10 == -1 */
if (-1 % 10 == -1) {
do {
char c = (val % 10); val /= 10;
*p-- = '0' - c;
} while (val < 0);
} else {
do {
char c = (val % 10); val /= 10;
*p-- = '0' + c;
} while (val < 0);
}
/* sign by 0 padding */
if (padchar != '0') { *p-- = '-'; }
/* fulling with pad-char */
while (p >= buf + 1) {
*p-- = padchar;
}
/* sign by non 0 padding */
if (padchar == '0') { *p = '-'; }
return buf + width;
}
char *
TclItoAw(
char *buf,
int val,
char padchar,
unsigned short int width)
{
return _itoaw(buf, val, padchar, width);
}
static inline char *
_witoaw(
char *buf,
Tcl_WideInt val,
char padchar,
unsigned short int width)
{
char *p;
static int wrange[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
/* positive integer */
if (val >= 0)
{
/* check resp. recalculate width */
if (val >= 10000000000LL) {
Tcl_WideInt val2;
val2 = val / 10000000000LL;
while (width <= 9 && val2 >= wrange[width]) {
width++;
}
width += 10;
} else {
while (width <= 9 && val >= wrange[width]) {
width++;
}
}
/* number to string backwards */
p = buf + width;
*p-- = '\0';
do {
char c = (val % 10); val /= 10;
*p-- = '0' + c;
} while (val > 0);
/* fulling with pad-char */
while (p >= buf) {
*p-- = padchar;
}
return buf + width;
}
/* negative integer */
if (!width) width++;
/* check resp. recalculate width (regarding sign) */
width--;
if (val <= -10000000000LL) {
Tcl_WideInt val2;
val2 = val / 10000000000LL;
while (width <= 9 && val2 <= -wrange[width]) {
width++;
}
width += 10;
} else {
while (width <= 9 && val <= -wrange[width]) {
width++;
}
}
width++;
/* number to string backwards */
p = buf + width;
*p-- = '\0';
/* differentiate platforms with -1 % 10 == 1 and -1 % 10 == -1 */
if (-1 % 10 == -1) {
do {
char c = (val % 10); val /= 10;
*p-- = '0' - c;
} while (val < 0);
} else {
do {
char c = (val % 10); val /= 10;
*p-- = '0' + c;
} while (val < 0);
}
/* sign by 0 padding */
if (padchar != '0') { *p-- = '-'; }
/* fulling with pad-char */
while (p >= buf + 1) {
*p-- = padchar;
}
/* sign by non 0 padding */
if (padchar == '0') { *p = '-'; }
return buf + width;
}
/*
* Global GC as LIFO for released scan/format object storages.
*
* Used to holds last released CLOCK_FMT_SCN_STORAGE_GC_SIZE formats
* (after last reference from Tcl-object will be removed). This is helpful
* to avoid continuous (re)creation and compiling by some dynamically resp.
* variable format objects, that could be often reused.
*
* As long as format storage is used resp. belongs to GC, it takes place in
* FmtScnHashTable also.
*/
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
static struct {
ClockFmtScnStorage *stackPtr;
ClockFmtScnStorage *stackBound;
unsigned int count;
} ClockFmtScnStorage_GC = {NULL, NULL, 0};
/*
*----------------------------------------------------------------------
*
* ClockFmtScnStorageGC_In --
*
* Adds an format storage object to GC.
*
* If current GC is full (size larger as CLOCK_FMT_SCN_STORAGE_GC_SIZE)
* this removes last unused storage at begin of GC stack (LIFO).
*
* Assumes caller holds the ClockFmtMutex.
*
* Results:
* None.
*
*----------------------------------------------------------------------
*/
static inline void
ClockFmtScnStorageGC_In(ClockFmtScnStorage *entry)
{
/* add new entry */
TclSpliceIn(entry, ClockFmtScnStorage_GC.stackPtr);
if (ClockFmtScnStorage_GC.stackBound == NULL) {
ClockFmtScnStorage_GC.stackBound = entry;
}
ClockFmtScnStorage_GC.count++;
/* if GC ist full */
if (ClockFmtScnStorage_GC.count > CLOCK_FMT_SCN_STORAGE_GC_SIZE) {
/* GC stack is LIFO: delete first inserted entry */
ClockFmtScnStorage *delEnt = ClockFmtScnStorage_GC.stackBound;
ClockFmtScnStorage_GC.stackBound = delEnt->prevPtr;
TclSpliceOut(delEnt, ClockFmtScnStorage_GC.stackPtr);
ClockFmtScnStorage_GC.count--;
delEnt->prevPtr = delEnt->nextPtr = NULL;
/* remove it now */
ClockFmtScnStorageDelete(delEnt);
}
}
/*
*----------------------------------------------------------------------
*
* ClockFmtScnStorage_GC_Out --
*
* Restores (for reusing) given format storage object from GC.
*
* Assumes caller holds the ClockFmtMutex.
*
* Results:
* None.
*
*----------------------------------------------------------------------
*/
static inline void
ClockFmtScnStorage_GC_Out(ClockFmtScnStorage *entry)
{
TclSpliceOut(entry, ClockFmtScnStorage_GC.stackPtr);
ClockFmtScnStorage_GC.count--;
if (ClockFmtScnStorage_GC.stackBound == entry) {
ClockFmtScnStorage_GC.stackBound = entry->prevPtr;
}
entry->prevPtr = entry->nextPtr = NULL;
}
#endif
/*
* Global format storage hash table of type ClockFmtScnStorageHashKeyType
* (contains list of scan/format object storages, shared across all threads).
*
* Used for fast searching by format string.
*/
static Tcl_HashTable FmtScnHashTable;
static int initialized = 0;
/*
* Wrappers between pointers to hash entry and format storage object
*/
static inline Tcl_HashEntry *
HashEntry4FmtScn(ClockFmtScnStorage *fss) {
return (Tcl_HashEntry*)(fss + 1);
};
static inline ClockFmtScnStorage *
FmtScn4HashEntry(Tcl_HashEntry *hKeyPtr) {
return (ClockFmtScnStorage*)(((char*)hKeyPtr) - sizeof(ClockFmtScnStorage));
};
/*
*----------------------------------------------------------------------
*
* ClockFmtScnStorageAllocProc --
*
* Allocate space for a hash entry containing format storage together
* with the string key.
*
* Results:
* The return value is a pointer to the created entry.
*
*----------------------------------------------------------------------
*/
static Tcl_HashEntry *
ClockFmtScnStorageAllocProc(
TCL_UNUSED(Tcl_HashTable *), /* Hash table. */
void *keyPtr) /* Key to store in the hash table entry. */
{
ClockFmtScnStorage *fss;
const char *string = (const char *) keyPtr;
Tcl_HashEntry *hPtr;
unsigned int size,
allocsize = sizeof(ClockFmtScnStorage) + sizeof(Tcl_HashEntry);
allocsize += (size = strlen(string) + 1);
if (size > sizeof(hPtr->key)) {
allocsize -= sizeof(hPtr->key);
}
fss = (ClockFmtScnStorage *)Tcl_Alloc(allocsize);
/* initialize */
memset(fss, 0, sizeof(*fss));
hPtr = HashEntry4FmtScn(fss);
memcpy(&hPtr->key.string, string, size);
hPtr->clientData = 0; /* currently unused */
return hPtr;
}
/*
*----------------------------------------------------------------------
*
* ClockFmtScnStorageFreeProc --
*
* Free format storage object and space of given hash entry.
*
* Results:
* None.
*
*----------------------------------------------------------------------
*/
static void
ClockFmtScnStorageFreeProc(
Tcl_HashEntry *hPtr)
{
ClockFmtScnStorage *fss = FmtScn4HashEntry(hPtr);
if (fss->scnTok != NULL) {
Tcl_Free(fss->scnTok);
fss->scnTok = NULL;
fss->scnTokC = 0;
}
if (fss->fmtTok != NULL) {
Tcl_Free(fss->fmtTok);
fss->fmtTok = NULL;
fss->fmtTokC = 0;
}
Tcl_Free(fss);
}
/*
*----------------------------------------------------------------------
*
* ClockFmtScnStorageDelete --
*
* Delete format storage object.
*
* Results:
* None.
*
*----------------------------------------------------------------------
*/
static void
ClockFmtScnStorageDelete(ClockFmtScnStorage *fss) {
Tcl_HashEntry *hPtr = HashEntry4FmtScn(fss);
/*
* This will delete a hash entry and call "Tcl_Free" for storage self, if
* some additionally handling required, freeEntryProc can be used instead
*/
Tcl_DeleteHashEntry(hPtr);
}
/*
* Derivation of tclStringHashKeyType with another allocEntryProc
*/
static Tcl_HashKeyType ClockFmtScnStorageHashKeyType;
/*
* Type definition of clock-format tcl object type.
*/
static const Tcl_ObjType ClockFmtObjType = {
"clock-format", /* name */
ClockFmtObj_FreeInternalRep, /* freeIntRepProc */
ClockFmtObj_DupInternalRep, /* dupIntRepProc */
ClockFmtObj_UpdateString, /* updateStringProc */
ClockFmtObj_SetFromAny, /* setFromAnyProc */
TCL_OBJTYPE_V0
};
#define ObjClockFmtScn(objPtr) \
(*((ClockFmtScnStorage **)&(objPtr)->internalRep.twoPtrValue.ptr1))
#define ObjLocFmtKey(objPtr) \
(*((Tcl_Obj **)&(objPtr)->internalRep.twoPtrValue.ptr2))
static void
ClockFmtObj_DupInternalRep(
Tcl_Obj *srcPtr,
Tcl_Obj *copyPtr)
{
ClockFmtScnStorage *fss = ObjClockFmtScn(srcPtr);
if (fss != NULL) {
Tcl_MutexLock(&ClockFmtMutex);
fss->objRefCount++;
Tcl_MutexUnlock(&ClockFmtMutex);
}
ObjClockFmtScn(copyPtr) = fss;
/* regards special case - format not localizable */
if (ObjLocFmtKey(srcPtr) != srcPtr) {
TclInitObjRef(ObjLocFmtKey(copyPtr), ObjLocFmtKey(srcPtr));
} else {
ObjLocFmtKey(copyPtr) = copyPtr;
}
copyPtr->typePtr = &ClockFmtObjType;
/* if no format representation, dup string representation */
if (fss == NULL) {
copyPtr->bytes = (char *)Tcl_Alloc(srcPtr->length + 1);
memcpy(copyPtr->bytes, srcPtr->bytes, srcPtr->length + 1);
copyPtr->length = srcPtr->length;
}
}
static void
ClockFmtObj_FreeInternalRep(
Tcl_Obj *objPtr)
{
ClockFmtScnStorage *fss = ObjClockFmtScn(objPtr);
if (fss != NULL) {
Tcl_MutexLock(&ClockFmtMutex);
/* decrement object reference count of format/scan storage */
if (--fss->objRefCount <= 0) {
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
/* don't remove it right now (may be reusable), just add to GC */
ClockFmtScnStorageGC_In(fss);
#else
/* remove storage (format representation) */
ClockFmtScnStorageDelete(fss);
#endif
}
Tcl_MutexUnlock(&ClockFmtMutex);
}
ObjClockFmtScn(objPtr) = NULL;
if (ObjLocFmtKey(objPtr) != objPtr) {
TclUnsetObjRef(ObjLocFmtKey(objPtr));
} else {
ObjLocFmtKey(objPtr) = NULL;
}
objPtr->typePtr = NULL;
};
static int
ClockFmtObj_SetFromAny(
TCL_UNUSED(Tcl_Interp *),
Tcl_Obj *objPtr)
{
/* validate string representation before free old internal representation */
(void)TclGetString(objPtr);
/* free old internal representation */
if (objPtr->typePtr && objPtr->typePtr->freeIntRepProc)
objPtr->typePtr->freeIntRepProc(objPtr);
/* initial state of format object */
ObjClockFmtScn(objPtr) = NULL;
ObjLocFmtKey(objPtr) = NULL;
objPtr->typePtr = &ClockFmtObjType;
return TCL_OK;
};
static void
ClockFmtObj_UpdateString(
Tcl_Obj *objPtr)
{
const char *name = "UNKNOWN";
size_t len;
ClockFmtScnStorage *fss = ObjClockFmtScn(objPtr);
if (fss != NULL) {
Tcl_HashEntry *hPtr = HashEntry4FmtScn(fss);
name = hPtr->key.string;
}
len = strlen(name);
objPtr->length = len++,
objPtr->bytes = (char *)Tcl_Alloc(len);
if (objPtr->bytes) {
memcpy(objPtr->bytes, name, len);
}
}
/*
*----------------------------------------------------------------------
*
* ClockFrmObjGetLocFmtKey --
*
* Retrieves format key object used to search localized format.
*
* This is normally stored in second pointer of internal representation.
* If format object is not localizable, it is equal the given format
* pointer (special case to fast fallback by not-localizable formats).
*
* Results:
* Returns tcl object with key or format object if not localizable.
*
* Side effects:
* Converts given format object to ClockFmtObjType on demand for caching
* the key inside its internal representation.
*
*----------------------------------------------------------------------
*/
Tcl_Obj*
ClockFrmObjGetLocFmtKey(
Tcl_Interp *interp,
Tcl_Obj *objPtr)
{
Tcl_Obj *keyObj;
if (objPtr->typePtr != &ClockFmtObjType) {
if (ClockFmtObj_SetFromAny(interp, objPtr) != TCL_OK) {
return NULL;
}
}
keyObj = ObjLocFmtKey(objPtr);
if (keyObj) {
return keyObj;
}
keyObj = Tcl_ObjPrintf("FMT_%s", TclGetString(objPtr));
TclInitObjRef(ObjLocFmtKey(objPtr), keyObj);
return keyObj;
}
/*
*----------------------------------------------------------------------
*
* FindOrCreateFmtScnStorage --
*
* Retrieves format storage for given string format.
*
* This will find the given format in the global storage hash table
* or create a format storage object on demaind and save the
* reference in the first pointer of internal representation of given
* object.
*
* Results:
* Returns scan/format storage pointer to ClockFmtScnStorage.
*
* Side effects:
* Converts given format object to ClockFmtObjType on demand for caching
* the format storage reference inside its internal representation.
* Increments objRefCount of the ClockFmtScnStorage reference.
*
*----------------------------------------------------------------------
*/
static ClockFmtScnStorage *
FindOrCreateFmtScnStorage(
Tcl_Interp *interp,
Tcl_Obj *objPtr)
{
const char *strFmt = TclGetString(objPtr);
ClockFmtScnStorage *fss = NULL;
int isNew;
Tcl_HashEntry *hPtr;
Tcl_MutexLock(&ClockFmtMutex);
/* if not yet initialized */
if (!initialized) {
/* initialize type */
memcpy(&ClockFmtScnStorageHashKeyType, &tclStringHashKeyType, sizeof(tclStringHashKeyType));
ClockFmtScnStorageHashKeyType.allocEntryProc = ClockFmtScnStorageAllocProc;
ClockFmtScnStorageHashKeyType.freeEntryProc = ClockFmtScnStorageFreeProc;
/* initialize hash table */
Tcl_InitCustomHashTable(&FmtScnHashTable, TCL_CUSTOM_TYPE_KEYS,
&ClockFmtScnStorageHashKeyType);
initialized = 1;
Tcl_CreateExitHandler(ClockFrmScnFinalize, NULL);
}
/* get or create entry (and alocate storage) */
hPtr = Tcl_CreateHashEntry(&FmtScnHashTable, strFmt, &isNew);
if (hPtr != NULL) {
fss = FmtScn4HashEntry(hPtr);
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
/* unlink if it is currently in GC */
if (isNew == 0 && fss->objRefCount == 0) {
ClockFmtScnStorage_GC_Out(fss);
}
#endif
/* new reference, so increment in lock right now */
fss->objRefCount++;
ObjClockFmtScn(objPtr) = fss;
}
Tcl_MutexUnlock(&ClockFmtMutex);
if (fss == NULL && interp != NULL) {
Tcl_AppendResult(interp, "retrieve clock format failed \"",
strFmt ? strFmt : "", "\"", NULL);
Tcl_SetErrorCode(interp, "TCL", "EINVAL", (char *)NULL);
}
return fss;
}
/*
*----------------------------------------------------------------------
*
* Tcl_GetClockFrmScnFromObj --
*
* Returns a clock format/scan representation of (*objPtr), if possible.
* If something goes wrong, NULL is returned, and if interp is non-NULL,
* an error message is written there.
*
* Results:
* Valid representation of type ClockFmtScnStorage.
*
* Side effects:
* Caches the ClockFmtScnStorage reference as the internal rep of (*objPtr)
* and in global hash table, shared across all threads.
*
*----------------------------------------------------------------------
*/
ClockFmtScnStorage *
Tcl_GetClockFrmScnFromObj(
Tcl_Interp *interp,
Tcl_Obj *objPtr)
{
ClockFmtScnStorage *fss;
if (objPtr->typePtr != &ClockFmtObjType) {
if (ClockFmtObj_SetFromAny(interp, objPtr) != TCL_OK) {
return NULL;
}
}
fss = ObjClockFmtScn(objPtr);
if (fss == NULL) {
fss = FindOrCreateFmtScnStorage(interp, objPtr);
}
return fss;
}
/*
*----------------------------------------------------------------------
*
* ClockLocalizeFormat --
*
* Wrap the format object in options to the localized format,
* corresponding given locale.
*
* This searches localized format in locale catalog, and if not yet
* exists, it executes ::tcl::clock::LocalizeFormat in given interpreter
* and caches its result in the locale catalog.
*
* Results:
* Localized format object.
*
* Side effects:
* Caches the localized format inside locale catalog.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
ClockLocalizeFormat(
ClockFmtScnCmdArgs *opts)
{
ClockClientData *dataPtr = (ClockClientData *)opts->clientData;
Tcl_Obj *valObj = NULL, *keyObj;
keyObj = ClockFrmObjGetLocFmtKey(opts->interp, opts->formatObj);
/* special case - format object is not localizable */
if (keyObj == opts->formatObj) {
return opts->formatObj;
}
/* prevents loss of key object if the format object (where key stored)
* becomes changed (loses its internal representation during evals) */
Tcl_IncrRefCount(keyObj);
if (opts->mcDictObj == NULL) {
ClockMCDict(opts);
if (opts->mcDictObj == NULL)
goto done;
}
/* try to find in cache within locale mc-catalog */
if (Tcl_DictObjGet(NULL, opts->mcDictObj,
keyObj, &valObj) != TCL_OK) {
goto done;
}
/* call LocalizeFormat locale format fmtkey */
if (valObj == NULL) {
Tcl_Obj *callargs[4];
callargs[0] = dataPtr->literals[LIT_LOCALIZE_FORMAT];
callargs[1] = opts->localeObj;
callargs[2] = opts->formatObj;
callargs[3] = opts->mcDictObj;
if (Tcl_EvalObjv(opts->interp, 4, callargs, 0) == TCL_OK
) {
valObj = Tcl_GetObjResult(opts->interp);
}
/* ensure mcDictObj remains unshared */
if (opts->mcDictObj->refCount > 1) {
/* smart reference (shared dict as object with no ref-counter) */
opts->mcDictObj = TclDictObjSmartRef(opts->interp,
opts->mcDictObj);
}
if (!valObj) {
goto done;
}
/* cache it inside mc-dictionary (this incr. ref count of keyObj/valObj) */
if (Tcl_DictObjPut(opts->interp, opts->mcDictObj,
keyObj, valObj) != TCL_OK
) {
valObj = NULL;
goto done;
}
Tcl_ResetResult(opts->interp);
/* check special case - format object is not localizable */
if (valObj == opts->formatObj) {
/* mark it as unlocalizable, by setting self as key (without refcount incr) */
if (valObj->typePtr == &ClockFmtObjType) {
TclUnsetObjRef(ObjLocFmtKey(valObj));
ObjLocFmtKey(valObj) = valObj;
}
}
}
done:
TclUnsetObjRef(keyObj);
return (opts->formatObj = valObj);
}
/*
*----------------------------------------------------------------------
*
* FindTokenBegin --
*
* Find begin of given scan token in string, corresponding token type.
*
* Results:
* Position of token inside string if found. Otherwise - end of string.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static const char *
FindTokenBegin(
const char *p,
const char *end,
ClockScanToken *tok)
{
char c;
if (p < end) {
/* next token a known token type */
switch (tok->map->type) {
case CTOKT_INT:
case CTOKT_WIDE:
/* should match at least one digit */
while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {};
return p;
break;
case CTOKT_WORD:
c = *(tok->tokWord.start);
/* should match at least to the first char of this word */
while (*p != c && (p = Tcl_UtfNext(p)) < end) {};
return p;
break;
case CTOKT_SPACE:
while (!isspace(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {};
return p;
break;
case CTOKT_CHAR:
c = *((char *)tok->map->data);
while (*p != c && (p = Tcl_UtfNext(p)) < end) {};
return p;
break;
}
}
return p;
}
/*
*----------------------------------------------------------------------
*
* DetermineGreedySearchLen --
*
* Determine min/max lengths as exact as possible (speed, greedy match).
*
* Results:
* None. Lengths are stored in *minLenPtr, *maxLenPtr.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static void
DetermineGreedySearchLen(
DateInfo *info, ClockScanToken *tok,
int *minLenPtr, int *maxLenPtr)
{
int minLen = tok->map->minSize;
int maxLen;
const char *p = yyInput + minLen,
*end = info->dateEnd;
/* if still tokens available, try to correct minimum length */
if ((tok+1)->map) {
end -= tok->endDistance + yySpaceCount;
/* find position of next known token */
p = FindTokenBegin(p, end, tok+1);
if (p < end) {
minLen = p - yyInput;
}
}
/* max length to the end regarding distance to end (min-width of following tokens) */
maxLen = end - yyInput;
/* several amendments */
if (maxLen > tok->map->maxSize) {
maxLen = tok->map->maxSize;
};
if (minLen < tok->map->minSize) {
minLen = tok->map->minSize;
}
if (minLen > maxLen) {
maxLen = minLen;
}
if (maxLen > info->dateEnd - yyInput) {
maxLen = info->dateEnd - yyInput;
}
/* check digits rigth now */
if (tok->map->type == CTOKT_INT || tok->map->type == CTOKT_WIDE) {
p = yyInput;
end = p + maxLen;
if (end > info->dateEnd) { end = info->dateEnd; };
while (isdigit(UCHAR(*p)) && p < end) { p++; };
maxLen = p - yyInput;
}
/* try to get max length more precise for greedy match,
* check the next ahead token available there */
if (minLen < maxLen && tok->lookAhTok) {
ClockScanToken *laTok = tok + tok->lookAhTok + 1;
p = yyInput + maxLen;
/* regards all possible spaces here (because they are optional) */
end = p + tok->lookAhMax + yySpaceCount + 1;
if (end > info->dateEnd) {
end = info->dateEnd;
}
p += tok->lookAhMin;
if (laTok->map && p < end) {
const char *f;
/* try to find laTok between [lookAhMin, lookAhMax] */
while (minLen < maxLen) {
f = FindTokenBegin(p, end, laTok);
/* if found (not below lookAhMax) */
if (f < end) {
break;
}
/* try again with fewer length */
maxLen--;
p--;
end--;
}
} else if (p > end) {
maxLen -= (p - end);
if (maxLen < minLen) {
maxLen = minLen;
}
}
}
*minLenPtr = minLen;
*maxLenPtr = maxLen;
}
/*
*----------------------------------------------------------------------
*
* ObjListSearch --
*
* Find largest part of the input string from start regarding min and
* max lengths in the given list (utf-8, case sensitive).
*
* Results:
* TCL_OK - match found, TCL_RETURN - not matched, TCL_ERROR in error case.
*
* Side effects:
* Input points to end of the found token in string.
*
*----------------------------------------------------------------------
*/
static inline int
ObjListSearch(
DateInfo *info, int *val,
Tcl_Obj **lstv, Tcl_Size lstc,
int minLen, int maxLen)
{
Tcl_Size i, l, lf = -1;
const char *s, *f, *sf;
/* search in list */
for (i = 0; i < lstc; i++) {
s = TclGetStringFromObj(lstv[i], &l);
if ( l >= minLen
&& (f = TclUtfFindEqualNC(yyInput, yyInput + maxLen, s, s + l, &sf)) > yyInput
) {
l = f - yyInput;
if (l < minLen) {
continue;
}
/* found, try to find longest value (greedy search) */
if (l < maxLen && minLen != maxLen) {
lf = i;
minLen = l + 1;
continue;
}
/* max possible - end of search */
*val = i;
yyInput += l;
break;
}
}
/* if found */
if (i < lstc) {
return TCL_OK;
}
if (lf >= 0) {
*val = lf;
yyInput += minLen - 1;
return TCL_OK;
}
return TCL_RETURN;
}
#if 0
/* currently unused */
static int
LocaleListSearch(ClockFmtScnCmdArgs *opts,
DateInfo *info, int mcKey, int *val,
int minLen, int maxLen)
{
Tcl_Obj **lstv;
Tcl_Size lstc;
Tcl_Obj *valObj;
/* get msgcat value */
valObj = ClockMCGet(opts, mcKey);
if (valObj == NULL) {
return TCL_ERROR;
}
/* is a list */
if (TclListObjGetElements(opts->interp, valObj, &lstc, &lstv) != TCL_OK) {
return TCL_ERROR;
}
/* search in list */
return ObjListSearch(info, val, lstv, lstc,
minLen, maxLen);
}
#endif
/*
*----------------------------------------------------------------------
*
* ClockMCGetListIdxTree --
*
* Retrieves localized string indexed tree in the locale catalog for
* given literal index mcKey (and builds it on demand).
*
* Searches localized index in locale catalog, and if not yet exists,
* creates string indexed tree and stores it in the locale catalog.
*
* Results:
* Localized string index tree.
*
* Side effects:
* Caches the localized string index tree inside locale catalog.
*
*----------------------------------------------------------------------
*/
static TclStrIdxTree *
ClockMCGetListIdxTree(
ClockFmtScnCmdArgs *opts,
int mcKey)
{
TclStrIdxTree * idxTree;
Tcl_Obj *objPtr = ClockMCGetIdx(opts, mcKey);
if ( objPtr != NULL
&& (idxTree = TclStrIdxTreeGetFromObj(objPtr)) != NULL
) {
return idxTree;
} else {
/* build new index */
Tcl_Obj **lstv;
Tcl_Size lstc;
Tcl_Obj *valObj;
objPtr = TclStrIdxTreeNewObj();
if ((idxTree = TclStrIdxTreeGetFromObj(objPtr)) == NULL) {
goto done; /* unexpected, but ...*/
}
valObj = ClockMCGet(opts, mcKey);
if (valObj == NULL) {
goto done;
}
if (TclListObjGetElements(opts->interp, valObj,
&lstc, &lstv) != TCL_OK) {
goto done;
};
if (TclStrIdxTreeBuildFromList(idxTree, lstc, lstv, NULL) != TCL_OK) {
goto done;
}
ClockMCSetIdx(opts, mcKey, objPtr);
objPtr = NULL;
};
done:
if (objPtr) {
Tcl_DecrRefCount(objPtr);
idxTree = NULL;
}
return idxTree;
}
/*
*----------------------------------------------------------------------
*
* ClockMCGetMultiListIdxTree --
*
* Retrieves localized string indexed tree in the locale catalog for
* multiple lists by literal indices mcKeys (and builds it on demand).
*
* Searches localized index in locale catalog for mcKey, and if not
* yet exists, creates string indexed tree and stores it in the
* locale catalog.
*
* Results:
* Localized string index tree.
*
* Side effects:
* Caches the localized string index tree inside locale catalog.
*
*----------------------------------------------------------------------
*/
static TclStrIdxTree *
ClockMCGetMultiListIdxTree(
ClockFmtScnCmdArgs *opts,
int mcKey,
int *mcKeys)
{
TclStrIdxTree * idxTree;
Tcl_Obj *objPtr = ClockMCGetIdx(opts, mcKey);
if ( objPtr != NULL
&& (idxTree = TclStrIdxTreeGetFromObj(objPtr)) != NULL
) {
return idxTree;
} else {
/* build new index */
Tcl_Obj **lstv;
Tcl_Size lstc;
Tcl_Obj *valObj;
objPtr = TclStrIdxTreeNewObj();
if ((idxTree = TclStrIdxTreeGetFromObj(objPtr)) == NULL) {
goto done; /* unexpected, but ...*/
}
while (*mcKeys) {
valObj = ClockMCGet(opts, *mcKeys);
if (valObj == NULL) {
goto done;
}
if (TclListObjGetElements(opts->interp, valObj,
&lstc, &lstv) != TCL_OK) {
goto done;
};
if (TclStrIdxTreeBuildFromList(idxTree, lstc, lstv, NULL) != TCL_OK) {
goto done;
}
mcKeys++;
}
ClockMCSetIdx(opts, mcKey, objPtr);
objPtr = NULL;
};
done:
if (objPtr) {
Tcl_DecrRefCount(objPtr);
idxTree = NULL;
}
return idxTree;
}
/*
*----------------------------------------------------------------------
*
* ClockStrIdxTreeSearch --
*
* Find largest part of the input string from start regarding lengths
* in the given localized string indexed tree (utf-8, case sensitive).
*
* Results:
* TCL_OK - match found and the index stored in *val,
* TCL_RETURN - not matched or ambigous,
* TCL_ERROR - in error case.
*
* Side effects:
* Input points to end of the found token in string.
*
*----------------------------------------------------------------------
*/
static inline int
ClockStrIdxTreeSearch(
DateInfo *info, TclStrIdxTree *idxTree, int *val,
int minLen, int maxLen)
{
const char *f;
TclStrIdx *foundItem;
f = TclStrIdxTreeSearch(NULL, &foundItem, idxTree,
yyInput, yyInput + maxLen);
if (f <= yyInput || (f - yyInput) < minLen) {
/* not found */
return TCL_RETURN;
}
if (!foundItem->value) {
/* ambigous */
return TCL_RETURN;
}
*val = PTR2INT(foundItem->value);
/* shift input pointer */
yyInput = f;
return TCL_OK;
}
#if 0
/* currently unused */
static int
StaticListSearch(ClockFmtScnCmdArgs *opts,
DateInfo *info, const char **lst, int *val)
{
size_t len;
const char **s = lst;
while (*s != NULL) {
len = strlen(*s);
if ( len <= info->dateEnd - yyInput
&& strncasecmp(yyInput, *s, len) == 0
) {
*val = (s - lst);
yyInput += len;
break;
}
s++;
}
if (*s != NULL) {
return TCL_OK;
}
return TCL_RETURN;
}
#endif
static inline const char *
FindWordEnd(
ClockScanToken *tok,
const char * p, const char * end)
{
const char *x = tok->tokWord.start;
const char *pfnd = p;
if (x == tok->tokWord.end - 1) { /* fast phase-out for single char word */
if (*p == *x) {
return ++p;
}
}
/* multi-char word */
x = TclUtfFindEqualNC(x, tok->tokWord.end, p, end, &pfnd);
if (x < tok->tokWord.end) {
/* no match -> error */
return NULL;
}
return pfnd;
}
static int
ClockScnToken_Month_Proc(ClockFmtScnCmdArgs *opts,
DateInfo *info, ClockScanToken *tok)
{
#if 0
/* currently unused, test purposes only */
static const char * months[] = {
/* full */
"January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December",
/* abbr */
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
NULL
};
int val;
if (StaticListSearch(opts, info, months, &val) != TCL_OK) {
return TCL_RETURN;
}
yyMonth = (val % 12) + 1;
return TCL_OK;
#endif
static int monthsKeys[] = {MCLIT_MONTHS_FULL, MCLIT_MONTHS_ABBREV, 0};
int ret, val;
int minLen, maxLen;
TclStrIdxTree *idxTree;
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
/* get or create tree in msgcat dict */
idxTree = ClockMCGetMultiListIdxTree(opts, MCLIT_MONTHS_COMB, monthsKeys);
if (idxTree == NULL) {
return TCL_ERROR;
}
ret = ClockStrIdxTreeSearch(info, idxTree, &val, minLen, maxLen);
if (ret != TCL_OK) {
return ret;
}
yyMonth = val;
return TCL_OK;
}
static int
ClockScnToken_DayOfWeek_Proc(ClockFmtScnCmdArgs *opts,
DateInfo *info, ClockScanToken *tok)
{
static int dowKeys[] = {MCLIT_DAYS_OF_WEEK_ABBREV, MCLIT_DAYS_OF_WEEK_FULL, 0};
int ret, val;
int minLen, maxLen;
char curTok = *tok->tokWord.start;
TclStrIdxTree *idxTree;
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
/* %u %w %Ou %Ow */
if ( curTok != 'a' && curTok != 'A'
&& ((minLen <= 1 && maxLen >= 1) || PTR2INT(tok->map->data))
) {
val = -1;
if (PTR2INT(tok->map->data) == 0) {
if (*yyInput >= '0' && *yyInput <= '9') {
val = *yyInput - '0';
}
} else {
idxTree = ClockMCGetListIdxTree(opts, PTR2INT(tok->map->data) /* mcKey */);
if (idxTree == NULL) {
return TCL_ERROR;
}
ret = ClockStrIdxTreeSearch(info, idxTree, &val, minLen, maxLen);
if (ret != TCL_OK) {
return ret;
}
--val;
}
if (val != -1) {
if (val == 0) {
val = 7;
}
if (val > 7) {
Tcl_SetObjResult(opts->interp, Tcl_NewStringObj("day of week is greater than 7", -1));
Tcl_SetErrorCode(opts->interp, "CLOCK", "badDayOfWeek", (char *)NULL);
return TCL_ERROR;
}
info->date.dayOfWeek = val;
yyInput++;
return TCL_OK;
}
return TCL_RETURN;
}
/* %a %A */
idxTree = ClockMCGetMultiListIdxTree(opts, MCLIT_DAYS_OF_WEEK_COMB, dowKeys);
if (idxTree == NULL) {
return TCL_ERROR;
}
ret = ClockStrIdxTreeSearch(info, idxTree, &val, minLen, maxLen);
if (ret != TCL_OK) {
return ret;
}
--val;
if (val == 0) {
val = 7;
}
info->date.dayOfWeek = val;
return TCL_OK;
}
static int
ClockScnToken_amPmInd_Proc(ClockFmtScnCmdArgs *opts,
DateInfo *info, ClockScanToken *tok)
{
int ret, val;
int minLen, maxLen;
Tcl_Obj *amPmObj[2];
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
amPmObj[0] = ClockMCGet(opts, MCLIT_AM);
amPmObj[1] = ClockMCGet(opts, MCLIT_PM);
if (amPmObj[0] == NULL || amPmObj[1] == NULL) {
return TCL_ERROR;
}
ret = ObjListSearch(info, &val, amPmObj, 2,
minLen, maxLen);
if (ret != TCL_OK) {
return ret;
}
if (val == 0) {
yyMeridian = MERam;
} else {
yyMeridian = MERpm;
}
return TCL_OK;
}
static int
ClockScnToken_LocaleERA_Proc(ClockFmtScnCmdArgs *opts,
DateInfo *info, ClockScanToken *tok)
{
ClockClientData *dataPtr = (ClockClientData *)opts->clientData;
int ret, val;
int minLen, maxLen;
Tcl_Obj *eraObj[6];
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
eraObj[0] = ClockMCGet(opts, MCLIT_BCE);
eraObj[1] = ClockMCGet(opts, MCLIT_CE);
eraObj[2] = dataPtr->mcLiterals[MCLIT_BCE2];
eraObj[3] = dataPtr->mcLiterals[MCLIT_CE2];
eraObj[4] = dataPtr->mcLiterals[MCLIT_BCE3];
eraObj[5] = dataPtr->mcLiterals[MCLIT_CE3];
if (eraObj[0] == NULL || eraObj[1] == NULL) {
return TCL_ERROR;
}
ret = ObjListSearch(info, &val, eraObj, 6,
minLen, maxLen);
if (ret != TCL_OK) {
return ret;
}
if (val & 1) {
yydate.isBce = 0;
} else {
yydate.isBce = 1;
}
return TCL_OK;
}
static int
ClockScnToken_LocaleListMatcher_Proc(ClockFmtScnCmdArgs *opts,
DateInfo *info, ClockScanToken *tok)
{
int ret, val;
int minLen, maxLen;
TclStrIdxTree *idxTree;
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
/* get or create tree in msgcat dict */
idxTree = ClockMCGetListIdxTree(opts, PTR2INT(tok->map->data) /* mcKey */);
if (idxTree == NULL) {
return TCL_ERROR;
}
ret = ClockStrIdxTreeSearch(info, idxTree, &val, minLen, maxLen);
if (ret != TCL_OK) {
return ret;
}
if (tok->map->offs > 0) {
*(int *)(((char *)info) + tok->map->offs) = --val;
}
return TCL_OK;
}
static int
ClockScnToken_JDN_Proc(TCL_UNUSED(ClockFmtScnCmdArgs *),
DateInfo *info, ClockScanToken *tok)
{
int minLen, maxLen;
const char *p = yyInput, *end; const char *s;
Tcl_WideInt intJD; int fractJD = 0, fractJDDiv = 1;
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
end = yyInput + maxLen;
/* currently positive astronomic dates only */
if (*p == '+' || *p == '-') { p++; };
s = p;
while (p < end && isdigit(UCHAR(*p))) {
p++;
}
if ( _str2wideInt(&intJD, s, p, (*yyInput != '-' ? 1 : -1)) != TCL_OK) {
return TCL_RETURN;
};
yyInput = p;
if (p >= end || *p++ != '.') { /* allow pure integer JDN */
/* by astronomical JD the seconds of day offs is 12 hours */
if (tok->map->offs) {
goto done;
}
/* calendar JD */
yydate.julianDay = intJD;
return TCL_OK;
}
s = p;
while (p < end && isdigit(UCHAR(*p))) {
fractJDDiv *= 10;
p++;
}
if ( _str2int(&fractJD, s, p, 1) != TCL_OK) {
return TCL_RETURN;
};
yyInput = p;
done:
/*
* Build a date from julian day (integer and fraction).
* Note, astronomical JDN starts at noon in opposite to calendar julianday.
*/
fractJD = (int)tok->map->offs /* 0 for calendar or 43200 for astro JD */
+ (int)((Tcl_WideInt)SECONDS_PER_DAY * fractJD / fractJDDiv);
if (fractJD > SECONDS_PER_DAY) {
fractJD %= SECONDS_PER_DAY;
intJD += 1;
}
yydate.secondOfDay = fractJD;
yydate.julianDay = intJD;
yydate.seconds =
-210866803200LL
+ ( SECONDS_PER_DAY * intJD )
+ ( fractJD );
info->flags |= CLF_POSIXSEC;
return TCL_OK;
}
static int
ClockScnToken_TimeZone_Proc(ClockFmtScnCmdArgs *opts,
DateInfo *info, ClockScanToken *tok)
{
int minLen, maxLen;
int len = 0;
const char *p = yyInput;
Tcl_Obj *tzObjStor = NULL;
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
/* numeric timezone */
if (*p == '+' || *p == '-') {
/* max chars in numeric zone = "+00:00:00" */
#define MAX_ZONE_LEN 9
char buf[MAX_ZONE_LEN + 1];
char *bp = buf;
*bp++ = *p++; len++;
if (maxLen > MAX_ZONE_LEN)
maxLen = MAX_ZONE_LEN;
/* cumulate zone into buf without ':' */
while (len + 1 < maxLen) {
if (!isdigit(UCHAR(*p))) break;
*bp++ = *p++; len++;
if (!isdigit(UCHAR(*p))) break;
*bp++ = *p++; len++;
if (len + 2 < maxLen) {
if (*p == ':') {
p++; len++;
}
}
}
*bp = '\0';
if (len < minLen) {
return TCL_RETURN;
}
#undef MAX_ZONE_LEN
/* timezone */
tzObjStor = Tcl_NewStringObj(buf, bp-buf);
} else {
/* legacy (alnum) timezone like CEST, etc. */
if (maxLen > 4)
maxLen = 4;
while (len < maxLen) {
if ( (*p & 0x80)
|| (!isalpha(UCHAR(*p)) && !isdigit(UCHAR(*p)))
) { /* INTL: ISO only. */
break;
}
p++; len++;
}
if (len < minLen) {
return TCL_RETURN;
}
/* timezone */
tzObjStor = Tcl_NewStringObj(yyInput, p-yyInput);
/* convert using dict */
}
/* try to apply new time zone */
Tcl_IncrRefCount(tzObjStor);
opts->timezoneObj = ClockSetupTimeZone(opts->clientData, opts->interp,
tzObjStor);
Tcl_DecrRefCount(tzObjStor);
if (opts->timezoneObj == NULL) {
return TCL_ERROR;
}
yyInput += len;
return TCL_OK;
}
static int
ClockScnToken_StarDate_Proc(TCL_UNUSED(ClockFmtScnCmdArgs *),
DateInfo *info, ClockScanToken *tok)
{
int minLen, maxLen;
const char *p = yyInput, *end; const char *s;
int year, fractYear, fractDayDiv, fractDay;
static const char *stardatePref = "stardate ";
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
end = yyInput + maxLen;
/* stardate string */
p = TclUtfFindEqualNCInLwr(p, end, stardatePref, stardatePref + 9, &s);
if (p >= end || p - yyInput < 9) {
return TCL_RETURN;
}
/* bypass spaces */
while (p < end && isspace(UCHAR(*p))) {
p++;
}
if (p >= end) {
return TCL_RETURN;
}
/* currently positive stardate only */
if (*p == '+') { p++; };
s = p;
while (p < end && isdigit(UCHAR(*p))) {
p++;
}
if (p >= end || p - s < 4) {
return TCL_RETURN;
}
if ( _str2int(&year, s, p-3, 1) != TCL_OK
|| _str2int(&fractYear, p-3, p, 1) != TCL_OK) {
return TCL_RETURN;
};
if (*p++ != '.') {
return TCL_RETURN;
}
s = p;
fractDayDiv = 1;
while (p < end && isdigit(UCHAR(*p))) {
fractDayDiv *= 10;
p++;
}
if ( _str2int(&fractDay, s, p, 1) != TCL_OK) {
return TCL_RETURN;
};
yyInput = p;
/* Build a date from year and fraction. */
yydate.year = year + RODDENBERRY;
yydate.isBce = 0;
yydate.gregorian = 1;
if (IsGregorianLeapYear(&yydate)) {
fractYear *= 366;
} else {
fractYear *= 365;
}
yydate.dayOfYear = fractYear / 1000 + 1;
if (fractYear % 1000 >= 500) {
yydate.dayOfYear++;
}
GetJulianDayFromEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);
yydate.localSeconds =
-210866803200LL
+ ( SECONDS_PER_DAY * yydate.julianDay )
+ ( SECONDS_PER_DAY * fractDay / fractDayDiv );
return TCL_OK;
}
static const char *ScnSTokenMapIndex =
"dmbyYHMSpJjCgGVazUsntQ";
static ClockScanTokenMap ScnSTokenMap[] = {
/* %d %e */
{CTOKT_INT, CLF_DAYOFMONTH, 0, 1, 2, offsetof(DateInfo, date.dayOfMonth),
NULL, NULL},
/* %m %N */
{CTOKT_INT, CLF_MONTH, 0, 1, 2, offsetof(DateInfo, date.month),
NULL, NULL},
/* %b %B %h */
{CTOKT_PARSER, CLF_MONTH, 0, 0, 0xffff, 0,
ClockScnToken_Month_Proc, NULL},
/* %y */
{CTOKT_INT, CLF_YEAR, 0, 1, 2, offsetof(DateInfo, date.year),
NULL, NULL},
/* %Y */
{CTOKT_INT, CLF_YEAR | CLF_CENTURY, 0, 4, 4, offsetof(DateInfo, date.year),
NULL, NULL},
/* %H %k %I %l */
{CTOKT_INT, CLF_TIME, 0, 1, 2, offsetof(DateInfo, date.hour),
NULL, NULL},
/* %M */
{CTOKT_INT, CLF_TIME, 0, 1, 2, offsetof(DateInfo, date.minutes),
NULL, NULL},
/* %S */
{CTOKT_INT, CLF_TIME, 0, 1, 2, offsetof(DateInfo, date.secondOfMin),
NULL, NULL},
/* %p %P */
{CTOKT_PARSER, 0, 0, 0, 0xffff, 0,
ClockScnToken_amPmInd_Proc, NULL},
/* %J */
{CTOKT_WIDE, CLF_JULIANDAY | CLF_SIGNED, 0, 1, 0xffff, offsetof(DateInfo, date.julianDay),
NULL, NULL},
/* %j */
{CTOKT_INT, CLF_DAYOFYEAR, 0, 1, 3, offsetof(DateInfo, date.dayOfYear),
NULL, NULL},
/* %C */
{CTOKT_INT, CLF_CENTURY|CLF_ISO8601CENTURY, 0, 1, 2, offsetof(DateInfo, dateCentury),
NULL, NULL},
/* %g */
{CTOKT_INT, CLF_ISO8601YEAR, 0, 2, 2, offsetof(DateInfo, date.iso8601Year),
NULL, NULL},
/* %G */
{CTOKT_INT, CLF_ISO8601YEAR | CLF_ISO8601CENTURY, 0, 4, 4, offsetof(DateInfo, date.iso8601Year),
NULL, NULL},
/* %V */
{CTOKT_INT, CLF_ISO8601WEAK, 0, 1, 2, offsetof(DateInfo, date.iso8601Week),
NULL, NULL},
/* %a %A %u %w */
{CTOKT_PARSER, CLF_DAYOFWEEK, 0, 0, 0xffff, 0,
ClockScnToken_DayOfWeek_Proc, NULL},
/* %z %Z */
{CTOKT_PARSER, CLF_OPTIONAL, 0, 0, 0xffff, 0,
ClockScnToken_TimeZone_Proc, NULL},
/* %U %W */
{CTOKT_INT, CLF_OPTIONAL, 0, 1, 2, 0, /* currently no capture, parse only token */
NULL, NULL},
/* %s */
{CTOKT_WIDE, CLF_POSIXSEC | CLF_SIGNED, 0, 1, 0xffff, offsetof(DateInfo, date.seconds),
NULL, NULL},
/* %n */
{CTOKT_CHAR, 0, 0, 1, 1, 0, NULL, "\n"},
/* %t */
{CTOKT_CHAR, 0, 0, 1, 1, 0, NULL, "\t"},
/* %Q */
{CTOKT_PARSER, CLF_LOCALSEC, 0, 16, 30, 0,
ClockScnToken_StarDate_Proc, NULL},
};
static const char *ScnSTokenMapAliasIndex[2] = {
"eNBhkIlPAuwZW",
"dmbbHHHpaaazU"
};
static const char *ScnETokenMapIndex =
"EJjys";
static ClockScanTokenMap ScnETokenMap[] = {
/* %EE */
{CTOKT_PARSER, 0, 0, 0, 0xffff, offsetof(DateInfo, date.year),
ClockScnToken_LocaleERA_Proc, (void *)MCLIT_LOCALE_NUMERALS},
/* %EJ */
{CTOKT_PARSER, CLF_JULIANDAY | CLF_SIGNED, 0, 1, 0xffff, 0, /* calendar JDN starts at midnight */
ClockScnToken_JDN_Proc, NULL},
/* %Ej */
{CTOKT_PARSER, CLF_JULIANDAY | CLF_SIGNED, 0, 1, 0xffff, (SECONDS_PER_DAY/2), /* astro JDN starts at noon */
ClockScnToken_JDN_Proc, NULL},
/* %Ey */
{CTOKT_PARSER, 0, 0, 0, 0xffff, 0, /* currently no capture, parse only token */
ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
/* %Es */
{CTOKT_WIDE, CLF_LOCALSEC | CLF_SIGNED, 0, 1, 0xffff, offsetof(DateInfo, date.localSeconds),
NULL, NULL},
};
static const char *ScnETokenMapAliasIndex[2] = {
"",
""
};
static const char *ScnOTokenMapIndex =
"dmyHMSu";
static ClockScanTokenMap ScnOTokenMap[] = {
/* %Od %Oe */
{CTOKT_PARSER, CLF_DAYOFMONTH, 0, 0, 0xffff, offsetof(DateInfo, date.dayOfMonth),
ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
/* %Om */
{CTOKT_PARSER, CLF_MONTH, 0, 0, 0xffff, offsetof(DateInfo, date.month),
ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
/* %Oy */
{CTOKT_PARSER, CLF_YEAR, 0, 0, 0xffff, offsetof(DateInfo, date.year),
ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
/* %OH %Ok %OI %Ol */
{CTOKT_PARSER, CLF_TIME, 0, 0, 0xffff, offsetof(DateInfo, date.hour),
ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
/* %OM */
{CTOKT_PARSER, CLF_TIME, 0, 0, 0xffff, offsetof(DateInfo, date.minutes),
ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
/* %OS */
{CTOKT_PARSER, CLF_TIME, 0, 0, 0xffff, offsetof(DateInfo, date.secondOfMin),
ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
/* %Ou Ow */
{CTOKT_PARSER, CLF_DAYOFWEEK, 0, 0, 0xffff, 0,
ClockScnToken_DayOfWeek_Proc, (void *)MCLIT_LOCALE_NUMERALS},
};
static const char *ScnOTokenMapAliasIndex[2] = {
"ekIlw",
"dHHHu"
};
/* Token map reserved for CTOKT_SPACE */
static ClockScanTokenMap ScnSpaceTokenMap = {
CTOKT_SPACE, 0, 0, 1, 1, 0,
NULL, NULL
};
static ClockScanTokenMap ScnWordTokenMap = {
CTOKT_WORD, 0, 0, 1, 1, 0,
NULL, NULL
};
static inline unsigned int
EstimateTokenCount(
const char *fmt,
const char *end)
{
const char *p = fmt;
unsigned int tokcnt;
/* estimate token count by % char and format length */
tokcnt = 0;
while (p <= end) {
if (*p++ == '%') {
tokcnt++;
p++;
}
}
p = fmt + tokcnt * 2;
if (p < end) {
if ((unsigned int)(end - p) < tokcnt) {
tokcnt += (end - p);
} else {
tokcnt += tokcnt;
}
}
return ++tokcnt;
}
#define AllocTokenInChain(tok, chain, tokCnt, type) \
if (++(tok) >= (chain) + (tokCnt)) { \
chain = (type)Tcl_Realloc((char *)(chain), \
(tokCnt + CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE) * sizeof(*(tok))); \
if ((chain) == NULL) { goto done; }; \
(tok) = (chain) + (tokCnt); \
(tokCnt) += CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE; \
} \
memset(tok, 0, sizeof(*(tok)));
/*
*----------------------------------------------------------------------
*/
ClockFmtScnStorage *
ClockGetOrParseScanFormat(
Tcl_Interp *interp, /* Tcl interpreter */
Tcl_Obj *formatObj) /* Format container */
{
ClockFmtScnStorage *fss;
fss = Tcl_GetClockFrmScnFromObj(interp, formatObj);
if (fss == NULL) {
return NULL;
}
/* if format (scnTok) already tokenized */
if (fss->scnTok != NULL) {
return fss;
}
Tcl_MutexLock(&ClockFmtMutex);
/* first time scanning - tokenize format */
if (fss->scnTok == NULL) {
ClockScanToken *tok, *scnTok;
unsigned int tokCnt;
const char *p, *e, *cp;
e = p = HashEntry4FmtScn(fss)->key.string;
e += strlen(p);
/* estimate token count by % char and format length */
fss->scnTokC = EstimateTokenCount(p, e);
fss->scnSpaceCount = 0;
scnTok = tok = (ClockScanToken *)Tcl_Alloc(sizeof(*tok) * fss->scnTokC);
memset(tok, 0, sizeof(*(tok)));
tokCnt = 1;
while (p < e) {
switch (*p) {
case '%':
if (1) {
ClockScanTokenMap * scnMap = ScnSTokenMap;
const char *mapIndex = ScnSTokenMapIndex,
**aliasIndex = ScnSTokenMapAliasIndex;
if (p+1 >= e) {
goto word_tok;
}
p++;
/* try to find modifier: */
switch (*p) {
case '%':
/* begin new word token - don't join with previous word token,
* because current mapping should be "...%%..." -> "...%..." */
tok->map = &ScnWordTokenMap;
tok->tokWord.start = p;
tok->tokWord.end = p+1;
AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++;
p++;
continue;
break;
case 'E':
scnMap = ScnETokenMap,
mapIndex = ScnETokenMapIndex,
aliasIndex = ScnETokenMapAliasIndex;
p++;
break;
case 'O':
scnMap = ScnOTokenMap,
mapIndex = ScnOTokenMapIndex,
aliasIndex = ScnOTokenMapAliasIndex;
p++;
break;
}
/* search direct index */
cp = strchr(mapIndex, *p);
if (!cp || *cp == '\0') {
/* search wrapper index (multiple chars for same token) */
cp = strchr(aliasIndex[0], *p);
if (!cp || *cp == '\0') {
p--; if (scnMap != ScnSTokenMap) p--;
goto word_tok;
}
cp = strchr(mapIndex, aliasIndex[1][cp - aliasIndex[0]]);
if (!cp || *cp == '\0') { /* unexpected, but ... */
#ifdef DEBUG
Tcl_Panic("token \"%c\" has no map in wrapper resolver", *p);
#endif
p--; if (scnMap != ScnSTokenMap) p--;
goto word_tok;
}
}
tok->map = &scnMap[cp - mapIndex];
tok->tokWord.start = p;
/* calculate look ahead value by standing together tokens */
if (tok > scnTok) {
ClockScanToken *prevTok = tok - 1;
while (prevTok >= scnTok) {
if (prevTok->map->type != tok->map->type) {
break;
}
prevTok->lookAhMin += tok->map->minSize;
prevTok->lookAhMax += tok->map->maxSize;
prevTok->lookAhTok++;
prevTok--;
}
}
/* increase space count used in format */
if ( tok->map->type == CTOKT_CHAR
&& isspace(UCHAR(*((char *)tok->map->data)))
) {
fss->scnSpaceCount++;
}
/* next token */
AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++;
p++;
continue;
}
break;
default:
if ( *p == ' ' || isspace(UCHAR(*p)) ) {
tok->map = &ScnSpaceTokenMap;
tok->tokWord.start = p++;
while (p < e && isspace(UCHAR(*p))) {
p++;
}
tok->tokWord.end = p;
/* increase space count used in format */
fss->scnSpaceCount++;
/* next token */
AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++;
continue;
}
word_tok:
if (1) {
ClockScanToken *wordTok = tok;
if (tok > scnTok && (tok-1)->map == &ScnWordTokenMap) {
wordTok = tok-1;
}
/* new word token */
if (wordTok == tok) {
wordTok->tokWord.start = p;
wordTok->map = &ScnWordTokenMap;
AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++;
}
if (isspace(UCHAR(*p))) {
fss->scnSpaceCount++;
}
p = Tcl_UtfNext(p);
wordTok->tokWord.end = p;
}
break;
}
}
/* calculate end distance value for each tokens */
if (tok > scnTok) {
unsigned int endDist = 0;
ClockScanToken *prevTok = tok-1;
while (prevTok >= scnTok) {
prevTok->endDistance = endDist;
if (prevTok->map->type != CTOKT_WORD) {
endDist += prevTok->map->minSize;
} else {
endDist += prevTok->tokWord.end - prevTok->tokWord.start;
}
prevTok--;
}
}
/* correct count of real used tokens and free mem if desired
* (1 is acceptable delta to prevent memory fragmentation) */
if (fss->scnTokC > tokCnt + (CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE / 2)) {
if ( (tok = (ClockScanToken *)Tcl_Realloc(scnTok, tokCnt * sizeof(*tok))) != NULL ) {
scnTok = tok;
}
}
/* now we're ready - assign now to storage (note the threaded race condition) */
fss->scnTok = scnTok;
fss->scnTokC = tokCnt;
}
done:
Tcl_MutexUnlock(&ClockFmtMutex);
return fss;
}
/*
*----------------------------------------------------------------------
*/
int
ClockScan(
DateInfo *info, /* Date fields used for parsing & converting */
Tcl_Obj *strObj, /* String containing the time to scan */
ClockFmtScnCmdArgs *opts) /* Command options */
{
ClockClientData *dataPtr = (ClockClientData *)opts->clientData;
ClockFmtScnStorage *fss;
ClockScanToken *tok;
ClockScanTokenMap *map;
const char *p, *x, *end;
unsigned short int flags = 0;
int ret = TCL_ERROR;
/* get localized format */
if (ClockLocalizeFormat(opts) == NULL) {
return TCL_ERROR;
}
if ( !(fss = ClockGetOrParseScanFormat(opts->interp, opts->formatObj))
|| !(tok = fss->scnTok)
) {
return TCL_ERROR;
}
/* prepare parsing */
yyMeridian = MER24;
p = TclGetString(strObj);
end = p + strObj->length;
/* in strict mode - bypass spaces at begin / end only (not between tokens) */
if (opts->flags & CLF_STRICT) {
while (p < end && isspace(UCHAR(*p))) {
p++;
}
}
yyInput = p;
/* look ahead to count spaces (bypass it by count length and distances) */
x = end;
while (p < end) {
if (isspace(UCHAR(*p))) {
x = ++p; /* after first space in space block */
yySpaceCount++;
while (p < end && isspace(UCHAR(*p))) {
p++;
yySpaceCount++;
}
continue;
}
x = end;
p++;
}
/* ignore more as 1 space at end */
yySpaceCount -= (end - x);
end = x;
/* ignore mandatory spaces used in format */
yySpaceCount -= fss->scnSpaceCount;
if (yySpaceCount < 0) {
yySpaceCount = 0;
}
info->dateStart = p = yyInput;
info->dateEnd = end;
/* parse string */
for (; tok->map != NULL; tok++) {
map = tok->map;
/* bypass spaces at begin of input before parsing each token */
if ( !(opts->flags & CLF_STRICT)
&& ( map->type != CTOKT_SPACE
&& map->type != CTOKT_WORD
&& map->type != CTOKT_CHAR )
) {
while (p < end && isspace(UCHAR(*p))) {
yySpaceCount--;
p++;
}
}
yyInput = p;
/* end of input string */
if (p >= end) {
break;
}
switch (map->type)
{
case CTOKT_INT:
case CTOKT_WIDE:
if (1) {
int minLen, size;
int sign = 1;
if (map->flags & CLF_SIGNED) {
if (*p == '+') { yyInput = ++p; }
else
if (*p == '-') { yyInput = ++p; sign = -1; };
}
DetermineGreedySearchLen(info, tok, &minLen, &size);
if (size < map->minSize) {
/* missing input -> error */
if ((map->flags & CLF_OPTIONAL)) {
continue;
}
goto not_match;
}
/* string 2 number, put number into info structure by offset */
if (map->offs) {
p = yyInput; x = p + size;
if (map->type == CTOKT_INT) {
if (size <= 10) {
_str2int_no((int *)(((char *)info) + map->offs),
p, x, sign);
} else {
if (_str2int((int *)(((char *)info) + map->offs),
p, x, sign) != TCL_OK) {
goto overflow;
}
}
p = x;
} else {
if (size <= 18) {
_str2wideInt_no((Tcl_WideInt *)(((char *)info) + map->offs),
p, x, sign);
} else {
if (_str2wideInt((Tcl_WideInt *)(((char *)info) + map->offs),
p, x, sign) != TCL_OK) {
goto overflow;
}
}
p = x;
}
flags = (flags & ~map->clearFlags) | map->flags;
}
}
break;
case CTOKT_PARSER:
switch (map->parser(opts, info, tok)) {
case TCL_OK:
break;
case TCL_RETURN:
if ((map->flags & CLF_OPTIONAL)) {
yyInput = p;
continue;
}
goto not_match;
break;
default:
goto done;
break;
};
/* decrement count for possible spaces in match */
while (p < yyInput) {
if (isspace(UCHAR(*p))) {
yySpaceCount--;
}
p++;
}
p = yyInput;
flags = (flags & ~map->clearFlags) | map->flags;
break;
case CTOKT_SPACE:
/* at least one space */
if (!isspace(UCHAR(*p))) {
/* unmatched -> error */
goto not_match;
}
/* don't decrement yySpaceCount by regular (first expected space),
* already considered above with fss->scnSpaceCount */;
p++;
while (p < end && isspace(UCHAR(*p))) {
yySpaceCount--;
p++;
}
break;
case CTOKT_WORD:
x = FindWordEnd(tok, p, end);
if (!x) {
/* no match -> error */
goto not_match;
}
p = x;
break;
case CTOKT_CHAR:
x = (char *)map->data;
if (*x != *p) {
/* no match -> error */
goto not_match;
}
if (isspace(UCHAR(*x))) {
yySpaceCount--;
}
p++;
break;
}
}
/* check end was reached */
if (p < end) {
/* in non-strict mode bypass spaces at end of input */
if ( !(opts->flags & CLF_STRICT) && isspace(UCHAR(*p)) ) {
p++;
while (p < end && isspace(UCHAR(*p))) {
p++;
}
}
/* something after last token - wrong format */
if (p < end) {
goto not_match;
}
}
/* end of string, check only optional tokens at end, otherwise - not match */
while (tok->map != NULL) {
if (!(opts->flags & CLF_STRICT) && (tok->map->type == CTOKT_SPACE)) {
tok++;
if (tok->map == NULL) {
/* no tokens anymore - trailing spaces are mandatory */
goto not_match;
}
}
if (!(tok->map->flags & CLF_OPTIONAL)) {
goto not_match;
}
tok++;
}
/*
* Invalidate result
*/
flags |= info->flags;
/* seconds token (%s) take precedence over all other tokens */
if ((opts->flags & CLF_EXTENDED) || !(flags & CLF_POSIXSEC)) {
if (flags & CLF_DATE) {
if (!(flags & CLF_JULIANDAY)) {
info->flags |= CLF_ASSEMBLE_SECONDS|CLF_ASSEMBLE_JULIANDAY;
/* dd precedence below ddd */
switch (flags & (CLF_MONTH|CLF_DAYOFYEAR|CLF_DAYOFMONTH)) {
case (CLF_DAYOFYEAR|CLF_DAYOFMONTH):
/* miss month: ddd over dd (without month) */
flags &= ~CLF_DAYOFMONTH;
/* fallthrough */
case (CLF_DAYOFYEAR):
/* ddd over naked weekday */
if (!(flags & CLF_ISO8601YEAR)) {
flags &= ~CLF_ISO8601WEAK;
}
break;
case (CLF_MONTH|CLF_DAYOFYEAR|CLF_DAYOFMONTH):
/* both available: mmdd over ddd */
case (CLF_MONTH|CLF_DAYOFMONTH):
case (CLF_DAYOFMONTH):
/* mmdd / dd over naked weekday */
if (!(flags & CLF_ISO8601YEAR)) {
flags &= ~CLF_ISO8601WEAK;
}
break;
/* neither mmdd nor ddd available */
case 0:
/* but we have day of the week, which can be used */
if (flags & CLF_DAYOFWEEK) {
/* prefer week based calculation of julianday */
flags |= CLF_ISO8601WEAK;
}
}
/* YearWeekDay below YearMonthDay */
if ( (flags & CLF_ISO8601WEAK)
&& ( (flags & (CLF_YEAR|CLF_DAYOFYEAR)) == (CLF_YEAR|CLF_DAYOFYEAR)
|| (flags & (CLF_YEAR|CLF_DAYOFMONTH|CLF_MONTH)) == (CLF_YEAR|CLF_DAYOFMONTH|CLF_MONTH)
)
) {
/* yy precedence below yyyy */
if (!(flags & CLF_ISO8601CENTURY) && (flags & CLF_CENTURY)) {
/* normally precedence of ISO is higher, but no century - so put it down */
flags &= ~CLF_ISO8601WEAK;
}
else
/* yymmdd or yyddd over naked weekday */
if (!(flags & CLF_ISO8601YEAR)) {
flags &= ~CLF_ISO8601WEAK;
}
}
if ( (flags & CLF_YEAR) ) {
if (yyYear < 100) {
if (!(flags & CLF_CENTURY)) {
if (yyYear >= dataPtr->yearOfCenturySwitch) {
yyYear -= 100;
}
yyYear += dataPtr->currentYearCentury;
} else {
yyYear += info->dateCentury * 100;
}
}
}
if ( (flags & (CLF_ISO8601WEAK|CLF_ISO8601YEAR)) ) {
if ((flags & (CLF_ISO8601YEAR|CLF_YEAR)) == CLF_YEAR) {
/* for calculations expected iso year */
info->date.iso8601Year = yyYear;
}
else
if (info->date.iso8601Year < 100) {
if (!(flags & CLF_ISO8601CENTURY)) {
if (info->date.iso8601Year >= dataPtr->yearOfCenturySwitch) {
info->date.iso8601Year -= 100;
}
info->date.iso8601Year += dataPtr->currentYearCentury;
} else {
info->date.iso8601Year += info->dateCentury * 100;
}
}
if ((flags & (CLF_ISO8601YEAR|CLF_YEAR)) == CLF_ISO8601YEAR) {
/* for calculations expected year (e. g. CLF_ISO8601WEAK not set) */
yyYear = info->date.iso8601Year;
}
}
}
}
/* if no time - reset time */
if (!(flags & (CLF_TIME|CLF_LOCALSEC|CLF_POSIXSEC))) {
info->flags |= CLF_ASSEMBLE_SECONDS;
yydate.localSeconds = 0;
}
if (flags & CLF_TIME) {
info->flags |= CLF_ASSEMBLE_SECONDS;
yySecondOfDay = ToSeconds(yyHour, yyMinutes,
yySeconds, yyMeridian);
} else
if (!(flags & (CLF_LOCALSEC|CLF_POSIXSEC))) {
info->flags |= CLF_ASSEMBLE_SECONDS;
yySecondOfDay = yydate.localSeconds % SECONDS_PER_DAY;
}
}
/* tell caller which flags were set */
info->flags |= flags;
ret = TCL_OK;
goto done;
overflow:
Tcl_SetObjResult(opts->interp, Tcl_NewStringObj("integer value too large to represent",
-1));
Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", (char *)NULL);
goto done;
not_match:
#if 1
Tcl_SetObjResult(opts->interp, Tcl_NewStringObj("input string does not match supplied format",
-1));
#else
/* to debug where exactly scan breaks */
Tcl_SetObjResult(opts->interp, Tcl_ObjPrintf(
"input string \"%s\" does not match supplied format \"%s\","
" locale \"%s\" - token \"%s\"",
info->dateStart, HashEntry4FmtScn(fss)->key.string,
Tcl_GetString(opts->localeObj),
tok && tok->tokWord.start ? tok->tokWord.start : "NULL"));
#endif
Tcl_SetErrorCode(opts->interp, "CLOCK", "badInputString", (char *)NULL);
done:
return ret;
}
#define FrmResultIsAllocated(dateFmt) \
(dateFmt->resEnd - dateFmt->resMem > MIN_FMT_RESULT_BLOCK_ALLOC)
static inline int
FrmResultAllocate(
DateFormat *dateFmt,
int len)
{
int needed = dateFmt->output + len - dateFmt->resEnd;
if (needed >= 0) { /* >= 0 - regards NTS zero */
int newsize = dateFmt->resEnd - dateFmt->resMem
+ needed + MIN_FMT_RESULT_BLOCK_ALLOC*2;
char *newRes;
/* differentiate between stack and memory */
if (!FrmResultIsAllocated(dateFmt)) {
newRes = (char *)Tcl_Alloc(newsize);
if (newRes == NULL) {
return TCL_ERROR;
}
memcpy(newRes, dateFmt->resMem, dateFmt->output - dateFmt->resMem);
} else {
newRes = (char *)Tcl_Realloc(dateFmt->resMem, newsize);
if (newRes == NULL) {
return TCL_ERROR;
}
}
dateFmt->output = newRes + (dateFmt->output - dateFmt->resMem);
dateFmt->resMem = newRes;
dateFmt->resEnd = newRes + newsize;
}
return TCL_OK;
}
static int
ClockFmtToken_HourAMPM_Proc(
TCL_UNUSED(ClockFmtScnCmdArgs *),
TCL_UNUSED(DateFormat *),
TCL_UNUSED(ClockFormatToken *),
int *val)
{
*val = ( ( *val + SECONDS_PER_DAY - 3600 ) / 3600 ) % 12 + 1;
return TCL_OK;
}
static int
ClockFmtToken_AMPM_Proc(
ClockFmtScnCmdArgs *opts,
DateFormat *dateFmt,
ClockFormatToken *tok,
int *val)
{
Tcl_Obj *mcObj;
const char *s;
Tcl_Size len;
if (*val < (SECONDS_PER_DAY / 2)) {
mcObj = ClockMCGet(opts, MCLIT_AM);
} else {
mcObj = ClockMCGet(opts, MCLIT_PM);
}
if (mcObj == NULL) {
return TCL_ERROR;
}
s = TclGetStringFromObj(mcObj, &len);
if (FrmResultAllocate(dateFmt, len) != TCL_OK) { return TCL_ERROR; };
memcpy(dateFmt->output, s, len + 1);
if (*tok->tokWord.start == 'p') {
len = Tcl_UtfToUpper(dateFmt->output);
}
dateFmt->output += len;
return TCL_OK;
}
static int
ClockFmtToken_StarDate_Proc(
TCL_UNUSED(ClockFmtScnCmdArgs *),
DateFormat *dateFmt,
TCL_UNUSED(ClockFormatToken *),
TCL_UNUSED(int *))
{
int fractYear;
/* Get day of year, zero based */
int v = dateFmt->date.dayOfYear - 1;
/* Convert day of year to a fractional year */
if (IsGregorianLeapYear(&dateFmt->date)) {
fractYear = 1000 * v / 366;
} else {
fractYear = 1000 * v / 365;
}
/* Put together the StarDate as "Stardate %02d%03d.%1d" */
if (FrmResultAllocate(dateFmt, 30) != TCL_OK) { return TCL_ERROR; };
memcpy(dateFmt->output, "Stardate ", 9);
dateFmt->output += 9;
dateFmt->output = _itoaw(dateFmt->output,
dateFmt->date.year - RODDENBERRY, '0', 2);
dateFmt->output = _itoaw(dateFmt->output,
fractYear, '0', 3);
*dateFmt->output++ = '.';
/* be sure positive after decimal point (note: clock-value can be negative) */
v = dateFmt->date.secondOfDay / ( SECONDS_PER_DAY / 10 );
if (v < 0) v = 10 + v;
dateFmt->output = _itoaw(dateFmt->output, v, '0', 1);
return TCL_OK;
}
static int
ClockFmtToken_WeekOfYear_Proc(
TCL_UNUSED(ClockFmtScnCmdArgs *),
DateFormat *dateFmt,
ClockFormatToken *tok,
int *val)
{
int dow = dateFmt->date.dayOfWeek;
if (*tok->tokWord.start == 'U') {
if (dow == 7) {
dow = 0;
}
dow++;
}
*val = ( dateFmt->date.dayOfYear - dow + 7 ) / 7;
return TCL_OK;
}
static int
ClockFmtToken_JDN_Proc(
TCL_UNUSED(ClockFmtScnCmdArgs *),
DateFormat *dateFmt,
ClockFormatToken *tok,
TCL_UNUSED(int *))
{
Tcl_WideInt intJD = dateFmt->date.julianDay;
int fractJD;
/* Convert to JDN parts (regarding start offset) and time fraction */
fractJD = dateFmt->date.secondOfDay
- (int)tok->map->offs; /* 0 for calendar or 43200 for astro JD */
if (fractJD < 0) {
intJD--;
fractJD += SECONDS_PER_DAY;
}
if (fractJD && intJD < 0) { /* avoid jump over 0, by negative JD's */
intJD++;
if (intJD == 0) {
/* -0.0 / -0.9 has zero integer part, so append "-" extra */
if (FrmResultAllocate(dateFmt, 1) != TCL_OK) { return TCL_ERROR; };
*dateFmt->output++ = '-';
}
/* and inverse seconds of day, -0(75) -> -0.25 as float */
fractJD = SECONDS_PER_DAY - fractJD;
}
/* 21 is max width of (negative) wide-int (rather smaller, but anyway a time fraction below) */
if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { return TCL_ERROR; };
dateFmt->output = _witoaw(dateFmt->output, intJD, '0', 1);
/* simplest cases .0 and .5 */
if (!fractJD || fractJD == (SECONDS_PER_DAY / 2)) {
/* point + 0 or 5 */
if (FrmResultAllocate(dateFmt, 1+1) != TCL_OK) { return TCL_ERROR; };
*dateFmt->output++ = '.';
*dateFmt->output++ = !fractJD ? '0' : '5';
*dateFmt->output = '\0';
return TCL_OK;
} else {
/* wrap the time fraction */
#define JDN_MAX_PRECISION 8
#define JDN_MAX_PRECBOUND 100000000 /* 10**JDN_MAX_PRECISION */
char *p;
/* to float (part after floating point, + 0.5 to round it up) */
fractJD = (int)(
(double)fractJD * JDN_MAX_PRECBOUND / SECONDS_PER_DAY + 0.5
);
/* point + integer (as time fraction after floating point) */
if (FrmResultAllocate(dateFmt, 1+JDN_MAX_PRECISION) != TCL_OK) { return TCL_ERROR; };
*dateFmt->output++ = '.';
p = _itoaw(dateFmt->output, fractJD, '0', JDN_MAX_PRECISION);
/* remove trailing zero's */
dateFmt->output++;
while (p > dateFmt->output && *(p-1) == '0') {p--;}
*p = '\0';
dateFmt->output = p;
}
return TCL_OK;
}
static int
ClockFmtToken_TimeZone_Proc(
ClockFmtScnCmdArgs *opts,
DateFormat *dateFmt,
ClockFormatToken *tok,
TCL_UNUSED(int *))
{
if (*tok->tokWord.start == 'z') {
int z = dateFmt->date.tzOffset;
char sign = '+';
if ( z < 0 ) {
z = -z;
sign = '-';
}
if (FrmResultAllocate(dateFmt, 7) != TCL_OK) { return TCL_ERROR; };
*dateFmt->output++ = sign;
dateFmt->output = _itoaw(dateFmt->output, z / 3600, '0', 2);
z %= 3600;
dateFmt->output = _itoaw(dateFmt->output, z / 60, '0', 2);
z %= 60;
if (z != 0) {
dateFmt->output = _itoaw(dateFmt->output, z, '0', 2);
}
} else {
Tcl_Obj * objPtr;
const char *s; Tcl_Size len;
/* convert seconds to local seconds to obtain tzName object */
if (ConvertUTCToLocal(opts->clientData, opts->interp,
&dateFmt->date, opts->timezoneObj,
GREGORIAN_CHANGE_DATE) != TCL_OK) {
return TCL_ERROR;
};
objPtr = dateFmt->date.tzName;
s = TclGetStringFromObj(objPtr, &len);
if (FrmResultAllocate(dateFmt, len) != TCL_OK) { return TCL_ERROR; };
memcpy(dateFmt->output, s, len + 1);
dateFmt->output += len;
}
return TCL_OK;
}
static int
ClockFmtToken_LocaleERA_Proc(
ClockFmtScnCmdArgs *opts,
DateFormat *dateFmt,
TCL_UNUSED(ClockFormatToken *),
TCL_UNUSED(int *))
{
Tcl_Obj *mcObj;
const char *s;
Tcl_Size len;
if (dateFmt->date.isBce) {
mcObj = ClockMCGet(opts, MCLIT_BCE);
} else {
mcObj = ClockMCGet(opts, MCLIT_CE);
}
if (mcObj == NULL) {
return TCL_ERROR;
}
s = TclGetStringFromObj(mcObj, &len);
if (FrmResultAllocate(dateFmt, len) != TCL_OK) { return TCL_ERROR; };
memcpy(dateFmt->output, s, len + 1);
dateFmt->output += len;
return TCL_OK;
}
static int
ClockFmtToken_LocaleERAYear_Proc(
ClockFmtScnCmdArgs *opts,
DateFormat *dateFmt,
ClockFormatToken *tok,
int *val)
{
Tcl_Size rowc;
Tcl_Obj **rowv;
if (dateFmt->localeEra == NULL) {
Tcl_Obj *mcObj = ClockMCGet(opts, MCLIT_LOCALE_ERAS);
if (mcObj == NULL) {
return TCL_ERROR;
}
if (TclListObjGetElements(opts->interp, mcObj, &rowc, &rowv) != TCL_OK) {
return TCL_ERROR;
}
if (rowc != 0) {
dateFmt->localeEra = LookupLastTransition(opts->interp,
dateFmt->date.localSeconds, rowc, rowv, NULL);
}
if (dateFmt->localeEra == NULL) {
dateFmt->localeEra = (Tcl_Obj*)1;
}
}
/* if no LOCALE_ERAS in catalog or era not found */
if (dateFmt->localeEra == (Tcl_Obj*)1) {
if (FrmResultAllocate(dateFmt, 11) != TCL_OK) { return TCL_ERROR; };
if (*tok->tokWord.start == 'C') { /* %EC */
*val = dateFmt->date.year / 100;
dateFmt->output = _itoaw(dateFmt->output,
*val, '0', 2);
} else { /* %Ey */
*val = dateFmt->date.year % 100;
dateFmt->output = _itoaw(dateFmt->output,
*val, '0', 2);
}
} else {
Tcl_Obj *objPtr;
const char *s;
Tcl_Size len;
if (*tok->tokWord.start == 'C') { /* %EC */
if (Tcl_ListObjIndex(opts->interp, dateFmt->localeEra, 1,
&objPtr) != TCL_OK ) {
return TCL_ERROR;
}
} else { /* %Ey */
if (Tcl_ListObjIndex(opts->interp, dateFmt->localeEra, 2,
&objPtr) != TCL_OK ) {
return TCL_ERROR;
}
if (Tcl_GetIntFromObj(opts->interp, objPtr, val) != TCL_OK) {
return TCL_ERROR;
}
*val = dateFmt->date.year - *val;
/* if year in locale numerals */
if (*val >= 0 && *val < 100) {
/* year as integer */
Tcl_Obj * mcObj = ClockMCGet(opts, MCLIT_LOCALE_NUMERALS);
if (mcObj == NULL) {
return TCL_ERROR;
}
if (Tcl_ListObjIndex(opts->interp, mcObj, *val, &objPtr) != TCL_OK) {
return TCL_ERROR;
}
} else {
/* year as integer */
if (FrmResultAllocate(dateFmt, 11) != TCL_OK) { return TCL_ERROR; };
dateFmt->output = _itoaw(dateFmt->output,
*val, '0', 2);
return TCL_OK;
}
}
s = TclGetStringFromObj(objPtr, &len);
if (FrmResultAllocate(dateFmt, len) != TCL_OK) { return TCL_ERROR; };
memcpy(dateFmt->output, s, len + 1);
dateFmt->output += len;
}
return TCL_OK;
}
static const char *FmtSTokenMapIndex =
"demNbByYCHMSIklpaAuwUVzgGjJsntQ";
static ClockFormatTokenMap FmtSTokenMap[] = {
/* %d */
{CTOKT_INT, "0", 2, 0, 0, 0, offsetof(DateFormat, date.dayOfMonth), NULL, NULL},
/* %e */
{CTOKT_INT, " ", 2, 0, 0, 0, offsetof(DateFormat, date.dayOfMonth), NULL, NULL},
/* %m */
{CTOKT_INT, "0", 2, 0, 0, 0, offsetof(DateFormat, date.month), NULL, NULL},
/* %N */
{CTOKT_INT, " ", 2, 0, 0, 0, offsetof(DateFormat, date.month), NULL, NULL},
/* %b %h */
{CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX | CLFMT_DECR, 0, 12, offsetof(DateFormat, date.month),
NULL, (void *)MCLIT_MONTHS_ABBREV},
/* %B */
{CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX | CLFMT_DECR, 0, 12, offsetof(DateFormat, date.month),
NULL, (void *)MCLIT_MONTHS_FULL},
/* %y */
{CTOKT_INT, "0", 2, 0, 0, 100, offsetof(DateFormat, date.year), NULL, NULL},
/* %Y */
{CTOKT_INT, "0", 4, 0, 0, 0, offsetof(DateFormat, date.year), NULL, NULL},
/* %C */
{CTOKT_INT, "0", 2, 0, 100, 0, offsetof(DateFormat, date.year), NULL, NULL},
/* %H */
{CTOKT_INT, "0", 2, 0, 3600, 24, offsetof(DateFormat, date.secondOfDay), NULL, NULL},
/* %M */
{CTOKT_INT, "0", 2, 0, 60, 60, offsetof(DateFormat, date.secondOfDay), NULL, NULL},
/* %S */
{CTOKT_INT, "0", 2, 0, 0, 60, offsetof(DateFormat, date.secondOfDay), NULL, NULL},
/* %I */
{CTOKT_INT, "0", 2, CLFMT_CALC, 0, 0, offsetof(DateFormat, date.secondOfDay),
ClockFmtToken_HourAMPM_Proc, NULL},
/* %k */
{CTOKT_INT, " ", 2, 0, 3600, 24, offsetof(DateFormat, date.secondOfDay), NULL, NULL},
/* %l */
{CTOKT_INT, " ", 2, CLFMT_CALC, 0, 0, offsetof(DateFormat, date.secondOfDay),
ClockFmtToken_HourAMPM_Proc, NULL},
/* %p %P */
{CTOKT_INT, NULL, 0, 0, 0, 0, offsetof(DateFormat, date.secondOfDay),
ClockFmtToken_AMPM_Proc, NULL},
/* %a */
{CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, offsetof(DateFormat, date.dayOfWeek),
NULL, (void *)MCLIT_DAYS_OF_WEEK_ABBREV},
/* %A */
{CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, offsetof(DateFormat, date.dayOfWeek),
NULL, (void *)MCLIT_DAYS_OF_WEEK_FULL},
/* %u */
{CTOKT_INT, " ", 1, 0, 0, 0, offsetof(DateFormat, date.dayOfWeek), NULL, NULL},
/* %w */
{CTOKT_INT, " ", 1, 0, 0, 7, offsetof(DateFormat, date.dayOfWeek), NULL, NULL},
/* %U %W */
{CTOKT_INT, "0", 2, CLFMT_CALC, 0, 0, offsetof(DateFormat, date.dayOfYear),
ClockFmtToken_WeekOfYear_Proc, NULL},
/* %V */
{CTOKT_INT, "0", 2, 0, 0, 0, offsetof(DateFormat, date.iso8601Week), NULL, NULL},
/* %z %Z */
{CFMTT_PROC, NULL, 0, 0, 0, 0, 0,
ClockFmtToken_TimeZone_Proc, NULL},
/* %g */
{CTOKT_INT, "0", 2, 0, 0, 100, offsetof(DateFormat, date.iso8601Year), NULL, NULL},
/* %G */
{CTOKT_INT, "0", 4, 0, 0, 0, offsetof(DateFormat, date.iso8601Year), NULL, NULL},
/* %j */
{CTOKT_INT, "0", 3, 0, 0, 0, offsetof(DateFormat, date.dayOfYear), NULL, NULL},
/* %J */
{CTOKT_WIDE, "0", 7, 0, 0, 0, offsetof(DateFormat, date.julianDay), NULL, NULL},
/* %s */
{CTOKT_WIDE, "0", 1, 0, 0, 0, offsetof(DateFormat, date.seconds), NULL, NULL},
/* %n */
{CTOKT_CHAR, "\n", 0, 0, 0, 0, 0, NULL, NULL},
/* %t */
{CTOKT_CHAR, "\t", 0, 0, 0, 0, 0, NULL, NULL},
/* %Q */
{CFMTT_PROC, NULL, 0, 0, 0, 0, 0,
ClockFmtToken_StarDate_Proc, NULL},
};
static const char *FmtSTokenMapAliasIndex[2] = {
"hPWZ",
"bpUz"
};
static const char *FmtETokenMapIndex =
"EJjys";
static ClockFormatTokenMap FmtETokenMap[] = {
/* %EE */
{CFMTT_PROC, NULL, 0, 0, 0, 0, 0,
ClockFmtToken_LocaleERA_Proc, NULL},
/* %EJ */
{CFMTT_PROC, NULL, 0, 0, 0, 0, 0, /* calendar JDN starts at midnight */
ClockFmtToken_JDN_Proc, NULL},
/* %Ej */
{CFMTT_PROC, NULL, 0, 0, 0, 0, (SECONDS_PER_DAY/2), /* astro JDN starts at noon */
ClockFmtToken_JDN_Proc, NULL},
/* %Ey %EC */
{CTOKT_INT, NULL, 0, 0, 0, 0, offsetof(DateFormat, date.year),
ClockFmtToken_LocaleERAYear_Proc, NULL},
/* %Es */
{CTOKT_WIDE, "0", 1, 0, 0, 0, offsetof(DateFormat, date.localSeconds), NULL, NULL},
};
static const char *FmtETokenMapAliasIndex[2] = {
"C",
"y"
};
static const char *FmtOTokenMapIndex =
"dmyHIMSuw";
static ClockFormatTokenMap FmtOTokenMap[] = {
/* %Od %Oe */
{CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.dayOfMonth),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %Om */
{CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.month),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %Oy */
{CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.year),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %OH %Ok */
{CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 3600, 24, offsetof(DateFormat, date.secondOfDay),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %OI %Ol */
{CTOKT_INT, NULL, 0, CLFMT_CALC | CLFMT_LOCALE_INDX, 0, 0, offsetof(DateFormat, date.secondOfDay),
ClockFmtToken_HourAMPM_Proc, (void *)MCLIT_LOCALE_NUMERALS},
/* %OM */
{CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 60, 60, offsetof(DateFormat, date.secondOfDay),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %OS */
{CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 60, offsetof(DateFormat, date.secondOfDay),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %Ou */
{CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.dayOfWeek),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %Ow */
{CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, offsetof(DateFormat, date.dayOfWeek),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
};
static const char *FmtOTokenMapAliasIndex[2] = {
"ekl",
"dHI"
};
static ClockFormatTokenMap FmtWordTokenMap = {
CTOKT_WORD, NULL, 0, 0, 0, 0, 0, NULL, NULL
};
/*
*----------------------------------------------------------------------
*/
ClockFmtScnStorage *
ClockGetOrParseFmtFormat(
Tcl_Interp *interp, /* Tcl interpreter */
Tcl_Obj *formatObj) /* Format container */
{
ClockFmtScnStorage *fss;
fss = Tcl_GetClockFrmScnFromObj(interp, formatObj);
if (fss == NULL) {
return NULL;
}
/* if format (fmtTok) already tokenized */
if (fss->fmtTok != NULL) {
return fss;
}
Tcl_MutexLock(&ClockFmtMutex);
/* first time formatting - tokenize format */
if (fss->fmtTok == NULL) {
ClockFormatToken *tok, *fmtTok;
unsigned int tokCnt;
const char *p, *e, *cp;
e = p = HashEntry4FmtScn(fss)->key.string;
e += strlen(p);
/* estimate token count by % char and format length */
fss->fmtTokC = EstimateTokenCount(p, e);
fmtTok = tok = (ClockFormatToken *)Tcl_Alloc(sizeof(*tok) * fss->fmtTokC);
memset(tok, 0, sizeof(*(tok)));
tokCnt = 1;
while (p < e) {
switch (*p) {
case '%':
if (1) {
ClockFormatTokenMap * fmtMap = FmtSTokenMap;
const char *mapIndex = FmtSTokenMapIndex,
**aliasIndex = FmtSTokenMapAliasIndex;
if (p+1 >= e) {
goto word_tok;
}
p++;
/* try to find modifier: */
switch (*p) {
case '%':
/* begin new word token - don't join with previous word token,
* because current mapping should be "...%%..." -> "...%..." */
tok->map = &FmtWordTokenMap;
tok->tokWord.start = p;
tok->tokWord.end = p+1;
AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); tokCnt++;
p++;
continue;
break;
case 'E':
fmtMap = FmtETokenMap,
mapIndex = FmtETokenMapIndex,
aliasIndex = FmtETokenMapAliasIndex;
p++;
break;
case 'O':
fmtMap = FmtOTokenMap,
mapIndex = FmtOTokenMapIndex,
aliasIndex = FmtOTokenMapAliasIndex;
p++;
break;
}
/* search direct index */
cp = strchr(mapIndex, *p);
if (!cp || *cp == '\0') {
/* search wrapper index (multiple chars for same token) */
cp = strchr(aliasIndex[0], *p);
if (!cp || *cp == '\0') {
p--; if (fmtMap != FmtSTokenMap) p--;
goto word_tok;
}
cp = strchr(mapIndex, aliasIndex[1][cp - aliasIndex[0]]);
if (!cp || *cp == '\0') { /* unexpected, but ... */
#ifdef DEBUG
Tcl_Panic("token \"%c\" has no map in wrapper resolver", *p);
#endif
p--; if (fmtMap != FmtSTokenMap) p--;
goto word_tok;
}
}
tok->map = &fmtMap[cp - mapIndex];
tok->tokWord.start = p;
/* next token */
AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); tokCnt++;
p++;
continue;
}
break;
default:
word_tok:
if (1) {
ClockFormatToken *wordTok = tok;
if (tok > fmtTok && (tok-1)->map == &FmtWordTokenMap) {
wordTok = tok-1;
}
if (wordTok == tok) {
wordTok->tokWord.start = p;
wordTok->map = &FmtWordTokenMap;
AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); tokCnt++;
}
p = Tcl_UtfNext(p);
wordTok->tokWord.end = p;
}
break;
}
}
/* correct count of real used tokens and free mem if desired
* (1 is acceptable delta to prevent memory fragmentation) */
if (fss->fmtTokC > tokCnt + (CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE / 2)) {
if ( (tok = (ClockFormatToken *)Tcl_Realloc(fmtTok, tokCnt * sizeof(*tok))) != NULL ) {
fmtTok = tok;
}
}
/* now we're ready - assign now to storage (note the threaded race condition) */
fss->fmtTok = fmtTok;
fss->fmtTokC = tokCnt;
}
done:
Tcl_MutexUnlock(&ClockFmtMutex);
return fss;
}
/*
*----------------------------------------------------------------------
*/
int
ClockFormat(
DateFormat *dateFmt, /* Date fields used for parsing & converting */
ClockFmtScnCmdArgs *opts) /* Command options */
{
ClockFmtScnStorage *fss;
ClockFormatToken *tok;
ClockFormatTokenMap *map;
char resMem[MIN_FMT_RESULT_BLOCK_ALLOC];
/* get localized format */
if (ClockLocalizeFormat(opts) == NULL) {
return TCL_ERROR;
}
if ( !(fss = ClockGetOrParseFmtFormat(opts->interp, opts->formatObj))
|| !(tok = fss->fmtTok)
) {
return TCL_ERROR;
}
/* result container object */
dateFmt->resMem = resMem;
dateFmt->resEnd = dateFmt->resMem + sizeof(resMem);
if (fss->fmtMinAlloc > sizeof(resMem)) {
dateFmt->resMem = (char *)Tcl_Alloc(fss->fmtMinAlloc);
dateFmt->resEnd = dateFmt->resMem + fss->fmtMinAlloc;
if (dateFmt->resMem == NULL) {
return TCL_ERROR;
}
}
dateFmt->output = dateFmt->resMem;
*dateFmt->output = '\0';
/* do format each token */
for (; tok->map != NULL; tok++) {
map = tok->map;
switch (map->type)
{
case CTOKT_INT:
if (1) {
int val = (int)*(int *)(((char *)dateFmt) + map->offs);
if (map->fmtproc == NULL) {
if (map->flags & CLFMT_DECR) {
val--;
}
if (map->flags & CLFMT_INCR) {
val++;
}
if (map->divider) {
val /= map->divider;
}
if (map->divmod) {
val %= map->divmod;
}
} else {
if (map->fmtproc(opts, dateFmt, tok, &val) != TCL_OK) {
goto done;
}
/* if not calculate only (output inside fmtproc) */
if (!(map->flags & CLFMT_CALC)) {
continue;
}
}
if (!(map->flags & CLFMT_LOCALE_INDX)) {
if (FrmResultAllocate(dateFmt, 11) != TCL_OK) { goto error; };
if (map->width) {
dateFmt->output = _itoaw(dateFmt->output, val, *map->tostr, map->width);
} else {
dateFmt->output += sprintf(dateFmt->output, map->tostr, val);
}
} else {
const char *s;
Tcl_Obj * mcObj = ClockMCGet(opts, PTR2INT(map->data) /* mcKey */);
if (mcObj == NULL) {
goto error;
}
if ( Tcl_ListObjIndex(opts->interp, mcObj, val, &mcObj) != TCL_OK
|| mcObj == NULL
) {
goto error;
}
s = TclGetString(mcObj);
if (FrmResultAllocate(dateFmt, mcObj->length) != TCL_OK) { goto error; };
memcpy(dateFmt->output, s, mcObj->length + 1);
dateFmt->output += mcObj->length;
}
}
break;
case CTOKT_WIDE:
if (1) {
Tcl_WideInt val = *(Tcl_WideInt *)(((char *)dateFmt) + map->offs);
if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { goto error; };
if (map->width) {
dateFmt->output = _witoaw(dateFmt->output, val, *map->tostr, map->width);
} else {
dateFmt->output += sprintf(dateFmt->output, map->tostr, val);
}
}
break;
case CTOKT_CHAR:
if (FrmResultAllocate(dateFmt, 1) != TCL_OK) { goto error; };
*dateFmt->output++ = *map->tostr;
break;
case CFMTT_PROC:
if (map->fmtproc(opts, dateFmt, tok, NULL) != TCL_OK) {
goto error;
};
break;
case CTOKT_WORD:
if (1) {
Tcl_Size len = tok->tokWord.end - tok->tokWord.start;
if (FrmResultAllocate(dateFmt, len) != TCL_OK) { goto error; };
if (len == 1) {
*dateFmt->output++ = *tok->tokWord.start;
} else {
memcpy(dateFmt->output, tok->tokWord.start, len);
dateFmt->output += len;
}
}
break;
}
}
goto done;
error:
if (dateFmt->resMem != resMem) {
Tcl_Free(dateFmt->resMem);
}
dateFmt->resMem = NULL;
done:
if (dateFmt->resMem) {
size_t size;
Tcl_Obj *result;
TclNewObj(result);
result->length = dateFmt->output - dateFmt->resMem;
size = result->length+1;
if (dateFmt->resMem == resMem) {
result->bytes = (char *)Tcl_Alloc(size);
if (result->bytes == NULL) {
return TCL_ERROR;
}
memcpy(result->bytes, dateFmt->resMem, size);
} else if ((dateFmt->resEnd - dateFmt->resMem) / size > MAX_FMT_RESULT_THRESHOLD) {
result->bytes = (char *)Tcl_Realloc(dateFmt->resMem, size);
if (result->bytes == NULL) {
result->bytes = dateFmt->resMem;
}
} else {
result->bytes = dateFmt->resMem;
}
/* save last used buffer length */
if ( dateFmt->resMem != resMem
&& fss->fmtMinAlloc < size + MIN_FMT_RESULT_BLOCK_DELTA
) {
fss->fmtMinAlloc = size + MIN_FMT_RESULT_BLOCK_DELTA;
}
result->bytes[result->length] = '\0';
Tcl_SetObjResult(opts->interp, result);
return TCL_OK;
}
return TCL_ERROR;
}
void
ClockFrmScnClearCaches(void)
{
Tcl_MutexLock(&ClockFmtMutex);
/* clear caches ... */
Tcl_MutexUnlock(&ClockFmtMutex);
}
static void
ClockFrmScnFinalize(
TCL_UNUSED(void *))
{
Tcl_MutexLock(&ClockFmtMutex);
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
/* clear GC */
ClockFmtScnStorage_GC.stackPtr = NULL;
ClockFmtScnStorage_GC.stackBound = NULL;
ClockFmtScnStorage_GC.count = 0;
#endif
if (initialized) {
Tcl_DeleteHashTable(&FmtScnHashTable);
initialized = 0;
}
Tcl_MutexUnlock(&ClockFmtMutex);
Tcl_MutexFinalize(&ClockFmtMutex);
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
|
Changes to generic/tclCmdIL.c.
| ︙ | ︙ | |||
2201 2202 2203 2204 2205 2206 2207 |
}
return TCL_OK;
}
joinObjPtr = (objc == 2) ? Tcl_NewStringObj(" ", 1) : objv[2];
Tcl_IncrRefCount(joinObjPtr);
| | | 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 |
}
return TCL_OK;
}
joinObjPtr = (objc == 2) ? Tcl_NewStringObj(" ", 1) : objv[2];
Tcl_IncrRefCount(joinObjPtr);
(void)TclGetStringFromObj(joinObjPtr, &length);
if (length == 0) {
resObjPtr = TclStringCat(interp, listLen, elemPtrs, 0);
} else {
Tcl_Size i;
TclNewObj(resObjPtr);
for (i = 0; i < listLen; i++) {
|
| ︙ | ︙ | |||
5429 5430 5431 5432 5433 5434 5435 |
/*
* Convert character to Unicode for comparison purposes. If either
* string is at the terminating null, do a byte-wise comparison and
* bail out immediately.
*/
if ((*left != '\0') && (*right != '\0')) {
| | | | 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 |
/*
* Convert character to Unicode for comparison purposes. If either
* string is at the terminating null, do a byte-wise comparison and
* bail out immediately.
*/
if ((*left != '\0') && (*right != '\0')) {
left += TclUtfToUniChar(left, &uniLeft);
right += TclUtfToUniChar(right, &uniRight);
/*
* Convert both chars to lower for the comparison, because
* dictionary sorts are case-insensitive. Covert to lower, not
* upper, so chars between Z and a will sort before A (where most
* other interesting punctuations occur).
*/
|
| ︙ | ︙ |
Changes to generic/tclCmdMZ.c.
| ︙ | ︙ | |||
1216 1217 1218 1219 1220 1221 1222 |
* is a *major* win when splitting on a long string (especially in the
* megabyte range!) - DKF
*/
Tcl_InitHashTable(&charReuseTable, TCL_ONE_WORD_KEYS);
for ( ; stringPtr < end; stringPtr += len) {
| | | 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 |
* is a *major* win when splitting on a long string (especially in the
* megabyte range!) - DKF
*/
Tcl_InitHashTable(&charReuseTable, TCL_ONE_WORD_KEYS);
for ( ; stringPtr < end; stringPtr += len) {
len = TclUtfToUniChar(stringPtr, &ch);
hPtr = Tcl_CreateHashEntry(&charReuseTable, INT2PTR(ch), &isNew);
if (isNew) {
TclNewStringObj(objPtr, stringPtr, len);
/*
* Don't need to fiddle with refcount...
*/
|
| ︙ | ︙ | |||
1262 1263 1264 1265 1266 1267 1268 |
* Normal case: split on any of a given set of characters. Discard
* instances of the split characters.
*/
splitEnd = splitChars + splitCharLen;
for (element = stringPtr; stringPtr < end; stringPtr += len) {
| | | | 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 |
* Normal case: split on any of a given set of characters. Discard
* instances of the split characters.
*/
splitEnd = splitChars + splitCharLen;
for (element = stringPtr; stringPtr < end; stringPtr += len) {
len = TclUtfToUniChar(stringPtr, &ch);
for (p = splitChars; p < splitEnd; p += splitLen) {
splitLen = TclUtfToUniChar(p, &splitChar);
if (ch == splitChar) {
TclNewStringObj(objPtr, element, stringPtr - element);
Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
element = stringPtr + len;
break;
}
}
|
| ︙ | ︙ | |||
1887 1888 1889 1890 1891 1892 1893 |
}
goto str_is_done;
}
end = string1 + length1;
for (; string1 < end; string1 += length2, failat++) {
int ucs4;
| | | 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 |
}
goto str_is_done;
}
end = string1 + length1;
for (; string1 < end; string1 += length2, failat++) {
int ucs4;
length2 = TclUtfToUniChar(string1, &ucs4);
if (!chcomp(ucs4)) {
result = 0;
break;
}
}
}
|
| ︙ | ︙ |
Changes to generic/tclCompCmds.c.
| ︙ | ︙ | |||
892 893 894 895 896 897 898 | Tcl_Obj **objs; const char *bytes; Tcl_Size len, slen; TclListObjGetElements(NULL, listObj, &len, &objs); objPtr = Tcl_ConcatObj(len, objs); Tcl_DecrRefCount(listObj); | | | 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 |
Tcl_Obj **objs;
const char *bytes;
Tcl_Size len, slen;
TclListObjGetElements(NULL, listObj, &len, &objs);
objPtr = Tcl_ConcatObj(len, objs);
Tcl_DecrRefCount(listObj);
bytes = TclGetStringFromObj(objPtr, &slen);
PushLiteral(envPtr, bytes, slen);
Tcl_DecrRefCount(objPtr);
return TCL_OK;
}
/*
* General case: runtime concat.
|
| ︙ | ︙ | |||
1407 1408 1409 1410 1411 1412 1413 |
Tcl_DecrRefCount(valueObj);
}
/*
* We did! Excellent. The "verifyDict" is to do type forcing.
*/
| | | 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 |
Tcl_DecrRefCount(valueObj);
}
/*
* We did! Excellent. The "verifyDict" is to do type forcing.
*/
bytes = TclGetStringFromObj(dictObj, &len);
PushLiteral(envPtr, bytes, len);
TclEmitOpcode( INST_DUP, envPtr);
TclEmitOpcode( INST_DICT_VERIFY, envPtr);
Tcl_DecrRefCount(dictObj);
return TCL_OK;
/*
|
| ︙ | ︙ | |||
2849 2850 2851 2852 2853 2854 2855 | Tcl_Obj *varNameObj; const char *bytes; int varIndex; Tcl_Size length; Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj); | | | 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 |
Tcl_Obj *varNameObj;
const char *bytes;
int varIndex;
Tcl_Size length;
Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj);
bytes = TclGetStringFromObj(varNameObj, &length);
varIndex = LocalScalar(bytes, length, envPtr);
if (varIndex < 0) {
code = TCL_ERROR;
goto done;
}
varListPtr->varIndexes[j] = varIndex;
}
|
| ︙ | ︙ | |||
3285 3286 3287 3288 3289 3290 3291 |
}
/*
* Not an error, always a constant result, so just push the result as a
* literal. Job done.
*/
| | | 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 |
}
/*
* Not an error, always a constant result, so just push the result as a
* literal. Job done.
*/
bytes = TclGetStringFromObj(tmpObj, &len);
PushLiteral(envPtr, bytes, len);
Tcl_DecrRefCount(tmpObj);
return TCL_OK;
checkForStringConcatCase:
/*
* See if we can generate a sequence of things to concatenate. This
|
| ︙ | ︙ | |||
3356 3357 3358 3359 3360 3361 3362 |
* being built. */
for (bytes = start ; *bytes ; bytes++) {
if (*bytes == '%') {
Tcl_AppendToObj(tmpObj, start, bytes - start);
if (*++bytes == '%') {
Tcl_AppendToObj(tmpObj, "%", 1);
} else {
| | | 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 |
* being built. */
for (bytes = start ; *bytes ; bytes++) {
if (*bytes == '%') {
Tcl_AppendToObj(tmpObj, start, bytes - start);
if (*++bytes == '%') {
Tcl_AppendToObj(tmpObj, "%", 1);
} else {
const char *b = TclGetStringFromObj(tmpObj, &len);
/*
* If there is a non-empty literal from the format string,
* push it and reset.
*/
if (len > 0) {
|
| ︙ | ︙ | |||
3390 3391 3392 3393 3394 3395 3396 |
}
/*
* Handle the case of a trailing literal.
*/
Tcl_AppendToObj(tmpObj, start, bytes - start);
| | | 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 |
}
/*
* Handle the case of a trailing literal.
*/
Tcl_AppendToObj(tmpObj, start, bytes - start);
bytes = TclGetStringFromObj(tmpObj, &len);
if (len > 0) {
PushLiteral(envPtr, bytes, len);
i++;
}
Tcl_DecrRefCount(tmpObj);
Tcl_DecrRefCount(formatObj);
|
| ︙ | ︙ |
Changes to generic/tclCompExpr.c.
| ︙ | ︙ | |||
2145 2146 2147 2148 2149 2150 2151 |
* Might be inspired by reserved identifier rules in C, which of course
* have no direct relevance here.
*/
if (!TclIsBareword(*start) || *start == '_') {
Tcl_Size scanned;
if (Tcl_UtfCharComplete(start, numBytes)) {
| | | | 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 |
* Might be inspired by reserved identifier rules in C, which of course
* have no direct relevance here.
*/
if (!TclIsBareword(*start) || *start == '_') {
Tcl_Size scanned;
if (Tcl_UtfCharComplete(start, numBytes)) {
scanned = TclUtfToUniChar(start, &ch);
} else {
char utfBytes[8];
memcpy(utfBytes, start, numBytes);
utfBytes[numBytes] = '\0';
scanned = TclUtfToUniChar(utfBytes, &ch);
}
*lexemePtr = INVALID;
Tcl_DecrRefCount(literal);
return scanned;
}
end = start;
while (numBytes && TclIsBareword(*end)) {
|
| ︙ | ︙ | |||
2348 2349 2350 2351 2352 2353 2354 |
case FUNCTION: {
Tcl_DString cmdName;
const char *p;
Tcl_Size length;
Tcl_DStringInit(&cmdName);
TclDStringAppendLiteral(&cmdName, "tcl::mathfunc::");
| | | 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 |
case FUNCTION: {
Tcl_DString cmdName;
const char *p;
Tcl_Size length;
Tcl_DStringInit(&cmdName);
TclDStringAppendLiteral(&cmdName, "tcl::mathfunc::");
p = TclGetStringFromObj(*funcObjv, &length);
funcObjv++;
Tcl_DStringAppend(&cmdName, p, length);
TclEmitPush(TclRegisterLiteral(envPtr,
Tcl_DStringValue(&cmdName),
Tcl_DStringLength(&cmdName), LITERAL_CMD_NAME), envPtr);
Tcl_DStringFree(&cmdName);
|
| ︙ | ︙ | |||
2504 2505 2506 2507 2508 2509 2510 |
break;
case OT_LITERAL: {
Tcl_Obj *const *litObjv = *litObjvPtr;
Tcl_Obj *literal = *litObjv;
if (optimize) {
Tcl_Size length;
| | | 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 |
break;
case OT_LITERAL: {
Tcl_Obj *const *litObjv = *litObjvPtr;
Tcl_Obj *literal = *litObjv;
if (optimize) {
Tcl_Size length;
const char *bytes = TclGetStringFromObj(literal, &length);
int idx = TclRegisterLiteral(envPtr, bytes, length, 0);
Tcl_Obj *objPtr = TclFetchLiteral(envPtr, idx);
if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) {
/*
* Would like to do this:
*
|
| ︙ | ︙ | |||
2564 2565 2566 2567 2568 2569 2570 |
* already, then use it to share via the literal table.
*/
if (TclHasStringRep(objPtr)) {
Tcl_Obj *tableValue;
Tcl_Size numBytes;
const char *bytes
| | | 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 |
* already, then use it to share via the literal table.
*/
if (TclHasStringRep(objPtr)) {
Tcl_Obj *tableValue;
Tcl_Size numBytes;
const char *bytes
= TclGetStringFromObj(objPtr, &numBytes);
idx = TclRegisterLiteral(envPtr, bytes, numBytes, 0);
tableValue = TclFetchLiteral(envPtr, idx);
if ((tableValue->typePtr == NULL) &&
(objPtr->typePtr != NULL)) {
/*
* Same internalrep surgery as for OT_LITERAL.
|
| ︙ | ︙ |
Changes to generic/tclDate.c.
| ︙ | ︙ | |||
74 75 76 77 78 79 80 | /* * tclDate.c -- * * This file is generated from a yacc grammar defined in the file * tclGetDate.y. It should not be edited directly. * | | | > < < < | | < < > < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < > > > > > > > | | | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
/*
* tclDate.c --
*
* This file is generated from a yacc grammar defined in the file
* tclGetDate.y. It should not be edited directly.
*
* Copyright © 1992-1995 Karl Lehenbauer & Mark Diekhans.
* Copyright © 1995-1997 Sun Microsystems, Inc.
* Copyright © 2015 Sergey G. Brester aka sebres.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
#include "tclInt.h"
/*
* Bison generates several labels that happen to be unused. MS Visual C++
* doesn't like that, and complains. Tell it to shut up.
*/
#ifdef _MSC_VER
#pragma warning( disable : 4102 )
#endif /* _MSC_VER */
#if 0
#define YYDEBUG 1
#endif
/*
* yyparse will accept a 'struct DateInfo' as its parameter; that's where the
* parsed fields will be returned.
*/
#include "tclDate.h"
#define YYMALLOC Tcl_Alloc
#define YYFREE(x) (Tcl_Free((void*) (x)))
#define EPOCH 1970
#define START_OF_TIME 1902
#define END_OF_TIME 2037
/*
* The offset of tm_year of struct tm returned by localtime, gmtime, etc.
* Posix requires 1900.
*/
#define TM_YEAR_BASE 1900
#define HOUR(x) ((60 * (int)(x)))
#define IsLeapYear(x) (((x) % 4 == 0) && ((x) % 100 != 0 || (x) % 400 == 0))
#define yyIncrFlags(f) \
do { \
info->errFlags |= (info->flags & (f)); \
if (info->errFlags) { YYABORT; } \
info->flags |= (f); \
} while (0);
/*
* An entry in the lexical lookup table.
*/
typedef struct {
const char *name;
int type;
int value;
} TABLE;
/*
* Daylight-savings mode: on, off, or not yet known.
*/
typedef enum _DSTMODE {
|
| ︙ | ︙ | |||
255 256 257 258 259 260 261 |
tDAYZONE = 260, /* tDAYZONE */
tID = 261, /* tID */
tMERIDIAN = 262, /* tMERIDIAN */
tMONTH = 263, /* tMONTH */
tMONTH_UNIT = 264, /* tMONTH_UNIT */
tSTARDATE = 265, /* tSTARDATE */
tSEC_UNIT = 266, /* tSEC_UNIT */
| | | | > | | | > > | | > | | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
tDAYZONE = 260, /* tDAYZONE */
tID = 261, /* tID */
tMERIDIAN = 262, /* tMERIDIAN */
tMONTH = 263, /* tMONTH */
tMONTH_UNIT = 264, /* tMONTH_UNIT */
tSTARDATE = 265, /* tSTARDATE */
tSEC_UNIT = 266, /* tSEC_UNIT */
tUNUMBER = 267, /* tUNUMBER */
tZONE = 268, /* tZONE */
tZONEwO4 = 269, /* tZONEwO4 */
tZONEwO2 = 270, /* tZONEwO2 */
tEPOCH = 271, /* tEPOCH */
tDST = 272, /* tDST */
tISOBAS8 = 273, /* tISOBAS8 */
tISOBAS6 = 274, /* tISOBAS6 */
tISOBASL = 275, /* tISOBASL */
tDAY_UNIT = 276, /* tDAY_UNIT */
tNEXT = 277, /* tNEXT */
SP = 278 /* SP */
};
typedef enum yytokentype yytoken_kind_t;
#endif
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
Tcl_WideInt Number;
enum _MERIDIAN Meridian;
};
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
|
| ︙ | ︙ | |||
319 320 321 322 323 324 325 | YYSYMBOL_tDAYZONE = 5, /* tDAYZONE */ YYSYMBOL_tID = 6, /* tID */ YYSYMBOL_tMERIDIAN = 7, /* tMERIDIAN */ YYSYMBOL_tMONTH = 8, /* tMONTH */ YYSYMBOL_tMONTH_UNIT = 9, /* tMONTH_UNIT */ YYSYMBOL_tSTARDATE = 10, /* tSTARDATE */ YYSYMBOL_tSEC_UNIT = 11, /* tSEC_UNIT */ | | | | > | | | > > | | > | | | | > | | | | | > | | > | > | | > > > | | | | | | | > | | | < < | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | YYSYMBOL_tDAYZONE = 5, /* tDAYZONE */ YYSYMBOL_tID = 6, /* tID */ YYSYMBOL_tMERIDIAN = 7, /* tMERIDIAN */ YYSYMBOL_tMONTH = 8, /* tMONTH */ YYSYMBOL_tMONTH_UNIT = 9, /* tMONTH_UNIT */ YYSYMBOL_tSTARDATE = 10, /* tSTARDATE */ YYSYMBOL_tSEC_UNIT = 11, /* tSEC_UNIT */ YYSYMBOL_tUNUMBER = 12, /* tUNUMBER */ YYSYMBOL_tZONE = 13, /* tZONE */ YYSYMBOL_tZONEwO4 = 14, /* tZONEwO4 */ YYSYMBOL_tZONEwO2 = 15, /* tZONEwO2 */ YYSYMBOL_tEPOCH = 16, /* tEPOCH */ YYSYMBOL_tDST = 17, /* tDST */ YYSYMBOL_tISOBAS8 = 18, /* tISOBAS8 */ YYSYMBOL_tISOBAS6 = 19, /* tISOBAS6 */ YYSYMBOL_tISOBASL = 20, /* tISOBASL */ YYSYMBOL_tDAY_UNIT = 21, /* tDAY_UNIT */ YYSYMBOL_tNEXT = 22, /* tNEXT */ YYSYMBOL_SP = 23, /* SP */ YYSYMBOL_24_ = 24, /* ':' */ YYSYMBOL_25_ = 25, /* ',' */ YYSYMBOL_26_ = 26, /* '-' */ YYSYMBOL_27_ = 27, /* '/' */ YYSYMBOL_28_T_ = 28, /* 'T' */ YYSYMBOL_29_ = 29, /* '.' */ YYSYMBOL_30_ = 30, /* '+' */ YYSYMBOL_YYACCEPT = 31, /* $accept */ YYSYMBOL_spec = 32, /* spec */ YYSYMBOL_item = 33, /* item */ YYSYMBOL_iextime = 34, /* iextime */ YYSYMBOL_time = 35, /* time */ YYSYMBOL_zone = 36, /* zone */ YYSYMBOL_comma = 37, /* comma */ YYSYMBOL_day = 38, /* day */ YYSYMBOL_iexdate = 39, /* iexdate */ YYSYMBOL_date = 40, /* date */ YYSYMBOL_ordMonth = 41, /* ordMonth */ YYSYMBOL_isosep = 42, /* isosep */ YYSYMBOL_isodate = 43, /* isodate */ YYSYMBOL_isotime = 44, /* isotime */ YYSYMBOL_iso = 45, /* iso */ YYSYMBOL_trek = 46, /* trek */ YYSYMBOL_relspec = 47, /* relspec */ YYSYMBOL_relunits = 48, /* relunits */ YYSYMBOL_sign = 49, /* sign */ YYSYMBOL_unit = 50, /* unit */ YYSYMBOL_INTNUM = 51, /* INTNUM */ YYSYMBOL_numitem = 52, /* numitem */ YYSYMBOL_o_merid = 53 /* o_merid */ }; typedef enum yysymbol_kind_t yysymbol_kind_t; /* Second part of user prologue. */ /* * Prototypes of internal functions. */ static int LookupWord(YYSTYPE* yylvalPtr, char *buff); static void TclDateerror(YYLTYPE* location, DateInfo* info, const char *s); static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location, DateInfo* info); MODULE_SCOPE int yyparse(DateInfo*); #ifdef short # undef short |
| ︙ | ︙ | |||
696 697 698 699 700 701 702 | # endif # endif #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ | | | | | | | | | | | > | > | | | | | | | | > | | | | | | | | | | | | > > | | | > | | | | | | | > | > | | > | > | | | | | < > | | | > | | > | | | < | | | | | | > | | | | | > | < < | | | | > > > > | > | | | | > | 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 |
# endif
# endif
#endif /* !YYCOPY_NEEDED */
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
#define YYLAST 98
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 31
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 23
/* YYNRULES -- Number of rules. */
#define YYNRULES 72
/* YYNSTATES -- Number of states. */
#define YYNSTATES 103
/* YYMAXUTOK -- Last valid token kind. */
#define YYMAXUTOK 278
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */
#define YYTRANSLATE(YYX) \
(0 <= (YYX) && (YYX) <= YYMAXUTOK \
? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \
: YYSYMBOL_YYUNDEF)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
as returned by yylex. */
static const yytype_int8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 30, 25, 26, 29, 27, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 24, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 28, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23
};
#if YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_int16 yyrline[] =
{
0, 171, 171, 172, 176, 179, 182, 185, 188, 191,
194, 197, 201, 204, 209, 215, 221, 226, 230, 234,
238, 242, 246, 252, 253, 256, 260, 264, 268, 272,
276, 282, 288, 292, 297, 298, 303, 307, 312, 316,
321, 328, 332, 338, 338, 340, 345, 350, 352, 357,
359, 360, 368, 379, 393, 398, 401, 404, 407, 410,
413, 416, 421, 424, 429, 433, 437, 443, 446, 449,
454, 472, 475
};
#endif
/** Accessing symbol of state STATE. */
#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State])
#if YYDEBUG || 0
/* The user-facing name of the symbol whose (internal) number is
YYSYMBOL. No bounds checking. */
static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED;
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
"\"end of file\"", "error", "\"invalid token\"", "tAGO", "tDAY",
"tDAYZONE", "tID", "tMERIDIAN", "tMONTH", "tMONTH_UNIT", "tSTARDATE",
"tSEC_UNIT", "tUNUMBER", "tZONE", "tZONEwO4", "tZONEwO2", "tEPOCH",
"tDST", "tISOBAS8", "tISOBAS6", "tISOBASL", "tDAY_UNIT", "tNEXT", "SP",
"':'", "','", "'-'", "'/'", "'T'", "'.'", "'+'", "$accept", "spec",
"item", "iextime", "time", "zone", "comma", "day", "iexdate", "date",
"ordMonth", "isosep", "isodate", "isotime", "iso", "trek", "relspec",
"relunits", "sign", "unit", "INTNUM", "numitem", "o_merid", YY_NULLPTR
};
static const char *
yysymbol_name (yysymbol_kind_t yysymbol)
{
return yytname[yysymbol];
}
#endif
#define YYPACT_NINF (-21)
#define yypact_value_is_default(Yyn) \
((Yyn) == YYPACT_NINF)
#define YYTABLE_NINF (-68)
#define yytable_value_is_error(Yyn) \
0
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
static const yytype_int8 yypact[] =
{
-21, 11, -21, -20, -21, 5, -21, -9, -21, 46,
17, 9, 9, -21, -21, -21, 24, -21, 57, -21,
-21, -21, 33, -21, -21, -21, -21, -21, -21, -15,
-21, -21, -21, 45, 26, -21, -7, -21, 51, -21,
-20, -21, -21, -21, 48, -21, -21, 67, 68, 52,
69, -21, -9, -9, -21, -21, -21, -21, 74, -21,
-7, -21, -21, -21, -21, 44, -21, 79, 40, -7,
-21, -21, 72, 73, -21, 62, 61, 63, 64, -21,
-21, -21, -21, 66, -21, -21, -21, -21, 84, -7,
-21, -21, -21, 80, 81, 82, 83, -21, -21, -21,
-21, -21, -21
};
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
Performed when YYTABLE does not specify something else to do. Zero
means the default is an error. */
static const yytype_int8 yydefact[] =
{
2, 0, 1, 25, 19, 0, 66, 0, 64, 70,
18, 0, 0, 39, 45, 46, 0, 65, 0, 62,
63, 3, 71, 4, 5, 8, 47, 6, 7, 34,
10, 11, 9, 55, 0, 61, 0, 12, 23, 26,
36, 67, 69, 68, 0, 27, 15, 38, 0, 0,
0, 17, 0, 0, 52, 51, 30, 41, 67, 59,
0, 72, 16, 44, 43, 0, 54, 67, 0, 22,
58, 24, 0, 0, 40, 14, 0, 0, 32, 20,
21, 42, 60, 0, 48, 49, 50, 29, 67, 0,
57, 37, 53, 0, 0, 0, 0, 28, 56, 13,
35, 31, 33
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
-21, -21, -21, 31, -21, -21, 58, -21, -21, -21,
-21, -21, -21, -21, -21, -21, -21, -21, -5, -18,
-6, -21, -21
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
0, 1, 21, 22, 23, 24, 39, 25, 26, 27,
28, 65, 29, 86, 30, 31, 32, 33, 34, 35,
36, 37, 62
};
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule whose
number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_int8 yytable[] =
{
59, 44, 6, 41, 8, 38, 52, 53, 63, 42,
43, 2, 60, 64, 17, 3, 4, 40, 70, 5,
6, 7, 8, 9, 10, 11, 12, 13, 69, 14,
15, 16, 17, 18, 51, 19, 54, 19, 67, 20,
61, 20, 82, 55, 42, 43, 79, 80, 66, 68,
45, 90, 88, 46, 47, -67, 83, -67, 42, 43,
76, 56, 89, 84, 77, 57, 6, -67, 8, 58,
48, 98, 49, 50, 71, 42, 43, 73, 17, 74,
75, 78, 81, 87, 91, 92, 93, 94, 97, 95,
48, 96, 99, 100, 101, 102, 85, 0, 72
};
static const yytype_int8 yycheck[] =
{
18, 7, 9, 12, 11, 25, 11, 12, 23, 18,
19, 0, 18, 28, 21, 4, 5, 12, 36, 8,
9, 10, 11, 12, 13, 14, 15, 16, 34, 18,
19, 20, 21, 22, 17, 26, 12, 26, 12, 30,
7, 30, 60, 19, 18, 19, 52, 53, 3, 23,
4, 69, 12, 7, 8, 9, 12, 11, 18, 19,
8, 4, 68, 19, 12, 8, 9, 21, 11, 12,
24, 89, 26, 27, 23, 18, 19, 29, 21, 12,
12, 12, 8, 4, 12, 12, 24, 26, 4, 26,
24, 27, 12, 12, 12, 12, 65, -1, 40
};
/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
state STATE-NUM. */
static const yytype_int8 yystos[] =
{
0, 32, 0, 4, 5, 8, 9, 10, 11, 12,
13, 14, 15, 16, 18, 19, 20, 21, 22, 26,
30, 33, 34, 35, 36, 38, 39, 40, 41, 43,
45, 46, 47, 48, 49, 50, 51, 52, 25, 37,
12, 12, 18, 19, 51, 4, 7, 8, 24, 26,
27, 17, 49, 49, 12, 19, 4, 8, 12, 50,
51, 7, 53, 23, 28, 42, 3, 12, 23, 51,
50, 23, 37, 29, 12, 12, 8, 12, 12, 51,
51, 8, 50, 12, 19, 34, 44, 4, 12, 51,
50, 12, 12, 24, 26, 26, 27, 4, 50, 12,
12, 12, 12
};
/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */
static const yytype_int8 yyr1[] =
{
0, 31, 32, 32, 33, 33, 33, 33, 33, 33,
33, 33, 33, 34, 34, 35, 35, 36, 36, 36,
36, 36, 36, 37, 37, 38, 38, 38, 38, 38,
38, 39, 40, 40, 40, 40, 40, 40, 40, 40,
40, 41, 41, 42, 42, 43, 43, 43, 44, 44,
45, 45, 45, 46, 47, 47, 48, 48, 48, 48,
48, 48, 49, 49, 50, 50, 50, 51, 51, 51,
52, 53, 53
};
/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */
static const yytype_int8 yyr2[] =
{
0, 2, 0, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 5, 3, 2, 2, 2, 1, 1,
3, 3, 2, 1, 2, 1, 2, 2, 4, 3,
2, 5, 3, 5, 1, 5, 2, 4, 2, 1,
3, 2, 3, 1, 1, 1, 1, 1, 1, 1,
3, 2, 2, 4, 2, 1, 4, 3, 2, 2,
3, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 1
};
enum { YYENOMEM = -2 };
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
|
| ︙ | ︙ | |||
1496 1497 1498 1499 1500 1501 1502 |
YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
yyerror_range[1] = yyloc;
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
case 4: /* item: time */
{
| | | | | | | | < > > > > | > > | > > > > | > > > > > | < < < < < < < < | < | < < < | < | < | > > > > > > | > > > > > > | > > | | | | | | | > > > > > > > | | | > > > > > > > | > | | < < < < < < < < | < < < < < < < < | | | | | | | | | | | | | | < | | | > > | > > | > | | | < < < < | < < < < < < < < < < | < < > > > > > > > > > > > > | | | | > > > > > > | | | | | | | | | | | | | | > > > | > > > > > > > > > > > > > > > | | | | 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 |
YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
yyerror_range[1] = yyloc;
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
case 4: /* item: time */
{
yyIncrFlags(CLF_TIME);
}
break;
case 5: /* item: zone */
{
yyIncrFlags(CLF_ZONE);
}
break;
case 6: /* item: date */
{
yyIncrFlags(CLF_HAVEDATE);
}
break;
case 7: /* item: ordMonth */
{
yyIncrFlags(CLF_ORDINALMONTH);
}
break;
case 8: /* item: day */
{
yyIncrFlags(CLF_DAYOFWEEK);
}
break;
case 9: /* item: relspec */
{
info->flags |= CLF_RELCONV;
}
break;
case 10: /* item: iso */
{
yyIncrFlags(CLF_TIME|CLF_HAVEDATE);
}
break;
case 11: /* item: trek */
{
yyIncrFlags(CLF_TIME|CLF_HAVEDATE);
info->flags |= CLF_RELCONV;
}
break;
case 13: /* iextime: tUNUMBER ':' tUNUMBER ':' tUNUMBER */
{
yyHour = (yyvsp[-4].Number);
yyMinutes = (yyvsp[-2].Number);
yySeconds = (yyvsp[0].Number);
}
break;
case 14: /* iextime: tUNUMBER ':' tUNUMBER */
{
yyHour = (yyvsp[-2].Number);
yyMinutes = (yyvsp[0].Number);
yySeconds = 0;
}
break;
case 15: /* time: tUNUMBER tMERIDIAN */
{
yyHour = (yyvsp[-1].Number);
yyMinutes = 0;
yySeconds = 0;
yyMeridian = (yyvsp[0].Meridian);
}
break;
case 16: /* time: iextime o_merid */
{
yyMeridian = (yyvsp[0].Meridian);
}
break;
case 17: /* zone: tZONE tDST */
{
yyTimezone = (yyvsp[-1].Number);
yyDSTmode = DSTon;
}
break;
case 18: /* zone: tZONE */
{
yyTimezone = (yyvsp[0].Number);
yyDSTmode = DSToff;
}
break;
case 19: /* zone: tDAYZONE */
{
yyTimezone = (yyvsp[0].Number);
yyDSTmode = DSTon;
}
break;
case 20: /* zone: tZONEwO4 sign INTNUM */
{ /* GMT+0100, GMT-1000, etc. */
yyTimezone = (yyvsp[-2].Number) - (yyvsp[-1].Number)*((yyvsp[0].Number) % 100 + ((yyvsp[0].Number) / 100) * 60);
yyDSTmode = DSToff;
}
break;
case 21: /* zone: tZONEwO2 sign INTNUM */
{ /* GMT+1, GMT-10, etc. */
yyTimezone = (yyvsp[-2].Number) - (yyvsp[-1].Number)*((yyvsp[0].Number) * 60);
yyDSTmode = DSToff;
}
break;
case 22: /* zone: sign INTNUM */
{ /* +0100, -0100 */
yyTimezone = -(yyvsp[-1].Number)*((yyvsp[0].Number) % 100 + ((yyvsp[0].Number) / 100) * 60);
yyDSTmode = DSToff;
}
break;
case 25: /* day: tDAY */
{
yyDayOrdinal = 1;
yyDayOfWeek = (yyvsp[0].Number);
}
break;
case 26: /* day: tDAY comma */
{
yyDayOrdinal = 1;
yyDayOfWeek = (yyvsp[-1].Number);
}
break;
case 27: /* day: tUNUMBER tDAY */
{
yyDayOrdinal = (yyvsp[-1].Number);
yyDayOfWeek = (yyvsp[0].Number);
}
break;
case 28: /* day: sign SP tUNUMBER tDAY */
{
yyDayOrdinal = (yyvsp[-3].Number) * (yyvsp[-1].Number);
yyDayOfWeek = (yyvsp[0].Number);
}
break;
case 29: /* day: sign tUNUMBER tDAY */
{
yyDayOrdinal = (yyvsp[-2].Number) * (yyvsp[-1].Number);
yyDayOfWeek = (yyvsp[0].Number);
}
break;
case 30: /* day: tNEXT tDAY */
{
yyDayOrdinal = 2;
yyDayOfWeek = (yyvsp[0].Number);
}
break;
case 31: /* iexdate: tUNUMBER '-' tUNUMBER '-' tUNUMBER */
{
yyMonth = (yyvsp[-2].Number);
yyDay = (yyvsp[0].Number);
yyYear = (yyvsp[-4].Number);
}
break;
case 32: /* date: tUNUMBER '/' tUNUMBER */
{
yyMonth = (yyvsp[-2].Number);
yyDay = (yyvsp[0].Number);
}
break;
case 33: /* date: tUNUMBER '/' tUNUMBER '/' tUNUMBER */
{
yyMonth = (yyvsp[-4].Number);
yyDay = (yyvsp[-2].Number);
yyYear = (yyvsp[0].Number);
}
break;
case 35: /* date: tUNUMBER '-' tMONTH '-' tUNUMBER */
{
yyDay = (yyvsp[-4].Number);
yyMonth = (yyvsp[-2].Number);
yyYear = (yyvsp[0].Number);
}
break;
case 36: /* date: tMONTH tUNUMBER */
{
yyMonth = (yyvsp[-1].Number);
yyDay = (yyvsp[0].Number);
}
break;
case 37: /* date: tMONTH tUNUMBER comma tUNUMBER */
{
yyMonth = (yyvsp[-3].Number);
yyDay = (yyvsp[-2].Number);
yyYear = (yyvsp[0].Number);
}
break;
case 38: /* date: tUNUMBER tMONTH */
{
yyMonth = (yyvsp[0].Number);
yyDay = (yyvsp[-1].Number);
}
break;
case 39: /* date: tEPOCH */
{
yyMonth = 1;
yyDay = 1;
yyYear = EPOCH;
}
break;
case 40: /* date: tUNUMBER tMONTH tUNUMBER */
{
yyMonth = (yyvsp[-1].Number);
yyDay = (yyvsp[-2].Number);
yyYear = (yyvsp[0].Number);
}
break;
case 41: /* ordMonth: tNEXT tMONTH */
{
yyMonthOrdinalIncr = 1;
yyMonthOrdinal = (yyvsp[0].Number);
}
break;
case 42: /* ordMonth: tNEXT tUNUMBER tMONTH */
{
yyMonthOrdinalIncr = (yyvsp[-1].Number);
yyMonthOrdinal = (yyvsp[0].Number);
}
break;
case 45: /* isodate: tISOBAS8 */
{ /* YYYYMMDD */
yyYear = (yyvsp[0].Number) / 10000;
yyMonth = ((yyvsp[0].Number) % 10000)/100;
yyDay = (yyvsp[0].Number) % 100;
}
break;
case 46: /* isodate: tISOBAS6 */
{ /* YYMMDD */
yyYear = (yyvsp[0].Number) / 10000;
yyMonth = ((yyvsp[0].Number) % 10000)/100;
yyDay = (yyvsp[0].Number) % 100;
}
break;
case 48: /* isotime: tISOBAS6 */
{
yyHour = (yyvsp[0].Number) / 10000;
yyMinutes = ((yyvsp[0].Number) % 10000)/100;
yySeconds = (yyvsp[0].Number) % 100;
}
break;
case 51: /* iso: tISOBASL tISOBAS6 */
{ /* YYYYMMDDhhmmss */
yyYear = (yyvsp[-1].Number) / 10000;
yyMonth = ((yyvsp[-1].Number) % 10000)/100;
yyDay = (yyvsp[-1].Number) % 100;
yyHour = (yyvsp[0].Number) / 10000;
yyMinutes = ((yyvsp[0].Number) % 10000)/100;
yySeconds = (yyvsp[0].Number) % 100;
}
break;
case 52: /* iso: tISOBASL tUNUMBER */
{ /* YYYYMMDDhhmm */
if (yyDigitCount != 4) YYABORT; /* normally unreached */
yyYear = (yyvsp[-1].Number) / 10000;
yyMonth = ((yyvsp[-1].Number) % 10000)/100;
yyDay = (yyvsp[-1].Number) % 100;
yyHour = (yyvsp[0].Number) / 100;
yyMinutes = ((yyvsp[0].Number) % 100);
yySeconds = 0;
}
break;
case 53: /* trek: tSTARDATE INTNUM '.' tUNUMBER */
{
/*
* Offset computed year by -377 so that the returned years will be
* in a range accessible with a 32 bit clock seconds value.
*/
yyYear = (yyvsp[-2].Number)/1000 + 2323 - 377;
yyDay = 1;
yyMonth = 1;
yyRelDay += (((yyvsp[-2].Number)%1000)*(365 + IsLeapYear(yyYear)))/1000;
yyRelSeconds += (yyvsp[0].Number) * (144LL * 60LL);
}
break;
case 54: /* relspec: relunits tAGO */
{
yyRelSeconds *= -1;
yyRelMonth *= -1;
yyRelDay *= -1;
}
break;
case 56: /* relunits: sign SP INTNUM unit */
{
*yyRelPointer += (yyvsp[-3].Number) * (yyvsp[-1].Number) * (yyvsp[0].Number);
}
break;
case 57: /* relunits: sign INTNUM unit */
{
*yyRelPointer += (yyvsp[-2].Number) * (yyvsp[-1].Number) * (yyvsp[0].Number);
}
break;
case 58: /* relunits: INTNUM unit */
{
*yyRelPointer += (yyvsp[-1].Number) * (yyvsp[0].Number);
}
break;
case 59: /* relunits: tNEXT unit */
{
*yyRelPointer += (yyvsp[0].Number);
}
break;
case 60: /* relunits: tNEXT INTNUM unit */
{
*yyRelPointer += (yyvsp[-1].Number) * (yyvsp[0].Number);
}
break;
case 61: /* relunits: unit */
{
*yyRelPointer += (yyvsp[0].Number);
}
break;
case 62: /* sign: '-' */
{
(yyval.Number) = -1;
}
break;
case 63: /* sign: '+' */
{
(yyval.Number) = 1;
}
break;
case 64: /* unit: tSEC_UNIT */
{
(yyval.Number) = (yyvsp[0].Number);
yyRelPointer = &yyRelSeconds;
}
break;
case 65: /* unit: tDAY_UNIT */
{
(yyval.Number) = (yyvsp[0].Number);
yyRelPointer = &yyRelDay;
}
break;
case 66: /* unit: tMONTH_UNIT */
{
(yyval.Number) = (yyvsp[0].Number);
yyRelPointer = &yyRelMonth;
}
break;
case 67: /* INTNUM: tUNUMBER */
{
(yyval.Number) = (yyvsp[0].Number);
}
break;
case 68: /* INTNUM: tISOBAS6 */
{
(yyval.Number) = (yyvsp[0].Number);
}
break;
case 69: /* INTNUM: tISOBAS8 */
{
(yyval.Number) = (yyvsp[0].Number);
}
break;
case 70: /* numitem: tUNUMBER */
{
if ((info->flags & (CLF_TIME|CLF_HAVEDATE|CLF_RELCONV)) == (CLF_TIME|CLF_HAVEDATE)) {
yyYear = (yyvsp[0].Number);
} else {
yyIncrFlags(CLF_TIME);
if (yyDigitCount <= 2) {
yyHour = (yyvsp[0].Number);
yyMinutes = 0;
} else {
yyHour = (yyvsp[0].Number) / 100;
yyMinutes = (yyvsp[0].Number) % 100;
}
yySeconds = 0;
yyMeridian = MER24;
}
}
break;
case 71: /* o_merid: %empty */
{
(yyval.Meridian) = MER24;
}
break;
case 72: /* o_merid: tMERIDIAN */
{
(yyval.Meridian) = (yyvsp[0].Meridian);
}
break;
|
| ︙ | ︙ | |||
2151 2152 2153 2154 2155 2156 2157 |
{ "tomorrow", tDAY_UNIT, 1 },
{ "yesterday", tDAY_UNIT, -1 },
{ "today", tDAY_UNIT, 0 },
{ "now", tSEC_UNIT, 0 },
{ "last", tUNUMBER, -1 },
{ "this", tSEC_UNIT, 0 },
{ "next", tNEXT, 1 },
| < < < < < < < < < < < < < < | 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 |
{ "tomorrow", tDAY_UNIT, 1 },
{ "yesterday", tDAY_UNIT, -1 },
{ "today", tDAY_UNIT, 0 },
{ "now", tSEC_UNIT, 0 },
{ "last", tUNUMBER, -1 },
{ "this", tSEC_UNIT, 0 },
{ "next", tNEXT, 1 },
{ "ago", tAGO, 1 },
{ "epoch", tEPOCH, 0 },
{ "stardate", tSTARDATE, 0 },
{ NULL, 0, 0 }
};
/*
|
| ︙ | ︙ | |||
2264 2265 2266 2267 2268 2269 2270 |
};
/*
* Military timezone table.
*/
static const TABLE MilitaryTable[] = {
| | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > | | | | | | | | | | 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 |
};
/*
* Military timezone table.
*/
static const TABLE MilitaryTable[] = {
{ "a", tZONE, -HOUR( 1) },
{ "b", tZONE, -HOUR( 2) },
{ "c", tZONE, -HOUR( 3) },
{ "d", tZONE, -HOUR( 4) },
{ "e", tZONE, -HOUR( 5) },
{ "f", tZONE, -HOUR( 6) },
{ "g", tZONE, -HOUR( 7) },
{ "h", tZONE, -HOUR( 8) },
{ "i", tZONE, -HOUR( 9) },
{ "k", tZONE, -HOUR(10) },
{ "l", tZONE, -HOUR(11) },
{ "m", tZONE, -HOUR(12) },
{ "n", tZONE, HOUR( 1) },
{ "o", tZONE, HOUR( 2) },
{ "p", tZONE, HOUR( 3) },
{ "q", tZONE, HOUR( 4) },
{ "r", tZONE, HOUR( 5) },
{ "s", tZONE, HOUR( 6) },
{ "t", tZONE, HOUR( 7) },
{ "u", tZONE, HOUR( 8) },
{ "v", tZONE, HOUR( 9) },
{ "w", tZONE, HOUR( 10) },
{ "x", tZONE, HOUR( 11) },
{ "y", tZONE, HOUR( 12) },
{ "z", tZONE, HOUR( 0) },
{ NULL, 0, 0 }
};
static inline const char *
bypassSpaces(
const char *s)
{
while (TclIsSpaceProc(*s)) {
s++;
}
return s;
}
/*
* Dump error messages in the bit bucket.
*/
static void
TclDateerror(
YYLTYPE* location,
DateInfo* infoPtr,
const char *s)
{
Tcl_Obj* t;
if (!infoPtr->messages) {
TclNewObj(infoPtr->messages);
}
Tcl_AppendToObj(infoPtr->messages, infoPtr->separatrix, -1);
Tcl_AppendToObj(infoPtr->messages, s, -1);
Tcl_AppendToObj(infoPtr->messages, " (characters ", -1);
TclNewIntObj(t, location->first_column);
Tcl_IncrRefCount(t);
Tcl_AppendObjToObj(infoPtr->messages, t);
Tcl_DecrRefCount(t);
Tcl_AppendToObj(infoPtr->messages, "-", -1);
TclNewIntObj(t, location->last_column);
Tcl_IncrRefCount(t);
Tcl_AppendObjToObj(infoPtr->messages, t);
Tcl_DecrRefCount(t);
Tcl_AppendToObj(infoPtr->messages, ")", -1);
infoPtr->separatrix = "\n";
}
int
ToSeconds(
int Hours,
int Minutes,
int Seconds,
MERIDIAN Meridian)
{
if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) {
return -1;
}
switch (Meridian) {
case MER24:
if (Hours < 0 || Hours > 23) {
return -1;
}
return (Hours * 60 + Minutes) * 60 + Seconds;
case MERam:
if (Hours < 1 || Hours > 12) {
return -1;
}
return ((Hours % 12) * 60 + Minutes) * 60 + Seconds;
case MERpm:
if (Hours < 1 || Hours > 12) {
return -1;
}
return (((Hours % 12) + 12) * 60 + Minutes) * 60 + Seconds;
}
return -1; /* Should never be reached */
}
static int
LookupWord(
YYSTYPE* yylvalPtr,
char *buff)
{
char *p;
char *q;
const TABLE *tp;
int i, abbrev;
/*
* Make it lowercase.
*/
Tcl_UtfToLower(buff);
if (*buff == 'a' && (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0)) {
yylvalPtr->Meridian = MERam;
return tMERIDIAN;
}
if (*buff == 'p' && (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0)) {
yylvalPtr->Meridian = MERpm;
return tMERIDIAN;
}
/*
* See if we have an abbreviation for a month.
*/
|
| ︙ | ︙ | |||
2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 |
YYLTYPE* location,
DateInfo *info)
{
char c;
char *p;
char buff[20];
int Count;
location->first_column = yyInput - info->dateStart;
for ( ; ; ) {
| > | > > > | > > | | > > > | | > | > | > > > > > | | < > | > | > > > > | > > > | > < < | > > | < > | | | | > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < < | < < < < | | | | | | | < | | < < < < < < | < < < | < | | < > | < < < < | | > > > > > > > > > > > > > > > > | > | | > | < | < | > | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 |
YYLTYPE* location,
DateInfo *info)
{
char c;
char *p;
char buff[20];
int Count;
const char *tokStart;
location->first_column = yyInput - info->dateStart;
for ( ; ; ) {
if (isspace(UCHAR(*yyInput))) {
yyInput = bypassSpaces(yyInput);
/* ignore space at end of text and before some words */
c = *yyInput;
if (c != '\0' && !isalpha(UCHAR(c))) {
return SP;
}
}
tokStart = yyInput;
if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */
/*
* Count the number of digits.
*/
p = (char *)yyInput;
while (isdigit(UCHAR(*++p))) {};
yyDigitCount = p - yyInput;
/*
* A number with 12 or 14 digits is considered an ISO 8601 date.
*/
if (yyDigitCount == 14 || yyDigitCount == 12) {
/* long form of ISO 8601 (without separator), either
* YYYYMMDDhhmmss or YYYYMMDDhhmm, so reduce to date
* (8 chars is isodate) */
p = (char *)yyInput+8;
if (TclAtoWIe(&yylvalPtr->Number, yyInput, p, 1) != TCL_OK) {
return tID; /* overflow*/
}
yyDigitCount = 8;
yyInput = p;
location->last_column = yyInput - info->dateStart - 1;
return tISOBASL;
}
/*
* Convert the string into a number
*/
if (TclAtoWIe(&yylvalPtr->Number, yyInput, p, 1) != TCL_OK) {
return tID; /* overflow*/
}
yyInput = p;
/*
* A number with 6 or more digits is considered an ISO 8601 base.
*/
location->last_column = yyInput - info->dateStart - 1;
if (yyDigitCount >= 6) {
if (yyDigitCount == 8) {
return tISOBAS8;
}
if (yyDigitCount == 6) {
return tISOBAS6;
}
}
/* ignore spaces after digits (optional) */
yyInput = bypassSpaces(yyInput);
return tUNUMBER;
}
if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */
int ret;
for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */
|| c == '.'; ) {
if (p < &buff[sizeof(buff) - 1]) {
*p++ = c;
}
}
*p = '\0';
yyInput--;
location->last_column = yyInput - info->dateStart - 1;
ret = LookupWord(yylvalPtr, buff);
/*
* lookahead:
* for spaces to consider word boundaries (for instance
* literal T in isodateTisotimeZ is not a TZ, but Z is UTC);
* for +/- digit, to differentiate between "GMT+1000 day" and "GMT +1000 day";
* bypass spaces after token (but ignore by TZ+OFFS), because should
* recognize next SP token, if TZ only.
*/
if (ret == tZONE || ret == tDAYZONE) {
c = *yyInput;
if (isdigit(UCHAR(c))) { /* literal not a TZ */
yyInput = tokStart;
return *yyInput++;
}
if ((c == '+' || c == '-') && isdigit(UCHAR(*(yyInput+1)))) {
if ( !isdigit(UCHAR(*(yyInput+2)))
|| !isdigit(UCHAR(*(yyInput+3)))) {
/* GMT+1, GMT-10, etc. */
return tZONEwO2;
}
if ( isdigit(UCHAR(*(yyInput+4)))
&& !isdigit(UCHAR(*(yyInput+5)))) {
/* GMT+1000, etc. */
return tZONEwO4;
}
}
}
yyInput = bypassSpaces(yyInput);
return ret;
}
if (c != '(') {
location->last_column = yyInput - info->dateStart;
return *yyInput++;
}
Count = 0;
do {
c = *yyInput++;
if (c == '\0') {
location->last_column = yyInput - info->dateStart - 1;
return c;
} else if (c == '(') {
Count++;
} else if (c == ')') {
Count--;
}
} while (Count > 0);
}
}
int
TclClockFreeScan(
Tcl_Interp *interp, /* Tcl interpreter */
DateInfo *info) /* Input and result parameters */
{
int status;
#if YYDEBUG
/* enable debugging if compiled with YYDEBUG */
yydebug = 1;
#endif
/*
* yyInput = stringToParse;
*
* ClockInitDateInfo(info) should be executed to pre-init info;
*/
yyDSTmode = DSTmaybe;
info->separatrix = "";
info->dateStart = yyInput;
/* ignore spaces at begin */
yyInput = bypassSpaces(yyInput);
/* parse */
status = yyparse(info);
if (status == 1) {
const char *msg = NULL;
if (info->errFlags & CLF_HAVEDATE) {
msg = "more than one date in string";
} else if (info->errFlags & CLF_TIME) {
msg = "more than one time of day in string";
} else if (info->errFlags & CLF_ZONE) {
msg = "more than one time zone in string";
} else if (info->errFlags & CLF_DAYOFWEEK) {
msg = "more than one weekday in string";
} else if (info->errFlags & CLF_ORDINALMONTH) {
msg = "more than one ordinal month in string";
}
if (msg) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", (char *)NULL);
} else {
Tcl_SetObjResult(interp,
info->messages ? info->messages : Tcl_NewObj());
info->messages = NULL;
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", (char *)NULL);
}
status = TCL_ERROR;
} else if (status == 2) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
status = TCL_ERROR;
} else if (status != 0) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("Unknown status returned "
"from date parser. Please "
"report this error as a "
"bug in Tcl.", -1));
Tcl_SetErrorCode(interp, "TCL", "BUG", (char *)NULL);
status = TCL_ERROR;
}
if (info->messages) {
Tcl_DecrRefCount(info->messages);
}
return status;
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
|
Added generic/tclDate.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 |
/*
* tclDate.h --
*
* This header file handles common usage of clock primitives
* between tclDate.c (yacc), tclClock.c and tclClockFmt.c.
*
* Copyright (c) 2014 Serg G. Brester (aka sebres)
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef _TCLCLOCK_H
#define _TCLCLOCK_H
/*
* Constants
*/
#define JULIAN_DAY_POSIX_EPOCH 2440588
#define GREGORIAN_CHANGE_DATE 2361222
#define SECONDS_PER_DAY 86400
#define JULIAN_SEC_POSIX_EPOCH (((Tcl_WideInt) JULIAN_DAY_POSIX_EPOCH) \
* SECONDS_PER_DAY)
#define FOUR_CENTURIES 146097 /* days */
#define JDAY_1_JAN_1_CE_JULIAN 1721424
#define JDAY_1_JAN_1_CE_GREGORIAN 1721426
#define ONE_CENTURY_GREGORIAN 36524 /* days */
#define FOUR_YEARS 1461 /* days */
#define ONE_YEAR 365 /* days */
#define RODDENBERRY 1946 /* Another epoch (Hi, Jeff!) */
#define CLF_OPTIONAL (1 << 0) /* token is non mandatory */
#define CLF_POSIXSEC (1 << 1)
#define CLF_LOCALSEC (1 << 2)
#define CLF_JULIANDAY (1 << 3)
#define CLF_TIME (1 << 4)
#define CLF_ZONE (1 << 5)
#define CLF_CENTURY (1 << 6)
#define CLF_DAYOFMONTH (1 << 7)
#define CLF_DAYOFYEAR (1 << 8)
#define CLF_MONTH (1 << 9)
#define CLF_YEAR (1 << 10)
#define CLF_DAYOFWEEK (1 << 11)
#define CLF_ISO8601YEAR (1 << 12)
#define CLF_ISO8601WEAK (1 << 13)
#define CLF_ISO8601CENTURY (1 << 14)
#define CLF_SIGNED (1 << 15)
/* extra flags used outside of scan/format-tokens too (int, not a short int) */
#define CLF_RELCONV (1 << 17)
#define CLF_ORDINALMONTH (1 << 18)
/* On demand (lazy) assemble flags */
#define CLF_ASSEMBLE_DATE (1 << 28) /* assemble year, month, etc. using julianDay */
#define CLF_ASSEMBLE_JULIANDAY (1 << 29) /* assemble julianDay using year, month, etc. */
#define CLF_ASSEMBLE_SECONDS (1 << 30) /* assemble localSeconds (and seconds at end) */
#define CLF_HAVEDATE (CLF_DAYOFMONTH|CLF_MONTH|CLF_YEAR)
#define CLF_DATE (CLF_JULIANDAY | CLF_DAYOFMONTH | CLF_DAYOFYEAR | \
CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR | \
CLF_DAYOFWEEK | CLF_ISO8601WEAK)
#define TCL_MIN_SECONDS -0x00F0000000000000L
#define TCL_MAX_SECONDS 0x00F0000000000000L
#define TCL_INV_SECONDS (TCL_MIN_SECONDS-1)
/*
* Enumeration of the string literals used in [clock]
*/
typedef enum ClockLiteral {
LIT__NIL,
LIT__DEFAULT_FORMAT,
LIT_SYSTEM, LIT_CURRENT, LIT_C,
LIT_BCE, LIT_CE,
LIT_DAYOFMONTH, LIT_DAYOFWEEK, LIT_DAYOFYEAR,
LIT_ERA, LIT_GMT, LIT_GREGORIAN,
LIT_INTEGER_VALUE_TOO_LARGE,
LIT_ISO8601WEEK, LIT_ISO8601YEAR,
LIT_JULIANDAY, LIT_LOCALSECONDS,
LIT_MONTH,
LIT_SECONDS, LIT_TZNAME, LIT_TZOFFSET,
LIT_YEAR,
LIT_TZDATA,
LIT_GETSYSTEMTIMEZONE,
LIT_SETUPTIMEZONE,
LIT_MCGET,
LIT_GETSYSTEMLOCALE, LIT_GETCURRENTLOCALE,
LIT_LOCALIZE_FORMAT,
LIT__END
} ClockLiteral;
#define CLOCK_LITERAL_ARRAY(litarr) static const char *const litarr[] = { \
"", \
"%a %b %d %H:%M:%S %Z %Y", \
"system", "current", "C", \
"BCE", "CE", \
"dayOfMonth", "dayOfWeek", "dayOfYear", \
"era", ":GMT", "gregorian", \
"integer value too large to represent", \
"iso8601Week", "iso8601Year", \
"julianDay", "localSeconds", \
"month", \
"seconds", "tzName", "tzOffset", \
"year", \
"::tcl::clock::TZData", \
"::tcl::clock::GetSystemTimeZone", \
"::tcl::clock::SetupTimeZone", \
"::tcl::clock::mcget", \
"::tcl::clock::GetSystemLocale", "::tcl::clock::mclocale", \
"::tcl::clock::LocalizeFormat" \
}
/*
* Enumeration of the msgcat literals used in [clock]
*/
typedef enum ClockMsgCtLiteral {
MCLIT__NIL, /* placeholder */
MCLIT_MONTHS_FULL, MCLIT_MONTHS_ABBREV, MCLIT_MONTHS_COMB,
MCLIT_DAYS_OF_WEEK_FULL, MCLIT_DAYS_OF_WEEK_ABBREV, MCLIT_DAYS_OF_WEEK_COMB,
MCLIT_AM, MCLIT_PM,
MCLIT_LOCALE_ERAS,
MCLIT_BCE, MCLIT_CE,
MCLIT_BCE2, MCLIT_CE2,
MCLIT_BCE3, MCLIT_CE3,
MCLIT_LOCALE_NUMERALS,
MCLIT__END
} ClockMsgCtLiteral;
#define CLOCK_LOCALE_LITERAL_ARRAY(litarr, pref) static const char *const litarr[] = { \
pref "", \
pref "MONTHS_FULL", pref "MONTHS_ABBREV", pref "MONTHS_COMB", \
pref "DAYS_OF_WEEK_FULL", pref "DAYS_OF_WEEK_ABBREV", pref "DAYS_OF_WEEK_COMB", \
pref "AM", pref "PM", \
pref "LOCALE_ERAS", \
pref "BCE", pref "CE", \
pref "b.c.e.", pref "c.e.", \
pref "b.c.", pref "a.d.", \
pref "LOCALE_NUMERALS", \
}
/*
* Structure containing the fields used in [clock format] and [clock scan]
*/
#define CLF_CTZ (1 << 4)
typedef struct TclDateFields {
/* Cacheable fields: */
Tcl_WideInt seconds; /* Time expressed in seconds from the Posix
* epoch */
Tcl_WideInt localSeconds; /* Local time expressed in nominal seconds
* from the Posix epoch */
int tzOffset; /* Time zone offset in seconds east of
* Greenwich */
Tcl_WideInt julianDay; /* Julian Day Number in local time zone */
int isBce; /* 1 if BCE */
int gregorian; /* Flag == 1 if the date is Gregorian */
int year; /* Year of the era */
int dayOfYear; /* Day of the year (1 January == 1) */
int month; /* Month number */
int dayOfMonth; /* Day of the month */
int iso8601Year; /* ISO8601 week-based year */
int iso8601Week; /* ISO8601 week number */
int dayOfWeek; /* Day of the week */
int hour; /* Hours of day (in-between time only calculation) */
int minutes; /* Minutes of hour (in-between time only calculation) */
Tcl_WideInt secondOfMin; /* Seconds of minute (in-between time only calculation) */
Tcl_WideInt secondOfDay; /* Seconds of day (in-between time only calculation) */
int flags; /* 0 or CLF_CTZ */
/* Non cacheable fields: */
Tcl_Obj *tzName; /* Name (or corresponding DST-abbreviation) of the
* time zone, if set the refCount is incremented */
} TclDateFields;
#define ClockCacheableDateFieldsSize \
offsetof(TclDateFields, tzName)
/*
* Meridian: am, pm, or 24-hour style.
*/
typedef enum _MERIDIAN {
MERam, MERpm, MER24
} MERIDIAN;
/*
* Structure contains return parsed fields.
*/
typedef struct DateInfo {
const char *dateStart;
const char *dateInput;
const char *dateEnd;
TclDateFields date;
int flags; /* Signals parts of date/time get found */
int errFlags; /* Signals error (part of date/time found twice) */
MERIDIAN dateMeridian;
int dateTimezone;
int dateDSTmode;
Tcl_WideInt dateRelMonth;
Tcl_WideInt dateRelDay;
Tcl_WideInt dateRelSeconds;
int dateMonthOrdinalIncr;
int dateMonthOrdinal;
int dateDayOrdinal;
Tcl_WideInt *dateRelPointer;
int dateSpaceCount;
int dateDigitCount;
int dateCentury;
Tcl_Obj* messages; /* Error messages */
const char* separatrix; /* String separating messages */
} DateInfo;
#define yydate (info->date) /* Date fields used for converting */
#define yyDay (info->date.dayOfMonth)
#define yyMonth (info->date.month)
#define yyYear (info->date.year)
#define yyHour (info->date.hour)
#define yyMinutes (info->date.minutes)
#define yySeconds (info->date.secondOfMin)
#define yySecondOfDay (info->date.secondOfDay)
#define yyDSTmode (info->dateDSTmode)
#define yyDayOrdinal (info->dateDayOrdinal)
#define yyDayOfWeek (info->date.dayOfWeek)
#define yyMonthOrdinalIncr (info->dateMonthOrdinalIncr)
#define yyMonthOrdinal (info->dateMonthOrdinal)
#define yyTimezone (info->dateTimezone)
#define yyMeridian (info->dateMeridian)
#define yyRelMonth (info->dateRelMonth)
#define yyRelDay (info->dateRelDay)
#define yyRelSeconds (info->dateRelSeconds)
#define yyRelPointer (info->dateRelPointer)
#define yyInput (info->dateInput)
#define yyDigitCount (info->dateDigitCount)
#define yySpaceCount (info->dateSpaceCount)
static inline void
ClockInitDateInfo(DateInfo *info) {
memset(info, 0, sizeof(DateInfo));
}
/*
* Structure containing the command arguments supplied to [clock format] and [clock scan]
*/
#define CLF_VALIDATE_S1 (1 << 0)
#define CLF_VALIDATE_S2 (1 << 1)
#define CLF_VALIDATE (CLF_VALIDATE_S1|CLF_VALIDATE_S2)
#define CLF_EXTENDED (1 << 4)
#define CLF_STRICT (1 << 8)
#define CLF_LOCALE_USED (1 << 15)
typedef struct ClockFmtScnCmdArgs {
void *clientData; /* Opaque pointer to literal pool, etc. */
Tcl_Interp *interp; /* Tcl interpreter */
Tcl_Obj *formatObj; /* Format */
Tcl_Obj *localeObj; /* Name of the locale where the time will be expressed. */
Tcl_Obj *timezoneObj; /* Default time zone in which the time will be expressed */
Tcl_Obj *baseObj; /* Base (scan and add) or clockValue (format) */
int flags; /* Flags control scanning */
Tcl_Obj *mcDictObj; /* Current dictionary of tcl::clock package for given localeObj*/
} ClockFmtScnCmdArgs;
/* Last-period cache for fast UTC to local and backwards conversion */
typedef struct ClockLastTZOffs {
/* keys */
Tcl_Obj *timezoneObj;
int changeover;
Tcl_WideInt localSeconds;
Tcl_WideInt rangesVal[2]; /* Bounds for cached time zone offset */
/* values */
int tzOffset;
Tcl_Obj *tzName; /* Name (abbreviation) of this area in TZ */
} ClockLastTZOffs;
/*
* Structure containing the client data for [clock]
*/
typedef struct ClockClientData {
size_t refCount; /* Number of live references. */
Tcl_Obj **literals; /* Pool of object literals (common, locale independent). */
Tcl_Obj **mcLiterals; /* Msgcat object literals with mc-keys for search with locale. */
Tcl_Obj **mcLitIdxs; /* Msgcat object indices prefixed with _IDX_,
* used for quick dictionary search */
Tcl_Obj *mcDicts; /* Msgcat collection, contains weak pointers to locale
* catalogs, and owns it references (onetime referenced) */
/* Cache for current clock parameters, imparted via "configure" */
size_t lastTZEpoch;
int currentYearCentury;
int yearOfCenturySwitch;
int validMinYear;
int validMaxYear;
double maxJDN;
Tcl_Obj *systemTimeZone;
Tcl_Obj *systemSetupTZData;
Tcl_Obj *gmtSetupTimeZoneUnnorm;
Tcl_Obj *gmtSetupTimeZone;
Tcl_Obj *gmtSetupTZData;
Tcl_Obj *gmtTZName;
Tcl_Obj *lastSetupTimeZoneUnnorm;
Tcl_Obj *lastSetupTimeZone;
Tcl_Obj *lastSetupTZData;
Tcl_Obj *prevSetupTimeZoneUnnorm;
Tcl_Obj *prevSetupTimeZone;
Tcl_Obj *prevSetupTZData;
Tcl_Obj *defaultLocale;
Tcl_Obj *defaultLocaleDict;
Tcl_Obj *currentLocale;
Tcl_Obj *currentLocaleDict;
Tcl_Obj *lastUsedLocaleUnnorm;
Tcl_Obj *lastUsedLocale;
Tcl_Obj *lastUsedLocaleDict;
Tcl_Obj *prevUsedLocaleUnnorm;
Tcl_Obj *prevUsedLocale;
Tcl_Obj *prevUsedLocaleDict;
/* Cache for last base (last-second fast convert if base/tz not changed) */
struct {
Tcl_Obj *timezoneObj;
TclDateFields date;
} lastBase;
/* Last-period cache for fast UTC to Local and backwards conversion */
ClockLastTZOffs lastTZOffsCache[2];
int defFlags; /* Default flags (from configure), ATM
* only CLF_VALIDATE supported */
} ClockClientData;
#define ClockDefaultYearCentury 2000
#define ClockDefaultCenturySwitch 38
/*
* Clock scan and format facilities.
*/
#ifndef TCL_MEM_DEBUG
# define CLOCK_FMT_SCN_STORAGE_GC_SIZE 32
#else
# define CLOCK_FMT_SCN_STORAGE_GC_SIZE 0
#endif
#define CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE 2
typedef struct ClockScanToken ClockScanToken;
typedef int ClockScanTokenProc(
ClockFmtScnCmdArgs *opts,
DateInfo *info,
ClockScanToken *tok);
typedef enum _CLCKTOK_TYPE {
CTOKT_INT = 1, CTOKT_WIDE, CTOKT_PARSER, CTOKT_SPACE, CTOKT_WORD, CTOKT_CHAR,
CFMTT_PROC
} CLCKTOK_TYPE;
typedef struct ClockScanTokenMap {
unsigned short int type;
unsigned short int flags;
unsigned short int clearFlags;
unsigned short int minSize;
unsigned short int maxSize;
unsigned short int offs;
ClockScanTokenProc *parser;
const void *data;
} ClockScanTokenMap;
struct ClockScanToken {
ClockScanTokenMap *map;
struct {
const char *start;
const char *end;
} tokWord;
unsigned short int endDistance;
unsigned short int lookAhMin;
unsigned short int lookAhMax;
unsigned short int lookAhTok;
};
#define MIN_FMT_RESULT_BLOCK_ALLOC 80
#define MIN_FMT_RESULT_BLOCK_DELTA 0
/* Maximal permitted threshold (buffer size > result size) in percent,
* to directly return the buffer without reallocate */
#define MAX_FMT_RESULT_THRESHOLD 2
typedef struct DateFormat {
char *resMem;
char *resEnd;
char *output;
TclDateFields date;
Tcl_Obj *localeEra;
} DateFormat;
#define CLFMT_INCR (1 << 3)
#define CLFMT_DECR (1 << 4)
#define CLFMT_CALC (1 << 5)
#define CLFMT_LOCALE_INDX (1 << 8)
typedef struct ClockFormatToken ClockFormatToken;
typedef int ClockFormatTokenProc(
ClockFmtScnCmdArgs *opts,
DateFormat *dateFmt,
ClockFormatToken *tok,
int *val);
typedef struct ClockFormatTokenMap {
unsigned short int type;
const char *tostr;
unsigned short int width;
unsigned short int flags;
unsigned short int divider;
unsigned short int divmod;
unsigned short int offs;
ClockFormatTokenProc *fmtproc;
void *data;
} ClockFormatTokenMap;
struct ClockFormatToken {
ClockFormatTokenMap *map;
struct {
const char *start;
const char *end;
} tokWord;
};
typedef struct ClockFmtScnStorage ClockFmtScnStorage;
struct ClockFmtScnStorage {
int objRefCount; /* Reference count shared across threads */
ClockScanToken *scnTok;
unsigned int scnTokC;
unsigned int scnSpaceCount; /* Count of mandatory spaces used in format */
ClockFormatToken *fmtTok;
unsigned int fmtTokC;
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
ClockFmtScnStorage *nextPtr;
ClockFmtScnStorage *prevPtr;
#endif
size_t fmtMinAlloc;
#if 0
+Tcl_HashEntry hashEntry /* ClockFmtScnStorage is a derivate of Tcl_HashEntry,
* stored by offset +sizeof(self) */
#endif
};
/*
* Clock macros.
*/
/*
* Extracts Julian day and seconds of the day from posix seconds (tm).
*/
#define ClockExtractJDAndSODFromSeconds(jd, sod, tm) \
do { \
jd = (tm + JULIAN_SEC_POSIX_EPOCH); \
if (jd >= SECONDS_PER_DAY || jd <= -SECONDS_PER_DAY) { \
jd /= SECONDS_PER_DAY; \
sod = (int)(tm % SECONDS_PER_DAY); \
} else { \
sod = (int)jd, jd = 0; \
} \
if (sod < 0) { \
sod += SECONDS_PER_DAY; \
/* JD is affected, if switched into negative (avoid 24 hours difference) */ \
if (jd <= 0) { \
jd--; \
} \
} \
} while(0)
/*
* Prototypes of module functions.
*/
MODULE_SCOPE int ToSeconds(int Hours, int Minutes,
int Seconds, MERIDIAN Meridian);
MODULE_SCOPE int IsGregorianLeapYear(TclDateFields *);
MODULE_SCOPE void
GetJulianDayFromEraYearWeekDay(
TclDateFields *fields, int changeover);
MODULE_SCOPE void
GetJulianDayFromEraYearMonthDay(
TclDateFields *fields, int changeover);
MODULE_SCOPE void
GetJulianDayFromEraYearDay(
TclDateFields *fields, int changeover);
MODULE_SCOPE int ConvertUTCToLocal(void *clientData, Tcl_Interp *,
TclDateFields *, Tcl_Obj *timezoneObj, int);
MODULE_SCOPE Tcl_Obj *
LookupLastTransition(Tcl_Interp *, Tcl_WideInt,
Tcl_Size, Tcl_Obj *const *, Tcl_WideInt *rangesVal);
MODULE_SCOPE int TclClockFreeScan(Tcl_Interp *interp, DateInfo *info);
/* tclClock.c module declarations */
MODULE_SCOPE Tcl_Obj *
ClockSetupTimeZone(void *clientData,
Tcl_Interp *interp, Tcl_Obj *timezoneObj);
MODULE_SCOPE Tcl_Obj *
ClockMCDict(ClockFmtScnCmdArgs *opts);
MODULE_SCOPE Tcl_Obj *
ClockMCGet(ClockFmtScnCmdArgs *opts, int mcKey);
MODULE_SCOPE Tcl_Obj *
ClockMCGetIdx(ClockFmtScnCmdArgs *opts, int mcKey);
MODULE_SCOPE int ClockMCSetIdx(ClockFmtScnCmdArgs *opts, int mcKey,
Tcl_Obj *valObj);
/* tclClockFmt.c module declarations */
MODULE_SCOPE char *
TclItoAw(char *buf, int val, char padchar, unsigned short int width);
MODULE_SCOPE int
TclAtoWIe(Tcl_WideInt *out, const char *p, const char *e, int sign);
MODULE_SCOPE Tcl_Obj*
ClockFrmObjGetLocFmtKey(Tcl_Interp *interp,
Tcl_Obj *objPtr);
MODULE_SCOPE ClockFmtScnStorage *
Tcl_GetClockFrmScnFromObj(Tcl_Interp *interp,
Tcl_Obj *objPtr);
MODULE_SCOPE Tcl_Obj *
ClockLocalizeFormat(ClockFmtScnCmdArgs *opts);
MODULE_SCOPE int ClockScan(DateInfo *info,
Tcl_Obj *strObj, ClockFmtScnCmdArgs *opts);
MODULE_SCOPE int ClockFormat(DateFormat *dateFmt,
ClockFmtScnCmdArgs *opts);
MODULE_SCOPE void ClockFrmScnClearCaches(void);
#endif /* _TCLCLOCK_H */
|
Changes to generic/tclDictObj.c.
| ︙ | ︙ | |||
2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 |
Tcl_WrongNumArgs(interp, 1, objv, "dictionary");
return TCL_ERROR;
}
result = Tcl_DictObjSize(interp, objv[1], &size);
if (result == TCL_OK) {
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(size));
}
return result;
}
/*
*----------------------------------------------------------------------
*
* DictExistsCmd --
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 |
Tcl_WrongNumArgs(interp, 1, objv, "dictionary");
return TCL_ERROR;
}
result = Tcl_DictObjSize(interp, objv[1], &size);
if (result == TCL_OK) {
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(size));
}
return result;
}
/*
*----------------------------------------------------------------------
*
* TclDictObjSmartRef --
*
* This function returns new tcl-object with the smart reference to
* dictionary object.
*
* Object returned with this function is a smart reference (pointer),
* so new object of type tclDictType, that directly references given
* dictionary object (with internally increased refCount).
*
* The usage of such pointer objects allows to hold more as one
* reference to the same real dictionary object, allows to make a pointer
* to part of another dictionary, allows to change the dictionary without
* regarding of the "shared" state of the dictionary object.
*
* Prevents "called with shared object" exception if object is multiple
* referenced.
*
* Results:
* The newly create object (contains smart reference) is returned.
* The returned object has a ref count of 0.
*
* Side effects:
* Increases ref count of the referenced dictionary.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
TclDictObjSmartRef(
Tcl_Interp *interp,
Tcl_Obj *dictPtr)
{
Tcl_Obj *result;
Dict *dict;
if (dictPtr->typePtr != &tclDictType
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
return NULL;
}
DictGetInternalRep(dictPtr, dict);
result = Tcl_NewObj();
DictSetInternalRep(result, dict);
dict->refCount++;
result->internalRep.twoPtrValue.ptr2 = NULL;
result->typePtr = &tclDictType;
return result;
}
/*
*----------------------------------------------------------------------
*
* DictExistsCmd --
|
| ︙ | ︙ |
Changes to generic/tclDisassemble.c.
| ︙ | ︙ | |||
872 873 874 875 876 877 878 |
}
Tcl_AppendToObj(appendObj, "\"", -1);
p = stringPtr;
for (; (*p != '\0') && (i < maxChars); p+=len) {
int ucs4;
| | | 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 |
}
Tcl_AppendToObj(appendObj, "\"", -1);
p = stringPtr;
for (; (*p != '\0') && (i < maxChars); p+=len) {
int ucs4;
len = TclUtfToUniChar(p, &ucs4);
switch (ucs4) {
case '"':
Tcl_AppendToObj(appendObj, "\\\"", -1);
i += 2;
continue;
case '\f':
Tcl_AppendToObj(appendObj, "\\f", -1);
|
| ︙ | ︙ |
Changes to generic/tclEncoding.c.
| ︙ | ︙ | |||
1173 1174 1175 1176 1177 1178 1179 |
int result;
Tcl_Size dstLen, soFar;
const char *srcStart = src;
/* DO FIRST - Must always be initialized before returning */
Tcl_DStringInit(dstPtr);
| < < < < < < < < < < < < > | 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 |
int result;
Tcl_Size dstLen, soFar;
const char *srcStart = src;
/* DO FIRST - Must always be initialized before returning */
Tcl_DStringInit(dstPtr);
dst = Tcl_DStringValue(dstPtr);
dstLen = dstPtr->spaceAvl - 1;
if (encoding == NULL) {
encoding = systemEncoding;
}
encodingPtr = (Encoding *)encoding;
if (src == NULL) {
srcLen = 0;
} else if (srcLen == TCL_INDEX_NONE) {
srcLen = encodingPtr->lengthProc(src);
}
flags &= ~TCL_ENCODING_END;
flags |= TCL_ENCODING_START;
if (encodingPtr->toUtfProc == UtfToUtfProc) {
flags |= ENCODING_INPUT;
}
while (1) {
int srcChunkLen, srcChunkRead;
|
| ︙ | ︙ | |||
1501 1502 1503 1504 1505 1506 1507 |
int result;
const char *srcStart = src;
Tcl_Size dstLen, soFar;
/* DO FIRST - must always be initialized on return */
Tcl_DStringInit(dstPtr);
| < < < < < < < < < < < < > | 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 |
int result;
const char *srcStart = src;
Tcl_Size dstLen, soFar;
/* DO FIRST - must always be initialized on return */
Tcl_DStringInit(dstPtr);
dst = Tcl_DStringValue(dstPtr);
dstLen = dstPtr->spaceAvl - 1;
if (encoding == NULL) {
encoding = systemEncoding;
}
encodingPtr = (Encoding *) encoding;
if (src == NULL) {
srcLen = 0;
} else if (srcLen == TCL_INDEX_NONE) {
srcLen = strlen(src);
}
flags &= ~TCL_ENCODING_END;
flags |= TCL_ENCODING_START;
while (1) {
int srcChunkLen, srcChunkRead;
int dstChunkLen, dstChunkWrote, dstChunkChars;
if (srcLen > INT_MAX) {
srcChunkLen = INT_MAX;
|
| ︙ | ︙ | |||
1577 1578 1579 1580 1581 1582 1583 |
} else {
/* Caller wants error message on failure */
if (result != TCL_OK && interp != NULL) {
Tcl_Size pos = Tcl_NumUtfChars(srcStart, nBytesProcessed);
int ucs4;
char buf[TCL_INTEGER_SPACE];
| | | 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 |
} else {
/* Caller wants error message on failure */
if (result != TCL_OK && interp != NULL) {
Tcl_Size pos = Tcl_NumUtfChars(srcStart, nBytesProcessed);
int ucs4;
char buf[TCL_INTEGER_SPACE];
TclUtfToUniChar(&srcStart[nBytesProcessed], &ucs4);
snprintf(buf, sizeof(buf), "%" TCL_SIZE_MODIFIER "d", nBytesProcessed);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"unexpected character at index %" TCL_SIZE_MODIFIER
"u: 'U+%06X'",
pos, ucs4));
Tcl_SetErrorCode(interp, "TCL", "ENCODING", "ILLEGALSEQUENCE",
buf, (void *)NULL);
|
| ︙ | ︙ | |||
2547 2548 2549 2550 2551 2552 2553 |
if (PROFILE_REPLACE(profile)) {
ch = UNICODE_REPLACE_CHAR;
++src;
} else {
/* TCL_ENCODING_PROFILE_TCL8 */
char chbuf[2];
chbuf[0] = UCHAR(*src++); chbuf[1] = 0;
| | | | 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 |
if (PROFILE_REPLACE(profile)) {
ch = UNICODE_REPLACE_CHAR;
++src;
} else {
/* TCL_ENCODING_PROFILE_TCL8 */
char chbuf[2];
chbuf[0] = UCHAR(*src++); chbuf[1] = 0;
TclUtfToUniChar(chbuf, &ch);
}
dst += Tcl_UniCharToUtf(ch, dst);
} else {
size_t len = TclUtfToUniChar(src, &ch);
if (flags & ENCODING_INPUT) {
if (((len < 2) && (ch != 0)) || ((ch > 0xFFFF) && !(flags & ENCODING_UTF))) {
if (PROFILE_STRICT(profile)) {
result = TCL_CONVERT_SYNTAX;
break;
} else if (PROFILE_REPLACE(profile)) {
ch = UNICODE_REPLACE_CHAR;
|
| ︙ | ︙ | |||
2795 2796 2797 2798 2799 2800 2801 |
result = TCL_CONVERT_MULTIBYTE;
break;
}
if (dst > dstEnd) {
result = TCL_CONVERT_NOSPACE;
break;
}
| | | 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 |
result = TCL_CONVERT_MULTIBYTE;
break;
}
if (dst > dstEnd) {
result = TCL_CONVERT_NOSPACE;
break;
}
len = TclUtfToUniChar(src, &ch);
if (SURROGATE(ch)) {
if (PROFILE_STRICT(flags)) {
result = TCL_CONVERT_UNKNOWN;
break;
}
if (PROFILE_REPLACE(flags)) {
ch = UNICODE_REPLACE_CHAR;
|
| ︙ | ︙ | |||
3072 3073 3074 3075 3076 3077 3078 |
result = TCL_CONVERT_MULTIBYTE;
break;
}
if (dst > dstEnd) {
result = TCL_CONVERT_NOSPACE;
break;
}
| | | 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 |
result = TCL_CONVERT_MULTIBYTE;
break;
}
if (dst > dstEnd) {
result = TCL_CONVERT_NOSPACE;
break;
}
len = TclUtfToUniChar(src, &ch);
if (SURROGATE(ch)) {
if (PROFILE_STRICT(flags)) {
result = TCL_CONVERT_UNKNOWN;
break;
}
if (PROFILE_REPLACE(flags)) {
ch = UNICODE_REPLACE_CHAR;
|
| ︙ | ︙ | |||
3319 3320 3321 3322 3323 3324 3325 |
src--;
}
if (PROFILE_REPLACE(flags)) {
ch = UNICODE_REPLACE_CHAR;
} else {
char chbuf[2];
chbuf[0] = byte; chbuf[1] = 0;
| | | 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 |
src--;
}
if (PROFILE_REPLACE(flags)) {
ch = UNICODE_REPLACE_CHAR;
} else {
char chbuf[2];
chbuf[0] = byte; chbuf[1] = 0;
TclUtfToUniChar(chbuf, &ch);
}
}
/*
* Special case for 1-byte Utf chars for speed.
*/
|
| ︙ | ︙ |
Changes to generic/tclExecute.c.
| ︙ | ︙ | |||
8502 8503 8504 8505 8506 8507 8508 |
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"exponent too large", -1));
return GENERAL_ARITHMETIC_ERROR;
}
Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
err = mp_init(&bigResult);
if (err == MP_OKAY) {
| > | | 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 |
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"exponent too large", -1));
return GENERAL_ARITHMETIC_ERROR;
}
Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
err = mp_init(&bigResult);
if (err == MP_OKAY) {
/* Don't use "mp_expt_n" directly here, it doesn't exist in libtommath 1.2 */
err = TclBN_mp_expt_n(&big1, (int)w2, &bigResult);
}
if (err != MP_OKAY) {
return OUT_OF_MEMORY;
}
mp_clear(&big1);
BIG_RESULT(&bigResult);
}
|
| ︙ | ︙ |
Changes to generic/tclGetDate.y.
1 2 3 4 5 6 7 8 9 | /* * tclGetDate.y -- * * Contains yacc grammar for parsing date and time strings. The output of * this file should be the file tclDate.c which is used directly in the * Tcl sources. Note that this file is largely obsolete in Tcl 8.5; it is * only used when doing free-form date parsing, an ill-defined process * anyway. * | | | > | | > < < < | | < < > < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < > > > > > > > | | | | | < < | | | > | > > > | | > > | > > > | | | | | | | < > | < < | > > > > > > > > > > > | < < < | < < < < < < < < > > > > > > > > | > > > > | | | | > > > > | | > > > > > > | < < < < < < < < < | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
/*
* tclGetDate.y --
*
* Contains yacc grammar for parsing date and time strings. The output of
* this file should be the file tclDate.c which is used directly in the
* Tcl sources. Note that this file is largely obsolete in Tcl 8.5; it is
* only used when doing free-form date parsing, an ill-defined process
* anyway.
*
* Copyright © 1992-1995 Karl Lehenbauer & Mark Diekhans.
* Copyright © 1995-1997 Sun Microsystems, Inc.
* Copyright © 2015 Sergey G. Brester aka sebres.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
%parse-param {DateInfo* info}
%lex-param {DateInfo* info}
%define api.pure
/* %error-verbose would be nice, but our token names are meaningless */
%locations
%{
/*
* tclDate.c --
*
* This file is generated from a yacc grammar defined in the file
* tclGetDate.y. It should not be edited directly.
*
* Copyright © 1992-1995 Karl Lehenbauer & Mark Diekhans.
* Copyright © 1995-1997 Sun Microsystems, Inc.
* Copyright © 2015 Sergey G. Brester aka sebres.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
#include "tclInt.h"
/*
* Bison generates several labels that happen to be unused. MS Visual C++
* doesn't like that, and complains. Tell it to shut up.
*/
#ifdef _MSC_VER
#pragma warning( disable : 4102 )
#endif /* _MSC_VER */
#if 0
#define YYDEBUG 1
#endif
/*
* yyparse will accept a 'struct DateInfo' as its parameter; that's where the
* parsed fields will be returned.
*/
#include "tclDate.h"
#define YYMALLOC Tcl_Alloc
#define YYFREE(x) (Tcl_Free((void*) (x)))
#define EPOCH 1970
#define START_OF_TIME 1902
#define END_OF_TIME 2037
/*
* The offset of tm_year of struct tm returned by localtime, gmtime, etc.
* Posix requires 1900.
*/
#define TM_YEAR_BASE 1900
#define HOUR(x) ((60 * (int)(x)))
#define IsLeapYear(x) (((x) % 4 == 0) && ((x) % 100 != 0 || (x) % 400 == 0))
#define yyIncrFlags(f) \
do { \
info->errFlags |= (info->flags & (f)); \
if (info->errFlags) { YYABORT; } \
info->flags |= (f); \
} while (0);
/*
* An entry in the lexical lookup table.
*/
typedef struct {
const char *name;
int type;
int value;
} TABLE;
/*
* Daylight-savings mode: on, off, or not yet known.
*/
typedef enum _DSTMODE {
DSTon, DSToff, DSTmaybe
} DSTMODE;
%}
%union {
Tcl_WideInt Number;
enum _MERIDIAN Meridian;
}
%{
/*
* Prototypes of internal functions.
*/
static int LookupWord(YYSTYPE* yylvalPtr, char *buff);
static void TclDateerror(YYLTYPE* location,
DateInfo* info, const char *s);
static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
DateInfo* info);
MODULE_SCOPE int yyparse(DateInfo*);
%}
%token tAGO
%token tDAY
%token tDAYZONE
%token tID
%token tMERIDIAN
%token tMONTH
%token tMONTH_UNIT
%token tSTARDATE
%token tSEC_UNIT
%token tUNUMBER
%token tZONE
%token tZONEwO4
%token tZONEwO2
%token tEPOCH
%token tDST
%token tISOBAS8
%token tISOBAS6
%token tISOBASL
%token tDAY_UNIT
%token tNEXT
%token SP
%type <Number> tDAY
%type <Number> tDAYZONE
%type <Number> tMONTH
%type <Number> tMONTH_UNIT
%type <Number> tDST
%type <Number> tSEC_UNIT
%type <Number> tUNUMBER
%type <Number> INTNUM
%type <Number> tZONE
%type <Number> tZONEwO4
%type <Number> tZONEwO2
%type <Number> tISOBAS8
%type <Number> tISOBAS6
%type <Number> tISOBASL
%type <Number> tDAY_UNIT
%type <Number> unit
%type <Number> sign
%type <Number> tNEXT
%type <Number> tSTARDATE
%type <Meridian> tMERIDIAN
%type <Meridian> o_merid
%%
spec : /* NULL */
| spec item
/* | spec SP item */
;
item : time {
yyIncrFlags(CLF_TIME);
}
| zone {
yyIncrFlags(CLF_ZONE);
}
| date {
yyIncrFlags(CLF_HAVEDATE);
}
| ordMonth {
yyIncrFlags(CLF_ORDINALMONTH);
}
| day {
yyIncrFlags(CLF_DAYOFWEEK);
}
| relspec {
info->flags |= CLF_RELCONV;
}
| iso {
yyIncrFlags(CLF_TIME|CLF_HAVEDATE);
}
| trek {
yyIncrFlags(CLF_TIME|CLF_HAVEDATE);
info->flags |= CLF_RELCONV;
}
| numitem
;
iextime : tUNUMBER ':' tUNUMBER ':' tUNUMBER {
yyHour = $1;
yyMinutes = $3;
yySeconds = $5;
}
| tUNUMBER ':' tUNUMBER {
yyHour = $1;
yyMinutes = $3;
yySeconds = 0;
}
;
time : tUNUMBER tMERIDIAN {
yyHour = $1;
yyMinutes = 0;
yySeconds = 0;
yyMeridian = $2;
}
| iextime o_merid {
yyMeridian = $2;
}
;
zone : tZONE tDST {
yyTimezone = $1;
yyDSTmode = DSTon;
}
| tZONE {
yyTimezone = $1;
yyDSTmode = DSToff;
}
| tDAYZONE {
yyTimezone = $1;
yyDSTmode = DSTon;
}
| tZONEwO4 sign INTNUM { /* GMT+0100, GMT-1000, etc. */
yyTimezone = $1 - $2*($3 % 100 + ($3 / 100) * 60);
yyDSTmode = DSToff;
}
| tZONEwO2 sign INTNUM { /* GMT+1, GMT-10, etc. */
yyTimezone = $1 - $2*($3 * 60);
yyDSTmode = DSToff;
}
| sign INTNUM { /* +0100, -0100 */
yyTimezone = -$1*($2 % 100 + ($2 / 100) * 60);
yyDSTmode = DSToff;
}
;
comma : ','
| ',' SP
;
day : tDAY {
yyDayOrdinal = 1;
yyDayOfWeek = $1;
}
| tDAY comma {
yyDayOrdinal = 1;
yyDayOfWeek = $1;
}
| tUNUMBER tDAY {
yyDayOrdinal = $1;
yyDayOfWeek = $2;
}
| sign SP tUNUMBER tDAY {
yyDayOrdinal = $1 * $3;
yyDayOfWeek = $4;
}
| sign tUNUMBER tDAY {
yyDayOrdinal = $1 * $2;
yyDayOfWeek = $3;
}
| tNEXT tDAY {
yyDayOrdinal = 2;
yyDayOfWeek = $2;
}
;
iexdate : tUNUMBER '-' tUNUMBER '-' tUNUMBER {
yyMonth = $3;
yyDay = $5;
yyYear = $1;
}
;
date : tUNUMBER '/' tUNUMBER {
yyMonth = $1;
yyDay = $3;
}
| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
yyMonth = $1;
yyDay = $3;
yyYear = $5;
}
| isodate
| tUNUMBER '-' tMONTH '-' tUNUMBER {
yyDay = $1;
yyMonth = $3;
yyYear = $5;
}
| tMONTH tUNUMBER {
yyMonth = $1;
yyDay = $2;
}
| tMONTH tUNUMBER comma tUNUMBER {
yyMonth = $1;
yyDay = $2;
yyYear = $4;
}
| tUNUMBER tMONTH {
yyMonth = $2;
yyDay = $1;
|
| ︙ | ︙ | |||
362 363 364 365 366 367 368 |
yyMonth = $2;
yyDay = $1;
yyYear = $3;
}
;
ordMonth: tNEXT tMONTH {
| | | | | | < > | | | | < < < | < < < < > > | < < < < | | | > > > | > > > > > > > > > | | | > > > | | | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
yyMonth = $2;
yyDay = $1;
yyYear = $3;
}
;
ordMonth: tNEXT tMONTH {
yyMonthOrdinalIncr = 1;
yyMonthOrdinal = $2;
}
| tNEXT tUNUMBER tMONTH {
yyMonthOrdinalIncr = $2;
yyMonthOrdinal = $3;
}
;
isosep : 'T'|SP
;
isodate : tISOBAS8 { /* YYYYMMDD */
yyYear = $1 / 10000;
yyMonth = ($1 % 10000)/100;
yyDay = $1 % 100;
}
| tISOBAS6 { /* YYMMDD */
yyYear = $1 / 10000;
yyMonth = ($1 % 10000)/100;
yyDay = $1 % 100;
}
| iexdate
;
isotime : tISOBAS6 {
yyHour = $1 / 10000;
yyMinutes = ($1 % 10000)/100;
yySeconds = $1 % 100;
}
| iextime
;
iso : isodate isosep isotime
| tISOBASL tISOBAS6 { /* YYYYMMDDhhmmss */
yyYear = $1 / 10000;
yyMonth = ($1 % 10000)/100;
yyDay = $1 % 100;
yyHour = $2 / 10000;
yyMinutes = ($2 % 10000)/100;
yySeconds = $2 % 100;
}
| tISOBASL tUNUMBER { /* YYYYMMDDhhmm */
if (yyDigitCount != 4) YYABORT; /* normally unreached */
yyYear = $1 / 10000;
yyMonth = ($1 % 10000)/100;
yyDay = $1 % 100;
yyHour = $2 / 100;
yyMinutes = ($2 % 100);
yySeconds = 0;
}
;
trek : tSTARDATE INTNUM '.' tUNUMBER {
/*
* Offset computed year by -377 so that the returned years will be
* in a range accessible with a 32 bit clock seconds value.
*/
yyYear = $2/1000 + 2323 - 377;
yyDay = 1;
yyMonth = 1;
yyRelDay += (($2%1000)*(365 + IsLeapYear(yyYear)))/1000;
yyRelSeconds += $4 * (144LL * 60LL);
}
;
relspec : relunits tAGO {
yyRelSeconds *= -1;
yyRelMonth *= -1;
yyRelDay *= -1;
}
| relunits
;
relunits : sign SP INTNUM unit {
*yyRelPointer += $1 * $3 * $4;
}
| sign INTNUM unit {
*yyRelPointer += $1 * $2 * $3;
}
| INTNUM unit {
*yyRelPointer += $1 * $2;
}
| tNEXT unit {
*yyRelPointer += $2;
}
| tNEXT INTNUM unit {
*yyRelPointer += $2 * $3;
}
| unit {
*yyRelPointer += $1;
}
;
|
| ︙ | ︙ | |||
470 471 472 473 474 475 476 |
}
| tMONTH_UNIT {
$$ = $1;
yyRelPointer = &yyRelMonth;
}
;
| | > > > > > > > > > | > > | | 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 |
}
| tMONTH_UNIT {
$$ = $1;
yyRelPointer = &yyRelMonth;
}
;
INTNUM : tUNUMBER {
$$ = $1;
}
| tISOBAS6 {
$$ = $1;
}
| tISOBAS8 {
$$ = $1;
}
;
numitem : tUNUMBER {
if ((info->flags & (CLF_TIME|CLF_HAVEDATE|CLF_RELCONV)) == (CLF_TIME|CLF_HAVEDATE)) {
yyYear = $1;
} else {
yyIncrFlags(CLF_TIME);
if (yyDigitCount <= 2) {
yyHour = $1;
yyMinutes = 0;
} else {
yyHour = $1 / 100;
yyMinutes = $1 % 100;
}
|
| ︙ | ︙ | |||
559 560 561 562 563 564 565 |
{ "tomorrow", tDAY_UNIT, 1 },
{ "yesterday", tDAY_UNIT, -1 },
{ "today", tDAY_UNIT, 0 },
{ "now", tSEC_UNIT, 0 },
{ "last", tUNUMBER, -1 },
{ "this", tSEC_UNIT, 0 },
{ "next", tNEXT, 1 },
| < < < < < < < < < < < < < < | 536 537 538 539 540 541 542 543 544 545 546 547 548 549 |
{ "tomorrow", tDAY_UNIT, 1 },
{ "yesterday", tDAY_UNIT, -1 },
{ "today", tDAY_UNIT, 0 },
{ "now", tSEC_UNIT, 0 },
{ "last", tUNUMBER, -1 },
{ "this", tSEC_UNIT, 0 },
{ "next", tNEXT, 1 },
{ "ago", tAGO, 1 },
{ "epoch", tEPOCH, 0 },
{ "stardate", tSTARDATE, 0 },
{ NULL, 0, 0 }
};
/*
|
| ︙ | ︙ | |||
672 673 674 675 676 677 678 |
};
/*
* Military timezone table.
*/
static const TABLE MilitaryTable[] = {
| | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > | | | | | | | | | | 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 |
};
/*
* Military timezone table.
*/
static const TABLE MilitaryTable[] = {
{ "a", tZONE, -HOUR( 1) },
{ "b", tZONE, -HOUR( 2) },
{ "c", tZONE, -HOUR( 3) },
{ "d", tZONE, -HOUR( 4) },
{ "e", tZONE, -HOUR( 5) },
{ "f", tZONE, -HOUR( 6) },
{ "g", tZONE, -HOUR( 7) },
{ "h", tZONE, -HOUR( 8) },
{ "i", tZONE, -HOUR( 9) },
{ "k", tZONE, -HOUR(10) },
{ "l", tZONE, -HOUR(11) },
{ "m", tZONE, -HOUR(12) },
{ "n", tZONE, HOUR( 1) },
{ "o", tZONE, HOUR( 2) },
{ "p", tZONE, HOUR( 3) },
{ "q", tZONE, HOUR( 4) },
{ "r", tZONE, HOUR( 5) },
{ "s", tZONE, HOUR( 6) },
{ "t", tZONE, HOUR( 7) },
{ "u", tZONE, HOUR( 8) },
{ "v", tZONE, HOUR( 9) },
{ "w", tZONE, HOUR( 10) },
{ "x", tZONE, HOUR( 11) },
{ "y", tZONE, HOUR( 12) },
{ "z", tZONE, HOUR( 0) },
{ NULL, 0, 0 }
};
static inline const char *
bypassSpaces(
const char *s)
{
while (TclIsSpaceProc(*s)) {
s++;
}
return s;
}
/*
* Dump error messages in the bit bucket.
*/
static void
TclDateerror(
YYLTYPE* location,
DateInfo* infoPtr,
const char *s)
{
Tcl_Obj* t;
if (!infoPtr->messages) {
TclNewObj(infoPtr->messages);
}
Tcl_AppendToObj(infoPtr->messages, infoPtr->separatrix, -1);
Tcl_AppendToObj(infoPtr->messages, s, -1);
Tcl_AppendToObj(infoPtr->messages, " (characters ", -1);
TclNewIntObj(t, location->first_column);
Tcl_IncrRefCount(t);
Tcl_AppendObjToObj(infoPtr->messages, t);
Tcl_DecrRefCount(t);
Tcl_AppendToObj(infoPtr->messages, "-", -1);
TclNewIntObj(t, location->last_column);
Tcl_IncrRefCount(t);
Tcl_AppendObjToObj(infoPtr->messages, t);
Tcl_DecrRefCount(t);
Tcl_AppendToObj(infoPtr->messages, ")", -1);
infoPtr->separatrix = "\n";
}
int
ToSeconds(
int Hours,
int Minutes,
int Seconds,
MERIDIAN Meridian)
{
if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) {
return -1;
}
switch (Meridian) {
case MER24:
if (Hours < 0 || Hours > 23) {
return -1;
}
return (Hours * 60 + Minutes) * 60 + Seconds;
case MERam:
if (Hours < 1 || Hours > 12) {
return -1;
}
return ((Hours % 12) * 60 + Minutes) * 60 + Seconds;
case MERpm:
if (Hours < 1 || Hours > 12) {
return -1;
}
return (((Hours % 12) + 12) * 60 + Minutes) * 60 + Seconds;
}
return -1; /* Should never be reached */
}
static int
LookupWord(
YYSTYPE* yylvalPtr,
char *buff)
{
char *p;
char *q;
const TABLE *tp;
int i, abbrev;
/*
* Make it lowercase.
*/
Tcl_UtfToLower(buff);
if (*buff == 'a' && (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0)) {
yylvalPtr->Meridian = MERam;
return tMERIDIAN;
}
if (*buff == 'p' && (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0)) {
yylvalPtr->Meridian = MERpm;
return tMERIDIAN;
}
/*
* See if we have an abbreviation for a month.
*/
|
| ︙ | ︙ | |||
891 892 893 894 895 896 897 898 899 900 |
YYLTYPE* location,
DateInfo *info)
{
char c;
char *p;
char buff[20];
int Count;
location->first_column = yyInput - info->dateStart;
for ( ; ; ) {
| > | > > > | > > | | > > > | | > | > | > > > > > | | < > | > | > > > > | > > > | > < < | > > | < > | | | | > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < < | < < < < | | | | | | | < | | < < < < < < | < < < | < | | < > | < < < < | | > > > > > > > > > > > > > > > > | > | | > | < | < | > | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 |
YYLTYPE* location,
DateInfo *info)
{
char c;
char *p;
char buff[20];
int Count;
const char *tokStart;
location->first_column = yyInput - info->dateStart;
for ( ; ; ) {
if (isspace(UCHAR(*yyInput))) {
yyInput = bypassSpaces(yyInput);
/* ignore space at end of text and before some words */
c = *yyInput;
if (c != '\0' && !isalpha(UCHAR(c))) {
return SP;
}
}
tokStart = yyInput;
if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */
/*
* Count the number of digits.
*/
p = (char *)yyInput;
while (isdigit(UCHAR(*++p))) {};
yyDigitCount = p - yyInput;
/*
* A number with 12 or 14 digits is considered an ISO 8601 date.
*/
if (yyDigitCount == 14 || yyDigitCount == 12) {
/* long form of ISO 8601 (without separator), either
* YYYYMMDDhhmmss or YYYYMMDDhhmm, so reduce to date
* (8 chars is isodate) */
p = (char *)yyInput+8;
if (TclAtoWIe(&yylvalPtr->Number, yyInput, p, 1) != TCL_OK) {
return tID; /* overflow*/
}
yyDigitCount = 8;
yyInput = p;
location->last_column = yyInput - info->dateStart - 1;
return tISOBASL;
}
/*
* Convert the string into a number
*/
if (TclAtoWIe(&yylvalPtr->Number, yyInput, p, 1) != TCL_OK) {
return tID; /* overflow*/
}
yyInput = p;
/*
* A number with 6 or more digits is considered an ISO 8601 base.
*/
location->last_column = yyInput - info->dateStart - 1;
if (yyDigitCount >= 6) {
if (yyDigitCount == 8) {
return tISOBAS8;
}
if (yyDigitCount == 6) {
return tISOBAS6;
}
}
/* ignore spaces after digits (optional) */
yyInput = bypassSpaces(yyInput);
return tUNUMBER;
}
if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */
int ret;
for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */
|| c == '.'; ) {
if (p < &buff[sizeof(buff) - 1]) {
*p++ = c;
}
}
*p = '\0';
yyInput--;
location->last_column = yyInput - info->dateStart - 1;
ret = LookupWord(yylvalPtr, buff);
/*
* lookahead:
* for spaces to consider word boundaries (for instance
* literal T in isodateTisotimeZ is not a TZ, but Z is UTC);
* for +/- digit, to differentiate between "GMT+1000 day" and "GMT +1000 day";
* bypass spaces after token (but ignore by TZ+OFFS), because should
* recognize next SP token, if TZ only.
*/
if (ret == tZONE || ret == tDAYZONE) {
c = *yyInput;
if (isdigit(UCHAR(c))) { /* literal not a TZ */
yyInput = tokStart;
return *yyInput++;
}
if ((c == '+' || c == '-') && isdigit(UCHAR(*(yyInput+1)))) {
if ( !isdigit(UCHAR(*(yyInput+2)))
|| !isdigit(UCHAR(*(yyInput+3)))) {
/* GMT+1, GMT-10, etc. */
return tZONEwO2;
}
if ( isdigit(UCHAR(*(yyInput+4)))
&& !isdigit(UCHAR(*(yyInput+5)))) {
/* GMT+1000, etc. */
return tZONEwO4;
}
}
}
yyInput = bypassSpaces(yyInput);
return ret;
}
if (c != '(') {
location->last_column = yyInput - info->dateStart;
return *yyInput++;
}
Count = 0;
do {
c = *yyInput++;
if (c == '\0') {
location->last_column = yyInput - info->dateStart - 1;
return c;
} else if (c == '(') {
Count++;
} else if (c == ')') {
Count--;
}
} while (Count > 0);
}
}
int
TclClockFreeScan(
Tcl_Interp *interp, /* Tcl interpreter */
DateInfo *info) /* Input and result parameters */
{
int status;
#if YYDEBUG
/* enable debugging if compiled with YYDEBUG */
yydebug = 1;
#endif
/*
* yyInput = stringToParse;
*
* ClockInitDateInfo(info) should be executed to pre-init info;
*/
yyDSTmode = DSTmaybe;
info->separatrix = "";
info->dateStart = yyInput;
/* ignore spaces at begin */
yyInput = bypassSpaces(yyInput);
/* parse */
status = yyparse(info);
if (status == 1) {
const char *msg = NULL;
if (info->errFlags & CLF_HAVEDATE) {
msg = "more than one date in string";
} else if (info->errFlags & CLF_TIME) {
msg = "more than one time of day in string";
} else if (info->errFlags & CLF_ZONE) {
msg = "more than one time zone in string";
} else if (info->errFlags & CLF_DAYOFWEEK) {
msg = "more than one weekday in string";
} else if (info->errFlags & CLF_ORDINALMONTH) {
msg = "more than one ordinal month in string";
}
if (msg) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", (char *)NULL);
} else {
Tcl_SetObjResult(interp,
info->messages ? info->messages : Tcl_NewObj());
info->messages = NULL;
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", (char *)NULL);
}
status = TCL_ERROR;
} else if (status == 2) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
status = TCL_ERROR;
} else if (status != 0) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("Unknown status returned "
"from date parser. Please "
"report this error as a "
"bug in Tcl.", -1));
Tcl_SetErrorCode(interp, "TCL", "BUG", (char *)NULL);
status = TCL_ERROR;
}
if (info->messages) {
Tcl_DecrRefCount(info->messages);
}
return status;
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
|
Changes to generic/tclIO.c.
| ︙ | ︙ | |||
6303 6304 6305 6306 6307 6308 6309 | assert(bufPtr->nextPtr == NULL || BytesLeft(bufPtr->nextPtr) == 0 || (statePtr->inputEncodingFlags & TCL_ENCODING_END) == 0); code = Tcl_ExternalToUtf(NULL, encoding, src, srcLen, flags, &statePtr->inputEncodingState, dst, dstLimit, &srcRead, &dstDecoded, &numChars); | | | | 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 |
assert(bufPtr->nextPtr == NULL || BytesLeft(bufPtr->nextPtr) == 0
|| (statePtr->inputEncodingFlags & TCL_ENCODING_END) == 0);
code = Tcl_ExternalToUtf(NULL, encoding, src, srcLen,
flags, &statePtr->inputEncodingState,
dst, dstLimit, &srcRead, &dstDecoded, &numChars);
if (code == TCL_CONVERT_UNKNOWN || code == TCL_CONVERT_SYNTAX
|| (code == TCL_CONVERT_MULTIBYTE && GotFlag(statePtr, CHANNEL_EOF))) {
SetFlag(statePtr, CHANNEL_ENCODING_ERROR);
code = TCL_OK;
}
/*
* Perform the translation transformation in place. Read no more than
* the dstDecoded bytes the encoding transformation actually produced.
|
| ︙ | ︙ |
Changes to generic/tclIOCmd.c.
| ︙ | ︙ | |||
465 466 467 468 469 470 471 |
* If requested, remove the last newline in the channel if at EOF.
*/
if ((charactersRead > 0) && (newline != 0)) {
const char *result;
Tcl_Size length;
| | | 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 |
* If requested, remove the last newline in the channel if at EOF.
*/
if ((charactersRead > 0) && (newline != 0)) {
const char *result;
Tcl_Size length;
result = TclGetStringFromObj(resultPtr, &length);
if (result[length - 1] == '\n') {
Tcl_SetObjLength(resultPtr, length - 1);
}
}
Tcl_SetObjResult(interp, resultPtr);
TclChannelRelease(chan);
return TCL_OK;
|
| ︙ | ︙ | |||
711 712 713 714 715 716 717 |
const char *string;
Tcl_Size len;
if (Tcl_IsShared(resultPtr)) {
resultPtr = Tcl_DuplicateObj(resultPtr);
Tcl_SetObjResult(interp, resultPtr);
}
| | | 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 |
const char *string;
Tcl_Size len;
if (Tcl_IsShared(resultPtr)) {
resultPtr = Tcl_DuplicateObj(resultPtr);
Tcl_SetObjResult(interp, resultPtr);
}
string = TclGetStringFromObj(resultPtr, &len);
if ((len > 0) && (string[len - 1] == '\n')) {
Tcl_SetObjLength(resultPtr, len - 1);
}
return TCL_ERROR;
}
return TCL_OK;
|
| ︙ | ︙ | |||
996 997 998 999 1000 1001 1002 |
/*
* If the last character of the result is a newline, then remove the
* newline character.
*/
if (keepNewline == 0) {
| | | 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 |
/*
* If the last character of the result is a newline, then remove the
* newline character.
*/
if (keepNewline == 0) {
string = TclGetStringFromObj(resultPtr, &length);
if ((length > 0) && (string[length - 1] == '\n')) {
Tcl_SetObjLength(resultPtr, length - 1);
}
}
Tcl_SetObjResult(interp, resultPtr);
return result;
|
| ︙ | ︙ |
Changes to generic/tclIORChan.c.
| ︙ | ︙ | |||
2015 2016 2017 2018 2019 2020 2021 |
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"Expected list with even number of "
"elements, got %" TCL_SIZE_MODIFIER "d element%s instead", listc,
(listc == 1 ? "" : "s")));
goto error;
} else {
Tcl_Size len;
| | | 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 |
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"Expected list with even number of "
"elements, got %" TCL_SIZE_MODIFIER "d element%s instead", listc,
(listc == 1 ? "" : "s")));
goto error;
} else {
Tcl_Size len;
const char *str = TclGetStringFromObj(resObj, &len);
if (len) {
TclDStringAppendLiteral(dsPtr, " ");
Tcl_DStringAppend(dsPtr, str, len);
}
goto ok;
}
|
| ︙ | ︙ | |||
2450 2451 2452 2453 2454 2455 2456 |
*
* This is complex and ugly, and would be completely unnecessary
* if we only added support for a TCL_FORBID_EXCEPTIONS flag.
*/
if (result != TCL_ERROR) {
Tcl_Size cmdLen;
| | | 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 |
*
* This is complex and ugly, and would be completely unnecessary
* if we only added support for a TCL_FORBID_EXCEPTIONS flag.
*/
if (result != TCL_ERROR) {
Tcl_Size cmdLen;
const char *cmdString = TclGetStringFromObj(cmd, &cmdLen);
Tcl_IncrRefCount(cmd);
Tcl_ResetResult(rcPtr->interp);
Tcl_SetObjResult(rcPtr->interp, Tcl_ObjPrintf(
"chan handler returned bad code: %d", result));
Tcl_LogCommandInfo(rcPtr->interp, cmdString, cmdString,
cmdLen);
|
| ︙ | ︙ | |||
3325 3326 3327 3328 3329 3330 3331 |
snprintf(buf, 200,
"{Expected list with even number of elements, got %" TCL_SIZE_MODIFIER "d %s instead}",
listc, (listc == 1 ? "element" : "elements"));
ForwardSetDynamicError(paramPtr, buf);
} else {
Tcl_Size len;
| | | 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 |
snprintf(buf, 200,
"{Expected list with even number of elements, got %" TCL_SIZE_MODIFIER "d %s instead}",
listc, (listc == 1 ? "element" : "elements"));
ForwardSetDynamicError(paramPtr, buf);
} else {
Tcl_Size len;
const char *str = TclGetStringFromObj(resObj, &len);
if (len) {
TclDStringAppendLiteral(paramPtr->getOpt.value, " ");
Tcl_DStringAppend(paramPtr->getOpt.value, str, len);
}
}
}
|
| ︙ | ︙ | |||
3437 3438 3439 3440 3441 3442 3443 |
static void
ForwardSetObjError(
ForwardParam *paramPtr,
Tcl_Obj *obj)
{
Tcl_Size len;
| | | 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 |
static void
ForwardSetObjError(
ForwardParam *paramPtr,
Tcl_Obj *obj)
{
Tcl_Size len;
const char *msgStr = TclGetStringFromObj(obj, &len);
len++;
ForwardSetDynamicError(paramPtr, Tcl_Alloc(len));
memcpy(paramPtr->base.msgStr, msgStr, len);
}
#endif
|
| ︙ | ︙ |
Changes to generic/tclIORTrans.c.
| ︙ | ︙ | |||
2002 2003 2004 2005 2006 2007 2008 |
*
* This is complex and ugly, and would be completely unnecessary
* if we only added support for a TCL_FORBID_EXCEPTIONS flag.
*/
if (result != TCL_ERROR) {
Tcl_Obj *cmd = Tcl_NewListObj(cmdc, rtPtr->argv);
Tcl_Size cmdLen;
| | | 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 |
*
* This is complex and ugly, and would be completely unnecessary
* if we only added support for a TCL_FORBID_EXCEPTIONS flag.
*/
if (result != TCL_ERROR) {
Tcl_Obj *cmd = Tcl_NewListObj(cmdc, rtPtr->argv);
Tcl_Size cmdLen;
const char *cmdString = TclGetStringFromObj(cmd, &cmdLen);
Tcl_IncrRefCount(cmd);
Tcl_ResetResult(rtPtr->interp);
Tcl_SetObjResult(rtPtr->interp, Tcl_ObjPrintf(
"chan handler returned bad code: %d", result));
Tcl_LogCommandInfo(rtPtr->interp, cmdString, cmdString, cmdLen);
Tcl_DecrRefCount(cmd);
|
| ︙ | ︙ | |||
2768 2769 2770 2771 2772 2773 2774 |
static void
ForwardSetObjError(
ForwardParam *paramPtr,
Tcl_Obj *obj)
{
Tcl_Size len;
| | | 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 |
static void
ForwardSetObjError(
ForwardParam *paramPtr,
Tcl_Obj *obj)
{
Tcl_Size len;
const char *msgStr = TclGetStringFromObj(obj, &len);
len++;
ForwardSetDynamicError(paramPtr, Tcl_Alloc(len));
memcpy(paramPtr->base.msgStr, msgStr, len);
}
#endif /* TCL_THREADS */
|
| ︙ | ︙ |
Changes to generic/tclIOUtil.c.
| ︙ | ︙ | |||
520 521 522 523 524 525 526 |
if (tsdPtr->cwdPathPtr == *pathPtrPtr) {
return 1;
} else {
Tcl_Size len1, len2;
const char *str1, *str2;
| | | | 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 |
if (tsdPtr->cwdPathPtr == *pathPtrPtr) {
return 1;
} else {
Tcl_Size len1, len2;
const char *str1, *str2;
str1 = TclGetStringFromObj(tsdPtr->cwdPathPtr, &len1);
str2 = TclGetStringFromObj(*pathPtrPtr, &len2);
if ((len1 == len2) && !memcmp(str1, str2, len1)) {
/*
* The values are equal but the objects are different. Cache the
* current structure in place of the old one.
*/
Tcl_DecrRefCount(*pathPtrPtr);
|
| ︙ | ︙ | |||
664 665 666 667 668 669 670 |
void *clientData)
{
Tcl_Size len = 0;
const char *str = NULL;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
if (cwdObj != NULL) {
| | | 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 |
void *clientData)
{
Tcl_Size len = 0;
const char *str = NULL;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
if (cwdObj != NULL) {
str = TclGetStringFromObj(cwdObj, &len);
}
Tcl_MutexLock(&cwdMutex);
if (cwdPathPtr != NULL) {
Tcl_DecrRefCount(cwdPathPtr);
}
if (cwdClientData != NULL) {
|
| ︙ | ︙ | |||
1155 1156 1157 1158 1159 1160 1161 |
* i.e. the representation relative to pathPtr.
*/
norm = Tcl_FSGetNormalizedPath(NULL, pathPtr);
if (norm != NULL) {
const char *path, *mount;
| | | | 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 |
* i.e. the representation relative to pathPtr.
*/
norm = Tcl_FSGetNormalizedPath(NULL, pathPtr);
if (norm != NULL) {
const char *path, *mount;
mount = TclGetStringFromObj(mElt, &mlen);
path = TclGetStringFromObj(norm, &len);
if (path[len-1] == '/') {
/*
* Deal with the root of the volume.
*/
len--;
}
|
| ︙ | ︙ | |||
1334 1335 1336 1337 1338 1339 1340 |
* are reserved for VFS use. These names can not conflict with real UNC
* pathnames per https://msdn.microsoft.com/en-us/library/gg465305.aspx and
* rfc3986's definition of reg-name.
*
* We check these first to avoid useless calls to the native filesystem's
* normalizePathProc.
*/
| | | 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 |
* are reserved for VFS use. These names can not conflict with real UNC
* pathnames per https://msdn.microsoft.com/en-us/library/gg465305.aspx and
* rfc3986's definition of reg-name.
*
* We check these first to avoid useless calls to the native filesystem's
* normalizePathProc.
*/
path = TclGetStringFromObj(pathPtr, &i);
if ((i >= 3) && ((path[0] == '/' && path[1] == '/')
|| (path[0] == '\\' && path[1] == '\\'))) {
for (i = 2; ; i++) {
if (path[i] == '\0') {
break;
}
|
| ︙ | ︙ | |||
1776 1777 1778 1779 1780 1781 1782 |
goto end;
}
iPtr = (Interp *) interp;
oldScriptFile = iPtr->scriptFile;
iPtr->scriptFile = pathPtr;
Tcl_IncrRefCount(iPtr->scriptFile);
| | | 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 |
goto end;
}
iPtr = (Interp *) interp;
oldScriptFile = iPtr->scriptFile;
iPtr->scriptFile = pathPtr;
Tcl_IncrRefCount(iPtr->scriptFile);
string = TclGetStringFromObj(objPtr, &length);
/*
* TIP #280: Open a frame for the evaluated script.
*/
iPtr->evalFlags |= TCL_EVAL_FILE;
result = TclEvalEx(interp, string, length, 0, 1, NULL, string);
|
| ︙ | ︙ | |||
1803 1804 1805 1806 1807 1808 1809 |
if (result == TCL_RETURN) {
result = TclUpdateReturnInfo(iPtr);
} else if (result == TCL_ERROR) {
/*
* Record information about where the error occurred.
*/
| | | 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 |
if (result == TCL_RETURN) {
result = TclUpdateReturnInfo(iPtr);
} else if (result == TCL_ERROR) {
/*
* Record information about where the error occurred.
*/
const char *pathString = TclGetStringFromObj(pathPtr, &length);
int limit = 150;
int overflow = (length > limit);
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (file \"%.*s%s\" line %d)",
(overflow ? limit : (int)length), pathString,
(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
|
| ︙ | ︙ | |||
1956 1957 1958 1959 1960 1961 1962 |
result = TclUpdateReturnInfo(iPtr);
} else if (result == TCL_ERROR) {
/*
* Record information about where the error occurred.
*/
Tcl_Size length;
| | | 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 |
result = TclUpdateReturnInfo(iPtr);
} else if (result == TCL_ERROR) {
/*
* Record information about where the error occurred.
*/
Tcl_Size length;
const char *pathString = TclGetStringFromObj(pathPtr, &length);
const int limit = 150;
int overflow = (length > limit);
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (file \"%.*s%s\" line %d)",
(overflow ? limit : (int)length), pathString,
(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
|
| ︙ | ︙ | |||
2806 2807 2808 2809 2810 2811 2812 | * calling 'Tcl_FSEqualPaths', and in addition avoid a nasty * infinite loop bug when trying to normalize tsdPtr->cwdPathPtr. */ Tcl_Size len1, len2; const char *str1, *str2; | | | | 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 |
* calling 'Tcl_FSEqualPaths', and in addition avoid a nasty
* infinite loop bug when trying to normalize tsdPtr->cwdPathPtr.
*/
Tcl_Size len1, len2;
const char *str1, *str2;
str1 = TclGetStringFromObj(tsdPtr->cwdPathPtr, &len1);
str2 = TclGetStringFromObj(norm, &len2);
if ((len1 == len2) && (strcmp(str1, str2) == 0)) {
/*
* The pathname values are equal so retain the old pathname
* object which is probably already shared and free the
* normalized pathname that was just produced.
*/
cdEqual:
|
| ︙ | ︙ | |||
3908 3909 3910 3911 3912 3913 3914 |
* length of the volume name. */
Tcl_Obj **driveNameRef) /* If not NULL, for an absolute pathname, a
* place to store a pointer to an object with a
* refCount of 1, and whose value is the name
* of the volume. */
{
Tcl_Size pathLen;
| | | 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 |
* length of the volume name. */
Tcl_Obj **driveNameRef) /* If not NULL, for an absolute pathname, a
* place to store a pointer to an object with a
* refCount of 1, and whose value is the name
* of the volume. */
{
Tcl_Size pathLen;
const char *path = TclGetStringFromObj(pathPtr, &pathLen);
Tcl_PathType type;
type = TclFSNonnativePathType(path, pathLen, filesystemPtrPtr,
driveNameLengthPtr, driveNameRef);
if (type != TCL_PATH_ABSOLUTE) {
type = TclpGetNativePathType(pathPtr, driveNameLengthPtr,
|
| ︙ | ︙ | |||
4015 4016 4017 4018 4019 4020 4021 |
while (numVolumes > 0) {
Tcl_Obj *vol;
Tcl_Size len;
const char *strVol;
numVolumes--;
Tcl_ListObjIndex(NULL, thisFsVolumes, numVolumes, &vol);
| | | 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 |
while (numVolumes > 0) {
Tcl_Obj *vol;
Tcl_Size len;
const char *strVol;
numVolumes--;
Tcl_ListObjIndex(NULL, thisFsVolumes, numVolumes, &vol);
strVol = TclGetStringFromObj(vol,&len);
if (pathLen < len) {
continue;
}
if (strncmp(strVol, path, len) == 0) {
type = TCL_PATH_ABSOLUTE;
if (filesystemPtrPtr != NULL) {
*filesystemPtrPtr = fsRecPtr->fsPtr;
|
| ︙ | ︙ | |||
4375 4376 4377 4378 4379 4380 4381 |
Tcl_Obj *cwdPtr = Tcl_FSGetCwd(NULL);
if (cwdPtr != NULL) {
const char *cwdStr, *normPathStr;
Tcl_Size cwdLen, normLen;
Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr);
if (normPath != NULL) {
| | | | 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 |
Tcl_Obj *cwdPtr = Tcl_FSGetCwd(NULL);
if (cwdPtr != NULL) {
const char *cwdStr, *normPathStr;
Tcl_Size cwdLen, normLen;
Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr);
if (normPath != NULL) {
normPathStr = TclGetStringFromObj(normPath, &normLen);
cwdStr = TclGetStringFromObj(cwdPtr, &cwdLen);
if ((cwdLen >= normLen) && (strncmp(normPathStr, cwdStr,
normLen) == 0)) {
/*
* The cwd is inside the directory to be removed. Change
* the cwd to [file dirname $path].
*/
|
| ︙ | ︙ |
Changes to generic/tclInt.h.
| ︙ | ︙ | |||
3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 | MODULE_SCOPE void TclDeleteNamespaceVars(Namespace *nsPtr); MODULE_SCOPE void TclDeleteNamespaceChildren(Namespace *nsPtr); MODULE_SCOPE Tcl_Size TclDictGetSize(Tcl_Obj *dictPtr); MODULE_SCOPE int TclFindDictElement(Tcl_Interp *interp, const char *dict, Tcl_Size dictLength, const char **elementPtr, const char **nextPtr, Tcl_Size *sizePtr, int *literalPtr); /* TIP #280 - Modified token based evaluation, with line information. */ MODULE_SCOPE int TclEvalEx(Tcl_Interp *interp, const char *script, Tcl_Size numBytes, int flags, Tcl_Size line, Tcl_Size *clNextOuter, const char *outerScript); MODULE_SCOPE Tcl_ObjCmdProc2 TclFileAttrsCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclFileCopyCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclFileDeleteCmd; | > | 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 | MODULE_SCOPE void TclDeleteNamespaceVars(Namespace *nsPtr); MODULE_SCOPE void TclDeleteNamespaceChildren(Namespace *nsPtr); MODULE_SCOPE Tcl_Size TclDictGetSize(Tcl_Obj *dictPtr); MODULE_SCOPE int TclFindDictElement(Tcl_Interp *interp, const char *dict, Tcl_Size dictLength, const char **elementPtr, const char **nextPtr, Tcl_Size *sizePtr, int *literalPtr); MODULE_SCOPE Tcl_Obj * TclDictObjSmartRef(Tcl_Interp *interp, Tcl_Obj *); /* TIP #280 - Modified token based evaluation, with line information. */ MODULE_SCOPE int TclEvalEx(Tcl_Interp *interp, const char *script, Tcl_Size numBytes, int flags, Tcl_Size line, Tcl_Size *clNextOuter, const char *outerScript); MODULE_SCOPE Tcl_ObjCmdProc2 TclFileAttrsCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclFileCopyCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclFileDeleteCmd; |
| ︙ | ︙ | |||
4512 4513 4514 4515 4516 4517 4518 | * string handling. The macro's expression result is 1 for the 1-byte case or * the result of Tcl_UtfToUniChar. The ANSI C "prototype" for this macro is: * * MODULE_SCOPE int TclUtfToUniChar(const char *string, Tcl_UniChar *ch); *---------------------------------------------------------------- */ | < < < < < < < | 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 | * string handling. The macro's expression result is 1 for the 1-byte case or * the result of Tcl_UtfToUniChar. The ANSI C "prototype" for this macro is: * * MODULE_SCOPE int TclUtfToUniChar(const char *string, Tcl_UniChar *ch); *---------------------------------------------------------------- */ #define TclUtfToUniChar(str, chPtr) \ (((UCHAR(*(str))) < 0x80) ? \ ((*(chPtr) = UCHAR(*(str))), 1) \ : Tcl_UtfToUniChar(str, chPtr)) /* *---------------------------------------------------------------- * Macro counterpart of the Tcl_NumUtfChars() function. To be used in speed- * -sensitive points where it pays to avoid a function call in the common case * of counting along a string of all one-byte characters. The ANSI C * "prototype" for this macro is: |
| ︙ | ︙ |
Changes to generic/tclInterp.c.
| ︙ | ︙ | |||
4533 4534 4535 4536 4537 4538 4539 |
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
switch (index) {
case OPT_CMD:
scriptObj = objv[i+1];
| | | | 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 |
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
switch (index) {
case OPT_CMD:
scriptObj = objv[i+1];
(void) TclGetStringFromObj(scriptObj, &scriptLen);
break;
case OPT_GRAN:
granObj = objv[i+1];
if (TclGetIntFromObj(interp, objv[i+1], &gran) != TCL_OK) {
return TCL_ERROR;
}
if (gran < 1) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"granularity must be at least 1", -1));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
"BADVALUE", (void *)NULL);
return TCL_ERROR;
}
break;
case OPT_VAL:
limitObj = objv[i+1];
(void) TclGetStringFromObj(objv[i+1], &limitLen);
if (limitLen == 0) {
break;
}
if (TclGetIntFromObj(interp, objv[i+1], &limit) != TCL_OK) {
return TCL_ERROR;
}
if (limit < 0) {
|
| ︙ | ︙ | |||
4741 4742 4743 4744 4745 4746 4747 |
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
switch (index) {
case OPT_CMD:
scriptObj = objv[i+1];
| | | | | 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 |
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
switch (index) {
case OPT_CMD:
scriptObj = objv[i+1];
(void) TclGetStringFromObj(objv[i+1], &scriptLen);
break;
case OPT_GRAN:
granObj = objv[i+1];
if (TclGetIntFromObj(interp, objv[i+1], &gran) != TCL_OK) {
return TCL_ERROR;
}
if (gran < 1) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"granularity must be at least 1", -1));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
"BADVALUE", (void *)NULL);
return TCL_ERROR;
}
break;
case OPT_MILLI:
milliObj = objv[i+1];
(void) TclGetStringFromObj(objv[i+1], &milliLen);
if (milliLen == 0) {
break;
}
if (TclGetWideIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
return TCL_ERROR;
}
if (tmp < 0) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"milliseconds must be non-negative", -1));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
"BADVALUE", (void *)NULL);
return TCL_ERROR;
}
limitMoment.usec = tmp*1000;
break;
case OPT_SEC:
secObj = objv[i+1];
(void) TclGetStringFromObj(objv[i+1], &secLen);
if (secLen == 0) {
break;
}
if (TclGetWideIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
return TCL_ERROR;
}
if (tmp < 0) {
|
| ︙ | ︙ |
Changes to generic/tclLink.c.
| ︙ | ︙ | |||
566 567 568 569 570 571 572 |
TCL_UNUSED(Tcl_Interp *),
Tcl_Obj *objPtr)
{
const char *str;
const char *endPtr;
Tcl_Size length;
| | | 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 |
TCL_UNUSED(Tcl_Interp *),
Tcl_Obj *objPtr)
{
const char *str;
const char *endPtr;
Tcl_Size length;
str = TclGetStringFromObj(objPtr, &length);
if ((length == 1) && (str[0] == '.')) {
objPtr->typePtr = &invalidRealType;
objPtr->internalRep.doubleValue = 0.0;
return TCL_OK;
}
if (TclParseNumber(NULL, objPtr, NULL, str, length, &endPtr,
TCL_PARSE_DECIMAL_ONLY) == TCL_OK) {
|
| ︙ | ︙ | |||
611 612 613 614 615 616 617 |
static int
GetInvalidIntFromObj(
Tcl_Obj *objPtr,
int *intPtr)
{
Tcl_Size length;
| | | 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 |
static int
GetInvalidIntFromObj(
Tcl_Obj *objPtr,
int *intPtr)
{
Tcl_Size length;
const char *str = TclGetStringFromObj(objPtr, &length);
if ((length == 0) || ((length == 2) && (str[0] == '0')
&& strchr("xXbBoOdD", str[1]))) {
*intPtr = 0;
return TCL_OK;
} else if ((length == 1) && strchr("+-", str[0])) {
*intPtr = (str[0] == '+');
|
| ︙ | ︙ | |||
820 821 822 823 824 825 826 |
/*
* Special cases.
*/
switch (linkPtr->type) {
case TCL_LINK_STRING:
| | | | 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 |
/*
* Special cases.
*/
switch (linkPtr->type) {
case TCL_LINK_STRING:
value = TclGetStringFromObj(valueObj, &valueLength);
pp = (char **) linkPtr->addr;
*pp = (char *)Tcl_Realloc(*pp, ++valueLength);
memcpy(*pp, value, valueLength);
return NULL;
case TCL_LINK_CHARS:
value = (char *) TclGetStringFromObj(valueObj, &valueLength);
valueLength++; /* include end of string char */
if (valueLength > linkPtr->bytes) {
return (char *) "wrong size of char* value";
}
if (linkPtr->flags & LINK_ALLOC_LAST) {
memcpy(linkPtr->lastValue.aryPtr, value, valueLength);
memcpy(linkPtr->addr, value, valueLength);
|
| ︙ | ︙ |
Changes to generic/tclLiteral.c.
| ︙ | ︙ | |||
207 208 209 210 211 212 213 | * Literals should always have UTF-8 representations... but this * is not guaranteed so we need to be careful anyway. * * https://stackoverflow.com/q/54337750/301832 */ Tcl_Size objLength; | | | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
* Literals should always have UTF-8 representations... but this
* is not guaranteed so we need to be careful anyway.
*
* https://stackoverflow.com/q/54337750/301832
*/
Tcl_Size objLength;
const char *objBytes = TclGetStringFromObj(objPtr, &objLength);
if ((objLength == length) && ((length == 0)
|| ((objBytes[0] == bytes[0])
&& (memcmp(objBytes, bytes, length) == 0)))) {
/*
* A literal was found: return it
*/
|
| ︙ | ︙ | |||
513 514 515 516 517 518 519 |
{
Interp *iPtr = (Interp *) interp;
LiteralTable *globalTablePtr = &iPtr->literalTable;
LiteralEntry *entryPtr;
const char *bytes;
size_t globalHash, length;
| | | 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 |
{
Interp *iPtr = (Interp *) interp;
LiteralTable *globalTablePtr = &iPtr->literalTable;
LiteralEntry *entryPtr;
const char *bytes;
size_t globalHash, length;
bytes = TclGetStringFromObj(objPtr, &length);
globalHash = (HashString(bytes, length) & globalTablePtr->mask);
for (entryPtr=globalTablePtr->buckets[globalHash] ; entryPtr!=NULL;
entryPtr=entryPtr->nextPtr) {
if (entryPtr->objPtr == objPtr) {
return entryPtr;
}
}
|
| ︙ | ︙ | |||
575 576 577 578 579 580 581 |
*/
newObjPtr = Tcl_DuplicateObj(lPtr->objPtr);
Tcl_IncrRefCount(newObjPtr);
TclReleaseLiteral(interp, lPtr->objPtr);
lPtr->objPtr = newObjPtr;
| | | 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 |
*/
newObjPtr = Tcl_DuplicateObj(lPtr->objPtr);
Tcl_IncrRefCount(newObjPtr);
TclReleaseLiteral(interp, lPtr->objPtr);
lPtr->objPtr = newObjPtr;
bytes = TclGetStringFromObj(newObjPtr, &length);
localHash = HashString(bytes, length) & localTablePtr->mask;
nextPtrPtr = &localTablePtr->buckets[localHash];
for (entryPtr=*nextPtrPtr ; entryPtr!=NULL ; entryPtr=*nextPtrPtr) {
if (entryPtr == lPtr) {
*nextPtrPtr = lPtr->nextPtr;
lPtr->nextPtr = NULL;
|
| ︙ | ︙ | |||
712 713 714 715 716 717 718 |
if (localPtr->objPtr == objPtr) {
found = 1;
}
}
}
if (!found) {
| | | 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 |
if (localPtr->objPtr == objPtr) {
found = 1;
}
}
}
if (!found) {
bytes = TclGetStringFromObj(objPtr, &length);
Tcl_Panic("%s: literal \"%.*s\" wasn't found locally",
"AddLocalLiteralEntry", (length>60? 60 : (int)length), bytes);
}
}
#endif /*TCL_COMPILE_DEBUG*/
return objIndex;
|
| ︙ | ︙ | |||
842 843 844 845 846 847 848 |
Tcl_Size length;
if (iPtr == NULL) {
goto done;
}
globalTablePtr = &iPtr->literalTable;
| | | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 |
Tcl_Size length;
if (iPtr == NULL) {
goto done;
}
globalTablePtr = &iPtr->literalTable;
bytes = TclGetStringFromObj(objPtr, &length);
index = HashString(bytes, length) & globalTablePtr->mask;
/*
* Check to see if the object is in the global literal table and remove
* this reference. The object may not be in the table if it is a hidden
* local literal.
*/
|
| ︙ | ︙ | |||
1015 1016 1017 1018 1019 1020 1021 |
/*
* Rehash all of the existing entries into the new bucket array.
*/
for (oldChainPtr=oldBuckets ; oldSize>0 ; oldSize--,oldChainPtr++) {
for (entryPtr=*oldChainPtr ; entryPtr!=NULL ; entryPtr=*oldChainPtr) {
| | | 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 |
/*
* Rehash all of the existing entries into the new bucket array.
*/
for (oldChainPtr=oldBuckets ; oldSize>0 ; oldSize--,oldChainPtr++) {
for (entryPtr=*oldChainPtr ; entryPtr!=NULL ; entryPtr=*oldChainPtr) {
bytes = TclGetStringFromObj(entryPtr->objPtr, &length);
index = (HashString(bytes, length) & tablePtr->mask);
*oldChainPtr = entryPtr->nextPtr;
bucketPtr = &tablePtr->buckets[index];
entryPtr->nextPtr = *bucketPtr;
*bucketPtr = entryPtr;
}
|
| ︙ | ︙ | |||
1186 1187 1188 1189 1190 1191 1192 |
size_t i, length, count = 0;
for (i=0 ; i<localTablePtr->numBuckets ; i++) {
for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL;
localPtr=localPtr->nextPtr) {
count++;
if (localPtr->refCount != TCL_INDEX_NONE) {
| | | 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 |
size_t i, length, count = 0;
for (i=0 ; i<localTablePtr->numBuckets ; i++) {
for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL;
localPtr=localPtr->nextPtr) {
count++;
if (localPtr->refCount != TCL_INDEX_NONE) {
bytes = TclGetStringFromObj(localPtr->objPtr, &length);
Tcl_Panic("%s: local literal \"%.*s\" had bad refCount %" TCL_Z_MODIFIER "u",
"TclVerifyLocalLiteralTable",
(length>60? 60 : (int) length), bytes, localPtr->refCount);
}
if (localPtr->objPtr->bytes == NULL) {
Tcl_Panic("%s: literal has NULL string rep",
"TclVerifyLocalLiteralTable");
|
| ︙ | ︙ | |||
1235 1236 1237 1238 1239 1240 1241 |
size_t i, length, count = 0;
for (i=0 ; i<globalTablePtr->numBuckets ; i++) {
for (globalPtr=globalTablePtr->buckets[i] ; globalPtr!=NULL;
globalPtr=globalPtr->nextPtr) {
count++;
if (globalPtr->refCount + 1 < 2) {
| | | 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 |
size_t i, length, count = 0;
for (i=0 ; i<globalTablePtr->numBuckets ; i++) {
for (globalPtr=globalTablePtr->buckets[i] ; globalPtr!=NULL;
globalPtr=globalPtr->nextPtr) {
count++;
if (globalPtr->refCount + 1 < 2) {
bytes = TclGetStringFromObj(globalPtr->objPtr, &length);
Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %" TCL_Z_MODIFIER "u",
"TclVerifyGlobalLiteralTable",
(length>60? 60 : (int)length), bytes, globalPtr->refCount);
}
if (globalPtr->objPtr->bytes == NULL) {
Tcl_Panic("%s: literal has NULL string rep",
"TclVerifyGlobalLiteralTable");
|
| ︙ | ︙ |
Changes to generic/tclOODefineCmds.c.
| ︙ | ︙ | |||
767 768 769 770 771 772 773 |
Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_UNKNOWN", (void *)NULL);
return TCL_ERROR;
}
if (TclOOGetDefineCmdContext(interp) == NULL) {
return TCL_ERROR;
}
| | | 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 |
Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_UNKNOWN", (void *)NULL);
return TCL_ERROR;
}
if (TclOOGetDefineCmdContext(interp) == NULL) {
return TCL_ERROR;
}
soughtStr = TclGetStringFromObj(objv[1], &soughtLen);
if (soughtLen == 0) {
goto noMatch;
}
hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
while (hPtr != NULL) {
const char *nameStr = (const char *)Tcl_GetHashKey(&nsPtr->cmdTable, hPtr);
|
| ︙ | ︙ | |||
829 830 831 832 833 834 835 |
static Tcl_Command
FindCommand(
Tcl_Interp *interp,
Tcl_Obj *stringObj,
Tcl_Namespace *const namespacePtr)
{
Tcl_Size length;
| | | 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 |
static Tcl_Command
FindCommand(
Tcl_Interp *interp,
Tcl_Obj *stringObj,
Tcl_Namespace *const namespacePtr)
{
Tcl_Size length;
const char *nameStr, *string = TclGetStringFromObj(stringObj, &length);
Namespace *const nsPtr = (Namespace *) namespacePtr;
FOREACH_HASH_DECLS;
Tcl_Command cmd, cmd2;
/*
* If someone is playing games, we stop playing right now.
*/
|
| ︙ | ︙ | |||
1050 1051 1052 1053 1054 1055 1056 |
const char *typeOfSubject) /* Part of the message, saying whether it was
* an object, class or class-as-object that
* was being configured. */
{
Tcl_Size length;
Tcl_Obj *realNameObj = Tcl_ObjectDeleted((Tcl_Object) oPtr)
? savedNameObj : TclOOObjectName(interp, oPtr);
| | | 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 |
const char *typeOfSubject) /* Part of the message, saying whether it was
* an object, class or class-as-object that
* was being configured. */
{
Tcl_Size length;
Tcl_Obj *realNameObj = Tcl_ObjectDeleted((Tcl_Object) oPtr)
? savedNameObj : TclOOObjectName(interp, oPtr);
const char *objName = TclGetStringFromObj(realNameObj, &length);
int limit = OBJNAME_LENGTH_IN_ERRORINFO_LIMIT;
int overflow = (length > limit);
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (in definition script for %s \"%.*s%s\" line %d)",
typeOfSubject, (overflow ? limit : (int)length), objName,
(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
|
| ︙ | ︙ | |||
1602 1603 1604 1605 1606 1607 1608 |
oPtr = (Object *) TclOOGetDefineCmdContext(interp);
if (oPtr == NULL) {
return TCL_ERROR;
}
clsPtr = oPtr->classPtr;
| | | 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 |
oPtr = (Object *) TclOOGetDefineCmdContext(interp);
if (oPtr == NULL) {
return TCL_ERROR;
}
clsPtr = oPtr->classPtr;
(void)TclGetStringFromObj(objv[2], &bodyLength);
if (bodyLength > 0) {
/*
* Create the method structure.
*/
method = (Tcl_Method) TclOONewProcMethod(interp, clsPtr,
PUBLIC_METHOD, NULL, objv[1], objv[2], NULL);
|
| ︙ | ︙ | |||
1808 1809 1810 1811 1812 1813 1814 |
oPtr = (Object *) TclOOGetDefineCmdContext(interp);
if (oPtr == NULL) {
return TCL_ERROR;
}
clsPtr = oPtr->classPtr;
| | | 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 |
oPtr = (Object *) TclOOGetDefineCmdContext(interp);
if (oPtr == NULL) {
return TCL_ERROR;
}
clsPtr = oPtr->classPtr;
(void)TclGetStringFromObj(objv[1], &bodyLength);
if (bodyLength > 0) {
/*
* Create the method structure.
*/
method = (Tcl_Method) TclOONewProcMethod(interp, clsPtr,
PUBLIC_METHOD, NULL, NULL, objv[1], NULL);
|
| ︙ | ︙ |
Changes to generic/tclObj.c.
| ︙ | ︙ | |||
633 634 635 636 637 638 639 |
*/
/*
* First compute the range of the word within the script. (Is there a
* better way which doesn't shimmer?)
*/
| | | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 |
*/
/*
* First compute the range of the word within the script. (Is there a
* better way which doesn't shimmer?)
*/
(void)TclGetStringFromObj(objPtr, &length);
end = start + length; /* First char after the word */
/*
* Then compute the table slice covering the range of the word.
*/
while (*wordCLLast >= 0 && *wordCLLast < end) {
|
| ︙ | ︙ |
Changes to generic/tclParse.c.
| ︙ | ︙ | |||
922 923 924 925 926 927 928 |
* We have to convert here in case the user has put a backslash in
* front of a multi-byte utf-8 character. While this means nothing
* special, we shouldn't break up a correct utf-8 character. [Bug
* #217987] test subst-3.2
*/
if (Tcl_UtfCharComplete(p, numBytes - 1)) {
| | | | 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 |
* We have to convert here in case the user has put a backslash in
* front of a multi-byte utf-8 character. While this means nothing
* special, we shouldn't break up a correct utf-8 character. [Bug
* #217987] test subst-3.2
*/
if (Tcl_UtfCharComplete(p, numBytes - 1)) {
count = TclUtfToUniChar(p, &unichar) + 1; /* +1 for '\' */
} else {
char utfBytes[8];
memcpy(utfBytes, p, numBytes - 1);
utfBytes[numBytes - 1] = '\0';
count = TclUtfToUniChar(utfBytes, &unichar) + 1;
}
result = unichar;
break;
}
done:
if (readPtr != NULL) {
|
| ︙ | ︙ |
Changes to generic/tclPkg.c.
| ︙ | ︙ | |||
1179 1180 1181 1182 1183 1184 1185 |
Tcl_Free(argv3i);
return TCL_OK;
}
pkgPtr = (Package *)Tcl_GetHashValue(hPtr);
} else {
pkgPtr = FindPackage(interp, argv2);
}
| | | 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 |
Tcl_Free(argv3i);
return TCL_OK;
}
pkgPtr = (Package *)Tcl_GetHashValue(hPtr);
} else {
pkgPtr = FindPackage(interp, argv2);
}
argv3 = TclGetStringFromObj(objv[3], &length);
for (availPtr = pkgPtr->availPtr, prevPtr = NULL; availPtr != NULL;
prevPtr = availPtr, availPtr = availPtr->nextPtr) {
if (CheckVersionAndConvert(interp, availPtr->version, &avi,
NULL) != TCL_OK) {
Tcl_Free(argv3i);
return TCL_ERROR;
|
| ︙ | ︙ | |||
1226 1227 1228 1229 1230 1231 1232 |
pkgPtr->availPtr = availPtr;
} else {
availPtr->nextPtr = prevPtr->nextPtr;
prevPtr->nextPtr = availPtr;
}
}
if (iPtr->scriptFile) {
| | | | 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 |
pkgPtr->availPtr = availPtr;
} else {
availPtr->nextPtr = prevPtr->nextPtr;
prevPtr->nextPtr = availPtr;
}
}
if (iPtr->scriptFile) {
argv4 = TclGetStringFromObj(iPtr->scriptFile, &length);
DupBlock(availPtr->pkgIndex, argv4, length + 1);
}
argv4 = TclGetStringFromObj(objv[4], &length);
DupBlock(availPtr->script, argv4, length + 1);
break;
}
case PKG_NAMES:
if (objc != 2) {
Tcl_WrongNumArgs(interp, 2, objv, NULL);
return TCL_ERROR;
|
| ︙ | ︙ | |||
1406 1407 1408 1409 1410 1411 1412 |
Tcl_SetObjResult(interp,
Tcl_NewStringObj(iPtr->packageUnknown, -1));
}
} else if (objc == 3) {
if (iPtr->packageUnknown != NULL) {
Tcl_Free(iPtr->packageUnknown);
}
| | | 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 |
Tcl_SetObjResult(interp,
Tcl_NewStringObj(iPtr->packageUnknown, -1));
}
} else if (objc == 3) {
if (iPtr->packageUnknown != NULL) {
Tcl_Free(iPtr->packageUnknown);
}
argv2 = TclGetStringFromObj(objv[2], &length);
if (argv2[0] == 0) {
iPtr->packageUnknown = NULL;
} else {
DupBlock(iPtr->packageUnknown, argv2, length+1);
}
} else {
Tcl_WrongNumArgs(interp, 2, objv, "?command?");
|
| ︙ | ︙ | |||
2071 2072 2073 2074 2075 2076 2077 |
* available. */
{
Tcl_Obj *result = Tcl_GetObjResult(interp);
int i;
Tcl_Size length;
for (i = 0; i < reqc; i++) {
| | | 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 |
* available. */
{
Tcl_Obj *result = Tcl_GetObjResult(interp);
int i;
Tcl_Size length;
for (i = 0; i < reqc; i++) {
const char *v = TclGetStringFromObj(reqv[i], &length);
if ((length & 0x1) && (v[length/2] == '-')
&& (strncmp(v, v+((length+1)/2), length/2) == 0)) {
Tcl_AppendPrintfToObj(result, " exactly %s", v+((length+1)/2));
} else {
Tcl_AppendPrintfToObj(result, " %s", v);
}
|
| ︙ | ︙ |
Changes to generic/tclRegexp.c.
| ︙ | ︙ | |||
598 599 600 601 602 603 604 |
Tcl_Size length;
TclRegexp *regexpPtr;
const char *pattern;
RegexpGetInternalRep(objPtr, regexpPtr);
if ((regexpPtr == NULL) || (regexpPtr->flags != flags)) {
| | | 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 |
Tcl_Size length;
TclRegexp *regexpPtr;
const char *pattern;
RegexpGetInternalRep(objPtr, regexpPtr);
if ((regexpPtr == NULL) || (regexpPtr->flags != flags)) {
pattern = TclGetStringFromObj(objPtr, &length);
regexpPtr = CompileRegexp(interp, pattern, length, flags);
if (regexpPtr == NULL) {
return NULL;
}
RegexpSetInternalRep(objPtr, regexpPtr);
|
| ︙ | ︙ |
Changes to generic/tclResult.c.
| ︙ | ︙ | |||
355 356 357 358 359 360 361 |
Tcl_Obj *listPtr = Tcl_NewListObj(1, &elementPtr);
const char *bytes;
Tcl_Size length;
if (Tcl_IsShared(iPtr->objResultPtr)) {
Tcl_SetObjResult(interp, Tcl_DuplicateObj(iPtr->objResultPtr));
}
| | | 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
Tcl_Obj *listPtr = Tcl_NewListObj(1, &elementPtr);
const char *bytes;
Tcl_Size length;
if (Tcl_IsShared(iPtr->objResultPtr)) {
Tcl_SetObjResult(interp, Tcl_DuplicateObj(iPtr->objResultPtr));
}
bytes = TclGetStringFromObj(iPtr->objResultPtr, &length);
if (TclNeedSpace(bytes, bytes + length)) {
Tcl_AppendToObj(iPtr->objResultPtr, " ", 1);
}
Tcl_AppendObjToObj(iPtr->objResultPtr, listPtr);
Tcl_DecrRefCount(listPtr);
}
|
| ︙ | ︙ | |||
716 717 718 719 720 721 722 |
iPtr->errorInfo = NULL;
}
Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO],
&valuePtr);
if (valuePtr != NULL) {
Tcl_Size length;
| | | 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 |
iPtr->errorInfo = NULL;
}
Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO],
&valuePtr);
if (valuePtr != NULL) {
Tcl_Size length;
(void)TclGetStringFromObj(valuePtr, &length);
if (length) {
iPtr->errorInfo = valuePtr;
Tcl_IncrRefCount(iPtr->errorInfo);
iPtr->flags |= ERR_ALREADY_LOGGED;
}
}
Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORSTACK],
|
| ︙ | ︙ |
Changes to generic/tclScan.c.
| ︙ | ︙ | |||
898 899 900 901 902 903 904 | break; } case 'c': /* * Scan a single Unicode character. */ | | | 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 |
break;
}
case 'c':
/*
* Scan a single Unicode character.
*/
offset = TclUtfToUniChar(string, &i);
string += offset;
if (!(flags & SCAN_SUPPRESS)) {
TclNewIntObj(objPtr, i);
Tcl_IncrRefCount(objPtr);
CLANG_ASSERT(objs);
objs[objIndex++] = objPtr;
}
|
| ︙ | ︙ |
Added generic/tclStrIdxTree.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 |
/*
* tclStrIdxTree.c --
*
* Contains the routines for managing string index tries in Tcl.
*
* This code is back-ported from the tclSE engine, by Serg G. Brester.
*
* Copyright (c) 2016 by Sergey G. Brester aka sebres. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* -----------------------------------------------------------------------
*
* String index tries are prepaired structures used for fast greedy search of the string
* (index) by unique string prefix as key.
*
* Index tree build for two lists together can be explained in the following datagram
*
* Lists:
*
* {Januar Februar Maerz April Mai Juni Juli August September Oktober November Dezember}
* {Jnr Fbr Mrz Apr Mai Jni Jli Agt Spt Okt Nvb Dzb}
*
* Index-Tree:
*
* j 0 * ...
* anuar 1 *
* u 0 * a 0
* ni 6 * pril 4
* li 7 * ugust 8
* n 0 * gt 8
* r 1 * s 9
* i 6 * eptember 9
* li 7 * pt 9
* f 2 * oktober 10
* ebruar 2 * n 11
* br 2 * ovember 11
* m 0 * vb 11
* a 0 * d 12
* erz 3 * ezember 12
* i 5 * zb 12
* rz 3 *
* ...
*
* Thereby value 0 shows pure group items (corresponding ambigous matches).
* But the group may have a value if it contains only same values
* (see for example group "f" above).
*
* StrIdxTree's are very fast, so:
* build of above-mentioned tree takes about 10 microseconds.
* search of string index in this tree takes fewer as 0.1 microseconds.
*
*/
#include "tclInt.h"
#include "tclStrIdxTree.h"
/*
*----------------------------------------------------------------------
*
* TclStrIdxTreeSearch --
*
* Find largest part of string "start" in indexed tree (case sensitive).
*
* Also used for building of string index tree.
*
* Results:
* Return position of UTF character in start after last equal character
* and found item (with parent).
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
const char*
TclStrIdxTreeSearch(
TclStrIdxTree **foundParent, /* Return value of found sub tree (used for tree build) */
TclStrIdx **foundItem, /* Return value of found item */
TclStrIdxTree *tree, /* Index tree will be browsed */
const char *start, /* UTF string to find in tree */
const char *end) /* End of string */
{
TclStrIdxTree *parent = tree, *prevParent = tree;
TclStrIdx *item = tree->firstPtr, *prevItem = NULL;
const char *s = start, *f, *cin, *cinf, *prevf = NULL;
Tcl_Size offs = 0;
if (item == NULL) {
goto done;
}
/* search in tree */
do {
cinf = cin = TclGetString(item->key) + offs;
f = TclUtfFindEqualNCInLwr(s, end, cin, cin + item->length - offs, &cinf);
/* if something was found */
if (f > s) {
/* if whole string was found */
if (f >= end) {
start = f;
goto done;
};
/* set new offset and shift start string */
offs += cinf - cin;
s = f;
/* if match item, go deeper as long as possible */
if (offs >= item->length && item->childTree.firstPtr) {
/* save previuosly found item (if not ambigous) for
* possible fallback (few greedy match) */
if (item->value != NULL) {
prevf = f;
prevItem = item;
prevParent = parent;
}
parent = &item->childTree;
item = item->childTree.firstPtr;
continue;
}
/* no children - return this item and current chars found */
start = f;
goto done;
}
item = item->nextPtr;
} while (item != NULL);
/* fallback (few greedy match) not ambigous (has a value) */
if (prevItem != NULL) {
item = prevItem;
parent = prevParent;
start = prevf;
}
done:
if (foundParent)
*foundParent = parent;
if (foundItem)
*foundItem = item;
return start;
}
void
TclStrIdxTreeFree(
TclStrIdx *tree)
{
while (tree != NULL) {
TclStrIdx *t;
Tcl_DecrRefCount(tree->key);
if (tree->childTree.firstPtr != NULL) {
TclStrIdxTreeFree(tree->childTree.firstPtr);
}
t = tree, tree = tree->nextPtr;
Tcl_Free(t);
}
}
/*
* Several bidirectional list primitives
*/
static inline void
TclStrIdxTreeInsertBranch(
TclStrIdxTree *parent,
TclStrIdx *item,
TclStrIdx *child)
{
if (parent->firstPtr == child)
parent->firstPtr = item;
if (parent->lastPtr == child)
parent->lastPtr = item;
if ( (item->nextPtr = child->nextPtr) ) {
item->nextPtr->prevPtr = item;
child->nextPtr = NULL;
}
if ( (item->prevPtr = child->prevPtr) ) {
item->prevPtr->nextPtr = item;
child->prevPtr = NULL;
}
item->childTree.firstPtr = child;
item->childTree.lastPtr = child;
}
static inline void
TclStrIdxTreeAppend(
TclStrIdxTree *parent,
TclStrIdx *item)
{
if (parent->lastPtr != NULL) {
parent->lastPtr->nextPtr = item;
}
item->prevPtr = parent->lastPtr;
item->nextPtr = NULL;
parent->lastPtr = item;
if (parent->firstPtr == NULL) {
parent->firstPtr = item;
}
}
/*
*----------------------------------------------------------------------
*
* TclStrIdxTreeBuildFromList --
*
* Build or extend string indexed tree from tcl list.
* If the values not given the values of built list are indices starts with 1.
* Value of 0 is thereby reserved to the ambigous values.
*
* Important: by multiple lists, optimal tree can be created only if list with
* larger strings used firstly.
*
* Results:
* Returns a standard Tcl result.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TclStrIdxTreeBuildFromList(
TclStrIdxTree *idxTree,
Tcl_Size lstc,
Tcl_Obj **lstv,
void **values)
{
Tcl_Obj **lwrv;
Tcl_Size i;
int ret = TCL_ERROR;
void *val;
const char *s, *e, *f;
TclStrIdx *item;
/* create lowercase reflection of the list keys */
lwrv = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj*) * lstc);
if (lwrv == NULL) {
return TCL_ERROR;
}
for (i = 0; i < lstc; i++) {
lwrv[i] = Tcl_DuplicateObj(lstv[i]);
if (lwrv[i] == NULL) {
return TCL_ERROR;
}
Tcl_IncrRefCount(lwrv[i]);
lwrv[i]->length = Tcl_UtfToLower(TclGetString(lwrv[i]));
}
/* build index tree of the list keys */
for (i = 0; i < lstc; i++) {
TclStrIdxTree *foundParent = idxTree;
e = s = TclGetString(lwrv[i]);
e += lwrv[i]->length;
val = values ? values[i] : INT2PTR(i+1);
/* ignore empty keys (impossible to index it) */
if (lwrv[i]->length == 0) continue;
item = NULL;
if (idxTree->firstPtr != NULL) {
TclStrIdx *foundItem;
f = TclStrIdxTreeSearch(&foundParent, &foundItem,
idxTree, s, e);
/* if common prefix was found */
if (f > s) {
/* ignore element if fulfilled or ambigous */
if (f == e) {
continue;
}
/* if shortest key was found with the same value,
* just replace its current key with longest key */
if ( foundItem->value == val
&& foundItem->length <= lwrv[i]->length
&& foundItem->length <= (f - s) /* only if found item is covered in full */
&& foundItem->childTree.firstPtr == NULL
) {
TclSetObjRef(foundItem->key, lwrv[i]);
foundItem->length = lwrv[i]->length;
continue;
}
/* split tree (e. g. j->(jan,jun) + jul == j->(jan,ju->(jun,jul)) )
* but don't split by fulfilled child of found item ( ii->iii->iiii ) */
if (foundItem->length != (f - s)) {
/* first split found item (insert one between parent and found + new one) */
item = (TclStrIdx *)Tcl_Alloc(sizeof(TclStrIdx));
if (item == NULL) {
goto done;
}
TclInitObjRef(item->key, foundItem->key);
item->length = f - s;
/* set value or mark as ambigous if not the same value of both */
item->value = (foundItem->value == val) ? val : NULL;
/* insert group item between foundParent and foundItem */
TclStrIdxTreeInsertBranch(foundParent, item, foundItem);
foundParent = &item->childTree;
} else {
/* the new item should be added as child of found item */
foundParent = &foundItem->childTree;
}
}
}
/* append item at end of found parent */
item = (TclStrIdx *)Tcl_Alloc(sizeof(TclStrIdx));
if (item == NULL) {
goto done;
}
item->childTree.lastPtr = item->childTree.firstPtr = NULL;
TclInitObjRef(item->key, lwrv[i]);
item->length = lwrv[i]->length;
item->value = val;
TclStrIdxTreeAppend(foundParent, item);
};
ret = TCL_OK;
done:
if (lwrv != NULL) {
for (i = 0; i < lstc; i++) {
Tcl_DecrRefCount(lwrv[i]);
}
Tcl_Free(lwrv);
}
if (ret != TCL_OK) {
if (idxTree->firstPtr != NULL) {
TclStrIdxTreeFree(idxTree->firstPtr);
}
}
return ret;
}
static void
StrIdxTreeObj_DupIntRepProc(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void
StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr);
static void
StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr);
Tcl_ObjType StrIdxTreeObjType = {
"str-idx-tree", /* name */
StrIdxTreeObj_FreeIntRepProc, /* freeIntRepProc */
StrIdxTreeObj_DupIntRepProc, /* dupIntRepProc */
StrIdxTreeObj_UpdateStringProc, /* updateStringProc */
NULL, /* setFromAnyProc */
TCL_OBJTYPE_V0
};
Tcl_Obj*
TclStrIdxTreeNewObj()
{
Tcl_Obj *objPtr = Tcl_NewObj();
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = &StrIdxTreeObjType;
/* return tree root in internal representation */
return objPtr;
}
static void
StrIdxTreeObj_DupIntRepProc(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)
{
/* follow links (smart pointers) */
if ( srcPtr->internalRep.twoPtrValue.ptr1 != NULL
&& srcPtr->internalRep.twoPtrValue.ptr2 == NULL
) {
srcPtr = (Tcl_Obj*)srcPtr->internalRep.twoPtrValue.ptr1;
}
/* create smart pointer to it (ptr1 != NULL, ptr2 = NULL) */
TclInitObjRef(*((Tcl_Obj **)©Ptr->internalRep.twoPtrValue.ptr1),
srcPtr);
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
copyPtr->typePtr = &StrIdxTreeObjType;
}
static void
StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr)
{
/* follow links (smart pointers) */
if ( objPtr->internalRep.twoPtrValue.ptr1 != NULL
&& objPtr->internalRep.twoPtrValue.ptr2 == NULL
) {
/* is a link */
TclUnsetObjRef(*((Tcl_Obj **)&objPtr->internalRep.twoPtrValue.ptr1));
} else {
/* is a tree */
TclStrIdxTree *tree = (TclStrIdxTree*)&objPtr->internalRep.twoPtrValue.ptr1;
if (tree->firstPtr != NULL) {
TclStrIdxTreeFree(tree->firstPtr);
}
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
}
objPtr->typePtr = NULL;
};
static void
StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr)
{
/* currently only dummy empty string possible */
objPtr->length = 0;
objPtr->bytes = &tclEmptyString;
};
TclStrIdxTree *
TclStrIdxTreeGetFromObj(Tcl_Obj *objPtr) {
/* follow links (smart pointers) */
if (objPtr->typePtr != &StrIdxTreeObjType) {
return NULL;
}
if ( objPtr->internalRep.twoPtrValue.ptr1 != NULL
&& objPtr->internalRep.twoPtrValue.ptr2 == NULL
) {
objPtr = (Tcl_Obj*)objPtr->internalRep.twoPtrValue.ptr1;
}
/* return tree root in internal representation */
return (TclStrIdxTree*)&objPtr->internalRep.twoPtrValue.ptr1;
}
/*
* Several debug primitives
*/
#if 0
/* currently unused, debug resp. test purposes only */
static void
TclStrIdxTreePrint(
Tcl_Interp *interp,
TclStrIdx *tree,
int offs)
{
Tcl_Obj *obj[2];
const char *s;
TclInitObjRef(obj[0], Tcl_NewStringObj("::puts", -1));
while (tree != NULL) {
s = TclGetString(tree->key) + offs;
TclInitObjRef(obj[1], Tcl_ObjPrintf("%*s%.*s\t:%d",
offs, "", tree->length - offs, s, tree->value));
Tcl_PutsObjCmd(NULL, interp, 2, obj);
TclUnsetObjRef(obj[1]);
if (tree->childTree.firstPtr != NULL) {
TclStrIdxTreePrint(interp, tree->childTree.firstPtr, tree->length);
}
tree = tree->nextPtr;
}
TclUnsetObjRef(obj[0]);
}
int
TclStrIdxTreeTestObjCmd(
ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[])
{
const char *cs, *cin, *ret;
static const char *const options[] = {
"index", "puts-index", "findequal",
NULL
};
enum optionInd {
O_INDEX, O_PUTS_INDEX, O_FINDEQUAL
};
int optionIndex;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], options,
"option", 0, &optionIndex) != TCL_OK) {
Tcl_SetErrorCode(interp, "CLOCK", "badOption",
Tcl_GetString(objv[1]), (char *)NULL);
return TCL_ERROR;
}
switch (optionIndex) {
case O_FINDEQUAL:
if (objc < 4) {
Tcl_WrongNumArgs(interp, 1, objv, "");
return TCL_ERROR;
}
cs = TclGetString(objv[2]);
cin = TclGetString(objv[3]);
ret = TclUtfFindEqual(
cs, cs + objv[1]->length, cin, cin + objv[2]->length);
Tcl_SetObjResult(interp, Tcl_NewIntObj(ret - cs));
break;
case O_INDEX:
case O_PUTS_INDEX: {
Tcl_Obj **lstv;
int i, lstc;
TclStrIdxTree idxTree = {NULL, NULL};
i = 1;
while (++i < objc) {
if (TclListObjGetElements(interp, objv[i],
&lstc, &lstv) != TCL_OK) {
return TCL_ERROR;
};
TclStrIdxTreeBuildFromList(&idxTree, lstc, lstv, NULL);
}
if (optionIndex == O_PUTS_INDEX) {
TclStrIdxTreePrint(interp, idxTree.firstPtr, 0);
}
TclStrIdxTreeFree(idxTree.firstPtr);
}
break;
}
return TCL_OK;
}
#endif
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
|
Added generic/tclStrIdxTree.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
/*
* tclStrIdxTree.h --
*
* Declarations of string index tries and other primitives currently
* back-ported from tclSE.
*
* Copyright (c) 2016 Serg G. Brester (aka sebres)
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef _TCLSTRIDXTREE_H
#define _TCLSTRIDXTREE_H
/*
* Main structures declarations of index tree and entry
*/
typedef struct TclStrIdxTree {
struct TclStrIdx *firstPtr;
struct TclStrIdx *lastPtr;
} TclStrIdxTree;
typedef struct TclStrIdx {
struct TclStrIdxTree childTree;
struct TclStrIdx *nextPtr;
struct TclStrIdx *prevPtr;
Tcl_Obj *key;
Tcl_Size length;
void *value;
} TclStrIdx;
/*
*----------------------------------------------------------------------
*
* TclUtfFindEqual, TclUtfFindEqualNC --
*
* Find largest part of string cs in string cin (case sensitive and not).
*
* Results:
* Return position of UTF character in cs after last equal character.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static inline const char *
TclUtfFindEqual(
const char *cs, /* UTF string to find in cin. */
const char *cse, /* End of cs */
const char *cin, /* UTF string will be browsed. */
const char *cine) /* End of cin */
{
const char *ret = cs;
Tcl_UniChar ch1, ch2;
do {
cs += TclUtfToUniChar(cs, &ch1);
cin += TclUtfToUniChar(cin, &ch2);
if (ch1 != ch2) break;
} while ((ret = cs) < cse && cin < cine);
return ret;
}
static inline const char *
TclUtfFindEqualNC(
const char *cs, /* UTF string to find in cin. */
const char *cse, /* End of cs */
const char *cin, /* UTF string will be browsed. */
const char *cine, /* End of cin */
const char **cinfnd) /* Return position in cin */
{
const char *ret = cs;
Tcl_UniChar ch1, ch2;
do {
cs += TclUtfToUniChar(cs, &ch1);
cin += TclUtfToUniChar(cin, &ch2);
if (ch1 != ch2) {
ch1 = Tcl_UniCharToLower(ch1);
ch2 = Tcl_UniCharToLower(ch2);
if (ch1 != ch2) break;
}
*cinfnd = cin;
} while ((ret = cs) < cse && cin < cine);
return ret;
}
static inline const char *
TclUtfFindEqualNCInLwr(
const char *cs, /* UTF string (in anycase) to find in cin. */
const char *cse, /* End of cs */
const char *cin, /* UTF string (in lowercase) will be browsed. */
const char *cine, /* End of cin */
const char **cinfnd) /* Return position in cin */
{
const char *ret = cs;
Tcl_UniChar ch1, ch2;
do {
cs += TclUtfToUniChar(cs, &ch1);
cin += TclUtfToUniChar(cin, &ch2);
if (ch1 != ch2) {
ch1 = Tcl_UniCharToLower(ch1);
if (ch1 != ch2) break;
}
*cinfnd = cin;
} while ((ret = cs) < cse && cin < cine);
return ret;
}
/*
* Primitives to safe set, reset and free references.
*/
#define TclUnsetObjRef(obj) \
do { \
if (obj != NULL) { \
Tcl_DecrRefCount(obj); \
obj = NULL; \
} \
} while (0)
#define TclInitObjRef(obj, val) \
do { \
obj = val; \
if (obj) { \
Tcl_IncrRefCount(obj); \
} \
} while (0)
#define TclSetObjRef(obj, val) \
do { \
Tcl_Obj *nval = val; \
if (obj != nval) { \
Tcl_Obj *prev = obj; \
TclInitObjRef(obj, nval); \
if (prev != NULL) { \
Tcl_DecrRefCount(prev); \
}; \
} \
} while (0)
/*
* Prototypes of module functions.
*/
MODULE_SCOPE const char*
TclStrIdxTreeSearch(TclStrIdxTree **foundParent,
TclStrIdx **foundItem, TclStrIdxTree *tree,
const char *start, const char *end);
MODULE_SCOPE int TclStrIdxTreeBuildFromList(TclStrIdxTree *idxTree,
Tcl_Size lstc, Tcl_Obj **lstv, void **values);
MODULE_SCOPE Tcl_Obj*
TclStrIdxTreeNewObj();
MODULE_SCOPE TclStrIdxTree*
TclStrIdxTreeGetFromObj(Tcl_Obj *objPtr);
#if 0
/* currently unused, debug resp. test purposes only */
MODULE_SCOPE Tcl_ObjCmdProc2 TclStrIdxTreeTestObjCmd;
#endif
#endif /* _TCLSTRIDXTREE_H */
|
Changes to generic/tclStringObj.c.
| ︙ | ︙ | |||
614 615 616 617 618 619 620 |
Tcl_Size numChars = TclNumUtfChars(objPtr->bytes, objPtr->length);
if (index >= numChars) {
return -1;
}
const char *begin = TclUtfAtIndex(objPtr->bytes, index);
| < | | 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 |
Tcl_Size numChars = TclNumUtfChars(objPtr->bytes, objPtr->length);
if (index >= numChars) {
return -1;
}
const char *begin = TclUtfAtIndex(objPtr->bytes, index);
TclUtfToUniChar(begin, &ch);
return ch;
}
/*
*----------------------------------------------------------------------
*
* Tcl_GetUnicodeFromObj/TclGetUnicodeFromObj --
|
| ︙ | ︙ | |||
1470 1471 1472 1473 1474 1475 1476 |
if (TclHasInternalRep(appendObjPtr, &tclStringType)) {
Tcl_UniChar *unicode =
Tcl_GetUnicodeFromObj(appendObjPtr, &numChars);
AppendUnicodeToUnicodeRep(objPtr, unicode, numChars);
} else {
| | | | 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 |
if (TclHasInternalRep(appendObjPtr, &tclStringType)) {
Tcl_UniChar *unicode =
Tcl_GetUnicodeFromObj(appendObjPtr, &numChars);
AppendUnicodeToUnicodeRep(objPtr, unicode, numChars);
} else {
bytes = TclGetStringFromObj(appendObjPtr, &length);
AppendUtfToUnicodeRep(objPtr, bytes, length);
}
return;
}
/*
* Append to objPtr's UTF string rep. If we know the number of characters
* in both objects before appending, then set the combined number of
* characters in the final (appended-to) object.
*/
bytes = TclGetStringFromObj(appendObjPtr, &length);
numChars = stringPtr->numChars;
if ((numChars >= 0) && TclHasInternalRep(appendObjPtr, &tclStringType)) {
String *appendStringPtr = GET_STRING(appendObjPtr);
appendNumChars = appendStringPtr->numChars;
}
|
| ︙ | ︙ | |||
1861 1862 1863 1864 1865 1866 1867 |
"\"%n$\" argument index out of range"
};
static const char *overflow = "max size for a Tcl value exceeded";
if (Tcl_IsShared(appendObj)) {
Tcl_Panic("%s called with shared object", "Tcl_AppendFormatToObj");
}
| | | 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 |
"\"%n$\" argument index out of range"
};
static const char *overflow = "max size for a Tcl value exceeded";
if (Tcl_IsShared(appendObj)) {
Tcl_Panic("%s called with shared object", "Tcl_AppendFormatToObj");
}
(void)TclGetStringFromObj(appendObj, &originalLength);
limit = TCL_SIZE_MAX - originalLength;
/*
* Format string is NUL-terminated.
*/
while (*format != '\0') {
|
| ︙ | ︙ | |||
2289 2290 2291 2292 2293 2294 2295 |
#endif
} else if (useBig) {
pure = Tcl_NewBignumObj(&big);
} else {
TclNewIntObj(pure, l);
}
Tcl_IncrRefCount(pure);
| | | 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 |
#endif
} else if (useBig) {
pure = Tcl_NewBignumObj(&big);
} else {
TclNewIntObj(pure, l);
}
Tcl_IncrRefCount(pure);
bytes = TclGetStringFromObj(pure, &length);
/*
* Already did the sign above.
*/
if (*bytes == '-') {
length--;
|
| ︙ | ︙ | |||
2575 2576 2577 2578 2579 2580 2581 |
}
while (numChars < width) {
Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1);
numChars++;
}
}
| | | 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 |
}
while (numChars < width) {
Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1);
numChars++;
}
}
(void)TclGetStringFromObj(segment, &segmentNumBytes);
if (segmentNumBytes > limit) {
if (allocSegment) {
Tcl_DecrRefCount(segment);
}
msg = overflow;
errCode = "OVERFLOW";
goto errorMsg;
|
| ︙ | ︙ | |||
2958 2959 2960 2961 2962 2963 2964 |
TclGetStringStorage(
Tcl_Obj *objPtr,
Tcl_Size *sizePtr)
{
String *stringPtr;
if (!TclHasInternalRep(objPtr, &tclStringType) || objPtr->bytes == NULL) {
| | | 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 |
TclGetStringStorage(
Tcl_Obj *objPtr,
Tcl_Size *sizePtr)
{
String *stringPtr;
if (!TclHasInternalRep(objPtr, &tclStringType) || objPtr->bytes == NULL) {
return TclGetStringFromObj(objPtr, sizePtr);
}
stringPtr = GET_STRING(objPtr);
*sizePtr = stringPtr->allocated;
return objPtr->bytes;
}
|
| ︙ | ︙ | |||
3024 3025 3026 3027 3028 3029 3030 |
maxCount = TCL_SIZE_MAX;
} else if (unichar) {
/* Result will be pure Tcl_UniChar array. Pre-size it. */
(void)Tcl_GetUnicodeFromObj(objPtr, &length);
maxCount = TCL_SIZE_MAX/sizeof(Tcl_UniChar);
} else {
/* Result will be concat of string reps. Pre-size it. */
| | | 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 |
maxCount = TCL_SIZE_MAX;
} else if (unichar) {
/* Result will be pure Tcl_UniChar array. Pre-size it. */
(void)Tcl_GetUnicodeFromObj(objPtr, &length);
maxCount = TCL_SIZE_MAX/sizeof(Tcl_UniChar);
} else {
/* Result will be concat of string reps. Pre-size it. */
(void)TclGetStringFromObj(objPtr, &length);
maxCount = TCL_SIZE_MAX;
}
if (length == 0) {
/* Any repeats of empty is empty. */
return objPtr;
}
|
| ︙ | ︙ | |||
3284 3285 3286 3287 3288 3289 3290 |
Tcl_Obj *objPtr = *ov++;
if (objPtr->bytes == NULL
&& TclCheckEmptyString(objPtr) != TCL_EMPTYSTRING_YES) {
/* No string rep; Take the chance we can avoid making it */
pendingPtr = objPtr;
} else {
| | | 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 |
Tcl_Obj *objPtr = *ov++;
if (objPtr->bytes == NULL
&& TclCheckEmptyString(objPtr) != TCL_EMPTYSTRING_YES) {
/* No string rep; Take the chance we can avoid making it */
pendingPtr = objPtr;
} else {
(void) TclGetStringFromObj(objPtr, &length); /* PANIC? */
}
} while (--oc && (length == 0) && (pendingPtr == NULL));
/*
* Either we found a possibly non-empty value, and we remember
* this index as the first and last such value so far seen,
* or (oc == 0) and all values are known empty,
|
| ︙ | ︙ | |||
3308 3309 3310 3311 3312 3313 3314 |
* There's a pending value followed by more values. Loop over
* remaining values generating strings until a non-empty value
* is found, or the pending value gets its string generated.
*/
do {
Tcl_Obj *objPtr = *ov++;
| | | | 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 |
* There's a pending value followed by more values. Loop over
* remaining values generating strings until a non-empty value
* is found, or the pending value gets its string generated.
*/
do {
Tcl_Obj *objPtr = *ov++;
(void)TclGetStringFromObj(objPtr, &numBytes); /* PANIC? */
} while (--oc && numBytes == 0 && pendingPtr->bytes == NULL);
if (numBytes) {
last = objc -oc -1;
}
if (oc || numBytes) {
(void)TclGetStringFromObj(pendingPtr, &length);
}
if (length == 0) {
if (numBytes) {
first = last;
}
} else if (numBytes > (TCL_SIZE_MAX - length)) {
goto overflow;
|
| ︙ | ︙ | |||
3449 3450 3451 3452 3453 3454 3455 |
char *dst;
if (inPlace) {
Tcl_Size start;
objResultPtr = *objv++; objc--;
| | | 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 |
char *dst;
if (inPlace) {
Tcl_Size start;
objResultPtr = *objv++; objc--;
(void)TclGetStringFromObj(objResultPtr, &start);
if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"concatenation failed: unable to alloc %" TCL_SIZE_MODIFIER "d bytes",
length));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL);
}
|
| ︙ | ︙ | |||
3481 3482 3483 3484 3485 3486 3487 |
dst = TclGetString(objResultPtr);
}
while (objc--) {
Tcl_Obj *objPtr = *objv++;
if ((objPtr->bytes == NULL) || (objPtr->length)) {
Tcl_Size more;
| | | 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 |
dst = TclGetString(objResultPtr);
}
while (objc--) {
Tcl_Obj *objPtr = *objv++;
if ((objPtr->bytes == NULL) || (objPtr->length)) {
Tcl_Size more;
char *src = TclGetStringFromObj(objPtr, &more);
memcpy(dst, src, more);
dst += more;
}
}
/* Must NUL-terminate! */
*dst = '\0';
|
| ︙ | ︙ | |||
3714 3715 3716 3717 3718 3719 3720 |
}
}
} else {
empty = TclCheckEmptyString(value1Ptr);
if (empty > 0) {
switch (TclCheckEmptyString(value2Ptr)) {
case -1:
| | | | | | | | 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 |
}
}
} else {
empty = TclCheckEmptyString(value1Ptr);
if (empty > 0) {
switch (TclCheckEmptyString(value2Ptr)) {
case -1:
s1 = "";
s1len = 0;
s2 = TclGetStringFromObj(value2Ptr, &s2len);
break;
case 0:
match = -1;
goto matchdone;
case 1:
default: /* avoid warn: `s2` may be used uninitialized */
match = 0;
goto matchdone;
}
} else if (TclCheckEmptyString(value2Ptr) > 0) {
switch (empty) {
case -1:
s2 = "";
s2len = 0;
s1 = TclGetStringFromObj(value1Ptr, &s1len);
break;
case 0:
match = 1;
goto matchdone;
case 1:
default: /* avoid warn: `s1` may be used uninitialized */
match = 0;
goto matchdone;
}
} else {
s1 = TclGetStringFromObj(value1Ptr, &s1len);
s2 = TclGetStringFromObj(value2Ptr, &s2len);
}
if (!nocase && checkEq && reqlength < 0) {
/*
* When we have equal-length we can check only for
* (in)equality. We can use memcmp in all (n)eq cases because
* we don't need to worry about lexical LE/BE variance.
*/
|
| ︙ | ︙ | |||
4129 4130 4131 4132 4133 4134 4135 |
while (bytesLeft) {
/*
* NOTE: We know that the from buffer is NUL-terminated. It's
* part of the contract for objPtr->bytes values. Thus, we can
* skip calling Tcl_UtfCharComplete() here.
*/
| | | 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 |
while (bytesLeft) {
/*
* NOTE: We know that the from buffer is NUL-terminated. It's
* part of the contract for objPtr->bytes values. Thus, we can
* skip calling Tcl_UtfCharComplete() here.
*/
int bytesInChar = TclUtfToUniChar(from, &chw);
ReverseBytes((unsigned char *)to, (unsigned char *)from,
bytesInChar);
to += bytesInChar;
from += bytesInChar;
bytesLeft -= bytesInChar;
}
|
| ︙ | ︙ |
Changes to generic/tclStubInit.c.
| ︙ | ︙ | |||
60 61 62 63 64 65 66 | #undef Tcl_DictObjSize #undef Tcl_SplitList #undef Tcl_SplitPath #undef Tcl_FSSplitPath #undef Tcl_ParseArgsObjv #undef TclStaticLibrary #define TclStaticLibrary Tcl_StaticLibrary | < < < < | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #undef Tcl_DictObjSize #undef Tcl_SplitList #undef Tcl_SplitPath #undef Tcl_FSSplitPath #undef Tcl_ParseArgsObjv #undef TclStaticLibrary #define TclStaticLibrary Tcl_StaticLibrary #if !defined(_WIN32) && !defined(__CYGWIN__) # undef Tcl_WinConvertError # define Tcl_WinConvertError 0 #endif #undef TclGetStringFromObj #if defined(TCL_NO_DEPRECATED) # define TclGetStringFromObj 0 |
| ︙ | ︙ | |||
267 268 269 270 271 272 273 | #define TclBN_mp_to_radix mp_to_radix #define TclBN_mp_to_ubin mp_to_ubin #define TclBN_mp_ubin_size mp_ubin_size #define TclBN_mp_unpack mp_unpack #define TclBN_mp_xor mp_xor #define TclBN_mp_zero mp_zero #define TclBN_s_mp_add s_mp_add | | > | | | | | 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | #define TclBN_mp_to_radix mp_to_radix #define TclBN_mp_to_ubin mp_to_ubin #define TclBN_mp_ubin_size mp_ubin_size #define TclBN_mp_unpack mp_unpack #define TclBN_mp_xor mp_xor #define TclBN_mp_zero mp_zero #define TclBN_s_mp_add s_mp_add #define TclBN_s_mp_balance_mul s_mp_balance_mul #define TclBN_s_mp_div_3 s_mp_div_3 #define TclBN_s_mp_karatsuba_mul s_mp_karatsuba_mul #define TclBN_s_mp_karatsuba_sqr s_mp_karatsuba_sqr #define TclBN_s_mp_mul_digs s_mp_mul_digs #define TclBN_s_mp_mul_digs_fast s_mp_mul_digs_fast #define TclBN_s_mp_reverse s_mp_reverse #define TclBN_s_mp_sqr s_mp_sqr #define TclBN_s_mp_sqr_fast s_mp_sqr_fast #define TclBN_s_mp_sub s_mp_sub #define TclBN_s_mp_toom_mul s_mp_toom_mul #define TclBN_s_mp_toom_sqr s_mp_toom_sqr #ifndef MAC_OSX_TCL /* On UNIX, fill with other stub entries */ # define Tcl_MacOSXOpenVersionedBundleResources 0 # define Tcl_MacOSXNotifierAddRunLoopMode 0 #endif #ifdef _WIN32 # define Tcl_CreateFileHandler 0 |
| ︙ | ︙ | |||
403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
* The rest of this file shouldn't warn about deprecated functions; they're
* there because we intend them to be so and know that this file is OK to
* touch those fields.
*/
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
/* !BEGIN!: Do not edit below this line. */
static const TclIntStubs tclIntStubs = {
TCL_STUB_MAGIC,
0,
0, /* 0 */
0, /* 1 */
| > > > > > > > > | 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 |
* The rest of this file shouldn't warn about deprecated functions; they're
* there because we intend them to be so and know that this file is OK to
* touch those fields.
*/
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#ifdef TCL_WITH_EXTERNAL_TOMMATH
/* If Tcl is linked with an external libtommath 1.2.x, then mp_expt_n doesn't
* exist (since that was introduced in libtommath 1.3.0. Provide it here.) */
mp_err MP_WUR TclBN_mp_expt_n(const mp_int *a, int b, mp_int *c) {
return mp_expt_u32(a, (uint32_t)b, c);;
}
#endif /* TCL_WITH_EXTERNAL_TOMMATH */
/* !BEGIN!: Do not edit below this line. */
static const TclIntStubs tclIntStubs = {
TCL_STUB_MAGIC,
0,
0, /* 0 */
0, /* 1 */
|
| ︙ | ︙ | |||
739 740 741 742 743 744 745 |
TclBN_mp_count_bits, /* 12 */
TclBN_mp_div, /* 13 */
TclBN_mp_div_d, /* 14 */
TclBN_mp_div_2, /* 15 */
TclBN_mp_div_2d, /* 16 */
0, /* 17 */
TclBN_mp_exch, /* 18 */
| | | 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 |
TclBN_mp_count_bits, /* 12 */
TclBN_mp_div, /* 13 */
TclBN_mp_div_d, /* 14 */
TclBN_mp_div_2, /* 15 */
TclBN_mp_div_2d, /* 16 */
0, /* 17 */
TclBN_mp_exch, /* 18 */
TclBN_mp_expt_n, /* 19 */
TclBN_mp_grow, /* 20 */
TclBN_mp_init, /* 21 */
TclBN_mp_init_copy, /* 22 */
TclBN_mp_init_multi, /* 23 */
TclBN_mp_init_set, /* 24 */
TclBN_mp_init_size, /* 25 */
TclBN_mp_lshd, /* 26 */
|
| ︙ | ︙ |
Changes to generic/tclTest.c.
| ︙ | ︙ | |||
693 694 695 696 697 698 699 |
Tcl_CreateObjCommand2(interp, "testutfnext",
TestUtfNextCmd, NULL, NULL);
Tcl_CreateObjCommand2(interp, "testutfprev",
TestUtfPrevCmd, NULL, NULL);
Tcl_CreateObjCommand2(interp, "testnumutfchars",
TestNumUtfCharsCmd, NULL, NULL);
Tcl_CreateObjCommand2(interp, "testgetunichar",
| | | 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 |
Tcl_CreateObjCommand2(interp, "testutfnext",
TestUtfNextCmd, NULL, NULL);
Tcl_CreateObjCommand2(interp, "testutfprev",
TestUtfPrevCmd, NULL, NULL);
Tcl_CreateObjCommand2(interp, "testnumutfchars",
TestNumUtfCharsCmd, NULL, NULL);
Tcl_CreateObjCommand2(interp, "testgetunichar",
TestGetUniCharCmd, NULL, NULL);
Tcl_CreateObjCommand2(interp, "testfindfirst",
TestFindFirstCmd, NULL, NULL);
Tcl_CreateObjCommand2(interp, "testfindlast",
TestFindLastCmd, NULL, NULL);
Tcl_CreateObjCommand2(interp, "testgetintforindex",
TestGetIntForIndexCmd, NULL, NULL);
Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd,
|
| ︙ | ︙ | |||
859 860 861 862 863 864 865 |
{
TestAsyncHandler *asyncPtr, *prevPtr;
int id, code;
static int nextId = 1;
if (argc < 2) {
wrongNumArgs:
| | | | < | | | | | | 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 |
{
TestAsyncHandler *asyncPtr, *prevPtr;
int id, code;
static int nextId = 1;
if (argc < 2) {
wrongNumArgs:
Tcl_AppendResult(interp, "wrong # args", (char *)NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "create") == 0) {
if (argc != 3) {
goto wrongNumArgs;
}
asyncPtr = (TestAsyncHandler *)Tcl_Alloc(sizeof(TestAsyncHandler));
asyncPtr->command = (char *)Tcl_Alloc(strlen(argv[2]) + 1);
strcpy(asyncPtr->command, argv[2]);
Tcl_MutexLock(&asyncTestMutex);
asyncPtr->id = nextId;
nextId++;
asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc, INT2PTR(asyncPtr->id));
asyncPtr->nextPtr = firstHandler;
firstHandler = asyncPtr;
Tcl_MutexUnlock(&asyncTestMutex);
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(asyncPtr->id));
} else if (strcmp(argv[1], "delete") == 0) {
if (argc == 2) {
Tcl_MutexLock(&asyncTestMutex);
while (firstHandler != NULL) {
asyncPtr = firstHandler;
firstHandler = asyncPtr->nextPtr;
Tcl_AsyncDelete(asyncPtr->handler);
Tcl_Free(asyncPtr->command);
Tcl_Free(asyncPtr);
}
Tcl_MutexUnlock(&asyncTestMutex);
return TCL_OK;
}
if (argc != 3) {
goto wrongNumArgs;
}
if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
return TCL_ERROR;
}
Tcl_MutexLock(&asyncTestMutex);
for (prevPtr = NULL, asyncPtr = firstHandler; asyncPtr != NULL;
prevPtr = asyncPtr, asyncPtr = asyncPtr->nextPtr) {
if (asyncPtr->id != id) {
continue;
}
if (prevPtr == NULL) {
firstHandler = asyncPtr->nextPtr;
} else {
prevPtr->nextPtr = asyncPtr->nextPtr;
}
Tcl_AsyncDelete(asyncPtr->handler);
Tcl_Free(asyncPtr->command);
Tcl_Free(asyncPtr);
break;
}
Tcl_MutexUnlock(&asyncTestMutex);
} else if (strcmp(argv[1], "mark") == 0) {
if (argc != 5) {
goto wrongNumArgs;
}
if ((Tcl_GetInt(interp, argv[2], &id) != TCL_OK)
|| (Tcl_GetInt(interp, argv[4], &code) != TCL_OK)) {
return TCL_ERROR;
|
| ︙ | ︙ | |||
940 941 942 943 944 945 946 |
} else if (strcmp(argv[1], "marklater") == 0) {
if (argc != 3) {
goto wrongNumArgs;
}
if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
return TCL_ERROR;
}
| | | | | | | | | | | | | 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 |
} else if (strcmp(argv[1], "marklater") == 0) {
if (argc != 3) {
goto wrongNumArgs;
}
if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
return TCL_ERROR;
}
Tcl_MutexLock(&asyncTestMutex);
for (asyncPtr = firstHandler; asyncPtr != NULL;
asyncPtr = asyncPtr->nextPtr) {
if (asyncPtr->id == id) {
Tcl_ThreadId threadID;
if (Tcl_CreateThread(&threadID, AsyncThreadProc,
INT2PTR(id), TCL_THREAD_STACK_DEFAULT,
TCL_THREAD_NOFLAGS) != TCL_OK) {
Tcl_AppendResult(interp, "can't create thread", (char *)NULL);
Tcl_MutexUnlock(&asyncTestMutex);
return TCL_ERROR;
}
break;
}
}
Tcl_MutexUnlock(&asyncTestMutex);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be create, delete, int, mark, or marklater", (char *)NULL);
return TCL_ERROR;
}
return TCL_OK;
}
static int
AsyncHandlerProc(
void *clientData, /* If of TestAsyncHandler structure.
* in global list. */
Tcl_Interp *interp, /* Interpreter in which command was
* executed, or NULL. */
int code) /* Current return code from command. */
{
TestAsyncHandler *asyncPtr;
int id = PTR2INT(clientData);
const char *listArgv[4];
char *cmd;
char string[TCL_INTEGER_SPACE];
Tcl_MutexLock(&asyncTestMutex);
for (asyncPtr = firstHandler; asyncPtr != NULL;
asyncPtr = asyncPtr->nextPtr) {
if (asyncPtr->id == id) {
break;
}
}
Tcl_MutexUnlock(&asyncTestMutex);
if (!asyncPtr) {
/* Woops - this one was deleted between the AsyncMark and now */
return TCL_OK;
}
TclFormatInt(string, code);
listArgv[0] = asyncPtr->command;
listArgv[1] = Tcl_GetStringResult(interp);
listArgv[2] = string;
listArgv[3] = NULL;
|
| ︙ | ︙ | |||
1037 1038 1039 1040 1041 1042 1043 |
{
TestAsyncHandler *asyncPtr;
int id = PTR2INT(clientData);
Tcl_Sleep(1);
Tcl_MutexLock(&asyncTestMutex);
for (asyncPtr = firstHandler; asyncPtr != NULL;
| | | | | | | 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 |
{
TestAsyncHandler *asyncPtr;
int id = PTR2INT(clientData);
Tcl_Sleep(1);
Tcl_MutexLock(&asyncTestMutex);
for (asyncPtr = firstHandler; asyncPtr != NULL;
asyncPtr = asyncPtr->nextPtr) {
if (asyncPtr->id == id) {
Tcl_AsyncMark(asyncPtr->handler);
break;
}
}
Tcl_MutexUnlock(&asyncTestMutex);
Tcl_ExitThread(TCL_OK);
TCL_THREAD_CREATE_RETURN;
}
static int
|
| ︙ | ︙ | |||
1119 1120 1121 1122 1123 1124 1125 |
case CMDINFO_DELETE:
Tcl_DStringInit(&delString);
Tcl_DeleteCommand(interp, Tcl_GetString(objv[2]));
Tcl_DStringResult(interp, &delString);
break;
case CMDINFO_GET:
if (Tcl_GetCommandInfo(interp, Tcl_GetString(objv[2]), &info) ==0) {
| | | | | | | | | | | | | 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 |
case CMDINFO_DELETE:
Tcl_DStringInit(&delString);
Tcl_DeleteCommand(interp, Tcl_GetString(objv[2]));
Tcl_DStringResult(interp, &delString);
break;
case CMDINFO_GET:
if (Tcl_GetCommandInfo(interp, Tcl_GetString(objv[2]), &info) ==0) {
Tcl_AppendResult(interp, "??", (char *)NULL);
return TCL_OK;
}
if (info.proc == CmdProc1) {
Tcl_AppendResult(interp, "CmdProc1", " ",
(char *) info.clientData, (char *)NULL);
} else if (info.proc == CmdProc2) {
Tcl_AppendResult(interp, "CmdProc2", " ",
(char *) info.clientData, (char *)NULL);
} else {
Tcl_AppendResult(interp, "unknown", (char *)NULL);
}
if (info.deleteProc == CmdDelProc1) {
Tcl_AppendResult(interp, " CmdDelProc1", " ",
(char *) info.deleteData, (char *)NULL);
} else if (info.deleteProc == CmdDelProc2) {
Tcl_AppendResult(interp, " CmdDelProc2", " ",
(char *) info.deleteData, (char *)NULL);
} else {
Tcl_AppendResult(interp, " unknown", (char *)NULL);
}
Tcl_AppendResult(interp, " ", info.namespacePtr->fullName, (char *)NULL);
if (info.isNativeObjectProc == 0) {
Tcl_AppendResult(interp, " stringProc", (char *)NULL);
} else if (info.isNativeObjectProc == 1) {
Tcl_AppendResult(interp, " nativeObjectProc", (char *)NULL);
} else if (info.isNativeObjectProc == 2) {
Tcl_AppendResult(interp, " nativeObjectProc2", (char *)NULL);
} else {
Tcl_SetObjResult(interp, Tcl_ObjPrintf("Invalid isNativeObjectProc value %d",
info.isNativeObjectProc));
return TCL_ERROR;
}
break;
case CMDINFO_MODIFY:
|
| ︙ | ︙ | |||
1182 1183 1184 1185 1186 1187 1188 |
CmdProc0(
void *clientData, /* String to return. */
Tcl_Interp *interp, /* Current interpreter. */
TCL_UNUSED(int) /*argc*/,
TCL_UNUSED(const char **) /*argv*/)
{
TestCommandTokenRef *refPtr = (TestCommandTokenRef *) clientData;
| | | | | 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 |
CmdProc0(
void *clientData, /* String to return. */
Tcl_Interp *interp, /* Current interpreter. */
TCL_UNUSED(int) /*argc*/,
TCL_UNUSED(const char **) /*argv*/)
{
TestCommandTokenRef *refPtr = (TestCommandTokenRef *) clientData;
Tcl_AppendResult(interp, "CmdProc1 ", refPtr->value, (char *)NULL);
return TCL_OK;
}
static int
CmdProc1(
void *clientData, /* String to return. */
Tcl_Interp *interp, /* Current interpreter. */
TCL_UNUSED(int) /*argc*/,
TCL_UNUSED(const char **) /*argv*/)
{
Tcl_AppendResult(interp, "CmdProc1 ", (char *) clientData, (char *)NULL);
return TCL_OK;
}
static int
CmdProc2(
void *clientData, /* String to return. */
Tcl_Interp *interp, /* Current interpreter. */
TCL_UNUSED(int) /*argc*/,
TCL_UNUSED(const char **) /*argv*/)
{
Tcl_AppendResult(interp, "CmdProc2 ", (char *) clientData, (char *)NULL);
return TCL_OK;
}
static void
CmdDelProc0(
void *clientData) /* String to save. */
{
|
| ︙ | ︙ | |||
1278 1279 1280 1281 1282 1283 1284 |
{
TestCommandTokenRef *refPtr;
int id;
char buf[30];
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | | | | | 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 |
{
TestCommandTokenRef *refPtr;
int id;
char buf[30];
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" option arg\"", (char *)NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "create") == 0) {
refPtr = (TestCommandTokenRef *)Tcl_Alloc(sizeof(TestCommandTokenRef));
refPtr->token = Tcl_CreateCommand(interp, argv[2], CmdProc0,
refPtr, CmdDelProc0);
refPtr->id = nextCommandTokenRefId;
refPtr->value = "original";
nextCommandTokenRefId++;
refPtr->nextPtr = firstCommandTokenRef;
firstCommandTokenRef = refPtr;
snprintf(buf, sizeof(buf), "%d", refPtr->id);
Tcl_AppendResult(interp, buf, (char *)NULL);
} else {
if (sscanf(argv[2], "%d", &id) != 1) {
Tcl_AppendResult(interp, "bad command token \"", argv[2],
"\"", (char *)NULL);
return TCL_ERROR;
}
for (refPtr = firstCommandTokenRef; refPtr != NULL;
refPtr = refPtr->nextPtr) {
if (refPtr->id == id) {
break;
}
}
if (refPtr == NULL) {
Tcl_AppendResult(interp, "bad command token \"", argv[2],
"\"", (char *)NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "name") == 0) {
Tcl_Obj *objPtr;
objPtr = Tcl_NewObj();
Tcl_GetCommandFullName(interp, refPtr->token, objPtr);
Tcl_AppendElement(interp,
Tcl_GetCommandName(interp, refPtr->token));
Tcl_AppendElement(interp, Tcl_GetString(objPtr));
Tcl_DecrRefCount(objPtr);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be create, name, or free", (char *)NULL);
return TCL_ERROR;
}
}
return TCL_OK;
}
|
| ︙ | ︙ | |||
1362 1363 1364 1365 1366 1367 1368 |
const char **argv) /* Argument strings. */
{
Tcl_DString buffer;
int result;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | | 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 |
const char **argv) /* Argument strings. */
{
Tcl_DString buffer;
int result;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" option script\"", (char *)NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "tracetest") == 0) {
Tcl_DStringInit(&buffer);
cmdTrace = Tcl_CreateTrace(interp, 50000, CmdTraceProc, &buffer);
result = Tcl_EvalEx(interp, argv[2], TCL_INDEX_NONE, 0);
if (result == TCL_OK) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), (char *)NULL);
}
Tcl_DeleteTrace(interp, cmdTrace);
Tcl_DStringFree(&buffer);
} else if (strcmp(argv[1], "deletetest") == 0) {
/*
* Create a command trace then eval a script to check whether it is
* called. Note that this trace procedure removes itself as a further
|
| ︙ | ︙ | |||
1394 1395 1396 1397 1398 1399 1400 |
Interp *iPtr = (Interp *) interp;
Tcl_DStringInit(&buffer);
cmdTrace = Tcl_CreateTrace(interp, iPtr->numLevels + 4, CmdTraceProc,
&buffer);
result = Tcl_EvalEx(interp, argv[2], TCL_INDEX_NONE, 0);
if (result == TCL_OK) {
Tcl_ResetResult(interp);
| | | | | | 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 |
Interp *iPtr = (Interp *) interp;
Tcl_DStringInit(&buffer);
cmdTrace = Tcl_CreateTrace(interp, iPtr->numLevels + 4, CmdTraceProc,
&buffer);
result = Tcl_EvalEx(interp, argv[2], TCL_INDEX_NONE, 0);
if (result == TCL_OK) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), (char *)NULL);
}
Tcl_DeleteTrace(interp, cmdTrace);
Tcl_DStringFree(&buffer);
} else if (strcmp(argv[1], "resulttest") == 0) {
/* Create an object-based trace, then eval a script. This is used
* to test return codes other than TCL_OK from the trace engine.
*/
static int deleteCalled;
deleteCalled = 0;
cmdTrace = Tcl_CreateObjTrace2(interp, 50000,
TCL_ALLOW_INLINE_COMPILATION, ObjTraceProc,
&deleteCalled, ObjTraceDeleteProc);
result = Tcl_EvalEx(interp, argv[2], TCL_INDEX_NONE, 0);
Tcl_DeleteTrace(interp, cmdTrace);
if (!deleteCalled) {
Tcl_AppendResult(interp, "Delete wasn't called", (char *)NULL);
return TCL_ERROR;
} else {
return result;
}
} else if (strcmp(argv[1], "doubletest") == 0) {
Tcl_Trace t1, t2;
Tcl_DStringInit(&buffer);
t1 = Tcl_CreateTrace(interp, 1, CmdTraceProc, &buffer);
t2 = Tcl_CreateTrace(interp, 50000, CmdTraceProc, &buffer);
result = Tcl_EvalEx(interp, argv[2], TCL_INDEX_NONE, 0);
if (result == TCL_OK) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), (char *)NULL);
}
Tcl_DeleteTrace(interp, t2);
Tcl_DeleteTrace(interp, t1);
Tcl_DStringFree(&buffer);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be tracetest, deletetest, doubletest or resulttest", (char *)NULL);
return TCL_ERROR;
}
return TCL_OK;
}
static void
CmdTraceProc(
|
| ︙ | ︙ | |||
1551 1552 1553 1554 1555 1556 1557 |
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | | | | | | 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 |
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" option\"", (char *)NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "create") == 0) {
Tcl_CreateCommand(interp, "test_ns_basic::createdcommand",
CreatedCommandProc, NULL, NULL);
} else if (strcmp(argv[1], "delete") == 0) {
Tcl_DeleteCommand(interp, "test_ns_basic::createdcommand");
} else if (strcmp(argv[1], "create2") == 0) {
Tcl_CreateCommand(interp, "value:at:",
CreatedCommandProc2, NULL, NULL);
} else if (strcmp(argv[1], "delete2") == 0) {
Tcl_DeleteCommand(interp, "value:at:");
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be create, delete, create2, or delete2", (char *)NULL);
return TCL_ERROR;
}
return TCL_OK;
}
static int
CreatedCommandProc(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
TCL_UNUSED(int) /*argc*/,
TCL_UNUSED(const char **) /*argv*/)
{
Tcl_CmdInfo info;
int found;
found = Tcl_GetCommandInfo(interp, "test_ns_basic::createdcommand",
&info);
if (!found) {
Tcl_AppendResult(interp, "CreatedCommandProc could not get command info for test_ns_basic::createdcommand",
(char *)NULL);
return TCL_ERROR;
}
Tcl_AppendResult(interp, "CreatedCommandProc in ",
info.namespacePtr->fullName, (char *)NULL);
return TCL_OK;
}
static int
CreatedCommandProc2(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
TCL_UNUSED(int) /*argc*/,
TCL_UNUSED(const char **) /*argv*/)
{
Tcl_CmdInfo info;
int found;
found = Tcl_GetCommandInfo(interp, "value:at:", &info);
if (!found) {
Tcl_AppendResult(interp, "CreatedCommandProc2 could not get command info for test_ns_basic::createdcommand",
(char *)NULL);
return TCL_ERROR;
}
Tcl_AppendResult(interp, "CreatedCommandProc2 in ",
info.namespacePtr->fullName, (char *)NULL);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TestdcallCmd --
|
| ︙ | ︙ | |||
1707 1708 1709 1710 1711 1712 1713 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
DelCmd *dPtr;
Tcl_Interp *child;
if (argc != 4) {
| | | 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
DelCmd *dPtr;
Tcl_Interp *child;
if (argc != 4) {
Tcl_AppendResult(interp, "wrong # args", (char *)NULL);
return TCL_ERROR;
}
child = Tcl_GetChild(interp, argv[1]);
if (child == NULL) {
return TCL_ERROR;
}
|
| ︙ | ︙ | |||
1735 1736 1737 1738 1739 1740 1741 |
void *clientData, /* String result to return. */
Tcl_Interp *interp, /* Current interpreter. */
TCL_UNUSED(int) /*argc*/,
TCL_UNUSED(const char **) /*argv*/)
{
DelCmd *dPtr = (DelCmd *) clientData;
| | | 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 |
void *clientData, /* String result to return. */
Tcl_Interp *interp, /* Current interpreter. */
TCL_UNUSED(int) /*argc*/,
TCL_UNUSED(const char **) /*argv*/)
{
DelCmd *dPtr = (DelCmd *) clientData;
Tcl_AppendResult(interp, dPtr->deleteCmd, (char *)NULL);
Tcl_Free(dPtr->deleteCmd);
Tcl_Free(dPtr);
return TCL_OK;
}
static void
DelDeleteProc(
|
| ︙ | ︙ | |||
1780 1781 1782 1783 1784 1785 1786 |
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
| | | 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 |
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
" data_key\"", (char *)NULL);
return TCL_ERROR;
}
Tcl_DeleteAssocData(interp, argv[1]);
return TCL_OK;
}
/*
|
| ︙ | ︙ | |||
1906 1907 1908 1909 1910 1911 1912 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int count;
if (argc < 2) {
wrongNumArgs:
| | | 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int count;
if (argc < 2) {
wrongNumArgs:
Tcl_AppendResult(interp, "wrong # args", (char *)NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "append") == 0) {
if (argc != 4) {
goto wrongNumArgs;
}
if (Tcl_GetInt(interp, argv[3], &count) != TCL_OK) {
|
| ︙ | ︙ | |||
1942 1943 1944 1945 1946 1947 1948 |
}
Tcl_SetResult(interp, Tcl_DStringValue(&dstring), TCL_VOLATILE);
} else if (strcmp(argv[1], "gresult") == 0) {
if (argc != 3) {
goto wrongNumArgs;
}
if (strcmp(argv[2], "staticsmall") == 0) {
| | | | | 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 |
}
Tcl_SetResult(interp, Tcl_DStringValue(&dstring), TCL_VOLATILE);
} else if (strcmp(argv[1], "gresult") == 0) {
if (argc != 3) {
goto wrongNumArgs;
}
if (strcmp(argv[2], "staticsmall") == 0) {
Tcl_AppendResult(interp, "short", (char *)NULL);
} else if (strcmp(argv[2], "staticlarge") == 0) {
Tcl_AppendResult(interp, "first0 first1 first2 first3 first4 first5 first6 first7 first8 first9\nsecond0 second1 second2 second3 second4 second5 second6 second7 second8 second9\nthird0 third1 third2 third3 third4 third5 third6 third7 third8 third9\nfourth0 fourth1 fourth2 fourth3 fourth4 fourth5 fourth6 fourth7 fourth8 fourth9\nfifth0 fifth1 fifth2 fifth3 fifth4 fifth5 fifth6 fifth7 fifth8 fifth9\nsixth0 sixth1 sixth2 sixth3 sixth4 sixth5 sixth6 sixth7 sixth8 sixth9\nseventh0 seventh1 seventh2 seventh3 seventh4 seventh5 seventh6 seventh7 seventh8 seventh9\n", (char *)NULL);
} else if (strcmp(argv[2], "free") == 0) {
char *s = (char *)Tcl_Alloc(100);
strcpy(s, "This is a malloc-ed string");
Tcl_SetResult(interp, s, TCL_DYNAMIC);
} else if (strcmp(argv[2], "special") == 0) {
char *s = (char *)Tcl_Alloc(100) + 16;
strcpy(s, "This is a specially-allocated string");
Tcl_SetResult(interp, s, SpecialFree);
} else {
Tcl_AppendResult(interp, "bad gresult option \"", argv[2],
"\": must be staticsmall, staticlarge, free, or special",
(char *)NULL);
return TCL_ERROR;
}
Tcl_DStringGetResult(interp, &dstring);
} else if (strcmp(argv[1], "length") == 0) {
if (argc != 2) {
goto wrongNumArgs;
|
| ︙ | ︙ | |||
1992 1993 1994 1995 1996 1997 1998 |
if (argc != 2) {
goto wrongNumArgs;
}
Tcl_DStringStartSublist(&dstring);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be append, element, end, free, get, gresult, length, "
| | | 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 |
if (argc != 2) {
goto wrongNumArgs;
}
Tcl_DStringStartSublist(&dstring);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be append, element, end, free, get, gresult, length, "
"result, start, toobj, or trunc", (char *)NULL);
return TCL_ERROR;
}
return TCL_OK;
}
/*
* The procedure below is used as a special freeProc to test how well
|
| ︙ | ︙ | |||
2048 2049 2050 2051 2052 2053 2054 | * * The function also checks internally whether nuls are correctly * appended as requested but the TCL_ENCODING_NO_TERMINATE flag * and that no buffer overflows occur. *------------------------------------------------------------------------ */ typedef int | | > | > | 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 |
*
* The function also checks internally whether nuls are correctly
* appended as requested but the TCL_ENCODING_NO_TERMINATE flag
* and that no buffer overflows occur.
*------------------------------------------------------------------------
*/
typedef int
UtfTransformFn(Tcl_Interp *interp, Tcl_Encoding encoding, const char *src,
Tcl_Size srcLen, int flags, Tcl_EncodingState *statePtr, char *dst,
Tcl_Size dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr);
static int UtfExtWrapper(
Tcl_Interp *interp, UtfTransformFn *transformer, TclSizeT objc, Tcl_Obj *const objv[])
{
Tcl_Encoding encoding;
Tcl_EncodingState encState, *encStatePtr;
Tcl_Size srcLen, bufLen;
const unsigned char *bytes;
|
| ︙ | ︙ | |||
2081 2082 2083 2084 2085 2086 2087 |
{"profilereplace", TCL_ENCODING_PROFILE_REPLACE},
{NULL, 0}
};
Tcl_Size i;
Tcl_WideInt wide;
if (objc < 7 || objc > 10) {
| | | | | 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 |
{"profilereplace", TCL_ENCODING_PROFILE_REPLACE},
{NULL, 0}
};
Tcl_Size i;
Tcl_WideInt wide;
if (objc < 7 || objc > 10) {
Tcl_WrongNumArgs(interp, 2, objv,
"encoding srcbytes flags state dstlen ?srcreadvar? ?dstwrotevar? ?dstcharsvar?");
return TCL_ERROR;
}
if (Tcl_GetEncodingFromObj(interp, objv[2], &encoding) != TCL_OK) {
return TCL_ERROR;
}
/* Flags may be specified as list of integers and keywords */
flags = 0;
if (Tcl_ListObjGetElements(interp, objv[4], &nflags, &flagObjs) != TCL_OK) {
return TCL_ERROR;
}
|
| ︙ | ︙ | |||
2111 2112 2113 2114 2115 2116 2117 |
}
flags |= flagMap[idx].flag;
}
}
/* Assumes state is integer if not "" */
if (Tcl_GetWideIntFromObj(interp, objv[5], &wide) == TCL_OK) {
| | | | | | | | | | | | 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 |
}
flags |= flagMap[idx].flag;
}
}
/* Assumes state is integer if not "" */
if (Tcl_GetWideIntFromObj(interp, objv[5], &wide) == TCL_OK) {
encState = (Tcl_EncodingState)(size_t)wide;
encStatePtr = &encState;
} else if (Tcl_GetCharLength(objv[5]) == 0) {
encStatePtr = NULL;
} else {
return TCL_ERROR;
}
if (Tcl_GetIntFromObj(interp, objv[6], &dstLen) != TCL_OK) {
return TCL_ERROR;
}
srcReadVar = NULL;
dstWroteVar = NULL;
dstCharsVar = NULL;
if (objc > 7) {
/* Has caller requested srcRead? */
if (Tcl_GetCharLength(objv[7])) {
srcReadVar = objv[7];
}
if (objc > 8) {
/* Ditto for dstWrote */
if (Tcl_GetCharLength(objv[8])) {
dstWroteVar = objv[8];
}
if (objc > 9) {
if (Tcl_GetCharLength(objv[9])) {
dstCharsVar = objv[9];
}
}
}
}
if (flags & TCL_ENCODING_CHAR_LIMIT) {
/* Caller should have specified the dest char limit */
Tcl_Obj *valueObj;
|
| ︙ | ︙ | |||
2166 2167 2168 2169 2170 2171 2172 |
bufLen = dstLen + 4; /* 4 -> overflow detection */
bufPtr = (unsigned char *) Tcl_Alloc(bufLen);
memset(bufPtr, 0xFF, dstLen); /* Need to check nul terminator */
memmove(bufPtr + dstLen, "\xAB\xCD\xEF\xAB", 4); /* overflow detection */
bytes = Tcl_GetByteArrayFromObj(objv[3], &srcLen); /* Last! to avoid shimmering */
result = (*transformer)(interp, encoding, (const char *)bytes, srcLen, flags,
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 |
bufLen = dstLen + 4; /* 4 -> overflow detection */
bufPtr = (unsigned char *) Tcl_Alloc(bufLen);
memset(bufPtr, 0xFF, dstLen); /* Need to check nul terminator */
memmove(bufPtr + dstLen, "\xAB\xCD\xEF\xAB", 4); /* overflow detection */
bytes = Tcl_GetByteArrayFromObj(objv[3], &srcLen); /* Last! to avoid shimmering */
result = (*transformer)(interp, encoding, (const char *)bytes, srcLen, flags,
encStatePtr, (char *) bufPtr, dstLen,
srcReadVar ? &srcRead : NULL,
&dstWrote,
dstCharsVar ? &dstChars : NULL);
if (memcmp(bufPtr + bufLen - 4, "\xAB\xCD\xEF\xAB", 4)) {
Tcl_SetResult(interp,
"Tcl_ExternalToUtf wrote past output buffer",
TCL_STATIC);
result = TCL_ERROR;
} else if (result != TCL_ERROR) {
Tcl_Obj *resultObjs[3];
switch (result) {
case TCL_OK:
resultObjs[0] = Tcl_NewStringObj("ok", TCL_INDEX_NONE);
break;
case TCL_CONVERT_MULTIBYTE:
resultObjs[0] = Tcl_NewStringObj("multibyte", TCL_INDEX_NONE);
break;
case TCL_CONVERT_SYNTAX:
resultObjs[0] = Tcl_NewStringObj("syntax", TCL_INDEX_NONE);
break;
case TCL_CONVERT_UNKNOWN:
resultObjs[0] = Tcl_NewStringObj("unknown", TCL_INDEX_NONE);
break;
case TCL_CONVERT_NOSPACE:
resultObjs[0] = Tcl_NewStringObj("nospace", TCL_INDEX_NONE);
break;
default:
resultObjs[0] = Tcl_NewIntObj(result);
break;
}
result = TCL_OK;
resultObjs[1] =
encStatePtr ? Tcl_NewWideIntObj((Tcl_WideInt)(size_t)encState) : Tcl_NewObj();
resultObjs[2] = Tcl_NewByteArrayObj(bufPtr, dstLen);
if (srcReadVar) {
if (Tcl_ObjSetVar2(interp, srcReadVar, NULL, Tcl_NewIntObj(srcRead),
TCL_LEAVE_ERR_MSG) == NULL) {
result = TCL_ERROR;
}
}
if (dstWroteVar) {
if (Tcl_ObjSetVar2(interp, dstWroteVar, NULL, Tcl_NewIntObj(dstWrote),
TCL_LEAVE_ERR_MSG) == NULL) {
result = TCL_ERROR;
}
}
if (dstCharsVar) {
if (Tcl_ObjSetVar2(interp, dstCharsVar, NULL, Tcl_NewIntObj(dstChars),
TCL_LEAVE_ERR_MSG) == NULL) {
result = TCL_ERROR;
}
}
Tcl_SetObjResult(interp, Tcl_NewListObj(3, resultObjs));
}
Tcl_Free(bufPtr);
Tcl_FreeEncoding(encoding); /* Free returned reference */
return result;
}
|
| ︙ | ︙ | |||
2328 2329 2330 2331 2332 2333 2334 |
Tcl_GetEncoding(interp, objc == 2 ? NULL : Tcl_GetString(objv[2]));
if (encoding == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp,
Tcl_NewIntObj(Tcl_GetEncodingNulLength(encoding)));
Tcl_FreeEncoding(encoding);
| | | | | 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 |
Tcl_GetEncoding(interp, objc == 2 ? NULL : Tcl_GetString(objv[2]));
if (encoding == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp,
Tcl_NewIntObj(Tcl_GetEncodingNulLength(encoding)));
Tcl_FreeEncoding(encoding);
break;
case ENC_EXTTOUTF:
return UtfExtWrapper(interp,Tcl_ExternalToUtf,objc,objv);
case ENC_UTFTOEXT:
return UtfExtWrapper(interp,Tcl_UtfToExternal,objc,objv);
}
return TCL_OK;
}
static int
EncodingToUtfProc(
void *clientData, /* TclEncoding structure. */
|
| ︙ | ︙ | |||
2445 2446 2447 2448 2449 2450 2451 |
const char *script;
flags = 0;
if (objc == 3) {
const char *global = Tcl_GetString(objv[2]);
if (strcmp(global, "global") != 0) {
Tcl_AppendResult(interp, "bad value \"", global,
| | | 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 |
const char *script;
flags = 0;
if (objc == 3) {
const char *global = Tcl_GetString(objv[2]);
if (strcmp(global, "global") != 0) {
Tcl_AppendResult(interp, "bad value \"", global,
"\": must be global", (char *)NULL);
return TCL_ERROR;
}
flags = TCL_EVAL_GLOBAL;
} else if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "script ?global?");
return TCL_ERROR;
}
|
| ︙ | ︙ | |||
2714 2715 2716 2717 2718 2719 2720 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int value;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
| | | | 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int value;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
" create|delete value\"", (char *)NULL);
return TCL_ERROR;
}
if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) {
return TCL_ERROR;
}
if (strcmp(argv[1], "create") == 0) {
Tcl_CreateExitHandler((value & 1) ? ExitProcOdd : ExitProcEven,
INT2PTR(value));
} else if (strcmp(argv[1], "delete") == 0) {
Tcl_DeleteExitHandler((value & 1) ? ExitProcOdd : ExitProcEven,
INT2PTR(value));
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be create or delete", (char *)NULL);
return TCL_ERROR;
}
return TCL_OK;
}
static void
ExitProcOdd(
|
| ︙ | ︙ | |||
2792 2793 2794 2795 2796 2797 2798 |
{
long exprResult;
char buf[4 + TCL_INTEGER_SPACE];
int result;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
| | | | | 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 |
{
long exprResult;
char buf[4 + TCL_INTEGER_SPACE];
int result;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
" expression\"", (char *)NULL);
return TCL_ERROR;
}
Tcl_AppendResult(interp, "This is a result", (char *)NULL);
result = Tcl_ExprLong(interp, argv[1], &exprResult);
if (result != TCL_OK) {
return result;
}
snprintf(buf, sizeof(buf), ": %ld", exprResult);
Tcl_AppendResult(interp, buf, (char *)NULL);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TestexprlongobjCmd --
|
| ︙ | ︙ | |||
2837 2838 2839 2840 2841 2842 2843 |
char buf[4 + TCL_INTEGER_SPACE];
int result;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "expression");
return TCL_ERROR;
}
| | | | 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 |
char buf[4 + TCL_INTEGER_SPACE];
int result;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "expression");
return TCL_ERROR;
}
Tcl_AppendResult(interp, "This is a result", (char *)NULL);
result = Tcl_ExprLongObj(interp, objv[1], &exprResult);
if (result != TCL_OK) {
return result;
}
snprintf(buf, sizeof(buf), ": %ld", exprResult);
Tcl_AppendResult(interp, buf, (char *)NULL);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TestexprdoubleCmd --
|
| ︙ | ︙ | |||
2877 2878 2879 2880 2881 2882 2883 |
{
double exprResult;
char buf[4 + TCL_DOUBLE_SPACE];
int result;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
| | | | | 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 |
{
double exprResult;
char buf[4 + TCL_DOUBLE_SPACE];
int result;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
" expression\"", (char *)NULL);
return TCL_ERROR;
}
Tcl_AppendResult(interp, "This is a result", (char *)NULL);
result = Tcl_ExprDouble(interp, argv[1], &exprResult);
if (result != TCL_OK) {
return result;
}
strcpy(buf, ": ");
Tcl_PrintDouble(interp, exprResult, buf+2);
Tcl_AppendResult(interp, buf, (char *)NULL);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TestexprdoubleobjCmd --
|
| ︙ | ︙ | |||
2923 2924 2925 2926 2927 2928 2929 |
char buf[4 + TCL_DOUBLE_SPACE];
int result;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "expression");
return TCL_ERROR;
}
| | | | 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 |
char buf[4 + TCL_DOUBLE_SPACE];
int result;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "expression");
return TCL_ERROR;
}
Tcl_AppendResult(interp, "This is a result", (char *)NULL);
result = Tcl_ExprDoubleObj(interp, objv[1], &exprResult);
if (result != TCL_OK) {
return result;
}
strcpy(buf, ": ");
Tcl_PrintDouble(interp, exprResult, buf+2);
Tcl_AppendResult(interp, buf, (char *)NULL);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TestexprstringCmd --
|
| ︙ | ︙ | |||
2959 2960 2961 2962 2963 2964 2965 |
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
| | | 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 |
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
" expression\"", (char *)NULL);
return TCL_ERROR;
}
return Tcl_ExprString(interp, argv[1]);
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
3008 3009 3010 3011 3012 3013 3014 |
/* Create link from source to target */
contents = Tcl_FSLink(objv[1], objv[2],
TCL_CREATE_SYMBOLIC_LINK|TCL_CREATE_HARD_LINK);
if (contents == NULL) {
Tcl_AppendResult(interp, "could not create link from \"",
Tcl_GetString(objv[1]), "\" to \"",
Tcl_GetString(objv[2]), "\": ",
| | | | 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 |
/* Create link from source to target */
contents = Tcl_FSLink(objv[1], objv[2],
TCL_CREATE_SYMBOLIC_LINK|TCL_CREATE_HARD_LINK);
if (contents == NULL) {
Tcl_AppendResult(interp, "could not create link from \"",
Tcl_GetString(objv[1]), "\" to \"",
Tcl_GetString(objv[2]), "\": ",
Tcl_PosixError(interp), (char *)NULL);
return TCL_ERROR;
}
} else {
/* Read link */
contents = Tcl_FSLink(objv[1], NULL, 0);
if (contents == NULL) {
Tcl_AppendResult(interp, "could not read link \"",
Tcl_GetString(objv[1]), "\": ",
Tcl_PosixError(interp), (char *)NULL);
return TCL_ERROR;
}
}
Tcl_SetObjResult(interp, contents);
if (objc == 2) {
/*
* If we are creating a link, this will actually just
|
| ︙ | ︙ | |||
3060 3061 3062 3063 3064 3065 3066 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
char *res;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
| | | | 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
char *res;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
" data_key\"", (char *)NULL);
return TCL_ERROR;
}
res = (char *) Tcl_GetAssocData(interp, argv[1], NULL);
if (res != NULL) {
Tcl_AppendResult(interp, res, (char *)NULL);
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
3101 3102 3103 3104 3105 3106 3107 |
static const char *const platformStrings[] = { "unix", "mac", "windows" };
TclPlatformType *platform;
platform = TclGetPlatform();
if (argc != 1) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
| | | | 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 |
static const char *const platformStrings[] = { "unix", "mac", "windows" };
TclPlatformType *platform;
platform = TclGetPlatform();
if (argc != 1) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
(char *)NULL);
return TCL_ERROR;
}
Tcl_AppendResult(interp, platformStrings[*platform], (char *)NULL);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TestinterpdeleteCmd --
|
| ︙ | ︙ | |||
3138 3139 3140 3141 3142 3143 3144 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
Tcl_Interp *childToDelete;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
Tcl_Interp *childToDelete;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" path\"", (char *)NULL);
return TCL_ERROR;
}
childToDelete = Tcl_GetChild(interp, argv[1]);
if (childToDelete == NULL) {
return TCL_ERROR;
}
Tcl_DeleteInterp(childToDelete);
|
| ︙ | ︙ | |||
3196 3197 3198 3199 3200 3201 3202 |
char buffer[2*TCL_DOUBLE_SPACE];
int writable, flag;
Tcl_Obj *tmp;
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" option ?arg arg arg arg arg arg arg arg arg arg arg arg"
| | | | 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 |
char buffer[2*TCL_DOUBLE_SPACE];
int writable, flag;
Tcl_Obj *tmp;
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" option ?arg arg arg arg arg arg arg arg arg arg arg arg"
" arg arg?\"", (char *)NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "create") == 0) {
if (argc != 16) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " ", argv[1],
" intRO realRO boolRO stringRO wideRO charRO ucharRO shortRO"
" ushortRO uintRO longRO ulongRO floatRO uwideRO\"", (char *)NULL);
return TCL_ERROR;
}
if (created) {
Tcl_UnlinkVar(interp, "int");
Tcl_UnlinkVar(interp, "real");
Tcl_UnlinkVar(interp, "bool");
Tcl_UnlinkVar(interp, "string");
|
| ︙ | ︙ | |||
3413 3414 3415 3416 3417 3418 3419 |
int v;
if (argc != 16) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " ", argv[1],
" intValue realValue boolValue stringValue wideValue"
" charValue ucharValue shortValue ushortValue uintValue"
| | | 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 |
int v;
if (argc != 16) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " ", argv[1],
" intValue realValue boolValue stringValue wideValue"
" charValue ucharValue shortValue ushortValue uintValue"
" longValue ulongValue floatValue uwideValue\"", (char *)NULL);
return TCL_ERROR;
}
if (argv[2][0] != 0) {
if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) {
return TCL_ERROR;
}
}
|
| ︙ | ︙ | |||
3517 3518 3519 3520 3521 3522 3523 |
int v;
if (argc != 16) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " ", argv[1],
" intValue realValue boolValue stringValue wideValue"
" charValue ucharValue shortValue ushortValue uintValue"
| | | 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 |
int v;
if (argc != 16) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " ", argv[1],
" intValue realValue boolValue stringValue wideValue"
" charValue ucharValue shortValue ushortValue uintValue"
" longValue ulongValue floatValue uwideValue\"", (char *)NULL);
return TCL_ERROR;
}
if (argv[2][0] != 0) {
if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) {
return TCL_ERROR;
}
Tcl_UpdateLinkedVar(interp, "int");
|
| ︙ | ︙ | |||
3629 3630 3631 3632 3633 3634 3635 |
}
Tcl_DecrRefCount(tmp);
uwideVar = (Tcl_WideUInt) w;
Tcl_UpdateLinkedVar(interp, "uwide");
}
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
| | | 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 |
}
Tcl_DecrRefCount(tmp);
uwideVar = (Tcl_WideUInt) w;
Tcl_UpdateLinkedVar(interp, "uwide");
}
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": should be create, delete, get, set, or update", (char *)NULL);
return TCL_ERROR;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
3655 3656 3657 3658 3659 3660 3661 |
*
*----------------------------------------------------------------------
*/
static int
TestlinkarrayCmd(
TCL_UNUSED(void *),
| | | | | 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 |
*
*----------------------------------------------------------------------
*/
static int
TestlinkarrayCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
TclSizeT objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
static const char *LinkOption[] = {
"update", "remove", "create", NULL
};
enum LinkOptionEnum { LINK_UPDATE, LINK_REMOVE, LINK_CREATE } optionIndex;
static const char *LinkType[] = {
"char", "uchar", "short", "ushort", "int", "uint", "long", "ulong",
"wide", "uwide", "float", "double", "string", "char*", "binary", NULL
};
/* all values after TCL_LINK_CHARS_ARRAY are used as arrays (see below) */
|
| ︙ | ︙ | |||
3829 3830 3831 3832 3833 3834 3835 |
!= TCL_OK) {
return TCL_ERROR;
}
}
}
resultObj = TclListTestObj(length, leadSpace, endSpace);
if (resultObj == NULL) {
| | | 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 |
!= TCL_OK) {
return TCL_ERROR;
}
}
}
resultObj = TclListTestObj(length, leadSpace, endSpace);
if (resultObj == NULL) {
Tcl_AppendResult(interp, "List capacity exceeded", (char *)NULL);
return TCL_ERROR;
}
}
break;
case LISTREP_DESCRIBE:
#define APPEND_FIELD(targetObj_, structPtr_, fld_) \
|
| ︙ | ︙ | |||
3873 3874 3875 3876 3877 3878 3879 |
APPEND_FIELD(listRepObjs[1], listRep.storePtr, refCount);
APPEND_FIELD(listRepObjs[1], listRep.storePtr, flags);
if (listRep.spanPtr) {
listRepObjs[2] = Tcl_NewStringObj("span", -1);
listRepObjs[3] = Tcl_NewListObj(8, NULL);
Tcl_ListObjAppendElement(interp, listRepObjs[3],
Tcl_NewStringObj("memoryAddress", -1));
| | | 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 |
APPEND_FIELD(listRepObjs[1], listRep.storePtr, refCount);
APPEND_FIELD(listRepObjs[1], listRep.storePtr, flags);
if (listRep.spanPtr) {
listRepObjs[2] = Tcl_NewStringObj("span", -1);
listRepObjs[3] = Tcl_NewListObj(8, NULL);
Tcl_ListObjAppendElement(interp, listRepObjs[3],
Tcl_NewStringObj("memoryAddress", -1));
Tcl_ListObjAppendElement(interp, listRepObjs[3],
Tcl_ObjPrintf("%p", listRep.spanPtr));
APPEND_FIELD(listRepObjs[3], listRep.spanPtr, spanStart);
APPEND_FIELD(listRepObjs[3], listRep.spanPtr, spanLength);
APPEND_FIELD(listRepObjs[3], listRep.spanPtr, refCount);
}
resultObj = Tcl_NewListObj(listRep.spanPtr ? 4 : 2, listRepObjs);
}
|
| ︙ | ︙ | |||
4525 4526 4527 4528 4529 4530 4531 |
varName = Tcl_GetString(objv[2]);
TclRegExpRangeUniChar(regExpr, TCL_INDEX_NONE, &start, &end);
snprintf(resinfo, sizeof(resinfo), "%" TCL_Z_MODIFIER "d %" TCL_Z_MODIFIER "d", start, end-1);
value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0);
if (value == NULL) {
Tcl_AppendResult(interp, "couldn't set variable \"",
| | | | 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 |
varName = Tcl_GetString(objv[2]);
TclRegExpRangeUniChar(regExpr, TCL_INDEX_NONE, &start, &end);
snprintf(resinfo, sizeof(resinfo), "%" TCL_Z_MODIFIER "d %" TCL_Z_MODIFIER "d", start, end-1);
value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0);
if (value == NULL) {
Tcl_AppendResult(interp, "couldn't set variable \"",
varName, "\"", (char *)NULL);
return TCL_ERROR;
}
} else if (cflags & TCL_REG_CANMATCH) {
const char *varName;
const char *value;
char resinfo[TCL_INTEGER_SPACE * 2];
Tcl_RegExpGetInfo(regExpr, &info);
varName = Tcl_GetString(objv[2]);
snprintf(resinfo, sizeof(resinfo), "%" TCL_Z_MODIFIER "d", info.extendStart);
value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0);
if (value == NULL) {
Tcl_AppendResult(interp, "couldn't set variable \"",
varName, "\"", (char *)NULL);
return TCL_ERROR;
}
}
return TCL_OK;
}
/*
|
| ︙ | ︙ | |||
4760 4761 4762 4763 4764 4765 4766 |
const char **argv) /* Argument strings. */
{
char *buf, *oldData;
Tcl_InterpDeleteProc *procPtr;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
| | | 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 |
const char **argv) /* Argument strings. */
{
char *buf, *oldData;
Tcl_InterpDeleteProc *procPtr;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
" data_key data_item\"", (char *)NULL);
return TCL_ERROR;
}
buf = (char *)Tcl_Alloc(strlen(argv[2]) + 1);
strcpy(buf, argv[2]);
/*
|
| ︙ | ︙ | |||
4813 4814 4815 4816 4817 4818 4819 |
size_t length;
TclPlatformType *platform;
platform = TclGetPlatform();
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
| | | | 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 |
size_t length;
TclPlatformType *platform;
platform = TclGetPlatform();
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
" platform\"", (char *)NULL);
return TCL_ERROR;
}
length = strlen(argv[1]);
if (strncmp(argv[1], "unix", length) == 0) {
*platform = TCL_PLATFORM_UNIX;
} else if (strncmp(argv[1], "windows", length) == 0) {
*platform = TCL_PLATFORM_WINDOWS;
} else {
Tcl_AppendResult(interp, "unsupported platform: should be one of "
"unix, or windows", (char *)NULL);
return TCL_ERROR;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
4859 4860 4861 4862 4863 4864 4865 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int safe, loaded;
if (argc != 4) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
| | | 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int safe, loaded;
if (argc != 4) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
argv[0], " prefix safe loaded\"", (char *)NULL);
return TCL_ERROR;
}
if (Tcl_GetInt(interp, argv[2], &safe) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_GetInt(interp, argv[3], &loaded) != TCL_OK) {
return TCL_ERROR;
|
| ︙ | ︙ | |||
4911 4912 4913 4914 4915 4916 4917 |
const char **argv) /* Argument strings. */
{
Tcl_DString buffer;
const char *result;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
| | | | 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 |
const char **argv) /* Argument strings. */
{
Tcl_DString buffer;
const char *result;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
argv[0], " path\"", (char *)NULL);
return TCL_ERROR;
}
result = Tcl_TranslateFileName(interp, argv[1], &buffer);
if (result == NULL) {
return TCL_ERROR;
}
Tcl_AppendResult(interp, result, (char *)NULL);
Tcl_DStringFree(&buffer);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
4951 4952 4953 4954 4955 4956 4957 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int flags = 0;
if ((argc != 5) && (argc != 6)) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
| | | 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int flags = 0;
if ((argc != 5) && (argc != 6)) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
argv[0], " level name ?name2? dest global\"", (char *)NULL);
return TCL_ERROR;
}
if (argc == 5) {
if (strcmp(argv[4], "global") == 0) {
flags = TCL_GLOBAL_ONLY;
} else if (strcmp(argv[4], "namespace") == 0) {
|
| ︙ | ︙ | |||
5000 5001 5002 5003 5004 5005 5006 |
TestseterrorcodeCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
if (argc > 6) {
| | | | | | | | | 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 |
TestseterrorcodeCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
if (argc > 6) {
Tcl_AppendResult(interp, "too many args", (char *)NULL);
return TCL_ERROR;
}
switch (argc) {
case 1:
Tcl_SetErrorCode(interp, "NONE", (char *)NULL);
break;
case 2:
Tcl_SetErrorCode(interp, argv[1], (char *)NULL);
break;
case 3:
Tcl_SetErrorCode(interp, argv[1], argv[2], (char *)NULL);
break;
case 4:
Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], (char *)NULL);
break;
case 5:
Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4], (char *)NULL);
break;
case 6:
Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4],
argv[5], (char *)NULL);
}
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
5085 5086 5087 5088 5089 5090 5091 |
{
static Tcl_Interp *interp2 = NULL;
int code;
Tcl_Channel chan;
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | | | 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 |
{
static Tcl_Interp *interp2 = NULL;
int code;
Tcl_Channel chan;
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" option ?arg ...?", (char *)NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "cmd") == 0) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" cmd script", (char *)NULL);
return TCL_ERROR;
}
if (interp2 != NULL) {
code = Tcl_EvalEx(interp2, argv[2], TCL_INDEX_NONE, TCL_EVAL_GLOBAL);
Tcl_SetObjResult(interp, Tcl_GetObjResult(interp2));
return code;
} else {
Tcl_AppendResult(interp,
"called \"testfevent code\" before \"testfevent create\"",
(char *)NULL);
return TCL_ERROR;
}
} else if (strcmp(argv[1], "create") == 0) {
if (interp2 != NULL) {
Tcl_DeleteInterp(interp2);
}
interp2 = Tcl_CreateInterp();
|
| ︙ | ︙ | |||
5218 5219 5220 5221 5222 5223 5224 |
result = TCL_ERROR;
goto end;
}
if (result != TCL_OK) {
if (error != NULL) {
if (Tcl_GetString(error)[0] != '\0') {
| | | | 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 |
result = TCL_ERROR;
goto end;
}
if (result != TCL_OK) {
if (error != NULL) {
if (Tcl_GetString(error)[0] != '\0') {
Tcl_AppendResult(interp, Tcl_GetString(error), " ", (char *)NULL);
}
Tcl_DecrRefCount(error);
}
Tcl_AppendResult(interp, Tcl_ErrnoId(), (char *)NULL);
}
end:
return result;
}
/*
|
| ︙ | ︙ | |||
5663 5664 5665 5666 5667 5668 5669 |
if (Tcl_IsShared(obj)) {
obj = Tcl_DuplicateObj(obj);
}
if (Tcl_SetByteArrayLength(obj, n) == NULL) {
if (obj != objv[1]) {
Tcl_DecrRefCount(obj);
}
| | | 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 |
if (Tcl_IsShared(obj)) {
obj = Tcl_DuplicateObj(obj);
}
if (Tcl_SetByteArrayLength(obj, n) == NULL) {
if (obj != objv[1]) {
Tcl_DecrRefCount(obj);
}
Tcl_AppendResult(interp, "expected bytes", (char *)NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, obj);
return TCL_OK;
}
/*
|
| ︙ | ︙ | |||
5715 5716 5717 5718 5719 5720 5721 |
p = (const char *)Tcl_GetBytesFromObj(interp, objv[1], &x.n);
if (p == NULL) {
return TCL_ERROR;
}
if (x.m != 1) {
| | | 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 |
p = (const char *)Tcl_GetBytesFromObj(interp, objv[1], &x.n);
if (p == NULL) {
return TCL_ERROR;
}
if (x.m != 1) {
Tcl_AppendResult(interp, "Tcl_GetBytesFromObj() overwrites variable", (char *)NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewStringObj(p, x.n));
return TCL_OK;
}
/*
|
| ︙ | ︙ | |||
5750 5751 5752 5753 5754 5755 5756 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int flags = PTR2INT(data);
const char *value;
if (argc == 2) {
| | | | | | | | 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 |
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int flags = PTR2INT(data);
const char *value;
if (argc == 2) {
Tcl_AppendResult(interp, "before get", (char *)NULL);
value = Tcl_GetVar2(interp, argv[1], NULL, flags);
if (value == NULL) {
return TCL_ERROR;
}
Tcl_AppendElement(interp, value);
return TCL_OK;
} else if (argc == 3) {
Tcl_AppendResult(interp, "before set", (char *)NULL);
value = Tcl_SetVar2(interp, argv[1], NULL, argv[2], flags);
if (value == NULL) {
return TCL_ERROR;
}
Tcl_AppendElement(interp, value);
return TCL_OK;
} else {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " varName ?newValue?\"", (char *)NULL);
return TCL_ERROR;
}
}
static int
Testset2Cmd(
void *data, /* Additional flags for Get/SetVar2. */
Tcl_Interp *interp,/* Current interpreter. */
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int flags = PTR2INT(data);
const char *value;
if (argc == 3) {
Tcl_AppendResult(interp, "before get", (char *)NULL);
value = Tcl_GetVar2(interp, argv[1], argv[2], flags);
if (value == NULL) {
return TCL_ERROR;
}
Tcl_AppendElement(interp, value);
return TCL_OK;
} else if (argc == 4) {
Tcl_AppendResult(interp, "before set", (char *)NULL);
value = Tcl_SetVar2(interp, argv[1], argv[2], argv[3], flags);
if (value == NULL) {
return TCL_ERROR;
}
Tcl_AppendElement(interp, value);
return TCL_OK;
} else {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " varName elemName ?newValue?\"", (char *)NULL);
return TCL_ERROR;
}
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
5834 5835 5836 5837 5838 5839 5840 |
{
if (argc == 1) {
Tcl_Obj *idObj = Tcl_NewWideIntObj((Tcl_WideInt)(size_t)Tcl_GetCurrentThread());
Tcl_SetObjResult(interp, idObj);
return TCL_OK;
} else {
| | | 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 |
{
if (argc == 1) {
Tcl_Obj *idObj = Tcl_NewWideIntObj((Tcl_WideInt)(size_t)Tcl_GetCurrentThread());
Tcl_SetObjResult(interp, idObj);
return TCL_OK;
} else {
Tcl_AppendResult(interp, "wrong # args", (char *)NULL);
return TCL_ERROR;
}
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
5960 5961 5962 5963 5964 5965 5966 |
size_t len; /* Length of subcommand string. */
int IOQueued; /* How much IO is queued inside channel? */
char buf[TCL_INTEGER_SPACE];/* For snprintf. */
int mode; /* rw mode of the channel */
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 |
size_t len; /* Length of subcommand string. */
int IOQueued; /* How much IO is queued inside channel? */
char buf[TCL_INTEGER_SPACE];/* For snprintf. */
int mode; /* rw mode of the channel */
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" subcommand ?additional args..?\"", (char *)NULL);
return TCL_ERROR;
}
cmdName = argv[1];
len = strlen(cmdName);
chanPtr = NULL;
|
| ︙ | ︙ | |||
6043 6044 6045 6046 6047 6048 6049 |
*/
if ((cmdName[0] == 'c') && (strncmp(cmdName, "cut", len) == 0)) {
TestChannel *det;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 |
*/
if ((cmdName[0] == 'c') && (strncmp(cmdName, "cut", len) == 0)) {
TestChannel *det;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" cut channelName\"", (char *)NULL);
return TCL_ERROR;
}
Tcl_RegisterChannel(NULL, chan); /* prevent closing */
Tcl_UnregisterChannel(interp, chan);
Tcl_CutChannel(chan);
|
| ︙ | ︙ | |||
6066 6067 6068 6069 6070 6071 6072 |
return TCL_OK;
}
if ((cmdName[0] == 'c') &&
(strncmp(cmdName, "clearchannelhandlers", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | | 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 |
return TCL_OK;
}
if ((cmdName[0] == 'c') &&
(strncmp(cmdName, "clearchannelhandlers", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" clearchannelhandlers channelName\"", (char *)NULL);
return TCL_ERROR;
}
Tcl_ClearChannelHandlers(chan);
return TCL_OK;
}
if ((cmdName[0] == 'i') && (strncmp(cmdName, "info", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" info channelName\"", (char *)NULL);
return TCL_ERROR;
}
Tcl_AppendElement(interp, argv[2]);
Tcl_AppendElement(interp, Tcl_ChannelName(chanPtr->typePtr));
if (statePtr->flags & TCL_READABLE) {
Tcl_AppendElement(interp, "read");
} else {
|
| ︙ | ︙ | |||
6168 6169 6170 6171 6172 6173 6174 |
return TCL_OK;
}
if ((cmdName[0] == 'i') &&
(strncmp(cmdName, "inputbuffered", len) == 0)) {
if (argc != 3) {
| | | | | | | | | | | | | | | | | | | | | | | | | 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 |
return TCL_OK;
}
if ((cmdName[0] == 'i') &&
(strncmp(cmdName, "inputbuffered", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
IOQueued = Tcl_InputBuffered(chan);
TclFormatInt(buf, IOQueued);
Tcl_AppendResult(interp, buf, (char *)NULL);
return TCL_OK;
}
if ((cmdName[0] == 'i') && (strncmp(cmdName, "isshared", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
TclFormatInt(buf, Tcl_IsChannelShared(chan));
Tcl_AppendResult(interp, buf, (char *)NULL);
return TCL_OK;
}
if ((cmdName[0] == 'i') && (strncmp(cmdName, "isstandard", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
TclFormatInt(buf, Tcl_IsStandardChannel(chan));
Tcl_AppendResult(interp, buf, (char *)NULL);
return TCL_OK;
}
if ((cmdName[0] == 'm') && (strncmp(cmdName, "mode", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
if (statePtr->flags & TCL_READABLE) {
Tcl_AppendElement(interp, "read");
} else {
Tcl_AppendElement(interp, "");
}
if (statePtr->flags & TCL_WRITABLE) {
Tcl_AppendElement(interp, "write");
} else {
Tcl_AppendElement(interp, "");
}
return TCL_OK;
}
if ((cmdName[0] == 'm') && (strncmp(cmdName, "maxmode", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
if (statePtr->maxPerms & TCL_READABLE) {
Tcl_AppendElement(interp, "read");
} else {
Tcl_AppendElement(interp, "");
}
if (statePtr->maxPerms & TCL_WRITABLE) {
Tcl_AppendElement(interp, "write");
} else {
Tcl_AppendElement(interp, "");
}
return TCL_OK;
}
if ((cmdName[0] == 'm') && (strncmp(cmdName, "mremove-rd", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
return Tcl_RemoveChannelMode(interp, chan, TCL_READABLE);
}
if ((cmdName[0] == 'm') && (strncmp(cmdName, "mremove-wr", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
return Tcl_RemoveChannelMode(interp, chan, TCL_WRITABLE);
}
if ((cmdName[0] == 'm') && (strncmp(cmdName, "mthread", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
(Tcl_WideInt) (size_t) Tcl_GetChannelThread(chan)));
return TCL_OK;
}
if ((cmdName[0] == 'n') && (strncmp(cmdName, "name", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
Tcl_AppendResult(interp, statePtr->channelName, (char *)NULL);
return TCL_OK;
}
if ((cmdName[0] == 'o') && (strncmp(cmdName, "open", len) == 0)) {
hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
if (hTblPtr == NULL) {
return TCL_OK;
}
for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
hPtr != NULL;
hPtr = Tcl_NextHashEntry(&hSearch)) {
Tcl_AppendElement(interp, (char *)Tcl_GetHashKey(hTblPtr, hPtr));
}
return TCL_OK;
}
if ((cmdName[0] == 'o') &&
(strncmp(cmdName, "outputbuffered", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
IOQueued = Tcl_OutputBuffered(chan);
TclFormatInt(buf, IOQueued);
Tcl_AppendResult(interp, buf, (char *)NULL);
return TCL_OK;
}
if ((cmdName[0] == 'q') &&
(strncmp(cmdName, "queuedcr", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
Tcl_AppendResult(interp,
(statePtr->flags & INPUT_SAW_CR) ? "1" : "0", (char *)NULL);
return TCL_OK;
}
if ((cmdName[0] == 'r') && (strncmp(cmdName, "readable", len) == 0)) {
hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
if (hTblPtr == NULL) {
return TCL_OK;
|
| ︙ | ︙ | |||
6332 6333 6334 6335 6336 6337 6338 |
}
}
return TCL_OK;
}
if ((cmdName[0] == 'r') && (strncmp(cmdName, "refcount", len) == 0)) {
if (argc != 3) {
| | | | | | | 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 |
}
}
return TCL_OK;
}
if ((cmdName[0] == 'r') && (strncmp(cmdName, "refcount", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
TclFormatInt(buf, statePtr->refCount);
Tcl_AppendResult(interp, buf, (char *)NULL);
return TCL_OK;
}
/*
* "splice" is actually more a simplified attach facility as provided by
* the Thread package. Without the safeguards of a regular command (no
* checking that the command is truly cut'able, no mutexes for
* thread-safety). Its complementary command is "cut", see above.
*/
if ((cmdName[0] == 's') && (strncmp(cmdName, "splice", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
Tcl_SpliceChannel(chan);
Tcl_RegisterChannel(interp, chan);
Tcl_UnregisterChannel(NULL, chan);
return TCL_OK;
}
if ((cmdName[0] == 't') && (strncmp(cmdName, "type", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "channel name required", (char *)NULL);
return TCL_ERROR;
}
Tcl_AppendResult(interp, Tcl_ChannelName(chanPtr->typePtr), (char *)NULL);
return TCL_OK;
}
if ((cmdName[0] == 'w') && (strncmp(cmdName, "writable", len) == 0)) {
hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
if (hTblPtr == NULL) {
return TCL_OK;
|
| ︙ | ︙ | |||
6394 6395 6396 6397 6398 6399 6400 |
if ((cmdName[0] == 't') && (strncmp(cmdName, "transform", len) == 0)) {
/*
* Syntax: transform channel -command command
*/
if (argc != 5) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | | | | 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 |
if ((cmdName[0] == 't') && (strncmp(cmdName, "transform", len) == 0)) {
/*
* Syntax: transform channel -command command
*/
if (argc != 5) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" transform channelId -command cmd\"", (char *)NULL);
return TCL_ERROR;
}
if (strcmp(argv[3], "-command") != 0) {
Tcl_AppendResult(interp, "bad argument \"", argv[3],
"\": should be \"-command\"", (char *)NULL);
return TCL_ERROR;
}
return TclChannelTransform(interp, chan,
Tcl_NewStringObj(argv[4], -1));
}
if ((cmdName[0] == 'u') && (strncmp(cmdName, "unstack", len) == 0)) {
/*
* Syntax: unstack channel
*/
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" unstack channel\"", (char *)NULL);
return TCL_ERROR;
}
return Tcl_UnstackChannel(interp, chan);
}
Tcl_AppendResult(interp, "bad option \"", cmdName, "\": should be "
"cut, clearchannelhandlers, info, isshared, mode, open, "
"readable, splice, writable, transform, unstack", (char *)NULL);
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* TestChannelEventCmd --
|
| ︙ | ︙ | |||
6459 6460 6461 6462 6463 6464 6465 |
ChannelState *statePtr; /* state info for channel */
EventScriptRecord *esPtr, *prevEsPtr, *nextEsPtr;
const char *cmd;
int index, i, mask, len;
if ((argc < 3) || (argc > 5)) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | | | 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 |
ChannelState *statePtr; /* state info for channel */
EventScriptRecord *esPtr, *prevEsPtr, *nextEsPtr;
const char *cmd;
int index, i, mask, len;
if ((argc < 3) || (argc > 5)) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" channelName cmd ?arg1? ?arg2?\"", (char *)NULL);
return TCL_ERROR;
}
chanPtr = (Channel *) Tcl_GetChannel(interp, argv[1], NULL);
if (chanPtr == NULL) {
return TCL_ERROR;
}
statePtr = chanPtr->state;
cmd = argv[2];
len = strlen(cmd);
if ((cmd[0] == 'a') && (strncmp(cmd, "add", len) == 0)) {
if (argc != 5) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" channelName add eventSpec script\"", (char *)NULL);
return TCL_ERROR;
}
if (strcmp(argv[3], "readable") == 0) {
mask = TCL_READABLE;
} else if (strcmp(argv[3], "writable") == 0) {
mask = TCL_WRITABLE;
} else if (strcmp(argv[3], "none") == 0) {
mask = 0;
} else {
Tcl_AppendResult(interp, "bad event name \"", argv[3],
"\": must be readable, writable, or none", (char *)NULL);
return TCL_ERROR;
}
esPtr = (EventScriptRecord *)Tcl_Alloc(sizeof(EventScriptRecord));
esPtr->nextPtr = statePtr->scriptRecordPtr;
statePtr->scriptRecordPtr = esPtr;
|
| ︙ | ︙ | |||
6507 6508 6509 6510 6511 6512 6513 |
return TCL_OK;
}
if ((cmd[0] == 'd') && (strncmp(cmd, "delete", len) == 0)) {
if (argc != 4) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | | | 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 |
return TCL_OK;
}
if ((cmd[0] == 'd') && (strncmp(cmd, "delete", len) == 0)) {
if (argc != 4) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" channelName delete index\"", (char *)NULL);
return TCL_ERROR;
}
if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) {
return TCL_ERROR;
}
if (index < 0) {
Tcl_AppendResult(interp, "bad event index: ", argv[3],
": must be nonnegative", (char *)NULL);
return TCL_ERROR;
}
for (i = 0, esPtr = statePtr->scriptRecordPtr;
(i < index) && (esPtr != NULL);
i++, esPtr = esPtr->nextPtr) {
/* Empty loop body. */
}
if (esPtr == NULL) {
Tcl_AppendResult(interp, "bad event index ", argv[3],
": out of range", (char *)NULL);
return TCL_ERROR;
}
if (esPtr == statePtr->scriptRecordPtr) {
statePtr->scriptRecordPtr = esPtr->nextPtr;
} else {
for (prevEsPtr = statePtr->scriptRecordPtr;
(prevEsPtr != NULL) &&
|
| ︙ | ︙ | |||
6553 6554 6555 6556 6557 6558 6559 |
return TCL_OK;
}
if ((cmd[0] == 'l') && (strncmp(cmd, "list", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 |
return TCL_OK;
}
if ((cmd[0] == 'l') && (strncmp(cmd, "list", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" channelName list\"", (char *)NULL);
return TCL_ERROR;
}
resultListPtr = Tcl_GetObjResult(interp);
for (esPtr = statePtr->scriptRecordPtr;
esPtr != NULL;
esPtr = esPtr->nextPtr) {
if (esPtr->mask) {
|
| ︙ | ︙ | |||
6576 6577 6578 6579 6580 6581 6582 |
Tcl_SetObjResult(interp, resultListPtr);
return TCL_OK;
}
if ((cmd[0] == 'r') && (strncmp(cmd, "removeall", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | | | | | | 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 |
Tcl_SetObjResult(interp, resultListPtr);
return TCL_OK;
}
if ((cmd[0] == 'r') && (strncmp(cmd, "removeall", len) == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" channelName removeall\"", (char *)NULL);
return TCL_ERROR;
}
for (esPtr = statePtr->scriptRecordPtr;
esPtr != NULL;
esPtr = nextEsPtr) {
nextEsPtr = esPtr->nextPtr;
Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
TclChannelEventScriptInvoker, esPtr);
Tcl_DecrRefCount(esPtr->scriptPtr);
Tcl_Free(esPtr);
}
statePtr->scriptRecordPtr = NULL;
return TCL_OK;
}
if ((cmd[0] == 's') && (strncmp(cmd, "set", len) == 0)) {
if (argc != 5) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" channelName delete index event\"", (char *)NULL);
return TCL_ERROR;
}
if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) {
return TCL_ERROR;
}
if (index < 0) {
Tcl_AppendResult(interp, "bad event index: ", argv[3],
": must be nonnegative", (char *)NULL);
return TCL_ERROR;
}
for (i = 0, esPtr = statePtr->scriptRecordPtr;
(i < index) && (esPtr != NULL);
i++, esPtr = esPtr->nextPtr) {
/* Empty loop body. */
}
if (esPtr == NULL) {
Tcl_AppendResult(interp, "bad event index ", argv[3],
": out of range", (char *)NULL);
return TCL_ERROR;
}
if (strcmp(argv[4], "readable") == 0) {
mask = TCL_READABLE;
} else if (strcmp(argv[4], "writable") == 0) {
mask = TCL_WRITABLE;
} else if (strcmp(argv[4], "none") == 0) {
mask = 0;
} else {
Tcl_AppendResult(interp, "bad event name \"", argv[4],
"\": must be readable, writable, or none", (char *)NULL);
return TCL_ERROR;
}
esPtr->mask = mask;
Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask,
TclChannelEventScriptInvoker, esPtr);
return TCL_OK;
}
Tcl_AppendResult(interp, "bad command ", cmd, ", must be one of "
"add, delete, list, set, or removeall", (char *)NULL);
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* TestSocketCmd --
|
| ︙ | ︙ | |||
6671 6672 6673 6674 6675 6676 6677 |
const char **argv) /* Additional arg strings. */
{
const char *cmdName; /* Sub command. */
size_t len; /* Length of subcommand string. */
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 |
const char **argv) /* Additional arg strings. */
{
const char *cmdName; /* Sub command. */
size_t len; /* Length of subcommand string. */
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" subcommand ?additional args..?\"", (char *)NULL);
return TCL_ERROR;
}
cmdName = argv[1];
len = strlen(cmdName);
if ((cmdName[0] == 't') && (strncmp(cmdName, "testflags", len) == 0)) {
Tcl_Channel hChannel;
int modePtr;
int testMode;
TcpState *statePtr;
/* Set test value in the socket driver
*/
/* Check for argument "channel name"
*/
if (argc < 4) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" testflags channel flags\"", (char *)NULL);
return TCL_ERROR;
}
hChannel = Tcl_GetChannel(interp, argv[2], &modePtr);
if ( NULL == hChannel ) {
Tcl_AppendResult(interp, "unknown channel:", argv[2], (char *)NULL);
return TCL_ERROR;
}
statePtr = (TcpState *)Tcl_GetChannelInstanceData(hChannel);
if ( NULL == statePtr) {
Tcl_AppendResult(interp, "No channel instance data:", argv[2],
(char *)NULL);
return TCL_ERROR;
}
if (Tcl_GetBoolean(interp, argv[3], &testMode) != TCL_OK) {
return TCL_ERROR;
}
if (testMode) {
statePtr->flags |= TCP_ASYNC_TEST_MODE;
} else {
statePtr->flags &= ~TCP_ASYNC_TEST_MODE;
}
return TCL_OK;
}
Tcl_AppendResult(interp, "bad option \"", cmdName, "\": should be "
"testflags", (char *)NULL);
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* TestServiceModeCmd --
|
| ︙ | ︙ | |||
6747 6748 6749 6750 6751 6752 6753 |
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int newmode, oldmode;
if (argc > 2) {
| | | | | | | | | | | | | 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 |
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
{
int newmode, oldmode;
if (argc > 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ?newmode?\"", (char *)NULL);
return TCL_ERROR;
}
oldmode = (Tcl_GetServiceMode() != TCL_SERVICE_NONE);
if (argc == 2) {
if (Tcl_GetInt(interp, argv[1], &newmode) == TCL_ERROR) {
return TCL_ERROR;
}
if (newmode == 0) {
Tcl_SetServiceMode(TCL_SERVICE_NONE);
} else {
Tcl_SetServiceMode(TCL_SERVICE_ALL);
}
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(oldmode));
return TCL_OK;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
6810 6811 6812 6813 6814 6815 6816 |
}
if (i > objc - 3) {
/*
* Asked for more arguments than were given.
*/
insufArgs:
| | | 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 |
}
if (i > objc - 3) {
/*
* Asked for more arguments than were given.
*/
insufArgs:
Tcl_AppendResult(interp, "insufficient arguments", (char *)NULL);
return TCL_ERROR;
}
Tcl_WrongNumArgs(interp, i, &(objv[3]), msg);
return TCL_OK;
}
|
| ︙ | ︙ | |||
6863 6864 6865 6866 6867 6868 6869 |
}
memset(idx, 85, sizeof(idx));
if (Tcl_GetIndexFromObjStruct(interp, (Tcl_GetString(objv[1])[0] ? objv[1] : NULL), ary, 2*sizeof(char *),
"dummy", flags, &idx[1]) != TCL_OK) {
return TCL_ERROR;
}
if (idx[0] != 85 || idx[2] != 85) {
| | | | | 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 |
}
memset(idx, 85, sizeof(idx));
if (Tcl_GetIndexFromObjStruct(interp, (Tcl_GetString(objv[1])[0] ? objv[1] : NULL), ary, 2*sizeof(char *),
"dummy", flags, &idx[1]) != TCL_OK) {
return TCL_ERROR;
}
if (idx[0] != 85 || idx[2] != 85) {
Tcl_AppendResult(interp, "Tcl_GetIndexFromObjStruct overwrites bytes near index variable", (char *)NULL);
return TCL_ERROR;
} else if (idx[1] != target) {
char buffer[64];
snprintf(buffer, sizeof(buffer), "%d", idx[1]);
Tcl_AppendResult(interp, "index value comparison failed: got ",
buffer, (char *)NULL);
snprintf(buffer, sizeof(buffer), "%d", target);
Tcl_AppendResult(interp, " when ", buffer, " expected", (char *)NULL);
return TCL_ERROR;
}
Tcl_WrongNumArgs(interp, objc, objv, NULL);
return TCL_OK;
}
/*
|
| ︙ | ︙ | |||
7378 7379 7380 7381 7382 7383 7384 |
int permissions) /* If the open involves creating a file, with
* what modes to create it? */
{
Tcl_Obj *tempPtr;
Tcl_Channel chan;
if ((mode != 0) && !(mode & O_RDONLY)) {
| | | 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 |
int permissions) /* If the open involves creating a file, with
* what modes to create it? */
{
Tcl_Obj *tempPtr;
Tcl_Channel chan;
if ((mode != 0) && !(mode & O_RDONLY)) {
Tcl_AppendResult(interp, "read-only", (char *)NULL);
return NULL;
}
tempPtr = SimpleRedirect(pathPtr);
chan = Tcl_FSOpenFileChannel(interp, tempPtr, "r", permissions);
Tcl_DecrRefCount(tempPtr);
return chan;
|
| ︙ | ︙ | |||
7464 7465 7466 7467 7468 7469 7470 |
buffer[0] = buffer[numBytes + 1] = buffer[numBytes + 2] = buffer[numBytes + 3] = '\xA0';
first = result = Tcl_UtfNext(buffer + 1);
while ((buffer[0] = *p++) != '\0') {
/* Run Tcl_UtfNext with many more possible bytes at src[-1], all should give the same result */
result = Tcl_UtfNext(buffer + 1);
if (first != result) {
| | | 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 |
buffer[0] = buffer[numBytes + 1] = buffer[numBytes + 2] = buffer[numBytes + 3] = '\xA0';
first = result = Tcl_UtfNext(buffer + 1);
while ((buffer[0] = *p++) != '\0') {
/* Run Tcl_UtfNext with many more possible bytes at src[-1], all should give the same result */
result = Tcl_UtfNext(buffer + 1);
if (first != result) {
Tcl_AppendResult(interp, "Tcl_UtfNext is not supposed to read src[-1]", (char *)NULL);
return TCL_ERROR;
}
}
p = tobetested;
while ((buffer[numBytes + 1] = *p++) != '\0') {
/* Run Tcl_UtfNext with many more possible bytes at src[end], all should give the same result */
result = Tcl_UtfNext(buffer + 1);
|
| ︙ | ︙ | |||
7736 7737 7738 7739 7740 7741 7742 |
if (objc>1 && Tcl_GetIntFromObj(interp, objv[1], &limit)!=TCL_OK) {
return TCL_ERROR;
}
Tcl_InitCustomHashTable(&hash, TCL_CUSTOM_TYPE_KEYS, &hkType);
if (hash.numEntries != 0) {
| | | | 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 |
if (objc>1 && Tcl_GetIntFromObj(interp, objv[1], &limit)!=TCL_OK) {
return TCL_ERROR;
}
Tcl_InitCustomHashTable(&hash, TCL_CUSTOM_TYPE_KEYS, &hkType);
if (hash.numEntries != 0) {
Tcl_AppendResult(interp, "non-zero initial size", (char *)NULL);
Tcl_DeleteHashTable(&hash);
return TCL_ERROR;
}
for (i=0 ; i<limit ; i++) {
hPtr = Tcl_CreateHashEntry(&hash, INT2PTR(i), &isNew);
if (!isNew) {
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(i));
Tcl_AppendToObj(Tcl_GetObjResult(interp)," creation problem", -1);
Tcl_DeleteHashTable(&hash);
return TCL_ERROR;
}
Tcl_SetHashValue(hPtr, INT2PTR(i+42));
}
if (hash.numEntries != (Tcl_Size)limit) {
Tcl_AppendResult(interp, "unexpected maximal size", (char *)NULL);
Tcl_DeleteHashTable(&hash);
return TCL_ERROR;
}
for (i=0 ; i<limit ; i++) {
hPtr = Tcl_FindHashEntry(&hash, (char *) INT2PTR(i));
if (hPtr == NULL) {
|
| ︙ | ︙ | |||
7776 7777 7778 7779 7780 7781 7782 |
Tcl_DeleteHashTable(&hash);
return TCL_ERROR;
}
Tcl_DeleteHashEntry(hPtr);
}
if (hash.numEntries != 0) {
| | | | | 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 |
Tcl_DeleteHashTable(&hash);
return TCL_ERROR;
}
Tcl_DeleteHashEntry(hPtr);
}
if (hash.numEntries != 0) {
Tcl_AppendResult(interp, "non-zero final size", (char *)NULL);
Tcl_DeleteHashTable(&hash);
return TCL_ERROR;
}
Tcl_DeleteHashTable(&hash);
Tcl_AppendResult(interp, "OK", (char *)NULL);
return TCL_OK;
}
/*
* Used for testing Tcl_GetInt which is no longer used directly by the
* core very much.
*/
static int
TestgetintCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int argc,
const char **argv)
{
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args", (char *)NULL);
return TCL_ERROR;
} else {
int val, i, total=0;
for (i=1 ; i<argc ; i++) {
if (Tcl_GetInt(interp, argv[i], &val) != TCL_OK) {
return TCL_ERROR;
|
| ︙ | ︙ | |||
7825 7826 7827 7828 7829 7830 7831 |
TestlongsizeCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int argc,
TCL_UNUSED(const char **) /*argv*/)
{
if (argc != 1) {
| | | | | | | | | | | | | | | 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 |
TestlongsizeCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int argc,
TCL_UNUSED(const char **) /*argv*/)
{
if (argc != 1) {
Tcl_AppendResult(interp, "wrong # args", (char *)NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sizeof(long)));
return TCL_OK;
}
static int
NREUnwind_callback(
void *data[],
Tcl_Interp *interp,
TCL_UNUSED(int) /*result*/)
{
void *cStackPtr = TclGetCStackPtr();
if (data[0] == INT2PTR(-1)) {
Tcl_NRAddCallback(interp, NREUnwind_callback, cStackPtr, INT2PTR(-1),
INT2PTR(-1), NULL);
} else if (data[1] == INT2PTR(-1)) {
Tcl_NRAddCallback(interp, NREUnwind_callback, data[0], cStackPtr,
INT2PTR(-1), NULL);
} else if (data[2] == INT2PTR(-1)) {
Tcl_NRAddCallback(interp, NREUnwind_callback, data[0], data[1],
cStackPtr, NULL);
} else {
Tcl_Obj *idata[3];
idata[0] = Tcl_NewWideIntObj(((char *) data[1] - (char *) data[0]));
idata[1] = Tcl_NewWideIntObj(((char *) data[2] - (char *) data[0]));
idata[2] = Tcl_NewWideIntObj(((char *) cStackPtr - (char *) data[0]));
Tcl_SetObjResult(interp, Tcl_NewListObj(3, idata));
}
return TCL_OK;
}
static int
TestNREUnwind(
TCL_UNUSED(void *),
Tcl_Interp *interp,
TCL_UNUSED(TclSizeT) /*objc*/,
TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
/*
* Insure that callbacks effectively run at the proper level during the
* unwinding of the NRE stack.
*/
Tcl_NRAddCallback(interp, NREUnwind_callback, INT2PTR(-1), INT2PTR(-1),
INT2PTR(-1), NULL);
return TCL_OK;
}
static int
TestNRELevels(
TCL_UNUSED(void *),
|
| ︙ | ︙ | |||
7976 7977 7978 7979 7980 7981 7982 |
objv[0] = tmpPtr;
objv[1] = emptyPtr;
concatPtr = Tcl_ConcatObj(2, objv);
if (concatPtr->refCount != 0) {
result = TCL_ERROR;
Tcl_AppendResult(interp,
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 |
objv[0] = tmpPtr;
objv[1] = emptyPtr;
concatPtr = Tcl_ConcatObj(2, objv);
if (concatPtr->refCount != 0) {
result = TCL_ERROR;
Tcl_AppendResult(interp,
"\n\t* (a) concatObj does not have refCount 0", (char *)NULL);
}
if (concatPtr == tmpPtr) {
result = TCL_ERROR;
Tcl_AppendResult(interp, "\n\t* (a) concatObj is not a new obj ",
(char *)NULL);
switch (tmpPtr->refCount) {
case 0:
Tcl_AppendResult(interp, "(no new refCount)", (char *)NULL);
break;
case 1:
Tcl_AppendResult(interp, "(refCount added)", (char *)NULL);
break;
default:
Tcl_AppendResult(interp, "(more than one refCount added!)", (char *)NULL);
Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
}
tmpPtr = Tcl_DuplicateObj(list1Ptr);
objv[0] = tmpPtr;
}
Tcl_DecrRefCount(concatPtr);
Tcl_IncrRefCount(tmpPtr);
concatPtr = Tcl_ConcatObj(2, objv);
if (concatPtr->refCount != 0) {
result = TCL_ERROR;
Tcl_AppendResult(interp,
"\n\t* (b) concatObj does not have refCount 0", (char *)NULL);
}
if (concatPtr == tmpPtr) {
result = TCL_ERROR;
Tcl_AppendResult(interp, "\n\t* (b) concatObj is not a new obj ",
(char *)NULL);
switch (tmpPtr->refCount) {
case 0:
Tcl_AppendResult(interp, "(refCount removed?)", (char *)NULL);
Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
break;
case 1:
Tcl_AppendResult(interp, "(no new refCount)", (char *)NULL);
break;
case 2:
Tcl_AppendResult(interp, "(refCount added)", (char *)NULL);
Tcl_DecrRefCount(tmpPtr);
break;
default:
Tcl_AppendResult(interp, "(more than one refCount added!)", (char *)NULL);
Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
}
tmpPtr = Tcl_DuplicateObj(list1Ptr);
objv[0] = tmpPtr;
}
Tcl_DecrRefCount(concatPtr);
objv[0] = emptyPtr;
objv[1] = tmpPtr;
objv[2] = emptyPtr;
concatPtr = Tcl_ConcatObj(3, objv);
if (concatPtr->refCount != 0) {
result = TCL_ERROR;
Tcl_AppendResult(interp,
"\n\t* (c) concatObj does not have refCount 0", (char *)NULL);
}
if (concatPtr == tmpPtr) {
result = TCL_ERROR;
Tcl_AppendResult(interp, "\n\t* (c) concatObj is not a new obj ",
(char *)NULL);
switch (tmpPtr->refCount) {
case 0:
Tcl_AppendResult(interp, "(no new refCount)", (char *)NULL);
break;
case 1:
Tcl_AppendResult(interp, "(refCount added)", (char *)NULL);
break;
default:
Tcl_AppendResult(interp, "(more than one refCount added!)", (char *)NULL);
Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
}
tmpPtr = Tcl_DuplicateObj(list1Ptr);
objv[1] = tmpPtr;
}
Tcl_DecrRefCount(concatPtr);
Tcl_IncrRefCount(tmpPtr);
concatPtr = Tcl_ConcatObj(3, objv);
if (concatPtr->refCount != 0) {
result = TCL_ERROR;
Tcl_AppendResult(interp,
"\n\t* (d) concatObj does not have refCount 0", (char *)NULL);
}
if (concatPtr == tmpPtr) {
result = TCL_ERROR;
Tcl_AppendResult(interp, "\n\t* (d) concatObj is not a new obj ",
(char *)NULL);
switch (tmpPtr->refCount) {
case 0:
Tcl_AppendResult(interp, "(refCount removed?)", (char *)NULL);
Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
break;
case 1:
Tcl_AppendResult(interp, "(no new refCount)", (char *)NULL);
break;
case 2:
Tcl_AppendResult(interp, "(refCount added)", (char *)NULL);
Tcl_DecrRefCount(tmpPtr);
break;
default:
Tcl_AppendResult(interp, "(more than one refCount added!)", (char *)NULL);
Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
}
tmpPtr = Tcl_DuplicateObj(list1Ptr);
objv[1] = tmpPtr;
}
Tcl_DecrRefCount(concatPtr);
/*
* Verify that an unshared list is not corrupted when concat'ing things to
* it.
*/
objv[0] = tmpPtr;
objv[1] = list2Ptr;
concatPtr = Tcl_ConcatObj(2, objv);
if (concatPtr->refCount != 0) {
result = TCL_ERROR;
Tcl_AppendResult(interp,
"\n\t* (e) concatObj does not have refCount 0", (char *)NULL);
}
if (concatPtr == tmpPtr) {
result = TCL_ERROR;
Tcl_AppendResult(interp, "\n\t* (e) concatObj is not a new obj ",
(char *)NULL);
(void) Tcl_ListObjLength(NULL, concatPtr, &len);
switch (tmpPtr->refCount) {
case 3:
Tcl_AppendResult(interp, "(failed to concat)", (char *)NULL);
break;
default:
Tcl_AppendResult(interp, "(corrupted input!)", (char *)NULL);
}
if (Tcl_IsShared(tmpPtr)) {
Tcl_DecrRefCount(tmpPtr);
}
tmpPtr = Tcl_DuplicateObj(list1Ptr);
objv[0] = tmpPtr;
}
Tcl_DecrRefCount(concatPtr);
objv[0] = tmpPtr;
objv[1] = list2Ptr;
Tcl_IncrRefCount(tmpPtr);
concatPtr = Tcl_ConcatObj(2, objv);
if (concatPtr->refCount != 0) {
result = TCL_ERROR;
Tcl_AppendResult(interp,
"\n\t* (f) concatObj does not have refCount 0", (char *)NULL);
}
if (concatPtr == tmpPtr) {
result = TCL_ERROR;
Tcl_AppendResult(interp, "\n\t* (f) concatObj is not a new obj ",
(char *)NULL);
(void) Tcl_ListObjLength(NULL, concatPtr, &len);
switch (tmpPtr->refCount) {
case 3:
Tcl_AppendResult(interp, "(failed to concat)", (char *)NULL);
break;
default:
Tcl_AppendResult(interp, "(corrupted input!)", (char *)NULL);
}
if (Tcl_IsShared(tmpPtr)) {
Tcl_DecrRefCount(tmpPtr);
}
tmpPtr = Tcl_DuplicateObj(list1Ptr);
objv[0] = tmpPtr;
}
Tcl_DecrRefCount(concatPtr);
objv[0] = tmpPtr;
objv[1] = list2Ptr;
Tcl_IncrRefCount(tmpPtr);
Tcl_IncrRefCount(tmpPtr);
concatPtr = Tcl_ConcatObj(2, objv);
if (concatPtr->refCount != 0) {
result = TCL_ERROR;
Tcl_AppendResult(interp,
"\n\t* (g) concatObj does not have refCount 0", (char *)NULL);
}
if (concatPtr == tmpPtr) {
result = TCL_ERROR;
Tcl_AppendResult(interp, "\n\t* (g) concatObj is not a new obj ",
(char *)NULL);
(void) Tcl_ListObjLength(NULL, concatPtr, &len);
switch (tmpPtr->refCount) {
case 3:
Tcl_AppendResult(interp, "(failed to concat)", (char *)NULL);
break;
default:
Tcl_AppendResult(interp, "(corrupted input!)", (char *)NULL);
}
Tcl_DecrRefCount(tmpPtr);
if (Tcl_IsShared(tmpPtr)) {
Tcl_DecrRefCount(tmpPtr);
}
tmpPtr = Tcl_DuplicateObj(list1Ptr);
objv[0] = tmpPtr;
|
| ︙ | ︙ | |||
8236 8237 8238 8239 8240 8241 8242 |
TclSizeT objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Arguments. */
{
static int foo = 0;
Tcl_Size count = objc;
Tcl_Obj **remObjv, *result[3];
const Tcl_ArgvInfo argTable[] = {
| | | | | 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 |
TclSizeT objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Arguments. */
{
static int foo = 0;
Tcl_Size count = objc;
Tcl_Obj **remObjv, *result[3];
const Tcl_ArgvInfo argTable[] = {
{TCL_ARGV_CONSTANT, "-bool", INT2PTR(1), &foo, "booltest", NULL},
TCL_ARGV_AUTO_REST, TCL_ARGV_AUTO_HELP, TCL_ARGV_TABLE_END
};
foo = 0;
if (Tcl_ParseArgsObjv(interp, argTable, &count, objv, &remObjv)!=TCL_OK) {
return TCL_ERROR;
}
result[0] = Tcl_NewWideIntObj(foo);
result[1] = Tcl_NewWideIntObj(count);
result[2] = Tcl_NewListObj(count, remObjv);
Tcl_SetObjResult(interp, Tcl_NewListObj(3, result));
Tcl_Free(remObjv);
return TCL_OK;
|
| ︙ | ︙ | |||
8267 8268 8269 8270 8271 8272 8273 |
TCL_UNUSED(Tcl_Namespace *),
TCL_UNUSED(int) /* flags */,
Tcl_Command *rPtr)
{
Interp *iPtr = (Interp *) interp;
CallFrame *varFramePtr = iPtr->varFramePtr;
Proc *procPtr = (varFramePtr->isProcCallFrame & FRAME_IS_PROC) ?
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 |
TCL_UNUSED(Tcl_Namespace *),
TCL_UNUSED(int) /* flags */,
Tcl_Command *rPtr)
{
Interp *iPtr = (Interp *) interp;
CallFrame *varFramePtr = iPtr->varFramePtr;
Proc *procPtr = (varFramePtr->isProcCallFrame & FRAME_IS_PROC) ?
varFramePtr->procPtr : NULL;
Namespace *callerNsPtr = varFramePtr->nsPtr;
Tcl_Command resolvedCmdPtr = NULL;
/*
* Just do something special on a cmd literal "z" in two cases:
* A) when the caller is a proc "x", and the proc is either in "::" or in "::ns2".
* B) the caller's namespace is "ctx1" or "ctx2"
*/
if ( (name[0] == 'z') && (name[1] == '\0') ) {
Namespace *ns2NsPtr = (Namespace *) Tcl_FindNamespace(interp, "::ns2", NULL, 0);
if (procPtr != NULL
&& ((procPtr->cmdPtr->nsPtr == iPtr->globalNsPtr)
|| (ns2NsPtr != NULL && procPtr->cmdPtr->nsPtr == ns2NsPtr)
)
) {
/*
* Case A)
*
* - The context, in which this resolver becomes active, is
* determined by the name of the caller proc, which has to be
* named "x".
*
* - To determine the name of the caller proc, the proc is taken
* from the topmost stack frame.
*
* - Note that the context is NOT provided during byte-code
* compilation (e.g. in TclProcCompileProc)
*
* When these conditions hold, this function resolves the
* passed-in cmd literal into a cmd "y", which is taken from the
* the global namespace (for simplicity).
*/
const char *callingCmdName =
Tcl_GetCommandName(interp, (Tcl_Command) procPtr->cmdPtr);
if ( callingCmdName[0] == 'x' && callingCmdName[1] == '\0' ) {
resolvedCmdPtr = Tcl_FindCommand(interp, "y", NULL, TCL_GLOBAL_ONLY);
}
} else if (callerNsPtr != NULL) {
/*
* Case B)
*
* - The context, in which this resolver becomes active, is
* determined by the name of the parent namespace, which has
* to be named "ctx1" or "ctx2".
*
* - To determine the name of the parent namesace, it is taken
* from the 2nd highest stack frame.
*
* - Note that the context can be provided during byte-code
* compilation (e.g. in TclProcCompileProc)
*
* When these conditions hold, this function resolves the
* passed-in cmd literal into a cmd "y" or "Y" depending on the
* context. The resolved procs are taken from the the global
* namespace (for simplicity).
*/
CallFrame *parentFramePtr = varFramePtr->callerPtr;
const char *context = parentFramePtr != NULL ? parentFramePtr->nsPtr->name : "(NULL)";
if (strcmp(context, "ctx1") == 0 && (name[0] == 'z') && (name[1] == '\0')) {
resolvedCmdPtr = Tcl_FindCommand(interp, "y", NULL, TCL_GLOBAL_ONLY);
/* fprintf(stderr, "... y ==> %p\n", resolvedCmdPtr);*/
} else if (strcmp(context, "ctx2") == 0 && (name[0] == 'z') && (name[1] == '\0')) {
resolvedCmdPtr = Tcl_FindCommand(interp, "Y", NULL, TCL_GLOBAL_ONLY);
/*fprintf(stderr, "... Y ==> %p\n", resolvedCmdPtr);*/
}
}
if (resolvedCmdPtr != NULL) {
*rPtr = resolvedCmdPtr;
return TCL_OK;
}
}
return TCL_CONTINUE;
}
static int
InterpVarResolver(
TCL_UNUSED(Tcl_Interp *),
|
| ︙ | ︙ | |||
8375 8376 8377 8378 8379 8380 8381 |
} MyResolvedVarInfo;
static inline void
HashVarFree(
Tcl_Var var)
{
if (VarHashRefCount(var) < 2) {
| | | | | | | | | | | | | | | | | | 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 |
} MyResolvedVarInfo;
static inline void
HashVarFree(
Tcl_Var var)
{
if (VarHashRefCount(var) < 2) {
Tcl_Free(var);
} else {
VarHashRefCount(var)--;
}
}
static void
MyCompiledVarFree(
Tcl_ResolvedVarInfo *vInfoPtr)
{
MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *) vInfoPtr;
Tcl_DecrRefCount(resVarInfo->nameObj);
if (resVarInfo->var) {
HashVarFree(resVarInfo->var);
}
Tcl_Free(vInfoPtr);
}
#define TclVarHashGetValue(hPtr) \
((Var *) ((char *)hPtr - offsetof(VarInHash, entry)))
static Tcl_Var
MyCompiledVarFetch(
Tcl_Interp *interp,
Tcl_ResolvedVarInfo *vinfoPtr)
{
MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *) vinfoPtr;
Tcl_Var var = resVarInfo->var;
int isNewVar;
Interp *iPtr = (Interp *) interp;
Tcl_HashEntry *hPtr;
if (var != NULL) {
if (!(((Var *) var)->flags & VAR_DEAD_HASH)) {
/*
* The cached variable is valid, return it.
*/
return var;
}
/*
* The variable is not valid anymore. Clean it up.
*/
HashVarFree(var);
}
hPtr = Tcl_CreateHashEntry((Tcl_HashTable *) &iPtr->globalNsPtr->varTable,
resVarInfo->nameObj, &isNewVar);
if (hPtr) {
var = (Tcl_Var) TclVarHashGetValue(hPtr);
} else {
var = NULL;
}
resVarInfo->var = var;
/*
* Increment the reference counter to avoid Tcl_Free() of the variable in
* Tcl's FreeVarEntry(); for cleanup, we provide our own HashVarFree();
*/
|
| ︙ | ︙ | |||
8472 8473 8474 8475 8476 8477 8478 |
TestInterpResolverCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
TclSizeT objc,
Tcl_Obj *const objv[])
{
static const char *const table[] = {
| | | | | | | | | | | | | | 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 |
TestInterpResolverCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
TclSizeT objc,
Tcl_Obj *const objv[])
{
static const char *const table[] = {
"down", "up", NULL
};
int idx;
#define RESOLVER_KEY "testInterpResolver"
if ((objc < 2) || (objc > 3)) {
Tcl_WrongNumArgs(interp, 1, objv, "up|down ?interp?");
return TCL_ERROR;
}
if (objc == 3) {
interp = Tcl_GetChild(interp, Tcl_GetString(objv[2]));
if (interp == NULL) {
Tcl_AppendResult(interp, "provided interpreter not found", (char *)NULL);
return TCL_ERROR;
}
}
if (Tcl_GetIndexFromObj(interp, objv[1], table, "operation", TCL_EXACT,
&idx) != TCL_OK) {
return TCL_ERROR;
}
switch (idx) {
case 1: /* up */
Tcl_AddInterpResolvers(interp, RESOLVER_KEY, InterpCmdResolver,
InterpVarResolver, InterpCompiledVarResolver);
break;
case 0: /*down*/
if (!Tcl_RemoveInterpResolvers(interp, RESOLVER_KEY)) {
Tcl_AppendResult(interp, "could not remove the resolver scheme",
(char *)NULL);
return TCL_ERROR;
}
}
return TCL_OK;
}
/*
*------------------------------------------------------------------------
*
|
| ︙ | ︙ |
Changes to generic/tclTimer.c.
| ︙ | ︙ | |||
889 890 891 892 893 894 895 |
return TCL_ERROR;
}
if (objc == 3) {
commandPtr = objv[2];
} else {
commandPtr = Tcl_ConcatObj(objc-2, objv+2);
}
| | | | 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 |
return TCL_ERROR;
}
if (objc == 3) {
commandPtr = objv[2];
} else {
commandPtr = Tcl_ConcatObj(objc-2, objv+2);
}
command = TclGetStringFromObj(commandPtr, &length);
for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL;
afterPtr = afterPtr->nextPtr) {
tempCommand = TclGetStringFromObj(afterPtr->commandPtr,
&tempLength);
if ((length == tempLength)
&& !memcmp(command, tempCommand, length)) {
break;
}
}
if (afterPtr == NULL) {
|
| ︙ | ︙ |
Changes to generic/tclTomMath.decls.
| ︙ | ︙ | |||
73 74 75 76 77 78 79 |
declare 16 {
mp_err MP_WUR TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, mp_int *r)
}
declare 18 {
void TclBN_mp_exch(mp_int *a, mp_int *b)
}
declare 19 {
| | | 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
declare 16 {
mp_err MP_WUR TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, mp_int *r)
}
declare 18 {
void TclBN_mp_exch(mp_int *a, mp_int *b)
}
declare 19 {
mp_err MP_WUR TclBN_mp_expt_n(const mp_int *a, int b, mp_int *c)
}
declare 20 {
mp_err MP_WUR TclBN_mp_grow(mp_int *a, int size)
}
declare 21 {
mp_err MP_WUR TclBN_mp_init(mp_int *a)
}
|
| ︙ | ︙ |
Changes to generic/tclTomMathDecls.h.
| ︙ | ︙ | |||
59 60 61 62 63 64 65 |
# define MODULE_SCOPE extern
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
| | | > | > | | | | | | | | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# define MODULE_SCOPE extern
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
MODULE_SCOPE mp_err TclBN_mp_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE mp_err TclBN_mp_div_3(const mp_int *a, mp_int *q, mp_digit *r);
MODULE_SCOPE mp_err TclBN_mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c);
MODULE_SCOPE mp_err TclBN_s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE mp_err TclBN_s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d);
MODULE_SCOPE mp_err TclBN_s_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE mp_err TclBN_s_mp_karatsuba_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE mp_err TclBN_s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE mp_err TclBN_s_mp_toom_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE mp_err TclBN_s_mp_add(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE mp_err TclBN_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs);
MODULE_SCOPE mp_err TclBN_s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs);
MODULE_SCOPE void TclBN_s_mp_reverse(unsigned char *s, size_t len);
MODULE_SCOPE mp_err TclBN_s_mp_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE mp_err TclBN_s_mp_sqr_fast(const mp_int *a, mp_int *b);
MODULE_SCOPE mp_err TclBN_s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE const char *const TclBN_mp_s_rmap;
MODULE_SCOPE const uint8_t TclBN_mp_s_rmap_reverse[];
MODULE_SCOPE const size_t TclBN_mp_s_rmap_reverse_sz;
MODULE_SCOPE mp_err TclBN_mp_set_int(mp_int *a, unsigned long b);
#ifdef __cplusplus
}
#endif
|
| ︙ | ︙ | |||
106 107 108 109 110 111 112 113 114 115 116 117 118 119 | #define mp_div_2 TclBN_mp_div_2 #define mp_div_3 TclBN_mp_div_3 #define mp_div_2d TclBN_mp_div_2d #define mp_exch TclBN_mp_exch #define mp_expt_d TclBN_mp_expt_d #define mp_expt_d_ex TclBN_mp_expt_d_ex #define mp_expt_u32 TclBN_mp_expt_u32 #define mp_get_mag_u64 TclBN_mp_get_mag_u64 #define mp_grow TclBN_mp_grow #define mp_init TclBN_mp_init #define mp_init_copy TclBN_mp_init_copy #define mp_init_i64 TclBN_mp_init_i64 #define mp_init_multi TclBN_mp_init_multi #define mp_init_set TclBN_mp_init_set | > | 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | #define mp_div_2 TclBN_mp_div_2 #define mp_div_3 TclBN_mp_div_3 #define mp_div_2d TclBN_mp_div_2d #define mp_exch TclBN_mp_exch #define mp_expt_d TclBN_mp_expt_d #define mp_expt_d_ex TclBN_mp_expt_d_ex #define mp_expt_u32 TclBN_mp_expt_u32 #define mp_expt_n TclBN_mp_expt_n #define mp_get_mag_u64 TclBN_mp_get_mag_u64 #define mp_grow TclBN_mp_grow #define mp_init TclBN_mp_init #define mp_init_copy TclBN_mp_init_copy #define mp_init_i64 TclBN_mp_init_i64 #define mp_init_multi TclBN_mp_init_multi #define mp_init_set TclBN_mp_init_set |
| ︙ | ︙ | |||
155 156 157 158 159 160 161 | #define mp_to_radix TclBN_mp_to_radix #define mp_to_ubin TclBN_mp_to_ubin #define mp_ubin_size TclBN_mp_ubin_size #define mp_unpack TclBN_mp_unpack #define mp_xor TclBN_mp_xor #define mp_zero TclBN_mp_zero #define s_mp_add TclBN_s_mp_add | | > | | | | | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | #define mp_to_radix TclBN_mp_to_radix #define mp_to_ubin TclBN_mp_to_ubin #define mp_ubin_size TclBN_mp_ubin_size #define mp_unpack TclBN_mp_unpack #define mp_xor TclBN_mp_xor #define mp_zero TclBN_mp_zero #define s_mp_add TclBN_s_mp_add #define s_mp_balance_mul TclBN_s_mp_balance_mul #define s_mp_div_3 TclBN_s_mp_div_3 #define s_mp_karatsuba_mul TclBN_s_mp_karatsuba_mul #define s_mp_karatsuba_sqr TclBN_s_mp_karatsuba_sqr #define s_mp_mul_digs TclBN_s_mp_mul_digs #define s_mp_mul_digs_fast TclBN_s_mp_mul_digs_fast #define s_mp_reverse TclBN_s_mp_reverse #define s_mp_sqr TclBN_s_mp_sqr #define s_mp_sqr_fast TclBN_s_mp_sqr_fast #define s_mp_sub TclBN_s_mp_sub #define s_mp_toom_mul TclBN_s_mp_toom_mul #define s_mp_toom_sqr TclBN_s_mp_toom_sqr #endif /* !TCL_WITH_EXTERNAL_TOMMATH */ #undef TCL_STORAGE_CLASS #ifdef BUILD_tcl # define TCL_STORAGE_CLASS DLLEXPORT #else # ifdef USE_TCL_STUBS |
| ︙ | ︙ | |||
239 240 241 242 243 244 245 | /* 16 */ EXTERN mp_err TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, mp_int *r) MP_WUR; /* Slot 17 is reserved */ /* 18 */ EXTERN void TclBN_mp_exch(mp_int *a, mp_int *b); /* 19 */ | | < | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | /* 16 */ EXTERN mp_err TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, mp_int *r) MP_WUR; /* Slot 17 is reserved */ /* 18 */ EXTERN void TclBN_mp_exch(mp_int *a, mp_int *b); /* 19 */ EXTERN mp_err TclBN_mp_expt_n(const mp_int *a, int b, mp_int *c) MP_WUR; /* 20 */ EXTERN mp_err TclBN_mp_grow(mp_int *a, int size) MP_WUR; /* 21 */ EXTERN mp_err TclBN_mp_init(mp_int *a) MP_WUR; /* 22 */ EXTERN mp_err TclBN_mp_init_copy(mp_int *a, const mp_int *b) MP_WUR; /* 23 */ |
| ︙ | ︙ | |||
382 383 384 385 386 387 388 |
int (*tclBN_mp_count_bits) (const mp_int *a) MP_WUR; /* 12 */
mp_err (*tclBN_mp_div) (const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) MP_WUR; /* 13 */
mp_err (*tclBN_mp_div_d) (const mp_int *a, mp_digit b, mp_int *q, mp_digit *r) MP_WUR; /* 14 */
mp_err (*tclBN_mp_div_2) (const mp_int *a, mp_int *q) MP_WUR; /* 15 */
mp_err (*tclBN_mp_div_2d) (const mp_int *a, int b, mp_int *q, mp_int *r) MP_WUR; /* 16 */
void (*reserved17)(void);
void (*tclBN_mp_exch) (mp_int *a, mp_int *b); /* 18 */
| | | 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 |
int (*tclBN_mp_count_bits) (const mp_int *a) MP_WUR; /* 12 */
mp_err (*tclBN_mp_div) (const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) MP_WUR; /* 13 */
mp_err (*tclBN_mp_div_d) (const mp_int *a, mp_digit b, mp_int *q, mp_digit *r) MP_WUR; /* 14 */
mp_err (*tclBN_mp_div_2) (const mp_int *a, mp_int *q) MP_WUR; /* 15 */
mp_err (*tclBN_mp_div_2d) (const mp_int *a, int b, mp_int *q, mp_int *r) MP_WUR; /* 16 */
void (*reserved17)(void);
void (*tclBN_mp_exch) (mp_int *a, mp_int *b); /* 18 */
mp_err (*tclBN_mp_expt_n) (const mp_int *a, int b, mp_int *c) MP_WUR; /* 19 */
mp_err (*tclBN_mp_grow) (mp_int *a, int size) MP_WUR; /* 20 */
mp_err (*tclBN_mp_init) (mp_int *a) MP_WUR; /* 21 */
mp_err (*tclBN_mp_init_copy) (mp_int *a, const mp_int *b) MP_WUR; /* 22 */
mp_err (*tclBN_mp_init_multi) (mp_int *a, ...) MP_WUR; /* 23 */
mp_err (*tclBN_mp_init_set) (mp_int *a, mp_digit b) MP_WUR; /* 24 */
mp_err (*tclBN_mp_init_size) (mp_int *a, int size) MP_WUR; /* 25 */
mp_err (*tclBN_mp_lshd) (mp_int *a, int shift) MP_WUR; /* 26 */
|
| ︙ | ︙ | |||
495 496 497 498 499 500 501 | #define TclBN_mp_div_2 \ (tclTomMathStubsPtr->tclBN_mp_div_2) /* 15 */ #define TclBN_mp_div_2d \ (tclTomMathStubsPtr->tclBN_mp_div_2d) /* 16 */ /* Slot 17 is reserved */ #define TclBN_mp_exch \ (tclTomMathStubsPtr->tclBN_mp_exch) /* 18 */ | | | | 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 | #define TclBN_mp_div_2 \ (tclTomMathStubsPtr->tclBN_mp_div_2) /* 15 */ #define TclBN_mp_div_2d \ (tclTomMathStubsPtr->tclBN_mp_div_2d) /* 16 */ /* Slot 17 is reserved */ #define TclBN_mp_exch \ (tclTomMathStubsPtr->tclBN_mp_exch) /* 18 */ #define TclBN_mp_expt_n \ (tclTomMathStubsPtr->tclBN_mp_expt_n) /* 19 */ #define TclBN_mp_grow \ (tclTomMathStubsPtr->tclBN_mp_grow) /* 20 */ #define TclBN_mp_init \ (tclTomMathStubsPtr->tclBN_mp_init) /* 21 */ #define TclBN_mp_init_copy \ (tclTomMathStubsPtr->tclBN_mp_init_copy) /* 22 */ #define TclBN_mp_init_multi \ |
| ︙ | ︙ |
Changes to generic/tclUtf.c.
| ︙ | ︙ | |||
674 675 676 677 678 679 680 |
wString = (int *) (Tcl_DStringValue(dsPtr) + oldLength);
w = wString;
p = src;
endPtr = src + length;
optPtr = endPtr - 4;
while (p <= optPtr) {
| | | | 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 |
wString = (int *) (Tcl_DStringValue(dsPtr) + oldLength);
w = wString;
p = src;
endPtr = src + length;
optPtr = endPtr - 4;
while (p <= optPtr) {
p += TclUtfToUniChar(p, &ch);
*w++ = ch;
}
while ((p < endPtr) && Tcl_UtfCharComplete(p, endPtr-p)) {
p += TclUtfToUniChar(p, &ch);
*w++ = ch;
}
while (p < endPtr) {
*w++ = UCHAR(*p++);
}
*w = '\0';
Tcl_DStringSetLength(dsPtr,
|
| ︙ | ︙ | |||
924 925 926 927 928 929 930 |
const char *
Tcl_UtfFindFirst(
const char *src, /* The UTF-8 string to be searched. */
int ch) /* The Unicode character to search for. */
{
while (1) {
| | | 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 |
const char *
Tcl_UtfFindFirst(
const char *src, /* The UTF-8 string to be searched. */
int ch) /* The Unicode character to search for. */
{
while (1) {
int find, len = TclUtfToUniChar(src, &find);
if (find == ch) {
return src;
}
if (*src == '\0') {
return NULL;
}
|
| ︙ | ︙ | |||
963 964 965 966 967 968 969 |
Tcl_UtfFindLast(
const char *src, /* The UTF-8 string to be searched. */
int ch) /* The Unicode character to search for. */
{
const char *last = NULL;
while (1) {
| | | 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 |
Tcl_UtfFindLast(
const char *src, /* The UTF-8 string to be searched. */
int ch) /* The Unicode character to search for. */
{
const char *last = NULL;
while (1) {
int find, len = TclUtfToUniChar(src, &find);
if (find == ch) {
last = src;
}
if (*src == '\0') {
break;
}
|
| ︙ | ︙ | |||
1186 1187 1188 1189 1190 1191 1192 |
if (index < 0) {
return -1;
}
while (index--) {
i = TclUtfToUniChar(src, &ch);
src += i;
}
| | | 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 |
if (index < 0) {
return -1;
}
while (index--) {
i = TclUtfToUniChar(src, &ch);
src += i;
}
TclUtfToUniChar(src, &i);
return i;
}
/*
*---------------------------------------------------------------------------
*
* Tcl_UtfAtIndex --
|
| ︙ | ︙ | |||
1215 1216 1217 1218 1219 1220 1221 |
Tcl_UtfAtIndex(
const char *src, /* The UTF-8 string. */
Tcl_Size index) /* The position of the desired character. */
{
Tcl_UniChar ch = 0;
while (index-- > 0) {
| | | 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 |
Tcl_UtfAtIndex(
const char *src, /* The UTF-8 string. */
Tcl_Size index) /* The position of the desired character. */
{
Tcl_UniChar ch = 0;
while (index-- > 0) {
src += TclUtfToUniChar(src, &ch);
}
return src;
}
const char *
TclUtfAtIndex(
const char *src, /* The UTF-8 string. */
|
| ︙ | ︙ | |||
1325 1326 1327 1328 1329 1330 1331 |
/*
* Iterate over the string until we hit the terminating null.
*/
src = dst = str;
while (*src) {
| | | 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 |
/*
* Iterate over the string until we hit the terminating null.
*/
src = dst = str;
while (*src) {
len = TclUtfToUniChar(src, &ch);
upChar = Tcl_UniCharToUpper(ch);
/*
* To keep badly formed Utf strings from getting inflated by the
* conversion (thereby causing a segfault), only copy the upper case
* char to dst if its size is <= the original char.
*/
|
| ︙ | ︙ | |||
1378 1379 1380 1381 1382 1383 1384 |
/*
* Iterate over the string until we hit the terminating null.
*/
src = dst = str;
while (*src) {
| | | 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 |
/*
* Iterate over the string until we hit the terminating null.
*/
src = dst = str;
while (*src) {
len = TclUtfToUniChar(src, &ch);
lowChar = Tcl_UniCharToLower(ch);
/*
* To keep badly formed Utf strings from getting inflated by the
* conversion (thereby causing a segfault), only copy the lower case
* char to dst if its size is <= the original char.
*/
|
| ︙ | ︙ | |||
1434 1435 1436 1437 1438 1439 1440 |
* Capitalize the first character and then lowercase the rest of the
* characters until we get to a null.
*/
src = dst = str;
if (*src) {
| | | | 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 |
* Capitalize the first character and then lowercase the rest of the
* characters until we get to a null.
*/
src = dst = str;
if (*src) {
len = TclUtfToUniChar(src, &ch);
titleChar = Tcl_UniCharToTitle(ch);
if (len < TclUtfCount(titleChar)) {
memmove(dst, src, len);
dst += len;
} else {
dst += Tcl_UniCharToUtf(titleChar, dst);
}
src += len;
}
while (*src) {
len = TclUtfToUniChar(src, &ch);
lowChar = ch;
/* Special exception for Georgian Asomtavruli chars, no titlecase. */
if ((unsigned)(lowChar - 0x1C90) >= 0x30) {
lowChar = Tcl_UniCharToLower(lowChar);
}
if (len < TclUtfCount(lowChar)) {
|
| ︙ | ︙ |
Changes to generic/tclUtil.c.
| ︙ | ︙ | |||
1668 1669 1670 1671 1672 1673 1674 |
do {
const char *q = trim;
Tcl_Size pInc = 0, bytesLeft = numTrim;
pp = Tcl_UtfPrev(p, bytes);
do {
pp += pInc;
| | | | 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 |
do {
const char *q = trim;
Tcl_Size pInc = 0, bytesLeft = numTrim;
pp = Tcl_UtfPrev(p, bytes);
do {
pp += pInc;
pInc = TclUtfToUniChar(pp, &ch1);
} while (pp + pInc < p);
/*
* Inner loop: scan trim string for match to current character.
*/
do {
pInc = TclUtfToUniChar(q, &ch2);
if (ch1 == ch2) {
break;
}
q += pInc;
bytesLeft -= pInc;
|
| ︙ | ︙ | |||
1741 1742 1743 1744 1745 1746 1747 |
}
/*
* Outer loop: iterate over string to be trimmed.
*/
do {
| | | | 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 |
}
/*
* Outer loop: iterate over string to be trimmed.
*/
do {
Tcl_Size pInc = TclUtfToUniChar(p, &ch1);
const char *q = trim;
Tcl_Size bytesLeft = numTrim;
/*
* Inner loop: scan trim string for match to current character.
*/
do {
Tcl_Size qInc = TclUtfToUniChar(q, &ch2);
if (ch1 == ch2) {
break;
}
q += qInc;
bytesLeft -= qInc;
|
| ︙ | ︙ | |||
1817 1818 1819 1820 1821 1822 1823 |
numBytes -= trimLeft;
/* If we did not trim the whole string, it starts with a character
* that we will not trim. Skip over it. */
if (numBytes > 0) {
int ch;
const char *first = bytes + trimLeft;
| | | 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 |
numBytes -= trimLeft;
/* If we did not trim the whole string, it starts with a character
* that we will not trim. Skip over it. */
if (numBytes > 0) {
int ch;
const char *first = bytes + trimLeft;
bytes += TclUtfToUniChar(first, &ch);
numBytes -= (bytes - first);
if (numBytes > 0) {
/* When bytes is NUL-terminated, returns
* 0 <= trimRight <= numBytes */
trimRight = TclTrimRight(bytes, numBytes, trim, numTrim);
}
|
| ︙ | ︙ | |||
2147 2148 2149 2150 2151 2152 2153 |
* This is a special case optimization for single-byte utf.
*/
if (UCHAR(*pattern) < 0x80) {
ch2 = (int)
(nocase ? tolower(UCHAR(*pattern)) : UCHAR(*pattern));
} else {
| | | | | | | | | | 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 |
* This is a special case optimization for single-byte utf.
*/
if (UCHAR(*pattern) < 0x80) {
ch2 = (int)
(nocase ? tolower(UCHAR(*pattern)) : UCHAR(*pattern));
} else {
TclUtfToUniChar(pattern, &ch2);
if (nocase) {
ch2 = Tcl_UniCharToLower(ch2);
}
}
while (1) {
/*
* Optimization for matching - cruise through the string
* quickly if the next char in the pattern isn't a special
* character
*/
if ((p != '[') && (p != '?') && (p != '\\')) {
if (nocase) {
while (*str) {
charLen = TclUtfToUniChar(str, &ch1);
if (ch2==ch1 || ch2==Tcl_UniCharToLower(ch1)) {
break;
}
str += charLen;
}
} else {
/*
* There's no point in trying to make this code
* shorter, as the number of bytes you want to compare
* each time is non-constant.
*/
while (*str) {
charLen = TclUtfToUniChar(str, &ch1);
if (ch2 == ch1) {
break;
}
str += charLen;
}
}
}
if (Tcl_StringCaseMatch(str, pattern, nocase)) {
return 1;
}
if (*str == '\0') {
return 0;
}
str += TclUtfToUniChar(str, &ch1);
}
}
/*
* Check for a "?" as the next pattern character. It matches any
* single character.
*/
if (p == '?') {
pattern++;
str += TclUtfToUniChar(str, &ch1);
continue;
}
/*
* Check for a "[" as the next pattern character. It is followed by a
* list of characters that are acceptable, or by a range (two
* characters separated by "-").
*/
if (p == '[') {
int startChar = 0, endChar = 0;
pattern++;
if (UCHAR(*str) < 0x80) {
ch1 = (int)
(nocase ? tolower(UCHAR(*str)) : UCHAR(*str));
str++;
} else {
str += TclUtfToUniChar(str, &ch1);
if (nocase) {
ch1 = Tcl_UniCharToLower(ch1);
}
}
while (1) {
if ((*pattern == ']') || (*pattern == '\0')) {
return 0;
}
if (UCHAR(*pattern) < 0x80) {
startChar = (int) (nocase
? tolower(UCHAR(*pattern)) : UCHAR(*pattern));
pattern++;
} else {
pattern += TclUtfToUniChar(pattern, &startChar);
if (nocase) {
startChar = Tcl_UniCharToLower(startChar);
}
}
if (*pattern == '-') {
pattern++;
if (*pattern == '\0') {
return 0;
}
if (UCHAR(*pattern) < 0x80) {
endChar = (int) (nocase
? tolower(UCHAR(*pattern)) : UCHAR(*pattern));
pattern++;
} else {
pattern += TclUtfToUniChar(pattern, &endChar);
if (nocase) {
endChar = Tcl_UniCharToLower(endChar);
}
}
if (((startChar <= ch1) && (ch1 <= endChar))
|| ((endChar <= ch1) && (ch1 <= startChar))) {
/*
|
| ︙ | ︙ | |||
2298 2299 2300 2301 2302 2303 2304 | } /* * There's no special character. Just make sure that the next bytes of * each string match. */ | | | | 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 |
}
/*
* There's no special character. Just make sure that the next bytes of
* each string match.
*/
str += TclUtfToUniChar(str, &ch1);
pattern += TclUtfToUniChar(pattern, &ch2);
if (nocase) {
if (Tcl_UniCharToLower(ch1) != Tcl_UniCharToLower(ch2)) {
return 0;
}
} else if (ch1 != ch2) {
return 0;
}
|
| ︙ | ︙ |
Changes to generic/tclZlib.c.
| ︙ | ︙ | |||
440 441 442 443 444 445 446 |
Tcl_Panic("no latin-1 encoding");
}
if (GetValue(interp, dictObj, "comment", &value) != TCL_OK) {
goto error;
} else if (value != NULL) {
Tcl_EncodingState state;
| | | 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 |
Tcl_Panic("no latin-1 encoding");
}
if (GetValue(interp, dictObj, "comment", &value) != TCL_OK) {
goto error;
} else if (value != NULL) {
Tcl_EncodingState state;
valueStr = TclGetStringFromObj(value, &length);
result = Tcl_UtfToExternal(NULL, latin1enc, valueStr, length,
TCL_ENCODING_START|TCL_ENCODING_END|TCL_ENCODING_PROFILE_STRICT, &state,
headerPtr->nativeCommentBuf, MAX_COMMENT_LEN-1, NULL, &len,
NULL);
if (result != TCL_OK) {
if (interp) {
if (result == TCL_CONVERT_UNKNOWN) {
|
| ︙ | ︙ | |||
475 476 477 478 479 480 481 |
goto error;
}
if (GetValue(interp, dictObj, "filename", &value) != TCL_OK) {
goto error;
} else if (value != NULL) {
Tcl_EncodingState state;
| | | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 |
goto error;
}
if (GetValue(interp, dictObj, "filename", &value) != TCL_OK) {
goto error;
} else if (value != NULL) {
Tcl_EncodingState state;
valueStr = TclGetStringFromObj(value, &length);
result = Tcl_UtfToExternal(NULL, latin1enc, valueStr, length,
TCL_ENCODING_START|TCL_ENCODING_END|TCL_ENCODING_PROFILE_STRICT, &state,
headerPtr->nativeFilenameBuf, MAXPATHLEN-1, NULL, &len,
NULL);
if (result != TCL_OK) {
if (interp) {
if (result == TCL_CONVERT_UNKNOWN) {
|
| ︙ | ︙ | |||
3518 3519 3520 3521 3522 3523 3524 |
TclGetString(cd->compDictObj));
} else {
Tcl_DStringAppendElement(dsPtr, "");
}
} else {
if (cd->compDictObj) {
Tcl_Size length;
| | | 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 |
TclGetString(cd->compDictObj));
} else {
Tcl_DStringAppendElement(dsPtr, "");
}
} else {
if (cd->compDictObj) {
Tcl_Size length;
const char *str = TclGetStringFromObj(cd->compDictObj, &length);
Tcl_DStringAppend(dsPtr, str, length);
}
return TCL_OK;
}
}
|
| ︙ | ︙ |
Changes to library/clock.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #---------------------------------------------------------------------- # # clock.tcl -- # # This file implements the portions of the [clock] ensemble that are # coded in Tcl. Refer to the users' manual to see the description of # the [clock] command and its subcommands. # # #---------------------------------------------------------------------- # # Copyright © 2004-2007 Kevin B. Kenny # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # #---------------------------------------------------------------------- | > | < < | < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#----------------------------------------------------------------------
#
# clock.tcl --
#
# This file implements the portions of the [clock] ensemble that are
# coded in Tcl. Refer to the users' manual to see the description of
# the [clock] command and its subcommands.
#
#
#----------------------------------------------------------------------
#
# Copyright © 2004-2007 Kevin B. Kenny
# Copyright © 2015 Sergey G. Brester aka sebres.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#----------------------------------------------------------------------
# msgcat 1.7 features are used.
package require msgcat 1.7
# Put the library directory into the namespace for the ensemble so that the
# library code can find message catalogs and time zone definition files.
namespace eval ::tcl::clock \
[list variable LibDir [info library]]
|
| ︙ | ︙ | |||
54 55 56 57 58 59 60 |
namespace export milliseconds
namespace export scan
namespace export seconds
namespace export add
# Import the message catalog commands that we use.
| < < | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
namespace export milliseconds
namespace export scan
namespace export seconds
namespace export add
# Import the message catalog commands that we use.
namespace import ::msgcat::mclocale
namespace import ::msgcat::mcpackagelocale
}
#----------------------------------------------------------------------
#
# ::tcl::clock::Initialize --
|
| ︙ | ︙ | |||
283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
variable MINWIDE -9223372036854775808
variable MAXWIDE 9223372036854775807
# Day before Leap Day
variable FEB_28 58
# Translation table to map Windows TZI onto cities, so that the Olson
# rules can apply. In some cases the mapping is ambiguous, so it's wise
# to specify $::env(TCL_TZ) rather than simply depending on the system
# time zone.
# The keys are long lists of values obtained from the time zone
# information in the Registry. In order, the list elements are:
| > > > > > > > | 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
variable MINWIDE -9223372036854775808
variable MAXWIDE 9223372036854775807
# Day before Leap Day
variable FEB_28 58
# Default configuration
::tcl::unsupported::clock::configure -current-locale [mclocale]
#::tcl::unsupported::clock::configure -default-locale C
#::tcl::unsupported::clock::configure -year-century 2000 \
# -century-switch 38
# Translation table to map Windows TZI onto cities, so that the Olson
# rules can apply. In some cases the mapping is ambiguous, so it's wise
# to specify $::env(TCL_TZ) rather than simply depending on the system
# time zone.
# The keys are long lists of values obtained from the time zone
# information in the Registry. In order, the list elements are:
|
| ︙ | ︙ | |||
379 380 381 382 383 384 385 |
{36000 0 3600 0 3 0 5 3 0 0 0 0 10 0 5 2 0 0 0} :Australia/Sydney
{39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Noumea
{43200 0 3600 0 3 0 3 3 0 0 0 0 10 0 1 2 0 0 0} :Pacific/Auckland
{43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Fiji
{46800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Tongatapu
}]
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 377 378 379 380 381 382 383 384 385 386 387 388 389 390 |
{36000 0 3600 0 3 0 5 3 0 0 0 0 10 0 5 2 0 0 0} :Australia/Sydney
{39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Noumea
{43200 0 3600 0 3 0 3 3 0 0 0 0 10 0 1 2 0 0 0} :Pacific/Auckland
{43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Fiji
{46800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Tongatapu
}]
# Legacy time zones, used primarily for parsing RFC822 dates.
variable LegacyTimeZone [dict create \
gmt +0000 \
ut +0000 \
utc +0000 \
bst +0100 \
|
| ︙ | ︙ | |||
621 622 623 624 625 626 627 |
x -1100 \
y -1200 \
z +0000 \
]
# Caches
| | | < < < < < < < < | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < | < < < < < < < < < < < < < > | | > > | < < < < < > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < | < | < < < < < > > | < | > | < | | < | < < | < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | < < < < < < < < < < < | < < < < | < | < < | < < < < < < < < < < < < < < | < | < < < < < < < < < < < < < < < < < | < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < | | | < < < < < < < < < < < < < < < < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < | < < | | < < | < < < < | < < < < < < < < < < < < < < < < < | < < < | < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < | < < < < < < < < < < < < | < < | < < < < < < > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | | < < < < < < | < | < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < | < < < < < < < < | | < < < < < < < < < < < < < < < < < < < | < < | < < < < < | < < < > | < < < < < < < < < < | < < < < | < < < < < < < < | < < | < < < < < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < | < < < < < < < < < < < < < < < < | | | < < < < < < < < < < | | < < < | < < < < | < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < | < < < < | < < < < < < < < < < < < < < < < < < < < | < < < | < | < < < < | < < < < < < < < < < < < < < < < < < < < < < | | < < < < < < < < | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < | < < < < < < < < < | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | < | | < | < < < < < | > | > | | > > > > > | | > > | > | > > | > > > | > > | < < > | < | 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 |
x -1100 \
y -1200 \
z +0000 \
]
# Caches
variable LocFmtMap [dict create]; # Dictionary with localized format maps
variable TimeZoneBad [dict create]; # Dictionary whose keys are time zone
# names and whose values are 1 if
# the time zone is unknown and 0
# if it is known.
variable TZData; # Array whose keys are time zone names
# and whose values are lists of quads
# comprising start time, UTC offset,
# Daylight Saving Time indicator, and
# time zone abbreviation.
variable mcLocales [dict create]; # Dictionary with loaded locales
variable mcMergedCat [dict create]; # Dictionary with merged locale catalogs
}
::tcl::clock::Initialize
#----------------------------------------------------------------------
# mcget --
#
# Return the merged translation catalog for the ::tcl::clock namespace
# Searching of catalog is similar to "msgcat::mc".
#
# Contrary to "msgcat::mc" may additionally load a package catalog
# on demand.
#
# Arguments:
# loc The locale used for translation.
#
# Results:
# Returns the dictionary object as whole catalog of the package/locale.
#
proc ::tcl::clock::mcget {loc} {
variable mcMergedCat
switch -- $loc system {
set loc [GetSystemLocale]
} current {
set loc [mclocale]
}
if {$loc ne {}} {
set loc [string tolower $loc]
}
# try to retrieve now if already available:
if {[dict exists $mcMergedCat $loc]} {
return [dict get $mcMergedCat $loc]
}
# get locales list for given locale (de_de -> {de_de de {}})
variable mcLocales
if {[dict exists $mcLocales $loc]} {
set loclist [dict get $mcLocales $loc]
} else {
# save current locale:
set prevloc [mclocale]
# lazy load catalog on demand (set it will load the catalog)
mcpackagelocale set $loc
set loclist [msgcat::mcutil::getpreferences $loc]
dict set $mcLocales $loc $loclist
# restore:
if {$prevloc ne $loc} {
mcpackagelocale set $prevloc
}
}
# get whole catalog:
mcMerge $loclist
}
# mcMerge --
#
# Merge message catalog dictionaries to one dictionary.
#
# Arguments:
# locales List of locales to merge.
#
# Results:
# Returns the (weak pointer) to merged dictionary of message catalog.
#
proc ::tcl::clock::mcMerge {locales} {
variable mcMergedCat
if {[dict exists $mcMergedCat [set loc [lindex $locales 0]]]} {
return [dict get $mcMergedCat $loc]
}
# package msgcat currently does not provide possibility to get whole catalog:
upvar ::msgcat::Msgs Msgs
set ns ::tcl::clock
# Merge sequential locales (in reverse order, e. g. {} -> en -> en_en):
if {[llength $locales] > 1} {
set mrgcat [mcMerge [lrange $locales 1 end]]
if {[dict exists $Msgs $ns $loc]} {
set mrgcat [dict merge $mrgcat [dict get $Msgs $ns $loc]]
dict set mrgcat L $loc
} else {
# be sure a duplicate is created, don't overwrite {} (common) locale:
set mrgcat [dict merge $mrgcat [dict create L $loc]]
}
} else {
if {[dict exists $Msgs $ns $loc]} {
set mrgcat [dict get $Msgs $ns $loc]
dict set mrgcat L $loc
} else {
# be sure a duplicate is created, don't overwrite {} (common) locale:
set mrgcat [dict create L $loc]
}
}
dict set mcMergedCat $loc $mrgcat
# return smart reference (shared dict as object with exact one ref-counter)
return $mrgcat
}
#----------------------------------------------------------------------
#
# GetSystemLocale --
#
# Determines the system locale, which corresponds to "system"
# keyword for locale parameter of 'clock' command.
#
# Parameters:
# None.
#
# Results:
# Returns the system locale.
#
# Side effects:
# None.
#
#----------------------------------------------------------------------
proc ::tcl::clock::GetSystemLocale {} {
if { $::tcl_platform(platform) ne {windows} } {
# On a non-windows platform, the 'system' locale is the same as
# the 'current' locale
return [mclocale]
}
# On a windows platform, the 'system' locale is adapted from the
# 'current' locale by applying the date and time formats from the
# Control Panel. First, load the 'current' locale if it's not yet
# loaded
mcpackagelocale set [mclocale]
# Make a new locale string for the system locale, and get the
# Control Panel information
set locale [mclocale]_windows
if { ! [mcpackagelocale present $locale] } {
LoadWindowsDateTimeFormats $locale
}
return $locale
}
#----------------------------------------------------------------------
#
# EnterLocale --
#
# Switch [mclocale] to a given locale if necessary
#
# Parameters:
# locale -- Desired locale
#
# Results:
# Returns the locale that was previously current.
#
# Side effects:
# Does [mclocale]. If necessary, loades the designated locale's files.
#
#----------------------------------------------------------------------
proc ::tcl::clock::EnterLocale { locale } {
switch -- $locale system {
set locale [GetSystemLocale]
} current {
set locale [mclocale]
}
# Select the locale, eventually load it
mcpackagelocale set $locale
return $locale
}
#----------------------------------------------------------------------
#
# _hasRegistry --
#
# Helper that checks whether registry module is available (Windows only)
# and loads it on demand.
#
#----------------------------------------------------------------------
proc ::tcl::clock::_hasRegistry {} {
set res 0
if { $::tcl_platform(platform) eq {windows} } {
if { [catch { package require registry 1.1 }] } {
# try to load registry directly from root (if uninstalled / development env):
if {[regexp {[/\\]library$} [info library]]} {catch {
load [lindex \
[glob -tails -directory [file dirname [info nameofexecutable]] \
tclreg*[expr {[::tcl::pkgconfig get debug] ? {g} : {}}].dll] 0 \
] registry
}}
}
if { [namespace which -command ::registry] ne "" } {
set res 1
}
}
proc ::tcl::clock::_hasRegistry {} [list return $res]
return $res
}
#----------------------------------------------------------------------
#
# LoadWindowsDateTimeFormats --
#
# Load the date/time formats from the Control Panel in Windows and
|
| ︙ | ︙ | |||
2359 2360 2361 2362 2363 2364 2365 |
# default strings can be obtained if the Registry query fails.
#
#----------------------------------------------------------------------
proc ::tcl::clock::LoadWindowsDateTimeFormats { locale } {
# Bail out if we can't find the Registry
| < | | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 |
# default strings can be obtained if the Registry query fails.
#
#----------------------------------------------------------------------
proc ::tcl::clock::LoadWindowsDateTimeFormats { locale } {
# Bail out if we can't find the Registry
if { ![_hasRegistry] } return
if { ![catch {
registry get "HKEY_CURRENT_USER\\Control Panel\\International" \
sShortDate
} string] } {
set quote {}
set datefmt {}
|
| ︙ | ︙ | |||
2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 | # # Map away locale-dependent format groups in a clock format. # # Parameters: # locale -- Current [mclocale] locale, supplied to avoid # an extra call # format -- Format supplied to [clock scan] or [clock format] # # Results: # Returns the string with locale-dependent composite format groups # substituted out. # # Side effects: # None. # #---------------------------------------------------------------------- | > > | > | < | | < | | | | | | | | | | < < < < < < < < < < < | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < | < | < < < < < < | < | < | < < | < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < | < < < < < < < < < < < < < < < < < < < < < | < < | < | < < < < < < < < < < < < < < < < < < < | < < < < < < < < | < < | < | < | < | < < < < < | < < < < < < < < < < < < < < < < < < < < | < < < < < < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < | | < | | | | > | < | > | | < < | | < < < < < < < < < < < < < < < < < < < < | < < < < < < < | | > | > > | | | > | | 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 |
#
# Map away locale-dependent format groups in a clock format.
#
# Parameters:
# locale -- Current [mclocale] locale, supplied to avoid
# an extra call
# format -- Format supplied to [clock scan] or [clock format]
# mcd -- Message catalog dictionary for current locale (read-only,
# don't store it to avoid shared references).
#
# Results:
# Returns the string with locale-dependent composite format groups
# substituted out.
#
# Side effects:
# None.
#
#----------------------------------------------------------------------
proc ::tcl::clock::LocalizeFormat { locale format mcd } {
variable LocFmtMap
# get map list cached or build it:
if {[dict exists $LocFmtMap $locale]} {
set mlst [dict get $LocFmtMap $locale]
} else {
# Handle locale-dependent format groups by mapping them out of the format
# string. Note that the order of the [string map] operations is
# significant because later formats can refer to later ones; for example
# %c can refer to %X, which in turn can refer to %T.
set mlst {
%% %%
%D %m/%d/%Y
%+ {%a %b %e %H:%M:%S %Z %Y}
}
lappend mlst %EY [string map $mlst [dict get $mcd LOCALE_YEAR_FORMAT]]
lappend mlst %T [string map $mlst [dict get $mcd TIME_FORMAT_24_SECS]]
lappend mlst %R [string map $mlst [dict get $mcd TIME_FORMAT_24]]
lappend mlst %r [string map $mlst [dict get $mcd TIME_FORMAT_12]]
lappend mlst %X [string map $mlst [dict get $mcd TIME_FORMAT]]
lappend mlst %EX [string map $mlst [dict get $mcd LOCALE_TIME_FORMAT]]
lappend mlst %x [string map $mlst [dict get $mcd DATE_FORMAT]]
lappend mlst %Ex [string map $mlst [dict get $mcd LOCALE_DATE_FORMAT]]
lappend mlst %c [string map $mlst [dict get $mcd DATE_TIME_FORMAT]]
lappend mlst %Ec [string map $mlst [dict get $mcd LOCALE_DATE_TIME_FORMAT]]
dict set LocFmtMap $locale $mlst
}
# translate copy of format (don't use format object here, because otherwise
# it can lose its internal representation (string map - convert to unicode)
set locfmt [string map $mlst [string range " $format" 1 end]]
# Save original format as long as possible, because of internal
# representation (performance).
# Note that in this case such format will be never localized (also
# using another locales). To prevent this return a duplicate (but
# it may be slower).
if {$locfmt eq $format} {
set locfmt $format
}
return $locfmt
}
#----------------------------------------------------------------------
#
# GetSystemTimeZone --
#
# Determines the system time zone, which is the default for the
# 'clock' command if no other zone is supplied.
#
# Parameters:
# None.
#
# Results:
# Returns the system time zone.
#
# Side effects:
# Stores the system time zone in engine configuration, since
# determining it may be an expensive process.
#
#----------------------------------------------------------------------
proc ::tcl::clock::GetSystemTimeZone {} {
variable TimeZoneBad
if {[set result [getenv TCL_TZ]] ne {}} {
set timezone $result
} elseif {[set result [getenv TZ]] ne {}} {
set timezone $result
} else {
# ask engine for the cached timezone:
set timezone [::tcl::unsupported::clock::configure -system-tz]
if { $timezone ne "" } {
return $timezone
}
if { $::tcl_platform(platform) eq {windows} } {
set timezone [GuessWindowsTimeZone]
} elseif { [file exists /etc/localtime]
&& ![catch {ReadZoneinfoFile \
Tcl/Localtime /etc/localtime}] } {
set timezone :Tcl/Localtime
} else {
set timezone :localtime
}
}
if { ![dict exists $TimeZoneBad $timezone] } {
catch {set timezone [SetupTimeZone $timezone]}
}
if { [dict exists $TimeZoneBad $timezone] } {
set timezone :localtime
}
# tell backend - current system timezone:
::tcl::unsupported::clock::configure -system-tz $timezone
return $timezone
}
#----------------------------------------------------------------------
#
# SetupTimeZone --
#
# Given the name or specification of a time zone, sets up its in-memory
# data.
#
# Parameters:
# tzname - Name of a time zone
#
# Results:
# Unless the time zone is ':localtime', sets the TZData array to contain
# the lookup table for local<->UTC conversion. Returns an error if the
# time zone cannot be parsed.
#
#----------------------------------------------------------------------
proc ::tcl::clock::SetupTimeZone { timezone {alias {}} } {
variable TZData
if {! [info exists TZData($timezone)] } {
variable TimeZoneBad
if { [dict exists $TimeZoneBad $timezone] } {
return -code error \
-errorcode [list CLOCK badTimeZone $timezone] \
"time zone \"$timezone\" not found"
}
variable MINWIDE
if {
[regexp {^([-+])(\d\d)(?::?(\d\d)(?::?(\d\d))?)?} $timezone \
-> s hh mm ss]
} then {
# Make a fixed offset
::scan $hh %d hh
if { $mm eq {} } {
|
| ︙ | ︙ | |||
3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 |
if {
[catch {
LoadTimeZoneFile [string range $timezone 1 end]
}] && [catch {
LoadZoneinfoFile [string range $timezone 1 end]
}]
} then {
return -code error \
-errorcode [list CLOCK badTimeZone $timezone] \
"time zone \"$timezone\" not found"
}
} elseif { ![catch {ParsePosixTimeZone $timezone} tzfields] } {
# This looks like a POSIX time zone - try to process it
if { [catch {ProcessPosixTimeZone $tzfields} data opts] } {
if { [lindex [dict get $opts -errorcode] 0] eq {CLOCK} } {
dict unset opts -errorinfo
}
return -options $opts $data
} else {
set TZData($timezone) $data
}
} else {
# We couldn't parse this as a POSIX time zone. Try again with a
# time zone file - this time without a colon
if { [catch { LoadTimeZoneFile $timezone }]
&& [catch { LoadZoneinfoFile $timezone } - opts] } {
dict unset opts -errorinfo
return -options $opts "time zone $timezone not found"
}
set TZData($timezone) $TZData(:$timezone)
}
}
| > > > > > > > > > > > > > > > > > > | > | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 |
if {
[catch {
LoadTimeZoneFile [string range $timezone 1 end]
}] && [catch {
LoadZoneinfoFile [string range $timezone 1 end]
}]
} then {
dict set TimeZoneBad $timezone 1
return -code error \
-errorcode [list CLOCK badTimeZone $timezone] \
"time zone \"$timezone\" not found"
}
} elseif { ![catch {ParsePosixTimeZone $timezone} tzfields] } {
# This looks like a POSIX time zone - try to process it
if { [catch {ProcessPosixTimeZone $tzfields} data opts] } {
if { [lindex [dict get $opts -errorcode] 0] eq {CLOCK} } {
dict unset opts -errorinfo
}
dict set TimeZoneBad $timezone 1
return -options $opts $data
} else {
set TZData($timezone) $data
}
} else {
variable LegacyTimeZone
# We couldn't parse this as a POSIX time zone. Try again with a
# time zone file - this time without a colon
if { [catch { LoadTimeZoneFile $timezone }]
&& [catch { LoadZoneinfoFile $timezone } - opts] } {
# Check may be a legacy zone:
if { $alias eq {} && ![catch {
set tzname [dict get $LegacyTimeZone [string tolower $timezone]]
}] } {
set tzname [::tcl::clock::SetupTimeZone $tzname $timezone]
set TZData($timezone) $TZData($tzname)
# tell backend - timezone is initialized and return shared timezone object:
return [::tcl::unsupported::clock::configure -setup-tz $timezone]
}
dict unset opts -errorinfo
dict set TimeZoneBad $timezone 1
return -options $opts "time zone $timezone not found"
}
set TZData($timezone) $TZData(:$timezone)
}
}
# tell backend - timezone is initialized and return shared timezone object:
::tcl::unsupported::clock::configure -setup-tz $timezone
}
#----------------------------------------------------------------------
#
# GuessWindowsTimeZone --
#
# Determines the system time zone on windows.
|
| ︙ | ︙ | |||
3164 3165 3166 3167 3168 3169 3170 |
# zone that uses the same rules. If it finds one, it returns it; otherwise,
# it constructs a Posix-style time zone string and returns that.
#
#----------------------------------------------------------------------
proc ::tcl::clock::GuessWindowsTimeZone {} {
variable WinZoneInfo
| < | | 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 |
# zone that uses the same rules. If it finds one, it returns it; otherwise,
# it constructs a Posix-style time zone string and returns that.
#
#----------------------------------------------------------------------
proc ::tcl::clock::GuessWindowsTimeZone {} {
variable WinZoneInfo
variable TimeZoneBad
if { ![_hasRegistry] } {
return :localtime
}
# Dredge time zone information out of the registry
if { [catch {
set rpath HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\TimeZoneInformation
|
| ︙ | ︙ | |||
3205 3206 3207 3208 3209 3210 3211 |
# Make up a Posix time zone specifier if we can't find one. Check here
# that the tzdata file exists, in case we're running in an environment
# (e.g. starpack) where tzdata is incomplete. (Bug 1237907)
if { [dict exists $WinZoneInfo $data] } {
set tzname [dict get $WinZoneInfo $data]
if { ! [dict exists $TimeZoneBad $tzname] } {
| | | | 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 |
# Make up a Posix time zone specifier if we can't find one. Check here
# that the tzdata file exists, in case we're running in an environment
# (e.g. starpack) where tzdata is incomplete. (Bug 1237907)
if { [dict exists $WinZoneInfo $data] } {
set tzname [dict get $WinZoneInfo $data]
if { ! [dict exists $TimeZoneBad $tzname] } {
catch {set tzname [SetupTimeZone $tzname]}
}
} else {
set tzname {}
}
if { $tzname eq {} || [dict exists $TimeZoneBad $tzname] } {
lassign $data \
bias stdBias dstBias \
stdYear stdMonth stdDayOfWeek stdDayOfMonth \
stdHour stdMinute stdSecond stdMillisec \
dstYear dstMonth dstDayOfWeek dstDayOfMonth \
dstHour dstMinute dstSecond dstMillisec
set stdDelta [expr { $bias + $stdBias }]
|
| ︙ | ︙ | |||
3881 3882 3883 3884 3885 3886 3887 |
proc ::tcl::clock::DeterminePosixDSTTime { z bound y } {
variable FEB_28
# Determine the start or end day of DST
| | | | 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 |
proc ::tcl::clock::DeterminePosixDSTTime { z bound y } {
variable FEB_28
# Determine the start or end day of DST
set date [dict create era CE year $y gregorian 1]
set doy [dict get $z ${bound}DayOfYear]
if { $doy ne {} } {
# Time was specified as a day of the year
if { [dict get $z ${bound}J] ne {}
&& [IsGregorianLeapYear $date]
&& ( $doy > $FEB_28 ) } {
incr doy
}
dict set date dayOfYear $doy
set date [GetJulianDayFromEraYearDay $date[set date {}] 2361222]
} else {
# Time was specified as a day of the week within a month
|
| ︙ | ︙ | |||
3935 3936 3937 3938 3939 3940 3941 |
} else {
set s [lindex [::scan $s %d] 0]
}
set tod [expr { ( $h * 60 + $m ) * 60 + $s }]
return [expr { $seconds + $tod }]
}
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 |
} else {
set s [lindex [::scan $s %d] 0]
}
set tod [expr { ( $h * 60 + $m ) * 60 + $s }]
return [expr { $seconds + $tod }]
}
#----------------------------------------------------------------------
#
# GetJulianDayFromEraYearDay --
#
# Given a year, month and day on the Gregorian calendar, determines
# the Julian Day Number beginning at noon on that date.
#
|
| ︙ | ︙ | |||
4151 4152 4153 4154 4155 4156 4157 |
proc ::tcl::clock::WeekdayOnOrBefore { weekday j } {
set k [expr { ( $weekday + 6 ) % 7 }]
return [expr { $j - ( $j - $k ) % 7 }]
}
#----------------------------------------------------------------------
#
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < | | > | < | < > | | < < | < | 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 |
proc ::tcl::clock::WeekdayOnOrBefore { weekday j } {
set k [expr { ( $weekday + 6 ) % 7 }]
return [expr { $j - ( $j - $k ) % 7 }]
}
#----------------------------------------------------------------------
#
# ChangeCurrentLocale --
#
# The global locale was changed within msgcat.
# Clears the buffered parse functions of the current locale.
#
# Parameters:
# loclist (ignored)
#
# Results:
# None.
#
# Side effects:
# Buffered parse functions are cleared.
#
#----------------------------------------------------------------------
proc ::tcl::clock::ChangeCurrentLocale {args} {
::tcl::unsupported::clock::configure -current-locale [lindex $args 0]
}
#----------------------------------------------------------------------
#
# ClearCaches --
#
# Clears all caches to reclaim the memory used in [clock]
#
# Parameters:
# None.
#
# Results:
# None.
#
# Side effects:
# Caches are cleared.
#
#----------------------------------------------------------------------
proc ::tcl::clock::ClearCaches {} {
variable LocFmtMap
variable mcMergedCat
variable TimeZoneBad
# tell backend - should invalidate:
::tcl::unsupported::clock::configure -clear
# clear msgcat cache:
set mcMergedCat [dict create]
set LocFmtMap {}
set TimeZoneBad {}
InitTZData
}
|
Added library/encoding/koi8-ru.enc.
> > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # Encoding file: koi8-ru, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 25002502250C251025142518251C2524252C2534253C258025842588258C2590 259125922593232025A02219221A22482264226500A0232100B000B200B700F7 25502551255204510454255404560457255725582559255A255B0491045E255E 255F25602561040104042563040604072566256725682569256A0490040E00A9 044E0430043104460434043504440433044504380439043A043B043C043D043E 043F044F044004410442044304360432044C044B04370448044D04490447044A 042E0410041104260414041504240413042504180419041A041B041C041D041E 041F042F042004210422042304160412042C042B04170428042D04290427042A |
Added library/encoding/koi8-t.enc.
> > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # Encoding file: koi8-t, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 049B0493201A0492201E2026202020210000203004B3203904B204B704B60000 049A20182019201C201D202220132014000021220000203A0000000000000000 000004EF04EE045100A404E300A600A700000000000000AB00AC00AD00AE0000 00B000B100B20401000004E200B600B700002116000000BB00000000000000A9 044E0430043104460434043504440433044504380439043A043B043C043D043E 043F044F044004410442044304360432044C044B04370448044D04490447044A 042E0410041104260414041504240413042504180419041A041B041C041D041E 041F042F042004210422042304160412042C042B04170428042D04290427042A |
Changes to library/init.tcl.
| ︙ | ︙ | |||
105 106 107 108 109 110 111 |
{::tcl::MacOSXPkgUnknown ::tclPkgUnknown}}
} else {
package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
}
# Set up the 'clock' ensemble
| < | < < | | | < < < | < | > > | > < | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
{::tcl::MacOSXPkgUnknown ::tclPkgUnknown}}
} else {
package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
}
# Set up the 'clock' ensemble
proc clock args {
set cmdmap [dict create]
foreach cmd {add clicks format microseconds milliseconds scan seconds} {
dict set cmdmap $cmd ::tcl::clock::$cmd
}
namespace inscope ::tcl::clock [list namespace ensemble create -command \
[uplevel 1 [list ::namespace origin [::lindex [info level 0] 0]]] \
-map $cmdmap]
::tcl::unsupported::clock::configure -init-complete
uplevel 1 [info level 0]
}
}
# Conditionalize for presence of exec.
if {[namespace which -command exec] eq ""} {
# Some machines do not have exec. Also, on all
|
| ︙ | ︙ |
Changes to library/tclIndex.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 25 26 27 28 | set auto_index(::auto_mkindex_parser::mkindex) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::auto_mkindex_parser::hook) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::auto_mkindex_parser::childhook) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::auto_mkindex_parser::command) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::auto_mkindex_parser::commandInit) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::auto_mkindex_parser::fullname) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::auto_mkindex_parser::indexEntry) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(foreachLine) [list ::tcl::Pkg::source [file join $dir foreachline.tcl]] set auto_index(::tcl::history) [list ::tcl::Pkg::source [file join $dir history.tcl]] set auto_index(history) [list ::tcl::Pkg::source [file join $dir history.tcl]] set auto_index(::tcl::HistAdd) [list ::tcl::Pkg::source [file join $dir history.tcl]] set auto_index(::tcl::HistKeep) [list ::tcl::Pkg::source [file join $dir history.tcl]] set auto_index(::tcl::HistClear) [list ::tcl::Pkg::source [file join $dir history.tcl]] set auto_index(::tcl::HistInfo) [list ::tcl::Pkg::source [file join $dir history.tcl]] | > > > > > > > > > > > > > > > > > > > > > > > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | set auto_index(::auto_mkindex_parser::mkindex) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::auto_mkindex_parser::hook) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::auto_mkindex_parser::childhook) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::auto_mkindex_parser::command) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::auto_mkindex_parser::commandInit) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::auto_mkindex_parser::fullname) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::auto_mkindex_parser::indexEntry) [list ::tcl::Pkg::source [file join $dir auto.tcl]] set auto_index(::tcl::clock::Initialize) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::mcget) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::mcMerge) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::GetSystemLocale) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::EnterLocale) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::_hasRegistry) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::LoadWindowsDateTimeFormats) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::LocalizeFormat) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::GetSystemTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::SetupTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::GuessWindowsTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::LoadTimeZoneFile) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::LoadZoneinfoFile) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::ReadZoneinfoFile) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::ParsePosixTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::ProcessPosixTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::DeterminePosixDSTTime) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::GetJulianDayFromEraYearDay) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::GetJulianDayFromEraYearMonthWeekDay) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::IsGregorianLeapYear) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::WeekdayOnOrBefore) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::ChangeCurrentLocale) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(::tcl::clock::ClearCaches) [list ::tcl::Pkg::source [file join $dir clock.tcl]] set auto_index(foreachLine) [list ::tcl::Pkg::source [file join $dir foreachline.tcl]] set auto_index(::tcl::history) [list ::tcl::Pkg::source [file join $dir history.tcl]] set auto_index(history) [list ::tcl::Pkg::source [file join $dir history.tcl]] set auto_index(::tcl::HistAdd) [list ::tcl::Pkg::source [file join $dir history.tcl]] set auto_index(::tcl::HistKeep) [list ::tcl::Pkg::source [file join $dir history.tcl]] set auto_index(::tcl::HistClear) [list ::tcl::Pkg::source [file join $dir history.tcl]] set auto_index(::tcl::HistInfo) [list ::tcl::Pkg::source [file join $dir history.tcl]] |
| ︙ | ︙ |
Added libtommath/CMakeLists.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# SPDX-License-Identifier: Unlicense
#
# LibTomMath, a free open source portable number theoretic multiple-precision
# integer (MPI) library written entirely in C.
#
cmake_minimum_required(VERSION 3.10)
project(libtommath
VERSION 1.3.0
DESCRIPTION "A free open source portable number theoretic multiple-precision integer (MPI) library written entirely in C."
HOMEPAGE_URL "https://www.libtom.net/LibTomMath"
LANGUAGES C)
# package release version
# bump if re-releasing the same VERSION + patches
# set to 1 if releasing a new VERSION
set(PACKAGE_RELEASE_VERSION 1)
#-----------------------------------------------------------------------------
# Include cmake modules
#-----------------------------------------------------------------------------
include(GNUInstallDirs)
include(CheckIPOSupported)
include(CMakePackageConfigHelpers)
# default is "No tests"
option(BUILD_TESTING "" OFF)
include(CTest)
include(sources.cmake)
#-----------------------------------------------------------------------------
# Options
#-----------------------------------------------------------------------------
option(BUILD_SHARED_LIBS "Build shared library and only the shared library if \"ON\", default is static" OFF)
#-----------------------------------------------------------------------------
# Add support for ccache if desired
#-----------------------------------------------------------------------------
find_program(CCACHE ccache)
if(CCACHE)
option(ENABLE_CCACHE "Enable ccache." ON)
endif()
# use ccache if installed
if(CCACHE AND ENABLE_CCACHE)
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE})
endif()
#-----------------------------------------------------------------------------
# Compose CFLAGS
#-----------------------------------------------------------------------------
# Some information ported from makefile_include.mk
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE "Release")
endif()
# We only differentiate between MSVC and GCC-compatible compilers
if(MSVC)
set(LTM_C_FLAGS -W3)
elseif(WATCOM)
set(LTM_C_FLAGS -fo=.obj -oaxt -3r -w3)
else()
set(LTM_C_FLAGS -Wall -Wsign-compare -Wextra -Wshadow
-Wdeclaration-after-statement -Wbad-function-cast -Wcast-align
-Wstrict-prototypes -Wpointer-arith -Wsystem-headers)
set(CMAKE_C_FLAGS_DEBUG "-g3")
set(CMAKE_C_FLAGS_RELEASE "-O3 -funroll-loops -fomit-frame-pointer")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g3 -O2")
set(CMAKE_C_FLAGS_MINSIZEREL "-Os")
endif()
# What compiler do we have and what are their...uhm... peculiarities
if(CMAKE_C_COMPILER_ID MATCHES "(C|c?)lang")
list(APPEND LTM_C_FLAGS -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header)
# Clang requires at least '-O1' for dead code elimination
set(CMAKE_C_FLAGS_DEBUG "-O1 ${CMAKE_C_FLAGS_DEBUG}")
endif()
if(CMAKE_C_COMPILER MATCHES "mingw")
list(APPEND LTM_C_FLAGS -Wno-shadow -Wno-expansion-to-defined -Wno-declaration-after-statement -Wno-bad-function-cast)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
list(APPEND LTM_C_FLAGS -Wno-nullability-completeness)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN")
list(APPEND LTM_C_FLAGS -no-undefined)
endif()
# TODO: coverage (lgcov)
# If the user set the environment variables at generate-time, append them
# in order to allow overriding our defaults.
# ${LTM_CFLAGS} means the user passed it via sth like:
# $ cmake -DLTM_CFLAGS="foo"
list(APPEND LTM_C_FLAGS ${LTM_CFLAGS})
list(APPEND LTM_LD_FLAGS ${LTM_LDFLAGS})
#-----------------------------------------------------------------------------
# library target
#-----------------------------------------------------------------------------
add_library(${PROJECT_NAME}
${SOURCES}
${HEADERS}
)
target_include_directories(${PROJECT_NAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}>
)
target_compile_options(${PROJECT_NAME} BEFORE PRIVATE
${LTM_C_FLAGS}
)
target_link_options(${PROJECT_NAME} BEFORE PRIVATE
${LTM_LD_FLAGS}
)
set(PUBLIC_HEADERS tommath.h)
set(C89 False CACHE BOOL "(Usually maintained automatically) Enable when the library is in c89 mode to package the correct header files on install")
if(C89)
list(APPEND PUBLIC_HEADERS tommath_c89.h)
endif()
set_target_properties(${PROJECT_NAME} PROPERTIES
OUTPUT_NAME tommath
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
PUBLIC_HEADER "${PUBLIC_HEADERS}"
)
option(COMPILE_LTO "Build with LTO enabled")
if(COMPILE_LTO)
check_ipo_supported(RESULT COMPILER_SUPPORTS_LTO)
if(COMPILER_SUPPORTS_LTO)
set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
else()
message(SEND_ERROR "This compiler does not support LTO. Reconfigure ${PROJECT_NAME} with -DCOMPILE_LTO=OFF.")
endif()
endif()
#-----------------------------------------------------------------------------
# demo target
#-----------------------------------------------------------------------------
if(BUILD_TESTING)
enable_testing()
add_subdirectory(demo)
endif()
#-----------------------------------------------------------------------------
# Install/export targets and files
#-----------------------------------------------------------------------------
set(CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
set(PROJECT_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake")
set(PROJECT_CONFIG_FILE "${PROJECT_NAME}-config.cmake")
set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
install(TARGETS ${PROJECT_NAME}
EXPORT ${TARGETS_EXPORT_NAME}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT Libraries
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
# Install libtommath.pc for pkg-config if we build a shared library
if(BUILD_SHARED_LIBS)
# Let the user override the default directory of the pkg-config file (usually this shouldn't be required to be changed)
set(CMAKE_INSTALL_PKGCONFIGDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig" CACHE PATH "Folder where to install .pc files")
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
@ONLY
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
DESTINATION ${CMAKE_INSTALL_PKGCONFIGDIR}
)
endif()
# generate package version file
write_basic_package_version_file(
${PROJECT_VERSION_FILE}
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
# install version file
install(FILES ${PROJECT_VERSION_FILE}
DESTINATION ${CONFIG_INSTALL_DIR}
)
# build directory package config
export(EXPORT ${TARGETS_EXPORT_NAME}
FILE ${PROJECT_CONFIG_FILE}
)
# installed package config
install(EXPORT ${TARGETS_EXPORT_NAME}
DESTINATION ${CONFIG_INSTALL_DIR}
FILE ${PROJECT_CONFIG_FILE}
)
# add to CMake registry
export(PACKAGE ${PROJECT_NAME})
#---------------------------------------------------------------------------------------
# Create release packages
#---------------------------------------------------------------------------------------
# determine distribution and architecture
find_program(LSB_RELEASE lsb_release)
find_program(SYSCTL sysctl)
find_program(UNAME uname)
if(UNAME)
execute_process(COMMAND uname -m OUTPUT_VARIABLE MACHINE_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
elseif(SYSCTL)
execute_process(COMMAND sysctl -b hw.machine_arch OUTPUT_VARIABLE MACHINE_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
string(TOLOWER ${CMAKE_SYSTEM_NAME} MACHINE_ARCH)
endif()
if(LSB_RELEASE)
execute_process(COMMAND lsb_release -si OUTPUT_VARIABLE LINUX_DISTRO OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND lsb_release -sc OUTPUT_VARIABLE LINUX_DISTRO_CODENAME OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND lsb_release -sr OUTPUT_VARIABLE LINUX_DISTRO_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
string(TOLOWER ${LINUX_DISTRO} LINUX_DISTRO)
if(LINUX_DISTRO_CODENAME STREQUAL "n/a")
set(DISTRO_PACK_PATH ${LINUX_DISTRO}/${LINUX_DISTRO_VERSION}/)
else()
set(DISTRO_PACK_PATH ${LINUX_DISTRO}/${LINUX_DISTRO_CODENAME}/)
endif()
else()
set(DISTRO_PACK_PATH ${CMAKE_SYSTEM_NAME}/)
endif()
# make sure untagged versions get a different package name
execute_process(COMMAND git describe --exact-match --tags ERROR_QUIET RESULT_VARIABLE REPO_HAS_TAG)
if(REPO_HAS_TAG EQUAL 0)
set(PACKAGE_NAME_SUFFIX "")
else()
set(PACKAGE_NAME_SUFFIX "-git")
message(STATUS "Use -git suffix")
endif()
# default CPack generators
set(CPACK_GENERATOR TGZ STGZ)
# extra CPack generators
if(LINUX_DISTRO STREQUAL "debian" OR LINUX_DISTRO STREQUAL "ubuntu" OR LINUX_DISTRO STREQUAL "linuxmint")
list(APPEND CPACK_GENERATOR DEB)
elseif(LINUX_DISTRO STREQUAL "fedora" OR LINUX_DISTRO STREQUAL "opensuse" OR LINUX_DISTRO STREQUAL "centos")
list(APPEND CPACK_GENERATOR RPM)
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
list(APPEND CPACK_GENERATOR FREEBSD)
endif()
set(LTM_DEBIAN_SHARED_PACKAGE_NAME "${PROJECT_NAME}${PACKAGE_NAME_SUFFIX}${PROJECT_VERSION_MAJOR}")
# general CPack config
set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/packages/${DISTRO_PACK_PATH})
message(STATUS "CPack: packages will be generated under ${CPACK_PACKAGE_DIRECTORY}")
if(BUILD_SHARED_LIBS)
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}${PROJECT_VERSION_MAJOR}")
set(CPACK_DEBIAN_PACKAGE_NAME "${LTM_DEBIAN_SHARED_PACKAGE_NAME}")
else()
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}-devel")
set(CPACK_DEBIAN_LIBRARIES_PACKAGE_NAME "${PROJECT_NAME}${PACKAGE_NAME_SUFFIX}-dev")
endif()
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LibTomMath")
set(CPACK_PACKAGE_VENDOR "libtom projects")
set(CPACK_PACKAGE_CONTACT "libtom@googlegroups.com")
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
set(PACKAGE_NAME_TRAILER ${CPACK_PACKAGE_VERSION}-${PACKAGE_RELEASE_VERSION}_${MACHINE_ARCH})
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${PACKAGE_NAME_TRAILER})
# deb specific CPack config
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON)
set(CPACK_DEBIAN_PACKAGE_RELEASE ${PACKAGE_RELEASE_VERSION})
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
if(BUILD_SHARED_LIBS)
set(CPACK_DEBIAN_PACKAGE_SECTION "libs")
else()
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
set(CPACK_DEBIAN_PACKAGE_DEPENDS ${LTM_DEBIAN_SHARED_PACKAGE_NAME})
set(CPACK_DEB_COMPONENT_INSTALL ON)
set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
set(CPACK_COMPONENTS_ALL Libraries)
endif()
# rpm specific CPack config
set(CPACK_RPM_PACKAGE_RELEASE ${PACKAGE_RELEASE_VERSION})
set(CPACK_RPM_PACKAGE_ARCHITECTURE ${MACHINE_ARCH})
set(CPACK_RPM_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-${PROJECT_VERSION}")
set(CPACK_RPM_PACKAGE_LICENSE "The Unlicense")
# FreeBSD specific CPack config
set(CPACK_FREEBSD_PACKAGE_MAINTAINER "gahr@FreeBSD.org")
set(CPACK_FREEBSD_PACKAGE_ORIGIN "math/libtommath")
set(CPACK_FREEBSD_PACKAGE_CATEGORIES "math")
include(CPack)
|
Changes to libtommath/appveyor.yml.
|
| | | 1 2 3 4 5 6 7 8 |
version: 1.3.0-{build}
branches:
only:
- master
- develop
- /^release/
- /^travis/
image:
|
| ︙ | ︙ |
Changes to libtommath/bn_deprecated.c.
| ︙ | ︙ | |||
69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
}
#endif
#ifdef BN_MP_BALANCE_MUL_C
mp_err mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c)
{
return s_mp_balance_mul(a, b, c);
}
#endif
#ifdef BN_MP_EXPTMOD_FAST_C
mp_err mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode)
{
return s_mp_exptmod_fast(G, X, P, Y, redmode);
}
#endif
| > > > > > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
}
#endif
#ifdef BN_MP_BALANCE_MUL_C
mp_err mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c)
{
return s_mp_balance_mul(a, b, c);
}
#endif
#ifdef BN_MP_DIV_3_C
mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d)
{
return s_mp_div_3(a, c, d);
}
#endif
#ifdef BN_MP_EXPTMOD_FAST_C
mp_err mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode)
{
return s_mp_exptmod_fast(G, X, P, Y, redmode);
}
#endif
|
| ︙ | ︙ | |||
180 181 182 183 184 185 186 |
{
return (unsigned long)mp_get_mag_ul(a);
}
#endif
#ifdef BN_MP_GET_LONG_LONG_C
unsigned long long mp_get_long_long(const mp_int *a)
{
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | > > > > > > | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
{
return (unsigned long)mp_get_mag_ul(a);
}
#endif
#ifdef BN_MP_GET_LONG_LONG_C
unsigned long long mp_get_long_long(const mp_int *a)
{
return (unsigned long long)mp_get_mag_u64(a);
}
#endif
#ifdef BN_MP_GET_LL_C
MP_GET_SIGNED(mp_get_ll, mp_get_mag_u64, long long, uint64_t)
#endif
#ifdef BN_MP_GET_MAG_ULL_C
MP_GET_MAG(mp_get_mag_ull, unsigned long long)
#endif
#ifdef BN_MP_INIT_LL_C
MP_INIT_INT(mp_init_ll, mp_set_i64, long long)
#endif
#ifdef BN_MP_SET_LL_C
MP_SET_SIGNED(mp_set_ll, mp_set_i64, long long, long long)
#endif
#ifdef BN_MP_INIT_ULL_C
MP_INIT_INT(mp_init_ull, mp_set_u64, unsigned long long)
#endif
#ifdef BN_MP_SET_ULL_C
MP_SET_UNSIGNED(mp_set_ull, unsigned long long)
#endif
#ifdef BN_MP_PRIME_IS_DIVISIBLE_C
mp_err mp_prime_is_divisible(const mp_int *a, mp_bool *result)
{
return s_mp_prime_is_divisible(a, result);
}
#endif
#ifdef BN_MP_LOG_U32_C
mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c)
{
mp_err e;
int c_;
if (base > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
return MP_VAL;
}
e = mp_log_n(a, (int)base, &c_);
*c = (uint32_t)c_;
return e;
}
#endif
#ifdef BN_MP_EXPT_D_EX_C
mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast)
{
(void)fast;
if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
return MP_VAL;
}
return mp_expt_n(a, (int)b, c);
}
#endif
#ifdef BN_MP_EXPT_D_C
mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c)
{
if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
return MP_VAL;
}
return mp_expt_n(a, (int)b, c);
}
#endif
#ifdef BN_MP_N_ROOT_EX_C
mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast)
{
(void)fast;
if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
return MP_VAL;
}
return mp_root_n(a, (int)b, c);
}
#endif
#ifdef BN_MP_N_ROOT_C
mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c)
{
if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
return MP_VAL;
}
return mp_root_n(a, (int)b, c);
}
#endif
#ifdef BN_MP_ROOT_U32_C
mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c)
{
return mp_root_n(a, (int)b, c);
}
#endif
#ifdef BN_MP_UNSIGNED_BIN_SIZE_C
int mp_unsigned_bin_size(const mp_int *a)
{
return (int)mp_ubin_size(a);
}
|
| ︙ | ︙ |
Deleted libtommath/bn_mp_div_3.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to libtommath/bn_mp_div_d.c.
| ︙ | ︙ | |||
40 41 42 43 44 45 46 |
if (c != NULL) {
return mp_div_2d(a, ix, c, NULL);
}
return MP_OKAY;
}
/* three? */
| | | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
if (c != NULL) {
return mp_div_2d(a, ix, c, NULL);
}
return MP_OKAY;
}
/* three? */
if (MP_HAS(S_MP_DIV_3) && (b == 3u)) {
return s_mp_div_3(a, c, d);
}
/* no easy answer [c'est la vie]. Just division */
if ((err = mp_init_size(&q, a->used)) != MP_OKAY) {
return err;
}
|
| ︙ | ︙ |
Added libtommath/bn_mp_expt_n.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
#include "tommath_private.h"
#ifdef BN_MP_EXPT_N_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#ifdef BN_MP_EXPT_U32_C
mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c)
{
if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
return MP_VAL;
}
return mp_expt_n(a, (int)b, c);
}
#endif
/* calculate c = a**b using a square-multiply algorithm */
mp_err mp_expt_n(const mp_int *a, int b, mp_int *c)
{
mp_err err;
mp_int g;
if ((err = mp_init_copy(&g, a)) != MP_OKAY) {
return err;
}
/* set initial result */
mp_set(c, 1uL);
while (b > 0) {
/* if the bit is set multiply */
if ((b & 1) != 0) {
if ((err = mp_mul(c, &g, c)) != MP_OKAY) {
goto LBL_ERR;
}
}
/* square */
if (b > 1) {
if ((err = mp_sqr(&g, &g)) != MP_OKAY) {
goto LBL_ERR;
}
}
/* shift to next bit */
b >>= 1;
}
LBL_ERR:
mp_clear(&g);
return err;
}
#endif
|
Deleted libtommath/bn_mp_expt_u32.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to libtommath/bn_mp_exptmod.c.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 |
mp_int tmpG, tmpX;
mp_err err;
if (!MP_HAS(MP_INVMOD)) {
return MP_VAL;
}
| | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
mp_int tmpG, tmpX;
mp_err err;
if (!MP_HAS(MP_INVMOD)) {
return MP_VAL;
}
if ((err = mp_init_multi(&tmpG, &tmpX, (void *)NULL)) != MP_OKAY) {
return err;
}
/* first compute 1/G mod P */
if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
goto LBL_ERR;
}
/* now get |X| */
if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
goto LBL_ERR;
}
/* and now compute (1/G)**|X| instead of G**X [X < 0] */
err = mp_exptmod(&tmpG, &tmpX, P, Y);
LBL_ERR:
mp_clear_multi(&tmpG, &tmpX, (void *)NULL);
return err;
}
/* modified diminished radix reduction */
if (MP_HAS(MP_REDUCE_IS_2K_L) && MP_HAS(MP_REDUCE_2K_L) && MP_HAS(S_MP_EXPTMOD) &&
(mp_reduce_is_2k_l(P) == MP_YES)) {
return s_mp_exptmod(G, X, P, Y, 1);
|
| ︙ | ︙ |
Changes to libtommath/bn_mp_exteuclid.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include "tommath_private.h"
#ifdef BN_MP_EXTEUCLID_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
/* Extended euclidean algorithm of (a, b) produces
a*u1 + b*u2 = u3
*/
mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
{
mp_int u1, u2, u3, v1, v2, v3, t1, t2, t3, q, tmp;
mp_err err;
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include "tommath_private.h"
#ifdef BN_MP_EXTEUCLID_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
/* Extended euclidean algorithm of (a, b) produces
a*u1 + b*u2 = u3
*/
mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
{
mp_int u1, u2, u3, v1, v2, v3, t1, t2, t3, q, tmp;
mp_err err;
if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, (void *)NULL)) != MP_OKAY) {
return err;
}
/* initialize, (u1,u2,u3) = (1,0,a) */
mp_set(&u1, 1uL);
if ((err = mp_copy(a, &u3)) != MP_OKAY) goto LBL_ERR;
|
| ︙ | ︙ | |||
63 64 65 66 67 68 69 |
}
if (U3 != NULL) {
mp_exch(U3, &u3);
}
err = MP_OKAY;
LBL_ERR:
| | | 63 64 65 66 67 68 69 70 71 72 73 |
}
if (U3 != NULL) {
mp_exch(U3, &u3);
}
err = MP_OKAY;
LBL_ERR:
mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, (void *)NULL);
return err;
}
#endif
|
Deleted libtommath/bn_mp_get_ll.c.
|
| < < < < < < < |
Deleted libtommath/bn_mp_get_mag_ull.c.
|
| < < < < < < < |
Deleted libtommath/bn_mp_init_ll.c.
|
| < < < < < < < |
Deleted libtommath/bn_mp_init_ull.c.
|
| < < < < < < < |
Changes to libtommath/bn_mp_lcm.c.
1 2 3 4 5 6 7 8 9 10 11 12 |
#include "tommath_private.h"
#ifdef BN_MP_LCM_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
/* computes least common multiple as |a*b|/(a, b) */
mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c)
{
mp_err err;
mp_int t1, t2;
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include "tommath_private.h"
#ifdef BN_MP_LCM_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
/* computes least common multiple as |a*b|/(a, b) */
mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c)
{
mp_err err;
mp_int t1, t2;
if ((err = mp_init_multi(&t1, &t2, (void *)NULL)) != MP_OKAY) {
return err;
}
/* t1 = get the GCD of the two inputs */
if ((err = mp_gcd(a, b, &t1)) != MP_OKAY) {
goto LBL_T;
}
|
| ︙ | ︙ | |||
34 35 36 37 38 39 40 |
err = mp_mul(a, &t2, c);
}
/* fix the sign to positive */
c->sign = MP_ZPOS;
LBL_T:
| | | 34 35 36 37 38 39 40 41 42 43 44 |
err = mp_mul(a, &t2, c);
}
/* fix the sign to positive */
c->sign = MP_ZPOS;
LBL_T:
mp_clear_multi(&t1, &t2, (void *)NULL);
return err;
}
#endif
|
Added libtommath/bn_mp_log_n.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#include "tommath_private.h"
#ifdef BN_MP_LOG_N_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
mp_err mp_log_n(const mp_int *a, int base, int *c)
{
if (mp_isneg(a) || mp_iszero(a) || (base < 2) || (unsigned)base > (unsigned)MP_DIGIT_MAX) {
return MP_VAL;
}
if (MP_HAS(S_MP_LOG_2EXPT) && MP_IS_2EXPT((mp_digit)base)) {
*c = s_mp_log_2expt(a, (mp_digit)base);
return MP_OKAY;
}
if (MP_HAS(S_MP_LOG_D) && (a->used == 1)) {
*c = s_mp_log_d((mp_digit)base, a->dp[0]);
return MP_OKAY;
}
if (MP_HAS(S_MP_LOG)) {
return s_mp_log(a, (mp_digit)base, c);
}
return MP_VAL;
}
#endif
|
Deleted libtommath/bn_mp_log_u32.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to libtommath/bn_mp_prime_frobenius_underwood.c.
| ︙ | ︙ | |||
28 29 30 31 32 33 34 | mp_int T1z, T2z, Np1z, sz, tz; int a, ap2, length, i, j; mp_err err; *result = MP_NO; | | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
mp_int T1z, T2z, Np1z, sz, tz;
int a, ap2, length, i, j;
mp_err err;
*result = MP_NO;
if ((err = mp_init_multi(&T1z, &T2z, &Np1z, &sz, &tz, (void *)NULL)) != MP_OKAY) {
return err;
}
for (a = 0; a < LTM_FROBENIUS_UNDERWOOD_A; a++) {
/* TODO: That's ugly! No, really, it is! */
if ((a==2) || (a==4) || (a==7) || (a==8) || (a==10) ||
(a==14) || (a==18) || (a==23) || (a==26) || (a==28)) {
|
| ︙ | ︙ | |||
120 121 122 123 124 125 126 |
mp_set_u32(&T1z, (uint32_t)((2 * a) + 5));
if ((err = mp_mod(&T1z, N, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
if (MP_IS_ZERO(&sz) && (mp_cmp(&tz, &T1z) == MP_EQ)) {
*result = MP_YES;
}
LBL_FU_ERR:
| | | 120 121 122 123 124 125 126 127 128 129 130 131 132 |
mp_set_u32(&T1z, (uint32_t)((2 * a) + 5));
if ((err = mp_mod(&T1z, N, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
if (MP_IS_ZERO(&sz) && (mp_cmp(&tz, &T1z) == MP_EQ)) {
*result = MP_YES;
}
LBL_FU_ERR:
mp_clear_multi(&tz, &sz, &Np1z, &T2z, &T1z, (void *)NULL);
return err;
}
#endif
#endif
|
Changes to libtommath/bn_mp_prime_rand.c.
| ︙ | ︙ | |||
32 33 34 35 36 37 38 |
/* MP_PRIME_SAFE implies MP_PRIME_BBS */
if ((flags & MP_PRIME_SAFE) != 0) {
flags |= MP_PRIME_BBS;
}
/* calc the byte size */
| | > > > | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
/* MP_PRIME_SAFE implies MP_PRIME_BBS */
if ((flags & MP_PRIME_SAFE) != 0) {
flags |= MP_PRIME_BBS;
}
/* calc the byte size */
bsize = (size>>3);
if (size&7) {
bsize++;
}
/* we need a buffer of bsize bytes */
tmp = (unsigned char *) MP_MALLOC((size_t)bsize);
if (tmp == NULL) {
return MP_MEM;
}
|
| ︙ | ︙ |
Changes to libtommath/bn_mp_prime_strong_lucas_selfridge.c.
| ︙ | ︙ | |||
69 70 71 72 73 74 75 | such that Jacobi(D,N) = -1 (Selfridge's algorithm). Theory indicates that, if N is not a perfect square, D will "nearly always" be "small." Just in case, an overflow trap for D is included. */ if ((err = mp_init_multi(&Dz, &gcd, &Np1, &Uz, &Vz, &U2mz, &V2mz, &Qmz, &Q2mz, &Qkdz, &T1z, &T2z, &T3z, &T4z, &Q2kdz, | | | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
such that Jacobi(D,N) = -1 (Selfridge's algorithm). Theory
indicates that, if N is not a perfect square, D will "nearly
always" be "small." Just in case, an overflow trap for D is
included.
*/
if ((err = mp_init_multi(&Dz, &gcd, &Np1, &Uz, &Vz, &U2mz, &V2mz, &Qmz, &Q2mz, &Qkdz, &T1z, &T2z, &T3z, &T4z, &Q2kdz,
(void *)NULL)) != MP_OKAY) {
return err;
}
D = 5;
sign = 1;
for (;;) {
|
| ︙ | ︙ | |||
277 278 279 280 281 282 283 |
if (r < (s - 1)) {
if ((err = mp_sqr(&Qkdz, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR;
if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR;
if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) goto LBL_LS_ERR;
}
}
LBL_LS_ERR:
| | | 277 278 279 280 281 282 283 284 285 286 287 288 289 |
if (r < (s - 1)) {
if ((err = mp_sqr(&Qkdz, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR;
if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR;
if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) goto LBL_LS_ERR;
}
}
LBL_LS_ERR:
mp_clear_multi(&Q2kdz, &T4z, &T3z, &T2z, &T1z, &Qkdz, &Q2mz, &Qmz, &V2mz, &U2mz, &Vz, &Uz, &Np1, &gcd, &Dz, (void *)NULL);
return err;
}
#endif
#endif
#endif
|
Added libtommath/bn_mp_root_n.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
#include "tommath_private.h"
#ifdef BN_MP_ROOT_N_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
/* find the n'th root of an integer
*
* Result found such that (c)**b <= a and (c+1)**b > a
*
* This algorithm uses Newton's approximation
* x[i+1] = x[i] - f(x[i])/f'(x[i])
* which will find the root in log(N) time where
* each step involves a fair bit.
*/
mp_err mp_root_n(const mp_int *a, int b, mp_int *c)
{
mp_int t1, t2, t3, a_;
int ilog2;
mp_err err;
if ((unsigned)b > (unsigned)MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
return MP_VAL;
}
/* input must be positive if b is even */
if (((b & 1) == 0) && mp_isneg(a)) {
return MP_VAL;
}
if ((err = mp_init_multi(&t1, &t2, &t3, (void *)NULL)) != MP_OKAY) {
return err;
}
/* if a is negative fudge the sign but keep track */
a_ = *a;
a_.sign = MP_ZPOS;
/* Compute seed: 2^(log_2(n)/b + 2)*/
ilog2 = mp_count_bits(a);
/*
If "b" is larger than INT_MAX it is also larger than
log_2(n) because the bit-length of the "n" is measured
with an int and hence the root is always < 2 (two).
*/
if (b > INT_MAX/2) {
mp_set(c, 1uL);
c->sign = a->sign;
err = MP_OKAY;
goto LBL_ERR;
}
/* "b" is smaller than INT_MAX, we can cast safely */
if (ilog2 < b) {
mp_set(c, 1uL);
c->sign = a->sign;
err = MP_OKAY;
goto LBL_ERR;
}
ilog2 = ilog2 / b;
if (ilog2 == 0) {
mp_set(c, 1uL);
c->sign = a->sign;
err = MP_OKAY;
goto LBL_ERR;
}
/* Start value must be larger than root */
ilog2 += 2;
if ((err = mp_2expt(&t2,ilog2)) != MP_OKAY) goto LBL_ERR;
do {
/* t1 = t2 */
if ((err = mp_copy(&t2, &t1)) != MP_OKAY) goto LBL_ERR;
/* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
/* t3 = t1**(b-1) */
if ((err = mp_expt_n(&t1, b - 1, &t3)) != MP_OKAY) goto LBL_ERR;
/* numerator */
/* t2 = t1**b */
if ((err = mp_mul(&t3, &t1, &t2)) != MP_OKAY) goto LBL_ERR;
/* t2 = t1**b - a */
if ((err = mp_sub(&t2, &a_, &t2)) != MP_OKAY) goto LBL_ERR;
/* denominator */
/* t3 = t1**(b-1) * b */
if ((err = mp_mul_d(&t3, (mp_digit)b, &t3)) != MP_OKAY) goto LBL_ERR;
/* t3 = (t1**b - a)/(b * t1**(b-1)) */
if ((err = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY) goto LBL_ERR;
if ((err = mp_sub(&t1, &t3, &t2)) != MP_OKAY) goto LBL_ERR;
/*
Number of rounds is at most log_2(root). If it is more it
got stuck, so break out of the loop and do the rest manually.
*/
if (ilog2-- == 0) {
break;
}
} while (mp_cmp(&t1, &t2) != MP_EQ);
/* result can be off by a few so check */
/* Loop beneath can overshoot by one if found root is smaller than actual root */
for (;;) {
mp_ord cmp;
if ((err = mp_expt_n(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR;
cmp = mp_cmp(&t2, &a_);
if (cmp == MP_EQ) {
err = MP_OKAY;
goto LBL_ERR;
}
if (cmp == MP_LT) {
if ((err = mp_add_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR;
} else {
break;
}
}
/* correct overshoot from above or from recurrence */
for (;;) {
if ((err = mp_expt_n(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR;
if (mp_cmp(&t2, &a_) == MP_GT) {
if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR;
} else {
break;
}
}
/* set the result */
mp_exch(&t1, c);
/* set the sign of the result */
c->sign = a->sign;
LBL_ERR:
mp_clear_multi(&t1, &t2, &t3, (void *)NULL);
return err;
}
#endif
|
Deleted libtommath/bn_mp_root_u32.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to libtommath/bn_mp_set_double.c.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 |
union {
double dbl;
uint64_t bits;
} cast;
cast.dbl = b;
exp = (int)((unsigned)(cast.bits >> 52) & 0x7FFu);
| | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
union {
double dbl;
uint64_t bits;
} cast;
cast.dbl = b;
exp = (int)((unsigned)(cast.bits >> 52) & 0x7FFu);
frac = (cast.bits & ((1uLL << 52) - 1uLL)) | (1uLL << 52);
if (exp == 0x7FF) { /* +-inf, NaN */
return MP_VAL;
}
exp -= 1023 + 52;
mp_set_u64(a, frac);
err = (exp < 0) ? mp_div_2d(a, -exp, a, NULL) : mp_mul_2d(a, exp, a);
if (err != MP_OKAY) {
return err;
}
if (((cast.bits >> 63) != 0uLL) && !MP_IS_ZERO(a)) {
a->sign = MP_NEG;
}
return MP_OKAY;
}
#else
/* pragma message() not supported by several compilers (in mostly older but still used versions) */
|
| ︙ | ︙ |
Deleted libtommath/bn_mp_set_ll.c.
|
| < < < < < < < |
Deleted libtommath/bn_mp_set_ull.c.
|
| < < < < < < < |
Changes to libtommath/bn_mp_sqrtmod_prime.c.
| ︙ | ︙ | |||
21 22 23 24 25 26 27 |
mp_zero(ret);
return MP_OKAY;
}
if (mp_cmp_d(prime, 2uL) == MP_EQ) return MP_VAL; /* prime must be odd */
if ((err = mp_kronecker(n, prime, &legendre)) != MP_OKAY) return err;
if (legendre == -1) return MP_VAL; /* quadratic non-residue mod prime */
| | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
mp_zero(ret);
return MP_OKAY;
}
if (mp_cmp_d(prime, 2uL) == MP_EQ) return MP_VAL; /* prime must be odd */
if ((err = mp_kronecker(n, prime, &legendre)) != MP_OKAY) return err;
if (legendre == -1) return MP_VAL; /* quadratic non-residue mod prime */
if ((err = mp_init_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, (void *)NULL)) != MP_OKAY) {
return err;
}
/* SPECIAL CASE: if prime mod 4 == 3
* compute directly: err = n^(prime+1)/4 mod prime
* Handbook of Applied Cryptography algorithm 3.36
*/
|
| ︙ | ︙ | |||
107 108 109 110 111 112 113 |
if ((err = mp_mulmod(&T, &C, prime, &T)) != MP_OKAY) goto cleanup;
/* T = (T * C) mod prime */
mp_set(&M, i);
/* M = i */
}
cleanup:
| | | 107 108 109 110 111 112 113 114 115 116 117 118 |
if ((err = mp_mulmod(&T, &C, prime, &T)) != MP_OKAY) goto cleanup;
/* T = (T * C) mod prime */
mp_set(&M, i);
/* M = i */
}
cleanup:
mp_clear_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, (void *)NULL);
return err;
}
#endif
|
Added libtommath/bn_s_mp_div_3.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
#include "tommath_private.h"
#ifdef BN_S_MP_DIV_3_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
/* divide by three (based on routine from MPI and the GMP manual) */
mp_err s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d)
{
mp_int q;
mp_word w, t;
mp_digit b;
mp_err err;
int ix;
/* b = 2**MP_DIGIT_BIT / 3 */
b = ((mp_word)1 << (mp_word)MP_DIGIT_BIT) / (mp_word)3;
if ((err = mp_init_size(&q, a->used)) != MP_OKAY) {
return err;
}
q.used = a->used;
q.sign = a->sign;
w = 0;
for (ix = a->used - 1; ix >= 0; ix--) {
w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix];
if (w >= 3u) {
/* multiply w by [1/3] */
t = (w * (mp_word)b) >> (mp_word)MP_DIGIT_BIT;
/* now subtract 3 * [w/3] from w, to get the remainder */
w -= t+t+t;
/* fixup the remainder as required since
* the optimization is not exact.
*/
while (w >= 3u) {
t += 1u;
w -= 3u;
}
} else {
t = 0;
}
q.dp[ix] = (mp_digit)t;
}
/* [optional] store the remainder */
if (d != NULL) {
*d = (mp_digit)w;
}
/* [optional] store the quotient */
if (c != NULL) {
mp_clamp(&q);
mp_exch(&q, c);
}
mp_clear(&q);
return err;
}
#endif
|
Changes to libtommath/bn_s_mp_invmod_fast.c.
| ︙ | ︙ | |||
17 18 19 20 21 22 23 |
/* 2. [modified] b must be odd */
if (MP_IS_EVEN(b)) {
return MP_VAL;
}
/* init all our temps */
| | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
/* 2. [modified] b must be odd */
if (MP_IS_EVEN(b)) {
return MP_VAL;
}
/* init all our temps */
if ((err = mp_init_multi(&x, &y, &u, &v, &B, &D, (void *)NULL)) != MP_OKAY) {
return err;
}
/* x == modulus, y == value to invert */
if ((err = mp_copy(b, &x)) != MP_OKAY) goto LBL_ERR;
/* we need y = |a| */
|
| ︙ | ︙ | |||
108 109 110 111 112 113 114 | } mp_exch(&D, c); c->sign = neg; err = MP_OKAY; LBL_ERR: | | | 108 109 110 111 112 113 114 115 116 117 118 | } mp_exch(&D, c); c->sign = neg; err = MP_OKAY; LBL_ERR: mp_clear_multi(&x, &y, &u, &v, &B, &D, (void *)NULL); return err; } #endif |
Changes to libtommath/bn_s_mp_invmod_slow.c.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 |
/* b cannot be negative */
if ((b->sign == MP_NEG) || MP_IS_ZERO(b)) {
return MP_VAL;
}
/* init temps */
if ((err = mp_init_multi(&x, &y, &u, &v,
| | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
/* b cannot be negative */
if ((b->sign == MP_NEG) || MP_IS_ZERO(b)) {
return MP_VAL;
}
/* init temps */
if ((err = mp_init_multi(&x, &y, &u, &v,
&A, &B, &C, &D, (void *)NULL)) != MP_OKAY) {
return err;
}
/* x = a, y = b */
if ((err = mp_mod(a, b, &x)) != MP_OKAY) goto LBL_ERR;
if ((err = mp_copy(b, &y)) != MP_OKAY) goto LBL_ERR;
|
| ︙ | ︙ | |||
109 110 111 112 113 114 115 |
if ((err = mp_sub(&C, b, &C)) != MP_OKAY) goto LBL_ERR;
}
/* C is now the inverse */
mp_exch(&C, c);
err = MP_OKAY;
LBL_ERR:
| | | 109 110 111 112 113 114 115 116 117 118 119 |
if ((err = mp_sub(&C, b, &C)) != MP_OKAY) goto LBL_ERR;
}
/* C is now the inverse */
mp_exch(&C, c);
err = MP_OKAY;
LBL_ERR:
mp_clear_multi(&x, &y, &u, &v, &A, &B, &C, &D, (void *)NULL);
return err;
}
#endif
|
Added libtommath/bn_s_mp_log.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
#include "tommath_private.h"
#ifdef BN_S_MP_LOG_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
mp_err s_mp_log(const mp_int *a, mp_digit base, int *c)
{
mp_err err;
int high, low;
mp_int bracket_low, bracket_high, bracket_mid, t, bi_base;
mp_ord cmp = mp_cmp_d(a, base);
if ((cmp == MP_LT) || (cmp == MP_EQ)) {
*c = cmp == MP_EQ;
return MP_OKAY;
}
if ((err =
mp_init_multi(&bracket_low, &bracket_high,
&bracket_mid, &t, &bi_base, (void *)NULL)) != MP_OKAY) {
return err;
}
low = 0;
mp_set(&bracket_low, 1uL);
high = 1;
mp_set(&bracket_high, base);
/*
A kind of Giant-step/baby-step algorithm.
Idea shamelessly stolen from https://programmingpraxis.com/2010/05/07/integer-logarithms/2/
The effect is asymptotic, hence needs benchmarks to test if the Giant-step should be skipped
for small n.
*/
while (mp_cmp(&bracket_high, a) == MP_LT) {
low = high;
if ((err = mp_copy(&bracket_high, &bracket_low)) != MP_OKAY) {
goto LBL_END;
}
high <<= 1;
if ((err = mp_sqr(&bracket_high, &bracket_high)) != MP_OKAY) {
goto LBL_END;
}
}
mp_set(&bi_base, base);
while ((high - low) > 1) {
int mid = (high + low) >> 1;
if ((err = mp_expt_n(&bi_base, mid - low, &t)) != MP_OKAY) {
goto LBL_END;
}
if ((err = mp_mul(&bracket_low, &t, &bracket_mid)) != MP_OKAY) {
goto LBL_END;
}
cmp = mp_cmp(a, &bracket_mid);
if (cmp == MP_LT) {
high = mid;
mp_exch(&bracket_mid, &bracket_high);
}
if (cmp == MP_GT) {
low = mid;
mp_exch(&bracket_mid, &bracket_low);
}
if (cmp == MP_EQ) {
*c = mid;
goto LBL_END;
}
}
*c = (mp_cmp(&bracket_high, a) == MP_EQ) ? high : low;
LBL_END:
mp_clear_multi(&bracket_low, &bracket_high, &bracket_mid,
&t, &bi_base, (void *)NULL);
return err;
}
#endif
|
Added libtommath/bn_s_mp_log_2expt.c.
> > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 |
#include "tommath_private.h"
#ifdef BN_S_MP_LOG_2EXPT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
int s_mp_log_2expt(const mp_int *a, mp_digit base)
{
int y;
for (y = 0; (base & 1) == 0; y++, base >>= 1) {}
return (mp_count_bits(a) - 1) / y;
}
#endif
|
Added libtommath/bn_s_mp_log_d.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
#include "tommath_private.h"
#ifdef BN_S_MP_LOG_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
static mp_word s_pow(mp_word base, mp_word exponent)
{
mp_word result = 1u;
while (exponent != 0u) {
if ((exponent & 1u) == 1u) {
result *= base;
}
exponent >>= 1;
base *= base;
}
return result;
}
int s_mp_log_d(mp_digit base, mp_digit n)
{
mp_word bracket_low = 1uLL, bracket_high = base, N = n;
int ret, high = 1, low = 0;
if (n < base) {
return 0;
}
if (n == base) {
return 1;
}
while (bracket_high < N) {
low = high;
bracket_low = bracket_high;
high <<= 1;
bracket_high *= bracket_high;
}
while (((mp_digit)(high - low)) > 1uL) {
int mid = (low + high) >> 1;
mp_word bracket_mid = bracket_low * s_pow(base, (mp_word)(mid - low));
if (N < bracket_mid) {
high = mid ;
bracket_high = bracket_mid ;
}
if (N > bracket_mid) {
low = mid ;
bracket_low = bracket_mid ;
}
if (N == bracket_mid) {
return mid;
}
}
if (bracket_high == N) {
ret = high;
} else {
ret = low;
}
return ret;
}
#endif
|
Changes to libtommath/bn_s_mp_mul_high_digs_fast.c.
1 2 3 4 5 | #include "tommath_private.h" #ifdef BN_S_MP_MUL_HIGH_DIGS_FAST_C /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | #include "tommath_private.h" #ifdef BN_S_MP_MUL_HIGH_DIGS_FAST_C /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* this is a modified version of s_mp_mul_digs_fast that only produces * output digits *above* digs. See the comments for s_mp_mul_digs_fast * to see how it works. * * This is used in the Barrett reduction since for one of the multiplications * only the higher digits were needed. This essentially halves the work. * * Based on Algorithm 14.12 on pp.595 of HAC. |
| ︙ | ︙ |
Changes to libtommath/bn_s_mp_toom_mul.c.
| ︙ | ︙ | |||
142 143 144 145 146 147 148 | if ((err = mp_mul(&a2, &b2, &b1)) != MP_OKAY) goto LBL_ERR; /** \\S2 = (S2 - S3)/3; */ /** S2 = S2 - a1; */ if ((err = mp_sub(&S2, &a1, &S2)) != MP_OKAY) goto LBL_ERR; /** S2 = S2 / 3; \\ this is an exact division */ | | | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | if ((err = mp_mul(&a2, &b2, &b1)) != MP_OKAY) goto LBL_ERR; /** \\S2 = (S2 - S3)/3; */ /** S2 = S2 - a1; */ if ((err = mp_sub(&S2, &a1, &S2)) != MP_OKAY) goto LBL_ERR; /** S2 = S2 / 3; \\ this is an exact division */ if ((err = s_mp_div_3(&S2, &S2, NULL)) != MP_OKAY) goto LBL_ERR; /** a1 = S1 - a1; */ if ((err = mp_sub(&S1, &a1, &a1)) != MP_OKAY) goto LBL_ERR; /** a1 = a1 >> 1; */ if ((err = mp_div_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR; |
| ︙ | ︙ |
Changes to libtommath/changes.txt.
1 2 3 4 5 6 7 |
Sep 04th, 2023
v1.2.1
-- Bugfix release because of potential integer overflow
c.f. PR #546 resp. CVE-2023-36328
Oct 22nd, 2019
v1.2.0
| > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 |
Mar 27th, 2024
v1.3.0
-- Deprecate more APIs which are replaced in develop (PR #572)
-- Add support for CMake (PR #573)
-- Add support for GitHub Actions (PR #573)
Sep 04th, 2023
v1.2.1
-- Bugfix release because of potential integer overflow
c.f. PR #546 resp. CVE-2023-36328
Oct 22nd, 2019
v1.2.0
|
| ︙ | ︙ |
Changes to libtommath/helper.pl.
| ︙ | ︙ | |||
217 218 219 220 221 222 223 224 225 226 227 |
}
else {
die "patch_file failed: " . substr($v, 0, 30) . "..";
}
}
return $content;
}
sub process_makefiles {
my $write = shift;
my $changed_count = 0;
| > > > > > > > > > > > > > > > > > > > > > | | | > | > | 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
}
else {
die "patch_file failed: " . substr($v, 0, 30) . "..";
}
}
return $content;
}
sub make_sources_cmake {
my ($src_ref, $hdr_ref) = @_;
my @sources = @{ $src_ref };
my @headers = @{ $hdr_ref };
my $output = "# SPDX-License-Identifier: Unlicense
# Autogenerated File! Do not edit.
set(SOURCES\n";
foreach my $sobj (sort @sources) {
$output .= $sobj . "\n";
}
$output .= ")\n\nset(HEADERS\n";
foreach my $hobj (sort @headers) {
$output .= $hobj . "\n";
}
$output .= ")\n";
return $output;
}
sub process_makefiles {
my $write = shift;
my $changed_count = 0;
my @headers = bsd_glob("*.h");
my @sources = bsd_glob("*.c");
my @o = map { my $x = $_; $x =~ s/\.c$/.o/; $x } @sources;
my @all = sort(@sources, @headers);
my $var_o = prepare_variable("OBJECTS", @o);
(my $var_obj = $var_o) =~ s/\.o\b/.obj/sg;
# update MSVC project files
my $msvc_files = prepare_msvc_files_xml(\@all, qr/NOT_USED_HERE/, ['Debug|Win32', 'Release|Win32', 'Debug|x64', 'Release|x64']);
for my $m (qw/libtommath_VS2008.vcproj/) {
my $old = read_file($m);
my $new = $old;
$new =~ s|<Files>.*</Files>|$msvc_files|s;
if ($old ne $new) {
write_file($m, $new) if $write;
warn "changed: $m\n";
$changed_count++;
}
}
# update OBJECTS + HEADERS in makefile*
for my $m (qw/ makefile makefile.shared makefile_include.mk makefile.msvc makefile.unix makefile.mingw sources.cmake /) {
my $old = read_file($m);
my $new = $m eq 'makefile.msvc' ? patch_file($old, $var_obj)
: $m eq 'sources.cmake' ? make_sources_cmake(\@sources, \@headers)
: patch_file($old, $var_o);
if ($old ne $new) {
write_file($m, $new) if $write;
warn "changed: $m\n";
$changed_count++;
}
}
|
| ︙ | ︙ | |||
385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
my $a = $&;
next if $a eq "mp_err";
$a =~ tr/[a-z]/[A-Z]/;
$a = 'BN_' . $a . '_C';
push @deps, $a;
}
}
@deps = sort(@deps);
foreach my $a (@deps) {
if ($list !~ /$a/) {
print {$class} "# define $a\n";
}
$list = $list . ',' . $a;
}
| > > > > > | 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
my $a = $&;
next if $a eq "mp_err";
$a =~ tr/[a-z]/[A-Z]/;
$a = 'BN_' . $a . '_C';
push @deps, $a;
}
}
if ($filename =~ "BN_DEPRECATED") {
push(@deps, qw(BN_MP_GET_LL_C BN_MP_INIT_LL_C BN_MP_SET_LL_C));
push(@deps, qw(BN_MP_GET_MAG_ULL_C BN_MP_INIT_ULL_C BN_MP_SET_ULL_C));
push(@deps, qw(BN_MP_DIV_3_C BN_MP_EXPT_U32_C BN_MP_ROOT_U32_C BN_MP_LOG_U32_C));
}
@deps = sort(@deps);
foreach my $a (@deps) {
if ($list !~ /$a/) {
print {$class} "# define $a\n";
}
$list = $list . ',' . $a;
}
|
| ︙ | ︙ | |||
431 432 433 434 435 436 437 438 439 440 441 442 443 444 |
sub generate_def {
my @files = split /\n/, `git ls-files`;
@files = grep(/\.c/, @files);
@files = map { my $x = $_; $x =~ s/^bn_|\.c$//g; $x; } @files;
@files = grep(!/mp_radix_smap/, @files);
push(@files, qw(mp_set_int mp_set_long mp_set_long_long mp_get_int mp_get_long mp_get_long_long mp_init_set_int));
my $files = join("\n ", sort(grep(/^mp_/, @files)));
write_file "tommath.def", "; libtommath
;
; Use this command to produce a 32-bit .lib file, for use in any MSVC version
; lib -machine:X86 -name:libtommath.dll -def:tommath.def -out:tommath.lib
; Use this command to produce a 64-bit .lib file, for use in any MSVC version
| > > | 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
sub generate_def {
my @files = split /\n/, `git ls-files`;
@files = grep(/\.c/, @files);
@files = map { my $x = $_; $x =~ s/^bn_|\.c$//g; $x; } @files;
@files = grep(!/mp_radix_smap/, @files);
push(@files, qw(mp_set_int mp_set_long mp_set_long_long mp_get_int mp_get_long mp_get_long_long mp_init_set_int));
push(@files, qw(mp_get_ll mp_get_mag_ull mp_init_ll mp_set_ll mp_init_ull mp_set_ull));
push(@files, qw(mp_div_3 mp_expt_u32 mp_root_u32 mp_log_u32));
my $files = join("\n ", sort(grep(/^mp_/, @files)));
write_file "tommath.def", "; libtommath
;
; Use this command to produce a 32-bit .lib file, for use in any MSVC version
; lib -machine:X86 -name:libtommath.dll -def:tommath.def -out:tommath.lib
; Use this command to produce a 64-bit .lib file, for use in any MSVC version
|
| ︙ | ︙ |
Changes to libtommath/libtommath.pc.in.
|
| | | < | | | 1 2 3 4 5 6 7 8 9 |
prefix=@CMAKE_INSTALL_PREFIX@
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: LibTomMath
Description: public domain library for manipulating large integer numbers
Version: @PROJECT_VERSION@
Libs: -L${libdir} -ltommath
Cflags: -I${includedir}
|
Changes to libtommath/libtommath_VS2008.sln.
| ︙ | ︙ |
Changes to libtommath/libtommath_VS2008.vcproj.
| ︙ | ︙ | |||
395 396 397 398 399 400 401 | <File RelativePath="bn_mp_div_2.c" > </File> <File RelativePath="bn_mp_div_2d.c" > | < < < < | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | <File RelativePath="bn_mp_div_2.c" > </File> <File RelativePath="bn_mp_div_2d.c" > </File> <File RelativePath="bn_mp_div_d.c" > </File> <File RelativePath="bn_mp_dr_is_modulus.c" |
| ︙ | ︙ | |||
425 426 427 428 429 430 431 | > </File> <File RelativePath="bn_mp_exch.c" > </File> <File | | | 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 | > </File> <File RelativePath="bn_mp_exch.c" > </File> <File RelativePath="bn_mp_expt_n.c" > </File> <File RelativePath="bn_mp_exptmod.c" > </File> <File |
| ︙ | ︙ | |||
471 472 473 474 475 476 477 | <File RelativePath="bn_mp_get_i64.c" > </File> <File RelativePath="bn_mp_get_l.c" > | < < < < < < < < | 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | <File RelativePath="bn_mp_get_i64.c" > </File> <File RelativePath="bn_mp_get_l.c" > </File> <File RelativePath="bn_mp_get_mag_u32.c" > </File> <File RelativePath="bn_mp_get_mag_u64.c" > </File> <File RelativePath="bn_mp_get_mag_ul.c" > </File> <File RelativePath="bn_mp_grow.c" > </File> <File RelativePath="bn_mp_incr.c" |
| ︙ | ︙ | |||
519 520 521 522 523 524 525 | <File RelativePath="bn_mp_init_i64.c" > </File> <File RelativePath="bn_mp_init_l.c" > | < < < < | 507 508 509 510 511 512 513 514 515 516 517 518 519 520 | <File RelativePath="bn_mp_init_i64.c" > </File> <File RelativePath="bn_mp_init_l.c" > </File> <File RelativePath="bn_mp_init_multi.c" > </File> <File RelativePath="bn_mp_init_set.c" |
| ︙ | ︙ | |||
547 548 549 550 551 552 553 | <File RelativePath="bn_mp_init_u64.c" > </File> <File RelativePath="bn_mp_init_ul.c" > | < < < < | 531 532 533 534 535 536 537 538 539 540 541 542 543 544 | <File RelativePath="bn_mp_init_u64.c" > </File> <File RelativePath="bn_mp_init_ul.c" > </File> <File RelativePath="bn_mp_invmod.c" > </File> <File RelativePath="bn_mp_is_square.c" |
| ︙ | ︙ | |||
577 578 579 580 581 582 583 | > </File> <File RelativePath="bn_mp_lcm.c" > </File> <File | | | 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 | > </File> <File RelativePath="bn_mp_lcm.c" > </File> <File RelativePath="bn_mp_log_n.c" > </File> <File RelativePath="bn_mp_lshd.c" > </File> <File |
| ︙ | ︙ | |||
725 726 727 728 729 730 731 | > </File> <File RelativePath="bn_mp_reduce_setup.c" > </File> <File | | | 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 | > </File> <File RelativePath="bn_mp_reduce_setup.c" > </File> <File RelativePath="bn_mp_root_n.c" > </File> <File RelativePath="bn_mp_rshd.c" > </File> <File |
| ︙ | ︙ | |||
755 756 757 758 759 760 761 | <File RelativePath="bn_mp_set_i64.c" > </File> <File RelativePath="bn_mp_set_l.c" > | < < < < < < < < | 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 | <File RelativePath="bn_mp_set_i64.c" > </File> <File RelativePath="bn_mp_set_l.c" > </File> <File RelativePath="bn_mp_set_u32.c" > </File> <File RelativePath="bn_mp_set_u64.c" > </File> <File RelativePath="bn_mp_set_ul.c" > </File> <File RelativePath="bn_mp_shrink.c" > </File> <File RelativePath="bn_mp_signed_rsh.c" |
| ︙ | ︙ | |||
851 852 853 854 855 856 857 858 859 860 861 862 863 864 | <File RelativePath="bn_s_mp_add.c" > </File> <File RelativePath="bn_s_mp_balance_mul.c" > </File> <File RelativePath="bn_s_mp_exptmod.c" > </File> <File RelativePath="bn_s_mp_exptmod_fast.c" | > > > > | 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 | <File RelativePath="bn_s_mp_add.c" > </File> <File RelativePath="bn_s_mp_balance_mul.c" > </File> <File RelativePath="bn_s_mp_div_3.c" > </File> <File RelativePath="bn_s_mp_exptmod.c" > </File> <File RelativePath="bn_s_mp_exptmod_fast.c" |
| ︙ | ︙ | |||
879 880 881 882 883 884 885 886 887 888 889 890 891 892 | <File RelativePath="bn_s_mp_karatsuba_mul.c" > </File> <File RelativePath="bn_s_mp_karatsuba_sqr.c" > </File> <File RelativePath="bn_s_mp_montgomery_reduce_fast.c" > </File> <File RelativePath="bn_s_mp_mul_digs.c" | > > > > > > > > > > > > | 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 | <File RelativePath="bn_s_mp_karatsuba_mul.c" > </File> <File RelativePath="bn_s_mp_karatsuba_sqr.c" > </File> <File RelativePath="bn_s_mp_log.c" > </File> <File RelativePath="bn_s_mp_log_2expt.c" > </File> <File RelativePath="bn_s_mp_log_d.c" > </File> <File RelativePath="bn_s_mp_montgomery_reduce_fast.c" > </File> <File RelativePath="bn_s_mp_mul_digs.c" |
| ︙ | ︙ |
Changes to libtommath/makefile.
| ︙ | ︙ | |||
25 26 27 28 29 30 31 | LCOV_ARGS=--directory . #START_INS OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ | | | | | | < | | | | | | | | | | | | | | | > | | | | | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | LCOV_ARGS=--directory . #START_INS OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ bn_mp_div_2d.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_n.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \ bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o bn_mp_grow.o \ bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o bn_mp_init_i64.o bn_mp_init_l.o \ bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o \ bn_mp_invmod.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_n.o \ bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \ bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \ bn_mp_mulmod.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o \ bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o \ bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o \ bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o \ bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \ bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o \ bn_mp_root_n.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o \ bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_shrink.o \ bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \ bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o \ bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_div_3.o \ bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o \ bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_log.o bn_s_mp_log_2expt.o bn_s_mp_log_d.o \ bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o \ bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o \ bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o \ bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o #END_INS $(LIBNAME): $(OBJECTS) $(AR) $(ARFLAGS) $@ $(OBJECTS) $(RANLIB) $@ |
| ︙ | ︙ | |||
129 130 131 132 133 134 135 | .PHONY: pre_gen pre_gen: mkdir -p pre_gen perl gen.pl sed -e 's/[[:blank:]]*$$//' mpi.c > pre_gen/mpi.c rm mpi.c | > > > > | | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | .PHONY: pre_gen pre_gen: mkdir -p pre_gen perl gen.pl sed -e 's/[[:blank:]]*$$//' mpi.c > pre_gen/mpi.c rm mpi.c zipup: $(MAKE) clean $(MAKE) .zipup .zipup: astyle new_file docs @# Update the index, so diff-index won't fail in case the pdf has been created. @# As the pdf creation modifies the tex files, git sometimes detects the @# modified files, but misses that it's put back to its original version. @git update-index --refresh @git diff-index --quiet HEAD -- || ( echo "FAILURE: uncommited changes or not a git" && exit 1 ) rm -rf libtommath-$(VERSION) ltm-$(VERSION).* @# files/dirs excluded from "git archive" are defined in .gitattributes |
| ︙ | ︙ |
Changes to libtommath/makefile.mingw.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # MAKEFILE for MS Windows (mingw + gcc + gmake) # # BEWARE: variable OBJECTS is updated via helper.pl ### USAGE: # Open a command prompt with gcc + gmake in PATH and start: # # gmake -f makefile.mingw all # test.exe # gmake -f makefile.mingw PREFIX=c:\devel\libtom install #The following can be overridden from command line e.g. make -f makefile.mingw CC=gcc ARFLAGS=rcs PREFIX = c:\mingw | | > > | > > | | | | | | < | | | | | | | | | | | | | | | > | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | # MAKEFILE for MS Windows (mingw + gcc + gmake) # # BEWARE: variable OBJECTS is updated via helper.pl ### USAGE: # Open a command prompt with gcc + gmake in PATH and start: # # gmake -f makefile.mingw all # test.exe # gmake -f makefile.mingw PREFIX=c:\devel\libtom install #The following can be overridden from command line e.g. make -f makefile.mingw CC=gcc ARFLAGS=rcs PREFIX = c:\mingw CC = i686-w64-mingw32-gcc #CC = x86_64-w64-mingw32-clang #CC = aarch64-w64-mingw32-clang AR = ar ARFLAGS = r RANLIB = ranlib STRIP = i686-w64-mingw32-gcc-strip #STRIP = x86_64-w64-mingw32-strip #STRIP = aarch64-w64-mingw32-strip CFLAGS = -O2 LDFLAGS = #Compilation flags LTM_CFLAGS = -I. $(CFLAGS) -DTCL_WITH_EXTERNAL_TOMMATH LTM_LDFLAGS = $(LDFLAGS) -static-libgcc #Libraries to be created LIBMAIN_S =libtommath.a LIBMAIN_I =libtommath.dll.a LIBMAIN_D =libtommath.dll #List of objects to compile (all goes to libtommath.a) OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ bn_mp_div_2d.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_n.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \ bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o bn_mp_grow.o \ bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o bn_mp_init_i64.o bn_mp_init_l.o \ bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o \ bn_mp_invmod.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_n.o \ bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \ bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \ bn_mp_mulmod.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o \ bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o \ bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o \ bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o \ bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \ bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o \ bn_mp_root_n.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o \ bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_shrink.o \ bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \ bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o \ bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_div_3.o \ bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o \ bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_log.o bn_s_mp_log_2expt.o bn_s_mp_log_d.o \ bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o \ bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o \ bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o \ bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o HEADERS_PUB=tommath.h HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) #The default rule for make builds the libtommath.a library (static) default: $(LIBMAIN_S) #Dependencies on *.h $(OBJECTS): $(HEADERS) .c.o: $(CC) $(LTM_CFLAGS) -c $< -o $@ #Create libtommath.a $(LIBMAIN_S): $(OBJECTS) $(AR) $(ARFLAGS) $@ $(OBJECTS) $(RANLIB) $@ #Create DLL + import library libtommath.dll.a $(LIBMAIN_D) $(LIBMAIN_I): $(OBJECTS) $(CC) -s -shared -o $(LIBMAIN_D) $^ -Wl,--enable-auto-import tommath.def -Wl,--out-implib=$(LIBMAIN_I) $(LTM_LDFLAGS) $(STRIP) -S $(LIBMAIN_D) #Build test suite test.exe: demo/shared.o demo/test.o $(LIBMAIN_S) $(CC) $(LTM_CFLAGS) $(LTM_LDFLAGS) $^ -o $@ @echo NOTICE: start the tests by launching test.exe |
| ︙ | ︙ |
Changes to libtommath/makefile.msvc.
| ︙ | ︙ | |||
20 21 22 23 24 25 26 | #Libraries to be created (this makefile builds only static libraries) LIBMAIN_S =tommath.lib #List of objects to compile (all goes to tommath.lib) OBJECTS=bn_cutoffs.obj bn_deprecated.obj bn_mp_2expt.obj bn_mp_abs.obj bn_mp_add.obj bn_mp_add_d.obj bn_mp_addmod.obj \ bn_mp_and.obj bn_mp_clamp.obj bn_mp_clear.obj bn_mp_clear_multi.obj bn_mp_cmp.obj bn_mp_cmp_d.obj bn_mp_cmp_mag.obj \ bn_mp_cnt_lsb.obj bn_mp_complement.obj bn_mp_copy.obj bn_mp_count_bits.obj bn_mp_decr.obj bn_mp_div.obj bn_mp_div_2.obj \ | | | | | | < | | | | | | > | | | | < | | | | > | | | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #Libraries to be created (this makefile builds only static libraries) LIBMAIN_S =tommath.lib #List of objects to compile (all goes to tommath.lib) OBJECTS=bn_cutoffs.obj bn_deprecated.obj bn_mp_2expt.obj bn_mp_abs.obj bn_mp_add.obj bn_mp_add_d.obj bn_mp_addmod.obj \ bn_mp_and.obj bn_mp_clamp.obj bn_mp_clear.obj bn_mp_clear_multi.obj bn_mp_cmp.obj bn_mp_cmp_d.obj bn_mp_cmp_mag.obj \ bn_mp_cnt_lsb.obj bn_mp_complement.obj bn_mp_copy.obj bn_mp_count_bits.obj bn_mp_decr.obj bn_mp_div.obj bn_mp_div_2.obj \ bn_mp_div_2d.obj bn_mp_div_d.obj bn_mp_dr_is_modulus.obj bn_mp_dr_reduce.obj bn_mp_dr_setup.obj \ bn_mp_error_to_string.obj bn_mp_exch.obj bn_mp_expt_n.obj bn_mp_exptmod.obj bn_mp_exteuclid.obj bn_mp_fread.obj \ bn_mp_from_sbin.obj bn_mp_from_ubin.obj bn_mp_fwrite.obj bn_mp_gcd.obj bn_mp_get_double.obj bn_mp_get_i32.obj \ bn_mp_get_i64.obj bn_mp_get_l.obj bn_mp_get_mag_u32.obj bn_mp_get_mag_u64.obj bn_mp_get_mag_ul.obj bn_mp_grow.obj \ bn_mp_incr.obj bn_mp_init.obj bn_mp_init_copy.obj bn_mp_init_i32.obj bn_mp_init_i64.obj bn_mp_init_l.obj \ bn_mp_init_multi.obj bn_mp_init_set.obj bn_mp_init_size.obj bn_mp_init_u32.obj bn_mp_init_u64.obj bn_mp_init_ul.obj \ bn_mp_invmod.obj bn_mp_is_square.obj bn_mp_iseven.obj bn_mp_isodd.obj bn_mp_kronecker.obj bn_mp_lcm.obj bn_mp_log_n.obj \ bn_mp_lshd.obj bn_mp_mod.obj bn_mp_mod_2d.obj bn_mp_mod_d.obj bn_mp_montgomery_calc_normalization.obj \ bn_mp_montgomery_reduce.obj bn_mp_montgomery_setup.obj bn_mp_mul.obj bn_mp_mul_2.obj bn_mp_mul_2d.obj bn_mp_mul_d.obj \ bn_mp_mulmod.obj bn_mp_neg.obj bn_mp_or.obj bn_mp_pack.obj bn_mp_pack_count.obj bn_mp_prime_fermat.obj \ bn_mp_prime_frobenius_underwood.obj bn_mp_prime_is_prime.obj bn_mp_prime_miller_rabin.obj \ bn_mp_prime_next_prime.obj bn_mp_prime_rabin_miller_trials.obj bn_mp_prime_rand.obj \ bn_mp_prime_strong_lucas_selfridge.obj bn_mp_radix_size.obj bn_mp_radix_smap.obj bn_mp_rand.obj \ bn_mp_read_radix.obj bn_mp_reduce.obj bn_mp_reduce_2k.obj bn_mp_reduce_2k_l.obj bn_mp_reduce_2k_setup.obj \ bn_mp_reduce_2k_setup_l.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_is_2k_l.obj bn_mp_reduce_setup.obj \ bn_mp_root_n.obj bn_mp_rshd.obj bn_mp_sbin_size.obj bn_mp_set.obj bn_mp_set_double.obj bn_mp_set_i32.obj \ bn_mp_set_i64.obj bn_mp_set_l.obj bn_mp_set_u32.obj bn_mp_set_u64.obj bn_mp_set_ul.obj bn_mp_shrink.obj \ bn_mp_signed_rsh.obj bn_mp_sqr.obj bn_mp_sqrmod.obj bn_mp_sqrt.obj bn_mp_sqrtmod_prime.obj bn_mp_sub.obj bn_mp_sub_d.obj \ bn_mp_submod.obj bn_mp_to_radix.obj bn_mp_to_sbin.obj bn_mp_to_ubin.obj bn_mp_ubin_size.obj bn_mp_unpack.obj \ bn_mp_xor.obj bn_mp_zero.obj bn_prime_tab.obj bn_s_mp_add.obj bn_s_mp_balance_mul.obj bn_s_mp_div_3.obj \ bn_s_mp_exptmod.obj bn_s_mp_exptmod_fast.obj bn_s_mp_get_bit.obj bn_s_mp_invmod_fast.obj bn_s_mp_invmod_slow.obj \ bn_s_mp_karatsuba_mul.obj bn_s_mp_karatsuba_sqr.obj bn_s_mp_log.obj bn_s_mp_log_2expt.obj bn_s_mp_log_d.obj \ bn_s_mp_montgomery_reduce_fast.obj bn_s_mp_mul_digs.obj bn_s_mp_mul_digs_fast.obj bn_s_mp_mul_high_digs.obj \ bn_s_mp_mul_high_digs_fast.obj bn_s_mp_prime_is_divisible.obj bn_s_mp_rand_jenkins.obj \ bn_s_mp_rand_platform.obj bn_s_mp_reverse.obj bn_s_mp_sqr.obj bn_s_mp_sqr_fast.obj bn_s_mp_sub.obj \ bn_s_mp_toom_mul.obj bn_s_mp_toom_sqr.obj HEADERS_PUB=tommath.h HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) #The default rule for make builds the tommath.lib library (static) default: $(LIBMAIN_S) |
| ︙ | ︙ |
Changes to libtommath/makefile.shared.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 | LCOV_ARGS=--directory .libs --directory . #START_INS OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ | | | | | | < | | | | | | | | | | | | | | | > | | | | | > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | LCOV_ARGS=--directory .libs --directory . #START_INS OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ bn_mp_div_2d.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_n.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \ bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o bn_mp_grow.o \ bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o bn_mp_init_i64.o bn_mp_init_l.o \ bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o \ bn_mp_invmod.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_n.o \ bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \ bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \ bn_mp_mulmod.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o \ bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o \ bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o \ bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o \ bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \ bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o \ bn_mp_root_n.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o \ bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_shrink.o \ bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \ bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o \ bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_div_3.o \ bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o \ bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_log.o bn_s_mp_log_2expt.o bn_s_mp_log_d.o \ bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o \ bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o \ bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o \ bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o #END_INS objs: $(OBJECTS) .c.o: $(HEADERS) $(LTCOMPILE) $(LTM_CFLAGS) $(LTM_LDFLAGS) -o $@ -c $< LOBJECTS = $(OBJECTS:.o=.lo) $(LIBNAME): $(OBJECTS) $(LTLINK) $(LTM_LDFLAGS) $(LOBJECTS) -o $(LIBNAME) -rpath $(LIBPATH) -version-info $(VERSION_SO) $(LTM_LIBTOOLFLAGS) install: $(LIBNAME) install -d $(DESTDIR)$(LIBPATH) install -d $(DESTDIR)$(INCPATH) $(LIBTOOL) --mode=install install -m 644 $(LIBNAME) $(DESTDIR)$(LIBPATH)/$(LIBNAME) install -m 644 $(HEADERS_PUB) $(DESTDIR)$(INCPATH) sed -e 's,^prefix=.*,prefix=$(PREFIX),' -e 's,^Version:.*,Version: $(VERSION_PC),' -e 's,@CMAKE_INSTALL_LIBDIR@,lib,' \ -e 's,@CMAKE_INSTALL_INCLUDEDIR@,include,' libtommath.pc.in > libtommath.pc install -d $(DESTDIR)$(LIBPATH)/pkgconfig install -m 644 libtommath.pc $(DESTDIR)$(LIBPATH)/pkgconfig/ uninstall: $(LIBTOOL) --mode=uninstall rm $(DESTDIR)$(LIBPATH)/$(LIBNAME) rm $(HEADERS_PUB:%=$(DESTDIR)$(INCPATH)/%) rm $(DESTDIR)$(LIBPATH)/pkgconfig/libtommath.pc |
| ︙ | ︙ |
Changes to libtommath/makefile.unix.
| ︙ | ︙ | |||
17 18 19 20 21 22 23 | CC = cc AR = ar ARFLAGS = r RANLIB = ranlib CFLAGS = -O2 LDFLAGS = | | | | | | | < | | | | | | | | | | | | | | | > | | | | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | CC = cc AR = ar ARFLAGS = r RANLIB = ranlib CFLAGS = -O2 LDFLAGS = VERSION = 1.3.0 #Compilation flags LTM_CFLAGS = -I. $(CFLAGS) LTM_LDFLAGS = $(LDFLAGS) #Library to be created (this makefile builds only static library) LIBMAIN_S = libtommath.a OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ bn_mp_div_2d.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_n.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \ bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o bn_mp_grow.o \ bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o bn_mp_init_i64.o bn_mp_init_l.o \ bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o \ bn_mp_invmod.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_n.o \ bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \ bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \ bn_mp_mulmod.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o \ bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o \ bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o \ bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o \ bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \ bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o \ bn_mp_root_n.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o \ bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_shrink.o \ bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \ bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o \ bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_div_3.o \ bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o \ bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_log.o bn_s_mp_log_2expt.o bn_s_mp_log_d.o \ bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o \ bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o \ bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o \ bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o HEADERS_PUB=tommath.h HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) #The default rule for make builds the libtommath.a library (static) default: $(LIBMAIN_S) |
| ︙ | ︙ |
Changes to libtommath/makefile_include.mk.
1 2 3 4 5 | # # Include makefile for libtommath # #version of library | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#
# Include makefile for libtommath
#
#version of library
VERSION=1.3.0
VERSION_PC=1.3.0
VERSION_SO=4:0:3
PLATFORM := $(shell uname | sed -e 's/_.*//')
# default make target
default: ${LIBNAME}
# Compiler and Linker Names
|
| ︙ | ︙ |
Added libtommath/sources.cmake.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | # SPDX-License-Identifier: Unlicense # Autogenerated File! Do not edit. set(SOURCES bn_cutoffs.c bn_deprecated.c bn_mp_2expt.c bn_mp_abs.c bn_mp_add.c bn_mp_add_d.c bn_mp_addmod.c bn_mp_and.c bn_mp_clamp.c bn_mp_clear.c bn_mp_clear_multi.c bn_mp_cmp.c bn_mp_cmp_d.c bn_mp_cmp_mag.c bn_mp_cnt_lsb.c bn_mp_complement.c bn_mp_copy.c bn_mp_count_bits.c bn_mp_decr.c bn_mp_div.c bn_mp_div_2.c bn_mp_div_2d.c bn_mp_div_d.c bn_mp_dr_is_modulus.c bn_mp_dr_reduce.c bn_mp_dr_setup.c bn_mp_error_to_string.c bn_mp_exch.c bn_mp_expt_n.c bn_mp_exptmod.c bn_mp_exteuclid.c bn_mp_fread.c bn_mp_from_sbin.c bn_mp_from_ubin.c bn_mp_fwrite.c bn_mp_gcd.c bn_mp_get_double.c bn_mp_get_i32.c bn_mp_get_i64.c bn_mp_get_l.c bn_mp_get_mag_u32.c bn_mp_get_mag_u64.c bn_mp_get_mag_ul.c bn_mp_grow.c bn_mp_incr.c bn_mp_init.c bn_mp_init_copy.c bn_mp_init_i32.c bn_mp_init_i64.c bn_mp_init_l.c bn_mp_init_multi.c bn_mp_init_set.c bn_mp_init_size.c bn_mp_init_u32.c bn_mp_init_u64.c bn_mp_init_ul.c bn_mp_invmod.c bn_mp_is_square.c bn_mp_iseven.c bn_mp_isodd.c bn_mp_kronecker.c bn_mp_lcm.c bn_mp_log_n.c bn_mp_lshd.c bn_mp_mod.c bn_mp_mod_2d.c bn_mp_mod_d.c bn_mp_montgomery_calc_normalization.c bn_mp_montgomery_reduce.c bn_mp_montgomery_setup.c bn_mp_mul.c bn_mp_mul_2.c bn_mp_mul_2d.c bn_mp_mul_d.c bn_mp_mulmod.c bn_mp_neg.c bn_mp_or.c bn_mp_pack.c bn_mp_pack_count.c bn_mp_prime_fermat.c bn_mp_prime_frobenius_underwood.c bn_mp_prime_is_prime.c bn_mp_prime_miller_rabin.c bn_mp_prime_next_prime.c bn_mp_prime_rabin_miller_trials.c bn_mp_prime_rand.c bn_mp_prime_strong_lucas_selfridge.c bn_mp_radix_size.c bn_mp_radix_smap.c bn_mp_rand.c bn_mp_read_radix.c bn_mp_reduce.c bn_mp_reduce_2k.c bn_mp_reduce_2k_l.c bn_mp_reduce_2k_setup.c bn_mp_reduce_2k_setup_l.c bn_mp_reduce_is_2k.c bn_mp_reduce_is_2k_l.c bn_mp_reduce_setup.c bn_mp_root_n.c bn_mp_rshd.c bn_mp_sbin_size.c bn_mp_set.c bn_mp_set_double.c bn_mp_set_i32.c bn_mp_set_i64.c bn_mp_set_l.c bn_mp_set_u32.c bn_mp_set_u64.c bn_mp_set_ul.c bn_mp_shrink.c bn_mp_signed_rsh.c bn_mp_sqr.c bn_mp_sqrmod.c bn_mp_sqrt.c bn_mp_sqrtmod_prime.c bn_mp_sub.c bn_mp_sub_d.c bn_mp_submod.c bn_mp_to_radix.c bn_mp_to_sbin.c bn_mp_to_ubin.c bn_mp_ubin_size.c bn_mp_unpack.c bn_mp_xor.c bn_mp_zero.c bn_prime_tab.c bn_s_mp_add.c bn_s_mp_balance_mul.c bn_s_mp_div_3.c bn_s_mp_exptmod.c bn_s_mp_exptmod_fast.c bn_s_mp_get_bit.c bn_s_mp_invmod_fast.c bn_s_mp_invmod_slow.c bn_s_mp_karatsuba_mul.c bn_s_mp_karatsuba_sqr.c bn_s_mp_log.c bn_s_mp_log_2expt.c bn_s_mp_log_d.c bn_s_mp_montgomery_reduce_fast.c bn_s_mp_mul_digs.c bn_s_mp_mul_digs_fast.c bn_s_mp_mul_high_digs.c bn_s_mp_mul_high_digs_fast.c bn_s_mp_prime_is_divisible.c bn_s_mp_rand_jenkins.c bn_s_mp_rand_platform.c bn_s_mp_reverse.c bn_s_mp_sqr.c bn_s_mp_sqr_fast.c bn_s_mp_sub.c bn_s_mp_toom_mul.c bn_s_mp_toom_sqr.c ) set(HEADERS tommath.h tommath_class.h tommath_cutoffs.h tommath_private.h tommath_superclass.h ) |
Changes to libtommath/tommath.def.
| ︙ | ︙ | |||
29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
mp_div_3
mp_div_d
mp_dr_is_modulus
mp_dr_reduce
mp_dr_setup
mp_error_to_string
mp_exch
mp_expt_u32
mp_exptmod
mp_exteuclid
mp_fread
mp_from_sbin
mp_from_ubin
mp_fwrite
| > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
mp_div_3
mp_div_d
mp_dr_is_modulus
mp_dr_reduce
mp_dr_setup
mp_error_to_string
mp_exch
mp_expt_n
mp_expt_u32
mp_exptmod
mp_exteuclid
mp_fread
mp_from_sbin
mp_from_ubin
mp_fwrite
|
| ︙ | ︙ | |||
71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
mp_init_ull
mp_invmod
mp_is_square
mp_iseven
mp_isodd
mp_kronecker
mp_lcm
mp_log_u32
mp_lshd
mp_mod
mp_mod_2d
mp_mod_d
mp_montgomery_calc_normalization
mp_montgomery_reduce
| > | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
mp_init_ull
mp_invmod
mp_is_square
mp_iseven
mp_isodd
mp_kronecker
mp_lcm
mp_log_n
mp_log_u32
mp_lshd
mp_mod
mp_mod_2d
mp_mod_d
mp_montgomery_calc_normalization
mp_montgomery_reduce
|
| ︙ | ︙ | |||
107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
mp_reduce_2k
mp_reduce_2k_l
mp_reduce_2k_setup
mp_reduce_2k_setup_l
mp_reduce_is_2k
mp_reduce_is_2k_l
mp_reduce_setup
mp_root_u32
mp_rshd
mp_sbin_size
mp_set
mp_set_double
mp_set_i32
mp_set_i64
| > | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
mp_reduce_2k
mp_reduce_2k_l
mp_reduce_2k_setup
mp_reduce_2k_setup_l
mp_reduce_is_2k
mp_reduce_is_2k_l
mp_reduce_setup
mp_root_n
mp_root_u32
mp_rshd
mp_sbin_size
mp_set
mp_set_double
mp_set_i32
mp_set_i64
|
| ︙ | ︙ | |||
139 140 141 142 143 144 145 |
mp_to_radix
mp_to_sbin
mp_to_ubin
mp_ubin_size
mp_unpack
mp_xor
mp_zero
| | | | > | > | | | < | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
mp_to_radix
mp_to_sbin
mp_to_ubin
mp_ubin_size
mp_unpack
mp_xor
mp_zero
s_mp_add
s_mp_balance_mul
s_mp_karatsuba_mul
s_mp_karatsuba_sqr
s_mp_mul_digs
s_mp_mul_digs_fast
s_mp_reverse
s_mp_sqr
s_mp_sqr_fast
s_mp_sub
s_mp_toom_mul
s_mp_toom_sqr
|
Changes to libtommath/tommath.h.
| ︙ | ︙ | |||
230 231 232 233 234 235 236 |
# else
# define MP_WUR
# endif
#endif
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405)
# define MP_DEPRECATED(x) __attribute__((deprecated("replaced by " #x)))
| < < < < < < < < > | < < | | 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
# else
# define MP_WUR
# endif
#endif
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405)
# define MP_DEPRECATED(x) __attribute__((deprecated("replaced by " #x)))
# define PRIVATE_MP_DEPRECATED_PRAGMA(s) _Pragma(#s)
# define MP_DEPRECATED_PRAGMA(s) PRIVATE_MP_DEPRECATED_PRAGMA(GCC warning s)
#elif defined(_MSC_VER) && _MSC_VER >= 1500
# define MP_DEPRECATED(x) __declspec(deprecated("replaced by " #x))
# define MP_DEPRECATED_PRAGMA(s) __pragma(message(s))
#else
# define MP_DEPRECATED(s)
# define MP_DEPRECATED_PRAGMA(s)
#endif
#define DIGIT_BIT (MP_DEPRECATED_PRAGMA("DIGIT_BIT macro is deprecated, MP_DIGIT_BIT instead") MP_DIGIT_BIT)
#define USED(m) (MP_DEPRECATED_PRAGMA("USED macro is deprecated, use z->used instead") (m)->used)
#define DIGIT(m, k) (MP_DEPRECATED_PRAGMA("DIGIT macro is deprecated, use z->dp instead") (m)->dp[(k)])
#define SIGN(m) (MP_DEPRECATED_PRAGMA("SIGN macro is deprecated, use z->sign instead") (m)->sign)
|
| ︙ | ︙ | |||
334 335 336 337 338 339 340 | void mp_set_u64(mp_int *a, uint64_t b); mp_err mp_init_u64(mp_int *a, uint64_t b) MP_WUR; /* get magnitude */ uint32_t mp_get_mag_u32(const mp_int *a) MP_WUR; uint64_t mp_get_mag_u64(const mp_int *a) MP_WUR; unsigned long mp_get_mag_ul(const mp_int *a) MP_WUR; | | | | | | | | | | 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
void mp_set_u64(mp_int *a, uint64_t b);
mp_err mp_init_u64(mp_int *a, uint64_t b) MP_WUR;
/* get magnitude */
uint32_t mp_get_mag_u32(const mp_int *a) MP_WUR;
uint64_t mp_get_mag_u64(const mp_int *a) MP_WUR;
unsigned long mp_get_mag_ul(const mp_int *a) MP_WUR;
MP_DEPRECATED(mp_get_mag_u64) unsigned long long mp_get_mag_ull(const mp_int *a) MP_WUR;
/* get integer, set integer (long) */
long mp_get_l(const mp_int *a) MP_WUR;
void mp_set_l(mp_int *a, long b);
mp_err mp_init_l(mp_int *a, long b) MP_WUR;
/* get integer, set integer (unsigned long) */
#define mp_get_ul(a) ((unsigned long)mp_get_l(a))
void mp_set_ul(mp_int *a, unsigned long b);
mp_err mp_init_ul(mp_int *a, unsigned long b) MP_WUR;
/* get integer, set integer (long long) */
MP_DEPRECATED(mp_get_i64) long long mp_get_ll(const mp_int *a) MP_WUR;
MP_DEPRECATED(mp_set_i64) void mp_set_ll(mp_int *a, long long b);
MP_DEPRECATED(mp_init_i64) mp_err mp_init_ll(mp_int *a, long long b) MP_WUR;
/* get integer, set integer (unsigned long long) */
#define mp_get_ull(a) (MP_DEPRECATED_PRAGMA("mp_get_ull() has been deprecated, use mp_get_u64()") ((unsigned long long)mp_get_ll(a)))
MP_DEPRECATED(mp_set_u64) void mp_set_ull(mp_int *a, unsigned long long b);
MP_DEPRECATED(mp_init_u64) mp_err mp_init_ull(mp_int *a, unsigned long long b) MP_WUR;
/* set to single unsigned digit, up to MP_DIGIT_MAX */
void mp_set(mp_int *a, mp_digit b);
mp_err mp_init_set(mp_int *a, mp_digit b) MP_WUR;
/* get integer, set integer and init with integer (deprecated) */
MP_DEPRECATED(mp_get_mag_u32/mp_get_u32) unsigned long mp_get_int(const mp_int *a) MP_WUR;
MP_DEPRECATED(mp_get_mag_ul/mp_get_ul) unsigned long mp_get_long(const mp_int *a) MP_WUR;
MP_DEPRECATED(mp_get_mag_u64/mp_get_u64) unsigned long long mp_get_long_long(const mp_int *a) MP_WUR;
MP_DEPRECATED(mp_set_ul) mp_err mp_set_int(mp_int *a, unsigned long b);
MP_DEPRECATED(mp_set_ul) mp_err mp_set_long(mp_int *a, unsigned long b);
MP_DEPRECATED(mp_set_ull) mp_err mp_set_long_long(mp_int *a, unsigned long long b);
MP_DEPRECATED(mp_init_ul) mp_err mp_init_set_int(mp_int *a, unsigned long b) MP_WUR;
/* copy, b = a */
mp_err mp_copy(const mp_int *a, mp_int *b) MP_WUR;
|
| ︙ | ︙ | |||
412 413 414 415 416 417 418 | /* c = a / 2**b, implemented as c = a >> b */ mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d) MP_WUR; /* b = a/2 */ mp_err mp_div_2(const mp_int *a, mp_int *b) MP_WUR; /* a/3 => 3c + d == a */ | | | 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 | /* c = a / 2**b, implemented as c = a >> b */ mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d) MP_WUR; /* b = a/2 */ mp_err mp_div_2(const mp_int *a, mp_int *b) MP_WUR; /* a/3 => 3c + d == a */ MP_DEPRECATED(mp_div_d) mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) MP_WUR; /* c = a * 2**b, implemented as c = a << b */ mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c) MP_WUR; /* b = a*2 */ mp_err mp_mul_2(const mp_int *a, mp_int *b) MP_WUR; |
| ︙ | ︙ | |||
559 560 561 562 563 564 565 566 567 568 569 | /* produces value such that U1*a + U2*b = U3 */ mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) MP_WUR; /* c = [a, b] or (a*b)/(a, b) */ mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* finds one of the b'th root of a, such that |c|**b <= |a| * * returns error if a < 0 and b is even */ | > > > > > > > > > > > | | | | 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 | /* produces value such that U1*a + U2*b = U3 */ mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) MP_WUR; /* c = [a, b] or (a*b)/(a, b) */ mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* Integer logarithm to integer base */ mp_err mp_log_n(const mp_int *a, int base, int *c) MP_WUR; MP_DEPRECATED(mp_log_n) mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c) MP_WUR; /* c = a**b */ mp_err mp_expt_n(const mp_int *a, int b, mp_int *c) MP_WUR; MP_DEPRECATED(mp_expt_n) mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c) MP_WUR; MP_DEPRECATED(mp_expt_n) mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; MP_DEPRECATED(mp_expt_n) mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) MP_WUR; /* finds one of the b'th root of a, such that |c|**b <= |a| * * returns error if a < 0 and b is even */ mp_err mp_root_n(const mp_int *a, int b, mp_int *c) MP_WUR; MP_DEPRECATED(mp_root_n) mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c) MP_WUR; MP_DEPRECATED(mp_root_n) mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; MP_DEPRECATED(mp_root_n) mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) MP_WUR; /* special sqrt algo */ mp_err mp_sqrt(const mp_int *arg, mp_int *ret) MP_WUR; /* special sqrt (mod prime) */ mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret) MP_WUR; |
| ︙ | ︙ | |||
725 726 727 728 729 730 731 |
* so it can be NULL
*
*/
MP_DEPRECATED(mp_prime_rand) mp_err mp_prime_random_ex(mp_int *a, int t, int size, int flags,
private_mp_prime_callback cb, void *dat) MP_WUR;
mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) MP_WUR;
| < < < < < < < < | 727 728 729 730 731 732 733 734 735 736 737 738 739 740 |
* so it can be NULL
*
*/
MP_DEPRECATED(mp_prime_rand) mp_err mp_prime_random_ex(mp_int *a, int t, int size, int flags,
private_mp_prime_callback cb, void *dat) MP_WUR;
mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) MP_WUR;
/* ---> radix conversion <--- */
int mp_count_bits(const mp_int *a) MP_WUR;
MP_DEPRECATED(mp_ubin_size) int mp_unsigned_bin_size(const mp_int *a) MP_WUR;
MP_DEPRECATED(mp_from_ubin) mp_err mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c) MP_WUR;
MP_DEPRECATED(mp_to_ubin) mp_err mp_to_unsigned_bin(const mp_int *a, unsigned char *b) MP_WUR;
|
| ︙ | ︙ |
Changes to libtommath/tommath_class.h.
| ︙ | ︙ | |||
29 30 31 32 33 34 35 | # define BN_MP_COMPLEMENT_C # define BN_MP_COPY_C # define BN_MP_COUNT_BITS_C # define BN_MP_DECR_C # define BN_MP_DIV_C # define BN_MP_DIV_2_C # define BN_MP_DIV_2D_C | < | < < < < | | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | # define BN_MP_COMPLEMENT_C # define BN_MP_COPY_C # define BN_MP_COUNT_BITS_C # define BN_MP_DECR_C # define BN_MP_DIV_C # define BN_MP_DIV_2_C # define BN_MP_DIV_2D_C # define BN_MP_DIV_D_C # define BN_MP_DR_IS_MODULUS_C # define BN_MP_DR_REDUCE_C # define BN_MP_DR_SETUP_C # define BN_MP_ERROR_TO_STRING_C # define BN_MP_EXCH_C # define BN_MP_EXPT_N_C # define BN_MP_EXPTMOD_C # define BN_MP_EXTEUCLID_C # define BN_MP_FREAD_C # define BN_MP_FROM_SBIN_C # define BN_MP_FROM_UBIN_C # define BN_MP_FWRITE_C # define BN_MP_GCD_C # define BN_MP_GET_DOUBLE_C # define BN_MP_GET_I32_C # define BN_MP_GET_I64_C # define BN_MP_GET_L_C # define BN_MP_GET_MAG_U32_C # define BN_MP_GET_MAG_U64_C # define BN_MP_GET_MAG_UL_C # define BN_MP_GROW_C # define BN_MP_INCR_C # define BN_MP_INIT_C # define BN_MP_INIT_COPY_C # define BN_MP_INIT_I32_C # define BN_MP_INIT_I64_C # define BN_MP_INIT_L_C # define BN_MP_INIT_MULTI_C # define BN_MP_INIT_SET_C # define BN_MP_INIT_SIZE_C # define BN_MP_INIT_U32_C # define BN_MP_INIT_U64_C # define BN_MP_INIT_UL_C # define BN_MP_INVMOD_C # define BN_MP_IS_SQUARE_C # define BN_MP_ISEVEN_C # define BN_MP_ISODD_C # define BN_MP_KRONECKER_C # define BN_MP_LCM_C # define BN_MP_LOG_N_C # define BN_MP_LSHD_C # define BN_MP_MOD_C # define BN_MP_MOD_2D_C # define BN_MP_MOD_D_C # define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C # define BN_MP_MONTGOMERY_REDUCE_C # define BN_MP_MONTGOMERY_SETUP_C |
| ︙ | ︙ | |||
111 112 113 114 115 116 117 | # define BN_MP_REDUCE_2K_C # define BN_MP_REDUCE_2K_L_C # define BN_MP_REDUCE_2K_SETUP_C # define BN_MP_REDUCE_2K_SETUP_L_C # define BN_MP_REDUCE_IS_2K_C # define BN_MP_REDUCE_IS_2K_L_C # define BN_MP_REDUCE_SETUP_C | | < < > > > > | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | # define BN_MP_REDUCE_2K_C # define BN_MP_REDUCE_2K_L_C # define BN_MP_REDUCE_2K_SETUP_C # define BN_MP_REDUCE_2K_SETUP_L_C # define BN_MP_REDUCE_IS_2K_C # define BN_MP_REDUCE_IS_2K_L_C # define BN_MP_REDUCE_SETUP_C # define BN_MP_ROOT_N_C # define BN_MP_RSHD_C # define BN_MP_SBIN_SIZE_C # define BN_MP_SET_C # define BN_MP_SET_DOUBLE_C # define BN_MP_SET_I32_C # define BN_MP_SET_I64_C # define BN_MP_SET_L_C # define BN_MP_SET_U32_C # define BN_MP_SET_U64_C # define BN_MP_SET_UL_C # define BN_MP_SHRINK_C # define BN_MP_SIGNED_RSH_C # define BN_MP_SQR_C # define BN_MP_SQRMOD_C # define BN_MP_SQRT_C # define BN_MP_SQRTMOD_PRIME_C # define BN_MP_SUB_C # define BN_MP_SUB_D_C # define BN_MP_SUBMOD_C # define BN_MP_TO_RADIX_C # define BN_MP_TO_SBIN_C # define BN_MP_TO_UBIN_C # define BN_MP_UBIN_SIZE_C # define BN_MP_UNPACK_C # define BN_MP_XOR_C # define BN_MP_ZERO_C # define BN_PRIME_TAB_C # define BN_S_MP_ADD_C # define BN_S_MP_BALANCE_MUL_C # define BN_S_MP_DIV_3_C # define BN_S_MP_EXPTMOD_C # define BN_S_MP_EXPTMOD_FAST_C # define BN_S_MP_GET_BIT_C # define BN_S_MP_INVMOD_FAST_C # define BN_S_MP_INVMOD_SLOW_C # define BN_S_MP_KARATSUBA_MUL_C # define BN_S_MP_KARATSUBA_SQR_C # define BN_S_MP_LOG_C # define BN_S_MP_LOG_2EXPT_C # define BN_S_MP_LOG_D_C # define BN_S_MP_MONTGOMERY_REDUCE_FAST_C # define BN_S_MP_MUL_DIGS_C # define BN_S_MP_MUL_DIGS_FAST_C # define BN_S_MP_MUL_HIGH_DIGS_C # define BN_S_MP_MUL_HIGH_DIGS_FAST_C # define BN_S_MP_PRIME_IS_DIVISIBLE_C # define BN_S_MP_RAND_JENKINS_C |
| ︙ | ︙ | |||
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | # define BN_FAST_MP_MONTGOMERY_REDUCE_C # define BN_FAST_S_MP_MUL_DIGS_C # define BN_FAST_S_MP_MUL_HIGH_DIGS_C # define BN_FAST_S_MP_SQR_C # define BN_MP_AND_C # define BN_MP_BALANCE_MUL_C # define BN_MP_CMP_D_C # define BN_MP_EXPORT_C # define BN_MP_EXPTMOD_FAST_C # define BN_MP_EXPT_D_C # define BN_MP_EXPT_D_EX_C # define BN_MP_EXPT_U32_C # define BN_MP_FROM_SBIN_C # define BN_MP_FROM_UBIN_C # define BN_MP_GET_BIT_C # define BN_MP_GET_INT_C # define BN_MP_GET_LONG_C # define BN_MP_GET_LONG_LONG_C # define BN_MP_GET_MAG_U32_C # define BN_MP_GET_MAG_ULL_C # define BN_MP_GET_MAG_UL_C # define BN_MP_IMPORT_C # define BN_MP_INIT_SET_INT_C # define BN_MP_INIT_U32_C # define BN_MP_INVMOD_SLOW_C # define BN_MP_JACOBI_C # define BN_MP_KARATSUBA_MUL_C # define BN_MP_KARATSUBA_SQR_C # define BN_MP_KRONECKER_C # define BN_MP_N_ROOT_C # define BN_MP_N_ROOT_EX_C # define BN_MP_OR_C # define BN_MP_PACK_C # define BN_MP_PRIME_IS_DIVISIBLE_C # define BN_MP_PRIME_RANDOM_EX_C # define BN_MP_RAND_DIGIT_C # define BN_MP_READ_SIGNED_BIN_C # define BN_MP_READ_UNSIGNED_BIN_C # define BN_MP_ROOT_U32_C # define BN_MP_SBIN_SIZE_C # define BN_MP_SET_INT_C # define BN_MP_SET_LONG_C # define BN_MP_SET_LONG_LONG_C # define BN_MP_SET_U32_C # define BN_MP_SET_U64_C # define BN_MP_SIGNED_BIN_SIZE_C # define BN_MP_SIGNED_RSH_C # define BN_MP_TC_AND_C # define BN_MP_TC_DIV_2D_C # define BN_MP_TC_OR_C # define BN_MP_TC_XOR_C # define BN_MP_TOOM_MUL_C | > > > > > > > > > > > | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | # define BN_FAST_MP_MONTGOMERY_REDUCE_C # define BN_FAST_S_MP_MUL_DIGS_C # define BN_FAST_S_MP_MUL_HIGH_DIGS_C # define BN_FAST_S_MP_SQR_C # define BN_MP_AND_C # define BN_MP_BALANCE_MUL_C # define BN_MP_CMP_D_C # define BN_MP_DIV_3_C # define BN_MP_EXPORT_C # define BN_MP_EXPTMOD_FAST_C # define BN_MP_EXPT_D_C # define BN_MP_EXPT_D_EX_C # define BN_MP_EXPT_N_C # define BN_MP_EXPT_U32_C # define BN_MP_FROM_SBIN_C # define BN_MP_FROM_UBIN_C # define BN_MP_GET_BIT_C # define BN_MP_GET_INT_C # define BN_MP_GET_LL_C # define BN_MP_GET_LONG_C # define BN_MP_GET_LONG_LONG_C # define BN_MP_GET_MAG_U32_C # define BN_MP_GET_MAG_U64_C # define BN_MP_GET_MAG_ULL_C # define BN_MP_GET_MAG_UL_C # define BN_MP_IMPORT_C # define BN_MP_INIT_LL_C # define BN_MP_INIT_SET_INT_C # define BN_MP_INIT_U32_C # define BN_MP_INIT_ULL_C # define BN_MP_INVMOD_SLOW_C # define BN_MP_JACOBI_C # define BN_MP_KARATSUBA_MUL_C # define BN_MP_KARATSUBA_SQR_C # define BN_MP_KRONECKER_C # define BN_MP_LOG_N_C # define BN_MP_LOG_U32_C # define BN_MP_N_ROOT_C # define BN_MP_N_ROOT_EX_C # define BN_MP_OR_C # define BN_MP_PACK_C # define BN_MP_PRIME_IS_DIVISIBLE_C # define BN_MP_PRIME_RANDOM_EX_C # define BN_MP_RAND_DIGIT_C # define BN_MP_READ_SIGNED_BIN_C # define BN_MP_READ_UNSIGNED_BIN_C # define BN_MP_ROOT_N_C # define BN_MP_ROOT_U32_C # define BN_MP_SBIN_SIZE_C # define BN_MP_SET_INT_C # define BN_MP_SET_LL_C # define BN_MP_SET_LONG_C # define BN_MP_SET_LONG_LONG_C # define BN_MP_SET_U32_C # define BN_MP_SET_U64_C # define BN_MP_SET_ULL_C # define BN_MP_SIGNED_BIN_SIZE_C # define BN_MP_SIGNED_RSH_C # define BN_MP_TC_AND_C # define BN_MP_TC_DIV_2D_C # define BN_MP_TC_OR_C # define BN_MP_TC_XOR_C # define BN_MP_TOOM_MUL_C |
| ︙ | ︙ | |||
238 239 240 241 242 243 244 245 246 247 248 249 250 251 | # define BN_MP_TO_UNSIGNED_BIN_C # define BN_MP_TO_UNSIGNED_BIN_N_C # define BN_MP_UBIN_SIZE_C # define BN_MP_UNPACK_C # define BN_MP_UNSIGNED_BIN_SIZE_C # define BN_MP_XOR_C # define BN_S_MP_BALANCE_MUL_C # define BN_S_MP_EXPTMOD_FAST_C # define BN_S_MP_GET_BIT_C # define BN_S_MP_INVMOD_FAST_C # define BN_S_MP_INVMOD_SLOW_C # define BN_S_MP_KARATSUBA_MUL_C # define BN_S_MP_KARATSUBA_SQR_C # define BN_S_MP_MONTGOMERY_REDUCE_FAST_C | > | 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | # define BN_MP_TO_UNSIGNED_BIN_C # define BN_MP_TO_UNSIGNED_BIN_N_C # define BN_MP_UBIN_SIZE_C # define BN_MP_UNPACK_C # define BN_MP_UNSIGNED_BIN_SIZE_C # define BN_MP_XOR_C # define BN_S_MP_BALANCE_MUL_C # define BN_S_MP_DIV_3_C # define BN_S_MP_EXPTMOD_FAST_C # define BN_S_MP_GET_BIT_C # define BN_S_MP_INVMOD_FAST_C # define BN_S_MP_INVMOD_SLOW_C # define BN_S_MP_KARATSUBA_MUL_C # define BN_S_MP_KARATSUBA_SQR_C # define BN_S_MP_MONTGOMERY_REDUCE_FAST_C |
| ︙ | ︙ | |||
365 366 367 368 369 370 371 | # define BN_MP_CLAMP_C # define BN_MP_COPY_C # define BN_MP_MOD_2D_C # define BN_MP_RSHD_C # define BN_MP_ZERO_C #endif | < < < < < < < | | | | 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 | # define BN_MP_CLAMP_C # define BN_MP_COPY_C # define BN_MP_MOD_2D_C # define BN_MP_RSHD_C # define BN_MP_ZERO_C #endif #if defined(BN_MP_DIV_D_C) # define BN_MP_CLAMP_C # define BN_MP_CLEAR_C # define BN_MP_COPY_C # define BN_MP_DIV_2D_C # define BN_MP_EXCH_C # define BN_MP_INIT_SIZE_C # define BN_S_MP_DIV_3_C #endif #if defined(BN_MP_DR_IS_MODULUS_C) #endif #if defined(BN_MP_DR_REDUCE_C) # define BN_MP_CLAMP_C |
| ︙ | ︙ | |||
401 402 403 404 405 406 407 | #if defined(BN_MP_ERROR_TO_STRING_C) #endif #if defined(BN_MP_EXCH_C) #endif | | | 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 | #if defined(BN_MP_ERROR_TO_STRING_C) #endif #if defined(BN_MP_EXCH_C) #endif #if defined(BN_MP_EXPT_N_C) # define BN_MP_CLEAR_C # define BN_MP_INIT_COPY_C # define BN_MP_MUL_C # define BN_MP_SET_C # define BN_MP_SQR_C #endif |
| ︙ | ︙ | |||
482 483 484 485 486 487 488 | # define BN_MP_GET_MAG_U64_C #endif #if defined(BN_MP_GET_L_C) # define BN_MP_GET_MAG_UL_C #endif | < < < < < < < | 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 | # define BN_MP_GET_MAG_U64_C #endif #if defined(BN_MP_GET_L_C) # define BN_MP_GET_MAG_UL_C #endif #if defined(BN_MP_GET_MAG_U32_C) #endif #if defined(BN_MP_GET_MAG_U64_C) #endif #if defined(BN_MP_GET_MAG_UL_C) #endif #if defined(BN_MP_GROW_C) #endif #if defined(BN_MP_INCR_C) # define BN_MP_ADD_D_C # define BN_MP_DECR_C # define BN_MP_SET_C |
| ︙ | ︙ | |||
531 532 533 534 535 536 537 | #endif #if defined(BN_MP_INIT_L_C) # define BN_MP_INIT_C # define BN_MP_SET_L_C #endif | < < < < < | 526 527 528 529 530 531 532 533 534 535 536 537 538 539 | #endif #if defined(BN_MP_INIT_L_C) # define BN_MP_INIT_C # define BN_MP_SET_L_C #endif #if defined(BN_MP_INIT_MULTI_C) # define BN_MP_CLEAR_C # define BN_MP_INIT_C #endif #if defined(BN_MP_INIT_SET_C) # define BN_MP_INIT_C |
| ︙ | ︙ | |||
564 565 566 567 568 569 570 | #endif #if defined(BN_MP_INIT_UL_C) # define BN_MP_INIT_C # define BN_MP_SET_UL_C #endif | < < < < < | 554 555 556 557 558 559 560 561 562 563 564 565 566 567 | #endif #if defined(BN_MP_INIT_UL_C) # define BN_MP_INIT_C # define BN_MP_SET_UL_C #endif #if defined(BN_MP_INVMOD_C) # define BN_MP_CMP_D_C # define BN_S_MP_INVMOD_FAST_C # define BN_S_MP_INVMOD_SLOW_C #endif #if defined(BN_MP_IS_SQUARE_C) |
| ︙ | ︙ | |||
612 613 614 615 616 617 618 | # define BN_MP_CMP_MAG_C # define BN_MP_DIV_C # define BN_MP_GCD_C # define BN_MP_INIT_MULTI_C # define BN_MP_MUL_C #endif | | < | < | < | < < < < < | 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 | # define BN_MP_CMP_MAG_C # define BN_MP_DIV_C # define BN_MP_GCD_C # define BN_MP_INIT_MULTI_C # define BN_MP_MUL_C #endif #if defined(BN_MP_LOG_N_C) # define BN_S_MP_LOG_2EXPT_C # define BN_S_MP_LOG_C # define BN_S_MP_LOG_D_C #endif #if defined(BN_MP_LSHD_C) # define BN_MP_GROW_C #endif #if defined(BN_MP_MOD_C) |
| ︙ | ︙ | |||
925 926 927 928 929 930 931 | #endif #if defined(BN_MP_REDUCE_SETUP_C) # define BN_MP_2EXPT_C # define BN_MP_DIV_C #endif | | | | 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 | #endif #if defined(BN_MP_REDUCE_SETUP_C) # define BN_MP_2EXPT_C # define BN_MP_DIV_C #endif #if defined(BN_MP_ROOT_N_C) # define BN_MP_2EXPT_C # define BN_MP_ADD_D_C # define BN_MP_CLEAR_MULTI_C # define BN_MP_CMP_C # define BN_MP_COPY_C # define BN_MP_COUNT_BITS_C # define BN_MP_DIV_C # define BN_MP_EXCH_C # define BN_MP_EXPT_N_C # define BN_MP_INIT_MULTI_C # define BN_MP_MUL_C # define BN_MP_MUL_D_C # define BN_MP_SET_C # define BN_MP_SUB_C # define BN_MP_SUB_D_C #endif |
| ︙ | ︙ | |||
972 973 974 975 976 977 978 | # define BN_MP_SET_U64_C #endif #if defined(BN_MP_SET_L_C) # define BN_MP_SET_UL_C #endif | < < < < < < < | 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 | # define BN_MP_SET_U64_C #endif #if defined(BN_MP_SET_L_C) # define BN_MP_SET_UL_C #endif #if defined(BN_MP_SET_U32_C) #endif #if defined(BN_MP_SET_U64_C) #endif #if defined(BN_MP_SET_UL_C) #endif #if defined(BN_MP_SHRINK_C) #endif #if defined(BN_MP_SIGNED_RSH_C) # define BN_MP_ADD_D_C # define BN_MP_DIV_2D_C # define BN_MP_SUB_D_C |
| ︙ | ︙ | |||
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 | # define BN_MP_CLEAR_MULTI_C # define BN_MP_EXCH_C # define BN_MP_INIT_MULTI_C # define BN_MP_INIT_SIZE_C # define BN_MP_LSHD_C # define BN_MP_MUL_C #endif #if defined(BN_S_MP_EXPTMOD_C) # define BN_MP_CLEAR_C # define BN_MP_COPY_C # define BN_MP_COUNT_BITS_C # define BN_MP_EXCH_C # define BN_MP_INIT_C | > > > > > > > | 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 | # define BN_MP_CLEAR_MULTI_C # define BN_MP_EXCH_C # define BN_MP_INIT_MULTI_C # define BN_MP_INIT_SIZE_C # define BN_MP_LSHD_C # define BN_MP_MUL_C #endif #if defined(BN_S_MP_DIV_3_C) # define BN_MP_CLAMP_C # define BN_MP_CLEAR_C # define BN_MP_EXCH_C # define BN_MP_INIT_SIZE_C #endif #if defined(BN_S_MP_EXPTMOD_C) # define BN_MP_CLEAR_C # define BN_MP_COPY_C # define BN_MP_COUNT_BITS_C # define BN_MP_EXCH_C # define BN_MP_INIT_C |
| ︙ | ︙ | |||
1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 | # define BN_MP_CLEAR_C # define BN_MP_INIT_SIZE_C # define BN_MP_LSHD_C # define BN_MP_SQR_C # define BN_S_MP_ADD_C # define BN_S_MP_SUB_C #endif #if defined(BN_S_MP_MONTGOMERY_REDUCE_FAST_C) # define BN_MP_CLAMP_C # define BN_MP_CMP_MAG_C # define BN_MP_GROW_C # define BN_S_MP_SUB_C #endif | > > > > > > > > > > > > > > > > > > > > | 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 | # define BN_MP_CLEAR_C # define BN_MP_INIT_SIZE_C # define BN_MP_LSHD_C # define BN_MP_SQR_C # define BN_S_MP_ADD_C # define BN_S_MP_SUB_C #endif #if defined(BN_S_MP_LOG_C) # define BN_MP_CLEAR_MULTI_C # define BN_MP_CMP_C # define BN_MP_CMP_D_C # define BN_MP_COPY_C # define BN_MP_EXCH_C # define BN_MP_EXPT_N_C # define BN_MP_INIT_MULTI_C # define BN_MP_MUL_C # define BN_MP_SET_C # define BN_MP_SQR_C #endif #if defined(BN_S_MP_LOG_2EXPT_C) # define BN_MP_COUNT_BITS_C #endif #if defined(BN_S_MP_LOG_D_C) #endif #if defined(BN_S_MP_MONTGOMERY_REDUCE_FAST_C) # define BN_MP_CLAMP_C # define BN_MP_CMP_MAG_C # define BN_MP_GROW_C # define BN_S_MP_SUB_C #endif |
| ︙ | ︙ | |||
1279 1280 1281 1282 1283 1284 1285 | #if defined(BN_S_MP_TOOM_MUL_C) # define BN_MP_ADD_C # define BN_MP_CLAMP_C # define BN_MP_CLEAR_C # define BN_MP_CLEAR_MULTI_C # define BN_MP_DIV_2_C | < > | 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 | #if defined(BN_S_MP_TOOM_MUL_C) # define BN_MP_ADD_C # define BN_MP_CLAMP_C # define BN_MP_CLEAR_C # define BN_MP_CLEAR_MULTI_C # define BN_MP_DIV_2_C # define BN_MP_INIT_MULTI_C # define BN_MP_INIT_SIZE_C # define BN_MP_LSHD_C # define BN_MP_MUL_2_C # define BN_MP_MUL_C # define BN_MP_SUB_C # define BN_S_MP_DIV_3_C #endif #if defined(BN_S_MP_TOOM_SQR_C) # define BN_MP_ADD_C # define BN_MP_CLAMP_C # define BN_MP_CLEAR_C # define BN_MP_DIV_2_C |
| ︙ | ︙ |
Changes to libtommath/tommath_private.h.
1 2 3 4 5 6 7 | /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #ifndef TOMMATH_PRIV_H_ #define TOMMATH_PRIV_H_ #include <stdint.h> | > | > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #ifndef TOMMATH_PRIV_H_ #define TOMMATH_PRIV_H_ #include <stdint.h> #ifndef TCL_WITH_EXTERNAL_TOMMATH # include "tclTomMath.h" #else # include "tommath.h" #endif #include "tommath_class.h" /* * Private symbols * --------------- * * On Unix symbols can be marked as hidden if libtommath is compiled |
| ︙ | ︙ | |||
155 156 157 158 159 160 161 162 163 164 165 166 167 168 | #undef mp_word typedef private_mp_word mp_word; #endif #define MP_MIN(x, y) (((x) < (y)) ? (x) : (y)) #define MP_MAX(x, y) (((x) > (y)) ? (x) : (y)) /* Static assertion */ #define MP_STATIC_ASSERT(msg, cond) typedef char mp_static_assert_##msg[(cond) ? 1 : -1]; /* ---> Basic Manipulations <--- */ #define MP_IS_ZERO(a) ((a)->used == 0) #define MP_IS_EVEN(a) (((a)->used == 0) || (((a)->dp[0] & 1u) == 0u)) #define MP_IS_ODD(a) (((a)->used > 0) && (((a)->dp[0] & 1u) == 1u)) | > > | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | #undef mp_word typedef private_mp_word mp_word; #endif #define MP_MIN(x, y) (((x) < (y)) ? (x) : (y)) #define MP_MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MP_IS_2EXPT(x) (((x) != 0u) && (((x) & ((x) - 1u)) == 0u)) /* Static assertion */ #define MP_STATIC_ASSERT(msg, cond) typedef char mp_static_assert_##msg[(cond) ? 1 : -1]; /* ---> Basic Manipulations <--- */ #define MP_IS_ZERO(a) ((a)->used == 0) #define MP_IS_EVEN(a) (((a)->used == 0) || (((a)->dp[0] & 1u) == 0u)) #define MP_IS_ODD(a) (((a)->used > 0) && (((a)->dp[0] & 1u) == 1u)) |
| ︙ | ︙ | |||
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | MP_STATIC_ASSERT(prec_geq_min_prec, MP_PREC >= MP_MIN_PREC) /* random number source */ extern MP_PRIVATE mp_err(*s_mp_rand_source)(void *out, size_t size); /* lowlevel functions, do not call! */ MP_PRIVATE mp_bool s_mp_get_bit(const mp_int *a, unsigned int b); MP_PRIVATE mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; MP_PRIVATE mp_err s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; MP_PRIVATE mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; MP_PRIVATE mp_err s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; MP_PRIVATE mp_err s_mp_sqr_fast(const mp_int *a, mp_int *b) MP_WUR; MP_PRIVATE mp_err s_mp_sqr(const mp_int *a, mp_int *b) MP_WUR; MP_PRIVATE mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_karatsuba_sqr(const mp_int *a, mp_int *b) MP_WUR; MP_PRIVATE mp_err s_mp_toom_sqr(const mp_int *a, mp_int *b) MP_WUR; MP_PRIVATE mp_err s_mp_invmod_fast(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_montgomery_reduce_fast(mp_int *x, const mp_int *n, mp_digit rho) MP_WUR; MP_PRIVATE mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR; MP_PRIVATE mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR; MP_PRIVATE mp_err s_mp_rand_platform(void *p, size_t n) MP_WUR; MP_PRIVATE mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat); MP_PRIVATE void s_mp_reverse(unsigned char *s, size_t len); MP_PRIVATE mp_err s_mp_prime_is_divisible(const mp_int *a, mp_bool *result); /* TODO: jenkins prng is not thread safe as of now */ MP_PRIVATE mp_err s_mp_rand_jenkins(void *p, size_t n) MP_WUR; | > > > > | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | MP_STATIC_ASSERT(prec_geq_min_prec, MP_PREC >= MP_MIN_PREC) /* random number source */ extern MP_PRIVATE mp_err(*s_mp_rand_source)(void *out, size_t size); /* lowlevel functions, do not call! */ MP_PRIVATE mp_bool s_mp_get_bit(const mp_int *a, unsigned int b); MP_PRIVATE int s_mp_log_2expt(const mp_int *a, mp_digit base) MP_WUR; MP_PRIVATE int s_mp_log_d(mp_digit base, mp_digit n) MP_WUR; MP_PRIVATE mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) MP_WUR; MP_PRIVATE mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; MP_PRIVATE mp_err s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; MP_PRIVATE mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; MP_PRIVATE mp_err s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; MP_PRIVATE mp_err s_mp_sqr_fast(const mp_int *a, mp_int *b) MP_WUR; MP_PRIVATE mp_err s_mp_sqr(const mp_int *a, mp_int *b) MP_WUR; MP_PRIVATE mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_karatsuba_sqr(const mp_int *a, mp_int *b) MP_WUR; MP_PRIVATE mp_err s_mp_toom_sqr(const mp_int *a, mp_int *b) MP_WUR; MP_PRIVATE mp_err s_mp_invmod_fast(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_montgomery_reduce_fast(mp_int *x, const mp_int *n, mp_digit rho) MP_WUR; MP_PRIVATE mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR; MP_PRIVATE mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR; MP_PRIVATE mp_err s_mp_log(const mp_int *a, mp_digit base, int *c) MP_WUR; MP_PRIVATE mp_err s_mp_rand_platform(void *p, size_t n) MP_WUR; MP_PRIVATE mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat); MP_PRIVATE void s_mp_reverse(unsigned char *s, size_t len); MP_PRIVATE mp_err s_mp_prime_is_divisible(const mp_int *a, mp_bool *result); /* TODO: jenkins prng is not thread safe as of now */ MP_PRIVATE mp_err s_mp_rand_jenkins(void *p, size_t n) MP_WUR; |
| ︙ | ︙ |
Changes to libtommath/win32/libtommath.dll.
cannot compute difference between binary files
Changes to libtommath/win32/tommath.lib.
cannot compute difference between binary files
Changes to libtommath/win64-arm/libtommath.dll.
cannot compute difference between binary files
Changes to libtommath/win64-arm/tommath.lib.
cannot compute difference between binary files
Changes to libtommath/win64/libtommath.dll.
cannot compute difference between binary files
Changes to libtommath/win64/tommath.lib.
cannot compute difference between binary files
Changes to macosx/Tcl.xcodeproj/project.pbxproj.
| ︙ | ︙ | |||
106 107 108 109 110 111 112 |
F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */; };
F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_cnt_lsb.c */; };
F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_copy.c */; };
F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */; };
F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; };
F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; };
F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; };
| | | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */; };
F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_cnt_lsb.c */; };
F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_copy.c */; };
F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */; };
F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; };
F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; };
F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; };
F96D48F708F272C3004A47F5 /* bn_s_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_s_mp_div_3.c */; };
F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */; };
F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427E08F272B3004A47F5 /* bn_mp_exch.c */; };
F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428708F272B3004A47F5 /* bn_mp_grow.c */; };
F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428808F272B3004A47F5 /* bn_mp_init.c */; };
F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */; };
F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */; };
F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */; };
|
| ︙ | ︙ | |||
159 160 161 162 163 164 165 |
F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446808F272B9004A47F5 /* tclUnixTest.c */; };
F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446908F272B9004A47F5 /* tclUnixThrd.c */; };
F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446B08F272B9004A47F5 /* tclUnixTime.c */; };
F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */; };
F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; };
F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; };
F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; };
| | | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446808F272B9004A47F5 /* tclUnixTest.c */; };
F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446908F272B9004A47F5 /* tclUnixThrd.c */; };
F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446B08F272B9004A47F5 /* tclUnixTime.c */; };
F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */; };
F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; };
F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; };
F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; };
F9E61D2C090A48AC002B3151 /* bn_mp_expt_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_n.c */; };
F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */; };
F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A308F272B3004A47F5 /* bn_mp_or.c */; };
F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */; };
F9E61D31090A48F9002B3151 /* bn_mp_to_ubin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C608F272B3004A47F5 /* bn_mp_to_ubin.c */; };
F9E61D32090A48FA002B3151 /* bn_mp_ubin_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CC08F272B3004A47F5 /* bn_mp_ubin_size.c */; };
F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */ = {isa = PBXBuildFile; fileRef = F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */; };
F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */ = {isa = PBXBuildFile; fileRef = F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */; };
|
| ︙ | ︙ | |||
565 566 567 568 569 570 571 |
F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_d.c; sourceTree = "<group>"; };
F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_mag.c; sourceTree = "<group>"; };
F96D427408F272B3004A47F5 /* bn_mp_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_copy.c; sourceTree = "<group>"; };
F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_count_bits.c; sourceTree = "<group>"; };
F96D427608F272B3004A47F5 /* bn_mp_div.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div.c; sourceTree = "<group>"; };
F96D427708F272B3004A47F5 /* bn_mp_div_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2.c; sourceTree = "<group>"; };
F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2d.c; sourceTree = "<group>"; };
| | | | 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 |
F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_d.c; sourceTree = "<group>"; };
F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_mag.c; sourceTree = "<group>"; };
F96D427408F272B3004A47F5 /* bn_mp_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_copy.c; sourceTree = "<group>"; };
F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_count_bits.c; sourceTree = "<group>"; };
F96D427608F272B3004A47F5 /* bn_mp_div.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div.c; sourceTree = "<group>"; };
F96D427708F272B3004A47F5 /* bn_mp_div_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2.c; sourceTree = "<group>"; };
F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2d.c; sourceTree = "<group>"; };
F96D427908F272B3004A47F5 /* bn_s_mp_div_3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_div_3.c; sourceTree = "<group>"; };
F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_d.c; sourceTree = "<group>"; };
F96D427E08F272B3004A47F5 /* bn_mp_exch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exch.c; sourceTree = "<group>"; };
F96D427F08F272B3004A47F5 /* bn_mp_expt_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_n.c; sourceTree = "<group>"; };
F96D427F08F272B3004A47F5 /* bn_mp_expt_d_ex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_d_ex.c; sourceTree = "<group>"; };
F96D428708F272B3004A47F5 /* bn_mp_grow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_grow.c; sourceTree = "<group>"; };
F96D428808F272B3004A47F5 /* bn_mp_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init.c; sourceTree = "<group>"; };
F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_copy.c; sourceTree = "<group>"; };
F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_multi.c; sourceTree = "<group>"; };
F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_set.c; sourceTree = "<group>"; };
F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_size.c; sourceTree = "<group>"; };
|
| ︙ | ︙ | |||
1402 1403 1404 1405 1406 1407 1408 | F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */, F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */, F96D427408F272B3004A47F5 /* bn_mp_copy.c */, F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */, F96D427608F272B3004A47F5 /* bn_mp_div.c */, F96D427708F272B3004A47F5 /* bn_mp_div_2.c */, F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */, | | | | 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 | F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */, F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */, F96D427408F272B3004A47F5 /* bn_mp_copy.c */, F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */, F96D427608F272B3004A47F5 /* bn_mp_div.c */, F96D427708F272B3004A47F5 /* bn_mp_div_2.c */, F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */, F96D427908F272B3004A47F5 /* bn_s_mp_div_3.c */, F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */, F96D427E08F272B3004A47F5 /* bn_mp_exch.c */, F96D427F08F272B3004A47F5 /* bn_mp_expt_n.c */, F96D427F08F272B3004A47F5 /* bn_mp_expt_d_ex.c */, F96D428708F272B3004A47F5 /* bn_mp_grow.c */, F96D428808F272B3004A47F5 /* bn_mp_init.c */, F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */, F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */, F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */, F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */, |
| ︙ | ︙ | |||
2019 2020 2021 2022 2023 2024 2025 | F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */, F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */, F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */, F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */, F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */, F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */, F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */, | | | | 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 | F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */, F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */, F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */, F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */, F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */, F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */, F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */, F96D48F708F272C3004A47F5 /* bn_s_mp_div_3.c in Sources */, F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */, F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */, F9E61D2C090A48AC002B3151 /* bn_mp_expt_n.c in Sources */, F9E61D2C090A48AC002B3151 /* bn_mp_expt_d_ex.c in Sources */, F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */, F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */, F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */, F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */, F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */, F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */, |
| ︙ | ︙ |
Changes to tests-perf/clock.perf.tcl.
| ︙ | ︙ | |||
351 352 353 354 355 356 357 358 359 |
proc test-other {{reptime 1000}} {
_test_run $reptime {
# Bad zone
{catch {clock scan "1 day" -timezone BAD_ZONE -locale en}}
# Scan : julian day (overflow)
{catch {clock scan 5373485 -format %J}}
# Scan : test rotate of GC objects (format is dynamic, so tcl-obj removed with last reference)
| > > > | > | > > | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
proc test-other {{reptime 1000}} {
_test_run $reptime {
# Bad zone
{catch {clock scan "1 day" -timezone BAD_ZONE -locale en}}
# Scan : julian day (overflow)
{catch {clock scan 5373485 -format %J}}
setup {set _(org-reptime) $_(reptime); lset _(reptime) 1 50}
# Scan : test rotate of GC objects (format is dynamic, so tcl-obj removed with last reference)
setup {set i -1}
{clock scan "[incr i] - 25.11.2015" -format "$i - %d.%m.%Y" -base 0 -gmt 1}
# Scan : test reusability of GC objects (format is dynamic, so tcl-obj removed with last reference)
setup {incr i; set j $i}
{clock scan "[incr j -1] - 25.11.2015" -format "$j - %d.%m.%Y" -base 0 -gmt 1}
setup {set _(reptime) $_(org-reptime); set j $i}
{clock scan "[incr j -1] - 25.11.2015" -format "$j - %d.%m.%Y" -base 0 -gmt 1; if {!$j} {set j $i}}
}
}
proc test-ensemble-perf {{reptime 1000}} {
_test_run $reptime {
# Clock clicks (ensemble)
{clock clicks}
|
| ︙ | ︙ |
Added tests-perf/list.perf.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
#!/usr/bin/tclsh
# ------------------------------------------------------------------------
#
# list.perf.tcl --
#
# This file provides performance tests for comparison of tcl-speed
# of list facilities.
#
# ------------------------------------------------------------------------
#
# Copyright (c) 2024 Serg G. Brester (aka sebres)
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#
if {![namespace exists ::tclTestPerf]} {
source [file join [file dirname [info script]] test-performance.tcl]
}
namespace eval ::tclTestPerf-List {
namespace path {::tclTestPerf}
proc test-lsearch-regress {{reptime 1000}} {
_test_run -no-result $reptime {
# found-first immediately, list with 5000 strings with ca. 50 chars elements:
setup { set str [join [lrepeat 13 "XXX"] /]; set l [lrepeat 5000 $str]; llength $l }
{ lsearch $l $str }
{ lsearch -glob $l $str }
{ lsearch -exact $l $str }
{ lsearch -dictionary $l $str }
{ lsearch -exact -dictionary $l $str }
{ lsearch -nocase $l $str }
{ lsearch -nocase -glob $l $str }
{ lsearch -nocase -exact $l $str }
{ lsearch -nocase -dictionary $l $str }
{ lsearch -nocase -exact -dictionary $l $str }
}
}
proc test-lsearch-nf-regress {{reptime 1000}} {
_test_run -no-result $reptime {
# not-found, list with 5000 strings with ca. 50 chars elements:
setup { set str [join [lrepeat 13 "XXX"] /]; set sNF $str/NF; set l [lrepeat 5000 $str]; llength $l }
{ lsearch $l $sNF }
{ lsearch -glob $l $sNF }
{ lsearch -exact $l $sNF }
{ lsearch -dictionary $l $sNF }
{ lsearch -exact -dictionary $l $sNF }
{ lsearch -sorted $l $sNF }
{ lsearch -bisect $l $sNF }
{ lsearch -nocase $l $sNF }
{ lsearch -nocase -glob $l $sNF }
{ lsearch -nocase -exact $l $sNF }
{ lsearch -nocase -dictionary $l $sNF }
{ lsearch -nocase -exact -dictionary $l $sNF }
{ lsearch -nocase -sorted $l $sNF }
{ lsearch -nocase -bisect $l $sNF }
}
}
proc test-lsearch-nf-non-opti-fast {{reptime 1000}} {
_test_run -no-result $reptime {
# not-found, list with 5000 strings with ca. 50 chars elements:
setup { set str [join [lrepeat 13 "XXX"] /]; set sNF "$str/*"; set l [lrepeat 5000 $str]; llength $l }
{ lsearch -sorted -dictionary $l $sNF }
{ lsearch -bisect -dictionary $l $sNF }
{ lsearch -sorted -nocase -dictionary $l $sNF }
{ lsearch -bisect -nocase -dictionary $l $sNF }
}
}
proc test-lsearch-nf-non-opti-slow {{reptime 1000}} {
_test_run -no-result $reptime {
# not-found, list with 5000 strings with ca. 50 chars elements:
setup { set str [join [lrepeat 13 "XXX"] /]; set sNF "$str/*"; set l [lrepeat 5000 $str]; llength $l }
{ lsearch $l $sNF }
{ lsearch -glob $l $sNF }
{ lsearch -nocase $l $sNF }
{ lsearch -nocase -glob $l $sNF }
}
}
proc test {{reptime 1000}} {
test-lsearch-regress $reptime
test-lsearch-nf-regress $reptime
test-lsearch-nf-non-opti-fast $reptime
test-lsearch-nf-non-opti-slow $reptime
puts \n**OK**
}
}; # end of ::tclTestPerf-List
# ------------------------------------------------------------------------
# if calling direct:
if {[info exists ::argv0] && [file tail $::argv0] eq [file tail [info script]]} {
array set in {-time 500}
array set in $argv
::tclTestPerf-List::test $in(-time)
}
|
Changes to tests/binary.test.
| ︙ | ︙ | |||
3044 3045 3046 3047 3048 3049 3050 |
} -result "expected byte sequence but character 4 was '乎' (U+004E4E)"
test binary-80.3 {Tcl_GetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
testbytestring [testbytestring "\xC0\x80\xA0\xA0\xA0\xE4\xB9\x8E"]
} -result "expected byte sequence but character 4 was '乎' (U+004E4E)"
test binary-80.4 {Tcl_GetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
testbytestring [testbytestring "\xC0\x80\xA0\xA0\xA0\xF0\x9F\x98\x81"]
} -result "expected byte sequence but character 4 was '\U01F601' (U+01F601)"
| | > > | 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 |
} -result "expected byte sequence but character 4 was '乎' (U+004E4E)"
test binary-80.3 {Tcl_GetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
testbytestring [testbytestring "\xC0\x80\xA0\xA0\xA0\xE4\xB9\x8E"]
} -result "expected byte sequence but character 4 was '乎' (U+004E4E)"
test binary-80.4 {Tcl_GetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
testbytestring [testbytestring "\xC0\x80\xA0\xA0\xA0\xF0\x9F\x98\x81"]
} -result "expected byte sequence but character 4 was '\U01F601' (U+01F601)"
test binary-80.5 {Tcl_GetBytesFromObj} -constraints {
bigmem testbytestring pointerIs64bit deprecated
} -body {
testbytestring [string repeat A [expr 2**31]]
} -returnCodes 1 -result "byte sequence length exceeds INT_MAX"
# ----------------------------------------------------------------------
# cleanup
::tcltest::cleanupTests
|
| ︙ | ︙ |
Added tests/clock-ivm.test.
> > > > > > > > | 1 2 3 4 5 6 7 8 |
# clock-ivm.test --
#
# This test file covers the 'clock' command using inverted validity mode.
#
# See the file "clock.test" for more information.
::tcl::unsupported::clock::configure -valid [expr {![::tcl::unsupported::clock::configure -valid]}]
source [file join [file dirname [info script]] clock.test]
|
Changes to tests/clock.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# clock.test --
#
# This test file covers the 'clock' command that manipulates time.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands. Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
# Copyright © 2004 Kevin B. Kenny. All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {"::tcltest" ni [namespace children]} {
package require tcltest 2.5
namespace import -force ::tcltest::*
}
if {[testConstraint win]} {
if {[catch {
::tcltest::loadTestedCommands
| > < | > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# clock.test --
#
# This test file covers the 'clock' command that manipulates time.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands. Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
# Copyright © 2004 Kevin B. Kenny. All rights reserved.
# Copyright © 2015 Sergey G. Brester aka sebres.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {"::tcltest" ni [namespace children]} {
package require tcltest 2.5
namespace import -force ::tcltest::*
}
if {[testConstraint win]} {
if {[catch {
::tcltest::loadTestedCommands
}]} {
# nothing to be done (registry loaded on demand)
}
}
package require msgcat 1.4
testConstraint detroit \
[expr {![catch {clock format 0 -timezone :America/Detroit -format %z}]}]
testConstraint y2038 \
[expr {[clock format 2158894800 -format %z -timezone :America/Detroit] eq {-0400}}]
# Test with both validity modes - validate on / off:
set valid_mode [::tcl::unsupported::clock::configure -valid]
# Wrapper to show validity mode in the test-case name (for possible errors):
proc test {args} {
variable valid_mode
lset args 0 [lindex $args 0].vm:$valid_mode
tailcall ::tcltest::test {*}$args
}
puts [outputChannel] " Validity default mode: [expr {$valid_mode ? "on": "off"}]"
testConstraint valid_off [expr {![::tcl::unsupported::clock::configure -valid]}]
if {[namespace which -command ::tcl::unsupported::timerate] ne ""} {
namespace import ::tcl::unsupported::timerate
}
# TEST PLAN
# clock-0:
# several base test-cases
#
# clock-1:
# [clock format] - tests of bad and empty arguments
#
# clock-2
# formatting of year, month and day of month
#
# clock-3
|
| ︙ | ︙ | |||
246 247 248 249 250 251 252 253 254 255 256 |
}
if { ![dict exists $reg $path $key] } {
return -code error "test case attempts to read unknown registry entry $path $key"
}
return [dict get $reg $path $key]
}
# Test some of the basics of [clock format]
test clock-1.0 "clock format - wrong # args" {
list [catch {clock format} msg] $msg $::errorCode
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | | < < | > > | > > > > > > > > > > > > > > > | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
}
if { ![dict exists $reg $path $key] } {
return -code error "test case attempts to read unknown registry entry $path $key"
}
return [dict get $reg $path $key]
}
# Base test cases:
test clock-0.1 "initial: auto-loading of ensemble and stubs on demand" -setup {
set i [interp create]; # because clock can be used somewhere, test it in new interp:
} -body {
$i eval {
lappend ret ens:[namespace ensemble exists ::clock]
clock seconds; # init ensemble (but not yet stubs, loading of clock.tcl retarded)
lappend ret ens:[namespace ensemble exists ::clock]
lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
clock format -now; # clock.tcl stubs expected
lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
}
} -cleanup {
interp delete $i
} -result {ens:0 ens:1 stubs:0 stubs:1}
test clock-0.1a "initial: safe interpreter shares clock command with parent" -setup {
set i [interp create]
$i eval {set sci [interp create -safe]}
} -body {
$i eval {
lappend ret ens:[namespace ensemble exists ::clock]
$sci eval { clock seconds }; # init ensemble (but not yet stubs, loading of clock.tcl retarded)
lappend ret ens:[namespace ensemble exists ::clock]
lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
$sci eval { clock format -now }; # clock.tcl stubs expected
lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
}
} -cleanup {
interp delete $i
} -result {ens:0 ens:1 stubs:0 stubs:1}
test clock-0.2 "initial: loading of format/locale does not overwrite interp state (errorInfo)" -setup {
# be sure - we have no cached locale/msgcat, etc:
if {[namespace which -command ::tcl::clock::ClearCaches] ne ""} {
::tcl::clock::ClearCaches
}
} -body {
if {[catch {
return -level 0 -code error -errorcode {EXPERR TEST-ERROR} -errorinfo "ERROR expected error" test
}]} {
clock format -now -locale de; # should not overwrite error code/info
list $::errorCode $::errorInfo
}
} -result {{EXPERR TEST-ERROR} {ERROR expected error}}
# Test some of the basics of [clock format]
set syntax "clockval|-now ?-format string? ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?"
test clock-1.0 "clock format - wrong # args" {
list [catch {clock format} msg] $msg $::errorCode
} [subst {1 {wrong # args: should be "clock format $syntax"} {CLOCK wrongNumArgs}}]
test clock-1.0.1 "clock format - wrong # args (compiled ensemble with invalid syntax)" {
list [catch {clock format 0 -too-few-options-4-test} msg] $msg $::errorCode
} [subst {1 {wrong # args: should be "clock format $syntax"} {CLOCK wrongNumArgs}}]
test clock-1.1 "clock format - bad time" {
list [catch {clock format foo} msg] $msg
} {1 {expected integer but got "foo"}}
test clock-1.2 "clock format - bad gmt val" {
list [catch {clock format 0 -gmt foo} msg] $msg
} {1 {expected boolean value but got "foo"}}
test clock-1.3 "clock format - empty val" {
clock format 0 -gmt 1 -format ""
} {}
test clock-1.4 "clock format - bad flag" {
# range error message for possible extensions:
list [catch {clock format 0 -oops badflag} msg] $msg $::errorCode
} [subst {1 {bad option "-oops": must be -format, -gmt, -locale, or -timezone} {CLOCK badOption -oops}}]
test clock-1.4.1 "clock format - unexpected option for this sub-command" {
# range error message for possible extensions:
list [catch {clock format 0 -base 0} msg] $msg $::errorCode
} [subst {1 {bad option "-base": must be -format, -gmt, -locale, or -timezone} {CLOCK badOption -base}}]
test clock-1.5 "clock format - bad timezone" {
list [catch {clock format 0 -format "%s" -timezone :NOWHERE} msg] $msg $::errorCode
} {1 {time zone ":NOWHERE" not found} {CLOCK badTimeZone :NOWHERE}}
test clock-1.6 "clock format - gmt + timezone" {
list [catch {clock format 0 -timezone :GMT -gmt true} msg] $msg $::errorCode
} {1 {cannot use -gmt and -timezone in same call} {CLOCK gmtWithTimezone}}
test clock-1.7 "clock format - option abbreviations" {
clock format 0 -g true -f "%Y-%m-%d"
} 1970-01-01
test clock-1.7.1 "clock format - command abbreviations (compat regression test)" {
clock f 0 -g 1 -f "%Y-%m-%d"
} 1970-01-01
test clock-1.8 "clock format -now" {
# give one second more for test (if on boundary of the current second):
set n [clock format [clock seconds] -g 1 -f "%s"]
expr {[clock format -now -g 1 -f "%s"] in [list $n [incr n]]}
} 1
test clock-1.9 "clock arguments: option doubly present" {
list [catch {clock format 0 -gmt 1 -gmt 0} result] $result
} {1 {bad option "-gmt": doubly present}}
# BEGIN testcases2
# Test formatting of Gregorian year, month, day, all formats
# Formats tested: %b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y %EY
test clock-2.1 {conversion of 1872-01-01} {
|
| ︙ | ︙ | |||
15287 15288 15289 15290 15291 15292 15293 15294 15295 15296 15297 15298 15299 15300 |
} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:58 pm 23:59 58 lviii 23:59:58 23:59:58 xxiii h lix m lviii s Thu Jan 1 23:59:58 GMT 1970}
test clock-4.96 { format time of day 23:59:59 } {
clock format 86399 \
-format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
-locale en_US_roman \
-gmt true
} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:59 pm 23:59 59 lix 23:59:59 23:59:59 xxiii h lix m lix s Thu Jan 1 23:59:59 GMT 1970}
# END testcases4
# BEGIN testcases5
# Test formatting of Daylight Saving Time
test clock-5.1 {does Detroit exist} {
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 15374 15375 15376 15377 15378 15379 15380 15381 15382 15383 15384 15385 15386 15387 15388 15389 15390 15391 15392 15393 15394 15395 15396 15397 15398 15399 15400 15401 15402 15403 15404 15405 15406 15407 15408 15409 15410 15411 15412 15413 15414 15415 15416 15417 15418 15419 15420 15421 15422 15423 15424 15425 15426 15427 15428 15429 15430 15431 15432 15433 15434 15435 15436 15437 15438 15439 15440 15441 15442 15443 15444 15445 15446 15447 15448 15449 15450 15451 15452 15453 15454 15455 15456 15457 15458 15459 15460 15461 15462 15463 15464 15465 |
} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:58 pm 23:59 58 lviii 23:59:58 23:59:58 xxiii h lix m lviii s Thu Jan 1 23:59:58 GMT 1970}
test clock-4.96 { format time of day 23:59:59 } {
clock format 86399 \
-format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
-locale en_US_roman \
-gmt true
} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:59 pm 23:59 59 lix 23:59:59 23:59:59 xxiii h lix m lix s Thu Jan 1 23:59:59 GMT 1970}
test clock-4.97.1 { format JDN/JD (calendar and astronomical) } {
clock format 0 -format {%J %EJ %Ej} -gmt true
} {2440588 2440588.0 2440587.5}
test clock-4.97.2 { format JDN/JD (calendar and astronomical) } {
clock format 43200 -format {%J %EJ %Ej} -gmt true
} {2440588 2440588.5 2440588.0}
test clock-4.97.3 { format JDN/JD (calendar and astronomical) } {
clock format 86399 -format {%J %EJ %Ej} -gmt true
} {2440588 2440588.99998843 2440588.49998843}
test clock-4.97.4 { format JDN/JD (calendar and astronomical) } {
clock format 86400 -format {%J %EJ %Ej} -gmt true
} {2440589 2440589.0 2440588.5}
test clock-4.97.5 { format JDN/JD (calendar and astronomical) } {
clock format 129599 -format {%J %EJ %Ej} -gmt true
} {2440589 2440589.49998843 2440588.99998843}
test clock-4.97.6 { format JDN/JD (calendar and astronomical) } {
clock format 129600 -format {%J %EJ %Ej} -gmt true
} {2440589 2440589.5 2440589.0}
test clock-4.97.7 { format JDN/JD (calendar and astronomical) } {
set i 1548249092
list \
[clock format $i -format {%J %EJ %Ej} -gmt true] \
[clock format [incr i] -format {%J %EJ %Ej} -gmt true] \
[clock format [incr i] -format {%J %EJ %Ej} -gmt true]
} {{2458507 2458507.54967593 2458507.04967593} {2458507 2458507.5496875 2458507.0496875} {2458507 2458507.54969907 2458507.04969907}}
test clock-4.97.8 { format JDN/JD (calendar and astronomical) } {
set res {}
foreach i {
-172800 -129600 -86400 -43200
-1 0 1 21600 43199 43200 86399
86400 86401 108000 129600 172800
} {
lappend res $i [clock format [expr {-210866803200 - $i}] \
-format {%EE %Y-%m-%d %T -- %J %EJ %Ej} -gmt true]
}
set res
} [list \
-172800 {B.C.E. 4713-01-03 00:00:00 -- 0000002 2.0 1.5} \
-129600 {B.C.E. 4713-01-02 12:00:00 -- 0000001 1.5 1.0} \
-86400 {B.C.E. 4713-01-02 00:00:00 -- 0000001 1.0 0.5} \
-43200 {B.C.E. 4713-01-01 12:00:00 -- 0000000 0.5 0.0} \
-1 {B.C.E. 4713-01-01 00:00:01 -- 0000000 0.00001157 -0.49998843} \
0 {B.C.E. 4713-01-01 00:00:00 -- 0000000 0.0 -0.5} \
1 {B.C.E. 4714-12-31 23:59:59 -- -000001 -0.00001157 -0.50001157} \
21600 {B.C.E. 4714-12-31 18:00:00 -- -000001 -0.25 -0.75} \
43199 {B.C.E. 4714-12-31 12:00:01 -- -000001 -0.49998843 -0.99998843} \
43200 {B.C.E. 4714-12-31 12:00:00 -- -000001 -0.5 -1.0} \
86399 {B.C.E. 4714-12-31 00:00:01 -- -000001 -0.99998843 -1.49998843} \
86400 {B.C.E. 4714-12-31 00:00:00 -- -000001 -1.0 -1.5} \
86401 {B.C.E. 4714-12-30 23:59:59 -- -000002 -1.00001157 -1.50001157} \
108000 {B.C.E. 4714-12-30 18:00:00 -- -000002 -1.25 -1.75} \
129600 {B.C.E. 4714-12-30 12:00:00 -- -000002 -1.5 -2.0} \
172800 {B.C.E. 4714-12-30 00:00:00 -- -000002 -2.0 -2.5} \
]
test clock-4.97.9 { format JDN/JD (calendar and astronomical) } {
set res {}
foreach i {
-86400 -43200
-1 0 1
43199 43200 43201 86400
} {
lappend res $i [clock format [expr {653133196800 + $i}] \
-format {%Y-%m-%d %T -- %J %EJ %Ej} -gmt true]
}
set res
} [list \
-86400 {22666-12-19 00:00:00 -- 9999999 9999999.0 9999998.5} \
-43200 {22666-12-19 12:00:00 -- 9999999 9999999.5 9999999.0} \
-1 {22666-12-19 23:59:59 -- 9999999 9999999.99998843 9999999.49998843} \
0 {22666-12-20 00:00:00 -- 10000000 10000000.0 9999999.5} \
1 {22666-12-20 00:00:01 -- 10000000 10000000.00001157 9999999.50001157} \
43199 {22666-12-20 11:59:59 -- 10000000 10000000.49998843 9999999.99998843} \
43200 {22666-12-20 12:00:00 -- 10000000 10000000.5 10000000.0} \
43201 {22666-12-20 12:00:01 -- 10000000 10000000.50001157 10000000.00001157} \
86400 {22666-12-21 00:00:00 -- 10000001 10000001.0 10000000.5} \
]
# END testcases4
# BEGIN testcases5
# Test formatting of Daylight Saving Time
test clock-5.1 {does Detroit exist} {
|
| ︙ | ︙ | |||
18528 18529 18530 18531 18532 18533 18534 |
} 2147483648
test clock-6.8 {input of seconds} {
clock scan {9223372036854775807} -format %s -gmt true
} 9223372036854775807
test clock-6.9 {input of seconds - overflow} {
| | | < | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 18693 18694 18695 18696 18697 18698 18699 18700 18701 18702 18703 18704 18705 18706 18707 18708 18709 18710 18711 18712 18713 18714 18715 18716 18717 18718 18719 18720 18721 18722 18723 18724 18725 18726 18727 18728 18729 18730 18731 18732 18733 18734 18735 18736 18737 18738 18739 18740 18741 18742 18743 18744 18745 18746 18747 18748 18749 18750 18751 18752 18753 18754 18755 18756 18757 18758 18759 18760 18761 18762 18763 18764 18765 18766 18767 18768 18769 18770 18771 18772 18773 18774 18775 18776 18777 18778 18779 18780 18781 18782 18783 18784 18785 18786 18787 18788 18789 18790 18791 18792 18793 18794 18795 18796 18797 18798 18799 18800 18801 18802 18803 18804 18805 18806 18807 18808 18809 18810 18811 18812 18813 18814 18815 18816 18817 18818 18819 18820 18821 18822 18823 18824 18825 18826 18827 18828 18829 18830 18831 18832 18833 18834 18835 18836 18837 18838 18839 18840 18841 18842 18843 18844 18845 18846 18847 18848 18849 18850 18851 18852 18853 18854 18855 18856 18857 18858 18859 18860 18861 18862 18863 18864 18865 18866 18867 18868 18869 18870 18871 18872 18873 18874 18875 18876 18877 18878 18879 18880 18881 18882 18883 18884 18885 18886 18887 18888 18889 18890 18891 18892 18893 18894 18895 18896 18897 18898 18899 18900 18901 18902 18903 18904 18905 18906 18907 18908 18909 18910 18911 18912 18913 18914 18915 18916 18917 18918 18919 18920 18921 18922 18923 18924 18925 18926 18927 18928 18929 |
} 2147483648
test clock-6.8 {input of seconds} {
clock scan {9223372036854775807} -format %s -gmt true
} 9223372036854775807
test clock-6.9 {input of seconds - overflow} {
list [catch {clock scan -9223372036854775809 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
} {1 {integer value too large to represent} {CLOCK dateTooLarge}}
test clock-6.10 {input of seconds - overflow} {
list [catch {clock scan 9223372036854775808 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
} {1 {integer value too large to represent} {CLOCK dateTooLarge}}
foreach sign {{} -} {
test clock-6.10a {input of seconds - overflow, bug [1f40aa83c5]} {
list [catch {clock scan ${sign}27670116110564327423 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
} {1 {integer value too large to represent} {CLOCK dateTooLarge}}
test clock-6.10b {input of seconds - overflow, bug [1f40aa83c5]} {
list [catch {clock scan ${sign}27670116110564327424 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
} {1 {integer value too large to represent} {CLOCK dateTooLarge}}
test clock-6.10c {input of seconds - no overflow, bug [1f40aa83c5]} {
list [catch {clock scan ${sign}[string repeat 9 18] -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
} [list 0 ${sign}[string repeat 9 18] {}]
test clock-6.10d {input of seconds - overflow, bug [1f40aa83c5]} {
list [catch {clock scan ${sign}[string repeat 9 19] -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
} {1 {integer value too large to represent} {CLOCK dateTooLarge}}
# both fololowing freescan test don't generate overflow error,
# since it is a free scan, thus the token is simply not recognized further in yacc lexer,
# therefore we get parse error (can be surely changed latter):
test clock-6.10e {input of seconds - overflow (but since freescan parse error, but not boom), bug [1f40aa83c5]} -body {
list [catch {clock scan ${sign}27670116110564327423 -gmt true} result opt] $result [dict getd $opt -errorcode ""]
} -match glob -result {1 {unable to convert date-time string "*": syntax error *} {TCL VALUE DATE PARSE}}
test clock-6.10f {input of seconds - overflow (but since freescan parse error, but not boom), bug [1f40aa83c5]} -body {
list [catch {clock scan ${sign}27670116110564327424 -gmt true} result opt] $result [dict getd $opt -errorcode ""]
} -match glob -result {1 {unable to convert date-time string "*": syntax error *} {TCL VALUE DATE PARSE}}
}; unset sign
test clock-6.11 {input of seconds - two values} {
clock scan {1 2} -format {%s %s} -gmt true
} 2
test clock-6.12.0 {input of short forms of locale token (%b)} {
list [clock scan "12 Ja 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1] \
[clock scan "12 Au 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1]
} {979257600 997574400}
test clock-6.12.1 {input of all forms of unambiguous short locale token (%b)} {
# find all unambiguous short forms and check it'll be scanned successful and correctly:
set months {January February March April May June July August September October November December}
set res {}
foreach mon $months {
set i 0
while {[incr i] < [string length $mon]} {
# short month form:
set shm [string range $mon 0 $i]
# differentiate ambiguous:
if {[llength [lsearch -all -glob $months "${shm}*"]] <= 1} {
# unambiguous (expected date with wull month):
set e "12 $mon 2001"
} else {
# ambiguous (expected error):
set e "input string does not match supplied format"
}
set s "12 $shm 2001"
# scan and format with full month name:
catch {clock format \
[clock scan $s -format "%d %b %Y" -locale en_US_roman -gmt 1] \
-format "%d %B %Y" -locale en_US_roman -gmt 1} t
# check it corresponds the full form:
if {$t ne $e} {
lappend res "unexpected result converting $s, expected \"$e\", got \"$t\""
}
}
}
set res
} {}
test clock-6.13 {input of lowercase locale token (%b)} {
list [clock scan "12 ja 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1] \
[clock scan "12 au 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1]
} {979257600 997574400}
test clock-6.14 {input of uppercase locale token (%b)} {
list [clock scan "12 JA 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1] \
[clock scan "12 AU 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1]
} {979257600 997574400}
test clock-6.15 {input of ambiguous short locale token (%b)} {
list [catch {
clock scan "12 J 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1
} result] $result $errorCode
} {1 {input string does not match supplied format} {CLOCK badInputString}}
test clock-6.16 {input of ambiguous short locale token (%b)} {
list [catch {
clock scan "12 Ju 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1
} result] $result $errorCode
} {1 {input string does not match supplied format} {CLOCK badInputString}}
test clock-6.17 {spaces are always optional in non-strict mode (default)} {
list [clock scan "2009-06-30T18:30:00+02:00" -format "%Y-%m-%dT%H:%M:%S%z" -gmt 1] \
[clock scan "2009-06-30T18:30:00 +02:00" -format "%Y-%m-%dT%H:%M:%S%z" -gmt 1] \
[clock scan "2009-06-30T18:30:00Z" -format "%Y-%m-%dT%H:%M:%S%z" -timezone CET] \
[clock scan "2009-06-30T18:30:00 Z" -format "%Y-%m-%dT%H:%M:%S%z" -timezone CET]
} {1246379400 1246379400 1246386600 1246386600}
test clock-6.18 {zone token (%z) is optional} {
list [clock scan "2009-06-30T18:30:00 -01:00" -format "%Y-%m-%dT%H:%M:%S%z" -gmt 1] \
[clock scan "2009-06-30T18:30:00" -format "%Y-%m-%dT%H:%M:%S%z" -gmt 1] \
[clock scan " 2009-06-30T18:30:00 " -format "%Y-%m-%dT%H:%M:%S%z" -gmt 1] \
} {1246390200 1246386600 1246386600}
test clock-6.19 {no token parsing} {
list [catch { clock scan "%E%O%" -format "%E%O%" }] \
[catch { clock scan "...%..." -format "...%%..." }]
} {0 0}
test clock-6.20 {special char tokens %n, %t} {
clock scan "30\t06\t2009\n18\t30" -format "%d%t%m%t%Y%n%H%t%M" -gmt 1
} 1246386600
# Hi, Jeff!
proc _testStarDates {s {days {366*2}} {step {86400}}} {
set step [expr {int($step * 86400)}]
# reconvert - arrange in order of stardate:
set s [set i [clock scan [clock format $s -f "%Q" -g 1] -g 1]]
# test:
set wrong {}
while {$i < $s + $days*86400} {
set d [clock format $i -f "%Q" -g 1]
if {![regexp {^Stardate \d+\.\d$} $d]} {
lappend wrong "wrong: $d -- ($i) -- [clock format $i -g 1]"
}
if {[catch {
set i2 [clock scan $d -f "%Q" -g 1]
} msg]} {
lappend wrong "$d -- ($i) -- [clock format $i -g 1]: $msg"
}
if {$i != $i2} {
lappend wrong "$d -- ($i != $i2) -- [clock format $i -g 1]"
}
incr i $step
}
join $wrong \n
}
test clock-6.21.0 {Stardate 0 day} {
list [set d [clock format -757382400 -format "%Q" -gmt 1]] \
[clock scan $d -format "%Q" -gmt 1]
} [list "Stardate 00000.0" -757382400]
test clock-6.21.0.1 {Stardate 0.1 - 1.9 (test negative clock value -> positive Stardate)} {
_testStarDates -757382400 2 0.1
} {}
test clock-6.21.0.2 {Stardate 10000.1 - 10002.9 (test negative clock value -> positive Stardate)} {
_testStarDates [clock scan "Stardate 10000.1" -f %Q -g 1] 3 0.1
} {}
test clock-6.21.0.2 {Stardate 80000.1 - 80002.9 (test positive clock value)} {
_testStarDates [clock scan "Stardate 80001.1" -f %Q -g 1] 3 0.1
} {}
test clock-6.21.1 {Stardate} {
list [set d [clock format 1482857280 -format "%Q" -gmt 1]] \
[clock scan $d -format "%Q" -gmt 1]
} [list "Stardate 70986.7" 1482857280]
test clock-6.21.2 {Stardate next time} {
list [set d [clock format 1482865920 -format "%Q" -gmt 1]] \
[clock scan $d -format "%Q" -gmt 1]
} [list "Stardate 70986.8" 1482865920]
test clock-6.21.3 {Stardate correct scan over year (leap year, begin, middle and end of the year)} {
_testStarDates [clock scan "01.01.2016" -f "%d.%m.%Y" -g 1] [expr {366*2}] 1
} {}
rename _testStarDates {}
test clock-6.22.1 {Greedy match} {
clock format [clock scan "111" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Mon Jan 01 00:00:00 GMT 2001}
test clock-6.22.2 {Greedy match} {
clock format [clock scan "1111" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Thu Jan 11 00:00:00 GMT 2001}
test clock-6.22.3 {Greedy match} {
clock format [clock scan "11111" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Sun Nov 11 00:00:00 GMT 2001}
test clock-6.22.4 {Greedy match} {
clock format [clock scan "111111" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Fri Nov 11 00:00:00 GMT 2011}
test clock-6.22.5 {Greedy match} {
clock format [clock scan "1 1 1" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Mon Jan 01 00:00:00 GMT 2001}
test clock-6.22.6 {Greedy match} {
clock format [clock scan "111 1" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Thu Jan 11 00:00:00 GMT 2001}
test clock-6.22.7 {Greedy match} {
clock format [clock scan "1 111" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Thu Nov 01 00:00:00 GMT 2001}
test clock-6.22.8 {Greedy match} {
clock format [clock scan "1 11 1" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Thu Nov 01 00:00:00 GMT 2001}
test clock-6.22.9 {Greedy match} {
clock format [clock scan "1 11 11" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Tue Nov 01 00:00:00 GMT 2011}
test clock-6.22.10 {Greedy match} {
clock format [clock scan "11 11 11" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Fri Nov 11 00:00:00 GMT 2011}
test clock-6.22.11 {Greedy match} {
clock format [clock scan "1111 120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Sat Jan 01 01:02:00 GMT 2011}
test clock-6.22.12 {Greedy match} {
clock format [clock scan "11 1 120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Mon Jan 01 01:02:00 GMT 2001}
test clock-6.22.13 {Greedy match} {
clock format [clock scan "1 11 120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Mon Jan 01 01:02:00 GMT 2001}
test clock-6.22.14 {Greedy match} {
clock format [clock scan "111120" -format "%y%m%d%H%M%S" -gmt 1] -locale en -gmt 1
} {Mon Jan 01 01:02:00 GMT 2001}
test clock-6.22.15 {Greedy match} {
clock format [clock scan "1111120" -format "%y%m%d%H%M%S" -gmt 1] -locale en -gmt 1
} {Sat Jan 01 01:02:00 GMT 2011}
test clock-6.22.16 {Greedy match} {
clock format [clock scan "11121120" -format "%y%m%d%H%M%S" -gmt 1] -locale en -gmt 1
} {Thu Dec 01 01:02:00 GMT 2011}
test clock-6.22.17 {Greedy match} {
clock format [clock scan "111213120" -format "%y%m%d%H%M%S" -gmt 1] -locale en -gmt 1
} {Tue Dec 13 01:02:00 GMT 2011}
test clock-6.22.17 {Greedy match (space wins as date-time separator)} {
clock format [clock scan "1112 13120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Sun Jan 02 13:12:00 GMT 2011}
test clock-6.22.18 {Greedy match (second space wins as date-time separator)} {
clock format [clock scan "1112 13 120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Tue Dec 13 01:02:00 GMT 2011}
test clock-6.22.19 {Greedy match (space wins as date-time separator)} {
clock format [clock scan "111 213120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Mon Jan 01 21:31:20 GMT 2001}
test clock-6.22.20 {Greedy match (second space wins as date-time separator)} {
clock format [clock scan "111 2 13120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Sun Jan 02 13:12:00 GMT 2011}
test clock-7.1 {Julian Day} {
clock scan 0 -format %J -gmt true
} -210866803200
test clock-7.2 {Julian Day} {
clock format [clock scan 2440588 -format %J -gmt true] \
|
| ︙ | ︙ | |||
18605 18606 18607 18608 18609 18610 18611 18612 18613 18614 18615 18616 18617 18618 |
set s0m24h [clock add $s0 -24 hours -timezone :UTC]
set J0m24h [scan [clock format $s0m24h -format %J -gmt true] %lld]
set s0m1s [clock add $s0 -1 seconds -timezone :UTC]
set J0m1s [scan [clock format $s0m1s -format %J -gmt true] %lld]
list $s0m1d $s0m24h $J0m24h $s0m1s $J0m1s $s0 $J0 \
[::tcl::mathop::== $s0m1d $s0m24h] [::tcl::mathop::== $J0m24h $J0m1s]
} [list -210866889600 -210866889600 -1 -210866803201 -1 -210866803200 0 1 1]
# BEGIN testcases8
# Test parsing of ccyymmdd
test clock-8.1 {parse ccyymmdd} {
clock scan {1970 Jan 02} -format {%C%y %b %d} -locale en_US_roman -gmt 1
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 18983 18984 18985 18986 18987 18988 18989 18990 18991 18992 18993 18994 18995 18996 18997 18998 18999 19000 19001 19002 19003 19004 19005 19006 19007 19008 19009 19010 19011 19012 19013 19014 19015 19016 19017 19018 19019 19020 19021 19022 19023 19024 19025 19026 19027 19028 19029 19030 19031 19032 19033 19034 19035 19036 19037 19038 19039 19040 19041 19042 19043 19044 19045 19046 19047 19048 19049 19050 19051 19052 19053 19054 19055 19056 19057 19058 19059 19060 19061 19062 19063 19064 19065 19066 19067 19068 19069 19070 19071 19072 19073 19074 19075 19076 19077 19078 19079 19080 19081 |
set s0m24h [clock add $s0 -24 hours -timezone :UTC]
set J0m24h [scan [clock format $s0m24h -format %J -gmt true] %lld]
set s0m1s [clock add $s0 -1 seconds -timezone :UTC]
set J0m1s [scan [clock format $s0m1s -format %J -gmt true] %lld]
list $s0m1d $s0m24h $J0m24h $s0m1s $J0m1s $s0 $J0 \
[::tcl::mathop::== $s0m1d $s0m24h] [::tcl::mathop::== $J0m24h $J0m1s]
} [list -210866889600 -210866889600 -1 -210866803201 -1 -210866803200 0 1 1]
test clock-7.11.1 {Calendar vs Astronomical Julian Day (without and with time fraction)} {
list \
[clock scan {2440588} -format {%J} -gmt true] \
[clock scan {2440588} -format {%EJ} -gmt true] \
[clock scan {2440588} -format {%Ej} -gmt true] \
[clock scan {2440588.5} -format {%EJ} -gmt true] \
[clock scan {2440588.5} -format {%Ej} -gmt true] \
} {0 0 43200 43200 86400}
test clock-7.11.2 {Astronomical JDN/JD} {
clock scan 0 -format %Ej -gmt true
} -210866760000
test clock-7.12 {Astronomical JDN/JD} {
clock format [clock scan 2440587.5 -format %Ej -gmt true] \
-format "%Y-%m-%d %T" -gmt true
} "1970-01-01 00:00:00"
test clock-7.13 {Astronomical JDN/JD} {
clock format [clock scan 2451544.5 -format %Ej -gmt true] \
-format "%Y-%m-%d %T" -gmt true
} "2000-01-01 00:00:00"
test clock-7.13.1 {Astronomical JDN/JD} {
clock format [clock scan 2488069.5 -format %Ej -gmt true] \
-format "%Y-%m-%d %T" -gmt true
} "2100-01-01 00:00:00"
test clock-7.14 {Astronomical JDN/JD} {
clock format [clock scan 5373483.5 -format %Ej -gmt true] \
-format "%Y-%m-%d %T" -gmt true
} "9999-12-31 00:00:00"
test clock-7.14.1 {Astronomical JDN/JD} {
clock format [clock scan 5373484 -format %Ej -gmt true] \
-format "%Y-%m-%d %T" -gmt true
} "9999-12-31 12:00:00"
test clock-7.14.2 {Astronomical JDN/JD} {
clock format [clock scan 5373484.49999 -format %Ej -gmt true] \
-format "%Y-%m-%d %T" -gmt true
} "9999-12-31 23:59:59"
test clock-7.15 {Astronomical JDN/JD, bad} {
list [catch {
clock scan bogus -format %Ej
} result] $result $errorCode
} {1 {input string does not match supplied format} {CLOCK badInputString}}
test clock-7.16 {Astronomical JDN/JD, overflow} {
list [catch {
clock scan 5373484.5 -format %Ej
} result] $result $errorCode \
[catch {
clock scan 5373485 -format %Ej
} result] $result $errorCode \
[catch {
clock scan 2147483648 -format %Ej
} result] $result $errorCode \
[catch {
clock scan 2147483648.5 -format %Ej
} result] $result $errorCode
} [lrepeat 4 1 {requested date too large to represent} {CLOCK dateTooLarge}]
test clock-7.18 {Astronomical JDN/JD, same precedence as seconds (last wins} {
list [clock scan {2440588 86400} -format {%Ej %s} -gmt true] \
[clock scan {2440589 0} -format {%Ej %s} -gmt true] \
[clock scan {86400 2440588} -format {%s %Ej} -gmt true] \
[clock scan {0 2440589} -format {%s %Ej} -gmt true]
} {86400 0 43200 129600}
test clock-7.19 {Astronomical JDN/JD, two values} {
clock scan {2440588 2440589} -format {%Ej %Ej} -gmt true
} 129600
test clock-7.20 {all JDN/JD are signed (and extended accept floats)} {
set res {}
foreach i {%J %EJ %Ej} {
lappend res [clock scan "-1" -format $i -gmt 1]
}
foreach i {%EJ %Ej} {
lappend res [clock scan "-1.5" -format $i -gmt 1]
}
set res
} {-210866889600 -210866889600 -210866846400 -210866846400 -210866803200}
# BEGIN testcases8
# Test parsing of ccyymmdd
test clock-8.1 {parse ccyymmdd} {
clock scan {1970 Jan 02} -format {%C%y %b %d} -locale en_US_roman -gmt 1
|
| ︙ | ︙ | |||
21016 21017 21018 21019 21020 21021 21022 |
} 1009756800
# END testcases8
test clock-9.1 {seconds take precedence over ccyymmdd} {
clock scan {0 20000101} -format {%s %Y%m%d} -gmt true
} 0
| | > | > | > > > > > > > > > > > | 21479 21480 21481 21482 21483 21484 21485 21486 21487 21488 21489 21490 21491 21492 21493 21494 21495 21496 21497 21498 21499 21500 21501 21502 21503 21504 21505 21506 21507 21508 |
} 1009756800
# END testcases8
test clock-9.1 {seconds take precedence over ccyymmdd} {
clock scan {0 20000101} -format {%s %Y%m%d} -gmt true
} 0
test clock-9.2 {Calendar julian day takes precedence over ccyymmdd} {
list \
[clock scan {2440588 20000101} -format {%J %Y%m%d} -gmt true] \
[clock scan {2440588 20000101} -format {%EJ %Y%m%d} -gmt true]
} {0 0}
test clock-9.2.1 {Calendar julian day (with time fraction) takes precedence over date-time} {
list \
[clock scan {2440588.0 20000101 010203} -format {%EJ %Y%m%d %H%M%S} -gmt true] \
[clock scan {2440588.5 20000101 010203} -format {%EJ %Y%m%d %H%M%S} -gmt true]
} {0 43200}
test clock-9.3 {Astro julian day takes always precedence over date-time} {
list \
[clock scan {2440587.5 20000101 010203} -format {%Ej %Y%m%d %H%M%S} -gmt true] \
[clock scan {2440588 20000101 010203} -format {%Ej %Y%m%d %H%M%S} -gmt true]
} {0 43200}
# Test parsing of ccyyddd
test clock-10.1 {parse ccyyddd} {
clock scan {1970 001} -format {%Y %j} -locale en_US_roman -gmt 1
} 0
test clock-10.2 {parse ccyyddd} {
|
| ︙ | ︙ | |||
21059 21060 21061 21062 21063 21064 21065 |
test clock-10.10 {julian day takes precedence over ccyyddd} {
list [clock scan {2440588 2000001} -format {%J %Y%j} -gmt true] \
[clock scan {2000001 2440588} -format {%Y%j %J} -gmt true]
} {0 0}
# BEGIN testcases11
| | > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > | 21535 21536 21537 21538 21539 21540 21541 21542 21543 21544 21545 21546 21547 21548 21549 21550 21551 21552 21553 21554 21555 21556 21557 21558 21559 21560 21561 21562 21563 21564 21565 21566 21567 21568 21569 21570 21571 21572 21573 21574 21575 21576 21577 21578 21579 21580 21581 21582 21583 21584 21585 21586 21587 21588 21589 21590 21591 21592 21593 21594 21595 21596 21597 21598 21599 21600 21601 21602 21603 21604 21605 21606 21607 21608 21609 21610 21611 21612 21613 21614 21615 21616 21617 21618 21619 21620 21621 21622 21623 21624 21625 21626 21627 21628 21629 |
test clock-10.10 {julian day takes precedence over ccyyddd} {
list [clock scan {2440588 2000001} -format {%J %Y%j} -gmt true] \
[clock scan {2000001 2440588} -format {%Y%j %J} -gmt true]
} {0 0}
# BEGIN testcases11
# Test precedence yyyymmdd over yyyyddd
if {!$valid_mode} {
set res {-result 0}
} else {
set res {-returnCodes error -result "unable to convert input string: ambiguous day"}
}
test clock-11.1 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 19700101002 -format %Y%m%d%j -gmt 1
} {*}$res
test clock-11.2 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 01197001002 -format %m%Y%d%j -gmt 1
} {*}$res
test clock-11.3 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 01197001002 -format %d%Y%m%j -gmt 1
} {*}$res
test clock-11.4 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 00219700101 -format %j%Y%m%d -gmt 1
} {*}$res
test clock-11.5 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 19700100201 -format %Y%m%j%d -gmt 1
} {*}$res
test clock-11.6 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 01197000201 -format %m%Y%j%d -gmt 1
} {*}$res
test clock-11.7 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 01197000201 -format %d%Y%j%m -gmt 1
} {*}$res
test clock-11.8 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 00219700101 -format %j%Y%d%m -gmt 1
} {*}$res
test clock-11.9 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 19700101002 -format %Y%d%m%j -gmt 1
} {*}$res
test clock-11.10 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 01011970002 -format %m%d%Y%j -gmt 1
} {*}$res
test clock-11.11 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 01011970002 -format %d%m%Y%j -gmt 1
} {*}$res
test clock-11.12 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 00201197001 -format %j%m%Y%d -gmt 1
} {*}$res
test clock-11.13 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 19700100201 -format %Y%d%j%m -gmt 1
} {*}$res
test clock-11.14 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 01010021970 -format %m%d%j%Y -gmt 1
} {*}$res
test clock-11.15 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 01010021970 -format %d%m%j%Y -gmt 1
} {*}$res
test clock-11.16 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 00201011970 -format %j%m%d%Y -gmt 1
} {*}$res
test clock-11.17 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 19700020101 -format %Y%j%m%d -gmt 1
} {*}$res
test clock-11.18 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 01002197001 -format %m%j%Y%d -gmt 1
} {*}$res
test clock-11.19 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 01002197001 -format %d%j%Y%m -gmt 1
} {*}$res
test clock-11.20 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 00201197001 -format %j%d%Y%m -gmt 1
} {*}$res
test clock-11.21 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 19700020101 -format %Y%j%d%m -gmt 1
} {*}$res
test clock-11.22 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 01002011970 -format %m%j%d%Y -gmt 1
} {*}$res
test clock-11.23 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 01002011970 -format %d%j%m%Y -gmt 1
} {*}$res
test clock-11.24 {precedence of ccyymmdd over ccyyddd} -body {
clock scan 00201011970 -format %j%d%m%Y -gmt 1
} {*}$res
unset -nocomplain res
# END testcases11
# BEGIN testcases12
# Test parsing of ccyyWwwd
test clock-12.1 {parse ccyyWwwd} {
|
| ︙ | ︙ | |||
21429 21430 21431 21432 21433 21434 21435 |
clock scan {2002 W01 i} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
} 1009756800
test clock-12.96 {parse ccyyWwwd} {
clock scan {2002 W01 i} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
} 1009756800
# END testcases12
| | | | 21912 21913 21914 21915 21916 21917 21918 21919 21920 21921 21922 21923 21924 21925 21926 21927 21928 21929 21930 |
clock scan {2002 W01 i} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
} 1009756800
test clock-12.96 {parse ccyyWwwd} {
clock scan {2002 W01 i} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
} 1009756800
# END testcases12
test clock-13.1 {test that %s takes precedence over ccyyWwwd} valid_off {
list [clock scan {0 2000W011} -format {%s %GW%V%u} -gmt true] \
[clock scan {2000W011 0} -format {%GW%V%u %s} -gmt true]
} {0 0}
test clock-13.2 {test that %J takes precedence over ccyyWwwd} valid_off {
list [clock scan {2440588 2000W011} -format {%J %GW%V%u} -gmt true] \
[clock scan {2000W011 2440588} -format {%GW%V%u %J} -gmt true]
} {0 0}
test clock-13.3 {invalid weekday} {
catch {clock scan 2000W018 -format %GW%V%u -gmt true} result
list $result $::errorCode
} {{day of week is greater than 7} {CLOCK badDayOfWeek}}
|
| ︙ | ︙ | |||
23769 23770 23771 23772 23773 23774 23775 |
} {0 0}
test clock-15.2 {yymmdd precedence below julian day} {
list [clock scan {2440588 000101} -format {%J %y%m%d} -gmt true] \
[clock scan {000101 2440588} -format {%y%m%d %J} -gmt true]
} {0 0}
| | | 24252 24253 24254 24255 24256 24257 24258 24259 24260 24261 24262 24263 24264 24265 24266 |
} {0 0}
test clock-15.2 {yymmdd precedence below julian day} {
list [clock scan {2440588 000101} -format {%J %y%m%d} -gmt true] \
[clock scan {000101 2440588} -format {%y%m%d %J} -gmt true]
} {0 0}
test clock-15.3 {yymmdd precedence below yyyyWwwd} valid_off {
list [clock scan {1970W014000101} -format {%GW%V%u%y%m%d} -gmt true] \
[clock scan {0001011970W014} -format {%y%m%d%GW%V%u} -gmt true]
} {0 0}
# Test parsing of yyddd
test clock-16.1 {parse yyddd} {
|
| ︙ | ︙ | |||
23809 23810 23811 23812 23813 23814 23815 |
list [clock scan {0 00001} -format {%s %y%j} -gmt true] \
[clock scan {00001 0} -format {%y%j %s} -gmt true]
} {0 0}
test clock-16.10 {julian day takes precedence over yyddd} {
list [clock scan {2440588 00001} -format {%J %y%j} -gmt true] \
[clock scan {00001 2440588} -format {%Y%j %J} -gmt true]
} {0 0}
| | | 24292 24293 24294 24295 24296 24297 24298 24299 24300 24301 24302 24303 24304 24305 24306 |
list [clock scan {0 00001} -format {%s %y%j} -gmt true] \
[clock scan {00001 0} -format {%y%j %s} -gmt true]
} {0 0}
test clock-16.10 {julian day takes precedence over yyddd} {
list [clock scan {2440588 00001} -format {%J %y%j} -gmt true] \
[clock scan {00001 2440588} -format {%Y%j %J} -gmt true]
} {0 0}
test clock-16.11 {yyddd precedence below yyyyWwwd} valid_off {
list [clock scan {1970W01400001} -format {%GW%V%u%y%j} -gmt true] \
[clock scan {000011970W014} -format {%y%j%GW%V%u} -gmt true]
} {0 0}
# BEGIN testcases17
# Test parsing of yyWwwd
|
| ︙ | ︙ | |||
24110 24111 24112 24113 24114 24115 24116 |
test clock-17.96 {parse yyWwwd} {
clock scan {02 W01 i} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
} 1009756800
# END testcases17
# Test precedence of yyWwwd
| | | | | 24593 24594 24595 24596 24597 24598 24599 24600 24601 24602 24603 24604 24605 24606 24607 24608 24609 24610 24611 24612 24613 24614 24615 24616 24617 24618 24619 |
test clock-17.96 {parse yyWwwd} {
clock scan {02 W01 i} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
} 1009756800
# END testcases17
# Test precedence of yyWwwd
test clock-18.1 {seconds take precedence over yyWwwd} valid_off {
list [clock scan {0 00W014} -format {%s %gW%V%u} -gmt true] \
[clock scan {00W014 0} -format {%gW%V%u %s} -gmt true]
} {0 0}
test clock-18.2 {julian day takes precedence over yyddd} {
list [clock scan {2440588 00W014} -format {%J %gW%V%u} -gmt true] \
[clock scan {00W014 2440588} -format {%gW%V%u %J} -gmt true]
} {0 0}
test clock-18.3 {yyWwwd precedence below yyyymmdd} valid_off {
list [clock scan {19700101 00W014} -format {%Y%m%d %gW%V%u} -gmt true] \
[clock scan {00W014 19700101} -format {%gW%V%u %Y%m%d} -gmt true]
} {0 0}
test clock-18.4 {yyWwwd precedence below yyyyddd} valid_off {
list [clock scan {1970001 00W014} -format {%Y%j %gW%V%u} -gmt true] \
[clock scan {00W014 1970001} -format {%gW%V%u %Y%j} -gmt true]
} {0 0}
# BEGIN testcases19
# Test parsing of mmdd
|
| ︙ | ︙ | |||
25934 25935 25936 25937 25938 25939 25940 |
clock scan vii -format %Ou -locale en_US_roman -gmt 1 -base 1009411200
} 1009670400
test clock-26.48 {parse naked day of week} {
clock scan ? -format %Ow -locale en_US_roman -gmt 1 -base 1009411200
} 1009670400
# END testcases26
| > > > > > | | | | | | | | | | | | | | | | | | > | 26417 26418 26419 26420 26421 26422 26423 26424 26425 26426 26427 26428 26429 26430 26431 26432 26433 26434 26435 26436 26437 26438 26439 26440 26441 26442 26443 26444 26445 26446 26447 26448 26449 26450 26451 26452 26453 26454 26455 26456 26457 26458 26459 26460 26461 26462 26463 26464 26465 26466 26467 26468 26469 26470 26471 26472 |
clock scan vii -format %Ou -locale en_US_roman -gmt 1 -base 1009411200
} 1009670400
test clock-26.48 {parse naked day of week} {
clock scan ? -format %Ow -locale en_US_roman -gmt 1 -base 1009411200
} 1009670400
# END testcases26
if {!$valid_mode} {
set res {-result {0 0}}
} else {
set res {-returnCodes error -result "unable to convert input string: invalid day of week"}
}
test clock-27.1 {seconds take precedence over naked weekday} -body {
list [clock scan {0 1} -format {%s %u} -gmt true -base 0] \
[clock scan {1 0} -format {%u %s} -gmt true -base 0]
} {*}$res
test clock-27.2 {julian day takes precedence over naked weekday} -body {
list [clock scan {2440588 1} -format {%J %u} -gmt true -base 0] \
[clock scan {1 2440588} -format {%u %J} -gmt true -base 0]
} {*}$res
test clock-27.3 {yyyymmdd over naked weekday} -body {
list [clock scan {19700101 1} -format {%Y%m%d %u} -gmt true -base 0] \
[clock scan {1 19700101} -format {%u %Y%m%d} -gmt true -base 0]
} {*}$res
test clock-27.4 {yyyyddd over naked weekday} -body {
list [clock scan {1970001 1} -format {%Y%j %u} -gmt true -base 0] \
[clock scan {1 1970001} -format {%u %Y%j} -gmt true -base 0]
} {*}$res
test clock-27.5 {yymmdd over naked weekday} -body {
list [clock scan {700101 1} -format {%y%m%d %u} -gmt true -base 0] \
[clock scan {1 700101} -format {%u %y%m%d} -gmt true -base 0]
} {*}$res
test clock-27.6 {yyddd over naked weekday} -body {
list [clock scan {70001 1} -format {%y%j %u} -gmt true -base 0] \
[clock scan {1 70001} -format {%u %y%j} -gmt true -base 0]
} {*}$res
test clock-27.7 {mmdd over naked weekday} -body {
list [clock scan {0101 1} -format {%m%d %u} -gmt true -base 0] \
[clock scan {1 0101} -format {%u %m%d} -gmt true -base 0]
} {*}$res
test clock-27.8 {ddd over naked weekday} -body {
list [clock scan {001 1} -format {%j %u} -gmt true -base 0] \
[clock scan {1 001} -format {%u %j} -gmt true -base 0]
} {*}$res
test clock-27.9 {naked day of month over naked weekday} -body {
list [clock scan {01 1} -format {%d %u} -gmt true -base 0] \
[clock scan {1 01} -format {%u %d} -gmt true -base 0]
} {*}$res
unset -nocomplain res
test clock-28.1 {base date} {
clock scan {} -format {} -gmt true -base 1234567890
} 1234483200
# BEGIN testcases29
|
| ︙ | ︙ | |||
34979 34980 34981 34982 34983 34984 34985 34986 34987 34988 34989 34990 34991 34992 34993 34994 |
-format {%J %Ol:%M:%S %P}
} 86399
test clock-29.1800 {time parsing} {
clock scan {2440588 xi:lix:lix pm} \
-gmt true -locale en_US_roman \
-format {%J %Ol:%OM:%OS %P}
} 86399
# END testcases29
test clock-30.1 {clock add years} {
set t [clock scan 2000-01-01 -format %Y-%m-%d -timezone :UTC]
set f [clock add $t 1 year -timezone :UTC]
clock format $f -format %Y-%m-%d -timezone :UTC
} {2001-01-01}
test clock-30.2 {clock add years - leap day} {
set t [clock scan 2000-02-29 -format %Y-%m-%d -timezone :UTC]
| > > > > > > > > > > > > > > > > > > > > > > > > > > > | 35468 35469 35470 35471 35472 35473 35474 35475 35476 35477 35478 35479 35480 35481 35482 35483 35484 35485 35486 35487 35488 35489 35490 35491 35492 35493 35494 35495 35496 35497 35498 35499 35500 35501 35502 35503 35504 35505 35506 35507 35508 35509 35510 |
-format {%J %Ol:%M:%S %P}
} 86399
test clock-29.1800 {time parsing} {
clock scan {2440588 xi:lix:lix pm} \
-gmt true -locale en_US_roman \
-format {%J %Ol:%OM:%OS %P}
} 86399
test clock-29.1811 {parsing of several localized formats} {
set res {}
foreach loc {en de fr} {
foreach fmt {"%x %X" "%X %x"} {
lappend res [clock scan \
[clock format 0 -format $fmt -locale $loc -gmt 1] \
-format $fmt -locale $loc -gmt 1]
}
}
set res
} [lrepeat 6 0]
test clock-29.1812 {parsing of several localized formats} {
set res {}
foreach loc {en de fr} {
foreach fmt {"%a %d-%m-%Y" "%a %b %x-%X" "%a, %x %X" "%b, %x %X"} {
lappend res [clock scan \
[clock format 0 -format $fmt -locale $loc -gmt 1] \
-format $fmt -locale $loc -gmt 1]
}
}
set res
} [lrepeat 12 0]
# END testcases29
# BEGIN testcases30
# Test [clock add]
test clock-30.1 {clock add years} {
set t [clock scan 2000-01-01 -format %Y-%m-%d -timezone :UTC]
set f [clock add $t 1 year -timezone :UTC]
clock format $f -format %Y-%m-%d -timezone :UTC
} {2001-01-01}
test clock-30.2 {clock add years - leap day} {
set t [clock scan 2000-02-29 -format %Y-%m-%d -timezone :UTC]
|
| ︙ | ︙ | |||
35225 35226 35227 35228 35229 35230 35231 35232 35233 35234 35235 35236 35237 35238 |
set t [clock scan {2004-10-31 01:00:00 -0400} \
-format {%Y-%m-%d %H:%M:%S %z} \
-timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
set f1 [clock add $t 3600 seconds -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
-timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
} {2004-10-31 01:00:00 -0500}
test clock-31.1 {system locale} \
-constraints win \
-setup {
namespace eval ::tcl::clock {
namespace import -force ::testClock::registry
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 35741 35742 35743 35744 35745 35746 35747 35748 35749 35750 35751 35752 35753 35754 35755 35756 35757 35758 35759 35760 35761 35762 35763 35764 35765 35766 35767 35768 35769 35770 35771 35772 35773 35774 35775 35776 35777 35778 35779 35780 35781 35782 35783 35784 35785 35786 35787 35788 35789 35790 35791 35792 35793 35794 35795 35796 35797 35798 35799 35800 35801 35802 35803 35804 35805 35806 35807 35808 35809 35810 35811 35812 35813 35814 35815 35816 35817 35818 35819 35820 35821 35822 35823 35824 35825 35826 35827 35828 35829 35830 35831 35832 35833 35834 35835 35836 35837 35838 35839 35840 35841 35842 35843 |
set t [clock scan {2004-10-31 01:00:00 -0400} \
-format {%Y-%m-%d %H:%M:%S %z} \
-timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
set f1 [clock add $t 3600 seconds -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
-timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
} {2004-10-31 01:00:00 -0500}
test clock-30.26 {clock add weekdays} {
set t [clock scan {2013-11-20}] ;# Wednesday
set f1 [clock add $t 3 weekdays]
set x1 [clock format $f1 -format {%Y-%m-%d}]
} {2013-11-25}
test clock-30.27 {clock add weekdays starting on Saturday} {
set t [clock scan {2013-11-23}] ;# Saturday
set f1 [clock add $t 1 weekday]
set x1 [clock format $f1 -format {%Y-%m-%d}]
} {2013-11-25}
test clock-30.28 {clock add weekdays starting on Sunday} {
set t [clock scan {2013-11-24}] ;# Sunday
set f1 [clock add $t 1 weekday]
set x1 [clock format $f1 -format {%Y-%m-%d}]
} {2013-11-25}
test clock-30.29 {clock add 0 weekdays starting on a weekend} {
set t [clock scan {2016-02-27}] ;# Saturday
set f1 [clock add $t 0 weekdays]
set x1 [clock format $f1 -format {%Y-%m-%d}]
} {2016-02-27}
test clock-30.30 {clock add weekdays and back} -body {
set n [clock seconds]
# we start on each day of the week
for {set i 0} {$i < 7} {incr i} {
set start [clock add $n $i days]
set startu [clock format $start -format %u]
# add 0 - 100 weekdays
for {set j 0} {$j < 100} {incr j} {
set forth [clock add $start $j weekdays]
set back [clock add $forth -$j weekdays]
# If $s was a weekday or $j was 0, $b must be the same day.
# Otherwise, $b must be the immediately preceeding Friday
set fail 0
if {$j == 0 || $startu < 6} {
if {$start != $back} { set fail 1}
} else {
set friday [clock add $start -[expr {$startu % 5}] days]
if {$friday != $back} { set fail 1 }
}
if {$fail} {
set sdate [clock format $start -format {%Y-%m-%d}]
set bdate [clock format $back -format {%Y-%m-%d}]
return "$sdate + $j - $j := $bdate"
}
}
}
return "OK"
} -result {OK}
test clock-30.31 {regression test - add no int overflow} {
list \
[list \
[clock add 0 1600000000 seconds 24856 days -gmt 1] \
[clock add 0 1600000000 seconds 815 months -gmt 1] \
[clock add 0 1600000000 seconds 69 years -gmt 1] \
[clock add 0 1600000000 seconds 596524 hours -gmt 1] \
[clock add 0 1600000000 seconds 35791395 minutes -gmt 1] \
[clock add 0 1600000000 seconds 0x7fffffff seconds -gmt 1]
] \
[list \
[clock add 1600000000 24856 days -gmt 1] \
[clock add 1600000000 815 months -gmt 1] \
[clock add 1600000000 69 years -gmt 1] \
[clock add 1600000000 596524 hours -gmt 1] \
[clock add 1600000000 35791395 minutes -gmt 1] \
[clock add 1600000000 0x7fffffff seconds -gmt 1]
]
} [lrepeat 2 {3747558400 3743238400 3777452800 3747486400 3747483700 3747483647}]
test clock-30.32 {regression test - add no int overflow} {
list \
[list \
[clock add 3777452800 -1600000000 seconds -24856 days -gmt 1] \
[clock add 3777452800 -1600000000 seconds -815 months -gmt 1] \
[clock add 3777452800 -1600000000 seconds -69 years -gmt 1] \
[clock add 3777452800 -1600000000 seconds -596524 hours -gmt 1] \
[clock add 3777452800 -1600000000 seconds -35791395 minutes -gmt 1] \
[clock add 3777452800 -1600000000 seconds -0x7fffffff seconds -gmt 1]
] \
[list \
[clock add 2177452800 -24856 days -gmt 1] \
[clock add 2177452800 -815 months -gmt 1] \
[clock add 2177452800 -69 years -gmt 1] \
[clock add 2177452800 -596524 hours -gmt 1] \
[clock add 2177452800 -35791395 minutes -gmt 1] \
[clock add 2177452800 -0x7fffffff seconds -gmt 1]
]
} [lrepeat 2 {29894400 34214400 0 29966400 29969100 29969153}]
# END testcases30
test clock-31.1 {system locale} \
-constraints win \
-setup {
namespace eval ::tcl::clock {
namespace import -force ::testClock::registry
}
|
| ︙ | ︙ | |||
35594 35595 35596 35597 35598 35599 35600 35601 35602 |
if { $t3 == $t1 } break
set t1 $t3
}
expr { $t2 / 1000 == $t3 }
} {1}
# clock scan
test clock-34.1 {clock scan tests} {
list [catch {clock scan} msg] $msg
| > | | 36199 36200 36201 36202 36203 36204 36205 36206 36207 36208 36209 36210 36211 36212 36213 36214 36215 36216 |
if { $t3 == $t1 } break
set t1 $t3
}
expr { $t2 / 1000 == $t3 }
} {1}
# clock scan
set syntax "clock scan string ?-base seconds? ?-format string? ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE? ?-validate boolean?"
test clock-34.1 {clock scan tests} {
list [catch {clock scan} msg] $msg
} [subst {1 {wrong # args: should be "$syntax"}}]
test clock-34.2 {clock scan tests} {*}{
-body {clock scan "bad-string"}
-returnCodes error
-match glob
-result {unable to convert date-time string "bad-string"*}
}
test clock-34.3 {clock scan tests} {
|
| ︙ | ︙ | |||
35630 35631 35632 35633 35634 35635 35636 |
} {Oct 23,1992 15:00 GMT}
test clock-34.8 {clock scan tests} {
set time [clock scan "Oct 23,1992 15:00" -gmt true]
clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Oct 23,1992 15:00 GMT}
test clock-34.9 {clock scan tests} {
list [catch {clock scan "Jan 12" -bad arg} msg] $msg
| | > > > > > > > > > | | > | | | | | | | | > > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 36236 36237 36238 36239 36240 36241 36242 36243 36244 36245 36246 36247 36248 36249 36250 36251 36252 36253 36254 36255 36256 36257 36258 36259 36260 36261 36262 36263 36264 36265 36266 36267 36268 36269 36270 36271 36272 36273 36274 36275 36276 36277 36278 36279 36280 36281 36282 36283 36284 36285 36286 36287 36288 36289 36290 36291 36292 36293 36294 36295 36296 36297 36298 36299 36300 36301 36302 36303 36304 36305 36306 36307 36308 36309 36310 36311 36312 36313 36314 36315 36316 36317 36318 36319 36320 36321 36322 36323 36324 36325 36326 36327 36328 36329 36330 36331 36332 36333 36334 36335 36336 36337 36338 36339 36340 36341 36342 36343 36344 36345 36346 36347 36348 36349 36350 36351 36352 36353 36354 36355 36356 36357 36358 36359 36360 36361 36362 36363 36364 36365 36366 36367 36368 36369 36370 36371 36372 36373 36374 36375 36376 36377 36378 36379 36380 36381 36382 36383 36384 36385 36386 36387 36388 36389 36390 36391 36392 36393 36394 36395 36396 36397 36398 36399 36400 36401 36402 36403 36404 36405 36406 36407 36408 36409 36410 36411 36412 36413 36414 36415 36416 36417 36418 36419 36420 36421 36422 36423 36424 36425 36426 36427 36428 36429 36430 36431 36432 36433 36434 36435 36436 36437 36438 36439 36440 36441 36442 36443 36444 36445 36446 36447 36448 36449 36450 36451 36452 36453 36454 36455 36456 |
} {Oct 23,1992 15:00 GMT}
test clock-34.8 {clock scan tests} {
set time [clock scan "Oct 23,1992 15:00" -gmt true]
clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Oct 23,1992 15:00 GMT}
test clock-34.9 {clock scan tests} {
list [catch {clock scan "Jan 12" -bad arg} msg] $msg
} [subst {1 {bad option "-bad": must be -base, -format, -gmt, -locale, -timezone or -validate}}]
# The following two two tests test the two year date policy
test clock-34.10 {clock scan tests} {
set time [clock scan "1/1/71" -gmt true]
clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Jan 01,1971 00:00 GMT}
test clock-34.11 {clock scan tests} {
set time [clock scan "1/1/37" -gmt true]
clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Jan 01,2037 00:00 GMT}
test clock-34.11.1 {clock scan tests: same century switch} {
set times [clock scan "1/1/37" -gmt true]
} [clock scan "1/1/37" -format "%m/%d/%y" -gmt true]
test clock-34.11.2 {clock scan tests: same century switch} {
set times [clock scan "1/1/38" -gmt true]
} [clock scan "1/1/38" -format "%m/%d/%y" -gmt true]
test clock-34.11.3 {clock scan tests: same century switch} {
set times [clock scan "1/1/39" -gmt true]
} [clock scan "1/1/39" -format "%m/%d/%y" -gmt true]
test clock-34.12 {clock scan, relative times} {
set time [clock scan "Oct 23, 1992 -1 day" -gmt true]
clock format $time -format {%b %d, %Y} -gmt true
} "Oct 22, 1992"
test clock-34.13 {clock scan, ISO 8601 base date format} {
set time [clock scan "19921023" -gmt true]
clock format $time -format {%b %d, %Y} -gmt true
} "Oct 23, 1992"
test clock-34.14 {clock scan, ISO 8601 expanded date format} {
set time [clock scan "1992-10-23" -gmt true]
clock format $time -format {%b %d, %Y} -gmt true
} "Oct 23, 1992"
test clock-34.15 {clock scan, DD-Mon-YYYY format} {
set time [clock scan "23-Oct-1992" -gmt true]
clock format $time -format {%b %d, %Y} -gmt true
} "Oct 23, 1992"
test clock-34.16 {clock scan, ISO 8601 point in time format} {
set time [clock scan "19921023T235959" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.16.1a {clock scan, ISO 8601 T literal optional (YYYYMMDDhhmmss)} {
set time [clock scan "19921023235959" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.16.1b {clock scan, ISO 8601 T literal optional (YYYYMMDDhhmm)} {
set time [clock scan "199210232359" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:00"
test clock-34.16.2 {clock scan, ISO 8601 extended date time} {
set time [clock scan "1992-10-23T23:59:59" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.17 {clock scan, ISO 8601 point in time format} {
set time [clock scan "19921023 235959" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.17.2a {clock scan, ISO 8601 extended date time (YYYY-MM-DD hh:mm:ss)} {
set time [clock scan "1992-10-23 23:59:59" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.17.2b {clock scan, ISO 8601 extended date time (YYYY-MM-DDThh:mm:ss)} {
set time [clock scan "1992-10-23T23:59:59" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.17.2c {clock scan, ISO 8601 extended date time (YYYY-MM-DD hh:mm)} {
set time [clock scan "1992-10-23 23:59" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:00"
test clock-34.17.2d {clock scan, ISO 8601 extended date time (YYYY-MM-DDThh:mm)} {
set time [clock scan "1992-10-23T23:59" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:00"
test clock-34.17.3 {clock scan, TZ-word boundaries - Z is not TZ here } -body {
set time [clock scan "1992-10-23Z23:59:59" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} -returnCodes error -match glob \
-result {unable to convert date-time string*}
test clock-34.17.4 {clock scan, TZ-word boundaries - Z is TZ UTC here} {
set time [clock scan "1992-10-23 Z 23:59:59" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.17.5 {clock scan, ISO 8601 extended date time with UTC TZ} {
set time [clock scan "1992-10-23T23:59:59Z" -timezone :America/Detroit]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.18 {clock scan, ISO 8601 point in time format} {
set time [clock scan "19921023T000000" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 00:00:00"
test clock-34.18.2 {clock scan, ISO 8601 extended date time} {
set time [clock scan "1992-10-23T00:00:00" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 00:00:00"
test clock-34.18.3 {clock scan, TZ-word boundaries - Z is not TZ here } -body {
set time [clock scan "1992-10-23Z00:00:00" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} -returnCodes error -match glob \
-result {unable to convert date-time string*}
test clock-34.18.4 {clock scan, TZ-word boundaries - Z is TZ UTC here} {
set time [clock scan "1992-10-23 Z 00:00:00" -gmt true]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 00:00:00"
test clock-34.18.5 {clock scan, ISO 8601 extended date time with UTC TZ} {
set time [clock scan "1992-10-23T00:00:00Z" -timezone :America/Detroit]
clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 00:00:00"
test clock-34.20.1 {clock scan tests (-TZ)} {
set time [clock scan "31 Jan 14 23:59:59 -0100" -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Feb 01,2014 00:59:59 GMT}
test clock-34.20.2 {clock scan tests (+TZ)} {
set time [clock scan "31 Jan 14 23:59:59 +0100" -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 31,2014 22:59:59 GMT}
test clock-34.20.3 {clock scan tests (-TZ)} {
set time [clock scan "23:59:59 -0100" -base 0 -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 02,1970 00:59:59 GMT}
test clock-34.20.4 {clock scan tests (+TZ)} {
set time [clock scan "23:59:59 +0100" -base 0 -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 01,1970 22:59:59 GMT}
test clock-34.20.5 {clock scan tests (TZ)} {
set time [clock scan "Mon, 30 Jun 2014 23:59:59 CEST" -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jun 30,2014 21:59:59 GMT}
test clock-34.20.6 {clock scan tests (TZ)} {
set time [clock scan "Fri, 31 Jan 2014 23:59:59 CET" -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 31,2014 22:59:59 GMT}
test clock-34.20.7 {clock scan tests (relspec, day unit not TZ)} {
set time [clock scan "23:59:59 +15 day" -base 2000000 -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Feb 08,1970 23:59:59 GMT}
test clock-34.20.8 {clock scan tests (relspec, day unit not TZ)} {
set time [clock scan "23:59:59 -15 day" -base 2000000 -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 09,1970 23:59:59 GMT}
test clock-34.20.9 {clock scan tests (merid and TZ)} {
set time [clock scan "10:59 pm CET" -base 2000000 -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 24,1970 21:59:00 GMT}
test clock-34.20.10 {clock scan tests (merid and TZ)} {
set time [clock scan "10:59 pm +0100" -base 2000000 -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 24,1970 21:59:00 GMT}
test clock-34.20.11 {clock scan tests (complex TZ)} {
list [clock scan "GMT+1000" -base 100000000 -gmt 1] \
[clock scan "GMT+10" -base 100000000 -gmt 1] \
[clock scan "+1000" -base 100000000 -gmt 1]
} [lrepeat 3 99964000]
test clock-34.20.12 {clock scan tests (complex TZ)} {
list [clock scan "GMT-1000" -base 100000000 -gmt 1] \
[clock scan "GMT-10" -base 100000000 -gmt 1] \
[clock scan "-1000" -base 100000000 -gmt 1]
} [lrepeat 3 100036000]
test clock-34.20.13 {clock scan tests (complex TZ)} {
list [clock scan "GMT-0000" -base 100000000 -gmt 1] \
[clock scan "GMT+0000" -base 100000000 -gmt 1] \
[clock scan "GMT" -base 100000000 -gmt 1]
} [lrepeat 3 100000000]
test clock-34.20.14 {clock scan tests (complex TZ)} {
list [clock scan "CET+1000" -base 100000000 -gmt 1] \
[clock scan "CET-1000" -base 100000000 -gmt 1]
} {99960400 100032400}
test clock-34.20.15 {clock scan tests (complex TZ)} {
list [clock scan "CET-0000" -base 100000000 -gmt 1] \
[clock scan "CET+0000" -base 100000000 -gmt 1] \
[clock scan "CET" -base 100000000 -gmt 1]
} [lrepeat 3 99996400]
test clock-34.20.16 {clock scan tests (complex TZ)} {
list [clock format [clock scan "00:00 GMT+1000" -base 100000000 -gmt 1] -gmt 1] \
[clock format [clock scan "00:00 GMT+10" -base 100000000 -gmt 1] -gmt 1] \
[clock format [clock scan "00:00 +1000" -base 100000000 -gmt 1] -gmt 1] \
[clock format [clock scan "00:00" -base 100000000 -timezone +1000] -gmt 1]
} [lrepeat 4 "Fri Mar 02 14:00:00 GMT 1973"]
test clock-34.20.17 {clock scan tests (complex TZ)} {
list [clock format [clock scan "00:00 GMT+0100" -base 100000000 -gmt 1] -gmt 1] \
[clock format [clock scan "00:00 GMT+01" -base 100000000 -gmt 1] -gmt 1] \
[clock format [clock scan "00:00 GMT+1" -base 100000000 -gmt 1] -gmt 1] \
[clock format [clock scan "00:00" -base 100000000 -timezone +0100] -gmt 1]
} [lrepeat 4 "Fri Mar 02 23:00:00 GMT 1973"]
test clock-34.20.18 {clock scan tests (no TZ)} {
list [clock scan "1000days" -base 100000000 -gmt 1] \
[clock scan "1000 days" -base 100000000 -gmt 1] \
[clock scan "+1000days" -base 100000000 -gmt 1] \
[clock scan "+1000 days" -base 100000000 -gmt 1] \
[clock scan "GMT +1000 days" -base 100000000 -gmt 1] \
[clock scan "00:00 GMT +1000 days" -base 100000000 -gmt 1]
} [lrepeat 6 186364800]
test clock-34.20.19 {clock scan tests (no TZ)} {
list [clock scan "-1000days" -base 100000000 -gmt 1] \
[clock scan "-1000 days" -base 100000000 -gmt 1] \
[clock scan "GMT -1000days" -base 100000000 -gmt 1] \
[clock scan "00:00 GMT -1000 days" -base 100000000 -gmt 1] \
} [lrepeat 4 13564800]
test clock-34.20.20 {clock scan tests (TZ, TZ + 1day)} {
clock scan "00:00 GMT+1000 day" -base 100000000 -gmt 1
} 100015200
test clock-34.20.21 {clock scan tests (local date of base depends on given TZ, time apllied to different day)} {
list [clock scan "23:59:59 -0100" -base 0 -timezone :CET] \
[clock scan "23:59:59 -0100" -base 0 -gmt 1] \
[clock scan "23:59:59 -0100" -base 0 -timezone -1400] \
[clock scan "23:59:59 -0100" -base 0 -timezone :Pacific/Apia]
} {89999 89999 3599 3599}
# CLOCK SCAN REAL TESTS
# We use 5am PST, 31-12-1999 as the base for these scans because irrespective
# of your local timezone it should always give us times on December 31, 1999
set 5amPST 946645200
test clock-34.19 {clock scan, number meridian} {
set t1 [clock scan "5 am" -base $5amPST -gmt true]
|
| ︙ | ︙ | |||
35762 35763 35764 35765 35766 35767 35768 35769 35770 35771 35772 35773 35774 35775 |
clock format [clock scan "thursday" -base [clock scan 20000112]] \
-format {%b %d, %Y}
} "Jan 13, 2000"
test clock-34.40 {clock scan, next day of week} {
clock format [clock scan "next thursday" -base [clock scan 20000112]] \
-format {%b %d, %Y}
} "Jan 20, 2000"
# weekday specification and base.
test clock-34.41 {2nd monday in november} {
set res {}
foreach i {91 92 93 94 95 96} {
set nov8th [clock scan 11/8/$i]
set monday [clock scan monday -base $nov8th]
| > > > > > > > > > > > > > > > > > > > > > | 36537 36538 36539 36540 36541 36542 36543 36544 36545 36546 36547 36548 36549 36550 36551 36552 36553 36554 36555 36556 36557 36558 36559 36560 36561 36562 36563 36564 36565 36566 36567 36568 36569 36570 36571 |
clock format [clock scan "thursday" -base [clock scan 20000112]] \
-format {%b %d, %Y}
} "Jan 13, 2000"
test clock-34.40 {clock scan, next day of week} {
clock format [clock scan "next thursday" -base [clock scan 20000112]] \
-format {%b %d, %Y}
} "Jan 20, 2000"
test clock-34.40.1 {clock scan, ordinal month after relative date} {
# This will fail without the bug fix (clock.tcl), as still missing
# month/julian day conversion before ordinal month increment
clock format [ \
clock scan "5 years 18 months 387 days" -base 0 -gmt 1
] -format {%a, %b %d, %Y} -gmt 1 -locale en_US_roman
} "Sat, Jul 23, 1977"
test clock-34.40.2 {clock scan, ordinal month after relative date} {
# This will fail without the bug fix (clock.tcl), as still missing
# month/julian day conversion before ordinal month increment
clock format [ \
clock scan "5 years 18 months 387 days next Jan" -base 0 -gmt 1
] -format {%a, %b %d, %Y} -gmt 1 -locale en_US_roman
} "Mon, Jan 23, 1978"
test clock-34.40.3 {clock scan, day of week after ordinal date} {
# This will fail without the bug fix (clock.tcl), because the relative
# week day should be applied after whole date conversion
clock format [ \
clock scan "5 years 18 months 387 days next January Fri" -base 0 -gmt 1
] -format {%a, %b %d, %Y} -gmt 1 -locale en_US_roman
} "Fri, Jan 27, 1978"
# weekday specification and base.
test clock-34.41 {2nd monday in november} {
set res {}
foreach i {91 92 93 94 95 96} {
set nov8th [clock scan 11/8/$i]
set monday [clock scan monday -base $nov8th]
|
| ︙ | ︙ | |||
35912 35913 35914 35915 35916 35917 35918 35919 35920 35921 35922 35923 35924 35925 |
set time [clock scan "10:59 pm CET" -base 2000000 -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 24,1970 21:59:00 GMT}
test clock-34.68 {clock scan tests (merid and TZ)} {
set time [clock scan "10:59 pm +0100" -base 2000000 -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 24,1970 21:59:00 GMT}
# clock seconds
test clock-35.1 {clock seconds tests} {
expr {[clock seconds] + 1}
concat {}
} {}
test clock-35.2 {clock seconds tests} {
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 36708 36709 36710 36711 36712 36713 36714 36715 36716 36717 36718 36719 36720 36721 36722 36723 36724 36725 36726 36727 36728 36729 36730 36731 36732 36733 36734 36735 36736 36737 36738 36739 36740 36741 36742 36743 36744 36745 36746 36747 36748 36749 36750 36751 36752 36753 36754 36755 36756 36757 36758 36759 36760 36761 36762 36763 36764 36765 36766 36767 36768 36769 36770 36771 36772 36773 36774 36775 36776 36777 36778 36779 36780 36781 36782 36783 36784 36785 36786 36787 36788 36789 36790 36791 36792 36793 36794 36795 36796 36797 36798 36799 36800 36801 36802 36803 36804 36805 36806 36807 36808 36809 |
set time [clock scan "10:59 pm CET" -base 2000000 -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 24,1970 21:59:00 GMT}
test clock-34.68 {clock scan tests (merid and TZ)} {
set time [clock scan "10:59 pm +0100" -base 2000000 -gmt true]
clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 24,1970 21:59:00 GMT}
test clock-34.69.1 {relative from base, date switch} {
set base [clock scan "12/31/2016 23:59:59" -gmt 1]
clock format [clock scan "+1 second" \
-base $base -gmt 1] -gmt 1 -format {%Y-%m-%d %H:%M:%S}
} {2017-01-01 00:00:00}
test clock-34.69.2 {relative time, daylight switch} {
set base [clock scan "03/27/2016" -timezone CET]
set res {}
lappend res [clock format [clock scan "+1 hour" \
-base $base -timezone CET] -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]
lappend res [clock format [clock scan "+2 hour" \
-base $base -timezone CET] -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]
} {{2016-03-27 01:00:00 CET} {2016-03-27 03:00:00 CEST}}
test clock-34.69.3 {relative time with day increment / daylight switch} {
set base [clock scan "03/27/2016" -timezone CET]
set res {}
lappend res [clock format [clock scan "+5 day +25 hour" \
-base [expr {$base - 6*24*60*60}] -timezone CET] -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]
lappend res [clock format [clock scan "+5 day +26 hour" \
-base [expr {$base - 6*24*60*60}] -timezone CET] -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]
} {{2016-03-27 01:00:00 CET} {2016-03-27 03:00:00 CEST}}
test clock-34.69.4 {relative time with month & day increment / daylight switch} {
set base [clock scan "03/27/2016" -timezone CET]
set res {}
lappend res [clock format [clock scan "next Mar +5 day +25 hour" \
-base [expr {$base - 35*24*60*60}] -timezone CET] -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]
lappend res [clock format [clock scan "next Mar +5 day +26 hour" \
-base [expr {$base - 35*24*60*60}] -timezone CET] -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]
} {{2016-03-27 01:00:00 CET} {2016-03-27 03:00:00 CEST}}
test clock-34.70.1 {check date in DST-hole: daylight switch CET -> CEST} {
set res {}
# forwards
set base 1459033200
for {set i 0} {$i <= 3} {incr i} {
set d [clock scan "+$i hour" -base $base -timezone CET]
lappend res "$d = [clock format $d -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]"
}
lappend res "#--"
# backwards
set base 1459044000
for {set i 0} {$i <= 3} {incr i} {
set d [clock scan "-$i hour" -base $base -timezone CET]
lappend res "$d = [clock format $d -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]"
}
set res
} [split [regsub -all {^\n|\n$} {
1459033200 = 2016-03-27 00:00:00 CET
1459036800 = 2016-03-27 01:00:00 CET
1459040400 = 2016-03-27 03:00:00 CEST
1459044000 = 2016-03-27 04:00:00 CEST
#--
1459044000 = 2016-03-27 04:00:00 CEST
1459040400 = 2016-03-27 03:00:00 CEST
1459036800 = 2016-03-27 01:00:00 CET
1459033200 = 2016-03-27 00:00:00 CET
} {}] \n]
test clock-34.70.2 {check date in DST-hole: daylight switch CEST -> CET} {
set res {}
# forwards
set base 1477782000
for {set i 0} {$i <= 3} {incr i} {
set d [clock scan "+$i hour" -base $base -timezone CET]
lappend res "$d = [clock format $d -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]"
}
lappend res "#--"
# backwards
set base 1477792800
for {set i 0} {$i <= 3} {incr i} {
set d [clock scan "-$i hour" -base $base -timezone CET]
lappend res "$d = [clock format $d -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]"
}
set res
} [split [regsub -all {^\n|\n$} {
1477782000 = 2016-10-30 01:00:00 CEST
1477785600 = 2016-10-30 02:00:00 CEST
1477789200 = 2016-10-30 02:00:00 CET
1477792800 = 2016-10-30 03:00:00 CET
#--
1477792800 = 2016-10-30 03:00:00 CET
1477789200 = 2016-10-30 02:00:00 CET
1477785600 = 2016-10-30 02:00:00 CEST
1477782000 = 2016-10-30 01:00:00 CEST
} {}] \n]
# clock seconds
test clock-35.1 {clock seconds tests} {
expr {[clock seconds] + 1}
concat {}
} {}
test clock-35.2 {clock seconds tests} {
|
| ︙ | ︙ | |||
35943 35944 35945 35946 35947 35948 35949 |
} "07.2000"
test clock-36.3 {clock scan next monthname} {
clock format [clock scan "next may" -base [clock scan "june 1, 2000"]] \
-format %m.%Y
} "05.2001"
test clock-37.1 {%s gmt testing} {
| | > > | | > > > > > > > > > > > > > > > > > > | 36827 36828 36829 36830 36831 36832 36833 36834 36835 36836 36837 36838 36839 36840 36841 36842 36843 36844 36845 36846 36847 36848 36849 36850 36851 36852 36853 36854 36855 36856 36857 36858 36859 36860 36861 36862 36863 36864 36865 36866 36867 |
} "07.2000"
test clock-36.3 {clock scan next monthname} {
clock format [clock scan "next may" -base [clock scan "june 1, 2000"]] \
-format %m.%Y
} "05.2001"
test clock-37.1 {%s gmt testing} {
set s [clock scan "2017-05-10 09:00:00" -gmt 1]
set a [clock format $s -format %s -gmt 0]
set b [clock format $s -format %s -gmt 1]
set c [clock scan $s -format %s -gmt 0]
set d [clock scan $s -format %s -gmt 1]
# %s, being the difference between local and Greenwich, does not
# depend on the time zone.
list [expr {$b-$a}] [expr {$d-$c}]
} {0 0}
test clock-37.2 {%Es gmt testing CET} {
set s [clock scan "2017-01-10 09:00:00" -gmt 1]
set a [clock format $s -format %Es -timezone CET]
set b [clock format $s -format %Es -gmt 1]
set c [clock scan $s -format %Es -timezone CET]
set d [clock scan $s -format %Es -gmt 1]
# %Es depend on the time zone (local seconds instead of posix seconds).
list [expr {$b-$a}] [expr {$d-$c}]
} {-3600 3600}
test clock-37.3 {%Es gmt testing CEST} {
set s [clock scan "2017-05-10 09:00:00" -gmt 1]
set a [clock format $s -format %Es -timezone CET]
set b [clock format $s -format %Es -gmt 1]
set c [clock scan $s -format %Es -timezone CET]
set d [clock scan $s -format %Es -gmt 1]
# %Es depend on the time zone (local seconds instead of posix seconds).
list [expr {$b-$a}] [expr {$d-$c}]
} {-7200 7200}
test clock-38.1 {regression - convertUTCToLocalViaC - east of Greenwich} \
-setup {
if { [info exists env(TZ)] } {
set oldTZ $env(TZ)
}
set env(TZ) CET-01:00CEST-02:00,M3.5.0/02:00,M10.5.0/03:00
|
| ︙ | ︙ | |||
36003 36004 36005 36006 36007 36008 36009 36010 36011 36012 36013 36014 36015 36016 |
if { [info exists oldTclTZ] } {
set env(TCL_TZ) $oldTclTZ
unset oldTclTZ
}
} \
-result 1
test clock-39.1 {regression - synonym timezones} {
clock format 0 -format {%H:%M:%S} -timezone :US/Eastern
} {19:00:00}
test clock-40.1 {regression - bad month with -timezone :localtime} \
-setup {
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 36907 36908 36909 36910 36911 36912 36913 36914 36915 36916 36917 36918 36919 36920 36921 36922 36923 36924 36925 36926 36927 36928 36929 36930 36931 36932 36933 36934 36935 36936 36937 36938 36939 36940 36941 36942 36943 36944 36945 36946 36947 36948 36949 36950 36951 36952 36953 36954 36955 36956 36957 36958 36959 36960 36961 36962 36963 36964 36965 36966 |
if { [info exists oldTclTZ] } {
set env(TCL_TZ) $oldTclTZ
unset oldTclTZ
}
} \
-result 1
test clock-38.3sc {ensure cache of base is correct for :localtime if TZ-env changing / scan} \
-setup {
if { [info exists env(TZ)] } {
set oldTZ $env(TZ)
}
} \
-body {
set res {}
foreach env(TZ) {GMT-11:30 GMT-07:30 GMT-03:30 GMT} \
i {{07:30:00} {03:30:00} {23:30:00} {20:00:00}} \
{
lappend res [clock scan $i -format "%H:%M:%S" -base [expr {20*60*60}] -timezone :localtime]
}
set res
} \
-cleanup {
if { [info exists oldTZ] } {
set env(TZ) $oldTZ
unset oldTZ
} else {
unset env(TZ)
}
} \
-result [lrepeat 4 [expr {20*60*60}]]
test clock-38.3fm {ensure cache of base is correct for :localtime if TZ-env changing / format} \
-setup {
if { [info exists env(TZ)] } {
set oldTZ $env(TZ)
}
} \
-body {
set res {}
foreach env(TZ) {GMT-11:30 GMT-07:30 GMT-03:30 GMT} {
lappend res [clock format [expr {20*60*60}] -format "%Y-%m-%dT%H:%M:%S %Z" -timezone :localtime]
}
set res
} \
-cleanup {
if { [info exists oldTZ] } {
set env(TZ) $oldTZ
unset oldTZ
} else {
unset env(TZ)
}
} \
-result {{1970-01-02T07:30:00 +1130} {1970-01-02T03:30:00 +0730} {1970-01-01T23:30:00 +0330} {1970-01-01T20:00:00 +0000}}
test clock-39.1 {regression - synonym timezones} {
clock format 0 -format {%H:%M:%S} -timezone :US/Eastern
} {19:00:00}
test clock-40.1 {regression - bad month with -timezone :localtime} \
-setup {
|
| ︙ | ︙ | |||
36074 36075 36076 36077 36078 36079 36080 |
set env(TZ) $oldTZ
unset oldTZ
} else {
unset env(TZ)
}
} \
-result {12:34:56-0500}
| < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 37024 37025 37026 37027 37028 37029 37030 37031 37032 37033 37034 37035 37036 37037 37038 37039 37040 37041 37042 37043 37044 37045 37046 37047 37048 37049 37050 37051 37052 37053 37054 37055 37056 37057 37058 37059 37060 37061 37062 37063 37064 37065 37066 37067 37068 37069 37070 37071 37072 37073 37074 37075 37076 37077 37078 37079 37080 37081 37082 37083 37084 37085 37086 37087 37088 37089 37090 37091 37092 37093 37094 37095 37096 37097 37098 37099 37100 37101 37102 37103 37104 37105 37106 37107 37108 37109 37110 37111 37112 37113 37114 37115 37116 37117 37118 37119 37120 37121 37122 37123 37124 37125 37126 37127 37128 37129 37130 37131 37132 37133 37134 37135 37136 37137 37138 37139 37140 37141 37142 37143 37144 37145 37146 37147 37148 37149 37150 37151 37152 37153 37154 37155 37156 37157 37158 37159 37160 37161 37162 37163 37164 37165 37166 37167 37168 37169 37170 37171 37172 37173 37174 37175 37176 37177 37178 37179 37180 37181 37182 37183 37184 37185 37186 37187 37188 37189 37190 37191 37192 37193 37194 37195 37196 37197 37198 37199 37200 37201 37202 37203 37204 37205 37206 37207 37208 37209 37210 37211 37212 37213 37214 37215 37216 37217 37218 37219 37220 37221 37222 37223 37224 37225 37226 37227 37228 37229 37230 37231 37232 37233 37234 37235 37236 37237 37238 37239 37240 37241 37242 37243 37244 37245 37246 37247 37248 37249 37250 37251 37252 37253 37254 37255 37256 37257 37258 37259 37260 37261 37262 37263 37264 37265 37266 37267 37268 37269 37270 37271 37272 37273 37274 37275 37276 37277 37278 37279 37280 37281 37282 37283 37284 37285 37286 37287 37288 37289 37290 37291 37292 37293 37294 37295 37296 37297 37298 37299 37300 37301 37302 37303 37304 37305 37306 37307 37308 37309 37310 37311 37312 37313 37314 37315 37316 37317 37318 37319 37320 37321 37322 37323 37324 37325 37326 37327 37328 37329 37330 37331 37332 37333 37334 37335 37336 37337 37338 37339 37340 37341 37342 37343 37344 37345 37346 37347 37348 37349 37350 |
set env(TZ) $oldTZ
unset oldTZ
} else {
unset env(TZ)
}
} \
-result {12:34:56-0500}
test clock-44.2 {regression test - time zone containing only two digits} \
-body {
clock scan 1985-04-12T10:15:30+04 -format %Y-%m-%dT%H:%M:%S%Z
} \
-result 482134530
test clock-45.1 {compat: scan regression on spaces (multiple spaces in format)} \
-body {
list \
[clock scan "11/08/2018 0612" -format "%m/%d/%Y %H%M" -gmt 1] \
[clock scan "11/08/2018 0612" -format "%m/%d/%Y %H%M" -gmt 1] \
[clock scan "11/08/2018 0612" -format "%m/%d/%Y %H%M" -gmt 1] \
[clock scan " 11/08/2018 0612" -format " %m/%d/%Y %H%M" -gmt 1] \
[clock scan " 11/08/2018 0612" -format " %m/%d/%Y %H%M" -gmt 1] \
[clock scan " 11/08/2018 0612" -format " %m/%d/%Y %H%M" -gmt 1] \
[clock scan "11/08/2018 0612 " -format "%m/%d/%Y %H%M " -gmt 1] \
[clock scan "11/08/2018 0612 " -format "%m/%d/%Y %H%M " -gmt 1] \
[clock scan "11/08/2018 0612 " -format "%m/%d/%Y %H%M " -gmt 1]
} -result [lrepeat 9 1541657520]
test clock-45.2 {compat: scan regression on spaces (multiple leading/trailing spaces in input)} \
-body {
set sp [string repeat " " 20]
list \
[clock scan "NOV 7${sp}" -format "%b %d" -base 0 -gmt 1 -locale en] \
[clock scan "${sp}NOV 7" -format "%b %d" -base 0 -gmt 1 -locale en] \
[clock scan "${sp}NOV 7${sp}" -format "%b %d" -base 0 -gmt 1 -locale en] \
[clock scan "1970 NOV 7${sp}" -format "%Y %b %d" -gmt 1 -locale en] \
[clock scan "${sp}1970 NOV 7" -format "%Y %b %d" -gmt 1 -locale en] \
[clock scan "${sp}1970 NOV 7${sp}" -format "%Y %b %d" -gmt 1 -locale en]
} -result [lrepeat 6 26784000]
test clock-45.3 {compat: scan regression on spaces (shortest match)} \
-body {
list \
[clock scan "11 1 120" -format "%y%m%d %H%M%S" -gmt 1] \
[clock scan "11 1 120 " -format "%y%m%d %H%M%S" -gmt 1] \
[clock scan " 11 1 120" -format "%y%m%d %H%M%S" -gmt 1] \
[clock scan "11 1 120 " -format "%y%m%d %H%M%S " -gmt 1] \
[clock scan " 11 1 120" -format " %y%m%d %H%M%S" -gmt 1]
} -result [lrepeat 5 978310920]
test clock-45.4 {compat: scan regression on spaces (mandatory leading/trailing spaces in format)} \
-body {
list \
[catch {clock scan "11 1 120" -format "%y%m%d %H%M%S " -gmt 1} ret] $ret \
[catch {clock scan "11 1 120" -format " %y%m%d %H%M%S" -gmt 1} ret] $ret \
[catch {clock scan "11 1 120" -format " %y%m%d %H%M%S " -gmt 1} ret] $ret
} -result [lrepeat 3 1 "input string does not match supplied format"]
test clock-45.5 {regression test - freescan no int overflow} {
# note that the relative date changes currently reset the time to 00:00,
# this can be changed later (simply achievable by adding 00:00 if expected):
list \
[clock scan "+24856 days" -base 1600000000 -gmt 1] \
[clock scan "+815 months" -base 1600000000 -gmt 1] \
[clock scan "+69 years" -base 1600000000 -gmt 1] \
[clock scan "+596524 hours" -base 1600000000 -gmt 1] \
[clock scan "+35791395 minutes" -base 1600000000 -gmt 1] \
[clock scan "+2147483647 seconds" -base 1600000000 -gmt 1]
} {3747513600 3743193600 3777408000 3747486400 3747483700 3747483647}
test clock-45.6 {regression test - freescan no int overflow} {
# note that the relative date changes currently reset the time to 00:00,
# this can be changed later (simply achievable by adding 00:00 if expected):
list \
[clock scan "-24856 days" -base 2177452800 -gmt 1] \
[clock scan "-815 months" -base 2177452800 -gmt 1] \
[clock scan "-69 years" -base 2177452800 -gmt 1] \
[clock scan "-596524 hours" -base 2177452800 -gmt 1] \
[clock scan "-35791395 minutes" -base 2177452800 -gmt 1] \
[clock scan "-2147483647 seconds" -base 2177452800 -gmt 1]
} {29894400 34214400 0 29966400 29969100 29969153}
test clock-46.1 {regression test - month zero} -constraints valid_off \
-body {
clock scan 2004-00-00 -format %Y-%m-%d
} -result [clock scan 2003-11-30 -format %Y-%m-%d]
test clock-46.2 {regression test - month zero} -constraints valid_off \
-body {
clock scan 20040000
} -result [clock scan 2003-11-30 -format %Y-%m-%d]
test clock-46.3 {regression test - month thirteen} -constraints valid_off \
-body {
clock scan 2004-13-01 -format %Y-%m-%d
} -result [clock scan 2005-01-01 -format %Y-%m-%d]
test clock-46.4 {regression test - month thirteen} -constraints valid_off \
-body {
clock scan 20041301
} -result [clock scan 2005-01-01 -format %Y-%m-%d]
test clock-46.5 {regression test - good time} \
-body {
# 12:01 apm are valid input strings...
list [clock scan "12:01 am" -base 0 -gmt 1] \
[clock scan "12:01 pm" -base 0 -gmt 1]
} -result {60 43260}
test clock-46.6 {freescan: regression test - bad time} -constraints valid_off \
-body {
# 13:00 am/pm are invalid input strings...
list [clock scan "13:00 am" -base 0 -gmt 1] \
[clock scan "13:00 pm" -base 0 -gmt 1]
} -result {-1 -1}
proc _invalid_test {args} {
global valid_mode
# ensure validation works TZ independently, since the conversion
# of local time to UTC may adjust date/time tokens, depending on TZ:
set res {}
foreach tz {:GMT :CET {} :Europe/Berlin :localtime} {
foreach {v} $args {
if {$valid_mode} { # globally -valid 1
lappend res [catch {clock scan $v -timezone $tz} msg] $msg
} else {
lappend res [catch {clock scan $v -valid 1 -timezone $tz} msg] $msg
}
}
}
set res
}
# test without and with relative offsets:
foreach {idx relstr} {"" "" "+rel" "+ 15 month + 40 days + 30 hours + 80 minutes +9999 seconds"} {
test clock-46.10$idx {freescan: validation rules: invalid time} \
-body {
# 13:00 am/pm are invalid input strings...
_invalid_test "13:00 am$relstr" "13:00 pm$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid time (hour)}]
test clock-46.11$idx {freescan: validation rules: invalid time} \
-body {
# invalid minutes in input strings...
_invalid_test "23:70$relstr" "11:80 pm$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid time (minutes)}]
test clock-46.12$idx {freescan: validation rules: invalid time} \
-body {
# invalid seconds in input strings...
_invalid_test "23:00:70$relstr" "11:00:80 pm$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid time}]
test clock-46.13$idx {freescan: validation rules: invalid day} \
-body {
_invalid_test "29 Feb 2017$relstr" "30 Feb 2016$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.14$idx {freescan: validation rules: invalid day} \
-body {
_invalid_test "0 Feb 2017$relstr" "00 Feb 2017$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.15$idx {freescan: validation rules: invalid month} \
-body {
_invalid_test "13/13/2017$relstr" "00/00/2017$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid month}]
test clock-46.16$idx {freescan: validation rules: invalid day of week} \
-body {
_invalid_test "Sat Jan 02 00:00:00 1970$relstr" "Thu Jan 04 00:00:00 1970$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid day of week}]
test clock-46.17$idx {scan: validation rules: invalid year} -setup {
set orgcfg [list -min-year [::tcl::unsupported::clock::configure -min-year] -max-year [::tcl::unsupported::clock::configure -max-year] \
-year-century [::tcl::unsupported::clock::configure -year-century] -century-switch [::tcl::unsupported::clock::configure -century-switch]]
::tcl::unsupported::clock::configure -min-year 2000 -max-year 2100 -year-century 2000 -century-switch 38
} -body {
_invalid_test "70-01-01$relstr" "1870-01-01$relstr" "9570-01-01$relstr"
} -result [lrepeat 15 1 {unable to convert input string: invalid year}] -cleanup {
::tcl::unsupported::clock::configure {*}$orgcfg
unset -nocomplain orgcfg
}
}; # foreach
rename _invalid_test {}
unset -nocomplain idx relstr
set dst_hole_check {
{":Europe/Berlin"
"2017-03-26 01:59:59" "2017-03-26 02:00:00" "2017-03-26 02:59:59" "2017-03-26 03:00:00"
"2017-10-29 01:59:59" "2017-10-29 02:00:00"}
{":Europe/Berlin"
"2018-03-25 01:59:59" "2018-03-25 02:00:00" "2018-03-25 02:59:59" "2018-03-25 03:00:00"
"2018-10-28 01:59:59" "2018-10-28 02:00:00"}
{":America/New_York"
"2017-03-12 01:59:59" "2017-03-12 02:00:00" "2017-03-12 02:59:59" "2017-03-12 03:00:00"
"2017-11-05 01:59:59" "2017-11-05 02:00:00"}
{":America/New_York"
"2018-03-11 01:59:59" "2018-03-11 02:00:00" "2018-03-11 02:59:59" "2018-03-11 03:00:00"
"2018-11-04 01:59:59" "2018-11-04 02:00:00"}
}
test clock-46.19-1 {free-scan: validation rules: invalid time (DST-hole, out of range in time-zone)} \
-body {
set res {}
foreach tz $dst_hole_check { set dt [lassign $tz tz]; foreach dt $dt {
lappend res [set v [catch {clock scan $dt -timezone $tz -valid 1} msg]]
if {$v} { lappend res $msg }
}}
set res
} -cleanup {
unset -nocomplain res v dt tz
} -result [lrepeat 4 \
{*}[list 0 {*}[lrepeat 2 1 {unable to convert input string: invalid time (does not exist in this time-zone)}] 0 0 0]]
test clock-46.19-2 {free-scan: validation rules regression: all scans successful, if -valid 0} \
-body {
set res {}
set res {}
foreach tz $dst_hole_check { set dt [lassign $tz tz]; foreach dt $dt {
lappend res [set v [catch {clock scan $dt -timezone $tz} msg]]
}}
set res
} -cleanup {
unset -nocomplain res v dt tz
} -result [lrepeat 4 {*}[if {$valid_mode} {list 0 1 1 0 0 0} else {list 0 0 0 0 0 0}]]
test clock-46.19-3 {scan: validation rules: invalid time (DST-hole, out of range in time-zone)} \
-body {
set res {}
foreach tz $dst_hole_check { set dt [lassign $tz tz]; foreach dt $dt {
lappend res [set v [catch {clock scan $dt -timezone $tz -format "%Y-%m-%d %H:%M:%S" -valid 1} msg]]
if {$v} { lappend res $msg }
}}
set res
} -cleanup {
unset -nocomplain res v dt tz
} -result [lrepeat 4 \
{*}[list 0 {*}[lrepeat 2 1 {unable to convert input string: invalid time (does not exist in this time-zone)}] 0 0 0]]
test clock-46.19-4 {scan: validation rules regression: all scans successful, if -valid 0} \
-body {
set res {}
set res {}
foreach tz $dst_hole_check { set dt [lassign $tz tz]; foreach dt $dt {
lappend res [set v [catch {clock scan $dt -timezone $tz -format "%Y-%m-%d %H:%M:%S"} msg]]
}}
set res
} -cleanup {
unset -nocomplain res v dt tz
} -result [lrepeat 4 {*}[if {$valid_mode} {list 0 1 1 0 0 0} else {list 0 0 0 0 0 0}]]
unset -nocomplain dst_hole_check
proc _invalid_test {args} {
global valid_mode
# ensure validation works TZ independently, since the conversion
# of local time to UTC may adjust date/time tokens, depending on TZ:
set res {}
foreach tz {:GMT :CET {} :Europe/Berlin :localtime} {
foreach {v fmt} $args {
if {$valid_mode} { # globally -valid 1
lappend res [catch {clock scan $v -format $fmt -timezone $tz} msg] $msg
} else {
lappend res [catch {clock scan $v -format $fmt -valid 1 -timezone $tz} msg] $msg
}
}
}
set res
}
test clock-46.20 {scan: validation rules: invalid time} \
-body {
# 13:00 am/pm are invalid input strings...
_invalid_test "13:00 am" "%H:%M %p" "13:00 pm" "%H:%M %p"
} -result [lrepeat 10 1 {unable to convert input string: invalid time (hour)}]
test clock-46.21 {scan: validation rules: invalid time} \
-body {
# invalid minutes in input strings...
_invalid_test "23:70" "%H:%M" "11:80 pm" "%H:%M %p"
} -result [lrepeat 10 1 {unable to convert input string: invalid time (minutes)}]
test clock-46.22 {scan: validation rules: invalid time} \
-body {
# invalid seconds in input strings...
_invalid_test "23:00:70" "%H:%M:%S" "11:00:80 pm" "%H:%M:%S %p"
} -result [lrepeat 10 1 {unable to convert input string: invalid time}]
test clock-46.23 {scan: validation rules: invalid day} \
-body {
_invalid_test "29 Feb 2017" "%d %b %Y" "30 Feb 2016" "%d %b %Y"
} -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.24 {scan: validation rules: invalid day} \
-body {
_invalid_test "0 Feb 2017" "%d %b %Y" "00 Feb 2017" "%d %b %Y"
} -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.25 {scan: validation rules: invalid month} \
-body {
_invalid_test "13/13/2017" "%m/%d/%Y" "00/01/2017" "%m/%d/%Y"
} -result [lrepeat 10 1 {unable to convert input string: invalid month}]
test clock-46.26 {scan: validation rules: ambiguous day} \
-body {
_invalid_test "1970-01-02--004" "%Y-%m-%d--%j" "70-01-02--004" "%y-%m-%d--%j"
} -result [lrepeat 10 1 {unable to convert input string: ambiguous day}]
test clock-46.27 {scan: validation rules: ambiguous year} \
-body {
_invalid_test "19700106 00W014" "%Y%m%d %gW%V%u" "1970006 00W014" "%Y%j %gW%V%u"
} -result [lrepeat 10 1 {unable to convert input string: ambiguous year}]
test clock-46.28 {scan: validation rules: invalid day of week} \
-body {
_invalid_test "Sat Jan 02 00:00:00 1970" "%a %b %d %H:%M:%S %Y"
} -result [lrepeat 5 1 {unable to convert input string: invalid day of week}]
test clock-46.29-1 {scan: validation rules: invalid day of year} \
-body {
_invalid_test "000-2017" "%j-%Y" "366-2017" "%j-%Y" "000-2017" "%j-%G" "366-2017" "%j-%G"
} -result [lrepeat 20 1 {unable to convert input string: invalid day of year}]
test clock-46.29-2 {scan: validation rules: valid day of leap/not leap year} \
-body {
list [clock format [clock scan "366-2016" -format "%j-%Y" -valid 1 -gmt 1] -format "%d-%m-%Y"] \
[clock format [clock scan "365-2017" -format "%j-%Y" -valid 1 -gmt 1] -format "%d-%m-%Y"] \
[clock format [clock scan "366-2016" -format "%j-%G" -valid 1 -gmt 1] -format "%d-%m-%Y"] \
[clock format [clock scan "365-2017" -format "%j-%G" -valid 1 -gmt 1] -format "%d-%m-%Y"]
} -result {31-12-2016 31-12-2017 31-12-2016 31-12-2017}
test clock-46.30 {scan: validation rules: invalid year} -setup {
set orgcfg [list -min-year [::tcl::unsupported::clock::configure -min-year] -max-year [::tcl::unsupported::clock::configure -max-year] \
-year-century [::tcl::unsupported::clock::configure -year-century] -century-switch [::tcl::unsupported::clock::configure -century-switch]]
::tcl::unsupported::clock::configure -min-year 2000 -max-year 2100 -year-century 2000 -century-switch 38
} -body {
_invalid_test "01-01-70" "%d-%m-%y" "01-01-1870" "%d-%m-%C%y" "01-01-1970" "%d-%m-%Y"
} -result [lrepeat 15 1 {unable to convert input string: invalid year}] -cleanup {
::tcl::unsupported::clock::configure {*}$orgcfg
unset -nocomplain orgcfg
}
test clock-46.31 {scan: validation rules: invalid iso year} -setup {
set orgcfg [list -min-year [::tcl::unsupported::clock::configure -min-year] -max-year [::tcl::unsupported::clock::configure -max-year] \
-year-century [::tcl::unsupported::clock::configure -year-century] -century-switch [::tcl::unsupported::clock::configure -century-switch]]
::tcl::unsupported::clock::configure -min-year 2000 -max-year 2100 -year-century 2000 -century-switch 38
} -body {
_invalid_test "01-01-70" "%d-%m-%g" "01-01-9870" "%d-%m-%C%g" "01-01-9870" "%d-%m-%G"
} -result [lrepeat 15 1 {unable to convert input string: invalid iso year}] -cleanup {
::tcl::unsupported::clock::configure {*}$orgcfg
unset -nocomplain orgcfg
}
rename _invalid_test {}
test clock-47.1 {regression test - four-digit time} {
clock scan 0012
} [clock scan 0012 -format %H%M]
test clock-47.2 {regression test - four digit time} {
clock scan 0039
} [clock scan 0039 -format %H%M]
|
| ︙ | ︙ | |||
36936 36937 36938 36939 36940 36941 36942 |
clock scan "1 DECEMBER 2000" -gmt true -format "%d %b %Y"
} [clock scan "2000-12-01" -gmt true -format "%Y-%m-%d"]
test clock-61.1 {overflow of a wide integer on output} {*}{
-body {
clock format 0x8000000000000000 -format %s -gmt true
}
| | | | | | | | > | > > > > > > | 38176 38177 38178 38179 38180 38181 38182 38183 38184 38185 38186 38187 38188 38189 38190 38191 38192 38193 38194 38195 38196 38197 38198 38199 38200 38201 38202 38203 38204 38205 38206 38207 38208 38209 38210 38211 38212 |
clock scan "1 DECEMBER 2000" -gmt true -format "%d %b %Y"
} [clock scan "2000-12-01" -gmt true -format "%Y-%m-%d"]
test clock-61.1 {overflow of a wide integer on output} {*}{
-body {
clock format 0x8000000000000000 -format %s -gmt true
}
-result {expected integer but got "0x8000000000000000"}
-returnCodes error
}
test clock-61.2 {overflow of a wide integer on output} {*}{
-body {
clock format -0x8000000000000001 -format %s -gmt true
}
-result {expected integer but got "-0x8000000000000001"}
-returnCodes error
}
test clock-61.3 {near-miss overflow of a wide integer on output, very large datetime (upper range)} {
clock format 0x00F0000000000000 -format "%s %Y %EE" -gmt true
} [list [expr 0x00F0000000000000] 2140702833 C.E.]
test clock-61.4 {near-miss overflow of a wide integer on output, very small datetime (lower range)} {
clock format -0x00F0000000000000 -format "%s %Y %EE" -gmt true
} [list [expr -0x00F0000000000000] 2140654939 B.C.E.]
test clock-61.5 {overflow of possible date-time (upper range)} -body {
clock format 0x00F0000000000001 -gmt true
} -returnCodes error -result {integer value too large to represent}
test clock-61.6 {overflow of possible date-time (lower range)} -body {
clock format -0x00F0000000000001 -gmt true
} -returnCodes error -result {integer value too large to represent}
test clock-62.1 {Bug 1902423} {*}{
-setup {::tcl::clock::ClearCaches}
-body {
set s 1204049747
set f1 [clock format $s -format {%Y-%m-%d %T} -locale C]
set f2 [clock format $s -format {%Y-%m-%d %H:%M:%S} -locale C]
|
| ︙ | ︙ | |||
37058 37059 37060 37061 37062 37063 37064 |
expr {$res == [clock scan "01/01/1970" -locale current -format %x -gmt 1]}
} -cleanup {
msgcat::mclocale $current
} -result {1}
# cleanup
| < > > > > > > > > > > > | 38305 38306 38307 38308 38309 38310 38311 38312 38313 38314 38315 38316 38317 38318 38319 38320 38321 38322 38323 38324 38325 38326 38327 38328 38329 |
expr {$res == [clock scan "01/01/1970" -locale current -format %x -gmt 1]}
} -cleanup {
msgcat::mclocale $current
} -result {1}
# cleanup
::tcl::clock::ClearCaches
rename test {}
namespace import -force ::tcltest::*
# adjust expected skipped (valid_off is an artificial constraint):
if {$valid_mode && [info exists ::tcltest::skippedBecause(valid_off)]} {
incr ::tcltest::numTests(Total) -$::tcltest::skippedBecause(valid_off)
incr ::tcltest::numTests(Skipped) -$::tcltest::skippedBecause(valid_off)
unset ::tcltest::skippedBecause(valid_off)
}
::tcltest::cleanupTests
namespace delete ::testClock
unset valid_mode
return
# Local Variables:
# mode: tcl
# End:
|
Changes to tests/encoding.test.
| ︙ | ︙ | |||
1063 1064 1065 1066 1067 1068 1069 | encoding convertto -profile tcl8 $name $string # discard the cached internal representation of Tcl_Encoding # Unfortunately, without this, encoding 2-1 fails. llength $name } return $count | | | 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 |
encoding convertto -profile tcl8 $name $string
# discard the cached internal representation of Tcl_Encoding
# Unfortunately, without this, encoding 2-1 fails.
llength $name
}
return $count
} -result 93
runtests
test encoding-bug-183a1adcc0-1 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
testencoding
} -body {
# Note - buffers are initialized to \xFF
|
| ︙ | ︙ |
Changes to tests/string.test.
| ︙ | ︙ | |||
221 222 223 224 225 226 227 |
} 0
test string-2.35.$noComp {string compare, binary neq} {
run {string compare [binary format a100a 0 1] [binary format a100a 0 0]}
} 1
test string-2.36.$noComp {string compare, binary neq unequal length} {
run {string compare [binary format a20a 0 1] [binary format a100a 0 0]}
} 1
| | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
} 0
test string-2.35.$noComp {string compare, binary neq} {
run {string compare [binary format a100a 0 1] [binary format a100a 0 0]}
} 1
test string-2.36.$noComp {string compare, binary neq unequal length} {
run {string compare [binary format a20a 0 1] [binary format a100a 0 0]}
} 1
test string-2.37.$noComp {string compare, big -length} {
if {[package vsatisfies [info patchlevel] 8.7-]} {
run {string compare -length 0x100000000 ab abde}
} else {
run {string compare -length 0x7fffffff ab abde}
}
} -1
test string-2.38a.$noComp {string compare empty string against byte array} {
# Bug edb4b065f4
run {string compare "" [binary decode hex 00]}
} -1
test string-2.38b.$noComp {string compare -length empty string against byte array} {
# Bug edb4b065f4
run {string compare -length 1 "" [binary decode hex 00]}
} -1
test string-2.38c.$noComp {string compare -nocase empty string against byte array} {
# Bug edb4b065f4
run {string compare -nocase "" [binary decode hex 00]}
} -1
test string-2.38d.$noComp {string compare empty string against byte array} {
# Bug edb4b065f4
run {string compare [binary decode hex 00] ""}
} 1
test string-2.38e.$noComp {string compare -length empty string against byte array} {
# Bug edb4b065f4
run {string compare -length 1 [binary decode hex 00] ""}
} 1
test string-2.38f.$noComp {string compare -nocase empty string against byte array} {
# Bug edb4b065f4
run {string compare -nocase [binary decode hex 00] ""}
} 1
# only need a few tests on equal, since it uses the same code as
# string compare, but just modifies the return output
test string-3.1.$noComp {string equal} {
run {string equal abcde abdef}
} 0
test string-3.2.$noComp {string equal} {
|
| ︙ | ︙ | |||
365 366 367 368 369 370 371 |
test string-3.41.$noComp {string equal, binary neq} {
run {string equal [binary format a100a 0 1] [binary format a100a 0 0]}
} 0
test string-3.42.$noComp {string equal, binary neq inequal length} {
run {string equal [binary format a20a 0 1] [binary format a100a 0 0]}
} 0
test string-3.43.$noComp {string equal, big -length} {
| > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 |
test string-3.41.$noComp {string equal, binary neq} {
run {string equal [binary format a100a 0 1] [binary format a100a 0 0]}
} 0
test string-3.42.$noComp {string equal, binary neq inequal length} {
run {string equal [binary format a20a 0 1] [binary format a100a 0 0]}
} 0
test string-3.43.$noComp {string equal, big -length} {
if {[package vsatisfies [info patchlevel] 8.7-]} {
run {string equal -length 0x100000000 abc def}
} else {
run {string equal -length 0x7fffffff abc def}
}
} 0
test string-3.44.$noComp {string equal, bigger -length} -body {
run {string equal -length 18446744073709551616 abc def}
} -returnCodes 1 -result {integer value too large to represent}
test string-3.45a.$noComp {string equal empty string against byte array} {
# Bug edb4b065f4
run {string equal "" [binary decode hex 00]}
} 0
test string-3.45b.$noComp {string equal -length empty string against byte array} {
# Bug edb4b065f4
run {string equal -length 1 "" [binary decode hex 00]}
} 0
test string-3.45c.$noComp {string equal -nocase empty string against byte array} {
# Bug edb4b065f4
run {string equal -nocase "" [binary decode hex 00]}
} 0
test string-3.45d.$noComp {string equal empty string against byte array} {
# Bug edb4b065f4
run {string equal [binary decode hex 00] ""}
} 0
test string-3.45e.$noComp {string equal -length empty string against byte array} {
# Bug edb4b065f4
run {string equal -length 1 [binary decode hex 00] ""}
} 0
test string-3.45f.$noComp {string equal -nocase empty string against byte array} {
# Bug edb4b065f4
run {string equal -nocase [binary decode hex 00] ""}
} 0
test string-4.1.$noComp {string first, not enough args} {
list [catch {run {string first a}} msg] $msg
} {1 {wrong # args: should be "string first needleString haystackString ?startIndex?"}}
test string-4.2.$noComp {string first, bad args} {
list [catch {run {string first a b c}} msg] $msg
} {1 {bad index "c": must be integer?[+-]integer? or end?[+-]integer?}}
|
| ︙ | ︙ |
Changes to tests/tcltests.tcl.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
testConstraint purify [tcl::build-info purify]
testConstraint debugpurify [
expr {
![tcl::build-info memdebug]
&& [testConstraint debug]
&& [testConstraint purify]
}]
testConstraint fcopy [llength [info commands fcopy]]
testConstraint fileevent [llength [info commands fileevent]]
testConstraint thread [expr {![catch {package require Thread 2.7-}]}]
testConstraint notValgrind [expr {![testConstraint valgrind]}]
namespace eval ::tcltests {
| > > > > > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
testConstraint purify [tcl::build-info purify]
testConstraint debugpurify [
expr {
![tcl::build-info memdebug]
&& [testConstraint debug]
&& [testConstraint purify]
}]
testConstraint bigmem [expr {[
info exists ::env(TCL_TESTCONSTRAINT_BIGMEM)]
? !!$::env(TCL_TESTCONSTRAINT_BIGMEM)
: 1
}]
testConstraint fcopy [llength [info commands fcopy]]
testConstraint fileevent [llength [info commands fileevent]]
testConstraint thread [expr {![catch {package require Thread 2.7-}]}]
testConstraint notValgrind [expr {![testConstraint valgrind]}]
namespace eval ::tcltests {
|
| ︙ | ︙ |
Changes to tests/zipfs.test.
| ︙ | ︙ | |||
1446 1447 1448 1449 1450 1451 1452 |
testzipfsglob basic-dir $basicMounts [list -directory $defMountPt *] [zipfspathsmt $defMountPt test testdir]
testzipfsglob basic-dir-tails $basicMounts [list -tails -dir $defMountPt *] [list test testdir]
testzipfsglob basic-type-d $basicMounts [list -type d $defMountPt/*] [zipfspathsmt $defMountPt testdir]
testzipfsglob basic-type-f $basicMounts [list -type f $defMountPt/*] [zipfspathsmt $defMountPt test]
testzipfsglob basic-type-d-f $basicMounts [list -type {d f} $defMountPt/*] [zipfspathsmt $defMountPt test testdir]
testzipfsglob basic-type-l $basicMounts [list -type l $defMountPt/*] {}
foreach type {b c l p s} {
| | | 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 |
testzipfsglob basic-dir $basicMounts [list -directory $defMountPt *] [zipfspathsmt $defMountPt test testdir]
testzipfsglob basic-dir-tails $basicMounts [list -tails -dir $defMountPt *] [list test testdir]
testzipfsglob basic-type-d $basicMounts [list -type d $defMountPt/*] [zipfspathsmt $defMountPt testdir]
testzipfsglob basic-type-f $basicMounts [list -type f $defMountPt/*] [zipfspathsmt $defMountPt test]
testzipfsglob basic-type-d-f $basicMounts [list -type {d f} $defMountPt/*] [zipfspathsmt $defMountPt test testdir]
testzipfsglob basic-type-l $basicMounts [list -type l $defMountPt/*] {}
foreach type {b c l p s} {
testzipfsglob basic-type-1-$type $basicMounts [list -type $type $defMountPt/*] {}
testzipfsglob basic-type-f-$type $basicMounts [list -type [list f $type] $defMountPt/*] [zipfspathsmt $defMountPt test]
testzipfsglob basic-type-d-$type $basicMounts [list -type [list d $type] $defMountPt/*] [zipfspathsmt $defMountPt testdir]
}
testzipfsglob basic-path $basicMounts [list -path $defMountPt/t *d*] [zipfspathsmt $defMountPt testdir]
testzipfsglob basic-enoent $basicMounts [list $defMountPt/x*] {}
testzipfsglob basic-enoent-ok $basicMounts [list -nocomplain $defMountPt/x*] {}
|
| ︙ | ︙ |
Changes to tools/genStubs.tcl.
| ︙ | ︙ | |||
807 808 809 810 811 812 813 814 815 816 817 818 819 820 |
append text [addPlatformGuard $plat $temp]
set emit 1
}
## aqua ##
set temp {}
set plat aqua
if {!$slot(unix) && !$slot(macosx)} {
if {$slot($plat)} {
append temp [$slotProc $name $stubs($name,$plat,$i) $i]
} elseif {$onAll} {
eval {append temp} $skipString
}
}
if {$temp ne ""} {
| > > > > > > > > > > > > > > > | 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 |
append text [addPlatformGuard $plat $temp]
set emit 1
}
## aqua ##
set temp {}
set plat aqua
if {!$slot(unix) && !$slot(macosx)} {
if {[string range $skipString 1 2] ne "/*"} {
# genStubs.tcl previously had a bug here causing it to
# erroneously generate both a unix entry and an aqua
# entry for a given stubs table slot. To preserve
# backwards compatibility, generate a dummy stubs entry
# before every aqua entry (note that this breaks the
# correspondence between emitted entry number and
# actual position of the entry in the stubs table, e.g.
# TkIntStubs entry 113 for aqua is in fact at position
# 114 in the table, entry 114 at position 116 etc).
eval {append temp} $skipString
set temp "# if TCL_MAJOR_VERSION < 9\n[string range $temp 0 end-1] /*\
Dummy entry for stubs table backwards\
compatibility */\n# endif /* TCL_MAJOR_VERSION < 9 */\n"
}
if {$slot($plat)} {
append temp [$slotProc $name $stubs($name,$plat,$i) $i]
} elseif {$onAll} {
eval {append temp} $skipString
}
}
if {$temp ne ""} {
|
| ︙ | ︙ |
Changes to unix/Makefile.in.
| ︙ | ︙ | |||
297 298 299 300 301 302 303 | XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \ tclThreadTest.o tclUnixTest.o tclXtNotify.o tclXtTest.o \ tclTestABSList.o GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \ tclArithSeries.o tclAssembly.o tclAsync.o tclBasic.o tclBinary.o \ | | | | | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \ tclThreadTest.o tclUnixTest.o tclXtNotify.o tclXtTest.o \ tclTestABSList.o GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \ tclArithSeries.o tclAssembly.o tclAsync.o tclBasic.o tclBinary.o \ tclCkalloc.o tclClock.o tclClockFmt.o tclCmdAH.o tclCmdIL.o tclCmdMZ.o \ tclCompCmds.o tclCompCmdsGR.o tclCompCmdsSZ.o tclCompExpr.o \ tclCompile.o tclConfig.o tclDate.o tclDictObj.o tclDisassemble.o \ tclEncoding.o tclEnsemble.o \ tclEnv.o tclEvent.o tclExecute.o tclFCmd.o tclFileName.o tclGet.o \ tclHash.o tclHistory.o tclIndexObj.o tclInterp.o tclIO.o tclIOCmd.o \ tclIORChan.o tclIORTrans.o tclIOGT.o tclIOSock.o tclIOUtil.o \ tclLink.o tclListObj.o \ tclLiteral.o tclLoad.o tclMain.o tclNamesp.o tclNotify.o \ tclObj.o tclOptimize.o tclPanic.o tclParse.o tclPathObj.o tclPipe.o \ tclPkg.o tclPkgConfig.o tclPosixStr.o \ tclPreserve.o tclProc.o tclProcess.o tclRegexp.o \ tclResolve.o tclResult.o tclScan.o tclStringObj.o tclStrIdxTree.o \ tclStrToD.o tclThread.o \ tclThreadAlloc.o tclThreadJoin.o tclThreadStorage.o tclStubInit.o \ tclTimer.o tclTrace.o tclUtf.o tclUtil.o tclVar.o tclZlib.o \ tclTomMathInterface.o tclZipfs.o OO_OBJS = tclOO.o tclOOBasic.o tclOOCall.o tclOODefineCmds.o tclOOInfo.o \ tclOOMethod.o tclOOStubInit.o TOMMATH_OBJS = bn_s_mp_reverse.o bn_s_mp_mul_digs_fast.o \ bn_s_mp_sqr_fast.o bn_mp_add.o bn_mp_and.o \ bn_mp_add_d.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o \ bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ bn_mp_cnt_lsb.o bn_mp_copy.o \ bn_mp_count_bits.o bn_mp_div.o bn_mp_div_d.o bn_mp_div_2.o \ bn_mp_div_2d.o bn_s_mp_div_3.o bn_mp_exch.o bn_mp_expt_n.o \ bn_mp_get_mag_u64.o \ bn_mp_grow.o bn_mp_init.o \ bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o \ bn_mp_init_size.o bn_s_mp_karatsuba_mul.o \ bn_mp_init_i64.o bn_mp_init_u64.o \ bn_s_mp_karatsuba_sqr.o bn_s_mp_balance_mul.o \ bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mul.o bn_mp_mul_2.o \ |
| ︙ | ︙ | |||
407 408 409 410 411 412 413 414 415 416 417 418 419 420 | $(GENERIC_DIR)/tclArithSeries.c \ $(GENERIC_DIR)/tclAssembly.c \ $(GENERIC_DIR)/tclAsync.c \ $(GENERIC_DIR)/tclBasic.c \ $(GENERIC_DIR)/tclBinary.c \ $(GENERIC_DIR)/tclCkalloc.c \ $(GENERIC_DIR)/tclClock.c \ $(GENERIC_DIR)/tclCmdAH.c \ $(GENERIC_DIR)/tclCmdIL.c \ $(GENERIC_DIR)/tclCmdMZ.c \ $(GENERIC_DIR)/tclCompCmds.c \ $(GENERIC_DIR)/tclCompCmdsGR.c \ $(GENERIC_DIR)/tclCompCmdsSZ.c \ $(GENERIC_DIR)/tclCompExpr.c \ | > | 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 | $(GENERIC_DIR)/tclArithSeries.c \ $(GENERIC_DIR)/tclAssembly.c \ $(GENERIC_DIR)/tclAsync.c \ $(GENERIC_DIR)/tclBasic.c \ $(GENERIC_DIR)/tclBinary.c \ $(GENERIC_DIR)/tclCkalloc.c \ $(GENERIC_DIR)/tclClock.c \ $(GENERIC_DIR)/tclClockFmt.c \ $(GENERIC_DIR)/tclCmdAH.c \ $(GENERIC_DIR)/tclCmdIL.c \ $(GENERIC_DIR)/tclCmdMZ.c \ $(GENERIC_DIR)/tclCompCmds.c \ $(GENERIC_DIR)/tclCompCmdsGR.c \ $(GENERIC_DIR)/tclCompCmdsSZ.c \ $(GENERIC_DIR)/tclCompExpr.c \ |
| ︙ | ︙ | |||
462 463 464 465 466 467 468 469 470 471 472 473 474 475 | $(GENERIC_DIR)/tclProcess.c \ $(GENERIC_DIR)/tclRegexp.c \ $(GENERIC_DIR)/tclResolve.c \ $(GENERIC_DIR)/tclResult.c \ $(GENERIC_DIR)/tclScan.c \ $(GENERIC_DIR)/tclStubInit.c \ $(GENERIC_DIR)/tclStringObj.c \ $(GENERIC_DIR)/tclStrToD.c \ $(GENERIC_DIR)/tclTest.c \ $(GENERIC_DIR)/tclTestABSList.c \ $(GENERIC_DIR)/tclTestObj.c \ $(GENERIC_DIR)/tclTestProcBodyObj.c \ $(GENERIC_DIR)/tclThread.c \ $(GENERIC_DIR)/tclThreadAlloc.c \ | > | 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | $(GENERIC_DIR)/tclProcess.c \ $(GENERIC_DIR)/tclRegexp.c \ $(GENERIC_DIR)/tclResolve.c \ $(GENERIC_DIR)/tclResult.c \ $(GENERIC_DIR)/tclScan.c \ $(GENERIC_DIR)/tclStubInit.c \ $(GENERIC_DIR)/tclStringObj.c \ $(GENERIC_DIR)/tclStrIdxTree.c \ $(GENERIC_DIR)/tclStrToD.c \ $(GENERIC_DIR)/tclTest.c \ $(GENERIC_DIR)/tclTestABSList.c \ $(GENERIC_DIR)/tclTestObj.c \ $(GENERIC_DIR)/tclTestProcBodyObj.c \ $(GENERIC_DIR)/tclThread.c \ $(GENERIC_DIR)/tclThreadAlloc.c \ |
| ︙ | ︙ | |||
518 519 520 521 522 523 524 | $(TOMMATH_DIR)/bn_mp_complement.c \ $(TOMMATH_DIR)/bn_mp_copy.c \ $(TOMMATH_DIR)/bn_mp_count_bits.c \ $(TOMMATH_DIR)/bn_mp_decr.c \ $(TOMMATH_DIR)/bn_mp_div.c \ $(TOMMATH_DIR)/bn_mp_div_2.c \ $(TOMMATH_DIR)/bn_mp_div_2d.c \ | | | < < < < | > > > | 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 | $(TOMMATH_DIR)/bn_mp_complement.c \ $(TOMMATH_DIR)/bn_mp_copy.c \ $(TOMMATH_DIR)/bn_mp_count_bits.c \ $(TOMMATH_DIR)/bn_mp_decr.c \ $(TOMMATH_DIR)/bn_mp_div.c \ $(TOMMATH_DIR)/bn_mp_div_2.c \ $(TOMMATH_DIR)/bn_mp_div_2d.c \ $(TOMMATH_DIR)/bn_s_mp_div_3.c \ $(TOMMATH_DIR)/bn_mp_div_d.c \ $(TOMMATH_DIR)/bn_mp_dr_is_modulus.c \ $(TOMMATH_DIR)/bn_mp_dr_reduce.c \ $(TOMMATH_DIR)/bn_mp_dr_setup.c \ $(TOMMATH_DIR)/bn_mp_error_to_string.c \ $(TOMMATH_DIR)/bn_mp_exch.c \ $(TOMMATH_DIR)/bn_mp_expt_n.c \ $(TOMMATH_DIR)/bn_mp_exptmod.c \ $(TOMMATH_DIR)/bn_mp_exteuclid.c \ $(TOMMATH_DIR)/bn_mp_fread.c \ $(TOMMATH_DIR)/bn_mp_from_sbin.c \ $(TOMMATH_DIR)/bn_mp_from_ubin.c \ $(TOMMATH_DIR)/bn_mp_fwrite.c \ $(TOMMATH_DIR)/bn_mp_gcd.c \ $(TOMMATH_DIR)/bn_mp_get_double.c \ $(TOMMATH_DIR)/bn_mp_get_i32.c \ $(TOMMATH_DIR)/bn_mp_get_i64.c \ $(TOMMATH_DIR)/bn_mp_get_l.c \ $(TOMMATH_DIR)/bn_mp_get_mag_u32.c \ $(TOMMATH_DIR)/bn_mp_get_mag_u64.c \ $(TOMMATH_DIR)/bn_mp_get_mag_ul.c \ $(TOMMATH_DIR)/bn_mp_grow.c \ $(TOMMATH_DIR)/bn_mp_incr.c \ $(TOMMATH_DIR)/bn_mp_init.c \ $(TOMMATH_DIR)/bn_mp_init_copy.c \ $(TOMMATH_DIR)/bn_mp_init_i32.c \ $(TOMMATH_DIR)/bn_mp_init_i64.c \ $(TOMMATH_DIR)/bn_mp_init_l.c \ $(TOMMATH_DIR)/bn_mp_init_multi.c \ $(TOMMATH_DIR)/bn_mp_init_set.c \ $(TOMMATH_DIR)/bn_mp_init_size.c \ $(TOMMATH_DIR)/bn_mp_init_u32.c \ $(TOMMATH_DIR)/bn_mp_init_u64.c \ $(TOMMATH_DIR)/bn_mp_init_ul.c \ $(TOMMATH_DIR)/bn_mp_invmod.c \ $(TOMMATH_DIR)/bn_mp_is_square.c \ $(TOMMATH_DIR)/bn_mp_iseven.c \ $(TOMMATH_DIR)/bn_mp_isodd.c \ $(TOMMATH_DIR)/bn_mp_kronecker.c \ $(TOMMATH_DIR)/bn_mp_lcm.c \ $(TOMMATH_DIR)/bn_mp_log_n.c \ $(TOMMATH_DIR)/bn_s_mp_log.c \ $(TOMMATH_DIR)/bn_s_mp_log_2expt.c \ $(TOMMATH_DIR)/bn_s_mp_log_d.c \ $(TOMMATH_DIR)/bn_mp_lshd.c \ $(TOMMATH_DIR)/bn_mp_mod.c \ $(TOMMATH_DIR)/bn_mp_mod_2d.c \ $(TOMMATH_DIR)/bn_mp_mod_d.c \ $(TOMMATH_DIR)/bn_mp_montgomery_calc_normalization.c \ $(TOMMATH_DIR)/bn_mp_montgomery_reduce.c \ $(TOMMATH_DIR)/bn_mp_montgomery_setup.c \ |
| ︙ | ︙ | |||
600 601 602 603 604 605 606 | $(TOMMATH_DIR)/bn_mp_reduce_2k.c \ $(TOMMATH_DIR)/bn_mp_reduce_2k_l.c \ $(TOMMATH_DIR)/bn_mp_reduce_2k_setup.c \ $(TOMMATH_DIR)/bn_mp_reduce_2k_setup_l.c \ $(TOMMATH_DIR)/bn_mp_reduce_is_2k.c \ $(TOMMATH_DIR)/bn_mp_reduce_is_2k_l.c \ $(TOMMATH_DIR)/bn_mp_reduce_setup.c \ | | < < | 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 | $(TOMMATH_DIR)/bn_mp_reduce_2k.c \ $(TOMMATH_DIR)/bn_mp_reduce_2k_l.c \ $(TOMMATH_DIR)/bn_mp_reduce_2k_setup.c \ $(TOMMATH_DIR)/bn_mp_reduce_2k_setup_l.c \ $(TOMMATH_DIR)/bn_mp_reduce_is_2k.c \ $(TOMMATH_DIR)/bn_mp_reduce_is_2k_l.c \ $(TOMMATH_DIR)/bn_mp_reduce_setup.c \ $(TOMMATH_DIR)/bn_mp_root_n.c \ $(TOMMATH_DIR)/bn_mp_rshd.c \ $(TOMMATH_DIR)/bn_mp_sbin_size.c \ $(TOMMATH_DIR)/bn_mp_set.c \ $(TOMMATH_DIR)/bn_mp_set_double.c \ $(TOMMATH_DIR)/bn_mp_set_i32.c \ $(TOMMATH_DIR)/bn_mp_set_i64.c \ $(TOMMATH_DIR)/bn_mp_set_l.c \ $(TOMMATH_DIR)/bn_mp_set_u32.c \ $(TOMMATH_DIR)/bn_mp_set_u64.c \ $(TOMMATH_DIR)/bn_mp_set_ul.c \ $(TOMMATH_DIR)/bn_mp_shrink.c \ $(TOMMATH_DIR)/bn_mp_signed_rsh.c \ $(TOMMATH_DIR)/bn_mp_sqr.c \ $(TOMMATH_DIR)/bn_mp_sqrmod.c \ $(TOMMATH_DIR)/bn_mp_sqrt.c \ $(TOMMATH_DIR)/bn_mp_sqrtmod_prime.c \ $(TOMMATH_DIR)/bn_mp_sub.c \ |
| ︙ | ︙ | |||
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 |
MATHHDRS = $(GENERIC_DIR)/tclTomMath.h $(GENERIC_DIR)/tclTomMathDecls.h
PARSEHDR = $(GENERIC_DIR)/tclParse.h
NREHDR = $(GENERIC_DIR)/tclInt.h
TRIMHDR = $(GENERIC_DIR)/tclStringTrim.h
TCL_LOCATIONS = -DTCL_LIBRARY="\"${TCL_LIBRARY}\"" \
-DTCL_PACKAGE_PATH="\"${TCL_PACKAGE_PATH}\""
regcomp.o: $(REGHDRS) $(GENERIC_DIR)/regcomp.c $(GENERIC_DIR)/regc_lex.c \
$(GENERIC_DIR)/regc_color.c $(GENERIC_DIR)/regc_locale.c \
$(GENERIC_DIR)/regc_nfa.c $(GENERIC_DIR)/regc_cvec.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/regcomp.c
regexec.o: $(REGHDRS) $(GENERIC_DIR)/regexec.c $(GENERIC_DIR)/rege_dfa.c
| > | 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 |
MATHHDRS = $(GENERIC_DIR)/tclTomMath.h $(GENERIC_DIR)/tclTomMathDecls.h
PARSEHDR = $(GENERIC_DIR)/tclParse.h
NREHDR = $(GENERIC_DIR)/tclInt.h
TRIMHDR = $(GENERIC_DIR)/tclStringTrim.h
TCL_LOCATIONS = -DTCL_LIBRARY="\"${TCL_LIBRARY}\"" \
-DTCL_PACKAGE_PATH="\"${TCL_PACKAGE_PATH}\""
TCLDATEHDR=$(GENERIC_DIR)/tclDate.h $(GENERIC_DIR)/tclStrIdxTree.h
regcomp.o: $(REGHDRS) $(GENERIC_DIR)/regcomp.c $(GENERIC_DIR)/regc_lex.c \
$(GENERIC_DIR)/regc_color.c $(GENERIC_DIR)/regc_locale.c \
$(GENERIC_DIR)/regc_nfa.c $(GENERIC_DIR)/regc_cvec.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/regcomp.c
regexec.o: $(REGHDRS) $(GENERIC_DIR)/regexec.c $(GENERIC_DIR)/rege_dfa.c
|
| ︙ | ︙ | |||
1301 1302 1303 1304 1305 1306 1307 | tclBinary.o: $(GENERIC_DIR)/tclBinary.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclBinary.c tclCkalloc.o: $(GENERIC_DIR)/tclCkalloc.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCkalloc.c | | > > > | | 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 | tclBinary.o: $(GENERIC_DIR)/tclBinary.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclBinary.c tclCkalloc.o: $(GENERIC_DIR)/tclCkalloc.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCkalloc.c tclClock.o: $(GENERIC_DIR)/tclClock.c $(TCLDATEHDR) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclClock.c tclClockFmt.o: $(GENERIC_DIR)/tclClockFmt.c $(TCLDATEHDR) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclClockFmt.c tclCmdAH.o: $(GENERIC_DIR)/tclCmdAH.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdAH.c tclCmdIL.o: $(GENERIC_DIR)/tclCmdIL.c $(TCLREHDRS) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdIL.c tclCmdMZ.o: $(GENERIC_DIR)/tclCmdMZ.c $(TCLREHDRS) $(TRIMHDR) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdMZ.c tclDate.o: $(GENERIC_DIR)/tclDate.c $(TCLDATEHDR) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclDate.c tclCompCmds.o: $(GENERIC_DIR)/tclCompCmds.c $(COMPILEHDR) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmds.c tclCompCmdsGR.o: $(GENERIC_DIR)/tclCompCmdsGR.c $(COMPILEHDR) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmdsGR.c |
| ︙ | ︙ | |||
1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 | tclScan.o: $(GENERIC_DIR)/tclScan.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclScan.c tclStringObj.o: $(GENERIC_DIR)/tclStringObj.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStringObj.c tclStrToD.o: $(GENERIC_DIR)/tclStrToD.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStrToD.c tclStubInit.o: $(GENERIC_DIR)/tclStubInit.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStubInit.c tclTrace.o: $(GENERIC_DIR)/tclTrace.c | > > > | 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 | tclScan.o: $(GENERIC_DIR)/tclScan.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclScan.c tclStringObj.o: $(GENERIC_DIR)/tclStringObj.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStringObj.c tclStrIdxTree.o: $(GENERIC_DIR)/tclStrIdxTree.c $(GENERIC_DIR)/tclStrIdxTree.h $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStrIdxTree.c tclStrToD.o: $(GENERIC_DIR)/tclStrToD.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStrToD.c tclStubInit.o: $(GENERIC_DIR)/tclStubInit.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStubInit.c tclTrace.o: $(GENERIC_DIR)/tclTrace.c |
| ︙ | ︙ | |||
1652 1653 1654 1655 1656 1657 1658 | bn_mp_div_2.o: $(TOMMATH_DIR)/bn_mp_div_2.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2.c bn_mp_div_2d.o: $(TOMMATH_DIR)/bn_mp_div_2d.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2d.c | | | | | | 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 | bn_mp_div_2.o: $(TOMMATH_DIR)/bn_mp_div_2.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2.c bn_mp_div_2d.o: $(TOMMATH_DIR)/bn_mp_div_2d.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2d.c bn_s_mp_div_3.o: $(TOMMATH_DIR)/bn_s_mp_div_3.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_div_3.c bn_mp_exch.o: $(TOMMATH_DIR)/bn_mp_exch.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_exch.c bn_mp_expt_n.o: $(TOMMATH_DIR)/bn_mp_expt_n.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_expt_n.c bn_mp_get_mag_u64.o: $(TOMMATH_DIR)/bn_mp_get_mag_u64.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_get_mag_u64.c bn_mp_grow.o: $(TOMMATH_DIR)/bn_mp_grow.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_grow.c |
| ︙ | ︙ |
Changes to unix/tclUnixChan.c.
| ︙ | ︙ | |||
872 873 874 875 876 877 878 |
iostate.c_cc[VSTART] = argv[0][0];
iostate.c_cc[VSTOP] = argv[1][0];
if (argv[0][0] & 0x80 || argv[1][0] & 0x80) {
Tcl_UniChar character = 0;
int charLen;
| | | | 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 |
iostate.c_cc[VSTART] = argv[0][0];
iostate.c_cc[VSTOP] = argv[1][0];
if (argv[0][0] & 0x80 || argv[1][0] & 0x80) {
Tcl_UniChar character = 0;
int charLen;
charLen = TclUtfToUniChar(argv[0], &character);
if ((character > 0xFF) || argv[0][charLen]) {
goto badXchar;
}
iostate.c_cc[VSTART] = character;
charLen = TclUtfToUniChar(argv[1], &character);
if ((character > 0xFF) || argv[1][charLen]) {
goto badXchar;
}
iostate.c_cc[VSTOP] = character;
}
Tcl_Free(argv);
|
| ︙ | ︙ |
Changes to unix/tclUnixTest.c.
| ︙ | ︙ | |||
100 101 102 103 104 105 106 |
Tcl_CreateObjCommand2(interp, "testfilehandler", TestfilehandlerCmd,
NULL, NULL);
Tcl_CreateObjCommand2(interp, "testfilewait", TestfilewaitCmd,
NULL, NULL);
Tcl_CreateObjCommand2(interp, "testfindexecutable", TestfindexecutableCmd,
NULL, NULL);
Tcl_CreateObjCommand2(interp, "testfork", TestforkCmd,
| | | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
Tcl_CreateObjCommand2(interp, "testfilehandler", TestfilehandlerCmd,
NULL, NULL);
Tcl_CreateObjCommand2(interp, "testfilewait", TestfilewaitCmd,
NULL, NULL);
Tcl_CreateObjCommand2(interp, "testfindexecutable", TestfindexecutableCmd,
NULL, NULL);
Tcl_CreateObjCommand2(interp, "testfork", TestforkCmd,
NULL, NULL);
Tcl_CreateObjCommand2(interp, "testalarm", TestalarmCmd,
NULL, NULL);
Tcl_CreateObjCommand2(interp, "testgotsig", TestgotsigCmd,
NULL, NULL);
return TCL_OK;
}
|
| ︙ | ︙ | |||
152 153 154 155 156 157 158 |
testPipes[i].readFile = NULL;
}
initialized = 1;
}
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "option ...");
| | | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
testPipes[i].readFile = NULL;
}
initialized = 1;
}
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "option ...");
return TCL_ERROR;
}
pipePtr = NULL;
if (objc >= 3) {
if (Tcl_GetIntFromObj(interp, objv[2], &i) != TCL_OK) {
return TCL_ERROR;
}
if (i >= MAX_PIPES) {
|
| ︙ | ︙ | |||
243 244 245 246 247 248 249 |
}
} else if (strcmp(Tcl_GetString(objv[1]), "empty") == 0) {
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "index");
return TCL_ERROR;
}
| | | | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
}
} else if (strcmp(Tcl_GetString(objv[1]), "empty") == 0) {
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "index");
return TCL_ERROR;
}
while (read(GetFd(pipePtr->readFile), buffer, 4000) > 0) {
/* Empty loop body. */
}
} else if (strcmp(Tcl_GetString(objv[1]), "fill") == 0) {
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "index");
return TCL_ERROR;
}
memset(buffer, 'a', 4000);
|
| ︙ | ︙ | |||
459 460 461 462 463 464 465 |
Tcl_Interp *interp, /* Current interpreter. */
Tcl_Size objc, /* Number of arguments. */
Tcl_Obj *const *objv) /* Argument strings. */
{
pid_t pid;
if (objc != 1) {
| | | | | | | 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 |
Tcl_Interp *interp, /* Current interpreter. */
Tcl_Size objc, /* Number of arguments. */
Tcl_Obj *const *objv) /* Argument strings. */
{
pid_t pid;
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "");
return TCL_ERROR;
}
pid = fork();
if (pid == -1) {
Tcl_AppendResult(interp,
"Cannot fork", (char *)NULL);
return TCL_ERROR;
}
/* Only needed when pthread_atfork is not present,
* should not hurt otherwise. */
if (pid==0) {
Tcl_InitNotifier();
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pid));
|
| ︙ | ︙ |
Changes to win/Makefile.in.
| ︙ | ︙ | |||
286 287 288 289 290 291 292 293 294 295 296 297 298 299 | tclArithSeries.$(OBJEXT) \ tclAssembly.$(OBJEXT) \ tclAsync.$(OBJEXT) \ tclBasic.$(OBJEXT) \ tclBinary.$(OBJEXT) \ tclCkalloc.$(OBJEXT) \ tclClock.$(OBJEXT) \ tclCmdAH.$(OBJEXT) \ tclCmdIL.$(OBJEXT) \ tclCmdMZ.$(OBJEXT) \ tclCompCmds.$(OBJEXT) \ tclCompCmdsGR.$(OBJEXT) \ tclCompCmdsSZ.$(OBJEXT) \ tclCompExpr.$(OBJEXT) \ | > | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | tclArithSeries.$(OBJEXT) \ tclAssembly.$(OBJEXT) \ tclAsync.$(OBJEXT) \ tclBasic.$(OBJEXT) \ tclBinary.$(OBJEXT) \ tclCkalloc.$(OBJEXT) \ tclClock.$(OBJEXT) \ tclClockFmt.$(OBJEXT) \ tclCmdAH.$(OBJEXT) \ tclCmdIL.$(OBJEXT) \ tclCmdMZ.$(OBJEXT) \ tclCompCmds.$(OBJEXT) \ tclCompCmdsGR.$(OBJEXT) \ tclCompCmdsSZ.$(OBJEXT) \ tclCompExpr.$(OBJEXT) \ |
| ︙ | ︙ | |||
349 350 351 352 353 354 355 356 357 358 359 360 361 362 | tclProc.$(OBJEXT) \ tclProcess.$(OBJEXT) \ tclRegexp.$(OBJEXT) \ tclResolve.$(OBJEXT) \ tclResult.$(OBJEXT) \ tclScan.$(OBJEXT) \ tclStringObj.$(OBJEXT) \ tclStrToD.$(OBJEXT) \ tclStubInit.$(OBJEXT) \ tclThread.$(OBJEXT) \ tclThreadAlloc.$(OBJEXT) \ tclThreadJoin.$(OBJEXT) \ tclThreadStorage.$(OBJEXT) \ tclTimer.$(OBJEXT) \ | > | 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | tclProc.$(OBJEXT) \ tclProcess.$(OBJEXT) \ tclRegexp.$(OBJEXT) \ tclResolve.$(OBJEXT) \ tclResult.$(OBJEXT) \ tclScan.$(OBJEXT) \ tclStringObj.$(OBJEXT) \ tclStrIdxTree.$(OBJEXT) \ tclStrToD.$(OBJEXT) \ tclStubInit.$(OBJEXT) \ tclThread.$(OBJEXT) \ tclThreadAlloc.$(OBJEXT) \ tclThreadJoin.$(OBJEXT) \ tclThreadStorage.$(OBJEXT) \ tclTimer.$(OBJEXT) \ |
| ︙ | ︙ | |||
381 382 383 384 385 386 387 |
bn_mp_cnt_lsb.${OBJEXT} \
bn_mp_copy.${OBJEXT} \
bn_mp_count_bits.${OBJEXT} \
bn_mp_div.${OBJEXT} \
bn_mp_div_d.${OBJEXT} \
bn_mp_div_2.${OBJEXT} \
bn_mp_div_2d.${OBJEXT} \
| | | | 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 |
bn_mp_cnt_lsb.${OBJEXT} \
bn_mp_copy.${OBJEXT} \
bn_mp_count_bits.${OBJEXT} \
bn_mp_div.${OBJEXT} \
bn_mp_div_d.${OBJEXT} \
bn_mp_div_2.${OBJEXT} \
bn_mp_div_2d.${OBJEXT} \
bn_s_mp_div_3.${OBJEXT} \
bn_mp_exch.${OBJEXT} \
bn_mp_expt_n.${OBJEXT} \
bn_mp_get_mag_u64.${OBJEXT} \
bn_mp_grow.${OBJEXT} \
bn_mp_init.${OBJEXT} \
bn_mp_init_copy.${OBJEXT} \
bn_mp_init_i64.${OBJEXT} \
bn_mp_init_multi.${OBJEXT} \
bn_mp_init_set.${OBJEXT} \
|
| ︙ | ︙ |
Changes to win/makefile.vc.
| ︙ | ︙ | |||
250 251 252 253 254 255 256 257 258 259 260 261 262 263 | $(TMP_DIR)\tclAlloc.obj \ $(TMP_DIR)\tclAssembly.obj \ $(TMP_DIR)\tclAsync.obj \ $(TMP_DIR)\tclBasic.obj \ $(TMP_DIR)\tclBinary.obj \ $(TMP_DIR)\tclCkalloc.obj \ $(TMP_DIR)\tclClock.obj \ $(TMP_DIR)\tclCmdAH.obj \ $(TMP_DIR)\tclCmdIL.obj \ $(TMP_DIR)\tclCmdMZ.obj \ $(TMP_DIR)\tclCompCmds.obj \ $(TMP_DIR)\tclCompCmdsGR.obj \ $(TMP_DIR)\tclCompCmdsSZ.obj \ $(TMP_DIR)\tclCompExpr.obj \ | > | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | $(TMP_DIR)\tclAlloc.obj \ $(TMP_DIR)\tclAssembly.obj \ $(TMP_DIR)\tclAsync.obj \ $(TMP_DIR)\tclBasic.obj \ $(TMP_DIR)\tclBinary.obj \ $(TMP_DIR)\tclCkalloc.obj \ $(TMP_DIR)\tclClock.obj \ $(TMP_DIR)\tclClockFmt.obj \ $(TMP_DIR)\tclCmdAH.obj \ $(TMP_DIR)\tclCmdIL.obj \ $(TMP_DIR)\tclCmdMZ.obj \ $(TMP_DIR)\tclCompCmds.obj \ $(TMP_DIR)\tclCompCmdsGR.obj \ $(TMP_DIR)\tclCompCmdsSZ.obj \ $(TMP_DIR)\tclCompExpr.obj \ |
| ︙ | ︙ | |||
313 314 315 316 317 318 319 320 321 322 323 324 325 326 | $(TMP_DIR)\tclProc.obj \ $(TMP_DIR)\tclProcess.obj \ $(TMP_DIR)\tclRegexp.obj \ $(TMP_DIR)\tclResolve.obj \ $(TMP_DIR)\tclResult.obj \ $(TMP_DIR)\tclScan.obj \ $(TMP_DIR)\tclStringObj.obj \ $(TMP_DIR)\tclStrToD.obj \ $(TMP_DIR)\tclStubInit.obj \ $(TMP_DIR)\tclThread.obj \ $(TMP_DIR)\tclThreadAlloc.obj \ $(TMP_DIR)\tclThreadJoin.obj \ $(TMP_DIR)\tclThreadStorage.obj \ $(TMP_DIR)\tclTimer.obj \ | > | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | $(TMP_DIR)\tclProc.obj \ $(TMP_DIR)\tclProcess.obj \ $(TMP_DIR)\tclRegexp.obj \ $(TMP_DIR)\tclResolve.obj \ $(TMP_DIR)\tclResult.obj \ $(TMP_DIR)\tclScan.obj \ $(TMP_DIR)\tclStringObj.obj \ $(TMP_DIR)\tclStrIdxTree.obj \ $(TMP_DIR)\tclStrToD.obj \ $(TMP_DIR)\tclStubInit.obj \ $(TMP_DIR)\tclThread.obj \ $(TMP_DIR)\tclThreadAlloc.obj \ $(TMP_DIR)\tclThreadJoin.obj \ $(TMP_DIR)\tclThreadStorage.obj \ $(TMP_DIR)\tclTimer.obj \ |
| ︙ | ︙ | |||
363 364 365 366 367 368 369 | $(TMP_DIR)\bn_mp_cnt_lsb.obj \ $(TMP_DIR)\bn_mp_copy.obj \ $(TMP_DIR)\bn_mp_count_bits.obj \ $(TMP_DIR)\bn_mp_div.obj \ $(TMP_DIR)\bn_mp_div_d.obj \ $(TMP_DIR)\bn_mp_div_2.obj \ $(TMP_DIR)\bn_mp_div_2d.obj \ | | | | 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 | $(TMP_DIR)\bn_mp_cnt_lsb.obj \ $(TMP_DIR)\bn_mp_copy.obj \ $(TMP_DIR)\bn_mp_count_bits.obj \ $(TMP_DIR)\bn_mp_div.obj \ $(TMP_DIR)\bn_mp_div_d.obj \ $(TMP_DIR)\bn_mp_div_2.obj \ $(TMP_DIR)\bn_mp_div_2d.obj \ $(TMP_DIR)\bn_s_mp_div_3.obj \ $(TMP_DIR)\bn_mp_exch.obj \ $(TMP_DIR)\bn_mp_expt_n.obj \ $(TMP_DIR)\bn_mp_get_mag_u64.obj \ $(TMP_DIR)\bn_mp_grow.obj \ $(TMP_DIR)\bn_mp_init.obj \ $(TMP_DIR)\bn_mp_init_copy.obj \ $(TMP_DIR)\bn_mp_init_i64.obj \ $(TMP_DIR)\bn_mp_init_multi.obj \ $(TMP_DIR)\bn_mp_init_set.obj \ |
| ︙ | ︙ |
Changes to win/tclWinSerial.c.
| ︙ | ︙ | |||
1791 1792 1793 1794 1795 1796 1797 |
dcb.XonChar = argv[0][0];
dcb.XoffChar = argv[1][0];
if (argv[0][0] & 0x80 || argv[1][0] & 0x80) {
Tcl_UniChar character = 0;
int charLen;
| | | | 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 |
dcb.XonChar = argv[0][0];
dcb.XoffChar = argv[1][0];
if (argv[0][0] & 0x80 || argv[1][0] & 0x80) {
Tcl_UniChar character = 0;
int charLen;
charLen = TclUtfToUniChar(argv[0], &character);
if ((character > 0xFF) || argv[0][charLen]) {
goto badXchar;
}
dcb.XonChar = (char) character;
charLen = TclUtfToUniChar(argv[1], &character);
if ((character > 0xFF) || argv[1][charLen]) {
goto badXchar;
}
dcb.XoffChar = (char) character;
}
Tcl_Free((void *)argv);
|
| ︙ | ︙ |