Update from GNU libc.
[gnulib.git] / lib / getdate.y
index ce11905..6988604 100644 (file)
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
+
+#ifdef FORCE_ALLOCA_H
+#include <alloca.h>
+#endif
 #endif
 
 /* Since the code of getdate.y is not included in the Emacs executable
 #include <stdio.h>
 #include <ctype.h>
 
+#if defined (STDC_HEADERS) || !defined (isascii)
+# define ISASCII(c) 1
+#else
+# define ISASCII(c) isascii(c)
+#endif
+
+#define ISSPACE(c) (ISASCII (c) && isspace (c))
+#define ISALPHA(c) (ISASCII (c) && isalpha (c))
+#define ISUPPER(c) (ISASCII (c) && isupper (c))
+#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+
 #if    defined (vms)
 #include <types.h>
 #include <time.h>
@@ -82,14 +97,58 @@ struct timeb
 extern struct tm       *gmtime ();
 extern struct tm       *localtime ();
 
-#define yyparse getdate_yyparse
-#define yylex getdate_yylex
-#define yyerror getdate_yyerror
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+   as well as gratuitiously global symbol names, so we can have multiple
+   yacc generated parsers in the same program.  Note that these are only
+   the variables produced by yacc.  If other parser generators (bison,
+   byacc, etc) produce additional global names that conflict at link time,
+   then those parser generators need to be fixed instead of adding those
+   names to this list. */
+
+#define yymaxdepth gd_maxdepth
+#define yyparse gd_parse
+#define yylex   gd_lex
+#define yyerror gd_error
+#define yylval  gd_lval
+#define yychar  gd_char
+#define yydebug gd_debug
+#define yypact  gd_pact
+#define yyr1    gd_r1
+#define yyr2    gd_r2
+#define yydef   gd_def
+#define yychk   gd_chk
+#define yypgo   gd_pgo
+#define yyact   gd_act
+#define yyexca  gd_exca
+#define yyerrflag gd_errflag
+#define yynerrs gd_nerrs
+#define yyps    gd_ps
+#define yypv    gd_pv
+#define yys     gd_s
+#define yy_yys  gd_yys
+#define yystate gd_state
+#define yytmp   gd_tmp
+#define yyv     gd_v
+#define yy_yyv  gd_yyv
+#define yyval   gd_val
+#define yylloc  gd_lloc
+#define yyreds  gd_reds          /* With YYDEBUG defined */
+#define yytoks  gd_toks          /* With YYDEBUG defined */
+#define yylhs   gd_yylhs
+#define yylen   gd_yylen
+#define yydefred gd_yydefred
+#define yydgoto gd_yydgoto
+#define yysindex gd_yysindex
+#define yyrindex gd_yyrindex
+#define yygindex gd_yygindex
+#define yytable  gd_yytable
+#define yycheck  gd_yycheck
 
 static int yylex ();
 static int yyerror ();
 
 #define EPOCH          1970
+#define DOOMSDAY       2038
 #define HOUR(x)                ((time_t)(x) * 60)
 #define SECSPERDAY     (24L * 60L * 60L)
 
@@ -242,7 +301,7 @@ day : tDAY {
            yyDayOrdinal = 1;
            yyDayNumber = $1;
        }
