PageRenderTime 27ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/generic/tclGetDate.y

https://code.google.com/p/tcljit/
Happy | 1128 lines | 1021 code | 107 blank | 0 comment | 0 complexity | 75c4db2636ab9c889ef53d70decf67b7 MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*
  2. * tclGetDate.y --
  3. *
  4. * Contains yacc grammar for parsing date and time strings. The output of
  5. * this file should be the file tclDate.c which is used directly in the
  6. * Tcl sources. Note that this file is largely obsolete in Tcl 8.5; it is
  7. * only used when doing free-form date parsing, an ill-defined process
  8. * anyway.
  9. *
  10. * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
  11. * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  12. *
  13. * See the file "license.terms" for information on usage and redistribution of
  14. * this file, and for a DISCLAIMER OF ALL WARRANTIES.
  15. *
  16. * RCS: @(#) $Id: tclGetDate.y,v 1.38.2.1 2009/06/09 13:52:58 kennykb Exp $
  17. */
  18. %parse-param {DateInfo* info}
  19. %lex-param {DateInfo* info}
  20. %pure-parser
  21. /* %error-verbose would be nice, but our token names are meaningless */
  22. %locations
  23. %{
  24. /*
  25. * tclDate.c --
  26. *
  27. * This file is generated from a yacc grammar defined in the file
  28. * tclGetDate.y. It should not be edited directly.
  29. *
  30. * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
  31. * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  32. *
  33. * See the file "license.terms" for information on usage and redistribution of
  34. * this file, and for a DISCLAIMER OF ALL WARRANTIES.
  35. *
  36. */
  37. #include "tclInt.h"
  38. /*
  39. * Bison generates several labels that happen to be unused. MS Visual C++
  40. * doesn't like that, and complains. Tell it to shut up.
  41. */
  42. #ifdef _MSC_VER
  43. #pragma warning( disable : 4102 )
  44. #endif /* _MSC_VER */
  45. /*
  46. * yyparse will accept a 'struct DateInfo' as its parameter; that's where the
  47. * parsed fields will be returned.
  48. */
  49. typedef struct DateInfo {
  50. Tcl_Obj* messages; /* Error messages */
  51. const char* separatrix; /* String separating messages */
  52. time_t dateYear;
  53. time_t dateMonth;
  54. time_t dateDay;
  55. int dateHaveDate;
  56. time_t dateHour;
  57. time_t dateMinutes;
  58. time_t dateSeconds;
  59. int dateMeridian;
  60. int dateHaveTime;
  61. time_t dateTimezone;
  62. int dateDSTmode;
  63. int dateHaveZone;
  64. time_t dateRelMonth;
  65. time_t dateRelDay;
  66. time_t dateRelSeconds;
  67. int dateHaveRel;
  68. time_t dateMonthOrdinal;
  69. int dateHaveOrdinalMonth;
  70. time_t dateDayOrdinal;
  71. time_t dateDayNumber;
  72. int dateHaveDay;
  73. const char *dateStart;
  74. const char *dateInput;
  75. time_t *dateRelPointer;
  76. int dateDigitCount;
  77. } DateInfo;
  78. #define YYMALLOC ckalloc
  79. #define YYFREE(x) (ckfree((void*) (x)))
  80. #define yyDSTmode (info->dateDSTmode)
  81. #define yyDayOrdinal (info->dateDayOrdinal)
  82. #define yyDayNumber (info->dateDayNumber)
  83. #define yyMonthOrdinal (info->dateMonthOrdinal)
  84. #define yyHaveDate (info->dateHaveDate)
  85. #define yyHaveDay (info->dateHaveDay)
  86. #define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth)
  87. #define yyHaveRel (info->dateHaveRel)
  88. #define yyHaveTime (info->dateHaveTime)
  89. #define yyHaveZone (info->dateHaveZone)
  90. #define yyTimezone (info->dateTimezone)
  91. #define yyDay (info->dateDay)
  92. #define yyMonth (info->dateMonth)
  93. #define yyYear (info->dateYear)
  94. #define yyHour (info->dateHour)
  95. #define yyMinutes (info->dateMinutes)
  96. #define yySeconds (info->dateSeconds)
  97. #define yyMeridian (info->dateMeridian)
  98. #define yyRelMonth (info->dateRelMonth)
  99. #define yyRelDay (info->dateRelDay)
  100. #define yyRelSeconds (info->dateRelSeconds)
  101. #define yyRelPointer (info->dateRelPointer)
  102. #define yyInput (info->dateInput)
  103. #define yyDigitCount (info->dateDigitCount)
  104. #define EPOCH 1970
  105. #define START_OF_TIME 1902
  106. #define END_OF_TIME 2037
  107. /*
  108. * The offset of tm_year of struct tm returned by localtime, gmtime, etc.
  109. * Posix requires 1900.
  110. */
  111. #define TM_YEAR_BASE 1900
  112. #define HOUR(x) ((int) (60 * x))
  113. #define SECSPERDAY (24L * 60L * 60L)
  114. #define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
  115. /*
  116. * An entry in the lexical lookup table.
  117. */
  118. typedef struct _TABLE {
  119. const char *name;
  120. int type;
  121. time_t value;
  122. } TABLE;
  123. /*
  124. * Daylight-savings mode: on, off, or not yet known.
  125. */
  126. typedef enum _DSTMODE {
  127. DSTon, DSToff, DSTmaybe
  128. } DSTMODE;
  129. /*
  130. * Meridian: am, pm, or 24-hour style.
  131. */
  132. typedef enum _MERIDIAN {
  133. MERam, MERpm, MER24
  134. } MERIDIAN;
  135. %}
  136. %union {
  137. time_t Number;
  138. enum _MERIDIAN Meridian;
  139. }
  140. %{
  141. /*
  142. * Prototypes of internal functions.
  143. */
  144. static int LookupWord(YYSTYPE* yylvalPtr, char *buff);
  145. static void TclDateerror(YYLTYPE* location,
  146. DateInfo* info, const char *s);
  147. static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
  148. DateInfo* info);
  149. static time_t ToSeconds(time_t Hours, time_t Minutes,
  150. time_t Seconds, MERIDIAN Meridian);
  151. MODULE_SCOPE int yyparse(DateInfo*);
  152. %}
  153. %token tAGO
  154. %token tDAY
  155. %token tDAYZONE
  156. %token tID
  157. %token tMERIDIAN
  158. %token tMONTH
  159. %token tMONTH_UNIT
  160. %token tSTARDATE
  161. %token tSEC_UNIT
  162. %token tSNUMBER
  163. %token tUNUMBER
  164. %token tZONE
  165. %token tEPOCH
  166. %token tDST
  167. %token tISOBASE
  168. %token tDAY_UNIT
  169. %token tNEXT
  170. %type <Number> tDAY
  171. %type <Number> tDAYZONE
  172. %type <Number> tMONTH
  173. %type <Number> tMONTH_UNIT
  174. %type <Number> tDST
  175. %type <Number> tSEC_UNIT
  176. %type <Number> tSNUMBER
  177. %type <Number> tUNUMBER
  178. %type <Number> tZONE
  179. %type <Number> tISOBASE
  180. %type <Number> tDAY_UNIT
  181. %type <Number> unit
  182. %type <Number> sign
  183. %type <Number> tNEXT
  184. %type <Number> tSTARDATE
  185. %type <Meridian> tMERIDIAN
  186. %type <Meridian> o_merid
  187. %%
  188. spec : /* NULL */
  189. | spec item
  190. ;
  191. item : time {
  192. yyHaveTime++;
  193. }
  194. | zone {
  195. yyHaveZone++;
  196. }
  197. | date {
  198. yyHaveDate++;
  199. }
  200. | ordMonth {
  201. yyHaveOrdinalMonth++;
  202. }
  203. | day {
  204. yyHaveDay++;
  205. }
  206. | relspec {
  207. yyHaveRel++;
  208. }
  209. | iso {
  210. yyHaveTime++;
  211. yyHaveDate++;
  212. }
  213. | trek {
  214. yyHaveTime++;
  215. yyHaveDate++;
  216. yyHaveRel++;
  217. }
  218. | number
  219. ;
  220. time : tUNUMBER tMERIDIAN {
  221. yyHour = $1;
  222. yyMinutes = 0;
  223. yySeconds = 0;
  224. yyMeridian = $2;
  225. }
  226. | tUNUMBER ':' tUNUMBER o_merid {
  227. yyHour = $1;
  228. yyMinutes = $3;
  229. yySeconds = 0;
  230. yyMeridian = $4;
  231. }
  232. | tUNUMBER ':' tUNUMBER '-' tUNUMBER {
  233. yyHour = $1;
  234. yyMinutes = $3;
  235. yyMeridian = MER24;
  236. yyDSTmode = DSToff;
  237. yyTimezone = ($5 % 100 + ($5 / 100) * 60);
  238. ++yyHaveZone;
  239. }
  240. | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
  241. yyHour = $1;
  242. yyMinutes = $3;
  243. yySeconds = $5;
  244. yyMeridian = $6;
  245. }
  246. | tUNUMBER ':' tUNUMBER ':' tUNUMBER '-' tUNUMBER {
  247. yyHour = $1;
  248. yyMinutes = $3;
  249. yySeconds = $5;
  250. yyMeridian = MER24;
  251. yyDSTmode = DSToff;
  252. yyTimezone = ($7 % 100 + ($7 / 100) * 60);
  253. ++yyHaveZone;
  254. }
  255. ;
  256. zone : tZONE tDST {
  257. yyTimezone = $1;
  258. yyDSTmode = DSTon;
  259. }
  260. | tZONE {
  261. yyTimezone = $1;
  262. yyDSTmode = DSToff;
  263. }
  264. | tDAYZONE {
  265. yyTimezone = $1;
  266. yyDSTmode = DSTon;
  267. }
  268. ;
  269. day : tDAY {
  270. yyDayOrdinal = 1;
  271. yyDayNumber = $1;
  272. }
  273. | tDAY ',' {
  274. yyDayOrdinal = 1;
  275. yyDayNumber = $1;
  276. }
  277. | tUNUMBER tDAY {
  278. yyDayOrdinal = $1;
  279. yyDayNumber = $2;
  280. }
  281. | sign tUNUMBER tDAY {
  282. yyDayOrdinal = $1 * $2;
  283. yyDayNumber = $3;
  284. }
  285. | tNEXT tDAY {
  286. yyDayOrdinal = 2;
  287. yyDayNumber = $2;
  288. }
  289. ;
  290. date : tUNUMBER '/' tUNUMBER {
  291. yyMonth = $1;
  292. yyDay = $3;
  293. }
  294. | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
  295. yyMonth = $1;
  296. yyDay = $3;
  297. yyYear = $5;
  298. }
  299. | tISOBASE {
  300. yyYear = $1 / 10000;
  301. yyMonth = ($1 % 10000)/100;
  302. yyDay = $1 % 100;
  303. }
  304. | tUNUMBER '-' tMONTH '-' tUNUMBER {
  305. yyDay = $1;
  306. yyMonth = $3;
  307. yyYear = $5;
  308. }
  309. | tUNUMBER '-' tUNUMBER '-' tUNUMBER {
  310. yyMonth = $3;
  311. yyDay = $5;
  312. yyYear = $1;
  313. }
  314. | tMONTH tUNUMBER {
  315. yyMonth = $1;
  316. yyDay = $2;
  317. }
  318. | tMONTH tUNUMBER ',' tUNUMBER {
  319. yyMonth = $1;
  320. yyDay = $2;
  321. yyYear = $4;
  322. }
  323. | tUNUMBER tMONTH {
  324. yyMonth = $2;
  325. yyDay = $1;
  326. }
  327. | tEPOCH {
  328. yyMonth = 1;
  329. yyDay = 1;
  330. yyYear = EPOCH;
  331. }
  332. | tUNUMBER tMONTH tUNUMBER {
  333. yyMonth = $2;
  334. yyDay = $1;
  335. yyYear = $3;
  336. }
  337. ;
  338. ordMonth: tNEXT tMONTH {
  339. yyMonthOrdinal = 1;
  340. yyMonth = $2;
  341. }
  342. | tNEXT tUNUMBER tMONTH {
  343. yyMonthOrdinal = $2;
  344. yyMonth = $3;
  345. }
  346. ;
  347. iso : tISOBASE tZONE tISOBASE {
  348. if ($2 != HOUR( 7)) YYABORT;
  349. yyYear = $1 / 10000;
  350. yyMonth = ($1 % 10000)/100;
  351. yyDay = $1 % 100;
  352. yyHour = $3 / 10000;
  353. yyMinutes = ($3 % 10000)/100;
  354. yySeconds = $3 % 100;
  355. }
  356. | tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER {
  357. if ($2 != HOUR( 7)) YYABORT;
  358. yyYear = $1 / 10000;
  359. yyMonth = ($1 % 10000)/100;
  360. yyDay = $1 % 100;
  361. yyHour = $3;
  362. yyMinutes = $5;
  363. yySeconds = $7;
  364. }
  365. | tISOBASE tISOBASE {
  366. yyYear = $1 / 10000;
  367. yyMonth = ($1 % 10000)/100;
  368. yyDay = $1 % 100;
  369. yyHour = $2 / 10000;
  370. yyMinutes = ($2 % 10000)/100;
  371. yySeconds = $2 % 100;
  372. }
  373. ;
  374. trek : tSTARDATE tUNUMBER '.' tUNUMBER {
  375. /*
  376. * Offset computed year by -377 so that the returned years will be
  377. * in a range accessible with a 32 bit clock seconds value.
  378. */
  379. yyYear = $2/1000 + 2323 - 377;
  380. yyDay = 1;
  381. yyMonth = 1;
  382. yyRelDay += (($2%1000)*(365 + IsLeapYear(yyYear)))/1000;
  383. yyRelSeconds += $4 * 144 * 60;
  384. }
  385. ;
  386. relspec : relunits tAGO {
  387. yyRelSeconds *= -1;
  388. yyRelMonth *= -1;
  389. yyRelDay *= -1;
  390. }
  391. | relunits
  392. ;
  393. relunits : sign tUNUMBER unit {
  394. *yyRelPointer += $1 * $2 * $3;
  395. }
  396. | tUNUMBER unit {
  397. *yyRelPointer += $1 * $2;
  398. }
  399. | tNEXT unit {
  400. *yyRelPointer += $2;
  401. }
  402. | tNEXT tUNUMBER unit {
  403. *yyRelPointer += $2 * $3;
  404. }
  405. | unit {
  406. *yyRelPointer += $1;
  407. }
  408. ;
  409. sign : '-' {
  410. $$ = -1;
  411. }
  412. | '+' {
  413. $$ = 1;
  414. }
  415. ;
  416. unit : tSEC_UNIT {
  417. $$ = $1;
  418. yyRelPointer = &yyRelSeconds;
  419. }
  420. | tDAY_UNIT {
  421. $$ = $1;
  422. yyRelPointer = &yyRelDay;
  423. }
  424. | tMONTH_UNIT {
  425. $$ = $1;
  426. yyRelPointer = &yyRelMonth;
  427. }
  428. ;
  429. number : tUNUMBER {
  430. if (yyHaveTime && yyHaveDate && !yyHaveRel) {
  431. yyYear = $1;
  432. } else {
  433. yyHaveTime++;
  434. if (yyDigitCount <= 2) {
  435. yyHour = $1;
  436. yyMinutes = 0;
  437. } else {
  438. yyHour = $1 / 100;
  439. yyMinutes = $1 % 100;
  440. }
  441. yySeconds = 0;
  442. yyMeridian = MER24;
  443. }
  444. }
  445. ;
  446. o_merid : /* NULL */ {
  447. $$ = MER24;
  448. }
  449. | tMERIDIAN {
  450. $$ = $1;
  451. }
  452. ;
  453. %%
  454. MODULE_SCOPE int yychar;
  455. MODULE_SCOPE YYSTYPE yylval;
  456. MODULE_SCOPE int yynerrs;
  457. /*
  458. * Month and day table.
  459. */
  460. static TABLE MonthDayTable[] = {
  461. { "january", tMONTH, 1 },
  462. { "february", tMONTH, 2 },
  463. { "march", tMONTH, 3 },
  464. { "april", tMONTH, 4 },
  465. { "may", tMONTH, 5 },
  466. { "june", tMONTH, 6 },
  467. { "july", tMONTH, 7 },
  468. { "august", tMONTH, 8 },
  469. { "september", tMONTH, 9 },
  470. { "sept", tMONTH, 9 },
  471. { "october", tMONTH, 10 },
  472. { "november", tMONTH, 11 },
  473. { "december", tMONTH, 12 },
  474. { "sunday", tDAY, 0 },
  475. { "monday", tDAY, 1 },
  476. { "tuesday", tDAY, 2 },
  477. { "tues", tDAY, 2 },
  478. { "wednesday", tDAY, 3 },
  479. { "wednes", tDAY, 3 },
  480. { "thursday", tDAY, 4 },
  481. { "thur", tDAY, 4 },
  482. { "thurs", tDAY, 4 },
  483. { "friday", tDAY, 5 },
  484. { "saturday", tDAY, 6 },
  485. { NULL }
  486. };
  487. /*
  488. * Time units table.
  489. */
  490. static TABLE UnitsTable[] = {
  491. { "year", tMONTH_UNIT, 12 },
  492. { "month", tMONTH_UNIT, 1 },
  493. { "fortnight", tDAY_UNIT, 14 },
  494. { "week", tDAY_UNIT, 7 },
  495. { "day", tDAY_UNIT, 1 },
  496. { "hour", tSEC_UNIT, 60 * 60 },
  497. { "minute", tSEC_UNIT, 60 },
  498. { "min", tSEC_UNIT, 60 },
  499. { "second", tSEC_UNIT, 1 },
  500. { "sec", tSEC_UNIT, 1 },
  501. { NULL }
  502. };
  503. /*
  504. * Assorted relative-time words.
  505. */
  506. static TABLE OtherTable[] = {
  507. { "tomorrow", tDAY_UNIT, 1 },
  508. { "yesterday", tDAY_UNIT, -1 },
  509. { "today", tDAY_UNIT, 0 },
  510. { "now", tSEC_UNIT, 0 },
  511. { "last", tUNUMBER, -1 },
  512. { "this", tSEC_UNIT, 0 },
  513. { "next", tNEXT, 1 },
  514. #if 0
  515. { "first", tUNUMBER, 1 },
  516. { "second", tUNUMBER, 2 },
  517. { "third", tUNUMBER, 3 },
  518. { "fourth", tUNUMBER, 4 },
  519. { "fifth", tUNUMBER, 5 },
  520. { "sixth", tUNUMBER, 6 },
  521. { "seventh", tUNUMBER, 7 },
  522. { "eighth", tUNUMBER, 8 },
  523. { "ninth", tUNUMBER, 9 },
  524. { "tenth", tUNUMBER, 10 },
  525. { "eleventh", tUNUMBER, 11 },
  526. { "twelfth", tUNUMBER, 12 },
  527. #endif
  528. { "ago", tAGO, 1 },
  529. { "epoch", tEPOCH, 0 },
  530. { "stardate", tSTARDATE, 0 },
  531. { NULL }
  532. };
  533. /*
  534. * The timezone table. (Note: This table was modified to not use any floating
  535. * point constants to work around an SGI compiler bug).
  536. */
  537. static TABLE TimezoneTable[] = {
  538. { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
  539. { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
  540. { "utc", tZONE, HOUR( 0) },
  541. { "uct", tZONE, HOUR( 0) }, /* Universal Coordinated Time */
  542. { "wet", tZONE, HOUR( 0) }, /* Western European */
  543. { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
  544. { "wat", tZONE, HOUR( 1) }, /* West Africa */
  545. { "at", tZONE, HOUR( 2) }, /* Azores */
  546. #if 0
  547. /* For completeness. BST is also British Summer, and GST is
  548. * also Guam Standard. */
  549. { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
  550. { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
  551. #endif
  552. { "nft", tZONE, HOUR( 7/2) }, /* Newfoundland */
  553. { "nst", tZONE, HOUR( 7/2) }, /* Newfoundland Standard */
  554. { "ndt", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */
  555. { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
  556. { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
  557. { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
  558. { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
  559. { "cst", tZONE, HOUR( 6) }, /* Central Standard */
  560. { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
  561. { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
  562. { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
  563. { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
  564. { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
  565. { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
  566. { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
  567. { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
  568. { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
  569. { "cat", tZONE, HOUR(10) }, /* Central Alaska */
  570. { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
  571. { "nt", tZONE, HOUR(11) }, /* Nome */
  572. { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
  573. { "cet", tZONE, -HOUR( 1) }, /* Central European */
  574. { "cest", tDAYZONE, -HOUR( 1) }, /* Central European Summer */
  575. { "met", tZONE, -HOUR( 1) }, /* Middle European */
  576. { "mewt", tZONE, -HOUR( 1) }, /* Middle European Winter */
  577. { "mest", tDAYZONE, -HOUR( 1) }, /* Middle European Summer */
  578. { "swt", tZONE, -HOUR( 1) }, /* Swedish Winter */
  579. { "sst", tDAYZONE, -HOUR( 1) }, /* Swedish Summer */
  580. { "fwt", tZONE, -HOUR( 1) }, /* French Winter */
  581. { "fst", tDAYZONE, -HOUR( 1) }, /* French Summer */
  582. { "eet", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */
  583. { "bt", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */
  584. { "it", tZONE, -HOUR( 7/2) }, /* Iran */
  585. { "zp4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */
  586. { "zp5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */
  587. { "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */
  588. { "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */
  589. #if 0
  590. /* For completeness. NST is also Newfoundland Stanard, nad SST is
  591. * also Swedish Summer. */
  592. { "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */
  593. { "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */
  594. #endif /* 0 */
  595. { "wast", tZONE, -HOUR( 7) }, /* West Australian Standard */
  596. { "wadt", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */
  597. { "jt", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */
  598. { "cct", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */
  599. { "jst", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */
  600. { "jdt", tDAYZONE, -HOUR( 9) }, /* Japan Daylight */
  601. { "kst", tZONE, -HOUR( 9) }, /* Korea Standard */
  602. { "kdt", tDAYZONE, -HOUR( 9) }, /* Korea Daylight */
  603. { "cast", tZONE, -HOUR(19/2) }, /* Central Australian Standard */
  604. { "cadt", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */
  605. { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
  606. { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
  607. { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
  608. { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
  609. { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
  610. { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
  611. { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
  612. /* ADDED BY Marco Nijdam */
  613. { "dst", tDST, HOUR( 0) }, /* DST on (hour is ignored) */
  614. /* End ADDED */
  615. { NULL }
  616. };
  617. /*
  618. * Military timezone table.
  619. */
  620. static TABLE MilitaryTable[] = {
  621. { "a", tZONE, -HOUR( 1) },
  622. { "b", tZONE, -HOUR( 2) },
  623. { "c", tZONE, -HOUR( 3) },
  624. { "d", tZONE, -HOUR( 4) },
  625. { "e", tZONE, -HOUR( 5) },
  626. { "f", tZONE, -HOUR( 6) },
  627. { "g", tZONE, -HOUR( 7) },
  628. { "h", tZONE, -HOUR( 8) },
  629. { "i", tZONE, -HOUR( 9) },
  630. { "k", tZONE, -HOUR(10) },
  631. { "l", tZONE, -HOUR(11) },
  632. { "m", tZONE, -HOUR(12) },
  633. { "n", tZONE, HOUR( 1) },
  634. { "o", tZONE, HOUR( 2) },
  635. { "p", tZONE, HOUR( 3) },
  636. { "q", tZONE, HOUR( 4) },
  637. { "r", tZONE, HOUR( 5) },
  638. { "s", tZONE, HOUR( 6) },
  639. { "t", tZONE, HOUR( 7) },
  640. { "u", tZONE, HOUR( 8) },
  641. { "v", tZONE, HOUR( 9) },
  642. { "w", tZONE, HOUR( 10) },
  643. { "x", tZONE, HOUR( 11) },
  644. { "y", tZONE, HOUR( 12) },
  645. { "z", tZONE, HOUR( 0) },
  646. { NULL }
  647. };
  648. /*
  649. * Dump error messages in the bit bucket.
  650. */
  651. static void
  652. TclDateerror(
  653. YYLTYPE* location,
  654. DateInfo* infoPtr,
  655. const char *s)
  656. {
  657. Tcl_Obj* t;
  658. Tcl_AppendToObj(infoPtr->messages, infoPtr->separatrix, -1);
  659. Tcl_AppendToObj(infoPtr->messages, s, -1);
  660. Tcl_AppendToObj(infoPtr->messages, " (characters ", -1);
  661. t = Tcl_NewIntObj(location->first_column);
  662. Tcl_IncrRefCount(t);
  663. Tcl_AppendObjToObj(infoPtr->messages, t);
  664. Tcl_DecrRefCount(t);
  665. Tcl_AppendToObj(infoPtr->messages, "-", -1);
  666. t = Tcl_NewIntObj(location->last_column);
  667. Tcl_IncrRefCount(t);
  668. Tcl_AppendObjToObj(infoPtr->messages, t);
  669. Tcl_DecrRefCount(t);
  670. Tcl_AppendToObj(infoPtr->messages, ")", -1);
  671. infoPtr->separatrix = "\n";
  672. }
  673. static time_t
  674. ToSeconds(
  675. time_t Hours,
  676. time_t Minutes,
  677. time_t Seconds,
  678. MERIDIAN Meridian)
  679. {
  680. if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) {
  681. return -1;
  682. }
  683. switch (Meridian) {
  684. case MER24:
  685. if (Hours < 0 || Hours > 23) {
  686. return -1;
  687. }
  688. return (Hours * 60L + Minutes) * 60L + Seconds;
  689. case MERam:
  690. if (Hours < 1 || Hours > 12) {
  691. return -1;
  692. }
  693. return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
  694. case MERpm:
  695. if (Hours < 1 || Hours > 12) {
  696. return -1;
  697. }
  698. return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
  699. }
  700. return -1; /* Should never be reached */
  701. }
  702. static int
  703. LookupWord(
  704. YYSTYPE* yylvalPtr,
  705. char *buff)
  706. {
  707. register char *p;
  708. register char *q;
  709. register TABLE *tp;
  710. int i, abbrev;
  711. /*
  712. * Make it lowercase.
  713. */
  714. Tcl_UtfToLower(buff);
  715. if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
  716. yylvalPtr->Meridian = MERam;
  717. return tMERIDIAN;
  718. }
  719. if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
  720. yylvalPtr->Meridian = MERpm;
  721. return tMERIDIAN;
  722. }
  723. /*
  724. * See if we have an abbreviation for a month.
  725. */
  726. if (strlen(buff) == 3) {
  727. abbrev = 1;
  728. } else if (strlen(buff) == 4 && buff[3] == '.') {
  729. abbrev = 1;
  730. buff[3] = '\0';
  731. } else {
  732. abbrev = 0;
  733. }
  734. for (tp = MonthDayTable; tp->name; tp++) {
  735. if (abbrev) {
  736. if (strncmp(buff, tp->name, 3) == 0) {
  737. yylvalPtr->Number = tp->value;
  738. return tp->type;
  739. }
  740. } else if (strcmp(buff, tp->name) == 0) {
  741. yylvalPtr->Number = tp->value;
  742. return tp->type;
  743. }
  744. }
  745. for (tp = TimezoneTable; tp->name; tp++) {
  746. if (strcmp(buff, tp->name) == 0) {
  747. yylvalPtr->Number = tp->value;
  748. return tp->type;
  749. }
  750. }
  751. for (tp = UnitsTable; tp->name; tp++) {
  752. if (strcmp(buff, tp->name) == 0) {
  753. yylvalPtr->Number = tp->value;
  754. return tp->type;
  755. }
  756. }
  757. /*
  758. * Strip off any plural and try the units table again.
  759. */
  760. i = strlen(buff) - 1;
  761. if (i > 0 && buff[i] == 's') {
  762. buff[i] = '\0';
  763. for (tp = UnitsTable; tp->name; tp++) {
  764. if (strcmp(buff, tp->name) == 0) {
  765. yylvalPtr->Number = tp->value;
  766. return tp->type;
  767. }
  768. }
  769. }
  770. for (tp = OtherTable; tp->name; tp++) {
  771. if (strcmp(buff, tp->name) == 0) {
  772. yylvalPtr->Number = tp->value;
  773. return tp->type;
  774. }
  775. }
  776. /*
  777. * Military timezones.
  778. */
  779. if (buff[1] == '\0' && !(*buff & 0x80)
  780. && isalpha(UCHAR(*buff))) { /* INTL: ISO only */
  781. for (tp = MilitaryTable; tp->name; tp++) {
  782. if (strcmp(buff, tp->name) == 0) {
  783. yylvalPtr->Number = tp->value;
  784. return tp->type;
  785. }
  786. }
  787. }
  788. /*
  789. * Drop out any periods and try the timezone table again.
  790. */
  791. for (i = 0, p = q = buff; *q; q++) {
  792. if (*q != '.') {
  793. *p++ = *q;
  794. } else {
  795. i++;
  796. }
  797. }
  798. *p = '\0';
  799. if (i) {
  800. for (tp = TimezoneTable; tp->name; tp++) {
  801. if (strcmp(buff, tp->name) == 0) {
  802. yylvalPtr->Number = tp->value;
  803. return tp->type;
  804. }
  805. }
  806. }
  807. return tID;
  808. }
  809. static int
  810. TclDatelex(
  811. YYSTYPE* yylvalPtr,
  812. YYLTYPE* location,
  813. DateInfo *info)
  814. {
  815. register char c;
  816. register char *p;
  817. char buff[20];
  818. int Count;
  819. location->first_column = yyInput - info->dateStart;
  820. for ( ; ; ) {
  821. while (isspace(UCHAR(*yyInput))) {
  822. yyInput++;
  823. }
  824. if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */
  825. /*
  826. * Convert the string into a number; count the number of digits.
  827. */
  828. Count = 0;
  829. for (yylvalPtr->Number = 0;
  830. isdigit(UCHAR(c = *yyInput++)); ) { /* INTL: digit */
  831. yylvalPtr->Number = 10 * yylvalPtr->Number + c - '0';
  832. Count++;
  833. }
  834. yyInput--;
  835. yyDigitCount = Count;
  836. /*
  837. * A number with 6 or more digits is considered an ISO 8601 base.
  838. */
  839. if (Count >= 6) {
  840. location->last_column = yyInput - info->dateStart - 1;
  841. return tISOBASE;
  842. } else {
  843. location->last_column = yyInput - info->dateStart - 1;
  844. return tUNUMBER;
  845. }
  846. }
  847. if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */
  848. for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */
  849. || c == '.'; ) {
  850. if (p < &buff[sizeof buff - 1]) {
  851. *p++ = c;
  852. }
  853. }
  854. *p = '\0';
  855. yyInput--;
  856. location->last_column = yyInput - info->dateStart - 1;
  857. return LookupWord(yylvalPtr, buff);
  858. }
  859. if (c != '(') {
  860. location->last_column = yyInput - info->dateStart;
  861. return *yyInput++;
  862. }
  863. Count = 0;
  864. do {
  865. c = *yyInput++;
  866. if (c == '\0') {
  867. location->last_column = yyInput - info->dateStart - 1;
  868. return c;
  869. } else if (c == '(') {
  870. Count++;
  871. } else if (c == ')') {
  872. Count--;
  873. }
  874. } while (Count > 0);
  875. }
  876. }
  877. int
  878. TclClockOldscanObjCmd(
  879. ClientData clientData, /* Unused */
  880. Tcl_Interp *interp, /* Tcl interpreter */
  881. int objc, /* Count of paraneters */
  882. Tcl_Obj *CONST *objv) /* Parameters */
  883. {
  884. Tcl_Obj *result, *resultElement;
  885. int yr, mo, da;
  886. DateInfo dateInfo;
  887. DateInfo* info = &dateInfo;
  888. int status;
  889. if (objc != 5) {
  890. Tcl_WrongNumArgs(interp, 1, objv,
  891. "stringToParse baseYear baseMonth baseDay" );
  892. return TCL_ERROR;
  893. }
  894. yyInput = Tcl_GetString( objv[1] );
  895. dateInfo.dateStart = yyInput;
  896. yyHaveDate = 0;
  897. if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
  898. || Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
  899. || Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
  900. return TCL_ERROR;
  901. }
  902. yyYear = yr; yyMonth = mo; yyDay = da;
  903. yyHaveTime = 0;
  904. yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24;
  905. yyHaveZone = 0;
  906. yyTimezone = 0; yyDSTmode = DSTmaybe;
  907. yyHaveOrdinalMonth = 0;
  908. yyMonthOrdinal = 0;
  909. yyHaveDay = 0;
  910. yyDayOrdinal = 0; yyDayNumber = 0;
  911. yyHaveRel = 0;
  912. yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;
  913. dateInfo.messages = Tcl_NewObj();
  914. dateInfo.separatrix = "";
  915. Tcl_IncrRefCount(dateInfo.messages);
  916. status = yyparse(&dateInfo);
  917. if (status == 1) {
  918. Tcl_SetObjResult(interp, dateInfo.messages);
  919. Tcl_DecrRefCount(dateInfo.messages);
  920. return TCL_ERROR;
  921. } else if (status == 2) {
  922. Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
  923. Tcl_DecrRefCount(dateInfo.messages);
  924. return TCL_ERROR;
  925. } else if (status != 0) {
  926. Tcl_SetObjResult(interp, Tcl_NewStringObj("Unknown status returned "
  927. "from date parser. Please "
  928. "report this error as a "
  929. "bug in Tcl.", -1));
  930. Tcl_DecrRefCount(dateInfo.messages);
  931. return TCL_ERROR;
  932. }
  933. Tcl_DecrRefCount(dateInfo.messages);
  934. if (yyHaveDate > 1) {
  935. Tcl_SetObjResult(interp,
  936. Tcl_NewStringObj("more than one date in string", -1));
  937. return TCL_ERROR;
  938. }
  939. if (yyHaveTime > 1) {
  940. Tcl_SetObjResult(interp,
  941. Tcl_NewStringObj("more than one time of day in string", -1));
  942. return TCL_ERROR;
  943. }
  944. if (yyHaveZone > 1) {
  945. Tcl_SetObjResult(interp,
  946. Tcl_NewStringObj("more than one time zone in string", -1));
  947. return TCL_ERROR;
  948. }
  949. if (yyHaveDay > 1) {
  950. Tcl_SetObjResult(interp,
  951. Tcl_NewStringObj("more than one weekday in string", -1));
  952. return TCL_ERROR;
  953. }
  954. if (yyHaveOrdinalMonth > 1) {
  955. Tcl_SetObjResult(interp,
  956. Tcl_NewStringObj("more than one ordinal month in string", -1));
  957. return TCL_ERROR;
  958. }
  959. result = Tcl_NewObj();
  960. resultElement = Tcl_NewObj();
  961. if (yyHaveDate) {
  962. Tcl_ListObjAppendElement(interp, resultElement,
  963. Tcl_NewIntObj((int) yyYear));
  964. Tcl_ListObjAppendElement(interp, resultElement,
  965. Tcl_NewIntObj((int) yyMonth));
  966. Tcl_ListObjAppendElement(interp, resultElement,
  967. Tcl_NewIntObj((int) yyDay));
  968. }
  969. Tcl_ListObjAppendElement(interp, result, resultElement);
  970. if (yyHaveTime) {
  971. Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj((int)
  972. ToSeconds(yyHour, yyMinutes, yySeconds, yyMeridian)));
  973. } else {
  974. Tcl_ListObjAppendElement(interp, result, Tcl_NewObj());
  975. }
  976. resultElement = Tcl_NewObj();
  977. if (yyHaveZone) {
  978. Tcl_ListObjAppendElement(interp, resultElement,
  979. Tcl_NewIntObj((int) -yyTimezone));
  980. Tcl_ListObjAppendElement(interp, resultElement,
  981. Tcl_NewIntObj(1 - yyDSTmode));
  982. }
  983. Tcl_ListObjAppendElement(interp, result, resultElement);
  984. resultElement = Tcl_NewObj();
  985. if (yyHaveRel) {
  986. Tcl_ListObjAppendElement(interp, resultElement,
  987. Tcl_NewIntObj((int) yyRelMonth));
  988. Tcl_ListObjAppendElement(interp, resultElement,
  989. Tcl_NewIntObj((int) yyRelDay));
  990. Tcl_ListObjAppendElement(interp, resultElement,
  991. Tcl_NewIntObj((int) yyRelSeconds));
  992. }
  993. Tcl_ListObjAppendElement(interp, result, resultElement);
  994. resultElement = Tcl_NewObj();
  995. if (yyHaveDay && !yyHaveDate) {
  996. Tcl_ListObjAppendElement(interp, resultElement,
  997. Tcl_NewIntObj((int) yyDayOrdinal));
  998. Tcl_ListObjAppendElement(interp, resultElement,
  999. Tcl_NewIntObj((int) yyDayNumber));
  1000. }
  1001. Tcl_ListObjAppendElement(interp, result, resultElement);
  1002. resultElement = Tcl_NewObj();
  1003. if (yyHaveOrdinalMonth) {
  1004. Tcl_ListObjAppendElement(interp, resultElement,
  1005. Tcl_NewIntObj((int) yyMonthOrdinal));
  1006. Tcl_ListObjAppendElement(interp, resultElement,
  1007. Tcl_NewIntObj((int) yyMonth));
  1008. }
  1009. Tcl_ListObjAppendElement(interp, result, resultElement);
  1010. Tcl_SetObjResult(interp, result);
  1011. return TCL_OK;
  1012. }
  1013. /*
  1014. * Local Variables:
  1015. * mode: c
  1016. * c-basic-offset: 4
  1017. * fill-column: 78
  1018. * End:
  1019. */