3 ** Originally written by Steven M. Bellovin <smb@research.att.com> while
4 ** at the University of North Carolina at Chapel Hill. Later tweaked by
5 ** a couple of people on Usenet. Completely overhauled by Rich $alz
6 ** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
7 ** send any email to Rich.
9 ** This grammar has 10 shift/reduce conflicts.
11 ** This code is in the public domain and has no copyright.
13 /* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
14 /* SUPPRESS 288 on yyerrlab *//* Label unused */
24 /* Since the code of getdate.y is not included in the Emacs executable
25 itself, there is no need to #define static in this file. Even if
26 the code were included in the Emacs executable, it probably
27 wouldn't do any harm to #undef it here; this will only cause
28 problems if we try to write to a static variable, which I don't
29 think this code needs to do. */
37 #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
38 # define IN_CTYPE_DOMAIN(c) 1
40 # define IN_CTYPE_DOMAIN(c) isascii(c)
43 #define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
44 #define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
45 #define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c))
46 #define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
48 /* ISDIGIT differs from ISDIGIT_LOCALE, as follows:
49 - Its arg may be any int or unsigned int; it need not be an unsigned char.
50 - It's guaranteed to evaluate its argument exactly once.
51 - It's typically faster.
52 Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
53 only '0' through '9' are digits. Prefer ISDIGIT to ISDIGIT_LOCALE unless
54 it's important to use the locale's definition of `digit' even when the
55 host does not conform to Posix. */
56 #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
62 #include <sys/types.h>
63 #ifdef TIME_WITH_SYS_TIME
67 #ifdef HAVE_SYS_TIME_H
73 #endif /* defined (vms) */
75 #if defined (STDC_HEADERS) || defined (USG)
79 /* Some old versions of bison generate parsers that use bcopy.
80 That loses on systems that don't provide the function, so we have
81 to redefine it here. */
82 #if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
83 #define bcopy(from, to, len) memcpy ((to), (from), (len))
86 extern struct tm *gmtime ();
87 extern struct tm *localtime ();
88 extern time_t mktime ();
90 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
91 as well as gratuitiously global symbol names, so we can have multiple
92 yacc generated parsers in the same program. Note that these are only
93 the variables produced by yacc. If other parser generators (bison,
94 byacc, etc) produce additional global names that conflict at link time,
95 then those parser generators need to be fixed instead of adding those
96 names to this list. */
98 #define yymaxdepth gd_maxdepth
99 #define yyparse gd_parse
101 #define yyerror gd_error
102 #define yylval gd_lval
103 #define yychar gd_char
104 #define yydebug gd_debug
105 #define yypact gd_pact
112 #define yyexca gd_exca
113 #define yyerrflag gd_errflag
114 #define yynerrs gd_nerrs
118 #define yy_yys gd_yys
119 #define yystate gd_state
122 #define yy_yyv gd_yyv
124 #define yylloc gd_lloc
125 #define yyreds gd_reds /* With YYDEBUG defined */
126 #define yytoks gd_toks /* With YYDEBUG defined */
127 #define yylhs gd_yylhs
128 #define yylen gd_yylen
129 #define yydefred gd_yydefred
130 #define yydgoto gd_yydgoto
131 #define yysindex gd_yysindex
132 #define yyrindex gd_yyrindex
133 #define yygindex gd_yygindex
134 #define yytable gd_yytable
135 #define yycheck gd_yycheck
138 static int yyerror ();
141 #define HOUR(x) ((x) * 60)
143 #define MAX_BUFF_LEN 128 /* size of buffer to read the date into */
146 ** An entry in the lexical lookup table.
148 typedef struct _TABLE {
156 ** Meridian: am, pm, or 24-hour style.
158 typedef enum _MERIDIAN {
164 ** Global variables. We could get rid of most of these by using a good
165 ** union as the yacc stack. (This routine was originally written before
166 ** yacc had the %union construct.) Maybe someday; right now we only use
167 ** the %union very rarely.
169 static char *yyInput;
170 static int yyDayOrdinal;
171 static int yyDayNumber;
172 static int yyHaveDate;
173 static int yyHaveDay;
174 static int yyHaveRel;
175 static int yyHaveTime;
176 static int yyHaveZone;
177 static int yyTimezone;
180 static int yyMinutes;
182 static int yySeconds;
184 static MERIDIAN yyMeridian;
186 static int yyRelHour;
187 static int yyRelMinutes;
188 static int yyRelMonth;
189 static int yyRelSeconds;
190 static int yyRelYear;
196 enum _MERIDIAN Meridian;
199 %token tAGO tDAY tDAY_UNIT tDAYZONE tDST tHOUR_UNIT tID
200 %token tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
201 %token tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE
203 %type <Number> tDAY tDAY_UNIT tDAYZONE tHOUR_UNIT tMINUTE_UNIT
204 %type <Number> tMONTH tMONTH_UNIT
205 %type <Number> tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE
206 %type <Meridian> tMERIDIAN o_merid
232 time : tUNUMBER tMERIDIAN {
238 | tUNUMBER ':' tUNUMBER o_merid {
244 | tUNUMBER ':' tUNUMBER tSNUMBER {
250 ? -$4 % 100 + (-$4 / 100) * 60
251 : - ($4 % 100 + ($4 / 100) * 60));
253 | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
259 | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
266 ? -$6 % 100 + (-$6 / 100) * 60
267 : - ($6 % 100 + ($6 / 100) * 60));
275 yyTimezone = $1 - 60;
279 yyTimezone = $1 - 60;
297 date : tUNUMBER '/' tUNUMBER {
301 | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
302 /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY.
303 The goal in recognizing YYYY/MM/DD is solely to support legacy
304 machine-generated dates like those in an RCS log listing. If
305 you want portability, use the ISO 8601 format. */
319 | tUNUMBER tSNUMBER tSNUMBER {
320 /* ISO 8601 format. yyyy-mm-dd. */
325 | tUNUMBER tMONTH tSNUMBER {
326 /* e.g. 17-JUN-1992. */
335 | tMONTH tUNUMBER ',' tUNUMBER {
344 | tUNUMBER tMONTH tUNUMBER {
352 yyRelSeconds = -yyRelSeconds;
353 yyRelMinutes = -yyRelMinutes;
354 yyRelHour = -yyRelHour;
355 yyRelDay = -yyRelDay;
356 yyRelMonth = -yyRelMonth;
357 yyRelYear = -yyRelYear;
362 relunit : tUNUMBER tYEAR_UNIT {
363 yyRelYear += $1 * $2;
365 | tSNUMBER tYEAR_UNIT {
366 yyRelYear += $1 * $2;
371 | tUNUMBER tMONTH_UNIT {
372 yyRelMonth += $1 * $2;
374 | tSNUMBER tMONTH_UNIT {
375 yyRelMonth += $1 * $2;
380 | tUNUMBER tDAY_UNIT {
383 | tSNUMBER tDAY_UNIT {
389 | tUNUMBER tHOUR_UNIT {
390 yyRelHour += $1 * $2;
392 | tSNUMBER tHOUR_UNIT {
393 yyRelHour += $1 * $2;
398 | tUNUMBER tMINUTE_UNIT {
399 yyRelMinutes += $1 * $2;
401 | tSNUMBER tMINUTE_UNIT {
402 yyRelMinutes += $1 * $2;
407 | tUNUMBER tSEC_UNIT {
408 yyRelSeconds += $1 * $2;
410 | tSNUMBER tSEC_UNIT {
411 yyRelSeconds += $1 * $2;
419 if (yyHaveTime && yyHaveDate && !yyHaveRel)
425 yyMonth= ($1/100)%100;
436 yyMinutes = $1 % 100;
445 o_merid : /* NULL */ {
455 /* Month and day table. */
456 static TABLE const MonthDayTable[] = {
457 { "january", tMONTH, 1 },
458 { "february", tMONTH, 2 },
459 { "march", tMONTH, 3 },
460 { "april", tMONTH, 4 },
461 { "may", tMONTH, 5 },
462 { "june", tMONTH, 6 },
463 { "july", tMONTH, 7 },
464 { "august", tMONTH, 8 },
465 { "september", tMONTH, 9 },
466 { "sept", tMONTH, 9 },
467 { "october", tMONTH, 10 },
468 { "november", tMONTH, 11 },
469 { "december", tMONTH, 12 },
470 { "sunday", tDAY, 0 },
471 { "monday", tDAY, 1 },
472 { "tuesday", tDAY, 2 },
474 { "wednesday", tDAY, 3 },
475 { "wednes", tDAY, 3 },
476 { "thursday", tDAY, 4 },
478 { "thurs", tDAY, 4 },
479 { "friday", tDAY, 5 },
480 { "saturday", tDAY, 6 },
484 /* Time units table. */
485 static TABLE const UnitsTable[] = {
486 { "year", tYEAR_UNIT, 1 },
487 { "month", tMONTH_UNIT, 1 },
488 { "fortnight", tDAY_UNIT, 14 },
489 { "week", tDAY_UNIT, 7 },
490 { "day", tDAY_UNIT, 1 },
491 { "hour", tHOUR_UNIT, 1 },
492 { "minute", tMINUTE_UNIT, 1 },
493 { "min", tMINUTE_UNIT, 1 },
494 { "second", tSEC_UNIT, 1 },
495 { "sec", tSEC_UNIT, 1 },
499 /* Assorted relative-time words. */
500 static TABLE const OtherTable[] = {
501 { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
502 { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
503 { "today", tMINUTE_UNIT, 0 },
504 { "now", tMINUTE_UNIT, 0 },
505 { "last", tUNUMBER, -1 },
506 { "this", tMINUTE_UNIT, 0 },
507 { "next", tUNUMBER, 2 },
508 { "first", tUNUMBER, 1 },
509 /* { "second", tUNUMBER, 2 }, */
510 { "third", tUNUMBER, 3 },
511 { "fourth", tUNUMBER, 4 },
512 { "fifth", tUNUMBER, 5 },
513 { "sixth", tUNUMBER, 6 },
514 { "seventh", tUNUMBER, 7 },
515 { "eighth", tUNUMBER, 8 },
516 { "ninth", tUNUMBER, 9 },
517 { "tenth", tUNUMBER, 10 },
518 { "eleventh", tUNUMBER, 11 },
519 { "twelfth", tUNUMBER, 12 },
524 /* The timezone table. */
525 static TABLE const TimezoneTable[] = {
526 { "gmt", tZONE, HOUR ( 0) }, /* Greenwich Mean */
527 { "ut", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */
528 { "utc", tZONE, HOUR ( 0) },
529 { "wet", tZONE, HOUR ( 0) }, /* Western European */
530 { "bst", tDAYZONE, HOUR ( 0) }, /* British Summer */
531 { "wat", tZONE, HOUR ( 1) }, /* West Africa */
532 { "at", tZONE, HOUR ( 2) }, /* Azores */
534 /* For completeness. BST is also British Summer, and GST is
535 * also Guam Standard. */
536 { "bst", tZONE, HOUR ( 3) }, /* Brazil Standard */
537 { "gst", tZONE, HOUR ( 3) }, /* Greenland Standard */
540 { "nft", tZONE, HOUR (3.5) }, /* Newfoundland */
541 { "nst", tZONE, HOUR (3.5) }, /* Newfoundland Standard */
542 { "ndt", tDAYZONE, HOUR (3.5) }, /* Newfoundland Daylight */
544 { "ast", tZONE, HOUR ( 4) }, /* Atlantic Standard */
545 { "adt", tDAYZONE, HOUR ( 4) }, /* Atlantic Daylight */
546 { "est", tZONE, HOUR ( 5) }, /* Eastern Standard */
547 { "edt", tDAYZONE, HOUR ( 5) }, /* Eastern Daylight */
548 { "cst", tZONE, HOUR ( 6) }, /* Central Standard */
549 { "cdt", tDAYZONE, HOUR ( 6) }, /* Central Daylight */
550 { "mst", tZONE, HOUR ( 7) }, /* Mountain Standard */
551 { "mdt", tDAYZONE, HOUR ( 7) }, /* Mountain Daylight */
552 { "pst", tZONE, HOUR ( 8) }, /* Pacific Standard */
553 { "pdt", tDAYZONE, HOUR ( 8) }, /* Pacific Daylight */
554 { "yst", tZONE, HOUR ( 9) }, /* Yukon Standard */
555 { "ydt", tDAYZONE, HOUR ( 9) }, /* Yukon Daylight */
556 { "hst", tZONE, HOUR (10) }, /* Hawaii Standard */
557 { "hdt", tDAYZONE, HOUR (10) }, /* Hawaii Daylight */
558 { "cat", tZONE, HOUR (10) }, /* Central Alaska */
559 { "ahst", tZONE, HOUR (10) }, /* Alaska-Hawaii Standard */
560 { "nt", tZONE, HOUR (11) }, /* Nome */
561 { "idlw", tZONE, HOUR (12) }, /* International Date Line West */
562 { "cet", tZONE, -HOUR (1) }, /* Central European */
563 { "met", tZONE, -HOUR (1) }, /* Middle European */
564 { "mewt", tZONE, -HOUR (1) }, /* Middle European Winter */
565 { "mest", tDAYZONE, -HOUR (1) }, /* Middle European Summer */
566 { "mesz", tDAYZONE, -HOUR (1) }, /* Middle European Summer */
567 { "swt", tZONE, -HOUR (1) }, /* Swedish Winter */
568 { "sst", tDAYZONE, -HOUR (1) }, /* Swedish Summer */
569 { "fwt", tZONE, -HOUR (1) }, /* French Winter */
570 { "fst", tDAYZONE, -HOUR (1) }, /* French Summer */
571 { "eet", tZONE, -HOUR (2) }, /* Eastern Europe, USSR Zone 1 */
572 { "bt", tZONE, -HOUR (3) }, /* Baghdad, USSR Zone 2 */
574 { "it", tZONE, -HOUR (3.5) },/* Iran */
576 { "zp4", tZONE, -HOUR (4) }, /* USSR Zone 3 */
577 { "zp5", tZONE, -HOUR (5) }, /* USSR Zone 4 */
579 { "ist", tZONE, -HOUR (5.5) },/* Indian Standard */
581 { "zp6", tZONE, -HOUR (6) }, /* USSR Zone 5 */
583 /* For completeness. NST is also Newfoundland Standard, and SST is
584 * also Swedish Summer. */
585 { "nst", tZONE, -HOUR (6.5) },/* North Sumatra */
586 { "sst", tZONE, -HOUR (7) }, /* South Sumatra, USSR Zone 6 */
588 { "wast", tZONE, -HOUR (7) }, /* West Australian Standard */
589 { "wadt", tDAYZONE, -HOUR (7) }, /* West Australian Daylight */
591 { "jt", tZONE, -HOUR (7.5) },/* Java (3pm in Cronusland!) */
593 { "cct", tZONE, -HOUR (8) }, /* China Coast, USSR Zone 7 */
594 { "jst", tZONE, -HOUR (9) }, /* Japan Standard, USSR Zone 8 */
596 { "cast", tZONE, -HOUR (9.5) },/* Central Australian Standard */
597 { "cadt", tDAYZONE, -HOUR (9.5) },/* Central Australian Daylight */
599 { "east", tZONE, -HOUR (10) }, /* Eastern Australian Standard */
600 { "eadt", tDAYZONE, -HOUR (10) }, /* Eastern Australian Daylight */
601 { "gst", tZONE, -HOUR (10) }, /* Guam Standard, USSR Zone 9 */
602 { "nzt", tZONE, -HOUR (12) }, /* New Zealand */
603 { "nzst", tZONE, -HOUR (12) }, /* New Zealand Standard */
604 { "nzdt", tDAYZONE, -HOUR (12) }, /* New Zealand Daylight */
605 { "idle", tZONE, -HOUR (12) }, /* International Date Line East */
609 /* Military timezone table. */
610 static TABLE const MilitaryTable[] = {
611 { "a", tZONE, HOUR ( 1) },
612 { "b", tZONE, HOUR ( 2) },
613 { "c", tZONE, HOUR ( 3) },
614 { "d", tZONE, HOUR ( 4) },
615 { "e", tZONE, HOUR ( 5) },
616 { "f", tZONE, HOUR ( 6) },
617 { "g", tZONE, HOUR ( 7) },
618 { "h", tZONE, HOUR ( 8) },
619 { "i", tZONE, HOUR ( 9) },
620 { "k", tZONE, HOUR ( 10) },
621 { "l", tZONE, HOUR ( 11) },
622 { "m", tZONE, HOUR ( 12) },
623 { "n", tZONE, HOUR (- 1) },
624 { "o", tZONE, HOUR (- 2) },
625 { "p", tZONE, HOUR (- 3) },
626 { "q", tZONE, HOUR (- 4) },
627 { "r", tZONE, HOUR (- 5) },
628 { "s", tZONE, HOUR (- 6) },
629 { "t", tZONE, HOUR (- 7) },
630 { "u", tZONE, HOUR (- 8) },
631 { "v", tZONE, HOUR (- 9) },
632 { "w", tZONE, HOUR (-10) },
633 { "x", tZONE, HOUR (-11) },
634 { "y", tZONE, HOUR (-12) },
635 { "z", tZONE, HOUR ( 0) },
652 ToHour (Hours, Meridian)
658 if (Hours < 0 || Hours > 23)
662 if (Hours < 1 || Hours > 12)
668 if (Hours < 1 || Hours > 12)
687 /* XPG4 suggests that years 00-68 map to 2000-2068, and
688 years 69-99 map to 1969-1999. */
704 register const TABLE *tp;
708 /* Make it lowercase. */
709 for (p = buff; *p; p++)
713 if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) {
714 yylval.Meridian = MERam;
717 if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0) {
718 yylval.Meridian = MERpm;
722 /* See if we have an abbreviation for a month. */
723 if (strlen (buff) == 3)
725 else if (strlen (buff) == 4 && buff[3] == '.') {
732 for (tp = MonthDayTable; tp->name; tp++) {
734 if (strncmp (buff, tp->name, 3) == 0) {
735 yylval.Number = tp->value;
739 else if (strcmp (buff, tp->name) == 0) {
740 yylval.Number = tp->value;
745 for (tp = TimezoneTable; tp->name; tp++)
746 if (strcmp (buff, tp->name) == 0) {
747 yylval.Number = tp->value;
751 if (strcmp (buff, "dst") == 0)
754 for (tp = UnitsTable; tp->name; tp++)
755 if (strcmp (buff, tp->name) == 0) {
756 yylval.Number = tp->value;
760 /* Strip off any plural and try the units table again. */
761 i = strlen (buff) - 1;
762 if (buff[i] == 's') {
764 for (tp = UnitsTable; tp->name; tp++)
765 if (strcmp (buff, tp->name) == 0) {
766 yylval.Number = tp->value;
769 buff[i] = 's'; /* Put back for "this" in OtherTable. */
772 for (tp = OtherTable; tp->name; tp++)
773 if (strcmp (buff, tp->name) == 0) {
774 yylval.Number = tp->value;
778 /* Military timezones. */
779 if (buff[1] == '\0' && ISALPHA (*buff)) {
780 for (tp = MilitaryTable; tp->name; tp++)
781 if (strcmp (buff, tp->name) == 0) {
782 yylval.Number = tp->value;
787 /* Drop out any periods and try the timezone table again. */
788 for (i = 0, p = q = buff; *q; q++)
795 for (tp = TimezoneTable; tp->name; tp++)
796 if (strcmp (buff, tp->name) == 0) {
797 yylval.Number = tp->value;
815 while (ISSPACE (*yyInput))
818 if (ISDIGIT (c = *yyInput) || c == '-' || c == '+') {
819 if (c == '-' || c == '+') {
820 sign = c == '-' ? -1 : 1;
821 if (!ISDIGIT (*++yyInput))
822 /* skip the '-' sign */
827 for (yylval.Number = 0; ISDIGIT (c = *yyInput++); )
828 yylval.Number = 10 * yylval.Number + c - '0';
831 yylval.Number = -yylval.Number;
832 return sign ? tSNUMBER : tUNUMBER;
835 for (p = buff; (c = *yyInput++, ISALPHA (c)) || c == '.'; )
836 if (p < &buff[sizeof buff - 1])
840 return LookupWord (buff);
857 #define TM_YEAR_ORIGIN 1900
859 /* Yield A - B, measured in seconds. */
864 int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
865 int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
867 /* difference in day of year */
868 a->tm_yday - b->tm_yday
869 /* + intervening leap days */
870 + ((ay >> 2) - (by >> 2))
872 + ((ay/100 >> 2) - (by/100 >> 2))
873 /* + difference in years * 365 */
874 + (long)(ay-by) * 365
876 return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
877 + (a->tm_min - b->tm_min))
878 + (a->tm_sec - b->tm_sec));
886 struct tm tm, tm0, *tmp;
890 Start = now ? *now : time ((time_t *) NULL);
891 tmp = localtime (&Start);
892 yyYear = tmp->tm_year + TM_YEAR_ORIGIN;
893 yyMonth = tmp->tm_mon + 1;
894 yyDay = tmp->tm_mday;
895 yyHour = tmp->tm_hour;
896 yyMinutes = tmp->tm_min;
897 yySeconds = tmp->tm_sec;
912 || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
915 tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear;
916 tm.tm_mon = yyMonth - 1 + yyRelMonth;
917 tm.tm_mday = yyDay + yyRelDay;
918 if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay)) {
919 tm.tm_hour = ToHour (yyHour, yyMeridian);
922 tm.tm_min = yyMinutes;
923 tm.tm_sec = yySeconds;
925 tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
927 tm.tm_hour += yyRelHour;
928 tm.tm_min += yyRelMinutes;
929 tm.tm_sec += yyRelSeconds;
933 Start = mktime (&tm);
935 if (Start == (time_t) -1) {
937 /* Guard against falsely reporting errors near the time_t boundaries
938 when parsing times in other time zones. For example, if the min
939 time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
940 of UTC, then the min localtime value is 1970-01-01 08:00:00; if
941 we apply mktime to 1970-01-01 00:00:00 we will get an error, so
942 we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
943 zone by 24 hours to compensate. This algorithm assumes that
944 there is no DST transition within a day of the time_t boundaries. */
947 if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN) {
949 yyTimezone -= 24 * 60;
952 yyTimezone += 24 * 60;
954 Start = mktime (&tm);
957 if (Start == (time_t) -1)
961 if (yyHaveDay && !yyHaveDate) {
962 tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7
963 + 7 * (yyDayOrdinal - (0 < yyDayOrdinal)));
964 Start = mktime (&tm);
965 if (Start == (time_t) -1)
970 long delta = yyTimezone * 60L + difftm (&tm, gmtime (&Start));
971 if ((Start + delta < Start) != (delta < 0))
972 return -1; /* time_t overflow */
988 char buff[MAX_BUFF_LEN + 1];
991 (void)printf ("Enter date, or blank line to exit.\n\t> ");
992 (void)fflush (stdout);
994 buff[MAX_BUFF_LEN] = 0;
995 while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) {
996 d = get_date (buff, (time_t *)NULL);
998 (void)printf ("Bad format - couldn't convert.\n");
1000 (void)printf ("%s", ctime (&d));
1001 (void)printf ("\t> ");
1002 (void)fflush (stdout);
1007 #endif /* defined (TEST) */