From: Tim Kientzle Date: Sun, 22 Feb 2009 06:23:03 +0000 (-0500) Subject: Towards a yacc-less bsdtar: Push some bookkeeping down towards the X-Git-Tag: v2.7.0~228 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf092016eb17a2b76122dce08a67137ca7085df4;p=thirdparty%2Flibarchive.git Towards a yacc-less bsdtar: Push some bookkeeping down towards the leaves, which gets us closer to a simple "phrase book" structure for the grammar. Isolate a stateless tokenizer that can be used in other ways. SVN-Revision: 693 --- diff --git a/tar/getdate.c b/tar/getdate.c index b86f09719..90fdeadbc 100644 --- a/tar/getdate.c +++ b/tar/getdate.c @@ -84,6 +84,11 @@ typedef enum _DSTMODE { DSTon, DSToff, DSTmaybe } DSTMODE; +/* +** Meridian: am or pm. +*/ +enum { tAM, tPM }; + /* ** Global variables. We could get rid of most of these by using a good ** union as the yacc stack. (This routine was originally written before @@ -110,80 +115,84 @@ static time_t yyYear; static time_t yyRelMonth; static time_t yyRelSeconds; -#line 93 "getdate.y" +/* +struct token { int token, time_t value }; +static struct token tokens[256]; +struct token *tokenp; +*/ + +#line 104 "getdate.y" typedef union { time_t Number; } YYSTYPE; -#line 118 "getdate.c" +#line 129 "getdate.c" #define YYERRCODE 256 #define tAGO 257 #define tDAY 258 #define tDAYZONE 259 -#define tAM 260 -#define tPM 261 -#define tMONTH 262 -#define tMONTH_UNIT 263 -#define tSEC_UNIT 264 -#define tUNUMBER 265 -#define tZONE 266 -#define tDST 267 +#define tAMPM 260 +#define tMONTH 261 +#define tMONTH_UNIT 262 +#define tSEC_UNIT 263 +#define tUNUMBER 264 +#define tZONE 265 +#define tDST 266 const short yylhs[] = { -1, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, - 2, 2, 2, 2, 2, 8, 8, 3, 3, 3, - 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, - 4, 6, 6, 9, 9, 9, 9, 9, 9, 9, - 9, 7, + 2, 2, 2, 8, 8, 3, 3, 3, 5, 5, + 5, 4, 4, 4, 4, 4, 4, 4, 4, 6, + 6, 9, 9, 9, 9, 9, 9, 9, 9, 7, }; const short yylen[] = { 2, - 0, 2, 1, 1, 1, 1, 1, 1, 2, 2, - 1, 2, 2, 3, 3, 3, 5, 1, 1, 2, - 1, 2, 2, 3, 5, 5, 5, 2, 4, 2, - 3, 2, 1, 3, 3, 2, 1, 3, 3, 2, - 1, 1, + 0, 2, 1, 1, 1, 1, 1, 1, 2, 1, + 2, 3, 3, 3, 5, 1, 1, 2, 1, 2, + 2, 3, 5, 5, 5, 2, 4, 2, 3, 2, + 1, 3, 3, 2, 1, 3, 3, 2, 1, 1, }; const short yydefred[] = { 1, - 0, 0, 19, 0, 41, 37, 0, 0, 0, 0, - 2, 3, 4, 5, 6, 7, 8, 0, 0, 22, - 0, 23, 9, 10, 0, 40, 36, 0, 0, 0, - 20, 0, 0, 12, 13, 0, 0, 32, 0, 31, - 0, 0, 0, 0, 39, 35, 38, 34, 14, 15, - 29, 0, 0, 0, 0, 27, 26, 17, 25, + 0, 0, 17, 0, 39, 35, 0, 0, 0, 0, + 2, 3, 4, 5, 6, 7, 8, 0, 0, 20, + 0, 21, 9, 0, 38, 34, 0, 0, 0, 18, + 0, 0, 11, 0, 0, 30, 0, 29, 0, 0, + 0, 0, 37, 33, 36, 32, 12, 13, 27, 0, + 0, 0, 0, 25, 24, 15, 23, }; const short yydgoto[] = { 1, 11, 12, 13, 14, 15, 16, 17, 18, 19, }; const short yysindex[] = { 0, - -43, -40, 0, -260, 0, 0, -34, -258, -253, -250, - 0, 0, 0, 0, 0, 0, 0, -29, -237, 0, - -23, 0, 0, 0, -243, 0, 0, -259, -242, -240, - 0, -256, -246, 0, 0, -239, -238, 0, -236, 0, - -15, -14, -26, -13, 0, 0, 0, 0, 0, 0, - 0, -232, -230, -229, -227, 0, 0, 0, 0, + -43, -40, 0, -259, 0, 0, -35, -252, -253, -248, + 0, 0, 0, 0, 0, 0, 0, -30, -237, 0, + -23, 0, 0, -242, 0, 0, -258, -240, -238, 0, + -255, -244, 0, -236, -235, 0, -234, 0, -18, -14, + -26, -13, 0, 0, 0, 0, 0, 0, 0, -229, + -228, -227, -226, 0, 0, 0, 0, }; const short yyrindex[] = { 0, - 0, 10, 0, 0, 0, 0, 67, 19, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 65, 28, 0, - 37, 0, 0, 0, 56, 0, 0, 0, 0, 0, + 0, 9, 0, 0, 0, 0, 64, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 57, 25, 0, + 33, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 47, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 41, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, }; const short yygindex[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -#define YYTABLESIZE 333 +#define YYTABLESIZE 329 const short yytable[] = { 9, - 16, 10, 41, 20, 21, 42, 45, 46, 31, 21, - 28, 32, 30, 36, 33, 37, 47, 48, 18, 38, - 39, 40, 43, 29, 44, 49, 50, 33, 51, 52, - 53, 54, 56, 55, 57, 58, 28, 59, 0, 0, - 0, 0, 0, 16, 0, 16, 24, 0, 0, 0, - 0, 0, 21, 0, 21, 30, 0, 0, 0, 0, - 0, 18, 0, 18, 11, 0, 42, 0, 0, 0, - 33, 0, 33, 0, 0, 0, 0, 0, 0, 28, - 0, 28, 0, 0, 0, 0, 0, 0, 0, 24, - 0, 24, 0, 0, 0, 0, 0, 0, 30, 0, - 30, 0, 0, 0, 0, 0, 0, 0, 0, 42, + 14, 10, 39, 20, 21, 40, 43, 44, 19, 27, + 31, 29, 34, 30, 35, 32, 16, 45, 46, 36, + 37, 38, 28, 41, 31, 42, 50, 47, 48, 49, + 51, 52, 26, 53, 54, 55, 56, 57, 0, 0, + 22, 0, 0, 14, 0, 14, 0, 0, 28, 0, + 0, 19, 0, 19, 0, 0, 10, 0, 0, 16, + 0, 16, 0, 40, 0, 0, 0, 31, 0, 31, + 0, 0, 0, 0, 0, 26, 0, 26, 0, 0, + 0, 0, 0, 22, 0, 22, 0, 0, 0, 0, + 0, 28, 0, 28, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -193,33 +202,32 @@ const short yytable[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 3, 0, 4, 5, 6, + 7, 8, 22, 0, 23, 24, 25, 26, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 3, 0, 0, 4, 5, - 6, 7, 8, 22, 0, 23, 24, 25, 26, 27, - 34, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 21, 21, 0, - 0, 21, 21, 21, 21, 21, 18, 18, 0, 0, - 18, 18, 18, 18, 18, 33, 33, 0, 0, 33, - 33, 33, 33, 33, 28, 28, 0, 0, 28, 28, - 28, 28, 28, 0, 24, 24, 0, 0, 24, 24, - 24, 24, 24, 30, 30, 0, 0, 30, 30, 30, - 0, 30, 11, 11, 0, 42, 11, 11, 11, 11, - 11, 42, 42, + 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, + 14, 14, 14, 14, 14, 14, 19, 19, 0, 19, + 19, 19, 19, 19, 16, 16, 0, 16, 16, 16, + 16, 16, 31, 31, 0, 31, 31, 31, 31, 31, + 26, 26, 0, 26, 26, 26, 26, 26, 22, 22, + 0, 22, 22, 22, 22, 22, 28, 28, 0, 28, + 28, 28, 0, 28, 10, 10, 0, 10, 10, 10, + 10, 10, 40, 0, 0, 0, 0, 40, 40, }; const short yycheck[] = { 43, - 0, 45, 262, 44, 265, 265, 263, 264, 267, 0, - 45, 265, 47, 43, 265, 45, 263, 264, 0, 257, - 44, 265, 265, 58, 265, 265, 265, 0, 265, 45, - 45, 58, 265, 47, 265, 265, 0, 265, -1, -1, - -1, -1, -1, 43, -1, 45, 0, -1, -1, -1, - -1, -1, 43, -1, 45, 0, -1, -1, -1, -1, - -1, 43, -1, 45, 0, -1, 0, -1, -1, -1, - 43, -1, 45, -1, -1, -1, -1, -1, -1, 43, - -1, 45, -1, -1, -1, -1, -1, -1, -1, 43, - -1, 45, -1, -1, -1, -1, -1, -1, 43, -1, - 45, -1, -1, -1, -1, -1, -1, -1, -1, 43, + 0, 45, 261, 44, 264, 264, 262, 263, 0, 45, + 264, 47, 43, 266, 45, 264, 0, 262, 263, 257, + 44, 264, 58, 264, 0, 264, 45, 264, 264, 264, + 45, 58, 0, 47, 264, 264, 264, 264, -1, -1, + 0, -1, -1, 43, -1, 45, -1, -1, 0, -1, + -1, 43, -1, 45, -1, -1, 0, -1, -1, 43, + -1, 45, -1, 0, -1, -1, -1, 43, -1, 45, + -1, -1, -1, -1, -1, 43, -1, 45, -1, -1, + -1, -1, -1, 43, -1, 45, -1, -1, -1, -1, + -1, 43, -1, 45, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -229,26 +237,24 @@ const short yycheck[] = { 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 258, 259, -1, 261, 262, 263, + 264, 265, 258, -1, 260, 261, 262, 263, -1, 260, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 258, 259, -1, -1, 262, 263, - 264, 265, 266, 258, -1, 260, 261, 262, 263, 264, - 260, 261, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 258, 259, -1, - -1, 262, 263, 264, 265, 266, 258, 259, -1, -1, - 262, 263, 264, 265, 266, 258, 259, -1, -1, 262, - 263, 264, 265, 266, 258, 259, -1, -1, 262, 263, - 264, 265, 266, -1, 258, 259, -1, -1, 262, 263, - 264, 265, 266, 258, 259, -1, -1, 262, 263, 264, - -1, 266, 258, 259, -1, 259, 262, 263, 264, 265, - 266, 265, 266, + 260, 261, 262, 263, 264, 265, 258, 259, -1, 261, + 262, 263, 264, 265, 258, 259, -1, 261, 262, 263, + 264, 265, 258, 259, -1, 261, 262, 263, 264, 265, + 258, 259, -1, 261, 262, 263, 264, 265, 258, 259, + -1, 261, 262, 263, 264, 265, 258, 259, -1, 261, + 262, 263, -1, 265, 258, 259, -1, 261, 262, 263, + 264, 265, 259, -1, -1, -1, -1, 264, 265, }; #define YYFINAL 1 #ifndef YYDEBUG #define YYDEBUG 0 #endif -#define YYMAXTOKEN 267 +#define YYMAXTOKEN 266 #if YYDEBUG const char * const yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -258,24 +264,21 @@ const char * const yyname[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"tAGO","tDAY", -"tDAYZONE","tAM","tPM","tMONTH","tMONTH_UNIT","tSEC_UNIT","tUNUMBER","tZONE", -"tDST", +"tDAYZONE","tAMPM","tMONTH","tMONTH_UNIT","tSEC_UNIT","tUNUMBER","tZONE","tDST", }; const char * const yyrule[] = { "$accept : spec", "spec :", -"spec : spec item", -"item : time", -"item : zone", -"item : date", -"item : day", -"item : rel", -"item : number", -"time : tUNUMBER tAM", -"time : tUNUMBER tPM", +"spec : spec phrase", +"phrase : time", +"phrase : zone", +"phrase : date", +"phrase : day", +"phrase : rel", +"phrase : number", +"time : tUNUMBER tAMPM", "time : bare_time", -"time : bare_time tAM", -"time : bare_time tPM", +"time : bare_time tAMPM", "time : bare_time '+' tUNUMBER", "time : bare_time '-' tUNUMBER", "bare_time : tUNUMBER ':' tUNUMBER", @@ -334,17 +337,17 @@ short *yyss; short *yysslim; YYSTYPE *yyvs; int yystacksize; -#line 338 "getdate.y" +#line 367 "getdate.y" -static struct TABLE { +static struct LEXICON { size_t abbrev; const char *name; int type; time_t value; } const TimeWords[] = { /* am/pm */ - { 0, "am", tAM, 0 }, - { 0, "pm", tPM, 0 }, + { 0, "am", tAMPM, tAM }, + { 0, "pm", tAMPM, tPM }, /* Month names. */ { 3, "january", tMONTH, 1 }, @@ -615,20 +618,20 @@ RelativeMonth(time_t Start, time_t RelMonth) } static int -yylex(void) +nexttoken(char **in, time_t *value) { char c; char buff[64]; for ( ; ; ) { - while (isspace((unsigned char)*yyInput)) - yyInput++; + while (isspace((unsigned char)**in)) + ++*in; /* Skip parenthesized comments. */ - if (*yyInput == '(') { + if (**in == '(') { int Count = 0; do { - c = *yyInput++; + c = *(*in)++; if (c == '\0') return c; if (c == '(') @@ -642,8 +645,8 @@ yylex(void) /* Try the next token in the word table first. */ /* This allows us to match "2nd", for example. */ { - char *src = yyInput; - const struct TABLE *tp; + char *src = *in; + const struct LEXICON *tp; unsigned i = 0; /* Force to lowercase and strip '.' characters. */ @@ -673,9 +676,9 @@ yylex(void) && strncmp(tp->name, buff, strlen(buff)) == 0) { /* Skip over token. */ - yyInput = src; + *in = src; /* Return the match. */ - yylval.Number = tp->value; + *value = tp->value; return tp->type; } } @@ -686,17 +689,23 @@ yylex(void) * Because '-' and '+' have other special meanings, I * don't deal with signed numbers here. */ - if (isdigit((unsigned char)(c = *yyInput))) { - for (yylval.Number = 0; isdigit((unsigned char)(c = *yyInput++)); ) - yylval.Number = 10 * yylval.Number + c - '0'; - yyInput--; + if (isdigit((unsigned char)(c = **in))) { + for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); ) + *value = 10 * *value + c - '0'; + (*in)--; return (tUNUMBER); } - return (*yyInput++); + return *(*in)++; } } +static int +yylex(void) +{ + return nexttoken(&yyInput, &yylval.Number); +} + #define TM_YEAR_ORIGIN 1900 /* Yield A - B, measured in seconds. */ @@ -768,8 +777,10 @@ get_date(char *p) yyHaveTime = 0; yyHaveZone = 0; - if (yyparse() - || yyHaveTime > 1 || yyHaveZone > 1 + if (yyparse()) + return -1; + + if (yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1) return -1; @@ -819,7 +830,7 @@ main(int argc, char **argv) /* NOTREACHED */ } #endif /* defined(TEST) */ -#line 823 "getdate.c" +#line 834 "getdate.c" /* allocate initial stack or double stack size, up to YYMAXDEPTH */ static int yygrowstack() { @@ -1014,157 +1025,135 @@ yyreduce: yyval = yyvsp[1-yym]; switch (yyn) { -case 3: -#line 109 "getdate.y" -{ yyHaveTime++; } -break; -case 4: -#line 110 "getdate.y" -{ yyHaveZone++; } -break; -case 5: -#line 111 "getdate.y" -{ yyHaveDate++; } -break; -case 6: -#line 112 "getdate.y" -{ yyHaveDay++; } -break; -case 7: -#line 113 "getdate.y" -{ yyHaveRel++; } -break; case 9: -#line 117 "getdate.y" +#line 128 "getdate.y" { /* "7am" */ + yyHaveTime++; yyHour = yyvsp[-1].Number; - yyMinutes = 0; - yySeconds = 0; if (yyHour == 12) yyHour = 0; - } -break; -case 10: -#line 125 "getdate.y" -{ - /* "7pm" */ - yyHour = yyvsp[-1].Number; yyMinutes = 0; yySeconds = 0; - if (yyHour < 12) + if (yyvsp[0].Number == tPM) yyHour += 12; } break; -case 11: -#line 133 "getdate.y" +case 10: +#line 139 "getdate.y" { /* "7:12:18" "19:17" */ + yyHaveTime++; } break; -case 12: -#line 136 "getdate.y" +case 11: +#line 143 "getdate.y" { - /* "12:20:13am" */ + /* "7:12pm", "12:20:13am" */ + yyHaveTime++; if (yyHour == 12) yyHour = 0; - } -break; -case 13: -#line 141 "getdate.y" -{ - /* "7:12pm" */ - if (yyHour < 12) + if (yyvsp[0].Number == tPM) yyHour += 12; } break; -case 14: -#line 146 "getdate.y" +case 12: +#line 151 "getdate.y" { /* "7:14+0700" */ + yyHaveTime++; yyDSTmode = DSToff; yyTimezone = - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60); } break; -case 15: -#line 151 "getdate.y" +case 13: +#line 157 "getdate.y" { /* "19:14:12-0530" */ + yyHaveTime++; yyDSTmode = DSToff; yyTimezone = + (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60); } break; -case 16: -#line 158 "getdate.y" +case 14: +#line 165 "getdate.y" { yyHour = yyvsp[-2].Number; yyMinutes = yyvsp[0].Number; yySeconds = 0; } break; -case 17: -#line 163 "getdate.y" +case 15: +#line 170 "getdate.y" { yyHour = yyvsp[-4].Number; yyMinutes = yyvsp[-2].Number; yySeconds = yyvsp[0].Number; } break; -case 18: -#line 170 "getdate.y" +case 16: +#line 177 "getdate.y" { + yyHaveZone++; yyTimezone = yyvsp[0].Number; yyDSTmode = DSToff; } break; -case 19: -#line 174 "getdate.y" +case 17: +#line 182 "getdate.y" { + yyHaveZone++; yyTimezone = yyvsp[0].Number; yyDSTmode = DSTon; } break; -case 20: -#line 178 "getdate.y" +case 18: +#line 187 "getdate.y" { + yyHaveZone++; yyTimezone = yyvsp[-1].Number; yyDSTmode = DSTon; } break; -case 21: -#line 184 "getdate.y" +case 19: +#line 194 "getdate.y" { + yyHaveDay++; yyDayOrdinal = 1; yyDayNumber = yyvsp[0].Number; } break; -case 22: -#line 188 "getdate.y" +case 20: +#line 199 "getdate.y" { /* "tue," "wednesday," */ + yyHaveDay++; yyDayOrdinal = 1; yyDayNumber = yyvsp[-1].Number; } break; -case 23: -#line 193 "getdate.y" +case 21: +#line 205 "getdate.y" { /* "second tues" "3 wed" */ + yyHaveDay++; yyDayOrdinal = yyvsp[-1].Number; yyDayNumber = yyvsp[0].Number; } break; -case 24: -#line 200 "getdate.y" +case 22: +#line 213 "getdate.y" { /* "1/15" */ + yyHaveDate++; yyMonth = yyvsp[-2].Number; yyDay = yyvsp[0].Number; } break; -case 25: -#line 205 "getdate.y" +case 23: +#line 219 "getdate.y" { + yyHaveDate++; if (yyvsp[-4].Number >= 13) { /* First number is big: 2004/01/29, 99/02/17 */ yyYear = yyvsp[-4].Number; @@ -1184,18 +1173,20 @@ case 25: } } break; -case 26: -#line 224 "getdate.y" +case 24: +#line 239 "getdate.y" { /* ISO 8601 format. yyyy-mm-dd. */ + yyHaveDate++; yyYear = yyvsp[-4].Number; yyMonth = yyvsp[-2].Number; yyDay = yyvsp[0].Number; } break; -case 27: -#line 230 "getdate.y" +case 25: +#line 246 "getdate.y" { + yyHaveDate++; if (yyvsp[-4].Number > 31) { /* e.g. 1992-Jun-17 */ yyYear = yyvsp[-4].Number; @@ -1209,105 +1200,117 @@ case 27: } } break; -case 28: -#line 243 "getdate.y" +case 26: +#line 260 "getdate.y" { /* "May 3" */ + yyHaveDate++; yyMonth = yyvsp[-1].Number; yyDay = yyvsp[0].Number; } break; -case 29: -#line 248 "getdate.y" +case 27: +#line 266 "getdate.y" { /* "June 17, 2001" */ + yyHaveDate++; yyMonth = yyvsp[-3].Number; yyDay = yyvsp[-2].Number; yyYear = yyvsp[0].Number; } break; -case 30: -#line 254 "getdate.y" +case 28: +#line 273 "getdate.y" { /* "12 Sept" */ + yyHaveDate++; yyDay = yyvsp[-1].Number; yyMonth = yyvsp[0].Number; } break; -case 31: -#line 259 "getdate.y" +case 29: +#line 279 "getdate.y" { /* "12 Sept 1997" */ + yyHaveDate++; yyDay = yyvsp[-2].Number; yyMonth = yyvsp[-1].Number; yyYear = yyvsp[0].Number; } break; -case 32: -#line 267 "getdate.y" +case 30: +#line 288 "getdate.y" { yyRelSeconds = -yyRelSeconds; yyRelMonth = -yyRelMonth; } break; -case 34: -#line 274 "getdate.y" +case 32: +#line 295 "getdate.y" { /* "-3 hours" */ + yyHaveRel++; yyRelSeconds -= yyvsp[-1].Number * yyvsp[0].Number; } break; -case 35: -#line 278 "getdate.y" +case 33: +#line 300 "getdate.y" { /* "+1 minute" */ + yyHaveRel++; yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; } break; -case 36: -#line 282 "getdate.y" +case 34: +#line 305 "getdate.y" { /* "1 day" */ + yyHaveRel++; yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; } break; -case 37: -#line 286 "getdate.y" +case 35: +#line 310 "getdate.y" { /* "hour" */ + yyHaveRel++; yyRelSeconds += yyvsp[0].Number; } break; -case 38: -#line 290 "getdate.y" +case 36: +#line 315 "getdate.y" { /* "-3 months" */ + yyHaveRel++; yyRelMonth -= yyvsp[-1].Number * yyvsp[0].Number; } break; -case 39: -#line 294 "getdate.y" +case 37: +#line 320 "getdate.y" { /* "+5 years" */ + yyHaveRel++; yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; } break; -case 40: -#line 298 "getdate.y" +case 38: +#line 325 "getdate.y" { /* "2 years" */ + yyHaveRel++; yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; } break; -case 41: -#line 302 "getdate.y" +case 39: +#line 330 "getdate.y" { /* "6 months" */ + yyHaveRel++; yyRelMonth += yyvsp[0].Number; } break; -case 42: -#line 308 "getdate.y" +case 40: +#line 337 "getdate.y" { if (yyHaveTime && yyHaveDate && !yyHaveRel) yyYear = yyvsp[0].Number; @@ -1335,7 +1338,7 @@ case 42: } } break; -#line 1339 "getdate.c" +#line 1342 "getdate.c" } yyssp -= yym; yystate = *yyssp; diff --git a/tar/getdate.h b/tar/getdate.h index 77c24f1e2..85dcde54f 100644 --- a/tar/getdate.h +++ b/tar/getdate.h @@ -5,14 +5,13 @@ #define tAGO 257 #define tDAY 258 #define tDAYZONE 259 -#define tAM 260 -#define tPM 261 -#define tMONTH 262 -#define tMONTH_UNIT 263 -#define tSEC_UNIT 264 -#define tUNUMBER 265 -#define tZONE 266 -#define tDST 267 +#define tAMPM 260 +#define tMONTH 261 +#define tMONTH_UNIT 262 +#define tSEC_UNIT 263 +#define tUNUMBER 264 +#define tZONE 265 +#define tDST 266 typedef union { time_t Number; } YYSTYPE; diff --git a/tar/getdate.y b/tar/getdate.y index 4522c4f3a..c748992ff 100644 --- a/tar/getdate.y +++ b/tar/getdate.y @@ -62,6 +62,11 @@ typedef enum _DSTMODE { DSTon, DSToff, DSTmaybe } DSTMODE; +/* +** Meridian: am or pm. +*/ +enum { tAM, tPM }; + /* ** Global variables. We could get rid of most of these by using a good ** union as the yacc stack. (This routine was originally written before @@ -88,68 +93,70 @@ static time_t yyYear; static time_t yyRelMonth; static time_t yyRelSeconds; +/* +struct token { int token, time_t value }; +static struct token tokens[256]; +struct token *tokenp; +*/ + %} %union { time_t Number; } -%token tAGO tDAY tDAYZONE tAM tPM tMONTH tMONTH_UNIT tSEC_UNIT tUNUMBER +%token tAGO tDAY tDAYZONE tAMPM tMONTH tMONTH_UNIT tSEC_UNIT tUNUMBER %token tZONE tDST %type tDAY tDAYZONE tMONTH tMONTH_UNIT -%type tSEC_UNIT tUNUMBER tZONE +%type tSEC_UNIT tUNUMBER tZONE tAMPM %% spec : /* NULL */ - | spec item + | spec phrase ; -item : time { yyHaveTime++; } - | zone { yyHaveZone++; } - | date { yyHaveDate++; } - | day { yyHaveDay++; } - | rel { yyHaveRel++; } +phrase : time + | zone + | date + | day + | rel | number ; -time : tUNUMBER tAM { +time : tUNUMBER tAMPM { /* "7am" */ + yyHaveTime++; yyHour = $1; - yyMinutes = 0; - yySeconds = 0; if (yyHour == 12) yyHour = 0; - } - | tUNUMBER tPM { - /* "7pm" */ - yyHour = $1; yyMinutes = 0; yySeconds = 0; - if (yyHour < 12) + if ($2 == tPM) yyHour += 12; } | bare_time { /* "7:12:18" "19:17" */ + yyHaveTime++; } - | bare_time tAM { - /* "12:20:13am" */ + | bare_time tAMPM { + /* "7:12pm", "12:20:13am" */ + yyHaveTime++; if (yyHour == 12) yyHour = 0; - } - | bare_time tPM { - /* "7:12pm" */ - if (yyHour < 12) + if ($2 == tPM) yyHour += 12; } | bare_time '+' tUNUMBER { /* "7:14+0700" */ + yyHaveTime++; yyDSTmode = DSToff; yyTimezone = - ($3 % 100 + ($3 / 100) * 60); } | bare_time '-' tUNUMBER { /* "19:14:12-0530" */ + yyHaveTime++; yyDSTmode = DSToff; yyTimezone = + ($3 % 100 + ($3 / 100) * 60); } @@ -168,30 +175,36 @@ bare_time : tUNUMBER ':' tUNUMBER { ; zone : tZONE { + yyHaveZone++; yyTimezone = $1; yyDSTmode = DSToff; } | tDAYZONE { + yyHaveZone++; yyTimezone = $1; yyDSTmode = DSTon; } | tZONE tDST { + yyHaveZone++; yyTimezone = $1; yyDSTmode = DSTon; } ; day : tDAY { + yyHaveDay++; yyDayOrdinal = 1; yyDayNumber = $1; } | tDAY ',' { /* "tue," "wednesday," */ + yyHaveDay++; yyDayOrdinal = 1; yyDayNumber = $1; } | tUNUMBER tDAY { /* "second tues" "3 wed" */ + yyHaveDay++; yyDayOrdinal = $1; yyDayNumber = $2; } @@ -199,10 +212,12 @@ day : tDAY { date : tUNUMBER '/' tUNUMBER { /* "1/15" */ + yyHaveDate++; yyMonth = $1; yyDay = $3; } | tUNUMBER '/' tUNUMBER '/' tUNUMBER { + yyHaveDate++; if ($1 >= 13) { /* First number is big: 2004/01/29, 99/02/17 */ yyYear = $1; @@ -223,11 +238,13 @@ date : tUNUMBER '/' tUNUMBER { } | tUNUMBER '-' tUNUMBER '-' tUNUMBER { /* ISO 8601 format. yyyy-mm-dd. */ + yyHaveDate++; yyYear = $1; yyMonth = $3; yyDay = $5; } | tUNUMBER '-' tMONTH '-' tUNUMBER { + yyHaveDate++; if ($1 > 31) { /* e.g. 1992-Jun-17 */ yyYear = $1; @@ -242,22 +259,26 @@ date : tUNUMBER '/' tUNUMBER { } | tMONTH tUNUMBER { /* "May 3" */ + yyHaveDate++; yyMonth = $1; yyDay = $2; } | tMONTH tUNUMBER ',' tUNUMBER { /* "June 17, 2001" */ + yyHaveDate++; yyMonth = $1; yyDay = $2; yyYear = $4; } | tUNUMBER tMONTH { /* "12 Sept" */ + yyHaveDate++; yyDay = $1; yyMonth = $2; } | tUNUMBER tMONTH tUNUMBER { /* "12 Sept 1997" */ + yyHaveDate++; yyDay = $1; yyMonth = $2; yyYear = $3; @@ -273,34 +294,42 @@ rel : relunit tAGO { relunit : '-' tUNUMBER tSEC_UNIT { /* "-3 hours" */ + yyHaveRel++; yyRelSeconds -= $2 * $3; } | '+' tUNUMBER tSEC_UNIT { /* "+1 minute" */ + yyHaveRel++; yyRelSeconds += $2 * $3; } | tUNUMBER tSEC_UNIT { /* "1 day" */ + yyHaveRel++; yyRelSeconds += $1 * $2; } | tSEC_UNIT { /* "hour" */ + yyHaveRel++; yyRelSeconds += $1; } | '-' tUNUMBER tMONTH_UNIT { /* "-3 months" */ + yyHaveRel++; yyRelMonth -= $2 * $3; } | '+' tUNUMBER tMONTH_UNIT { /* "+5 years" */ + yyHaveRel++; yyRelMonth += $2 * $3; } | tUNUMBER tMONTH_UNIT { /* "2 years" */ + yyHaveRel++; yyRelMonth += $1 * $2; } | tMONTH_UNIT { /* "6 months" */ + yyHaveRel++; yyRelMonth += $1; } ; @@ -336,15 +365,15 @@ number : tUNUMBER { %% -static struct TABLE { +static struct LEXICON { size_t abbrev; const char *name; int type; time_t value; } const TimeWords[] = { /* am/pm */ - { 0, "am", tAM, 0 }, - { 0, "pm", tPM, 0 }, + { 0, "am", tAMPM, tAM }, + { 0, "pm", tAMPM, tPM }, /* Month names. */ { 3, "january", tMONTH, 1 }, @@ -615,20 +644,20 @@ RelativeMonth(time_t Start, time_t RelMonth) } static int -yylex(void) +nexttoken(char **in, time_t *value) { char c; char buff[64]; for ( ; ; ) { - while (isspace((unsigned char)*yyInput)) - yyInput++; + while (isspace((unsigned char)**in)) + ++*in; /* Skip parenthesized comments. */ - if (*yyInput == '(') { + if (**in == '(') { int Count = 0; do { - c = *yyInput++; + c = *(*in)++; if (c == '\0') return c; if (c == '(') @@ -642,8 +671,8 @@ yylex(void) /* Try the next token in the word table first. */ /* This allows us to match "2nd", for example. */ { - char *src = yyInput; - const struct TABLE *tp; + char *src = *in; + const struct LEXICON *tp; unsigned i = 0; /* Force to lowercase and strip '.' characters. */ @@ -673,9 +702,9 @@ yylex(void) && strncmp(tp->name, buff, strlen(buff)) == 0) { /* Skip over token. */ - yyInput = src; + *in = src; /* Return the match. */ - yylval.Number = tp->value; + *value = tp->value; return tp->type; } } @@ -686,17 +715,23 @@ yylex(void) * Because '-' and '+' have other special meanings, I * don't deal with signed numbers here. */ - if (isdigit((unsigned char)(c = *yyInput))) { - for (yylval.Number = 0; isdigit((unsigned char)(c = *yyInput++)); ) - yylval.Number = 10 * yylval.Number + c - '0'; - yyInput--; + if (isdigit((unsigned char)(c = **in))) { + for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); ) + *value = 10 * *value + c - '0'; + (*in)--; return (tUNUMBER); } - return (*yyInput++); + return *(*in)++; } } +static int +yylex(void) +{ + return nexttoken(&yyInput, &yylval.Number); +} + #define TM_YEAR_ORIGIN 1900 /* Yield A - B, measured in seconds. */ @@ -768,8 +803,10 @@ get_date(char *p) yyHaveTime = 0; yyHaveZone = 0; - if (yyparse() - || yyHaveTime > 1 || yyHaveZone > 1 + if (yyparse()) + return -1; + + if (yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1) return -1;