tclDate.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:55k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tclDate.c --
  3.  *
  4.  * This file is generated from a yacc grammar defined in
  5.  * the file tclGetDate.y.  It should not be edited directly.
  6.  *
  7.  * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
  8.  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * RCS: @(#) $Id: tclDate.c,v 1.20.4.3 2006/06/14 15:21:14 patthoyts Exp $
  14.  */
  15. #include "tclInt.h"
  16. #include "tclPort.h"
  17. #if defined(MAC_TCL) && !defined(TCL_MAC_USE_MSL_EPOCH)
  18. #   define EPOCH           1904
  19. #   define START_OF_TIME   1904
  20. #   define END_OF_TIME     2039
  21. #else
  22. #   define EPOCH           1970
  23. #   define START_OF_TIME   1902
  24. #   define END_OF_TIME     2037
  25. #endif
  26. /*
  27.  * The offset of tm_year of struct tm returned by localtime, gmtime, etc.
  28.  * I don't know how universal this is; K&R II, the NetBSD manpages, and
  29.  * ../compat/strftime.c all agree that tm_year is the year-1900.  However,
  30.  * some systems may have a different value.  This #define should be the
  31.  * same as in ../compat/strftime.c.
  32.  */
  33. #define TM_YEAR_BASE 1900
  34. #define HOUR(x)         ((int) (60 * x))
  35. #define SECSPERDAY      (24L * 60L * 60L)
  36. #define IsLeapYear(x)   ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
  37. /*
  38.  *  An entry in the lexical lookup table.
  39.  */
  40. typedef struct _TABLE {
  41.     char        *name;
  42.     int         type;
  43.     time_t      value;
  44. } TABLE;
  45. /*
  46.  *  Daylight-savings mode:  on, off, or not yet known.
  47.  */
  48. typedef enum _DSTMODE {
  49.     DSTon, DSToff, DSTmaybe
  50. } DSTMODE;
  51. /*
  52.  *  Meridian:  am, pm, or 24-hour style.
  53.  */
  54. typedef enum _MERIDIAN {
  55.     MERam, MERpm, MER24
  56. } MERIDIAN;
  57. /*
  58.  *  Global variables.  We could get rid of most of these by using a good
  59.  *  union as the yacc stack.  (This routine was originally written before
  60.  *  yacc had the %union construct.)  Maybe someday; right now we only use
  61.  *  the %union very rarely.
  62.  */
  63. static char     *TclDateInput;
  64. static DSTMODE  TclDateDSTmode;
  65. static time_t   TclDateDayOrdinal;
  66. static time_t   TclDateDayNumber;
  67. static time_t   TclDateMonthOrdinal;
  68. static int      TclDateHaveDate;
  69. static int      TclDateHaveDay;
  70. static int      TclDateHaveOrdinalMonth;
  71. static int      TclDateHaveRel;
  72. static int      TclDateHaveTime;
  73. static int      TclDateHaveZone;
  74. static time_t   TclDateTimezone;
  75. static time_t   TclDateDay;
  76. static time_t   TclDateHour;
  77. static time_t   TclDateMinutes;
  78. static time_t   TclDateMonth;
  79. static time_t   TclDateSeconds;
  80. static time_t   TclDateYear;
  81. static MERIDIAN TclDateMeridian;
  82. static time_t   TclDateRelMonth;
  83. static time_t   TclDateRelDay;
  84. static time_t   TclDateRelSeconds;
  85. static time_t  *TclDateRelPointer;
  86. /*
  87.  * Prototypes of internal functions.
  88.  */
  89. static void TclDateerror _ANSI_ARGS_((char *s));
  90. static time_t ToSeconds _ANSI_ARGS_((time_t Hours, time_t Minutes,
  91.     time_t Seconds, MERIDIAN Meridian));
  92. static int Convert _ANSI_ARGS_((time_t Month, time_t Day, time_t Year,
  93.     time_t Hours, time_t Minutes, time_t Seconds,
  94.     MERIDIAN Meridia, DSTMODE DSTmode, time_t *TimePtr));
  95. static time_t DSTcorrect _ANSI_ARGS_((time_t Start, time_t Future));
  96. static time_t NamedDay _ANSI_ARGS_((time_t Start, time_t DayOrdinal,
  97.     time_t DayNumber));
  98. static time_t   NamedMonth _ANSI_ARGS_((time_t Start, time_t MonthOrdinal,
  99.                     time_t MonthNumber));
  100. static int RelativeMonth _ANSI_ARGS_((time_t Start, time_t RelMonth,
  101.     time_t *TimePtr));
  102. static int RelativeDay _ANSI_ARGS_((time_t Start, time_t RelDay,
  103.     time_t *TimePtr));
  104. static int LookupWord _ANSI_ARGS_((char *buff));
  105. static int TclDatelex _ANSI_ARGS_((void));
  106. int
  107. TclDateparse _ANSI_ARGS_((void));
  108. typedef union
  109. #ifdef __cplusplus
  110. YYSTYPE
  111. #endif
  112.  {
  113.     time_t              Number;
  114.     enum _MERIDIAN      Meridian;
  115. } YYSTYPE;
  116. # define tAGO 257
  117. # define tDAY 258
  118. # define tDAYZONE 259
  119. # define tID 260
  120. # define tMERIDIAN 261
  121. # define tMINUTE_UNIT 262
  122. # define tMONTH 263
  123. # define tMONTH_UNIT 264
  124. # define tSTARDATE 265
  125. # define tSEC_UNIT 266
  126. # define tSNUMBER 267
  127. # define tUNUMBER 268
  128. # define tZONE 269
  129. # define tEPOCH 270
  130. # define tDST 271
  131. # define tISOBASE 272
  132. # define tDAY_UNIT 273
  133. # define tNEXT 274
  134. #if defined(__cplusplus) || defined(__STDC__)
  135. #if defined(__cplusplus) && defined(__EXTERN_C__)
  136. extern "C" {
  137. #endif
  138. #ifndef TclDateerror
  139. #if defined(__cplusplus)
  140. void TclDateerror(CONST char *);
  141. #endif
  142. #endif
  143. #ifndef TclDatelex
  144. int TclDatelex(void);
  145. #endif
  146. int TclDateparse(void);
  147. #if defined(__cplusplus) && defined(__EXTERN_C__)
  148. }
  149. #endif
  150. #endif
  151. #define TclDateclearin TclDatechar = -1
  152. #define TclDateerrok TclDateerrflag = 0
  153. extern int TclDatechar;
  154. extern int TclDateerrflag;
  155. YYSTYPE TclDatelval;
  156. YYSTYPE TclDateval;
  157. typedef int TclDatetabelem;
  158. #ifndef YYMAXDEPTH
  159. #define YYMAXDEPTH 150
  160. #endif
  161. #if YYMAXDEPTH > 0
  162. int TclDate_TclDates[YYMAXDEPTH], *TclDates = TclDate_TclDates;
  163. YYSTYPE TclDate_TclDatev[YYMAXDEPTH], *TclDatev = TclDate_TclDatev;
  164. #else /* user does initial allocation */
  165. int *TclDates;
  166. YYSTYPE *TclDatev;
  167. #endif
  168. static int TclDatemaxdepth = YYMAXDEPTH;
  169. # define YYERRCODE 256
  170. /*
  171.  * Month and day table.
  172.  */
  173. static TABLE    MonthDayTable[] = {
  174.     { "january",        tMONTH,  1 },
  175.     { "february",       tMONTH,  2 },
  176.     { "march",          tMONTH,  3 },
  177.     { "april",          tMONTH,  4 },
  178.     { "may",            tMONTH,  5 },
  179.     { "june",           tMONTH,  6 },
  180.     { "july",           tMONTH,  7 },
  181.     { "august",         tMONTH,  8 },
  182.     { "september",      tMONTH,  9 },
  183.     { "sept",           tMONTH,  9 },
  184.     { "october",        tMONTH, 10 },
  185.     { "november",       tMONTH, 11 },
  186.     { "december",       tMONTH, 12 },
  187.     { "sunday",         tDAY, 0 },
  188.     { "monday",         tDAY, 1 },
  189.     { "tuesday",        tDAY, 2 },
  190.     { "tues",           tDAY, 2 },
  191.     { "wednesday",      tDAY, 3 },
  192.     { "wednes",         tDAY, 3 },
  193.     { "thursday",       tDAY, 4 },
  194.     { "thur",           tDAY, 4 },
  195.     { "thurs",          tDAY, 4 },
  196.     { "friday",         tDAY, 5 },
  197.     { "saturday",       tDAY, 6 },
  198.     { NULL }
  199. };
  200. /*
  201.  * Time units table.
  202.  */
  203. static TABLE    UnitsTable[] = {
  204.     { "year",           tMONTH_UNIT,    12 },
  205.     { "month",          tMONTH_UNIT,     1 },
  206.     { "fortnight",      tDAY_UNIT,      14 },
  207.     { "week",           tDAY_UNIT,       7 },
  208.     { "day",            tDAY_UNIT,       1 },
  209.     { "hour",           tSEC_UNIT, 60 * 60 },
  210.     { "minute",         tSEC_UNIT,      60 },
  211.     { "min",            tSEC_UNIT,      60 },
  212.     { "second",         tSEC_UNIT,       1 },
  213.     { "sec",            tSEC_UNIT,       1 },
  214.     { NULL }
  215. };
  216. /*
  217.  * Assorted relative-time words.
  218.  */
  219. static TABLE    OtherTable[] = {
  220.     { "tomorrow",       tDAY_UNIT,      1 },
  221.     { "yesterday",      tDAY_UNIT,     -1 },
  222.     { "today",          tDAY_UNIT,      0 },
  223.     { "now",            tSEC_UNIT,      0 },
  224.     { "last",           tUNUMBER,      -1 },
  225.     { "this",           tSEC_UNIT,      0 },
  226.     { "next",           tNEXT,          1 },
  227. #if 0
  228.     { "first",          tUNUMBER,       1 },
  229.     { "second",         tUNUMBER,       2 },
  230.     { "third",          tUNUMBER,       3 },
  231.     { "fourth",         tUNUMBER,       4 },
  232.     { "fifth",          tUNUMBER,       5 },
  233.     { "sixth",          tUNUMBER,       6 },
  234.     { "seventh",        tUNUMBER,       7 },
  235.     { "eighth",         tUNUMBER,       8 },
  236.     { "ninth",          tUNUMBER,       9 },
  237.     { "tenth",          tUNUMBER,       10 },
  238.     { "eleventh",       tUNUMBER,       11 },
  239.     { "twelfth",        tUNUMBER,       12 },
  240. #endif
  241.     { "ago",            tAGO,   1 },
  242.     { "epoch",          tEPOCH,   0 },
  243.     { "stardate",       tSTARDATE, 0},
  244.     { NULL }
  245. };
  246. /*
  247.  * The timezone table.  (Note: This table was modified to not use any floating
  248.  * point constants to work around an SGI compiler bug).
  249.  */
  250. static TABLE    TimezoneTable[] = {
  251.     { "gmt",    tZONE,     HOUR( 0) },      /* Greenwich Mean */
  252.     { "ut",     tZONE,     HOUR( 0) },      /* Universal (Coordinated) */
  253.     { "utc",    tZONE,     HOUR( 0) },
  254.     { "uct",    tZONE,     HOUR( 0) },      /* Universal Coordinated Time */
  255.     { "wet",    tZONE,     HOUR( 0) },      /* Western European */
  256.     { "bst",    tDAYZONE,  HOUR( 0) },      /* British Summer */
  257.     { "wat",    tZONE,     HOUR( 1) },      /* West Africa */
  258.     { "at",     tZONE,     HOUR( 2) },      /* Azores */
  259. #if     0
  260.     /* For completeness.  BST is also British Summer, and GST is
  261.      * also Guam Standard. */
  262.     { "bst",    tZONE,     HOUR( 3) },      /* Brazil Standard */
  263.     { "gst",    tZONE,     HOUR( 3) },      /* Greenland Standard */
  264. #endif
  265.     { "nft",    tZONE,     HOUR( 7/2) },    /* Newfoundland */
  266.     { "nst",    tZONE,     HOUR( 7/2) },    /* Newfoundland Standard */
  267.     { "ndt",    tDAYZONE,  HOUR( 7/2) },    /* Newfoundland Daylight */
  268.     { "ast",    tZONE,     HOUR( 4) },      /* Atlantic Standard */
  269.     { "adt",    tDAYZONE,  HOUR( 4) },      /* Atlantic Daylight */
  270.     { "est",    tZONE,     HOUR( 5) },      /* Eastern Standard */
  271.     { "edt",    tDAYZONE,  HOUR( 5) },      /* Eastern Daylight */
  272.     { "cst",    tZONE,     HOUR( 6) },      /* Central Standard */
  273.     { "cdt",    tDAYZONE,  HOUR( 6) },      /* Central Daylight */
  274.     { "mst",    tZONE,     HOUR( 7) },      /* Mountain Standard */
  275.     { "mdt",    tDAYZONE,  HOUR( 7) },      /* Mountain Daylight */
  276.     { "pst",    tZONE,     HOUR( 8) },      /* Pacific Standard */
  277.     { "pdt",    tDAYZONE,  HOUR( 8) },      /* Pacific Daylight */
  278.     { "yst",    tZONE,     HOUR( 9) },      /* Yukon Standard */
  279.     { "ydt",    tDAYZONE,  HOUR( 9) },      /* Yukon Daylight */
  280.     { "hst",    tZONE,     HOUR(10) },      /* Hawaii Standard */
  281.     { "hdt",    tDAYZONE,  HOUR(10) },      /* Hawaii Daylight */
  282.     { "cat",    tZONE,     HOUR(10) },      /* Central Alaska */
  283.     { "ahst",   tZONE,     HOUR(10) },      /* Alaska-Hawaii Standard */
  284.     { "nt",     tZONE,     HOUR(11) },      /* Nome */
  285.     { "idlw",   tZONE,     HOUR(12) },      /* International Date Line West */
  286.     { "cet",    tZONE,    -HOUR( 1) },      /* Central European */
  287.     { "cest",   tDAYZONE, -HOUR( 1) },      /* Central European Summer */
  288.     { "met",    tZONE,    -HOUR( 1) },      /* Middle European */
  289.     { "mewt",   tZONE,    -HOUR( 1) },      /* Middle European Winter */
  290.     { "mest",   tDAYZONE, -HOUR( 1) },      /* Middle European Summer */
  291.     { "swt",    tZONE,    -HOUR( 1) },      /* Swedish Winter */
  292.     { "sst",    tDAYZONE, -HOUR( 1) },      /* Swedish Summer */
  293.     { "fwt",    tZONE,    -HOUR( 1) },      /* French Winter */
  294.     { "fst",    tDAYZONE, -HOUR( 1) },      /* French Summer */
  295.     { "eet",    tZONE,    -HOUR( 2) },      /* Eastern Europe, USSR Zone 1 */
  296.     { "bt",     tZONE,    -HOUR( 3) },      /* Baghdad, USSR Zone 2 */
  297.     { "it",     tZONE,    -HOUR( 7/2) },    /* Iran */
  298.     { "zp4",    tZONE,    -HOUR( 4) },      /* USSR Zone 3 */
  299.     { "zp5",    tZONE,    -HOUR( 5) },      /* USSR Zone 4 */
  300.     { "ist",    tZONE,    -HOUR(11/2) },    /* Indian Standard */
  301.     { "zp6",    tZONE,    -HOUR( 6) },      /* USSR Zone 5 */
  302. #if     0
  303.     /* For completeness.  NST is also Newfoundland Stanard, nad SST is
  304.      * also Swedish Summer. */
  305.     { "nst",    tZONE,    -HOUR(13/2) },    /* North Sumatra */
  306.     { "sst",    tZONE,    -HOUR( 7) },      /* South Sumatra, USSR Zone 6 */
  307. #endif  /* 0 */
  308.     { "wast",   tZONE,    -HOUR( 7) },      /* West Australian Standard */
  309.     { "wadt",   tDAYZONE, -HOUR( 7) },      /* West Australian Daylight */
  310.     { "jt",     tZONE,    -HOUR(15/2) },    /* Java (3pm in Cronusland!) */
  311.     { "cct",    tZONE,    -HOUR( 8) },      /* China Coast, USSR Zone 7 */
  312.     { "jst",    tZONE,    -HOUR( 9) },      /* Japan Standard, USSR Zone 8 */
  313.     { "jdt",    tDAYZONE, -HOUR( 9) },      /* Japan Daylight */
  314.     { "kst",    tZONE,    -HOUR( 9) },      /* Korea Standard */
  315.     { "kdt",    tDAYZONE, -HOUR( 9) },      /* Korea Daylight */
  316.     { "cast",   tZONE,    -HOUR(19/2) },    /* Central Australian Standard */
  317.     { "cadt",   tDAYZONE, -HOUR(19/2) },    /* Central Australian Daylight */
  318.     { "east",   tZONE,    -HOUR(10) },      /* Eastern Australian Standard */
  319.     { "eadt",   tDAYZONE, -HOUR(10) },      /* Eastern Australian Daylight */
  320.     { "gst",    tZONE,    -HOUR(10) },      /* Guam Standard, USSR Zone 9 */
  321.     { "nzt",    tZONE,    -HOUR(12) },      /* New Zealand */
  322.     { "nzst",   tZONE,    -HOUR(12) },      /* New Zealand Standard */
  323.     { "nzdt",   tDAYZONE, -HOUR(12) },      /* New Zealand Daylight */
  324.     { "idle",   tZONE,    -HOUR(12) },      /* International Date Line East */
  325.     /* ADDED BY Marco Nijdam */
  326.     { "dst",    tDST,     HOUR( 0) },       /* DST on (hour is ignored) */
  327.     /* End ADDED */
  328.     {  NULL  }
  329. };
  330. /*
  331.  * Military timezone table.
  332.  */
  333. static TABLE    MilitaryTable[] = {
  334.     { "a",      tZONE,  HOUR(  1) },
  335.     { "b",      tZONE,  HOUR(  2) },
  336.     { "c",      tZONE,  HOUR(  3) },
  337.     { "d",      tZONE,  HOUR(  4) },
  338.     { "e",      tZONE,  HOUR(  5) },
  339.     { "f",      tZONE,  HOUR(  6) },
  340.     { "g",      tZONE,  HOUR(  7) },
  341.     { "h",      tZONE,  HOUR(  8) },
  342.     { "i",      tZONE,  HOUR(  9) },
  343.     { "k",      tZONE,  HOUR( 10) },
  344.     { "l",      tZONE,  HOUR( 11) },
  345.     { "m",      tZONE,  HOUR( 12) },
  346.     { "n",      tZONE,  HOUR(- 1) },
  347.     { "o",      tZONE,  HOUR(- 2) },
  348.     { "p",      tZONE,  HOUR(- 3) },
  349.     { "q",      tZONE,  HOUR(- 4) },
  350.     { "r",      tZONE,  HOUR(- 5) },
  351.     { "s",      tZONE,  HOUR(- 6) },
  352.     { "t",      tZONE,  HOUR(- 7) },
  353.     { "u",      tZONE,  HOUR(- 8) },
  354.     { "v",      tZONE,  HOUR(- 9) },
  355.     { "w",      tZONE,  HOUR(-10) },
  356.     { "x",      tZONE,  HOUR(-11) },
  357.     { "y",      tZONE,  HOUR(-12) },
  358.     { "z",      tZONE,  HOUR(  0) },
  359.     { NULL }
  360. };
  361. /*
  362.  * Dump error messages in the bit bucket.
  363.  */
  364. static void
  365. TclDateerror(s)
  366.     char  *s;
  367. {
  368. }
  369. static time_t
  370. ToSeconds(Hours, Minutes, Seconds, Meridian)
  371.     time_t      Hours;
  372.     time_t      Minutes;
  373.     time_t      Seconds;
  374.     MERIDIAN    Meridian;
  375. {
  376.     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
  377.         return -1;
  378.     switch (Meridian) {
  379.     case MER24:
  380.         if (Hours < 0 || Hours > 23)
  381.             return -1;
  382.         return (Hours * 60L + Minutes) * 60L + Seconds;
  383.     case MERam:
  384.         if (Hours < 1 || Hours > 12)
  385.             return -1;
  386.         return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
  387.     case MERpm:
  388.         if (Hours < 1 || Hours > 12)
  389.             return -1;
  390.         return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
  391.     }
  392.     return -1;  /* Should never be reached */
  393. }
  394. /*
  395.  *-----------------------------------------------------------------------------
  396.  *
  397.  * Convert --
  398.  *
  399.  *      Convert a {month, day, year, hours, minutes, seconds, meridian, dst}
  400.  *      tuple into a clock seconds value.
  401.  *
  402.  * Results:
  403.  *      0 or -1 indicating success or failure.
  404.  *
  405.  * Side effects:
  406.  *      Fills TimePtr with the computed value.
  407.  *
  408.  *-----------------------------------------------------------------------------
  409.  */
  410. static int
  411. Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr)
  412.     time_t      Month;
  413.     time_t      Day;
  414.     time_t      Year;
  415.     time_t      Hours;
  416.     time_t      Minutes;
  417.     time_t      Seconds;
  418.     MERIDIAN    Meridian;
  419.     DSTMODE     DSTmode;
  420.     time_t     *TimePtr;
  421. {
  422.     static int  DaysInMonth[12] = {
  423.         31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  424.     };
  425.     time_t tod;
  426.     time_t Julian;
  427.     int i;
  428.     /* Figure out how many days are in February for the given year.
  429.      * Every year divisible by 4 is a leap year.
  430.      * But, every year divisible by 100 is not a leap year.
  431.      * But, every year divisible by 400 is a leap year after all.
  432.      */
  433.     DaysInMonth[1] = IsLeapYear(Year) ? 29 : 28;
  434.     /* Check the inputs for validity */
  435.     if (Month < 1 || Month > 12
  436.     || Year < START_OF_TIME || Year > END_OF_TIME
  437.     || Day < 1 || Day > DaysInMonth[(int)--Month])
  438.         return -1;
  439.     /* Start computing the value.  First determine the number of days
  440.      * represented by the date, then multiply by the number of seconds/day.
  441.      */
  442.     for (Julian = Day - 1, i = 0; i < Month; i++)
  443.         Julian += DaysInMonth[i];
  444.     if (Year >= EPOCH) {
  445.         for (i = EPOCH; i < Year; i++)
  446.             Julian += 365 + IsLeapYear(i);
  447.     } else {
  448.         for (i = (int)Year; i < EPOCH; i++)
  449.             Julian -= 365 + IsLeapYear(i);
  450.     }
  451.     Julian *= SECSPERDAY;
  452.     /* Add the timezone offset ?? */
  453.     Julian += TclDateTimezone * 60L;
  454.     /* Add the number of seconds represented by the time component */
  455.     if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
  456.         return -1;
  457.     Julian += tod;
  458.     /* Perform a preliminary DST compensation ?? */
  459.     if (DSTmode == DSTon
  460.      || (DSTmode == DSTmaybe && TclpGetDate((TclpTime_t)&Julian, 0)->tm_isdst))
  461.         Julian -= 60 * 60;
  462.     *TimePtr = Julian;
  463.     return 0;
  464. }
  465. static time_t
  466. DSTcorrect(Start, Future)
  467.     time_t      Start;
  468.     time_t      Future;
  469. {
  470.     time_t      StartDay;
  471.     time_t      FutureDay;
  472.     StartDay = (TclpGetDate((TclpTime_t)&Start, 0)->tm_hour + 1) % 24;
  473.     FutureDay = (TclpGetDate((TclpTime_t)&Future, 0)->tm_hour + 1) % 24;
  474.     return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
  475. }
  476. static time_t
  477. NamedDay(Start, DayOrdinal, DayNumber)
  478.     time_t      Start;
  479.     time_t      DayOrdinal;
  480.     time_t      DayNumber;
  481. {
  482.     struct tm   *tm;
  483.     time_t      now;
  484.     now = Start;
  485.     tm = TclpGetDate((TclpTime_t)&now, 0);
  486.     now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
  487.     now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
  488.     return DSTcorrect(Start, now);
  489. }
  490. static time_t
  491. NamedMonth(Start, MonthOrdinal, MonthNumber)
  492.     time_t Start;
  493.     time_t MonthOrdinal;
  494.     time_t MonthNumber;
  495. {
  496.     struct tm *tm;
  497.     time_t now;
  498.     int result;
  499.     
  500.     now = Start;
  501.     tm = TclpGetDate((TclpTime_t)&now, 0);
  502.     /* To compute the next n'th month, we use this alg:
  503.      * add n to year value
  504.      * if currentMonth < requestedMonth decrement year value by 1 (so that
  505.      *  doing next february from january gives us february of the current year)
  506.      * set day to 1, time to 0
  507.      */
  508.     tm->tm_year += (int)MonthOrdinal;
  509.     if (tm->tm_mon < MonthNumber - 1) {
  510. tm->tm_year--;
  511.     }
  512.     result = Convert(MonthNumber, (time_t) 1, tm->tm_year + TM_YEAR_BASE,
  513.     (time_t) 0, (time_t) 0, (time_t) 0, MER24, DSTmaybe, &now);
  514.     if (result < 0) {
  515. return 0;
  516.     }
  517.     return DSTcorrect(Start, now);
  518. }
  519. static int
  520. RelativeMonth(Start, RelMonth, TimePtr)
  521.     time_t Start;
  522.     time_t RelMonth;
  523.     time_t *TimePtr;
  524. {
  525.     struct tm *tm;
  526.     time_t Month;
  527.     time_t Year;
  528.     time_t Julian;
  529.     int result;
  530.     if (RelMonth == 0) {
  531.         *TimePtr = 0;
  532.         return 0;
  533.     }
  534.     tm = TclpGetDate((TclpTime_t)&Start, 0);
  535.     Month = 12 * (tm->tm_year + TM_YEAR_BASE) + tm->tm_mon + RelMonth;
  536.     Year = Month / 12;
  537.     Month = Month % 12 + 1;
  538.     result = Convert(Month, (time_t) tm->tm_mday, Year,
  539.     (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
  540.     MER24, DSTmaybe, &Julian);
  541.     /*
  542.      * The Julian time returned above is behind by one day, if "month" 
  543.      * or "year" is used to specify relative time and the GMT flag is true.
  544.      * This problem occurs only when the current time is closer to
  545.      * midnight, the difference being not more than its time difference
  546.      * with GMT. For example, in US/Pacific time zone, the problem occurs
  547.      * whenever the current time is between midnight to 8:00am or 7:00amDST.
  548.      * See Bug# 413397 for more details and sample script.
  549.      * To resolve this bug, we simply add the number of seconds corresponding
  550.      * to timezone difference with GMT to Julian time, if GMT flag is true.
  551.      */
  552.     if (TclDateTimezone == 0) {
  553.         Julian += TclpGetTimeZone((unsigned long) Start) * 60L;
  554.     }
  555.     /*
  556.      * The following iteration takes into account the case were we jump
  557.      * into a "short month".  Far example, "one month from Jan 31" will
  558.      * fail because there is no Feb 31.  The code below will reduce the
  559.      * day and try converting the date until we succed or the date equals
  560.      * 28 (which always works unless the date is bad in another way).
  561.      */
  562.     while ((result != 0) && (tm->tm_mday > 28)) {
  563. tm->tm_mday--;
  564. result = Convert(Month, (time_t) tm->tm_mday, Year,
  565. (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
  566. MER24, DSTmaybe, &Julian);
  567.     }
  568.     if (result != 0) {
  569. return -1;
  570.     }
  571.     *TimePtr = DSTcorrect(Start, Julian);
  572.     return 0;
  573. }
  574. /*
  575.  *-----------------------------------------------------------------------------
  576.  *
  577.  * RelativeDay --
  578.  *
  579.  *      Given a starting time and a number of days before or after, compute the
  580.  *      DST corrected difference between those dates.
  581.  *
  582.  * Results:
  583.  *     1 or -1 indicating success or failure.
  584.  *
  585.  * Side effects:
  586.  *      Fills TimePtr with the computed value.
  587.  *
  588.  *-----------------------------------------------------------------------------
  589.  */
  590. static int
  591. RelativeDay(Start, RelDay, TimePtr)
  592.     time_t Start;
  593.     time_t RelDay;
  594.     time_t *TimePtr;
  595. {
  596.     time_t new;
  597.     new = Start + (RelDay * 60 * 60 * 24);
  598.     *TimePtr = DSTcorrect(Start, new);
  599.     return 1;
  600. }
  601. static int
  602. LookupWord(buff)
  603.     char                *buff;
  604. {
  605.     register char *p;
  606.     register char *q;
  607.     register TABLE *tp;
  608.     int i;
  609.     int abbrev;
  610.     /*
  611.      * Make it lowercase.
  612.      */
  613.     Tcl_UtfToLower(buff);
  614.     if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
  615.         TclDatelval.Meridian = MERam;
  616.         return tMERIDIAN;
  617.     }
  618.     if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
  619.         TclDatelval.Meridian = MERpm;
  620.         return tMERIDIAN;
  621.     }
  622.     /*
  623.      * See if we have an abbreviation for a month.
  624.      */
  625.     if (strlen(buff) == 3) {
  626.         abbrev = 1;
  627.     } else if (strlen(buff) == 4 && buff[3] == '.') {
  628.         abbrev = 1;
  629.         buff[3] = '';
  630.     } else {
  631.         abbrev = 0;
  632.     }
  633.     for (tp = MonthDayTable; tp->name; tp++) {
  634.         if (abbrev) {
  635.             if (strncmp(buff, tp->name, 3) == 0) {
  636.                 TclDatelval.Number = tp->value;
  637.                 return tp->type;
  638.             }
  639.         } else if (strcmp(buff, tp->name) == 0) {
  640.             TclDatelval.Number = tp->value;
  641.             return tp->type;
  642.         }
  643.     }
  644.     for (tp = TimezoneTable; tp->name; tp++) {
  645.         if (strcmp(buff, tp->name) == 0) {
  646.             TclDatelval.Number = tp->value;
  647.             return tp->type;
  648.         }
  649.     }
  650.     for (tp = UnitsTable; tp->name; tp++) {
  651.         if (strcmp(buff, tp->name) == 0) {
  652.             TclDatelval.Number = tp->value;
  653.             return tp->type;
  654.         }
  655.     }
  656.     /*
  657.      * Strip off any plural and try the units table again.
  658.      */
  659.     i = strlen(buff) - 1;
  660.     if (buff[i] == 's') {
  661.         buff[i] = '';
  662.         for (tp = UnitsTable; tp->name; tp++) {
  663.             if (strcmp(buff, tp->name) == 0) {
  664.                 TclDatelval.Number = tp->value;
  665.                 return tp->type;
  666.             }
  667. }
  668.     }
  669.     for (tp = OtherTable; tp->name; tp++) {
  670.         if (strcmp(buff, tp->name) == 0) {
  671.             TclDatelval.Number = tp->value;
  672.             return tp->type;
  673.         }
  674.     }
  675.     /*
  676.      * Military timezones.
  677.      */
  678.     if (buff[1] == '' && !(*buff & 0x80)
  679.     && isalpha(UCHAR(*buff))) { /* INTL: ISO only */
  680.         for (tp = MilitaryTable; tp->name; tp++) {
  681.             if (strcmp(buff, tp->name) == 0) {
  682.                 TclDatelval.Number = tp->value;
  683.                 return tp->type;
  684.             }
  685. }
  686.     }
  687.     /*
  688.      * Drop out any periods and try the timezone table again.
  689.      */
  690.     for (i = 0, p = q = buff; *q; q++)
  691.         if (*q != '.') {
  692.             *p++ = *q;
  693.         } else {
  694.             i++;
  695. }
  696.     *p = '';
  697.     if (i) {
  698.         for (tp = TimezoneTable; tp->name; tp++) {
  699.             if (strcmp(buff, tp->name) == 0) {
  700.                 TclDatelval.Number = tp->value;
  701.                 return tp->type;
  702.             }
  703. }
  704.     }
  705.     
  706.     return tID;
  707. }
  708. static int
  709. TclDatelex()
  710. {
  711.     register char       c;
  712.     register char       *p;
  713.     char                buff[20];
  714.     int                 Count;
  715.     for ( ; ; ) {
  716.         while (isspace(UCHAR(*TclDateInput))) {
  717.             TclDateInput++;
  718. }
  719.         if (isdigit(UCHAR(c = *TclDateInput))) { /* INTL: digit */
  720.     /* convert the string into a number; count the number of digits */
  721.     Count = 0;
  722.             for (TclDatelval.Number = 0;
  723.     isdigit(UCHAR(c = *TclDateInput++)); ) { /* INTL: digit */
  724.                 TclDatelval.Number = 10 * TclDatelval.Number + c - '0';
  725. Count++;
  726.     }
  727.             TclDateInput--;
  728.     /* A number with 6 or more digits is considered an ISO 8601 base */
  729.     if (Count >= 6) {
  730. return tISOBASE;
  731.     } else {
  732. return tUNUMBER;
  733.     }
  734.         }
  735.         if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */
  736.             for (p = buff; isalpha(UCHAR(c = *TclDateInput++)) /* INTL: ISO only. */
  737.      || c == '.'; ) {
  738.                 if (p < &buff[sizeof buff - 1]) {
  739.                     *p++ = c;
  740. }
  741.     }
  742.             *p = '';
  743.             TclDateInput--;
  744.             return LookupWord(buff);
  745.         }
  746.         if (c != '(') {
  747.             return *TclDateInput++;
  748. }
  749.         Count = 0;
  750.         do {
  751.             c = *TclDateInput++;
  752.             if (c == '') {
  753.                 return c;
  754.     } else if (c == '(') {
  755.                 Count++;
  756.     } else if (c == ')') {
  757.                 Count--;
  758.     }
  759.         } while (Count > 0);
  760.     }
  761. }
  762. /*
  763.  * Specify zone is of -50000 to force GMT.  (This allows BST to work).
  764.  */
  765. int
  766. TclGetDate(p, now, zone, timePtr)
  767.     char *p;
  768.     Tcl_WideInt now;
  769.     long zone;
  770.     Tcl_WideInt *timePtr;
  771. {
  772.     struct tm *tm;
  773.     time_t Start;
  774.     time_t Time;
  775.     time_t tod;
  776.     int thisyear;
  777.     TclDateInput = p;
  778.     /* now has to be cast to a time_t for 64bit compliance */
  779.     Start = (time_t) now;
  780.     tm = TclpGetDate((TclpTime_t) &Start, (zone == -50000));
  781.     thisyear = tm->tm_year + TM_YEAR_BASE;
  782.     TclDateYear = thisyear;
  783.     TclDateMonth = tm->tm_mon + 1;
  784.     TclDateDay = tm->tm_mday;
  785.     TclDateTimezone = zone;
  786.     if (zone == -50000) {
  787.         TclDateDSTmode = DSToff;  /* assume GMT */
  788.         TclDateTimezone = 0;
  789.     } else {
  790.         TclDateDSTmode = DSTmaybe;
  791.     }
  792.     TclDateHour = 0;
  793.     TclDateMinutes = 0;
  794.     TclDateSeconds = 0;
  795.     TclDateMeridian = MER24;
  796.     TclDateRelSeconds = 0;
  797.     TclDateRelMonth = 0;
  798.     TclDateRelDay = 0;
  799.     TclDateRelPointer = NULL;
  800.     TclDateHaveDate = 0;
  801.     TclDateHaveDay = 0;
  802.     TclDateHaveOrdinalMonth = 0;
  803.     TclDateHaveRel = 0;
  804.     TclDateHaveTime = 0;
  805.     TclDateHaveZone = 0;
  806.     if (TclDateparse() || TclDateHaveTime > 1 || TclDateHaveZone > 1 || TclDateHaveDate > 1 ||
  807.     TclDateHaveDay > 1 || TclDateHaveOrdinalMonth > 1) {
  808.         return -1;
  809.     }
  810.     
  811.     if (TclDateHaveDate || TclDateHaveTime || TclDateHaveDay) {
  812. if (TclDateYear < 0) {
  813.     TclDateYear = -TclDateYear;
  814. }
  815. /*
  816.  * The following line handles years that are specified using
  817.  * only two digits.  The line of code below implements a policy
  818.  * defined by the X/Open workgroup on the millinium rollover.
  819.  * Note: some of those dates may not actually be valid on some
  820.  * platforms.  The POSIX standard startes that the dates 70-99
  821.  * shall refer to 1970-1999 and 00-38 shall refer to 2000-2038.
  822.  * This later definition should work on all platforms.
  823.  */
  824. if (TclDateYear < 100) {
  825.     if (TclDateYear >= 69) {
  826. TclDateYear += 1900;
  827.     } else {
  828. TclDateYear += 2000;
  829.     }
  830. }
  831. if (Convert(TclDateMonth, TclDateDay, TclDateYear, TclDateHour, TclDateMinutes, TclDateSeconds,
  832. TclDateMeridian, TclDateDSTmode, &Start) < 0) {
  833.             return -1;
  834. }
  835.     } else {
  836.         Start = (time_t) now;
  837.         if (!TclDateHaveRel) {
  838.             Start -= ((tm->tm_hour * 60L * 60L) +
  839.     tm->tm_min * 60L) + tm->tm_sec;
  840. }
  841.     }
  842.     Start += TclDateRelSeconds;
  843.     if (RelativeMonth(Start, TclDateRelMonth, &Time) < 0) {
  844.         return -1;
  845.     }
  846.     Start += Time;
  847.     if (RelativeDay(Start, TclDateRelDay, &Time) < 0) {
  848. return -1;
  849.     }
  850.     Start += Time;
  851.     
  852.     if (TclDateHaveDay && !TclDateHaveDate) {
  853.         tod = NamedDay(Start, TclDateDayOrdinal, TclDateDayNumber);
  854.         Start += tod;
  855.     }
  856.     if (TclDateHaveOrdinalMonth) {
  857. tod = NamedMonth(Start, TclDateMonthOrdinal, TclDateMonth);
  858. Start += tod;
  859.     }
  860.     
  861.     *timePtr = Start;
  862.     return 0;
  863. }
  864. static CONST TclDatetabelem TclDateexca[] ={
  865. -1, 1,
  866. 0, -1,
  867. -2, 0,
  868. };
  869. # define YYNPROD 56
  870. # define YYLAST 261
  871. static CONST TclDatetabelem TclDateact[]={
  872.     24,    40,    23,    36,    54,    81,    41,    28,    53,    26,
  873.     37,    42,    58,    38,    56,    28,    27,    26,    28,    33,
  874.     26,    32,    61,    50,    27,    80,    76,    27,    51,    75,
  875.     74,    73,    30,    72,    71,    70,    69,    52,    49,    48,
  876.     47,    45,    39,    62,    78,    46,    79,    68,    25,    65,
  877.     60,    67,    66,    55,    44,    21,    63,    11,    10,     9,
  878.      8,    35,     7,     6,     5,     4,     3,    43,     2,     1,
  879.     20,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  880.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  881.      0,    57,     0,     0,    59,    77,     0,     0,     0,     0,
  882.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  883.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  884.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  885.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  886.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  887.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  888.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  889.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  890.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  891.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  892.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  893.      0,     0,     0,     0,     0,    19,    14,     0,     0,     0,
  894.     16,    28,    22,    26,     0,    12,    13,    17,     0,    15,
  895.     27,    18,    31,     0,     0,    29,     0,    34,    28,     0,
  896.     26,     0,     0,     0,     0,     0,     0,    27,     0,     0,
  897.      0,     0,     0,     0,     0,     0,     0,     0,     0,    64,
  898.     64 };
  899. static CONST TclDatetabelem TclDatepact[]={
  900. -10000000,   -43,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,
  901. -10000000,-10000000,   -26,  -268,-10000000,  -259,  -226,-10000000,  -257,    10,
  902.   -227,  -212,  -228,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,
  903.   -229,-10000000,  -230,  -240,  -231,-10000000,-10000000,  -264,-10000000,     9,
  904. -10000000,-10000000,  -249,-10000000,-10000000,  -246,-10000000,     4,    -2,     2,
  905.      7,     6,-10000000,-10000000,   -11,  -232,-10000000,-10000000,-10000000,-10000000,
  906.   -233,-10000000,  -234,  -235,-10000000,  -237,  -238,  -239,  -242,-10000000,
  907. -10000000,-10000000,    -1,-10000000,-10000000,-10000000,   -12,-10000000,  -243,  -263,
  908. -10000000,-10000000 };
  909. static CONST TclDatetabelem TclDatepgo[]={
  910.      0,    48,    70,    22,    69,    68,    66,    65,    64,    63,
  911.     62,    60,    59,    58,    57,    55 };
  912. static CONST TclDatetabelem TclDater1[]={
  913.      0,     4,     4,     5,     5,     5,     5,     5,     5,     5,
  914.      5,     5,     6,     6,     6,     6,     6,     7,     7,     7,
  915.     10,    10,    10,    10,    10,     8,     8,     8,     8,     8,
  916.      8,     8,     8,     8,     8,     9,     9,    12,    12,    12,
  917.     13,    11,    11,    15,    15,    15,    15,    15,     2,     2,
  918.      1,     1,     1,    14,     3,     3 };
  919. static CONST TclDatetabelem TclDater2[]={
  920.      0,     0,     4,     3,     3,     3,     3,     3,     3,     3,
  921.      3,     2,     5,     9,    11,    13,    15,     5,     3,     3,
  922.      3,     5,     5,     7,     5,     7,    11,     3,    11,    11,
  923.      5,     9,     5,     3,     7,     5,     7,     7,    15,     5,
  924.      9,     5,     2,     7,     5,     5,     7,     3,     3,     3,
  925.      3,     3,     3,     3,     1,     3 };
  926. static CONST TclDatetabelem TclDatechk[]={
  927. -10000000,    -4,    -5,    -6,    -7,    -8,    -9,   -10,   -11,   -12,
  928.    -13,   -14,   268,   269,   259,   272,   263,   270,   274,   258,
  929.     -2,   -15,   265,    45,    43,    -1,   266,   273,   264,   261,
  930.     58,   258,    47,    45,   263,    -1,   271,   269,   272,   268,
  931.    258,   263,   268,    -1,    44,   268,   257,   268,   268,   268,
  932.    263,   268,   268,   272,   268,    44,   263,    -1,   258,    -1,
  933.     46,    -3,    45,    58,   261,    47,    45,    45,    58,   268,
  934.    268,   268,   268,   268,   268,   268,   268,    -3,    45,    58,
  935.    268,   268 };
  936. static CONST TclDatetabelem TclDatedef[]={
  937.      1,    -2,     2,     3,     4,     5,     6,     7,     8,     9,
  938.     10,    11,    53,    18,    19,    27,     0,    33,     0,    20,
  939.      0,    42,     0,    48,    49,    47,    50,    51,    52,    12,
  940.      0,    22,     0,     0,    32,    44,    17,     0,    39,    30,
  941.     24,    35,     0,    45,    21,     0,    41,     0,    54,    25,
  942.      0,     0,    34,    37,     0,     0,    36,    46,    23,    43,
  943.      0,    13,     0,     0,    55,     0,     0,     0,     0,    31,
  944.     40,    14,    54,    26,    28,    29,     0,    15,     0,     0,
  945.     16,    38 };
  946. typedef struct
  947. #ifdef __cplusplus
  948. TclDatetoktype
  949. #endif
  950. { char *t_name; int t_val; } TclDatetoktype;
  951. #ifndef YYDEBUG
  952. # define YYDEBUG 0 /* don't allow debugging */
  953. #endif
  954. #if YYDEBUG
  955. TclDatetoktype TclDatetoks[] =
  956. {
  957. "tAGO", 257,
  958. "tDAY", 258,
  959. "tDAYZONE", 259,
  960. "tID", 260,
  961. "tMERIDIAN", 261,
  962. "tMINUTE_UNIT", 262,
  963. "tMONTH", 263,
  964. "tMONTH_UNIT", 264,
  965. "tSTARDATE", 265,
  966. "tSEC_UNIT", 266,
  967. "tSNUMBER", 267,
  968. "tUNUMBER", 268,
  969. "tZONE", 269,
  970. "tEPOCH", 270,
  971. "tDST", 271,
  972. "tISOBASE", 272,
  973. "tDAY_UNIT", 273,
  974. "tNEXT", 274,
  975. "-unknown-", -1 /* ends search */
  976. };
  977. char * TclDatereds[] =
  978. {
  979. "-no such reduction-",
  980. "spec : /* empty */",
  981. "spec : spec item",
  982. "item : time",
  983. "item : zone",
  984. "item : date",
  985. "item : ordMonth",
  986. "item : day",
  987. "item : relspec",
  988. "item : iso",
  989. "item : trek",
  990. "item : number",
  991. "time : tUNUMBER tMERIDIAN",
  992. "time : tUNUMBER ':' tUNUMBER o_merid",
  993. "time : tUNUMBER ':' tUNUMBER '-' tUNUMBER",
  994. "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
  995. "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER '-' tUNUMBER",
  996. "zone : tZONE tDST",
  997. "zone : tZONE",
  998. "zone : tDAYZONE",
  999. "day : tDAY",
  1000. "day : tDAY ','",
  1001. "day : tUNUMBER tDAY",
  1002. "day : sign tUNUMBER tDAY",
  1003. "day : tNEXT tDAY",
  1004. "date : tUNUMBER '/' tUNUMBER",
  1005. "date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
  1006. "date : tISOBASE",
  1007. "date : tUNUMBER '-' tMONTH '-' tUNUMBER",
  1008. "date : tUNUMBER '-' tUNUMBER '-' tUNUMBER",
  1009. "date : tMONTH tUNUMBER",
  1010. "date : tMONTH tUNUMBER ',' tUNUMBER",
  1011. "date : tUNUMBER tMONTH",
  1012. "date : tEPOCH",
  1013. "date : tUNUMBER tMONTH tUNUMBER",
  1014. "ordMonth : tNEXT tMONTH",
  1015. "ordMonth : tNEXT tUNUMBER tMONTH",
  1016. "iso : tISOBASE tZONE tISOBASE",
  1017. "iso : tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER",
  1018. "iso : tISOBASE tISOBASE",
  1019. "trek : tSTARDATE tUNUMBER '.' tUNUMBER",
  1020. "relspec : relunits tAGO",
  1021. "relspec : relunits",
  1022. "relunits : sign tUNUMBER unit",
  1023. "relunits : tUNUMBER unit",
  1024. "relunits : tNEXT unit",
  1025. "relunits : tNEXT tUNUMBER unit",
  1026. "relunits : unit",
  1027. "sign : '-'",
  1028. "sign : '+'",
  1029. "unit : tSEC_UNIT",
  1030. "unit : tDAY_UNIT",
  1031. "unit : tMONTH_UNIT",
  1032. "number : tUNUMBER",
  1033. "o_merid : /* empty */",
  1034. "o_merid : tMERIDIAN",
  1035. };
  1036. #endif /* YYDEBUG */
  1037. /*
  1038.  * Copyright (c) 1993 by Sun Microsystems, Inc.
  1039.  */
  1040. /*
  1041. ** Skeleton parser driver for yacc output
  1042. */
  1043. /*
  1044. ** yacc user known macros and defines
  1045. */
  1046. #define YYERROR goto TclDateerrlab
  1047. #define YYACCEPT return(0)
  1048. #define YYABORT return(1)
  1049. #define YYBACKUP( newtoken, newvalue )
  1050. {
  1051. if ( TclDatechar >= 0 || ( TclDater2[ TclDatetmp ] >> 1 ) != 1 )
  1052. {
  1053. TclDateerror( "syntax error - cannot backup" );
  1054. goto TclDateerrlab;
  1055. }
  1056. TclDatechar = newtoken;
  1057. TclDatestate = *TclDateps;
  1058. TclDatelval = newvalue;
  1059. goto TclDatenewstate;
  1060. }
  1061. #define YYRECOVERING() (!!TclDateerrflag)
  1062. #define YYNEW(type) malloc(sizeof(type) * TclDatenewmax)
  1063. #define YYCOPY(to, from, type) 
  1064. (type *) memcpy(to, (char *) from, TclDatemaxdepth * sizeof (type))
  1065. #define YYENLARGE( from, type) 
  1066. (type *) realloc((char *) from, TclDatenewmax * sizeof(type))
  1067. #ifndef YYDEBUG
  1068. # define YYDEBUG 1 /* make debugging available */
  1069. #endif
  1070. /*
  1071. ** user known globals
  1072. */
  1073. int TclDatedebug; /* set to 1 to get debugging */
  1074. /*
  1075. ** driver internal defines
  1076. */
  1077. #define YYFLAG (-10000000)
  1078. /*
  1079. ** global variables used by the parser
  1080. */
  1081. YYSTYPE *TclDatepv; /* top of value stack */
  1082. int *TclDateps; /* top of state stack */
  1083. int TclDatestate; /* current state */
  1084. int TclDatetmp; /* extra var (lasts between blocks) */
  1085. int TclDatenerrs; /* number of errors */
  1086. int TclDateerrflag; /* error recovery flag */
  1087. int TclDatechar; /* current input token number */
  1088. #ifdef YYNMBCHARS
  1089. #define YYLEX() TclDatecvtok(TclDatelex())
  1090. /*
  1091. ** TclDatecvtok - return a token if i is a wchar_t value that exceeds 255.
  1092. ** If i<255, i itself is the token.  If i>255 but the neither 
  1093. ** of the 30th or 31st bit is on, i is already a token.
  1094. */
  1095. #if defined(__STDC__) || defined(__cplusplus)
  1096. int TclDatecvtok(int i)
  1097. #else
  1098. int TclDatecvtok(i) int i;
  1099. #endif
  1100. {
  1101. int first = 0;
  1102. int last = YYNMBCHARS - 1;
  1103. int mid;
  1104. wchar_t j;
  1105. if(i&0x60000000){/*Must convert to a token. */
  1106. if( TclDatembchars[last].character < i ){
  1107. return i;/*Giving up*/
  1108. }
  1109. while ((last>=first)&&(first>=0)) {/*Binary search loop*/
  1110. mid = (first+last)/2;
  1111. j = TclDatembchars[mid].character;
  1112. if( j==i ){/*Found*/ 
  1113. return TclDatembchars[mid].tvalue;
  1114. }else if( j<i ){
  1115. first = mid + 1;
  1116. }else{
  1117. last = mid -1;
  1118. }
  1119. }
  1120. /*No entry in the table.*/
  1121. return i;/* Giving up.*/
  1122. }else{/* i is already a token. */
  1123. return i;
  1124. }
  1125. }
  1126. #else/*!YYNMBCHARS*/
  1127. #define YYLEX() TclDatelex()
  1128. #endif/*!YYNMBCHARS*/
  1129. /*
  1130. ** TclDateparse - return 0 if worked, 1 if syntax error not recovered from
  1131. */
  1132. #if defined(__STDC__) || defined(__cplusplus)
  1133. int TclDateparse(void)
  1134. #else
  1135. int TclDateparse()
  1136. #endif
  1137. {
  1138. register YYSTYPE *TclDatepvt = 0; /* top of value stack for $vars */
  1139. #if defined(__cplusplus) || defined(lint)
  1140. /*
  1141. hacks to please C++ and lint - goto's inside
  1142. switch should never be executed
  1143. */
  1144. static int __yaccpar_lint_hack__ = 0;
  1145. switch (__yaccpar_lint_hack__)
  1146. {
  1147. case 1: goto TclDateerrlab;
  1148. case 2: goto TclDatenewstate;
  1149. }
  1150. #endif
  1151. /*
  1152. ** Initialize externals - TclDateparse may be called more than once
  1153. */
  1154. TclDatepv = &TclDatev[-1];
  1155. TclDateps = &TclDates[-1];
  1156. TclDatestate = 0;
  1157. TclDatetmp = 0;
  1158. TclDatenerrs = 0;
  1159. TclDateerrflag = 0;
  1160. TclDatechar = -1;
  1161. #if YYMAXDEPTH <= 0
  1162. if (TclDatemaxdepth <= 0)
  1163. {
  1164. if ((TclDatemaxdepth = YYEXPAND(0)) <= 0)
  1165. {
  1166. TclDateerror("yacc initialization error");
  1167. YYABORT;
  1168. }
  1169. }
  1170. #endif
  1171. {
  1172. register YYSTYPE *TclDate_pv; /* top of value stack */
  1173. register int *TclDate_ps; /* top of state stack */
  1174. register int TclDate_state; /* current state */
  1175. register int  TclDate_n; /* internal state number info */
  1176. goto TclDatestack; /* moved from 6 lines above to here to please C++ */
  1177. /*
  1178. ** get globals into registers.
  1179. ** branch to here only if YYBACKUP was called.
  1180. */
  1181. TclDate_pv = TclDatepv;
  1182. TclDate_ps = TclDateps;
  1183. TclDate_state = TclDatestate;
  1184. goto TclDate_newstate;
  1185. /*
  1186. ** get globals into registers.
  1187. ** either we just started, or we just finished a reduction
  1188. */
  1189. TclDatestack:
  1190. TclDate_pv = TclDatepv;
  1191. TclDate_ps = TclDateps;
  1192. TclDate_state = TclDatestate;
  1193. /*
  1194. ** top of for (;;) loop while no reductions done
  1195. */
  1196. TclDate_stack:
  1197. /*
  1198. ** put a state and value onto the stacks
  1199. */
  1200. #if YYDEBUG
  1201. /*
  1202. ** if debugging, look up token value in list of value vs.
  1203. ** name pairs.  0 and negative (-1) are special values.
  1204. ** Note: linear search is used since time is not a real
  1205. ** consideration while debugging.
  1206. */
  1207. if ( TclDatedebug )
  1208. {
  1209. register int TclDate_i;
  1210. printf( "State %d, token ", TclDate_state );
  1211. if ( TclDatechar == 0 )
  1212. printf( "end-of-filen" );
  1213. else if ( TclDatechar < 0 )
  1214. printf( "-none-n" );
  1215. else
  1216. {
  1217. for ( TclDate_i = 0; TclDatetoks[TclDate_i].t_val >= 0;
  1218. TclDate_i++ )
  1219. {
  1220. if ( TclDatetoks[TclDate_i].t_val == TclDatechar )
  1221. break;
  1222. }
  1223. printf( "%sn", TclDatetoks[TclDate_i].t_name );
  1224. }
  1225. }
  1226. #endif /* YYDEBUG */
  1227. if ( ++TclDate_ps >= &TclDates[ TclDatemaxdepth ] ) /* room on stack? */
  1228. {
  1229. /*
  1230. ** reallocate and recover.  Note that pointers
  1231. ** have to be reset, or bad things will happen
  1232. */
  1233. long TclDateps_index = (TclDate_ps - TclDates);
  1234. long TclDatepv_index = (TclDate_pv - TclDatev);
  1235. long TclDatepvt_index = (TclDatepvt - TclDatev);
  1236. int TclDatenewmax;
  1237. #ifdef YYEXPAND
  1238. TclDatenewmax = YYEXPAND(TclDatemaxdepth);
  1239. #else
  1240. TclDatenewmax = 2 * TclDatemaxdepth; /* double table size */
  1241. if (TclDatemaxdepth == YYMAXDEPTH) /* first time growth */
  1242. {
  1243. char *newTclDates = (char *)YYNEW(int);
  1244. char *newTclDatev = (char *)YYNEW(YYSTYPE);
  1245. if (newTclDates != 0 && newTclDatev != 0)
  1246. {
  1247. TclDates = YYCOPY(newTclDates, TclDates, int);
  1248. TclDatev = YYCOPY(newTclDatev, TclDatev, YYSTYPE);
  1249. }
  1250. else
  1251. TclDatenewmax = 0; /* failed */
  1252. }
  1253. else /* not first time */
  1254. {
  1255. TclDates = YYENLARGE(TclDates, int);
  1256. TclDatev = YYENLARGE(TclDatev, YYSTYPE);
  1257. if (TclDates == 0 || TclDatev == 0)
  1258. TclDatenewmax = 0; /* failed */
  1259. }
  1260. #endif
  1261. if (TclDatenewmax <= TclDatemaxdepth) /* tables not expanded */
  1262. {
  1263. TclDateerror( "yacc stack overflow" );
  1264. YYABORT;
  1265. }
  1266. TclDatemaxdepth = TclDatenewmax;
  1267. TclDate_ps = TclDates + TclDateps_index;
  1268. TclDate_pv = TclDatev + TclDatepv_index;
  1269. TclDatepvt = TclDatev + TclDatepvt_index;
  1270. }
  1271. *TclDate_ps = TclDate_state;
  1272. *++TclDate_pv = TclDateval;
  1273. /*
  1274. ** we have a new state - find out what to do
  1275. */
  1276. TclDate_newstate:
  1277. if ( ( TclDate_n = TclDatepact[ TclDate_state ] ) <= YYFLAG )
  1278. goto TclDatedefault; /* simple state */
  1279. #if YYDEBUG
  1280. /*
  1281. ** if debugging, need to mark whether new token grabbed
  1282. */
  1283. TclDatetmp = TclDatechar < 0;
  1284. #endif
  1285. if ( ( TclDatechar < 0 ) && ( ( TclDatechar = YYLEX() ) < 0 ) )
  1286. TclDatechar = 0; /* reached EOF */
  1287. #if YYDEBUG
  1288. if ( TclDatedebug && TclDatetmp )
  1289. {
  1290. register int TclDate_i;
  1291. printf( "Received token " );
  1292. if ( TclDatechar == 0 )
  1293. printf( "end-of-filen" );
  1294. else if ( TclDatechar < 0 )
  1295. printf( "-none-n" );
  1296. else
  1297. {
  1298. for ( TclDate_i = 0; TclDatetoks[TclDate_i].t_val >= 0;
  1299. TclDate_i++ )
  1300. {
  1301. if ( TclDatetoks[TclDate_i].t_val == TclDatechar )
  1302. break;
  1303. }
  1304. printf( "%sn", TclDatetoks[TclDate_i].t_name );
  1305. }
  1306. }
  1307. #endif /* YYDEBUG */
  1308. if ( ( ( TclDate_n += TclDatechar ) < 0 ) || ( TclDate_n >= YYLAST ) )
  1309. goto TclDatedefault;
  1310. if ( TclDatechk[ TclDate_n = TclDateact[ TclDate_n ] ] == TclDatechar ) /*valid shift*/
  1311. {
  1312. TclDatechar = -1;
  1313. TclDateval = TclDatelval;
  1314. TclDate_state = TclDate_n;
  1315. if ( TclDateerrflag > 0 )
  1316. TclDateerrflag--;
  1317. goto TclDate_stack;
  1318. }
  1319. TclDatedefault:
  1320. if ( ( TclDate_n = TclDatedef[ TclDate_state ] ) == -2 )
  1321. {
  1322. #if YYDEBUG
  1323. TclDatetmp = TclDatechar < 0;
  1324. #endif
  1325. if ( ( TclDatechar < 0 ) && ( ( TclDatechar = YYLEX() ) < 0 ) )
  1326. TclDatechar = 0; /* reached EOF */
  1327. #if YYDEBUG
  1328. if ( TclDatedebug && TclDatetmp )
  1329. {
  1330. register int TclDate_i;
  1331. printf( "Received token " );
  1332. if ( TclDatechar == 0 )
  1333. printf( "end-of-filen" );
  1334. else if ( TclDatechar < 0 )
  1335. printf( "-none-n" );
  1336. else
  1337. {
  1338. for ( TclDate_i = 0;
  1339. TclDatetoks[TclDate_i].t_val >= 0;
  1340. TclDate_i++ )
  1341. {
  1342. if ( TclDatetoks[TclDate_i].t_val
  1343. == TclDatechar )
  1344. {
  1345. break;
  1346. }
  1347. }
  1348. printf( "%sn", TclDatetoks[TclDate_i].t_name );
  1349. }
  1350. }
  1351. #endif /* YYDEBUG */
  1352. /*
  1353. ** look through exception table
  1354. */
  1355. {
  1356. register CONST int *TclDatexi = TclDateexca;
  1357. while ( ( *TclDatexi != -1 ) ||
  1358. ( TclDatexi[1] != TclDate_state ) )
  1359. {
  1360. TclDatexi += 2;
  1361. }
  1362. while ( ( *(TclDatexi += 2) >= 0 ) &&
  1363. ( *TclDatexi != TclDatechar ) )
  1364. ;
  1365. if ( ( TclDate_n = TclDatexi[1] ) < 0 )
  1366. YYACCEPT;
  1367. }
  1368. }
  1369. /*
  1370. ** check for syntax error
  1371. */
  1372. if ( TclDate_n == 0 ) /* have an error */
  1373. {
  1374. /* no worry about speed here! */
  1375. switch ( TclDateerrflag )
  1376. {
  1377. case 0: /* new error */
  1378. TclDateerror( "syntax error" );
  1379. goto skip_init;
  1380. /*
  1381. ** get globals into registers.
  1382. ** we have a user generated syntax type error
  1383. */
  1384. TclDate_pv = TclDatepv;
  1385. TclDate_ps = TclDateps;
  1386. TclDate_state = TclDatestate;
  1387. skip_init:
  1388. TclDatenerrs++;
  1389. /* FALLTHRU */
  1390. case 1:
  1391. case 2: /* incompletely recovered error */
  1392. /* try again... */
  1393. TclDateerrflag = 3;
  1394. /*
  1395. ** find state where "error" is a legal
  1396. ** shift action
  1397. */
  1398. while ( TclDate_ps >= TclDates )
  1399. {
  1400. TclDate_n = TclDatepact[ *TclDate_ps ] + YYERRCODE;
  1401. if ( TclDate_n >= 0 && TclDate_n < YYLAST &&
  1402. TclDatechk[TclDateact[TclDate_n]] == YYERRCODE) {
  1403. /*
  1404. ** simulate shift of "error"
  1405. */
  1406. TclDate_state = TclDateact[ TclDate_n ];
  1407. goto TclDate_stack;
  1408. }
  1409. /*
  1410. ** current state has no shift on
  1411. ** "error", pop stack
  1412. */
  1413. #if YYDEBUG
  1414. # define _POP_ "Error recovery pops state %d, uncovers state %dn"
  1415. if ( TclDatedebug )
  1416. printf( _POP_, *TclDate_ps,
  1417. TclDate_ps[-1] );
  1418. # undef _POP_
  1419. #endif
  1420. TclDate_ps--;
  1421. TclDate_pv--;
  1422. }
  1423. /*
  1424. ** there is no state on stack with "error" as
  1425. ** a valid shift.  give up.
  1426. */
  1427. YYABORT;
  1428. case 3: /* no shift yet; eat a token */
  1429. #if YYDEBUG
  1430. /*
  1431. ** if debugging, look up token in list of
  1432. ** pairs.  0 and negative shouldn't occur,
  1433. ** but since timing doesn't matter when
  1434. ** debugging, it doesn't hurt to leave the
  1435. ** tests here.
  1436. */
  1437. if ( TclDatedebug )
  1438. {
  1439. register int TclDate_i;
  1440. printf( "Error recovery discards " );
  1441. if ( TclDatechar == 0 )
  1442. printf( "token end-of-filen" );
  1443. else if ( TclDatechar < 0 )
  1444. printf( "token -none-n" );
  1445. else
  1446. {
  1447. for ( TclDate_i = 0;
  1448. TclDatetoks[TclDate_i].t_val >= 0;
  1449. TclDate_i++ )
  1450. {
  1451. if ( TclDatetoks[TclDate_i].t_val
  1452. == TclDatechar )
  1453. {
  1454. break;
  1455. }
  1456. }
  1457. printf( "token %sn",
  1458. TclDatetoks[TclDate_i].t_name );
  1459. }
  1460. }
  1461. #endif /* YYDEBUG */
  1462. if ( TclDatechar == 0 ) /* reached EOF. quit */
  1463. YYABORT;
  1464. TclDatechar = -1;
  1465. goto TclDate_newstate;
  1466. }
  1467. }/* end if ( TclDate_n == 0 ) */
  1468. /*
  1469. ** reduction by production TclDate_n
  1470. ** put stack tops, etc. so things right after switch
  1471. */
  1472. #if YYDEBUG
  1473. /*
  1474. ** if debugging, print the string that is the user's
  1475. ** specification of the reduction which is just about
  1476. ** to be done.
  1477. */
  1478. if ( TclDatedebug )
  1479. printf( "Reduce by (%d) "%s"n",
  1480. TclDate_n, TclDatereds[ TclDate_n ] );
  1481. #endif
  1482. TclDatetmp = TclDate_n; /* value to switch over */
  1483. TclDatepvt = TclDate_pv; /* $vars top of value stack */
  1484. /*
  1485. ** Look in goto table for next state
  1486. ** Sorry about using TclDate_state here as temporary
  1487. ** register variable, but why not, if it works...
  1488. ** If TclDater2[ TclDate_n ] doesn't have the low order bit
  1489. ** set, then there is no action to be done for
  1490. ** this reduction.  So, no saving & unsaving of
  1491. ** registers done.  The only difference between the
  1492. ** code just after the if and the body of the if is
  1493. ** the goto TclDate_stack in the body.  This way the test
  1494. ** can be made before the choice of what to do is needed.
  1495. */
  1496. {
  1497. /* length of production doubled with extra bit */
  1498. register int TclDate_len = TclDater2[ TclDate_n ];
  1499. if ( !( TclDate_len & 01 ) )
  1500. {
  1501. TclDate_len >>= 1;
  1502. TclDateval = ( TclDate_pv -= TclDate_len )[1]; /* $$ = $1 */
  1503. TclDate_state = TclDatepgo[ TclDate_n = TclDater1[ TclDate_n ] ] +
  1504. *( TclDate_ps -= TclDate_len ) + 1;
  1505. if ( TclDate_state >= YYLAST ||
  1506. TclDatechk[ TclDate_state =
  1507. TclDateact[ TclDate_state ] ] != -TclDate_n )
  1508. {
  1509. TclDate_state = TclDateact[ TclDatepgo[ TclDate_n ] ];
  1510. }
  1511. goto TclDate_stack;
  1512. }
  1513. TclDate_len >>= 1;
  1514. TclDateval = ( TclDate_pv -= TclDate_len )[1]; /* $$ = $1 */
  1515. TclDate_state = TclDatepgo[ TclDate_n = TclDater1[ TclDate_n ] ] +
  1516. *( TclDate_ps -= TclDate_len ) + 1;
  1517. if ( TclDate_state >= YYLAST ||
  1518. TclDatechk[ TclDate_state = TclDateact[ TclDate_state ] ] != -TclDate_n )
  1519. {
  1520. TclDate_state = TclDateact[ TclDatepgo[ TclDate_n ] ];
  1521. }
  1522. }
  1523. /* save until reenter driver code */
  1524. TclDatestate = TclDate_state;
  1525. TclDateps = TclDate_ps;
  1526. TclDatepv = TclDate_pv;
  1527. }
  1528. /*
  1529. ** code supplied by user is placed in this switch
  1530. */
  1531. switch( TclDatetmp )
  1532. {
  1533. case 3:{
  1534.             TclDateHaveTime++;
  1535.         } break;
  1536. case 4:{
  1537.             TclDateHaveZone++;
  1538.         } break;
  1539. case 5:{
  1540.             TclDateHaveDate++;
  1541.         } break;
  1542. case 6:{
  1543.             TclDateHaveOrdinalMonth++;
  1544.         } break;
  1545. case 7:{
  1546.             TclDateHaveDay++;
  1547.         } break;
  1548. case 8:{
  1549.             TclDateHaveRel++;
  1550.         } break;
  1551. case 9:{
  1552.     TclDateHaveTime++;
  1553.     TclDateHaveDate++;
  1554. } break;
  1555. case 10:{
  1556.     TclDateHaveTime++;
  1557.     TclDateHaveDate++;
  1558.     TclDateHaveRel++;
  1559.         } break;
  1560. case 12:{
  1561.             TclDateHour = TclDatepvt[-1].Number;
  1562.             TclDateMinutes = 0;
  1563.             TclDateSeconds = 0;
  1564.             TclDateMeridian = TclDatepvt[-0].Meridian;
  1565.         } break;
  1566. case 13:{
  1567.             TclDateHour = TclDatepvt[-3].Number;
  1568.             TclDateMinutes = TclDatepvt[-1].Number;
  1569.             TclDateSeconds = 0;
  1570.             TclDateMeridian = TclDatepvt[-0].Meridian;
  1571.         } break;
  1572. case 14:{
  1573.             TclDateHour = TclDatepvt[-4].Number;
  1574.             TclDateMinutes = TclDatepvt[-2].Number;
  1575.             TclDateMeridian = MER24;
  1576.             TclDateDSTmode = DSToff;
  1577.             TclDateTimezone = (TclDatepvt[-0].Number % 100 + (TclDatepvt[-0].Number / 100) * 60);
  1578.         } break;
  1579. case 15:{
  1580.             TclDateHour = TclDatepvt[-5].Number;
  1581.             TclDateMinutes = TclDatepvt[-3].Number;
  1582.             TclDateSeconds = TclDatepvt[-1].Number;
  1583.             TclDateMeridian = TclDatepvt[-0].Meridian;
  1584.         } break;
  1585. case 16:{
  1586.             TclDateHour = TclDatepvt[-6].Number;
  1587.             TclDateMinutes = TclDatepvt[-4].Number;
  1588.             TclDateSeconds = TclDatepvt[-2].Number;
  1589.             TclDateMeridian = MER24;
  1590.             TclDateDSTmode = DSToff;
  1591.             TclDateTimezone = (TclDatepvt[-0].Number % 100 + (TclDatepvt[-0].Number / 100) * 60);
  1592.         } break;
  1593. case 17:{
  1594.             TclDateTimezone = TclDatepvt[-1].Number;
  1595.             TclDateDSTmode = DSTon;
  1596.         } break;
  1597. case 18:{
  1598.             TclDateTimezone = TclDatepvt[-0].Number;
  1599.             TclDateDSTmode = DSToff;
  1600.         } break;
  1601. case 19:{
  1602.             TclDateTimezone = TclDatepvt[-0].Number;
  1603.             TclDateDSTmode = DSTon;
  1604.         } break;
  1605. case 20:{
  1606.             TclDateDayOrdinal = 1;
  1607.             TclDateDayNumber = TclDatepvt[-0].Number;
  1608.         } break;
  1609. case 21:{
  1610.             TclDateDayOrdinal = 1;
  1611.             TclDateDayNumber = TclDatepvt[-1].Number;
  1612.         } break;
  1613. case 22:{
  1614.             TclDateDayOrdinal = TclDatepvt[-1].Number;
  1615.             TclDateDayNumber = TclDatepvt[-0].Number;
  1616.         } break;
  1617. case 23:{
  1618.             TclDateDayOrdinal = TclDatepvt[-2].Number * TclDatepvt[-1].Number;
  1619.             TclDateDayNumber = TclDatepvt[-0].Number;
  1620.         } break;
  1621. case 24:{
  1622.             TclDateDayOrdinal = 2;
  1623.             TclDateDayNumber = TclDatepvt[-0].Number;
  1624.         } break;
  1625. case 25:{
  1626.             TclDateMonth = TclDatepvt[-2].Number;
  1627.             TclDateDay = TclDatepvt[-0].Number;
  1628.         } break;
  1629. case 26:{
  1630.             TclDateMonth = TclDatepvt[-4].Number;
  1631.             TclDateDay = TclDatepvt[-2].Number;
  1632.             TclDateYear = TclDatepvt[-0].Number;
  1633.         } break;
  1634. case 27:{
  1635.     TclDateYear = TclDatepvt[-0].Number / 10000;
  1636.     TclDateMonth = (TclDatepvt[-0].Number % 10000)/100;
  1637.     TclDateDay = TclDatepvt[-0].Number % 100;
  1638. } break;
  1639. case 28:{
  1640.     TclDateDay = TclDatepvt[-4].Number;
  1641.     TclDateMonth = TclDatepvt[-2].Number;
  1642.     TclDateYear = TclDatepvt[-0].Number;
  1643. } break;
  1644. case 29:{
  1645.             TclDateMonth = TclDatepvt[-2].Number;
  1646.             TclDateDay = TclDatepvt[-0].Number;
  1647.             TclDateYear = TclDatepvt[-4].Number;
  1648.         } break;
  1649. case 30:{
  1650.             TclDateMonth = TclDatepvt[-1].Number;
  1651.             TclDateDay = TclDatepvt[-0].Number;
  1652.         } break;
  1653. case 31:{
  1654.             TclDateMonth = TclDatepvt[-3].Number;
  1655.             TclDateDay = TclDatepvt[-2].Number;
  1656.             TclDateYear = TclDatepvt[-0].Number;
  1657.         } break;
  1658. case 32:{
  1659.             TclDateMonth = TclDatepvt[-0].Number;
  1660.             TclDateDay = TclDatepvt[-1].Number;
  1661.         } break;
  1662. case 33:{
  1663.     TclDateMonth = 1;
  1664.     TclDateDay = 1;
  1665.     TclDateYear = EPOCH;
  1666. } break;
  1667. case 34:{
  1668.             TclDateMonth = TclDatepvt[-1].Number;
  1669.             TclDateDay = TclDatepvt[-2].Number;
  1670.             TclDateYear = TclDatepvt[-0].Number;
  1671.         } break;
  1672. case 35:{
  1673.     TclDateMonthOrdinal = 1;
  1674.     TclDateMonth = TclDatepvt[-0].Number;
  1675. } break;
  1676. case 36:{
  1677.     TclDateMonthOrdinal = TclDatepvt[-1].Number;
  1678.     TclDateMonth = TclDatepvt[-0].Number;
  1679. } break;
  1680. case 37:{
  1681.             if (TclDatepvt[-1].Number != HOUR(- 7)) YYABORT;
  1682.     TclDateYear = TclDatepvt[-2].Number / 10000;
  1683.     TclDateMonth = (TclDatepvt[-2].Number % 10000)/100;
  1684.     TclDateDay = TclDatepvt[-2].Number % 100;
  1685.     TclDateHour = TclDatepvt[-0].Number / 10000;
  1686.     TclDateMinutes = (TclDatepvt[-0].Number % 10000)/100;
  1687.     TclDateSeconds = TclDatepvt[-0].Number % 100;
  1688.         } break;
  1689. case 38:{
  1690.             if (TclDatepvt[-5].Number != HOUR(- 7)) YYABORT;
  1691.     TclDateYear = TclDatepvt[-6].Number / 10000;
  1692.     TclDateMonth = (TclDatepvt[-6].Number % 10000)/100;
  1693.     TclDateDay = TclDatepvt[-6].Number % 100;
  1694.     TclDateHour = TclDatepvt[-4].Number;
  1695.     TclDateMinutes = TclDatepvt[-2].Number;
  1696.     TclDateSeconds = TclDatepvt[-0].Number;
  1697.         } break;
  1698. case 39:{
  1699.     TclDateYear = TclDatepvt[-1].Number / 10000;
  1700.     TclDateMonth = (TclDatepvt[-1].Number % 10000)/100;
  1701.     TclDateDay = TclDatepvt[-1].Number % 100;
  1702.     TclDateHour = TclDatepvt[-0].Number / 10000;
  1703.     TclDateMinutes = (TclDatepvt[-0].Number % 10000)/100;
  1704.     TclDateSeconds = TclDatepvt[-0].Number % 100;
  1705.         } break;
  1706. case 40:{
  1707.             /*
  1708.      * Offset computed year by -377 so that the returned years will
  1709.      * be in a range accessible with a 32 bit clock seconds value
  1710.      */
  1711.             TclDateYear = TclDatepvt[-2].Number/1000 + 2323 - 377;
  1712.             TclDateDay  = 1;
  1713.     TclDateMonth = 1;
  1714.     TclDateRelDay += ((TclDatepvt[-2].Number%1000)*(365 + IsLeapYear(TclDateYear)))/1000;
  1715.     TclDateRelSeconds += TclDatepvt[-0].Number * 144 * 60;
  1716.         } break;
  1717. case 41:{
  1718.     TclDateRelSeconds *= -1;
  1719.     TclDateRelMonth *= -1;
  1720.     TclDateRelDay *= -1;
  1721. } break;
  1722. case 43:{ *TclDateRelPointer += TclDatepvt[-2].Number * TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
  1723. case 44:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
  1724. case 45:{ *TclDateRelPointer += TclDatepvt[-0].Number; } break;
  1725. case 46:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
  1726. case 47:{ *TclDateRelPointer += TclDatepvt[-0].Number; } break;
  1727. case 48:{ TclDateval.Number = -1; } break;
  1728. case 49:{ TclDateval.Number =  1; } break;
  1729. case 50:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelSeconds; } break;
  1730. case 51:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelDay; } break;
  1731. case 52:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelMonth; } break;
  1732. case 53:{
  1733. if (TclDateHaveTime && TclDateHaveDate && !TclDateHaveRel) {
  1734.     TclDateYear = TclDatepvt[-0].Number;
  1735. } else {
  1736.     TclDateHaveTime++;
  1737.     if (TclDatepvt[-0].Number < 100) {
  1738. TclDateHour = TclDatepvt[-0].Number;
  1739. TclDateMinutes = 0;
  1740.     } else {
  1741. TclDateHour = TclDatepvt[-0].Number / 100;
  1742. TclDateMinutes = TclDatepvt[-0].Number % 100;
  1743.     }
  1744.     TclDateSeconds = 0;
  1745.     TclDateMeridian = MER24;
  1746. }
  1747.     } break;
  1748. case 54:{
  1749.             TclDateval.Meridian = MER24;
  1750.         } break;
  1751. case 55:{
  1752.             TclDateval.Meridian = TclDatepvt[-0].Meridian;
  1753.         } break;
  1754. }
  1755. goto TclDatestack; /* reset registers in driver code */
  1756. }