getdate.y
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:24k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. %expect 10
  2. %{
  3. /*
  4. **  Originally written by Steven M. Bellovin <smb@research.att.com> while
  5. **  at the University of North Carolina at Chapel Hill.  Later tweaked by
  6. **  a couple of people on Usenet.  Completely overhauled by Rich $alz
  7. **  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
  8. **
  9. **  Major hack to coerce it into use with the Equivalence Portable
  10. **  Windows Library.
  11. **
  12. **  This grammar has 10 shift/reduce conflicts.
  13. **
  14. **  This code is in the public domain and has no copyright.
  15. */
  16. /* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
  17. /* SUPPRESS 288 on yyerrlab *//* Label unused */
  18. #include <time.h>
  19. #include <string.h>
  20. #include <ctype.h>
  21. #ifdef _MSC_VER
  22. #pragma warning(disable:4131 4701)
  23. #define STDAPICALLTYPE __stdcall
  24. #define MSDOS
  25. #else
  26. #define STDAPICALLTYPE
  27. #endif
  28. extern int  STDAPICALLTYPE PTimeGetChar(void * stream);
  29. extern void STDAPICALLTYPE PTimeUngetChar(void * stream, int c);
  30. int STDAPICALLTYPE PTimeGetDateOrder();
  31. int STDAPICALLTYPE PTimeIsMonthName(const char *, int, int);
  32. int STDAPICALLTYPE PTimeIsDayName(const char *, int, int);
  33. #define EPOCH 1970
  34. #define HOUR(x) ((time_t)(x) * 60)
  35. #define SECSPERDAY (24L * 60L * 60L)
  36. /*
  37. **  An entry in the lexical lookup table.
  38. */
  39. typedef struct _TABLE {
  40.     char *name;
  41.     int type;
  42.     time_t value;
  43. } TABLE;
  44. /*
  45. **  Daylight-savings mode:  on, off, or not yet known.
  46. */
  47. typedef enum _DSTMODE {
  48.     DSTon, DSToff, DSTmaybe
  49. } DSTMODE;
  50. /*
  51. **  Meridian:  am, pm, or 24-hour style.
  52. */
  53. typedef enum _MERIDIAN {
  54.     MERam, MERpm, MER24
  55. } MERIDIAN;
  56. /*
  57. **  Global variables.  We could get rid of most of these by using a good
  58. **  union as the yacc stack.  (This routine was originally written before
  59. **  yacc had the %union construct.)  Maybe someday; right now we only use
  60. **  the %union very rarely.
  61. */
  62. struct Variables {
  63.     void *yyInput;
  64.     DSTMODE yyDSTmode;
  65.     time_t yyDayOrdinal;
  66.     time_t yyDayNumber;
  67.     int yyHaveDate;
  68.     int yyHaveDay;
  69.     int yyHaveRel;
  70.     int yyHaveTime;
  71.     int yyHaveZone;
  72.     time_t yyTimezone;
  73.     time_t yyDay;
  74.     time_t yyHour;
  75.     time_t yyMinutes;
  76.     time_t yyMonth;
  77.     time_t yySeconds;
  78.     time_t yyYear;
  79.     MERIDIAN yyMeridian;
  80.     time_t yyRelMonth;
  81.     time_t yyRelSeconds;
  82. };
  83. #define VARIABLE ((struct Variables*)parseParam)
  84. #define YYPURE
  85. #define YYLEX_PARAM VARIABLE->yyInput
  86. #define YYPARSE_PARAM parseParam
  87. #define yyparse PTime_yyparse
  88. #define yylex PTime_yylex
  89. #define yyerror PTime_yyerror
  90. static int yyparse(void *); 
  91. #ifdef __GNUC__
  92. static int yyerror();
  93. static int yylex();
  94. #endif
  95. static void SetPossibleDate(struct Variables*, time_t, time_t, time_t);
  96. %}
  97. %union {
  98.     time_t Number;
  99.     enum _MERIDIAN Meridian;
  100. }
  101. %token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
  102. %token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST
  103. %type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
  104. %type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE
  105. %type <Meridian> tMERIDIAN o_merid
  106. %%
  107. spec : /* NULL */
  108. | spec item
  109. ;
  110. item : time {
  111.     VARIABLE->yyHaveTime++;
  112. }
  113. | zone {
  114.     VARIABLE->yyHaveZone++;
  115. }
  116. | date {
  117.     VARIABLE->yyHaveDate++;
  118. }
  119. | day {
  120.     VARIABLE->yyHaveDay++;
  121. }
  122. | rel {
  123.     VARIABLE->yyHaveRel++;
  124. }
  125. | number
  126. ;
  127. time : tUNUMBER tMERIDIAN {
  128.     VARIABLE->yyHour = $1;
  129.     VARIABLE->yyMinutes = 0;
  130.     VARIABLE->yySeconds = 0;
  131.     VARIABLE->yyMeridian = $2;
  132. }
  133. | tUNUMBER ':' tUNUMBER o_merid {
  134.     VARIABLE->yyHour = $1;
  135.     VARIABLE->yyMinutes = $3;
  136.     VARIABLE->yySeconds = 0;
  137.     VARIABLE->yyMeridian = $4;
  138. }
  139. | tUNUMBER ':' tUNUMBER tSNUMBER {
  140.     VARIABLE->yyHour = $1;
  141.     VARIABLE->yyMinutes = $3;
  142.     VARIABLE->yyMeridian = MER24;
  143.     VARIABLE->yyDSTmode = DSToff;
  144.     VARIABLE->yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
  145. }
  146. | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
  147.     VARIABLE->yyHour = $1;
  148.     VARIABLE->yyMinutes = $3;
  149.     VARIABLE->yySeconds = $5;
  150.     VARIABLE->yyMeridian = $6;
  151. }
  152. | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
  153.     VARIABLE->yyHour = $1;
  154.     VARIABLE->yyMinutes = $3;
  155.     VARIABLE->yySeconds = $5;
  156.     VARIABLE->yyMeridian = MER24;
  157.     VARIABLE->yyDSTmode = DSToff;
  158.     VARIABLE->yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
  159. }
  160. ;
  161. zone : tZONE {
  162.     VARIABLE->yyTimezone = $1;
  163.     VARIABLE->yyDSTmode = DSToff;
  164. }
  165. | tDAYZONE {
  166.     VARIABLE->yyTimezone = $1;
  167.     VARIABLE->yyDSTmode = DSTon;
  168. }
  169. |
  170.   tZONE tDST {
  171.     VARIABLE->yyTimezone = $1;
  172.     VARIABLE->yyDSTmode = DSTon;
  173. }
  174. ;
  175. day : tDAY {
  176.     VARIABLE->yyDayOrdinal = 1;
  177.     VARIABLE->yyDayNumber = $1;
  178. }
  179. | tDAY ',' {
  180.     VARIABLE->yyDayOrdinal = 1;
  181.     VARIABLE->yyDayNumber = $1;
  182. }
  183. | tUNUMBER tDAY {
  184.     VARIABLE->yyDayOrdinal = $1;
  185.     VARIABLE->yyDayNumber = $2;
  186. }
  187. ;
  188. date : tUNUMBER '/' tUNUMBER {
  189.     SetPossibleDate(VARIABLE, $1, $3, VARIABLE->yyYear);
  190. }
  191. | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
  192.     SetPossibleDate(VARIABLE, $1, $3, $5);
  193. }
  194. | tUNUMBER tSNUMBER tSNUMBER {
  195.     /* ISO 8601 format.  yyyy-mm-dd.  */
  196.     if ($1 > 31) {
  197. VARIABLE->yyYear = $1;
  198. VARIABLE->yyMonth = -$2;
  199. VARIABLE->yyDay = -$3;
  200.     }
  201.     else
  202. SetPossibleDate(VARIABLE, $1, -$2, -$3);
  203. }
  204. | tUNUMBER tMONTH tSNUMBER {
  205.     /* e.g. 17-JUN-1992.  */
  206.     VARIABLE->yyDay = $1;
  207.     VARIABLE->yyMonth = $2;
  208.     VARIABLE->yyYear = -$3;
  209. }
  210. | tMONTH tUNUMBER {
  211.     VARIABLE->yyMonth = $1;
  212.     VARIABLE->yyDay = $2;
  213. }
  214. | tMONTH tUNUMBER ',' tUNUMBER {
  215.     VARIABLE->yyMonth = $1;
  216.     VARIABLE->yyDay = $2;
  217.     VARIABLE->yyYear = $4;
  218. }
  219. | tUNUMBER tMONTH {
  220.     VARIABLE->yyMonth = $2;
  221.     VARIABLE->yyDay = $1;
  222. }
  223. | tUNUMBER tMONTH tUNUMBER {
  224.     VARIABLE->yyMonth = $2;
  225.     VARIABLE->yyDay = $1;
  226.     VARIABLE->yyYear = $3;
  227. }
  228. ;
  229. rel : relunit tAGO {
  230.     VARIABLE->yyRelSeconds = -VARIABLE->yyRelSeconds;
  231.     VARIABLE->yyRelMonth = -VARIABLE->yyRelMonth;
  232. }
  233. | relunit
  234. ;
  235. relunit : tUNUMBER tMINUTE_UNIT {
  236.     VARIABLE->yyRelSeconds += $1 * $2 * 60L;
  237. }
  238. | tSNUMBER tMINUTE_UNIT {
  239.     VARIABLE->yyRelSeconds += $1 * $2 * 60L;
  240. }
  241. | tMINUTE_UNIT {
  242.     VARIABLE->yyRelSeconds += $1 * 60L;
  243. }
  244. | tSNUMBER tSEC_UNIT {
  245.     VARIABLE->yyRelSeconds += $1;
  246. }
  247. | tUNUMBER tSEC_UNIT {
  248.     VARIABLE->yyRelSeconds += $1;
  249. }
  250. | tSEC_UNIT {
  251.     VARIABLE->yyRelSeconds++;
  252. }
  253. | tSNUMBER tMONTH_UNIT {
  254.     VARIABLE->yyRelMonth += $1 * $2;
  255. }
  256. | tUNUMBER tMONTH_UNIT {
  257.     VARIABLE->yyRelMonth += $1 * $2;
  258. }
  259. | tMONTH_UNIT {
  260.     VARIABLE->yyRelMonth += $1;
  261. }
  262. ;
  263. number : tUNUMBER {
  264.     if (VARIABLE->yyHaveTime && VARIABLE->yyHaveDate && !VARIABLE->yyHaveRel)
  265. VARIABLE->yyYear = $1;
  266.     else {
  267. if($1>10000) {
  268.     VARIABLE->yyHaveDate++;
  269.     VARIABLE->yyDay= ($1)%100;
  270.     VARIABLE->yyMonth= ($1/100)%100;
  271.     VARIABLE->yyYear = $1/10000;
  272. }
  273. else {
  274.     VARIABLE->yyHaveTime++;
  275.     if ($1 < 100) {
  276. VARIABLE->yyHour = $1;
  277. VARIABLE->yyMinutes = 0;
  278.     }
  279.     else {
  280.      VARIABLE->yyHour = $1 / 100;
  281.      VARIABLE->yyMinutes = $1 % 100;
  282.     }
  283.     VARIABLE->yySeconds = 0;
  284.     VARIABLE->yyMeridian = MER24;
  285.         }
  286.     }
  287. }
  288. ;
  289. o_merid : /* NULL */ {
  290.     $$ = MER24;
  291. }
  292. | tMERIDIAN {
  293.     $$ = $1;
  294. }
  295. ;
  296. %%
  297. /* Month and day table. */
  298. static TABLE const MonthDayTable[] = {
  299.     { "january", tMONTH,  1 },
  300.     { "february", tMONTH,  2 },
  301.     { "march", tMONTH,  3 },
  302.     { "april", tMONTH,  4 },
  303.     { "may", tMONTH,  5 },
  304.     { "june", tMONTH,  6 },
  305.     { "july", tMONTH,  7 },
  306.     { "august", tMONTH,  8 },
  307.     { "september", tMONTH,  9 },
  308.     { "sept", tMONTH,  9 },
  309.     { "october", tMONTH, 10 },
  310.     { "november", tMONTH, 11 },
  311.     { "december", tMONTH, 12 },
  312.     { "sunday", tDAY, 0 },
  313.     { "monday", tDAY, 1 },
  314.     { "tuesday", tDAY, 2 },
  315.     { "tues", tDAY, 2 },
  316.     { "wednesday", tDAY, 3 },
  317.     { "wednes", tDAY, 3 },
  318.     { "thursday", tDAY, 4 },
  319.     { "thur", tDAY, 4 },
  320.     { "thurs", tDAY, 4 },
  321.     { "friday", tDAY, 5 },
  322.     { "saturday", tDAY, 6 },
  323.     { NULL }
  324. };
  325. /* Time units table. */
  326. static TABLE const UnitsTable[] = {
  327.     { "year", tMONTH_UNIT, 12 },
  328.     { "month", tMONTH_UNIT, 1 },
  329.     { "fortnight", tMINUTE_UNIT, 14 * 24 * 60 },
  330.     { "week", tMINUTE_UNIT, 7 * 24 * 60 },
  331.     { "day", tMINUTE_UNIT, 1 * 24 * 60 },
  332.     { "hour", tMINUTE_UNIT, 60 },
  333.     { "minute", tMINUTE_UNIT, 1 },
  334.     { "min", tMINUTE_UNIT, 1 },
  335.     { "second", tSEC_UNIT, 1 },
  336.     { "sec", tSEC_UNIT, 1 },
  337.     { NULL }
  338. };
  339. /* Assorted relative-time words. */
  340. static TABLE const OtherTable[] = {
  341.     { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
  342.     { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
  343.     { "today", tMINUTE_UNIT, 0 },
  344.     { "now", tMINUTE_UNIT, 0 },
  345.     { "last", tUNUMBER, -1 },
  346.     { "this", tMINUTE_UNIT, 0 },
  347.     { "next", tUNUMBER, 2 },
  348.     { "first", tUNUMBER, 1 },
  349. /*  { "second", tUNUMBER, 2 }, */
  350.     { "third", tUNUMBER, 3 },
  351.     { "fourth", tUNUMBER, 4 },
  352.     { "fifth", tUNUMBER, 5 },
  353.     { "sixth", tUNUMBER, 6 },
  354.     { "seventh", tUNUMBER, 7 },
  355.     { "eighth", tUNUMBER, 8 },
  356.     { "ninth", tUNUMBER, 9 },
  357.     { "tenth", tUNUMBER, 10 },
  358.     { "eleventh", tUNUMBER, 11 },
  359.     { "twelfth", tUNUMBER, 12 },
  360.     { "ago", tAGO, 1 },
  361.     { NULL }
  362. };
  363. /* The timezone table. */
  364. /* Some of these are commented out because a time_t can't store a float. */
  365. static TABLE const TimezoneTable[] = {
  366.     { "gmt", tZONE,     HOUR( 0) }, /* Greenwich Mean */
  367.     { "ut", tZONE,     HOUR( 0) }, /* Universal (Coordinated) */
  368.     { "utc", tZONE,     HOUR( 0) },
  369.     { "wet", tZONE,     HOUR( 0) }, /* Western European */
  370.     { "bst", tDAYZONE,  HOUR( 0) }, /* British Summer */
  371.     { "wat", tZONE,     HOUR( 1) }, /* West Africa */
  372.     { "at", tZONE,     HOUR( 2) }, /* Azores */
  373. #if 0
  374.     /* For completeness.  BST is also British Summer, and GST is
  375.      * also Guam Standard. */
  376.     { "bst", tZONE,     HOUR( 3) }, /* Brazil Standard */
  377.     { "gst", tZONE,     HOUR( 3) }, /* Greenland Standard */
  378. #endif
  379. #if 0
  380.     { "nft", tZONE,     HOUR(3.5) }, /* Newfoundland */
  381.     { "nst", tZONE,     HOUR(3.5) }, /* Newfoundland Standard */
  382.     { "ndt", tDAYZONE,  HOUR(3.5) }, /* Newfoundland Daylight */
  383. #endif
  384.     { "ast", tZONE,     HOUR( 4) }, /* Atlantic Standard */
  385.     { "adt", tDAYZONE,  HOUR( 4) }, /* Atlantic Daylight */
  386.     { "est", tZONE,     HOUR( 5) }, /* Eastern Standard */
  387.     { "edt", tDAYZONE,  HOUR( 5) }, /* Eastern Daylight */
  388.     { "cst", tZONE,     HOUR( 6) }, /* Central Standard */
  389.     { "cdt", tDAYZONE,  HOUR( 6) }, /* Central Daylight */
  390.     { "mst", tZONE,     HOUR( 7) }, /* Mountain Standard */
  391.     { "mdt", tDAYZONE,  HOUR( 7) }, /* Mountain Daylight */
  392.     { "pst", tZONE,     HOUR( 8) }, /* Pacific Standard */
  393.     { "pdt", tDAYZONE,  HOUR( 8) }, /* Pacific Daylight */
  394.     { "yst", tZONE,     HOUR( 9) }, /* Yukon Standard */
  395.     { "ydt", tDAYZONE,  HOUR( 9) }, /* Yukon Daylight */
  396.     { "hst", tZONE,     HOUR(10) }, /* Hawaii Standard */
  397.     { "hdt", tDAYZONE,  HOUR(10) }, /* Hawaii Daylight */
  398.     { "cat", tZONE,     HOUR(10) }, /* Central Alaska */
  399.     { "ahst", tZONE,     HOUR(10) }, /* Alaska-Hawaii Standard */
  400.     { "nt", tZONE,     HOUR(11) }, /* Nome */
  401.     { "idlw", tZONE,     HOUR(12) }, /* International Date Line West */
  402.     { "cet", tZONE,     -HOUR(1) }, /* Central European */
  403.     { "met", tZONE,     -HOUR(1) }, /* Middle European */
  404.     { "mewt", tZONE,     -HOUR(1) }, /* Middle European Winter */
  405.     { "mest", tDAYZONE,  -HOUR(1) }, /* Middle European Summer */
  406.     { "swt", tZONE,     -HOUR(1) }, /* Swedish Winter */
  407.     { "sst", tDAYZONE,  -HOUR(1) }, /* Swedish Summer */
  408.     { "fwt", tZONE,     -HOUR(1) }, /* French Winter */
  409.     { "fst", tDAYZONE,  -HOUR(1) }, /* French Summer */
  410.     { "eet", tZONE,     -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */
  411.     { "bt", tZONE,     -HOUR(3) }, /* Baghdad, USSR Zone 2 */
  412. #if 0
  413.     { "it", tZONE,     -HOUR(3.5) },/* Iran */
  414. #endif
  415.     { "zp4", tZONE,     -HOUR(4) }, /* USSR Zone 3 */
  416.     { "zp5", tZONE,     -HOUR(5) }, /* USSR Zone 4 */
  417. #if 0
  418.     { "ist", tZONE,     -HOUR(5.5) },/* Indian Standard */
  419. #endif
  420.     { "zp6", tZONE,     -HOUR(6) }, /* USSR Zone 5 */
  421. #if 0
  422.     /* For completeness.  NST is also Newfoundland Stanard, and SST is
  423.      * also Swedish Summer. */
  424.     { "nst", tZONE,     -HOUR(6.5) },/* North Sumatra */
  425.     { "sst", tZONE,     -HOUR(7) }, /* South Sumatra, USSR Zone 6 */
  426. #endif /* 0 */
  427.     { "wast", tZONE,     -HOUR(7) }, /* West Australian Standard */
  428.     { "wadt", tDAYZONE,  -HOUR(7) }, /* West Australian Daylight */
  429. #if 0
  430.     { "jt", tZONE,     -HOUR(7.5) },/* Java (3pm in Cronusland!) */
  431. #endif
  432.     { "cct", tZONE,     -HOUR(8) }, /* China Coast, USSR Zone 7 */
  433.     { "jst", tZONE,     -HOUR(9) }, /* Japan Standard, USSR Zone 8 */
  434. #if 0
  435.     { "cast", tZONE,     -HOUR(9.5) },/* Central Australian Standard */
  436.     { "cadt", tDAYZONE,  -HOUR(9.5) },/* Central Australian Daylight */
  437. #endif
  438.     { "east", tZONE,     -HOUR(10) }, /* Eastern Australian Standard */
  439.     { "eadt", tDAYZONE,  -HOUR(10) }, /* Eastern Australian Daylight */
  440.     { "gst", tZONE,     -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
  441.     { "nzt", tZONE,     -HOUR(12) }, /* New Zealand */
  442.     { "nzst", tZONE,     -HOUR(12) }, /* New Zealand Standard */
  443.     { "nzdt", tDAYZONE,  -HOUR(12) }, /* New Zealand Daylight */
  444.     { "idle", tZONE,     -HOUR(12) }, /* International Date Line East */
  445.     {  NULL  }
  446. };
  447. /* Military timezone table. */
  448. static TABLE const MilitaryTable[] = {
  449.     { "a", tZONE, HOUR(  1) },
  450.     { "b", tZONE, HOUR(  2) },
  451.     { "c", tZONE, HOUR(  3) },
  452.     { "d", tZONE, HOUR(  4) },
  453.     { "e", tZONE, HOUR(  5) },
  454.     { "f", tZONE, HOUR(  6) },
  455.     { "g", tZONE, HOUR(  7) },
  456.     { "h", tZONE, HOUR(  8) },
  457.     { "i", tZONE, HOUR(  9) },
  458.     { "k", tZONE, HOUR( 10) },
  459.     { "l", tZONE, HOUR( 11) },
  460.     { "m", tZONE, HOUR( 12) },
  461.     { "n", tZONE, HOUR(- 1) },
  462.     { "o", tZONE, HOUR(- 2) },
  463.     { "p", tZONE, HOUR(- 3) },
  464.     { "q", tZONE, HOUR(- 4) },
  465.     { "r", tZONE, HOUR(- 5) },
  466.     { "s", tZONE, HOUR(- 6) },
  467.     { "t", tZONE, HOUR(- 7) },
  468.     { "u", tZONE, HOUR(- 8) },
  469.     { "v", tZONE, HOUR(- 9) },
  470.     { "w", tZONE, HOUR(-10) },
  471.     { "x", tZONE, HOUR(-11) },
  472.     { "y", tZONE, HOUR(-12) },
  473.     { "z", tZONE, HOUR(  0) },
  474.     { NULL }
  475. };
  476. static int LookupWord(char * buff, YYSTYPE * yylval)
  477. {
  478.     register char *p;
  479.     register char *q;
  480.     register const TABLE *tp;
  481.     int i;
  482.     int abbrev;
  483.     /* Make it lowercase. */
  484.     for (p = buff; *p != ''; p++)
  485.         *p = (char)tolower(*p);
  486.     if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
  487. yylval->Meridian = MERam;
  488. return tMERIDIAN;
  489.     }
  490.     if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
  491. yylval->Meridian = MERpm;
  492. return tMERIDIAN;
  493.     }
  494.     /* See if we have an abbreviation for a month. */
  495.     if (strlen(buff) == 3)
  496. abbrev = 1;
  497.     else if (strlen(buff) == 4 && buff[3] == '.') {
  498. abbrev = 1;
  499. buff[3] = '';
  500.     }
  501.     else
  502. abbrev = 0;
  503.     for (tp = MonthDayTable; tp->name; tp++) {
  504. if (abbrev) {
  505.     if (strncmp(buff, tp->name, 3) == 0) {
  506. yylval->Number = tp->value;
  507. return tp->type;
  508.     }
  509. }
  510. else if (strcmp(buff, tp->name) == 0) {
  511.     yylval->Number = tp->value;
  512.     return tp->type;
  513. }
  514.     }
  515.     for (tp = TimezoneTable; tp->name; tp++)
  516. if (strcmp(buff, tp->name) == 0) {
  517.     yylval->Number = tp->value;
  518.     return tp->type;
  519. }
  520.     if (strcmp(buff, "dst") == 0) 
  521. return tDST;
  522.     for (tp = UnitsTable; tp->name; tp++)
  523. if (strcmp(buff, tp->name) == 0) {
  524.     yylval->Number = tp->value;
  525.     return tp->type;
  526. }
  527.     /* Strip off any plural and try the units table again. */
  528.     i = strlen(buff) - 1;
  529.     if (buff[i] == 's') {
  530. buff[i] = '';
  531. for (tp = UnitsTable; tp->name; tp++)
  532.     if (strcmp(buff, tp->name) == 0) {
  533. yylval->Number = tp->value;
  534. return tp->type;
  535.     }
  536. buff[i] = 's'; /* Put back for "this" in OtherTable. */
  537.     }
  538.     for (tp = OtherTable; tp->name; tp++)
  539. if (strcmp(buff, tp->name) == 0) {
  540.     yylval->Number = tp->value;
  541.     return tp->type;
  542. }
  543.     /* Military timezones. */
  544.     if (buff[1] == '' && isalpha(*buff)) {
  545. for (tp = MilitaryTable; tp->name; tp++)
  546.     if (strcmp(buff, tp->name) == 0) {
  547. yylval->Number = tp->value;
  548. return tp->type;
  549.     }
  550.     }
  551.     /* Drop out any periods and try the timezone table again. */
  552.     for (i = 0, p = q = buff; *q; q++)
  553. if (*q != '.')
  554.     *p++ = *q;
  555. else
  556.     i++;
  557.     *p = '';
  558.     if (i)
  559. for (tp = TimezoneTable; tp->name; tp++)
  560.     if (strcmp(buff, tp->name) == 0) {
  561. yylval->Number = tp->value;
  562. return tp->type;
  563.     }
  564.     for (i = 1; i <= 12; i++)
  565. for (abbrev = 0; abbrev < 2; abbrev++)
  566.     if (PTimeIsMonthName(buff, i, abbrev)) {
  567. yylval->Number = i;
  568. return tMONTH;
  569.     }
  570.     for (i = 1; i <= 7; i++)
  571. for (abbrev = 0; abbrev < 2; abbrev++)
  572.     if (PTimeIsDayName(buff, i, abbrev)) {
  573. yylval->Number = i;
  574. return tDAY;
  575.     }
  576.     return tID;
  577. }
  578. #ifdef _MSC_VER
  579. #pragma warning(disable:4211)
  580. #endif
  581. #ifndef __GNUC__
  582. static
  583. #endif
  584. int yylex(YYSTYPE * yylval, void * yyInput)
  585. {
  586.     register char *p;
  587.     char buff[20];
  588.     int Count;
  589.     int sign;
  590.     register int c = PTimeGetChar(yyInput);
  591.     while (c != EOF && c != '' && c != 'n') {
  592. while (isspace(c))
  593.     c = PTimeGetChar(yyInput);
  594. if (isdigit(c) || c == '-' || c == '+') {
  595.     if (c == '-' || c == '+') {
  596. sign = c == '-' ? -1 : 1;
  597. if (!isdigit(c = PTimeGetChar(yyInput)))
  598.     /* skip the '-' sign */
  599.     continue;
  600.     }
  601.     else
  602. sign = 0;
  603.     yylval->Number = 0;
  604.     while (isdigit(c)) {
  605. yylval->Number = 10 * yylval->Number + c - '0';
  606. c = PTimeGetChar(yyInput);
  607.     }
  608.     PTimeUngetChar(yyInput, c);
  609.     if (sign < 0)
  610. yylval->Number = -yylval->Number;
  611.     return sign ? tSNUMBER : tUNUMBER;
  612. }
  613. if (isalpha(c)) {
  614.     for (p = buff; isalpha(c) || c == '.'; c = PTimeGetChar(yyInput)) {
  615. if (p < &buff[sizeof(buff)-1])
  616.     *p++ = (char)c;
  617.     }
  618.     *p = '';
  619.     PTimeUngetChar(yyInput, c);
  620.     return LookupWord(buff, yylval);
  621. }
  622. if (c != '(')
  623.     return c;
  624. Count = 0;
  625. do {
  626.     c = PTimeGetChar(yyInput);
  627.     if (c == '' || c == EOF)
  628. return c;
  629.     if (c == '(')
  630. Count++;
  631.     else if (c == ')')
  632. Count--;
  633. } while (Count > 0);
  634.     }
  635.     return EOF;
  636. }
  637. #ifdef _MSC_VER
  638. #pragma warning(default:4211)
  639. #endif
  640. static time_t ToSeconds(time_t Hours, time_t Minutes, time_t Seconds,
  641. MERIDIAN Meridian)
  642. {
  643.     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
  644. return -1;
  645.     switch (Meridian) {
  646.     case MER24:
  647. if (Hours < 0 || Hours > 23)
  648.     return -1;
  649. return (Hours * 60L + Minutes) * 60L + Seconds;
  650.     case MERam:
  651. if (Hours < 1 || Hours > 12)
  652.     return -1;
  653. if (Hours == 12)
  654.     Hours = 0;
  655. return (Hours * 60L + Minutes) * 60L + Seconds;
  656.     case MERpm:
  657. if (Hours < 1 || Hours > 12)
  658.     return -1;
  659. if (Hours == 12)
  660.     Hours = 0;
  661. return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
  662.     }
  663.     return -1;
  664. }
  665. static time_t Convert(time_t Month, time_t Day, time_t Year,
  666.       time_t Hours, time_t Minutes, time_t Seconds,
  667.       MERIDIAN Meridian, DSTMODE DSTmode, time_t yyTimezone)
  668. {
  669.     static int DaysInMonth[12] = {
  670. 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  671.     };
  672.     time_t tod;
  673.     time_t Julian;
  674.     int i;
  675.     if (Year < 0)
  676. Year = -Year;
  677.     if (Year < 70)
  678. Year += 2000;
  679.     else if (Year < 100)
  680. Year += 1900;
  681.     DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
  682.     ? 29 : 28;
  683.     /* Checking for 2038 bogusly assumes that time_t is 32 bits.  But
  684.        I'm too lazy to try to check for time_t overflow in another way.  */
  685.     if (Year < EPOCH || Year > 2038
  686.      || Month < 1 || Month > 12
  687.      /* Lint fluff:  "conversion from long may lose accuracy" */
  688.      || Day < 1 || Day > DaysInMonth[(int)--Month])
  689. return -1;
  690.     for (Julian = Day - 1, i = 0; i < Month; i++)
  691. Julian += DaysInMonth[i];
  692.     for (i = EPOCH; i < Year; i++)
  693. Julian += 365 + (i % 4 == 0);
  694.     Julian *= SECSPERDAY;
  695.     Julian += yyTimezone * 60L;
  696.     if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
  697. return -1;
  698.     Julian += tod;
  699.     if (DSTmode == DSTon
  700.      || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
  701. Julian -= 60 * 60;
  702.     return Julian;
  703. }
  704. static time_t DSTcorrect(time_t Start, time_t Future)
  705. {
  706.     time_t StartDay;
  707.     time_t FutureDay;
  708.     StartDay = (localtime(&Start)->tm_hour + 1) % 24;
  709.     FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
  710.     return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
  711. }
  712. static time_t RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
  713. {
  714.     struct tm *tm;
  715.     time_t now;
  716.     now = Start;
  717.     tm = localtime(&now);
  718.     now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
  719.     now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
  720.     return DSTcorrect(Start, now);
  721. }
  722. static time_t RelativeMonth(time_t Start, time_t RelMonth, time_t yyTimezone)
  723. {
  724.     struct tm *tm;
  725.     time_t Month;
  726.     time_t Year;
  727.     if (RelMonth == 0)
  728. return 0;
  729.     tm = localtime(&Start);
  730.     Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
  731.     Year = Month / 12;
  732.     Month = Month % 12 + 1;
  733.     return DSTcorrect(Start,
  734.     Convert(Month, (time_t)tm->tm_mday, Year,
  735. (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
  736. MER24, DSTmaybe, yyTimezone));
  737. }
  738. static void SetPossibleDate(struct Variables * var,
  739.       time_t possible_day,
  740.       time_t possible_month,
  741.       time_t possible_year)
  742. {
  743.     int date_order;
  744.     if (possible_day > 31) /* test for ymd */
  745. date_order = 2;
  746.     else if (possible_day > 12) /* test for dmy */
  747. date_order = 1;
  748.     else if (possible_month > 12) /* test for mdy */
  749. date_order = 0;
  750.     else {
  751. static int default_date_order = -1;
  752. if (default_date_order < 0)
  753.     default_date_order = PTimeGetDateOrder();
  754. date_order = default_date_order;
  755.     }
  756.     switch (date_order) {
  757.       case 0 :
  758. var->yyDay   = possible_month;
  759. var->yyMonth = possible_day;
  760. var->yyYear  = possible_year;
  761. break;
  762.       case 1 :
  763. var->yyDay   = possible_day;
  764. var->yyMonth = possible_month;
  765. var->yyYear  = possible_year;
  766. break;
  767.       default :
  768. var->yyDay   = possible_year;
  769. var->yyMonth = possible_month;
  770. var->yyYear  = possible_day;
  771.     }
  772. }
  773. time_t STDAPICALLTYPE PTimeParse(void * inputStream, struct tm * now, int timezone)
  774. {
  775.     time_t Start;
  776.     struct Variables var;
  777.     var.yyInput = inputStream;
  778.     var.yyYear = now->tm_year + 1900;
  779.     var.yyMonth = now->tm_mon + 1;
  780.     var.yyDay = now->tm_mday;
  781.     var.yyTimezone = -timezone;
  782.     var.yyDSTmode = DSTmaybe;
  783.     var.yyHour = 0;
  784.     var.yyMinutes = 0;
  785.     var.yySeconds = 0;
  786.     var.yyMeridian = MER24;
  787.     var.yyRelSeconds = 0;
  788.     var.yyRelMonth = 0;
  789.     var.yyHaveDate = 0;
  790.     var.yyHaveDay = 0;
  791.     var.yyHaveRel = 0;
  792.     var.yyHaveTime = 0;
  793.     var.yyHaveZone = 0;
  794.     yyparse(&var);
  795.     if (var.yyHaveTime > 1 || var.yyHaveZone > 1 ||
  796. var.yyHaveDate > 1 || var.yyHaveDay > 1)
  797. return -1;
  798.     if (var.yyHaveTime == 0 && var.yyHaveZone == 0 &&
  799. var.yyHaveDate == 0 && var.yyHaveDay == 0 && var.yyHaveRel == 0)
  800. return -1;
  801.     if (var.yyHaveDate || var.yyHaveTime || var.yyHaveDay) {
  802. Start = Convert(var.yyMonth, var.yyDay, var.yyYear,
  803. var.yyHour, var.yyMinutes, var.yySeconds,
  804. var.yyMeridian, var.yyDSTmode, var.yyTimezone);
  805. if (Start < 0)
  806.     return -1;
  807.     }
  808.     else {
  809. time(&Start);
  810. if (!var.yyHaveRel)
  811.     Start -= ((now->tm_hour * 60L + now->tm_min) * 60L) + now->tm_sec;
  812.     }
  813.     Start += var.yyRelSeconds;
  814.     Start += RelativeMonth(Start, var.yyRelMonth, var.yyTimezone);
  815.     if (var.yyHaveDay && !var.yyHaveDate)
  816. Start += RelativeDate(Start, var.yyDayOrdinal, var.yyDayNumber);
  817.     /* Have to do *something* with a legitimate -1 so it's distinguishable
  818.      * from the error return value.  (Alternately could set errno on error.) */
  819.     return Start == -1 ? 0 : Start;
  820. }
  821. #ifdef _MSC_VER
  822. #pragma warning(disable:4100 4211)
  823. #endif
  824. #ifdef __GNUC__
  825. int yyerror(const char * s)
  826. {
  827.   return 0;
  828. }
  829. #else
  830. static void yyerror(const char * s)
  831. {
  832. }
  833. #endif
  834. #ifdef _MSC_VER
  835. #pragma warning(default:4100 4211)
  836. #endif
  837. /* End of file ***************************************************************/