parsdate.y
上传用户:minyiyu
上传日期:2018-12-24
资源大小:864k
文件大小:23k
- %{
- /*
- * Project : tin - a Usenet reader
- * Module : parsedate.y
- * Author : S.Bellovin & R.$alz & J.Berets & P.Eggert
- * Created : 01-08-90
- * Updated : 04-12-92
- * Notes : This grammar has 6 shift/reduce conflicts.
- * Originally written by Steven M. Bellovin <smb@research.att.com>
- * while at the University of North Carolina at Chapel Hill.
- * Later tweaked by a couple of people on Usenet. Completely
- * overhauled by Rich $alz <rsalz@osf.org> and Jim Berets
- * <jberets@bbn.com> in August, 1990.
- * Further revised (removed obsolete constructs and cleaned up
- * timezone names) in August, 1991, by Rich.
- * Paul Eggert <eggert@twinsun.com> helped in September 1992.
- * Revision : 1.12
- * Copyright : This code is in the public domain and has no copyright.
- */
- /* SUPPRESS 530 *//* Empty body for statement */
- /* SUPPRESS 593 on yyerrlab *//* Label was not used */
- /* SUPPRESS 593 on yynewstate *//* Label was not used */
- /* SUPPRESS 595 on yypvt *//* Automatic variable may be used before set */
- /*#include "tin.h"*/
- #include "innbbsconf.h"
- #include <stdio.h>
- #include <time.h>
- typedef struct _TIMEINFO
- {
- time_t time;
- long usec;
- long tzone;
- } TIMEINFO;
- /*
- ** Get the number of elements in a fixed-size array, or a pointer just
- ** past the end of it.
- */
- #define SIZEOF(array) ((int)(sizeof array / sizeof array[0]))
- #define ENDOF(array) (&array[SIZEOF(array)])
- #define CTYPE(isXXXXX, c) ((isascii((c)) && isXXXXX((c))))
- typedef char *STRING;
- #define yyparse date_parse
- #define yylex date_lex
- #define yyerror date_error
- /* See the LeapYears table in Convert. */
- #define EPOCH 1970
- #define END_OF_TIME 2038
- /* Constants for general time calculations. */
- #define DST_OFFSET 1
- #define SECSPERDAY (24L * 60L * 60L)
- /* Readability for TABLE stuff. */
- #define HOUR(x) (x * 60)
- #define LPAREN '('
- #define RPAREN ')'
- #define IS7BIT(x) ((unsigned int)(x) < 0200)
- /*
- ** An entry in the lexical lookup table.
- */
- typedef struct _TABLE {
- STRING name;
- int type;
- time_t value;
- } TABLE;
- /*
- ** Daylight-savings mode: on, off, or not yet known.
- */
- typedef enum _DSTMODE {
- DSTon, DSToff, DSTmaybe
- } DSTMODE;
- /*
- ** Meridian: am, pm, or 24-hour style.
- */
- typedef enum _MERIDIAN {
- MERam, MERpm, MER24
- } MERIDIAN;
- /*
- ** Global variables. We could get rid of most of them by using a yacc
- ** union, but this is more efficient. (This routine predates the
- ** yacc %union construct.)
- */
- static char *yyInput;
- static DSTMODE yyDSTmode;
- static int yyHaveDate;
- static int yyHaveRel;
- static int yyHaveTime;
- static time_t yyTimezone;
- static time_t yyDay;
- static time_t yyHour;
- static time_t yyMinutes;
- static time_t yyMonth;
- static time_t yySeconds;
- static time_t yyYear;
- static MERIDIAN yyMeridian;
- static time_t yyRelMonth;
- static time_t yyRelSeconds;
- extern struct tm *localtime();
- static void date_error();
- %}
- %union {
- time_t Number;
- enum _MERIDIAN Meridian;
- }
- %token tDAY tDAYZONE tMERIDIAN tMONTH tMONTH_UNIT tSEC_UNIT tSNUMBER
- %token tUNUMBER tZONE
- %type <Number> tDAYZONE tMONTH tMONTH_UNIT tSEC_UNIT
- %type <Number> tSNUMBER tUNUMBER tZONE numzone zone
- %type <Meridian> tMERIDIAN o_merid
- %%
- spec : /* NULL */
- | spec item
- ;
- item : time {
- yyHaveTime++;
- #if defined(lint)
- /* I am compulsive about lint natterings... */
- if (yyHaveTime == -1) {
- YYERROR;
- }
- #endif /* defined(lint) */
- }
- | time zone {
- yyHaveTime++;
- yyTimezone = $2;
- }
- | date {
- yyHaveDate++;
- }
- | rel {
- yyHaveRel = 1;
- }
- ;
- time : tUNUMBER o_merid {
- if ($1 < 100) {
- yyHour = $1;
- yyMinutes = 0;
- }
- else {
- yyHour = $1 / 100;
- yyMinutes = $1 % 100;
- }
- yySeconds = 0;
- yyMeridian = $2;
- }
- | tUNUMBER ':' tUNUMBER o_merid {
- yyHour = $1;
- yyMinutes = $3;
- yySeconds = 0;
- yyMeridian = $4;
- }
- | tUNUMBER ':' tUNUMBER numzone {
- yyHour = $1;
- yyMinutes = $3;
- yyTimezone = $4;
- yyMeridian = MER24;
- yyDSTmode = DSToff;
- }
- | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
- yyHour = $1;
- yyMinutes = $3;
- yySeconds = $5;
- yyMeridian = $6;
- }
- | tUNUMBER ':' tUNUMBER ':' tUNUMBER numzone {
- yyHour = $1;
- yyMinutes = $3;
- yySeconds = $5;
- yyTimezone = $6;
- yyMeridian = MER24;
- yyDSTmode = DSToff;
- }
- ;
- zone : tZONE {
- $$ = $1;
- yyDSTmode = DSToff;
- }
- | tDAYZONE {
- $$ = $1;
- yyDSTmode = DSTon;
- }
- | tZONE numzone {
- /* Only allow "GMT+300" and "GMT-0800" */
- if ($1 != 0) {
- YYABORT;
- }
- $$ = $2;
- yyDSTmode = DSToff;
- }
- | numzone {
- $$ = $1;
- yyDSTmode = DSToff;
- }
- ;
- numzone : tSNUMBER {
- int i;
-
- /* Unix and GMT and numeric timezones -- a little confusing. */
- if ($1 < 0) {
- /* Don't work with negative modulus. */
- $1 = -$1;
- if ($1 > 9999 || (i = $1 % 100) >= 60) {
- YYABORT;
- }
- $$ = ($1 / 100) * 60 + i;
- }
- else {
- if ($1 > 9999 || (i = $1 % 100) >= 60) {
- YYABORT;
- }
- $$ = -(($1 / 100) * 60 + i);
- }
- }
- ;
- date : tUNUMBER '/' tUNUMBER {
- yyMonth = $1;
- yyDay = $3;
- }
- | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
- if ($1 > 100) {
- yyYear = $1;
- yyMonth = $3;
- yyDay = $5;
- }
- else {
- yyMonth = $1;
- yyDay = $3;
- yyYear = $5;
- }
- }
- | tMONTH tUNUMBER {
- yyMonth = $1;
- yyDay = $2;
- }
- | tMONTH tUNUMBER ',' tUNUMBER {
- yyMonth = $1;
- yyDay = $2;
- yyYear = $4;
- }
- | tUNUMBER tMONTH {
- yyDay = $1;
- yyMonth = $2;
- }
- | tUNUMBER tMONTH tUNUMBER {
- yyDay = $1;
- yyMonth = $2;
- yyYear = $3;
- }
- | tDAY ',' tUNUMBER tMONTH tUNUMBER {
- yyDay = $3;
- yyMonth = $4;
- yyYear = $5;
- }
- ;
- rel : tSNUMBER tSEC_UNIT {
- yyRelSeconds += $1 * $2;
- }
- | tUNUMBER tSEC_UNIT {
- yyRelSeconds += $1 * $2;
- }
- | tSNUMBER tMONTH_UNIT {
- yyRelMonth += $1 * $2;
- }
- | tUNUMBER tMONTH_UNIT {
- yyRelMonth += $1 * $2;
- }
- ;
- o_merid : /* NULL */ {
- $$ = MER24;
- }
- | tMERIDIAN {
- $$ = $1;
- }
- ;
- %%
- /* Month and day table. */
- static TABLE MonthDayTable[] = {
- { "january", tMONTH, 1 },
- { "february", tMONTH, 2 },
- { "march", tMONTH, 3 },
- { "april", tMONTH, 4 },
- { "may", tMONTH, 5 },
- { "june", tMONTH, 6 },
- { "july", tMONTH, 7 },
- { "august", tMONTH, 8 },
- { "september", tMONTH, 9 },
- { "october", tMONTH, 10 },
- { "november", tMONTH, 11 },
- { "december", tMONTH, 12 },
- /* The value of the day isn't used... */
- { "sunday", tDAY, 0 },
- { "monday", tDAY, 0 },
- { "tuesday", tDAY, 0 },
- { "wednesday", tDAY, 0 },
- { "thursday", tDAY, 0 },
- { "friday", tDAY, 0 },
- { "saturday", tDAY, 0 },
- };
- /* Time units table. */
- static TABLE UnitsTable[] = {
- { "year", tMONTH_UNIT, 12 },
- { "month", tMONTH_UNIT, 1 },
- #ifdef QNX4
- { "week", tSEC_UNIT, 604800 },
- { "day", tSEC_UNIT, 86400 },
- #else
- { "week", tSEC_UNIT, 7 * 24 * 60 * 60 },
- { "day", tSEC_UNIT, 1 * 24 * 60 * 60 },
- #endif
- { "hour", tSEC_UNIT, 60 * 60 },
- { "minute", tSEC_UNIT, 60 },
- { "min", tSEC_UNIT, 60 },
- { "second", tSEC_UNIT, 1 },
- { "sec", tSEC_UNIT, 1 },
- };
- /* Timezone table. */
- static TABLE TimezoneTable[] = {
- { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
- { "ut", tZONE, HOUR( 0) }, /* Universal */
- { "utc", tZONE, HOUR( 0) }, /* Universal Coordinated */
- { "cut", tZONE, HOUR( 0) }, /* Coordinated Universal */
- { "z", tZONE, HOUR( 0) }, /* Greenwich Mean */
- { "wet", tZONE, HOUR( 0) }, /* Western European */
- { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
- { "nst", tZONE, HOUR(3)+30 }, /* Newfoundland Standard */
- { "ndt", tDAYZONE, HOUR(3)+30 }, /* Newfoundland Daylight */
- { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
- { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
- { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
- { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
- { "cst", tZONE, HOUR( 6) }, /* Central Standard */
- { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
- { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
- { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
- { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
- { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
- { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
- { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
- { "akst", tZONE, HOUR( 9) }, /* Alaska Standard */
- { "akdt", tDAYZONE, HOUR( 9) }, /* Alaska Daylight */
- { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
- { "hast", tZONE, HOUR(10) }, /* Hawaii-Aleutian Standard */
- { "hadt", tDAYZONE, HOUR(10) }, /* Hawaii-Aleutian Daylight */
- { "ces", tDAYZONE, -HOUR(1) }, /* Central European Summer */
- { "cest", tDAYZONE, -HOUR(1) }, /* Central European Summer */
- { "mez", tZONE, -HOUR(1) }, /* Middle European */
- { "mezt", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
- { "cet", tZONE, -HOUR(1) }, /* Central European */
- { "met", tZONE, -HOUR(1) }, /* Middle European */
- { "eet", tZONE, -HOUR(2) }, /* Eastern Europe */
- { "msk", tZONE, -HOUR(3) }, /* Moscow Winter */
- { "msd", tDAYZONE, -HOUR(3) }, /* Moscow Summer */
- { "wast", tZONE, -HOUR(8) }, /* West Australian Standard */
- { "wadt", tDAYZONE, -HOUR(8) }, /* West Australian Daylight */
- { "hkt", tZONE, -HOUR(8) }, /* Hong Kong */
- { "cct", tZONE, -HOUR(8) }, /* China Coast */
- { "jst", tZONE, -HOUR(9) }, /* Japan Standard */
- { "kst", tZONE, -HOUR(9) }, /* Korean Standard */
- { "kdt", tZONE, -HOUR(9) }, /* Korean Daylight */
- { "cast", tZONE, -(HOUR(9)+30) }, /* Central Australian Standard */
- { "cadt", tDAYZONE, -(HOUR(9)+30) }, /* Central Australian Daylight */
- { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
- { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
- { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
- { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
- /* For completeness we include the following entries. */
- #if 0
- /* Duplicate names. Either they conflict with a zone listed above
- * (which is either more likely to be seen or just been in circulation
- * longer), or they conflict with another zone in this section and
- * we could not reasonably choose one over the other. */
- { "fst", tZONE, HOUR( 2) }, /* Fernando De Noronha Standard */
- { "fdt", tDAYZONE, HOUR( 2) }, /* Fernando De Noronha Daylight */
- { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
- { "est", tZONE, HOUR( 3) }, /* Eastern Standard (Brazil) */
- { "edt", tDAYZONE, HOUR( 3) }, /* Eastern Daylight (Brazil) */
- { "wst", tZONE, HOUR( 4) }, /* Western Standard (Brazil) */
- { "wdt", tDAYZONE, HOUR( 4) }, /* Western Daylight (Brazil) */
- { "cst", tZONE, HOUR( 5) }, /* Chile Standard */
- { "cdt", tDAYZONE, HOUR( 5) }, /* Chile Daylight */
- { "ast", tZONE, HOUR( 5) }, /* Acre Standard */
- { "adt", tDAYZONE, HOUR( 5) }, /* Acre Daylight */
- { "cst", tZONE, HOUR( 5) }, /* Cuba Standard */
- { "cdt", tDAYZONE, HOUR( 5) }, /* Cuba Daylight */
- { "est", tZONE, HOUR( 6) }, /* Easter Island Standard */
- { "edt", tDAYZONE, HOUR( 6) }, /* Easter Island Daylight */
- { "sst", tZONE, HOUR(11) }, /* Samoa Standard */
- { "ist", tZONE, -HOUR(2) }, /* Israel Standard */
- { "idt", tDAYZONE, -HOUR(2) }, /* Israel Daylight */
- { "idt", tDAYZONE, -(HOUR(3)+30) }, /* Iran Daylight */
- { "ist", tZONE, -(HOUR(3)+30) }, /* Iran Standard */
- { "cst", tZONE, -HOUR(8) }, /* China Standard */
- { "cdt", tDAYZONE, -HOUR(8) }, /* China Daylight */
- { "sst", tZONE, -HOUR(8) }, /* Singapore Standard */
- /* Dubious (e.g., not in Olson's TIMEZONE package) or obsolete. */
- { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
- { "wat", tZONE, -HOUR(1) }, /* West Africa */
- { "at", tZONE, HOUR( 2) }, /* Azores */
- { "gst", tZONE, -HOUR(10) }, /* Guam Standard */
- { "nft", tZONE, HOUR(3)+30 }, /* Newfoundland */
- { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
- { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
- { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
- { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
- { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
- { "fwt", tZONE, -HOUR(1) }, /* French Winter */
- { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
- { "bt", tZONE, -HOUR(3) }, /* Baghdad */
- { "it", tZONE, -(HOUR(3)+30) }, /* Iran */
- { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
- { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
- { "ist", tZONE, -(HOUR(5)+30) }, /* Indian Standard */
- { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
- { "nst", tZONE, -HOUR(7) }, /* North Sumatra */
- { "sst", tZONE, -HOUR(7) }, /* South Sumatra */
- { "jt", tZONE, -(HOUR(7)+30) }, /* Java (3pm in Cronusland!) */
- { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
- { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
- { "cat", tZONE, HOUR(10) }, /* -- expired 1967 */
- { "nt", tZONE, HOUR(11) }, /* -- expired 1967 */
- { "ahst", tZONE, HOUR(10) }, /* -- expired 1983 */
- { "hdt", tDAYZONE, HOUR(10) }, /* -- expired 1986 */
- #endif /* 0 */
- };
- /* ARGSUSED */
- static void
- date_error(s)
- char *s;
- {
- /* NOTREACHED */
- }
- static time_t
- ToSeconds(Hours, Minutes, Seconds, Meridian)
- time_t Hours;
- time_t Minutes;
- time_t Seconds;
- MERIDIAN Meridian;
- {
- if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
- return -1;
- if (Meridian == MER24) {
- if (Hours < 0 || Hours > 23)
- return -1;
- }
- else {
- if (Hours < 1 || Hours > 12)
- return -1;
- if (Meridian == MERpm)
- Hours += 12;
- }
- return (Hours * 60L + Minutes) * 60L + Seconds;
- }
- static time_t
- Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
- time_t Month;
- time_t Day;
- time_t Year;
- time_t Hours;
- time_t Minutes;
- time_t Seconds;
- MERIDIAN Meridian;
- DSTMODE dst;
- {
- static int DaysNormal[13] = {
- 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
- static int DaysLeap[13] = {
- 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
- static int LeapYears[] = {
- 1972, 1976, 1980, 1984, 1988, 1992, 1996,
- 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
- };
- register int *yp;
- register int *mp;
- register time_t Julian;
- register int i;
- time_t tod;
- if (Year < 0)
- Year = -Year;
- if (Year < 100)
- Year += 1900;
- if (Year < EPOCH)
- Year += 100;
- for (mp = DaysNormal, yp = LeapYears; yp < ENDOF(LeapYears); yp++)
- if (Year == *yp) {
- mp = DaysLeap;
- break;
- }
- if (Year < EPOCH || Year > END_OF_TIME
- || Month < 1 || Month > 12
- /* NOSTRICT *//* conversion from long may lose accuracy */
- || Day < 1 || Day > mp[(int)Month])
- return -1;
- Julian = Day - 1 + (Year - EPOCH) * 365;
- for (yp = LeapYears; yp < ENDOF(LeapYears); yp++, Julian++)
- if (Year <= *yp)
- break;
- for (i = 1; i < Month; i++)
- Julian += *++mp;
- Julian *= SECSPERDAY;
- Julian += yyTimezone * 60L;
- if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
- return -1;
- Julian += tod;
- tod = Julian;
- if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
- Julian -= DST_OFFSET * 60 * 60;
- return Julian;
- }
- static time_t
- DSTcorrect(Start, Future)
- time_t Start;
- time_t Future;
- {
- time_t StartDay;
- time_t FutureDay;
- StartDay = (localtime(&Start)->tm_hour + 1) % 24;
- FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
- return (Future - Start) + (StartDay - FutureDay) * DST_OFFSET * 60 * 60;
- }
- static time_t
- RelativeMonth(Start, RelMonth)
- time_t Start;
- time_t RelMonth;
- {
- struct tm *tm;
- time_t Month;
- time_t Year;
- tm = localtime(&Start);
- Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
- Year = Month / 12;
- Month = Month % 12 + 1;
- return DSTcorrect(Start,
- Convert(Month, (time_t)tm->tm_mday, Year,
- (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
- MER24, DSTmaybe));
- }
- static int
- LookupWord(buff, length)
- char *buff;
- register int length;
- {
- register char *p;
- register STRING q;
- register TABLE *tp;
- register int c;
- p = buff;
- c = p[0];
-
- /* See if we have an abbreviation for a month. */
- if (length == 3 || (length == 4 && p[3] == '.'))
- for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++) {
- q = tp->name;
- if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
- yylval.Number = tp->value;
- return tp->type;
- }
- }
- else
- for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++)
- if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
- /* Try for a timezone. */
- for (tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
- if (c == tp->name[0] && p[1] == tp->name[1]
- && strcmp(p, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
- /* Try the units table. */
- for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
- if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
- /* Strip off any plural and try the units table again. */
- if (--length > 0 && p[length] == 's') {
- p[length] = ' ';
- for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
- if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
- p[length] = 's';
- yylval.Number = tp->value;
- return tp->type;
- }
- p[length] = 's';
- }
- length++;
- /* Drop out any periods. */
- for (p = buff, q = (STRING)buff; *q; q++)
- if (*q != '.')
- *p++ = *q;
- *p = ' ';
- /* Try the meridians. */
- if (buff[1] == 'm' && buff[2] == ' ') {
- if (buff[0] == 'a') {
- yylval.Meridian = MERam;
- return tMERIDIAN;
- }
- if (buff[0] == 'p') {
- yylval.Meridian = MERpm;
- return tMERIDIAN;
- }
- }
- /* If we saw any periods, try the timezones again. */
- if (p - buff != length) {
- c = buff[0];
- for (p = buff, tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
- if (c == tp->name[0] && p[1] == tp->name[1]
- && strcmp(p, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
- }
-
- /* Unknown word -- assume GMT timezone. */
- yylval.Number = 0;
- return tZONE;
- }
- static int
- date_lex()
- {
- register char c;
- register char *p;
- char buff[20];
- register int sign;
- register int i;
- register int nesting;
- for ( ; ; ) {
- /* Get first character after the whitespace. */
- for ( ; ; ) {
- while (CTYPE(isspace, *yyInput))
- yyInput++;
- c = *yyInput;
- /* Ignore RFC 822 comments, typically time zone names. */
- if (c != LPAREN)
- break;
- for (nesting = 1; (c = *++yyInput) != RPAREN || --nesting; )
- if (c == LPAREN)
- nesting++;
- else if (!IS7BIT(c) || c == ' ' || c == 'r'
- || (c == '\' && ((c = *++yyInput) == ' ' || !IS7BIT(c))))
- /* Lexical error: bad comment. */
- return '?';
- yyInput++;
- }
- /* A number? */
- if (CTYPE(isdigit, c) || c == '-' || c == '+') {
- if (c == '-' || c == '+') {
- sign = c == '-' ? -1 : 1;
- yyInput++;
- if (!CTYPE(isdigit, *yyInput))
- /* Skip the plus or minus sign. */
- continue;
- }
- else
- sign = 0;
- for (i = 0; (c = *yyInput++) != ' ' && CTYPE(isdigit, c); )
- i = 10 * i + c - '0';
- yyInput--;
- yylval.Number = sign < 0 ? -i : i;
- return sign ? tSNUMBER : tUNUMBER;
- }
- /* A word? */
- if (CTYPE(isalpha, c)) {
- for (p = buff; (c = *yyInput++) == '.' || CTYPE(isalpha, c); )
- if (p < &buff[sizeof buff - 1])
- *p++ = CTYPE(isupper, c) ? tolower(c) : c;
- *p = ' ';
- yyInput--;
- return LookupWord(buff, p - buff);
- }
- return *yyInput++;
- }
- }
- int
- GetTimeInfo(Now)
- TIMEINFO *Now;
- {
- static time_t LastTime;
- static long LastTzone;
- struct tm *tm;
- #if defined(DO_HAVE_GETTIMEOFDAY)
- struct timeval tv;
- #endif /* defined(DO_HAVE_GETTIMEOFDAY) */
- #if !defined(WITH_GM_GMTOFF)
- # define DONT_HAVE_TM_GMTOFF
- #endif
- #if defined(DONT_HAVE_TM_GMTOFF)
- struct tm local;
- struct tm gmt;
- #endif /* !defined(DONT_HAVE_TM_GMTOFF) */
- /* Get the basic time. */
- #if defined(DO_HAVE_GETTIMEOFDAY)
- if (gettimeofday(&tv, (struct timezone *)NULL) == -1)
- return -1;
- Now->time = tv.tv_sec;
- Now->usec = tv.tv_usec;
- #else
- /* Can't check for -1 since that might be a time, I guess. */
- (void)time(&Now->time);
- Now->usec = 0;
- #endif /* defined(DO_HAVE_GETTIMEOFDAY) */
- /* Now get the timezone if it's been an hour since the last time. */
- if (Now->time - LastTime > 60 * 60) {
- LastTime = Now->time;
- if ((tm = localtime(&Now->time)) == NULL)
- return -1;
- #if defined(DONT_HAVE_TM_GMTOFF)
- /* To get the timezone, compare localtime with GMT. */
- local = *tm;
- if ((tm = gmtime(&Now->time)) == NULL)
- return -1;
- gmt = *tm;
- /* Assume we are never more than 24 hours away. */
- LastTzone = gmt.tm_yday - local.tm_yday;
- if (LastTzone > 1)
- LastTzone = -24;
- else if (LastTzone < -1)
- LastTzone = 24;
- else
- LastTzone *= 24;
- /* Scale in the hours and minutes; ignore seconds. */
- LastTzone += gmt.tm_hour - local.tm_hour;
- LastTzone *= 60;
- LastTzone += gmt.tm_min - local.tm_min;
- #else
- LastTzone = (0 - tm->tm_gmtoff) / 60;
- #endif /* defined(DONT_HAVE_TM_GMTOFF) */
- }
- Now->tzone = LastTzone;
- return 0;
- }
- time_t
- parsedate(p, now)
- char *p;
- TIMEINFO *now;
- {
- extern int date_parse();
- struct tm *tm;
- TIMEINFO ti;
- time_t Start;
- yyInput = p;
- if (now == NULL) {
- now = &ti;
- (void)GetTimeInfo(&ti);
- }
- tm = localtime(&now->time);
- yyYear = tm->tm_year;
- yyMonth = tm->tm_mon + 1;
- yyDay = tm->tm_mday;
- yyTimezone = now->tzone;
- yyDSTmode = DSTmaybe;
- yyHour = 0;
- yyMinutes = 0;
- yySeconds = 0;
- yyMeridian = MER24;
- yyRelSeconds = 0;
- yyRelMonth = 0;
- yyHaveDate = 0;
- yyHaveRel = 0;
- yyHaveTime = 0;
- if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
- return -1;
- if (yyHaveDate || yyHaveTime) {
- Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
- yyMeridian, yyDSTmode);
- if (Start < 0)
- return -1;
- }
- else {
- Start = now->time;
- if (!yyHaveRel)
- Start -= (tm->tm_hour * 60L + tm->tm_min) * 60L + tm->tm_sec;
- }
- Start += yyRelSeconds;
- if (yyRelMonth)
- Start += RelativeMonth(Start, yyRelMonth);
- /* Have to do *something* with a legitimate -1 so it's distinguishable
- * from the error return value. (Alternately could set errno on error.) */
- return Start == -1 ? 0 : Start;
- }