home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / cvs-1.8 / cvs-1 / cvs-1.8.1 / os2 / getdate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-06  |  38.1 KB  |  1,579 lines

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