** 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@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
-** send any email to Rich.
-**
-** This grammar has 10 shift/reduce conflicts.
+** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
**
** This code is in the public domain and has no copyright.
*/
-/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
-/* SUPPRESS 288 on yyerrlab *//* Label unused */
#ifdef HAVE_CONFIG_H
-#include <config.h>
-
-#ifdef FORCE_ALLOCA_H
-#include <alloca.h>
-#endif
+# 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
problems if we try to write to a static variable, which I don't
think this code needs to do. */
#ifdef emacs
-#undef static
+# undef static
#endif
#include <stdio.h>
host does not conform to Posix. */
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
-#if defined (vms)
-#include <types.h>
-#include <time.h>
-#else
-#include <sys/types.h>
-#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
+#if defined (STDC_HEADERS) || defined (USG)
+# include <string.h>
#endif
+
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __attribute__(x)
#endif
-#endif /* defined (vms) */
-#if defined (STDC_HEADERS) || defined (USG)
-#include <string.h>
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#endif
/* Some old versions of bison generate parsers that use bcopy.
That loses on systems that don't provide the function, so we have
to redefine it here. */
#if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
-#define bcopy(from, to, len) memcpy ((to), (from), (len))
+# define bcopy(from, to, len) memcpy ((to), (from), (len))
#endif
-extern struct tm *gmtime ();
-extern struct tm *localtime ();
-extern time_t mktime ();
-
/* 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
** yacc had the %union construct.) Maybe someday; right now we only use
** the %union very rarely.
*/
-static char *yyInput;
+static const char *yyInput;
static int yyDayOrdinal;
static int yyDayNumber;
static int yyHaveDate;
%}
+/* This grammar has 13 shift/reduce conflicts. */
+%expect 13
+
%union {
int Number;
enum _MERIDIAN Meridian;
yyRelYear += $1 * $2;
}
| tYEAR_UNIT {
- yyRelYear++;
+ yyRelYear += $1;
}
| tUNUMBER tMONTH_UNIT {
yyRelMonth += $1 * $2;
yyRelMonth += $1 * $2;
}
| tMONTH_UNIT {
- yyRelMonth++;
+ yyRelMonth += $1;
}
| tUNUMBER tDAY_UNIT {
yyRelDay += $1 * $2;
yyRelDay += $1 * $2;
}
| tDAY_UNIT {
- yyRelDay++;
+ yyRelDay += $1;
}
| tUNUMBER tHOUR_UNIT {
yyRelHour += $1 * $2;
yyRelHour += $1 * $2;
}
| tHOUR_UNIT {
- yyRelHour++;
+ yyRelHour += $1;
}
| tUNUMBER tMINUTE_UNIT {
yyRelMinutes += $1 * $2;
yyRelMinutes += $1 * $2;
}
| tMINUTE_UNIT {
- yyRelMinutes++;
+ yyRelMinutes += $1;
}
| tUNUMBER tSEC_UNIT {
yyRelSeconds += $1 * $2;
yyRelSeconds += $1 * $2;
}
| tSEC_UNIT {
- yyRelSeconds++;
+ yyRelSeconds += $1;
}
;
-number : tUNUMBER {
+number : tUNUMBER
+ {
if (yyHaveTime && yyHaveDate && !yyHaveRel)
- yyYear = $1;
- else {
- if ($1>10000) {
+ yyYear = $1;
+ else
+ {
+ if ($1>10000)
+ {
yyHaveDate++;
yyDay= ($1)%100;
yyMonth= ($1/100)%100;
yyYear = $1/10000;
- }
- else {
+ }
+ else
+ {
yyHaveTime++;
- if ($1 < 100) {
+ if ($1 < 100)
+ {
yyHour = $1;
yyMinutes = 0;
- }
- else {
+ }
+ else
+ {
yyHour = $1 / 100;
yyMinutes = $1 % 100;
- }
+ }
yySeconds = 0;
yyMeridian = MER24;
- }
- }
- }
+ }
+ }
+ }
;
-o_merid : /* NULL */ {
+o_merid : /* NULL */
+ {
$$ = MER24;
- }
- | tMERIDIAN {
+ }
+ | tMERIDIAN
+ {
$$ = $1;
- }
+ }
;
%%
+/* Include this file down here because bison inserts code above which
+ may define-away `const'. We want the prototype for get_date to have
+ the same signature as the function definition does. */
+#include "getdate.h"
+
+extern struct tm *gmtime ();
+extern struct tm *localtime ();
+extern time_t mktime ();
+
/* Month and day table. */
static TABLE const MonthDayTable[] = {
{ "january", tMONTH, 1 },
{ "thurs", tDAY, 4 },
{ "friday", tDAY, 5 },
{ "saturday", tDAY, 6 },
- { NULL }
+ { NULL, 0, 0 }
};
/* Time units table. */
{ "min", tMINUTE_UNIT, 1 },
{ "second", tSEC_UNIT, 1 },
{ "sec", tSEC_UNIT, 1 },
- { NULL }
+ { NULL, 0, 0 }
};
/* Assorted relative-time words. */
{ "now", tMINUTE_UNIT, 0 },
{ "last", tUNUMBER, -1 },
{ "this", tMINUTE_UNIT, 0 },
- { "next", tUNUMBER, 2 },
+ { "next", tUNUMBER, 1 },
{ "first", tUNUMBER, 1 },
/* { "second", tUNUMBER, 2 }, */
{ "third", tUNUMBER, 3 },
{ "eleventh", tUNUMBER, 11 },
{ "twelfth", tUNUMBER, 12 },
{ "ago", tAGO, 1 },
- { NULL }
+ { NULL, 0, 0 }
};
/* The timezone table. */
{ "nzst", tZONE, -HOUR (12) }, /* New Zealand Standard */
{ "nzdt", tDAYZONE, -HOUR (12) }, /* New Zealand Daylight */
{ "idle", tZONE, -HOUR (12) }, /* International Date Line East */
- { NULL }
+ { NULL, 0, 0 }
};
/* Military timezone table. */
{ "x", tZONE, HOUR (-11) },
{ "y", tZONE, HOUR (-12) },
{ "z", tZONE, HOUR ( 0) },
- { NULL }
+ { NULL, 0, 0 }
};
\f
/* ARGSUSED */
static int
yyerror (s)
- char *s;
+ char *s ATTRIBUTE_UNUSED;
{
return 0;
}
-
static int
ToHour (Hours, Meridian)
- int Hours;
- MERIDIAN Meridian;
+ int Hours;
+ MERIDIAN Meridian;
{
- switch (Meridian) {
- case MER24:
- if (Hours < 0 || Hours > 23)
- return -1;
- return Hours;
- case MERam:
- if (Hours < 1 || Hours > 12)
- return -1;
- if (Hours == 12)
- Hours = 0;
- return Hours;
- case MERpm:
- if (Hours < 1 || Hours > 12)
- return -1;
- if (Hours == 12)
- Hours = 0;
- return Hours + 12;
- default:
- abort ();
- }
+ switch (Meridian)
+ {
+ case MER24:
+ if (Hours < 0 || Hours > 23)
+ return -1;
+ return Hours;
+ case MERam:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ if (Hours == 12)
+ Hours = 0;
+ return Hours;
+ case MERpm:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ if (Hours == 12)
+ Hours = 0;
+ return Hours + 12;
+ default:
+ abort ();
+ }
/* NOTREACHED */
}
-
static int
ToYear (Year)
- int Year;
+ int Year;
{
if (Year < 0)
Year = -Year;
return Year;
}
-
static int
LookupWord (buff)
- char *buff;
+ char *buff;
{
- register char *p;
- register char *q;
- register const TABLE *tp;
- int i;
- int abbrev;
+ register char *p;
+ register char *q;
+ register const TABLE *tp;
+ int i;
+ int abbrev;
/* Make it lowercase. */
for (p = buff; *p; p++)
if (ISUPPER (*p))
*p = tolower (*p);
- if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) {
- yylval.Meridian = MERam;
- return tMERIDIAN;
- }
- if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0) {
- yylval.Meridian = MERpm;
- return tMERIDIAN;
- }
+ if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0)
+ {
+ yylval.Meridian = MERam;
+ return tMERIDIAN;
+ }
+ if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0)
+ {
+ yylval.Meridian = MERpm;
+ return tMERIDIAN;
+ }
/* See if we have an abbreviation for a month. */
if (strlen (buff) == 3)
abbrev = 1;
- else if (strlen (buff) == 4 && buff[3] == '.') {
- abbrev = 1;
- buff[3] = '\0';
- }
+ else if (strlen (buff) == 4 && buff[3] == '.')
+ {
+ abbrev = 1;
+ buff[3] = '\0';
+ }
else
abbrev = 0;
- for (tp = MonthDayTable; tp->name; tp++) {
- if (abbrev) {
- if (strncmp (buff, tp->name, 3) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
- }
- else if (strcmp (buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
+ for (tp = MonthDayTable; tp->name; tp++)
+ {
+ if (abbrev)
+ {
+ if (strncmp (buff, tp->name, 3) == 0)
+ {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+ else if (strcmp (buff, tp->name) == 0)
+ {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
}
- }
for (tp = TimezoneTable; tp->name; tp++)
- if (strcmp (buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
+ if (strcmp (buff, tp->name) == 0)
+ {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
if (strcmp (buff, "dst") == 0)
return tDST;
for (tp = UnitsTable; tp->name; tp++)
- if (strcmp (buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
-
- /* Strip off any plural and try the units table again. */
- i = strlen (buff) - 1;
- if (buff[i] == 's') {
- buff[i] = '\0';
- for (tp = UnitsTable; tp->name; tp++)
- if (strcmp (buff, tp->name) == 0) {
+ if (strcmp (buff, tp->name) == 0)
+ {
yylval.Number = tp->value;
return tp->type;
}
- buff[i] = 's'; /* Put back for "this" in OtherTable. */
- }
- for (tp = OtherTable; tp->name; tp++)
- if (strcmp (buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
+ /* Strip off any plural and try the units table again. */
+ i = strlen (buff) - 1;
+ if (buff[i] == 's')
+ {
+ buff[i] = '\0';
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp (buff, tp->name) == 0)
+ {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ buff[i] = 's'; /* Put back for "this" in OtherTable. */
}
- /* Military timezones. */
- if (buff[1] == '\0' && ISALPHA (*buff)) {
- for (tp = MilitaryTable; tp->name; tp++)
- if (strcmp (buff, tp->name) == 0) {
+ for (tp = OtherTable; tp->name; tp++)
+ if (strcmp (buff, tp->name) == 0)
+ {
yylval.Number = tp->value;
return tp->type;
}
- }
+
+ /* Military timezones. */
+ if (buff[1] == '\0' && ISALPHA (*buff))
+ {
+ for (tp = MilitaryTable; tp->name; tp++)
+ if (strcmp (buff, tp->name) == 0)
+ {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
/* Drop out any periods and try the timezone table again. */
for (i = 0, p = q = buff; *q; q++)
*p = '\0';
if (i)
for (tp = TimezoneTable; tp->name; tp++)
- if (strcmp (buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
+ if (strcmp (buff, tp->name) == 0)
+ {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
return tID;
}
-
static int
yylex ()
{
- register char c;
- register char *p;
- char buff[20];
- int Count;
- int sign;
-
- for ( ; ; ) {
- while (ISSPACE (*yyInput))
- yyInput++;
-
- if (ISDIGIT (c = *yyInput) || c == '-' || c == '+') {
- if (c == '-' || c == '+') {
- sign = c == '-' ? -1 : 1;
- if (!ISDIGIT (*++yyInput))
- /* skip the '-' sign */
- continue;
- }
- else
- sign = 0;
- 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; (c = *yyInput++, ISALPHA (c)) || c == '.'; )
- if (p < &buff[sizeof buff - 1])
- *p++ = c;
- *p = '\0';
- yyInput--;
- return LookupWord (buff);
+ register char c;
+ register char *p;
+ char buff[20];
+ int Count;
+ int sign;
+
+ for (;;)
+ {
+ while (ISSPACE (*yyInput))
+ yyInput++;
+
+ if (ISDIGIT (c = *yyInput) || c == '-' || c == '+')
+ {
+ if (c == '-' || c == '+')
+ {
+ sign = c == '-' ? -1 : 1;
+ if (!ISDIGIT (*++yyInput))
+ /* skip the '-' sign */
+ continue;
+ }
+ else
+ sign = 0;
+ 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; (c = *yyInput++, ISALPHA (c)) || c == '.';)
+ if (p < &buff[sizeof buff - 1])
+ *p++ = c;
+ *p = '\0';
+ yyInput--;
+ return LookupWord (buff);
+ }
+ if (c != '(')
+ return *yyInput++;
+ Count = 0;
+ do
+ {
+ c = *yyInput++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ Count++;
+ else if (c == ')')
+ Count--;
+ }
+ while (Count > 0);
}
- if (c != '(')
- return *yyInput++;
- Count = 0;
- do {
- c = *yyInput++;
- if (c == '\0')
- return c;
- if (c == '(')
- Count++;
- else if (c == ')')
- Count--;
- } while (Count > 0);
- }
}
#define TM_YEAR_ORIGIN 1900
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
long days = (
- /* difference in day of year */
- a->tm_yday - b->tm_yday
- /* + intervening leap days */
- + ((ay >> 2) - (by >> 2))
- - (ay/100 - by/100)
- + ((ay/100 >> 2) - (by/100 >> 2))
- /* + difference in years * 365 */
- + (long)(ay-by) * 365
- );
- return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
- + (a->tm_min - b->tm_min))
+ /* difference in day of year */
+ a->tm_yday - b->tm_yday
+ /* + intervening leap days */
+ + ((ay >> 2) - (by >> 2))
+ - (ay / 100 - by / 100)
+ + ((ay / 100 >> 2) - (by / 100 >> 2))
+ /* + difference in years * 365 */
+ + (long) (ay - by) * 365
+ );
+ return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ (a->tm_sec - b->tm_sec));
}
time_t
-get_date (p, now)
- char *p;
- time_t *now;
+get_date (const char *p, const time_t *now)
{
- struct tm tm, tm0, *tmp;
- time_t Start;
+ struct tm tm, tm0, *tmp;
+ time_t Start;
yyInput = p;
Start = now ? *now : time ((time_t *) NULL);
tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear;
tm.tm_mon = yyMonth - 1 + yyRelMonth;
tm.tm_mday = yyDay + yyRelDay;
- if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay)) {
- tm.tm_hour = ToHour (yyHour, yyMeridian);
- if (tm.tm_hour < 0)
- return -1;
- tm.tm_min = yyMinutes;
- tm.tm_sec = yySeconds;
- } else {
- tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
- }
+ if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay))
+ {
+ tm.tm_hour = ToHour (yyHour, yyMeridian);
+ if (tm.tm_hour < 0)
+ return -1;
+ tm.tm_min = yyMinutes;
+ tm.tm_sec = yySeconds;
+ }
+ else
+ {
+ tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
+ }
tm.tm_hour += yyRelHour;
tm.tm_min += yyRelMinutes;
tm.tm_sec += yyRelSeconds;
Start = mktime (&tm);
- if (Start == (time_t) -1) {
-
- /* Guard against falsely reporting errors near the time_t boundaries
- when parsing times in other time zones. For example, if the min
- time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
- of UTC, then the min localtime value is 1970-01-01 08:00:00; if
- we apply mktime to 1970-01-01 00:00:00 we will get an error, so
- we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
- zone by 24 hours to compensate. This algorithm assumes that
- there is no DST transition within a day of the time_t boundaries. */
- if (yyHaveZone) {
- tm = tm0;
- if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN) {
- tm.tm_mday++;
- yyTimezone -= 24 * 60;
- } else {
- tm.tm_mday--;
- yyTimezone += 24 * 60;
- }
+ if (Start == (time_t) -1)
+ {
+
+ /* Guard against falsely reporting errors near the time_t boundaries
+ when parsing times in other time zones. For example, if the min
+ time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
+ of UTC, then the min localtime value is 1970-01-01 08:00:00; if
+ we apply mktime to 1970-01-01 00:00:00 we will get an error, so
+ we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
+ zone by 24 hours to compensate. This algorithm assumes that
+ there is no DST transition within a day of the time_t boundaries. */
+ if (yyHaveZone)
+ {
+ tm = tm0;
+ if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN)
+ {
+ tm.tm_mday++;
+ yyTimezone -= 24 * 60;
+ }
+ else
+ {
+ tm.tm_mday--;
+ yyTimezone += 24 * 60;
+ }
+ Start = mktime (&tm);
+ }
+
+ if (Start == (time_t) -1)
+ return Start;
+ }
+
+ if (yyHaveDay && !yyHaveDate)
+ {
+ tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7
+ + 7 * (yyDayOrdinal - (0 < yyDayOrdinal)));
Start = mktime (&tm);
+ if (Start == (time_t) -1)
+ return Start;
+ }
+
+ if (yyHaveZone)
+ {
+ long delta = yyTimezone * 60L + difftm (&tm, gmtime (&Start));
+ if ((Start + delta < Start) != (delta < 0))
+ return -1; /* time_t overflow */
+ Start += delta;
}
-
- if (Start == (time_t) -1)
- return Start;
- }
-
- if (yyHaveDay && !yyHaveDate) {
- tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7
- + 7 * (yyDayOrdinal - (0 < yyDayOrdinal)));
- Start = mktime (&tm);
- if (Start == (time_t) -1)
- return Start;
- }
-
- if (yyHaveZone) {
- long delta = yyTimezone * 60L + difftm (&tm, gmtime (&Start));
- if ((Start + delta < Start) != (delta < 0))
- return -1; /* time_t overflow */
- Start += delta;
- }
return Start;
}
-
#if defined (TEST)
/* ARGSUSED */
int
main (ac, av)
- int ac;
- char *av[];
+ int ac;
+ char *av[];
{
char buff[MAX_BUFF_LEN + 1];
time_t d;
- (void)printf ("Enter date, or blank line to exit.\n\t> ");
- (void)fflush (stdout);
+ (void) printf ("Enter date, or blank line to exit.\n\t> ");
+ (void) fflush (stdout);
buff[MAX_BUFF_LEN] = 0;
- while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) {
- d = get_date (buff, (time_t *)NULL);
- if (d == -1)
- (void)printf ("Bad format - couldn't convert.\n");
- else
- (void)printf ("%s", ctime (&d));
- (void)printf ("\t> ");
- (void)fflush (stdout);
- }
+ while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
+ {
+ d = get_date (buff, (time_t *) NULL);
+ if (d == -1)
+ (void) printf ("Bad format - couldn't convert.\n");
+ else
+ (void) printf ("%s", ctime (&d));
+ (void) printf ("\t> ");
+ (void) fflush (stdout);
+ }
exit (0);
/* NOTREACHED */
}
-#endif /* defined (TEST) */
+#endif /* defined (TEST) */