Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/tcl8.5.2/generic/tclGetDate.y @ 63

Last change on this file since 63 was 25, checked in by landauf, 16 years ago

added tcl to libs

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