diff options
Diffstat (limited to 'generic/tclClockFmt.c')
| -rw-r--r-- | generic/tclClockFmt.c | 178 |
1 files changed, 103 insertions, 75 deletions
diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 06684a6..cbb935d 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -33,6 +33,11 @@ static void ClockFrmScnFinalize(void *); */ static Tcl_HashKeyType ClockFmtScnStorageHashKeyType; + +#define IntFieldAt(info, offset) \ + ((int *) (((char *) (info)) + (offset))) +#define WideFieldAt(info, offset) \ + ((Tcl_WideInt *) (((char *) (info)) + (offset))) /* * Clock scan and format facilities. @@ -41,7 +46,7 @@ static Tcl_HashKeyType ClockFmtScnStorageHashKeyType; /* *---------------------------------------------------------------------- * - * _str2int -- , _str2wideInt -- + * Clock_str2int, Clock_str2wideInt -- * * Fast inline-convertion of string to signed int or wide int by given * start/end. @@ -57,7 +62,7 @@ static Tcl_HashKeyType ClockFmtScnStorageHashKeyType; */ static inline void -_str2int_no( +Clock_str2int_no( int *out, const char *p, const char *e, @@ -65,8 +70,9 @@ _str2int_no( { /* 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 */ + while (p < e) { /* never overflows */ val = val * 10 + (*p++ - '0'); } if (sign < 0) { @@ -76,7 +82,7 @@ _str2int_no( } static inline void -_str2wideInt_no( +Clock_str2wideInt_no( Tcl_WideInt *out, const char *p, const char *e, @@ -84,8 +90,9 @@ _str2wideInt_no( { /* 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 */ + while (p < e) { /* never overflows */ val = val * 10 + (*p++ - '0'); } if (sign < 0) { @@ -100,7 +107,7 @@ _str2wideInt_no( #endif static inline int -_str2int( +Clock_str2int( int *out, const char *p, const char *e, @@ -109,6 +116,7 @@ _str2int( 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; } @@ -118,6 +126,7 @@ _str2int( if (sign >= 0) { while (p < e) { /* check for overflow */ int prev = val; + val = val * 10 + (*p++ - '0'); if (val / 10 < prev) { return TCL_ERROR; @@ -127,6 +136,7 @@ _str2int( val = -val; while (p < e) { /* check for overflow */ int prev = val; + val = val * 10 - (*p++ - '0'); if (val / 10 > prev) { return TCL_ERROR; @@ -138,7 +148,7 @@ _str2int( } static inline int -_str2wideInt( +Clock_str2wideInt( Tcl_WideInt *out, const char *p, const char *e, @@ -147,6 +157,7 @@ _str2wideInt( 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; } @@ -156,6 +167,7 @@ _str2wideInt( 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; @@ -165,6 +177,7 @@ _str2wideInt( val = -val; while (p < e) { /* check for overflow */ Tcl_WideInt prev = val; + val = val * 10 - (*p++ - '0'); if (val / 10 > prev) { return TCL_ERROR; @@ -182,7 +195,7 @@ TclAtoWIe( const char *e, int sign) { - return _str2wideInt(out, p, e, sign); + return Clock_str2wideInt(out, p, e, sign); } #if defined(__GNUC__) || defined(__GNUG__) @@ -192,7 +205,7 @@ TclAtoWIe( /* *---------------------------------------------------------------------- * - * _itoaw -- , _witoaw -- + * Clock_itoaw, Clock_witoaw -- * * Fast inline-convertion of signed int or wide int to string, using * given padding with specified padchar and width (or without padding). @@ -206,14 +219,16 @@ TclAtoWIe( */ static inline char * -_itoaw( +Clock_itoaw( char *buf, int val, char padchar, unsigned short width) { char *p; - static int wrange[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; + static const int wrange[] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 + }; /* positive integer */ @@ -226,7 +241,8 @@ _itoaw( p = buf + width; *p-- = '\0'; do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' + c; } while (val > 0); @@ -254,13 +270,15 @@ _itoaw( /* differentiate platforms with -1 % 10 == 1 and -1 % 10 == -1 */ if (-1 % 10 == -1) { do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' - c; } while (val < 0); } else { do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' + c; } while (val < 0); @@ -287,18 +305,20 @@ TclItoAw( char padchar, unsigned short width) { - return _itoaw(buf, val, padchar, width); + return Clock_itoaw(buf, val, padchar, width); } static inline char * -_witoaw( +Clock_witoaw( char *buf, Tcl_WideInt val, char padchar, unsigned short width) { char *p; - static int wrange[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; + static const int wrange[] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 + }; /* positive integer */ @@ -306,6 +326,7 @@ _witoaw( /* check resp. recalculate width */ if (val >= 10000000000LL) { Tcl_WideInt val2 = val / 10000000000LL; + while (width <= 9 && val2 >= wrange[width]) { width++; } @@ -340,6 +361,7 @@ _witoaw( width--; if (val <= -10000000000LL) { Tcl_WideInt val2 = val / 10000000000LL; + while (width <= 9 && val2 <= -wrange[width]) { width++; } @@ -356,13 +378,15 @@ _witoaw( /* differentiate platforms with -1 % 10 == 1 and -1 % 10 == -1 */ if (-1 % 10 == -1) { do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' - c; } while (val < 0); } else { do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' + c; } while (val < 0); @@ -903,7 +927,7 @@ Tcl_Obj * ClockLocalizeFormat( ClockFmtScnCmdArgs *opts) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; Tcl_Obj *valObj = NULL, *keyObj; keyObj = ClockFrmObjGetLocFmtKey(opts->interp, opts->formatObj); @@ -1051,8 +1075,8 @@ DetermineGreedySearchLen( { int minLen = tok->map->minSize; int maxLen; - const char *p = yyInput + minLen, - *end = info->dateEnd; + const char *p = yyInput + minLen; + const char *end = info->dateEnd; /* if still tokens available, try to correct minimum length */ if ((tok + 1)->map) { @@ -1558,7 +1582,7 @@ ClockScnToken_DayOfWeek_Proc( } if (val > 7) { Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "day of week is greater than 7", -1)); + "day of week is greater than 7", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(opts->interp, "CLOCK", "badDayOfWeek", (char *)NULL); return TCL_ERROR; } @@ -1625,7 +1649,7 @@ ClockScnToken_LocaleERA_Proc( DateInfo *info, ClockScanToken *tok) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; int ret, val; int minLen, maxLen; @@ -1683,7 +1707,7 @@ ClockScnToken_LocaleListMatcher_Proc( } if (tok->map->offs > 0) { - *(int *)(((char *)info) + tok->map->offs) = --val; + *IntFieldAt(info, tok->map->offs) = --val; } return TCL_OK; @@ -1712,7 +1736,7 @@ ClockScnToken_JDN_Proc( while (p < end && isdigit(UCHAR(*p))) { p++; } - if (_str2wideInt(&intJD, s, p, (*yyInput != '-' ? 1 : -1)) != TCL_OK) { + if (Clock_str2wideInt(&intJD, s, p, (*yyInput != '-' ? 1 : -1)) != TCL_OK) { return TCL_RETURN; } yyInput = p; @@ -1730,7 +1754,7 @@ ClockScnToken_JDN_Proc( fractJDDiv *= 10; p++; } - if (_str2int(&fractJD, s, p, 1) != TCL_OK) { + if (Clock_str2int(&fractJD, s, p, 1) != TCL_OK) { return TCL_RETURN; } yyInput = p; @@ -1742,7 +1766,7 @@ ClockScnToken_JDN_Proc( */ fractJD = (int)tok->map->offs /* 0 for calendar or 43200 for astro JD */ - + (int)((Tcl_WideInt)SECONDS_PER_DAY * fractJD / fractJDDiv); + + (int)((Tcl_WideInt)SECONDS_PER_DAY * fractJD / fractJDDiv); if (fractJD > SECONDS_PER_DAY) { fractJD %= SECONDS_PER_DAY; intJD += 1; @@ -1840,7 +1864,7 @@ ClockScnToken_TimeZone_Proc( /* try to apply new time zone */ Tcl_IncrRefCount(tzObjStor); - opts->timezoneObj = ClockSetupTimeZone(opts->clientData, opts->interp, + opts->timezoneObj = ClockSetupTimeZone(opts->dataPtr, opts->interp, tzObjStor); Tcl_DecrRefCount(tzObjStor); @@ -1890,8 +1914,8 @@ ClockScnToken_StarDate_Proc( 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) { + if (Clock_str2int(&year, s, p - 3, 1) != TCL_OK + || Clock_str2int(&fractYear, p - 3, p, 1) != TCL_OK) { return TCL_RETURN; } if (*p++ != '.') { @@ -1903,7 +1927,7 @@ ClockScnToken_StarDate_Proc( fractDayDiv *= 10; p++; } - if (_str2int(&fractDay, s, p, 1) != TCL_OK) { + if (Clock_str2int(&fractDay, s, p, 1) != TCL_OK) { return TCL_RETURN; } yyInput = p; @@ -1934,6 +1958,10 @@ ClockScnToken_StarDate_Proc( return TCL_OK; } +/* + * Descriptors for the various fields in [clock scan]. + */ + static const char *ScnSTokenMapIndex = "dmbyYHMSpJjCgGVazUsntQ"; static const ClockScanTokenMap ScnSTokenMap[] = { /* %d %e */ @@ -2142,7 +2170,7 @@ ClockGetOrParseScanFormat( fss->scnSpaceCount = 0; scnTok = tok = (ClockScanToken *) ckalloc(sizeof(*tok) * fss->scnTokC); - memset(tok, 0, sizeof(*(tok))); + memset(tok, 0, sizeof(*tok)); tokCnt = 1; while (p < e) { switch (*p) { @@ -2249,10 +2277,11 @@ ClockGetOrParseScanFormat( tokCnt++; continue; } -word_tok: + word_tok: { ClockScanToken *wordTok = tok; - if (tok > scnTok && (tok-1)->map == &ScnWordTokenMap) { + + if (tok > scnTok && (tok - 1)->map == &ScnWordTokenMap) { wordTok = tok - 1; } /* new word token */ @@ -2275,7 +2304,7 @@ word_tok: /* calculate end distance value for each tokens */ if (tok > scnTok) { unsigned endDist = 0; - ClockScanToken *prevTok = tok-1; + ClockScanToken *prevTok = tok - 1; while (prevTok >= scnTok) { prevTok->endDistance = endDist; @@ -2316,7 +2345,7 @@ ClockScan( Tcl_Obj *strObj, /* String containing the time to scan */ ClockFmtScnCmdArgs *opts) /* Command options */ { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; ClockFmtScnStorage *fss; ClockScanToken *tok; const ClockScanTokenMap *map; @@ -2421,24 +2450,20 @@ ClockScan( x = p + size; if (map->type == CTOKT_INT) { if (size <= 10) { - _str2int_no((int *)(((char *)info) + map->offs), + Clock_str2int_no(IntFieldAt(info, map->offs), p, x, sign); - } else { - if (_str2int((int *)(((char *)info) + map->offs), - p, x, sign) != TCL_OK) { - goto overflow; - } + } else if (Clock_str2int( + IntFieldAt(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; - } + Clock_str2wideInt_no( + WideFieldAt(info, map->offs), p, x, sign); + } else if (Clock_str2wideInt( + WideFieldAt(info, map->offs), p, x, sign) != TCL_OK) { + goto overflow; } p = x; } @@ -2651,14 +2676,14 @@ ClockScan( overflow: Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "integer value too large to represent", -1)); + "integer value too large to represent", TCL_AUTO_LENGTH)); 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)); + "input string does not match supplied format", TCL_AUTO_LENGTH)); #else /* to debug where exactly scan breaks */ Tcl_SetObjResult(opts->interp, Tcl_ObjPrintf( @@ -2772,9 +2797,9 @@ ClockFmtToken_StarDate_Proc( } memcpy(dateFmt->output, "Stardate ", 9); dateFmt->output += 9; - dateFmt->output = _itoaw(dateFmt->output, + dateFmt->output = Clock_itoaw(dateFmt->output, dateFmt->date.year - RODDENBERRY, '0', 2); - dateFmt->output = _itoaw(dateFmt->output, + dateFmt->output = Clock_itoaw(dateFmt->output, fractYear, '0', 3); *dateFmt->output++ = '.'; /* be sure positive after decimal point (note: clock-value can be negative) */ @@ -2782,7 +2807,7 @@ ClockFmtToken_StarDate_Proc( if (v < 0) { v = 10 + v; } - dateFmt->output = _itoaw(dateFmt->output, v, '0', 1); + dateFmt->output = Clock_itoaw(dateFmt->output, v, '0', 1); return TCL_OK; } static int @@ -2837,7 +2862,7 @@ ClockFmtToken_JDN_Proc( if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { return TCL_ERROR; } - dateFmt->output = _witoaw(dateFmt->output, intJD, '0', 1); + dateFmt->output = Clock_witoaw(dateFmt->output, intJD, '0', 1); /* simplest cases .0 and .5 */ if (!fractJD || fractJD == (SECONDS_PER_DAY / 2)) { /* point + 0 or 5 */ @@ -2863,11 +2888,11 @@ ClockFmtToken_JDN_Proc( return TCL_ERROR; } *dateFmt->output++ = '.'; - p = _itoaw(dateFmt->output, fractJD, '0', JDN_MAX_PRECISION); + p = Clock_itoaw(dateFmt->output, fractJD, '0', JDN_MAX_PRECISION); /* remove trailing zero's */ dateFmt->output++; - while (p > dateFmt->output && *(p-1) == '0') { + while (p > dateFmt->output && p[-1] == '0') { p--; } *p = '\0'; @@ -2894,12 +2919,12 @@ ClockFmtToken_TimeZone_Proc( return TCL_ERROR; } *dateFmt->output++ = sign; - dateFmt->output = _itoaw(dateFmt->output, z / 3600, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, z / 3600, '0', 2); z %= 3600; - dateFmt->output = _itoaw(dateFmt->output, z / 60, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, z / 60, '0', 2); z %= 60; if (z != 0) { - dateFmt->output = _itoaw(dateFmt->output, z, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, z, '0', 2); } } else { Tcl_Obj * objPtr; @@ -2907,7 +2932,7 @@ ClockFmtToken_TimeZone_Proc( Tcl_Size len; /* convert seconds to local seconds to obtain tzName object */ - if (ConvertUTCToLocal(opts->clientData, opts->interp, + if (ConvertUTCToLocal(opts->dataPtr, opts->interp, &dateFmt->date, opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) { return TCL_ERROR; @@ -2986,12 +3011,10 @@ ClockFmtToken_LocaleERAYear_Proc( } if (*tok->tokWord.start == 'C') { /* %EC */ *val = dateFmt->date.year / 100; - dateFmt->output = _itoaw(dateFmt->output, - *val, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, *val, '0', 2); } else { /* %Ey */ *val = dateFmt->date.year % 100; - dateFmt->output = _itoaw(dateFmt->output, - *val, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, *val, '0', 2); } } else { Tcl_Obj *objPtr; @@ -3027,8 +3050,7 @@ ClockFmtToken_LocaleERAYear_Proc( if (FrmResultAllocate(dateFmt, 11) != TCL_OK) { return TCL_ERROR; } - dateFmt->output = _itoaw(dateFmt->output, - *val, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, *val, '0', 2); return TCL_OK; } } @@ -3042,6 +3064,10 @@ ClockFmtToken_LocaleERAYear_Proc( return TCL_OK; } +/* + * Descriptors for the various fields in [clock format]. + */ + static const char *FmtSTokenMapIndex = "demNbByYCHMSIklpaAuwUVzgGjJsntQ"; static const ClockFormatTokenMap FmtSTokenMap[] = { @@ -3219,7 +3245,7 @@ ClockGetOrParseFmtFormat( fss->fmtTokC = EstimateTokenCount(p, e); fmtTok = tok = (ClockFormatToken *) ckalloc(sizeof(*tok) * fss->fmtTokC); - memset(tok, 0, sizeof(*(tok))); + memset(tok, 0, sizeof(*tok)); tokCnt = 1; while (p < e) { switch (*p) { @@ -3293,8 +3319,8 @@ ClockGetOrParseFmtFormat( word_tok: { ClockFormatToken *wordTok = tok; - if (tok > fmtTok && (tok-1)->map == &FmtWordTokenMap) { - wordTok = tok-1; + if (tok > fmtTok && (tok - 1)->map == &FmtWordTokenMap) { + wordTok = tok - 1; } if (wordTok == tok) { wordTok->tokWord.start = p; @@ -3368,7 +3394,7 @@ ClockFormat( map = tok->map; switch (map->type) { case CTOKT_INT: { - int val = (int)*(int *)(((char *)dateFmt) + map->offs); + int val = *IntFieldAt(dateFmt, map->offs); if (map->fmtproc == NULL) { if (map->flags & CLFMT_DECR) { @@ -3397,13 +3423,15 @@ ClockFormat( goto error; } if (map->width) { - dateFmt->output = _itoaw(dateFmt->output, val, *map->tostr, map->width); + dateFmt->output = Clock_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; } @@ -3421,13 +3449,13 @@ ClockFormat( break; } case CTOKT_WIDE: { - Tcl_WideInt val = *(Tcl_WideInt *)(((char *)dateFmt) + map->offs); + Tcl_WideInt val = *WideFieldAt(dateFmt, map->offs); if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { goto error; } if (map->width) { - dateFmt->output = _witoaw(dateFmt->output, val, *map->tostr, map->width); + dateFmt->output = Clock_witoaw(dateFmt->output, val, *map->tostr, map->width); } else { dateFmt->output += sprintf(dateFmt->output, map->tostr, val); } |