-       | tUNUMBER tDAY { /* FIXME */
+       | tUNUMBER tDAY {
            yyDayOrdinal = $1;
            yyDayNumber = $2;
        }
@@ -279,7 +338,6 @@ date        : tUNUMBER '/' tUNUMBER {
            yyYear = $4;
        }
        | tUNUMBER tMONTH {
-           /* FIXME: `date -d 'next october'' is interpreted as 2 october.  */
            yyMonth = $2;
            yyDay = $1;
        }
@@ -315,10 +373,10 @@ relunit   : tUNUMBER tMINUTE_UNIT {
        | tSEC_UNIT {
            yyRelSeconds++;
        }
-       | tSNUMBER tMONTH_UNIT { /* FIXME */
+       | tSNUMBER tMONTH_UNIT {
            yyRelMonth += $1 * $2;
        }
-       | tUNUMBER tMONTH_UNIT { /* FIXME */
+       | tUNUMBER tMONTH_UNIT {
            yyRelMonth += $1 * $2;
        }
        | tMONTH_UNIT {
@@ -613,11 +671,13 @@ Convert (Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
 
   if (Year < 0)
     Year = -Year;
-  if (Year < 100)
+  if (Year < DOOMSDAY-2000)
+    Year += 2000;
+  else if (Year < 100)
     Year += 1900;
   DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
     ? 29 : 28;
-  if (Year < EPOCH || Year > 2037
+  if (Year < EPOCH || Year >= DOOMSDAY
       || Month < 1 || Month > 12
       /* Lint fluff:  "conversion from long may lose accuracy" */
       || Day < 1 || Day > DaysInMonth[(int)--Month])
@@ -682,7 +742,7 @@ RelativeMonth (Start, RelMonth)
   if (RelMonth == 0)
     return 0;
   tm = localtime (&Start);
-  Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
+  Month = 12 * (1900 + tm->tm_year) + tm->tm_mon + RelMonth;
   Year = Month / 12;
   Month = Month % 12 + 1;
   return DSTcorrect (Start,
@@ -704,7 +764,7 @@ LookupWord (buff)
 
   /* Make it lowercase. */
   for (p = buff; *p; p++)
-    if (isupper (*p))
+    if (ISUPPER (*p))
       *p = tolower (*p);
 
   if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) {
@@ -745,7 +805,7 @@ LookupWord (buff)
       return tp->type;
     }
 
-  if (strcmp (buff, "dst") == 0) 
+  if (strcmp (buff, "dst") == 0)
     return tDST;
 
   for (tp = UnitsTable; tp->name; tp++)
@@ -773,7 +833,7 @@ LookupWord (buff)
     }
 
   /* Military timezones. */
-  if (buff[1] == '\0' && isalpha (*buff)) {
+  if (buff[1] == '\0' && ISALPHA (*buff)) {
     for (tp = MilitaryTable; tp->name; tp++)
       if (strcmp (buff, tp->name) == 0) {
        yylval.Number = tp->value;
@@ -809,27 +869,27 @@ yylex ()
   int                  sign;
 
   for ( ; ; ) {
-    while (isspace (*yyInput))
+    while (ISSPACE (*yyInput))
       yyInput++;
 
-    if (isdigit (c = *yyInput) || c == '-' || c == '+') {
+    if (ISDIGIT (c = *yyInput) || c == '-' || c == '+') {
       if (c == '-' || c == '+') {
        sign = c == '-' ? -1 : 1;
-       if (!isdigit (*++yyInput))
+       if (!ISDIGIT (*++yyInput))
          /* skip the '-' sign */
          continue;
       }
       else
        sign = 0;
-      for (yylval.Number = 0; isdigit (c = *yyInput++); )
+      for (yylval.Number = 0; ISDIGIT (c = *yyInput++); )
        yylval.Number = 10 * yylval.Number + c - '0';
       yyInput--;
       if (sign < 0)
        yylval.Number = -yylval.Number;
       return sign ? tSNUMBER : tUNUMBER;
     }
-    if (isalpha (c)) {
-      for (p = buff; isalpha (c = *yyInput++) || c == '.'; )
+    if (ISALPHA (c)) {
+      for (p = buff; ISALPHA (c = *yyInput++) || c == '.'; )
        if (p < &buff[sizeof buff - 1])
          *p++ = c;
       *p = '\0';
@@ -896,7 +956,7 @@ get_date (p, now)
 
     if (! (tm = localtime (&ftz.time)))
       return -1;
-       
+
     ftz.timezone = difftm (&gmt, tm) / 60;
     if (tm->tm_isdst)
       ftz.timezone += 60;