/* A Bison parser, made from d:\work\todo\gnu\tar109\getdate.y */ #define ID 258 #define MONTH 259 #define DAY 260 #define MERIDIAN 261 #define NUMBER 262 #define UNIT 263 #define MUNIT 264 #define SUNIT 265 #define ZONE 266 #define DAYZONE 267 #define AGO 268 #define DST 269 #line 2 "d:\work\todo\gnu\tar109\getdate.y" /* Originally from: Steven M. Bellovin (unc!smb) */ /* Dept. of Computer Science */ /* University of North Carolina at Chapel Hill */ /* @(#)getdate.y 2.17 11/30/87 */ /* #include "defs.h" JF not used any more */ #include #ifdef USG struct timeb { time_t time; unsigned short millitm; short timezone; short dstflag; }; static void ftime (); #else #include #endif #include #if defined(BSD4_2) || defined (BSD4_1C) #include #else /* sane */ #include #endif /* sane */ #if defined (STDC_HEADERS) || defined (USG) #include #endif #ifdef __GNUC__ #define alloca __builtin_alloca #else #ifdef sparc #include #endif #endif #ifndef NULL #define NULL 0 #endif #define daysec (24L*60L*60L) static int timeflag, zoneflag, dateflag, dayflag, relflag; static time_t relsec, relmonth; static int hh, mm, ss, merid, day_light; static int dayord, dayreq; static int month, day, year; static int ourzone; #define AM 1 #define PM 2 #define DAYLIGHT 1 #define STANDARD 2 #define MAYBE 3 static time_t timeconv(); static time_t daylcorr(); static lookup(); static yylex(); static yyerror(); static int yylex (); #define yyparse getdate_yyparse static int yyerror (); #ifndef YYLTYPE typedef struct yyltype { int timestamp; int first_line; int first_column; int last_line; int last_column; char *text; } yyltype; #define YYLTYPE yyltype #endif #ifndef YYSTYPE #define YYSTYPE int #endif #include #ifndef __STDC__ #define const #endif #define YYFINAL 44 #define YYFLAG -32768 #define YYNTBASE 18 #define YYTRANSLATE(x) ((unsigned)(x) <= 269 ? yytranslate[x] : 27) static const char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 17, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; #if YYDEBUG != 0 static const short yyrline[] = { 0, 71, 72, 75, 77, 79, 81, 83, 85, 87, 96, 98, 100, 102, 105, 107, 109, 113, 115, 118, 120, 123, 125, 127, 130, 132, 134, 136, 138, 140, 144, 146, 148, 150, 152, 154, 156 }; static const char * const yytname[] = { 0, "error","$illegal.","ID","MONTH","DAY","MERIDIAN","NUMBER","UNIT","MUNIT","SUNIT", "ZONE","DAYZONE","AGO","DST","':'","','","'/'","timedate" }; #endif static const short yyr1[] = { 0, 18, 18, 19, 19, 19, 19, 19, 19, 20, 21, 21, 21, 21, 21, 21, 21, 22, 22, 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26 }; static const short yyr2[] = { 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 4, 5, 6, 6, 2, 1, 0, 1, 1, 2, 2, 3, 5, 2, 4, 2, 3, 2, 2, 2, 1, 1, 1, 2 }; static const short yydefact[] = { 1, 0, 0, 21, 9, 33, 34, 35, 19, 18, 2, 8, 3, 4, 6, 5, 7, 26, 22, 28, 23, 10, 30, 31, 32, 0, 0, 20, 17, 36, 0, 29, 11, 24, 27, 12, 13, 0, 0, 14, 25, 15, 16, 0, 0 }; static const short yydefgoto[] = { 1, 10, 11, 12, 13, 28, 14, 15, 16 }; static const short yypact[] = {-32768, 10, 2, -13, -4,-32768,-32768,-32768, -2,-32768,-32768, -32768,-32768,-32768,-32768,-32768, 12, 11,-32768, 19,-32768, -32768,-32768,-32768,-32768, 21, 22,-32768,-32768,-32768, 23, -32768, 1, 14,-32768,-32768,-32768, 25, 26, 17,-32768, -32768,-32768, 34,-32768 }; static const short yypgoto[] = {-32768, -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768 }; #define YYLAST 34 static const short yytable[] = { 19, 20, 21, 18, 22, 23, 24, 35, 36, 17, 43, 25, 27, 26, 2, 3, 37, 4, 5, 6, 7, 8, 9, 41, 42, 29, 31, 30, 32, 33, 34, 38, 39, 40, 44 }; static const short yycheck[] = { 4, 5, 6, 16, 8, 9, 10, 6, 7, 7, 0, 15, 14, 17, 4, 5, 15, 7, 8, 9, 10, 11, 12, 6, 7, 13, 7, 16, 7, 7, 7, 17, 7, 7, 0 }; #define YYPURE 1 /* BISON template */ /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ #line 3 "simple.bsn" /* Skeleton output parser for bison, Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef __GNUC__ #define alloca __builtin_alloca #else /* Not GNU C. */ #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) #include #else #ifdef MSDOS #include #else void *alloca(unsigned); #endif /* MSDOS */ #endif /* Sparc. */ #endif /* Not GNU C. */ #ifndef bcopy #define bcopy(s,d,x) memcpy(d,s,x) #endif /* This is the parser code that is written into each bison parser when the %semantic_parser declaration is not specified in the grammar. It was written by Richard Stallman by simplifying the hairy parser used when %semantic_parser is specified. */ /* Note: there must be only one dollar sign in this file. It is replaced by the list of actions, each action as one case of the switch. */ #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY -2 #define YYEOF 0 #define YYACCEPT return(0) #define YYABORT return(1) #define YYERROR goto yyerrlab1 /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(token, value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { yychar = (token), yylval = (value); \ yychar1 = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { yyerror ("syntax error: cannot back up"); YYERROR; } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 #ifndef YYIMPURE #define YYLEX yylex() #endif #ifndef YYPURE #define YYLEX yylex(&yylval, &yylloc) #endif /* If nonreentrant, generate the variables here */ #ifndef YYIMPURE int yychar; /* the lookahead symbol */ YYSTYPE yylval; /* the semantic value of the */ /* lookahead symbol */ #ifdef YYLSP_NEEDED YYLTYPE yylloc; /* location data for the lookahead */ /* symbol */ #endif int yynerrs; /* number of parse errors so far */ #endif /* YYIMPURE */ #if YYDEBUG != 0 int yydebug; /* nonzero means print parse trace */ /* Since this is uninitialized, it does not stop multiple parsers from coexisting. */ #endif /* YYINITDEPTH indicates the initial size of the parser's stacks */ #ifndef YYINITDEPTH #define YYINITDEPTH 200 #endif /* YYMAXDEPTH is the maximum size the stacks can grow to (effective only if the built-in stack extension method is used). */ #if YYMAXDEPTH == 0 #undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH #define YYMAXDEPTH 10000 #endif /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void __yy_bcopy (from, to, count) char *from; char *to; int count; { register char *f = from; register char *t = to; register int i = count; while (i-- > 0) *t++ = *f++; } #line 131 "simple.bsn" int yyparse() { register int yystate; register int yyn; register short *yyssp; register YYSTYPE *yyvsp; int yyerrstatus; /* number of tokens to shift before error messages enabled */ int yychar1; /* lookahead token as an internal (translated) token number */ short yyssa[YYINITDEPTH]; /* the state stack */ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ short *yyss = yyssa; /* refer to the stacks thru separate pointers */ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ #ifdef YYLSP_NEEDED YYLTYPE *yyls = yylsa; YYLTYPE *yylsp; YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ #define YYPOPSTACK (yyvsp--, yysp--, yylsp--) #else #define YYPOPSTACK (yyvsp--, yysp--) #endif int yystacksize = YYINITDEPTH; #ifndef YYPURE int yychar; YYSTYPE yylval; int yynerrs; #ifdef YYLSP_NEEDED YYLTYPE yylloc; #endif #endif YYSTYPE yyval; /* the variable used to return */ /* semantic values from the action */ /* routines */ int yylen; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Starting parse\n"); #endif yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. */ yyssp = yyss - 1; yyvsp = yyvs; #ifdef YYLSP_NEEDED yylsp = yyls; #endif /* Push a new state, which is found in yystate . */ /* In all cases, when you get here, the value and location stacks have just been pushed. so pushing a state here evens the stacks. */ yynewstate: *++yyssp = yystate; if (yyssp >= yyss + yystacksize - 1) { /* Give user a chance to reallocate the stack */ /* Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; short *yyss1 = yyss; #ifdef YYLSP_NEEDED YYLTYPE *yyls1 = yyls; #endif /* Get the current used size of the three stacks, in elements. */ int size = yyssp - yyss + 1; #ifdef yyoverflow /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. */ yyoverflow("parser stack overflow", &yyss1, size * sizeof (*yyssp), &yyvs1, size * sizeof (*yyvsp), #ifdef YYLSP_NEEDED &yyls1, size * sizeof (*yylsp), #endif &yystacksize); yyss = yyss1; yyvs = yyvs1; #ifdef YYLSP_NEEDED yyls = yyls1; #endif #else /* no yyoverflow */ /* Extend the stack our own way. */ if (yystacksize >= YYMAXDEPTH) { yyerror("parser stack overflow"); return 2; } yystacksize *= 2; if (yystacksize > YYMAXDEPTH) yystacksize = YYMAXDEPTH; yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); __yy_bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); __yy_bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); #ifdef YYLSP_NEEDED yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); __yy_bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); #endif #endif /* no yyoverflow */ yyssp = yyss + size - 1; yyvsp = yyvs + size - 1; #ifdef YYLSP_NEEDED yylsp = yyls + size - 1; #endif #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Stack size increased to %d\n", yystacksize); #endif if (yyssp >= yyss + yystacksize - 1) YYABORT; } #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Entering state %d\n", yystate); #endif yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ /* yyresume: */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYFLAG) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* yychar is either YYEMPTY or YYEOF or a valid token in external form. */ if (yychar == YYEMPTY) { #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Reading a token: "); #endif yychar = YYLEX; } /* Convert token to internal form (in yychar1) for indexing tables with */ if (yychar <= 0) /* This means end of input. */ { yychar1 = 0; yychar = YYEOF; /* Don't call YYLEX any more */ #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Now at end of input.\n"); #endif } else { yychar1 = YYTRANSLATE(yychar); #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Next token is %d (%s)\n", yychar, yytname[yychar1]); #endif } yyn += yychar1; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) goto yydefault; yyn = yytable[yyn]; /* yyn is what to do for this token type in this state. Negative => reduce, -yyn is rule number. Positive => shift, yyn is new state. New state is final state => don't bother to shift, just return success. 0, or most negative number => error. */ if (yyn < 0) { if (yyn == YYFLAG) goto yyerrlab; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrlab; if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); #endif /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; #ifdef YYLSP_NEEDED *++yylsp = yylloc; #endif /* count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; /* Do the default action for the current state. */ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; /* Do a reduction. yyn is the number of a rule to reduce with. */ yyreduce: yylen = yyr2[yyn]; yyval = yyvsp[1-yylen]; /* implement default value of the action */ #if YYDEBUG != 0 if (yydebug) { if (yylen == 1) fprintf (stderr, "Reducing 1 value via rule %d (line %d), ", yyn, yyrline[yyn]); else fprintf (stderr, "Reducing %d values via rule %d (line %d), ", yylen, yyn, yyrline[yyn]); } #endif switch (yyn) { case 3: #line 76 "d:\work\todo\gnu\tar109\getdate.y" {timeflag++;; break;} case 4: #line 78 "d:\work\todo\gnu\tar109\getdate.y" {zoneflag++;; break;} case 5: #line 80 "d:\work\todo\gnu\tar109\getdate.y" {dateflag++;; break;} case 6: #line 82 "d:\work\todo\gnu\tar109\getdate.y" {dayflag++;; break;} case 7: #line 84 "d:\work\todo\gnu\tar109\getdate.y" {relflag++;; break;} case 9: #line 88 "d:\work\todo\gnu\tar109\getdate.y" {if (timeflag && dateflag && !relflag) year = yyvsp[0]; else if (yyvsp[0] > 10000) { dateflag++; day= yyvsp[0]%100; month= (yyvsp[0]/100)%100; year = month/10000; } else {timeflag++;hh = yyvsp[0]/100;mm = yyvsp[0]%100;ss = 0;merid = 24;}; break;} case 10: #line 97 "d:\work\todo\gnu\tar109\getdate.y" {hh = yyvsp[-1]; mm = 0; ss = 0; merid = yyvsp[0];; break;} case 11: #line 99 "d:\work\todo\gnu\tar109\getdate.y" {hh = yyvsp[-2]; mm = yyvsp[0]; merid = 24;; break;} case 12: #line 101 "d:\work\todo\gnu\tar109\getdate.y" {hh = yyvsp[-3]; mm = yyvsp[-1]; merid = yyvsp[0];; break;} case 13: #line 103 "d:\work\todo\gnu\tar109\getdate.y" {hh = yyvsp[-3]; mm = yyvsp[-1]; merid = 24; day_light = STANDARD; ourzone = -(yyvsp[0]%100 + 60*(yyvsp[0]/100));; break;} case 14: #line 106 "d:\work\todo\gnu\tar109\getdate.y" {hh = yyvsp[-4]; mm = yyvsp[-2]; ss = yyvsp[0]; merid = 24;; break;} case 15: #line 108 "d:\work\todo\gnu\tar109\getdate.y" {hh = yyvsp[-5]; mm = yyvsp[-3]; ss = yyvsp[-1]; merid = yyvsp[0];; break;} case 16: #line 110 "d:\work\todo\gnu\tar109\getdate.y" {hh = yyvsp[-5]; mm = yyvsp[-3]; ss = yyvsp[-1]; merid = 24; day_light = STANDARD; ourzone = -(yyvsp[0]%100 + 60*(yyvsp[0]/100));; break;} case 17: #line 114 "d:\work\todo\gnu\tar109\getdate.y" {ourzone = yyvsp[-1]; day_light = yyvsp[0];; break;} case 18: #line 116 "d:\work\todo\gnu\tar109\getdate.y" {ourzone = yyvsp[0]; day_light = DAYLIGHT;; break;} case 19: #line 119 "d:\work\todo\gnu\tar109\getdate.y" { yyval = STANDARD; ; break;} case 20: #line 121 "d:\work\todo\gnu\tar109\getdate.y" { yyval = DAYLIGHT; ; break;} case 21: #line 124 "d:\work\todo\gnu\tar109\getdate.y" {dayord = 1; dayreq = yyvsp[0];; break;} case 22: #line 126 "d:\work\todo\gnu\tar109\getdate.y" {dayord = 1; dayreq = yyvsp[-1];; break;} case 23: #line 128 "d:\work\todo\gnu\tar109\getdate.y" {dayord = yyvsp[-1]; dayreq = yyvsp[0];; break;} case 24: #line 131 "d:\work\todo\gnu\tar109\getdate.y" {month = yyvsp[-2]; day = yyvsp[0];; break;} case 25: #line 133 "d:\work\todo\gnu\tar109\getdate.y" {month = yyvsp[-4]; day = yyvsp[-2]; year = yyvsp[0];; break;} case 26: #line 135 "d:\work\todo\gnu\tar109\getdate.y" {month = yyvsp[-1]; day = yyvsp[0];; break;} case 27: #line 137 "d:\work\todo\gnu\tar109\getdate.y" {month = yyvsp[-3]; day = yyvsp[-2]; year = yyvsp[0];; break;} case 28: #line 139 "d:\work\todo\gnu\tar109\getdate.y" {month = yyvsp[0]; day = yyvsp[-1];; break;} case 29: #line 141 "d:\work\todo\gnu\tar109\getdate.y" {month = yyvsp[-1]; day = yyvsp[-2]; year = yyvsp[0];; break;} case 30: #line 145 "d:\work\todo\gnu\tar109\getdate.y" {relsec += 60L * yyvsp[-1] * yyvsp[0];; break;} case 31: #line 147 "d:\work\todo\gnu\tar109\getdate.y" {relmonth += yyvsp[-1] * yyvsp[0];; break;} case 32: #line 149 "d:\work\todo\gnu\tar109\getdate.y" {relsec += yyvsp[-1];; break;} case 33: #line 151 "d:\work\todo\gnu\tar109\getdate.y" {relsec += 60L * yyvsp[0];; break;} case 34: #line 153 "d:\work\todo\gnu\tar109\getdate.y" {relmonth += yyvsp[0];; break;} case 35: #line 155 "d:\work\todo\gnu\tar109\getdate.y" {relsec++;; break;} case 36: #line 157 "d:\work\todo\gnu\tar109\getdate.y" {relsec = -relsec; relmonth = -relmonth;; break;} } /* the action file gets copied in in place of this dollarsign */ #line 362 "simple.bsn" yyvsp -= yylen; yyssp -= yylen; #ifdef YYLSP_NEEDED yylsp -= yylen; #endif #if YYDEBUG != 0 if (yydebug) { short *ssp1 = yyss - 1; fprintf (stderr, "state stack now"); while (ssp1 != yyssp) fprintf (stderr, " %d", *++ssp1); fprintf (stderr, "\n"); } #endif *++yyvsp = yyval; #ifdef YYLSP_NEEDED yylsp++; if (yylen == 0) { yylsp->first_line = yylloc.first_line; yylsp->first_column = yylloc.first_column; yylsp->last_line = (yylsp-1)->last_line; yylsp->last_column = (yylsp-1)->last_column; yylsp->text = 0; } else { yylsp->last_line = (yylsp+yylen-1)->last_line; yylsp->last_column = (yylsp+yylen-1)->last_column; } #endif /* Now "shift" the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTBASE] + *yyssp; if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTBASE]; goto yynewstate; yyerrlab: /* here on detecting error */ if (! yyerrstatus) /* If not already recovering from an error, report this error. */ { ++yynerrs; #ifdef YYERROR_VERBOSE yyn = yypact[yystate]; if (yyn > YYFLAG && yyn < YYLAST) { int size = 0; char *msg; int x, count; count = 0; for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++) if (yycheck[x + yyn] == x) size += strlen(yytname[x]) + 15, count++; msg = (char *) xmalloc(size + 15); strcpy(msg, "parse error"); if (count < 5) { count = 0; for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++) if (yycheck[x + yyn] == x) { strcat(msg, count == 0 ? ", expecting `" : " or `"); strcat(msg, yytname[x]); strcat(msg, "'"); count++; } } yyerror(msg); free(msg); } else #endif /* YYERROR_VERBOSE */ yyerror("parse error"); } yyerrlab1: /* here on error raised explicitly by an action */ if (yyerrstatus == 3) { /* if just tried and failed to reuse lookahead token after an error, discard it. */ /* return failure if at end of input */ if (yychar == YYEOF) YYABORT; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); #endif yychar = YYEMPTY; } /* Else will try to reuse lookahead token after shifting the error token. */ yyerrstatus = 3; /* Each real token shifted decrements this */ goto yyerrhandle; yyerrdefault: /* current state does not do anything special for the error token. */ #if 0 /* This is wrong; only states that explicitly want error tokens should shift them. */ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ if (yyn) goto yydefault; #endif yyerrpop: /* pop the current state because it cannot handle the error token */ if (yyssp == yyss) YYABORT; yyvsp--; yystate = *--yyssp; #ifdef YYLSP_NEEDED yylsp--; #endif #if YYDEBUG != 0 if (yydebug) { short *ssp1 = yyss - 1; fprintf (stderr, "Error: state stack now"); while (ssp1 != yyssp) fprintf (stderr, " %d", *++ssp1); fprintf (stderr, "\n"); } #endif yyerrhandle: yyn = yypact[yystate]; if (yyn == YYFLAG) goto yyerrdefault; yyn += YYTERROR; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) goto yyerrdefault; yyn = yytable[yyn]; if (yyn < 0) { if (yyn == YYFLAG) goto yyerrpop; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrpop; if (yyn == YYFINAL) YYACCEPT; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Shifting error token, "); #endif *++yyvsp = yylval; #ifdef YYLSP_NEEDED *++yylsp = yylloc; #endif yystate = yyn; goto yynewstate; } #line 158 "d:\work\todo\gnu\tar109\getdate.y" static int mdays[12] = {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; #define epoch 1970 extern struct tm *localtime(); static time_t dateconv(mm, dd, yy, h, m, s, mer, zone, dayflag) int mm, dd, yy, h, m, s, mer, zone, dayflag; { time_t tod, jdate; register int i; if (yy < 0) yy = -yy; if (yy < 100) yy += 1900; mdays[1] = 28 + (yy%4 == 0 && (yy%100 != 0 || yy%400 == 0)); if (yy < epoch || yy > 1999 || mm < 1 || mm > 12 || dd < 1 || dd > mdays[--mm]) return (-1); jdate = dd-1; for (i=0; itm_isdst)) jdate += -1*60*60; return (jdate); } static time_t dayconv(ord, day, now) int ord, day; time_t now; { register struct tm *loctime; time_t tod; tod = now; loctime = localtime(&tod); tod += daysec * ((day - loctime->tm_wday + 7) % 7); tod += 7*daysec*(ord<=0?ord:ord-1); return daylcorr(tod, now); } static time_t timeconv(hh, mm, ss, mer) register int hh, mm, ss, mer; { if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (-1); switch (mer) { case AM: if (hh < 1 || hh > 12) return(-1); return (60L * ((hh%12)*60L + mm)+ss); case PM: if (hh < 1 || hh > 12) return(-1); return (60L * ((hh%12 +12)*60L + mm)+ss); case 24: if (hh < 0 || hh > 23) return (-1); return (60L * (hh*60L + mm)+ss); default: return (-1); } } static time_t monthadd(sdate, relmonth) time_t sdate, relmonth; { struct tm *ltime; time_t dateconv(); int mm, yy; if (relmonth == 0) return 0; ltime = localtime(&sdate); mm = 12*ltime->tm_year + ltime->tm_mon + relmonth; yy = mm/12; mm = mm%12 + 1; return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour, ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate); } static time_t daylcorr(future, now) time_t future, now; { int fdayl, nowdayl; nowdayl = (localtime(&now)->tm_hour+1) % 24; fdayl = (localtime(&future)->tm_hour+1) % 24; return (future-now) + 60L*60L*(nowdayl-fdayl); } static char *lptr; static int yylex() { extern int yylval; int sign; register char c; register char *p; char idbuf[20]; int pcnt; for (;;) { while (isspace(*lptr)) lptr++; if (isdigit(c = *lptr) || c == '-' || c == '+') { if (c== '-' || c == '+') { if (c=='-') sign = -1; else sign = 1; if (!isdigit(*++lptr)) { /* yylval = sign; return (NUMBER); */ return yylex(); /* skip the '-' sign */ } } else sign = 1; yylval = 0; while (isdigit(c = *lptr++)) yylval = 10*yylval + c - '0'; yylval *= sign; lptr--; return (NUMBER); } else if (isalpha(c)) { p = idbuf; while (isalpha(c = *lptr++) || c=='.') if (p < &idbuf[sizeof(idbuf)-1]) *p++ = c; *p = '\0'; lptr--; return (lookup(idbuf)); } else if (c == '(') { pcnt = 0; do { c = *lptr++; if (c == '\0') return(c); else if (c == '(') pcnt++; else if (c == ')') pcnt--; } while (pcnt > 0); } else return (*lptr++); } } struct table { char *name; int type, value; }; static struct table mdtab[] = { {"january", MONTH, 1}, {"february", MONTH, 2}, {"march", MONTH, 3}, {"april", MONTH, 4}, {"may", MONTH, 5}, {"june", MONTH, 6}, {"july", MONTH, 7}, {"august", MONTH, 8}, {"september", MONTH, 9}, {"sept", MONTH, 9}, {"october", MONTH, 10}, {"november", MONTH, 11}, {"december", MONTH, 12}, {"sunday", DAY, 0}, {"monday", DAY, 1}, {"tuesday", DAY, 2}, {"tues", DAY, 2}, {"wednesday", DAY, 3}, {"wednes", DAY, 3}, {"thursday", DAY, 4}, {"thur", DAY, 4}, {"thurs", DAY, 4}, {"friday", DAY, 5}, {"saturday", DAY, 6}, {0, 0, 0} }; #define HRS *60 #define HALFHR 30 static struct table mztab[] = { {"a.m.", MERIDIAN, AM}, {"am", MERIDIAN, AM}, {"p.m.", MERIDIAN, PM}, {"pm", MERIDIAN, PM}, {"nst", ZONE, 3 HRS + HALFHR}, /* Newfoundland */ {"n.s.t.", ZONE, 3 HRS + HALFHR}, {"ast", ZONE, 4 HRS}, /* Atlantic */ {"a.s.t.", ZONE, 4 HRS}, {"adt", DAYZONE, 4 HRS}, {"a.d.t.", DAYZONE, 4 HRS}, {"est", ZONE, 5 HRS}, /* Eastern */ {"e.s.t.", ZONE, 5 HRS}, {"edt", DAYZONE, 5 HRS}, {"e.d.t.", DAYZONE, 5 HRS}, {"cst", ZONE, 6 HRS}, /* Central */ {"c.s.t.", ZONE, 6 HRS}, {"cdt", DAYZONE, 6 HRS}, {"c.d.t.", DAYZONE, 6 HRS}, {"mst", ZONE, 7 HRS}, /* Mountain */ {"m.s.t.", ZONE, 7 HRS}, {"mdt", DAYZONE, 7 HRS}, {"m.d.t.", DAYZONE, 7 HRS}, {"pst", ZONE, 8 HRS}, /* Pacific */ {"p.s.t.", ZONE, 8 HRS}, {"pdt", DAYZONE, 8 HRS}, {"p.d.t.", DAYZONE, 8 HRS}, {"yst", ZONE, 9 HRS}, /* Yukon */ {"y.s.t.", ZONE, 9 HRS}, {"ydt", DAYZONE, 9 HRS}, {"y.d.t.", DAYZONE, 9 HRS}, {"hst", ZONE, 10 HRS}, /* Hawaii */ {"h.s.t.", ZONE, 10 HRS}, {"hdt", DAYZONE, 10 HRS}, {"h.d.t.", DAYZONE, 10 HRS}, {"gmt", ZONE, 0 HRS}, {"g.m.t.", ZONE, 0 HRS}, {"bst", DAYZONE, 0 HRS}, /* British Summer Time */ {"b.s.t.", DAYZONE, 0 HRS}, {"eet", ZONE, 0 HRS}, /* European Eastern Time */ {"e.e.t.", ZONE, 0 HRS}, {"eest", DAYZONE, 0 HRS}, /* European Eastern Summer Time */ {"e.e.s.t.", DAYZONE, 0 HRS}, {"met", ZONE, -1 HRS}, /* Middle European Time */ {"m.e.t.", ZONE, -1 HRS}, {"mest", DAYZONE, -1 HRS}, /* Middle European Summer Time */ {"m.e.s.t.", DAYZONE, -1 HRS}, {"wet", ZONE, -2 HRS }, /* Western European Time */ {"w.e.t.", ZONE, -2 HRS }, {"west", DAYZONE, -2 HRS}, /* Western European Summer Time */ {"w.e.s.t.", DAYZONE, -2 HRS}, {"jst", ZONE, -9 HRS}, /* Japan Standard Time */ {"j.s.t.", ZONE, -9 HRS}, /* Japan Standard Time */ /* No daylight savings time */ {"aest", ZONE, -10 HRS}, /* Australian Eastern Time */ {"a.e.s.t.", ZONE, -10 HRS}, {"aesst", DAYZONE, -10 HRS}, /* Australian Eastern Summer Time */ {"a.e.s.s.t.", DAYZONE, -10 HRS}, {"acst", ZONE, -(9 HRS + HALFHR)}, /* Australian Central Time */ {"a.c.s.t.", ZONE, -(9 HRS + HALFHR)}, {"acsst", DAYZONE, -(9 HRS + HALFHR)}, /* Australian Central Summer */ {"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)}, {"awst", ZONE, -8 HRS}, /* Australian Western Time */ {"a.w.s.t.", ZONE, -8 HRS}, /* (no daylight time there, I'm told */ {"dst", DST, 0}, /* Explicit daylight time */ {0, 0, 0}}; static struct table unittb[] = { {"year", MUNIT, 12}, {"month", MUNIT, 1}, {"fortnight", UNIT, 14*24*60}, {"week", UNIT, 7*24*60}, {"day", UNIT, 1*24*60}, {"hour", UNIT, 60}, {"minute", UNIT, 1}, {"min", UNIT, 1}, {"second", SUNIT, 1}, {"sec", SUNIT, 1}, {0, 0, 0}}; static struct table othertb[] = { {"tomorrow", UNIT, 1*24*60}, {"yesterday", UNIT, -1*24*60}, {"today", UNIT, 0}, {"now", UNIT, 0}, {"last", NUMBER, -1}, {"this", UNIT, 0}, {"next", NUMBER, 2}, {"first", NUMBER, 1}, /* {"second", NUMBER, 2}, */ {"third", NUMBER, 3}, {"fourth", NUMBER, 4}, {"fifth", NUMBER, 5}, {"sixth", NUMBER, 6}, {"seventh", NUMBER, 7}, {"eigth", NUMBER, 8}, {"ninth", NUMBER, 9}, {"tenth", NUMBER, 10}, {"eleventh", NUMBER, 11}, {"twelfth", NUMBER, 12}, {"ago", AGO, 1}, {0, 0, 0}}; static struct table milzone[] = { {"a", ZONE, 1 HRS}, {"b", ZONE, 2 HRS}, {"c", ZONE, 3 HRS}, {"d", ZONE, 4 HRS}, {"e", ZONE, 5 HRS}, {"f", ZONE, 6 HRS}, {"g", ZONE, 7 HRS}, {"h", ZONE, 8 HRS}, {"i", ZONE, 9 HRS}, {"k", ZONE, 10 HRS}, {"l", ZONE, 11 HRS}, {"m", ZONE, 12 HRS}, {"n", ZONE, -1 HRS}, {"o", ZONE, -2 HRS}, {"p", ZONE, -3 HRS}, {"q", ZONE, -4 HRS}, {"r", ZONE, -5 HRS}, {"s", ZONE, -6 HRS}, {"t", ZONE, -7 HRS}, {"u", ZONE, -8 HRS}, {"v", ZONE, -9 HRS}, {"w", ZONE, -10 HRS}, {"x", ZONE, -11 HRS}, {"y", ZONE, -12 HRS}, {"z", ZONE, 0 HRS}, {0, 0, 0}}; static int lookup(id) char *id; { #define gotit (yylval=i->value, i->type) char idvar[128]; register char *j, *k; register struct table *i; int abbrev; (void) strcpy(idvar, id); j = idvar; k = id - 1; while (*++k) *j++ = isupper(*k) ? tolower(*k) : *k; *j = '\0'; if (strlen(idvar) == 3) abbrev = 1; else if (strlen(idvar) == 4 && idvar[3] == '.' && idvar[1] != '.') { abbrev = 1; idvar[3] = '\0'; } else abbrev = 0; for (i = mdtab; i->name; i++) { k = idvar; for (j = i->name; *j++ == *k++;) { if (abbrev && j == i->name+3) return gotit; if (j[-1] == 0) return gotit; } } for (i=mztab; i->name; i++) if (strcmp(i->name, idvar) == 0) return gotit; for (i=unittb; i->name; i++) if (strcmp(i->name, idvar) == 0) return gotit; if (idvar[strlen(idvar)-1] == 's') idvar[strlen(idvar)-1] = '\0'; for (i=unittb; i->name; i++) if (strcmp(i->name, idvar) == 0) return gotit; for (i = othertb; i->name; i++) if (strcmp(i->name, idvar) == 0) return gotit; if (strlen(idvar) == 1 && isalpha(*idvar)) { for (i = milzone; i->name; i++) if (strcmp(i->name, idvar) == 0) return gotit; } return ID; } time_t getdate(p, now) char *p; struct timeb *now; { #define mcheck(f) if (f>1) err++ time_t monthadd(); int err; struct tm *lt; struct timeb ftz; time_t sdate, tod; lptr = p; if (now == ((struct timeb *) NULL)) { now = &ftz; ftime(&ftz); } lt = localtime(&now->time); year = lt->tm_year; month = lt->tm_mon+1; day = lt->tm_mday; relsec = 0; relmonth = 0; timeflag=zoneflag=dateflag=dayflag=relflag=0; ourzone = now->timezone; day_light = MAYBE; hh = mm = ss = 0; merid = 24; if (err = yyparse()) return (-1); mcheck(timeflag); mcheck(zoneflag); mcheck(dateflag); mcheck(dayflag); if (err) return (-1); if (dateflag || timeflag || dayflag) { sdate = dateconv(month,day,year,hh,mm,ss,merid,ourzone,day_light); if (sdate < 0) return -1; } else { sdate = now->time; if (relflag == 0) sdate -= (lt->tm_sec + lt->tm_min*60 + lt->tm_hour*(60L*60L)); } sdate += relsec; sdate += monthadd(sdate, relmonth); if (dayflag && !dateflag) { tod = dayconv(dayord, dayreq, sdate); sdate += tod; } /* ** Have to do *something* with a legitimate -1 so it's distinguishable ** from the error return value. (Alternately could set errno on error.) */ return (sdate == -1) ? 0 : sdate; } static int yyerror(s) char *s; { return 0; } #ifdef USG static void ftime(timeb) struct timeb *timeb; { extern long timezone; #ifndef DAYLIGHT_MISSING /* Not all non-BSD libraries have `daylight'. */ extern int daylight; #endif long t = 0; localtime(&t); /* Dummy to init timzeone */ time(&(timeb->time)); timeb->millitm=0; timeb->timezone=timezone/60; /* Timezone is in seconds! */ #ifndef DAYLIGHT_MISSING timeb->dstflag=daylight; #else timeb->dstflag=0; #endif } #endif