home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / futils / futils~1 / src / shell13s.zoo / shell1.3 / lib / getdate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-06  |  36.7 KB  |  1,532 lines

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