home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tkisrc04.zip / tcl / os2 / tclDate.c < prev    next >
C/C++ Source or Header  |  1998-08-07  |  47KB  |  1,620 lines

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