--- /dev/null
+--- at-3.1.8.orig/at.c
++++ at-3.1.8/at.c
+@@ -111,7 +111,7 @@
+ static char rcsid[] = "$Id$";
+ char *no_export[] =
+ {
+- "TERM", "DISPLAY", "_", "SHELLOPTS"
++ "TERM", "DISPLAY", "_", "SHELLOPTS", "BASH_VERSINFO", "EUID", "GROUPS", "PPID", "UID"
+ };
+ static int send_mail = 0;
+
+@@ -235,6 +235,7 @@
+ /* Install the signal handler for SIGINT; terminate after removing the
+ * spool file if necessary
+ */
++ memset(&act, 0, sizeof act);
+ act.sa_handler = sigc;
+ sigemptyset(&(act.sa_mask));
+ act.sa_flags = 0;
+@@ -274,8 +275,8 @@
+ if ((jobno = nextjob()) == EOF)
+ perr("Cannot generate job number");
+
+- sprintf(ppos, "%c%5lx%8lx", queue,
+- jobno, (unsigned long) (runtimer / 60));
++ (void)snprintf(ppos, sizeof(atfile) - (ppos - atfile),
++ "%c%5lx%8lx", queue, jobno, (unsigned long) (runtimer / 60));
+
+ for (ap = ppos; *ap != '\0'; ap++)
+ if (*ap == ' ')
+@@ -291,7 +292,7 @@
+ * bit. Yes, this is a kluge.
+ */
+ cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR);
+- if ((fd = creat(atfile, O_WRONLY)) == -1)
++ if ((fd = open(atfile, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR)) == -1)
+ perr("Cannot create atjob file %.500s", atfile);
+
+ if ((fd2 = dup(fd)) < 0)
+@@ -461,14 +462,6 @@
+
+ close(fd2);
+
+- /* POSIX.2 allows the shell specified by the user's SHELL environment
+- variable, the login shell from the user's password database entry,
+- or /bin/sh to be the command interpreter that processes the at-job.
+- It also alows a warning diagnostic to be printed. Because of the
+- possible variance, we always output the diagnostic. */
+-
+- fprintf(stderr, "warning: commands will be executed using /bin/sh\n");
+-
+ runtime = localtime(&runtimer);
+
+ /* We only use the sick POSIX time format if POSIXLY_CORRECT
+@@ -546,6 +539,7 @@
+ long jobno;
+ time_t runtimer;
+ char timestr[TIMESIZE];
++ struct passwd *pwd;
+
+ PRIV_START
+
+@@ -581,7 +575,10 @@
+ } else {
+ strftime(timestr, TIMESIZE, TIMEFORMAT_ISO, runtime);
+ }
+- printf("%ld\t%s %c\n", jobno, timestr, queue);
++ if ((pwd = getpwuid(buf.st_uid)))
++ printf("%ld\t%s %c %s\n", jobno, timestr, queue, pwd->pw_name);
++ else
++ printf("%ld\t%s %c\n", jobno, timestr, queue);
+ }
+ PRIV_END
+ }
+@@ -695,7 +692,7 @@
+ char *pgm;
+
+ int program = AT; /* our default program */
+- char *options = "q:f:mvldVc"; /* default options for at */
++ char *options = "q:f:MmvldhVc"; /* default options for at */
+ int disp_version = 0;
+ time_t timer;
+ struct passwd *pwe;
+@@ -726,16 +723,20 @@
+ */
+ if (strcmp(pgm, "atq") == 0) {
+ program = ATQ;
+- options = "q:V";
++ options = "hq:V";
+ } else if (strcmp(pgm, "atrm") == 0) {
+ program = ATRM;
+- options = "V";
++ options = "hV";
+ }
+ /* process whatever options we can process
+ */
+ opterr = 1;
+ while ((c = getopt(argc, argv, options)) != EOF)
+ switch (c) {
++ case 'h':
++ usage();
++ exit (0);
++
+ case 'v': /* verify time settings */
+ atverify = 1;
+ break;
+@@ -744,6 +745,10 @@
+ send_mail = 1;
+ break;
+
++ case 'M': /* don't send mail, even when job failed */
++ send_mail = -1;
++ break;
++
+ case 'f':
+ atinput = optarg;
+ break;
+@@ -753,7 +758,7 @@
+ usage();
+
+ atqueue = queue = *optarg;
+- if (!(islower(queue) || isupper(queue)))
++ if (!(islower(queue) || isupper(queue)) & (queue != '='))
+ usage();
+
+ queue_set = 1;
+@@ -842,6 +847,15 @@
+ struct tm *tm = localtime(&timer);
+ fprintf(stderr, "%s\n", asctime(tm));
+ }
++
++ /* POSIX.2 allows the shell specified by the user's SHELL environment
++ variable, the login shell from the user's password database entry,
++ or /bin/sh to be the command interpreter that processes the at-job.
++ It also alows a warning diagnostic to be printed. Because of the
++ possible variance, we always output the diagnostic. */
++
++ fprintf(stderr, "warning: commands will be executed using /bin/sh\n");
++
+ writefile(timer, queue);
+ break;
+
+--- at-3.1.8.orig/atd.c
++++ at-3.1.8/atd.c
+@@ -22,6 +22,18 @@
+ #include "config.h"
+ #endif
+
++/*
++ * /usr/bin/mail aka /usr/bin/mailx require the subject to be
++ * specified on the command line instead of reading it from stdin like
++ * /usr/sbin/sendmail does. For now simply disable MAILC and MAILX,
++ *
++ * TODO: Remove tests for MAILC and MAILX from configure.in in the
++ * next upstream version.
++ */
++#undef MAILC
++#undef MAILX
++
++
+ /* System Headers */
+
+ #include <sys/types.h>
+@@ -101,6 +113,8 @@
+ static char rcsid[] = "$Id$";
+ static double load_avg = LOADAVG_MX;
+ static time_t now;
++static time_t last_chg;
++static int nothing_to_do;
+ unsigned int batch_interval;
+ static int run_as_daemon = 0;
+
+@@ -121,6 +135,29 @@
+ return;
+ }
+
++/* SIGCHLD handler - discards completion status of children */
++RETSIGTYPE
++release_zombie(int dummy)
++{
++ int status;
++ pid_t pid;
++
++ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
++#ifdef DEBUG_ZOMBIE
++ if (WIFEXITED(status))
++ syslog(LOG_INFO, "pid %ld exited with status %d.", pid, WEXITSTATUS(status));
++ else if (WIFSIGNALED(status))
++ syslog(LOG_NOTICE, "pid %ld killed with signal %d.", pid, WTERMSIG(status));
++ else if (WIFSTOPPED(status))
++ syslog(LOG_NOTICE, "pid %ld stopped with signal %d.", pid, WSTOPSIG(status));
++ else
++ syslog(LOG_WARNING, "pid %ld unknown reason for SIGCHLD", pid);
++#endif
++ }
++ return;
++}
++
++
+ /* Local functions */
+
+ static int
+@@ -255,6 +292,13 @@
+
+ fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC);
+
++ /*
++ * If the spool directory is mounted via NFS `atd' isn't able to
++ * read from the job file and will bump out here. The file is
++ * opened as "root" but it is read as "daemon" which fails over
++ * NFS and works with local file systems. It's not clear where
++ * the bug is located. -Joey
++ */
+ if (fscanf(stream, "#!/bin/sh\n# atrun uid=%d gid=%d\n# mail %8s %d",
+ &nuid, &ngid, mailbuf, &send_mail) != 4)
+ pabort("File %.500s is in wrong format - aborting",
+@@ -298,6 +342,8 @@
+
+ write_string(fd_out, "Subject: Output from your job ");
+ write_string(fd_out, jobbuf);
++ write_string(fd_out, "\nTo: ");
++ write_string(fd_out, mailname);
+ write_string(fd_out, "\n\n");
+ fstat(fd_out, &buf);
+ size = buf.st_size;
+@@ -359,6 +405,11 @@
+ */
+ close(fd_in);
+ close(fd_out);
++
++ /* We inherited the master's SIGCHLD handler, which does a
++ non-blocking waitpid. So this blocking one will eventually
++ return with an ECHILD error.
++ */
+ waitpid(pid, (int *) NULL, 0);
+
+ /* Send mail. Unlink the output file after opening it, so it
+@@ -376,7 +427,7 @@
+ unlink(newname);
+ free(newname);
+
+- if ((buf.st_size != size) || send_mail) {
++ if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) {
+
+ PRIV_START
+
+@@ -436,34 +487,51 @@
+ * atrun.
+ */
+
+- if ((spool = opendir(".")) == NULL)
+- perr("Cannot read " ATJOB_DIR);
+-
+ next_job = now + CHECK_INTERVAL;
+ if (next_batch == 0)
+ next_batch = now;
+
++ /* To avoid spinning up the disk unnecessarily, stat the directory and
++ * return immediately if it hasn't changed since the last time we woke
++ * up.
++ */
++
++ if (stat(".", &buf) == -1)
++ perr("Cannot stat " ATJOB_DIR);
++
++ if (nothing_to_do && buf.st_mtime <= last_chg)
++ return next_job;
++ last_chg = buf.st_mtime;
++
++ if ((spool = opendir(".")) == NULL)
++ perr("Cannot read " ATJOB_DIR);
++
+ run_batch = 0;
++ nothing_to_do = 1;
+
+ batch_uid = (uid_t) - 1;
+ batch_gid = (gid_t) - 1;
+
+ while ((dirent = readdir(spool)) != NULL) {
+
+- if (stat(dirent->d_name, &buf) != 0) {
+- /* Chances are a '=' file has been deleted from under us.
+- * Ignore.
+- */
+- }
++ /* Avoid the stat if this doesn't look like a job file */
++ if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3)
++ continue;
+
+- /* We don't want directories or files which at(1) hasn't yet
+- * marked executable.
++ /* Chances are a '=' file has been deleted from under us.
++ * Ignore.
+ */
+- if ((!S_ISREG(buf.st_mode)) || !(buf.st_mode & S_IXUSR))
++ if (stat(dirent->d_name, &buf) != 0)
+ continue;
+
+- if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3)
++ if (!S_ISREG(buf.st_mode))
++ continue;
++
++ /* We don't want files which at(1) hasn't yet marked executable. */
++ if (!(buf.st_mode & S_IXUSR)) {
++ nothing_to_do = 0; /* it will probably become executable soon */
+ continue;
++ }
+
+ run_time = (time_t) ctm *60;
+
+@@ -493,9 +561,18 @@
+ lock_name[0] = '=';
+ unlink(lock_name);
+ next_job = now;
++ nothing_to_do = 0;
+ }
+ continue;
+ }
++
++ /* If we got here, then there are jobs of some kind waiting.
++ * We could try to be smarter and leave nothing_to_do set if
++ * we end up processing all the jobs, but that's risky (run_file
++ * might fail and expect the job to be rescheduled), and it doesn't
++ * gain us much. */
++ nothing_to_do = 0;
++
+ /* There's a job for later. Note its execution time if it's
+ * the earlierst so far.
+ */
+@@ -540,6 +617,7 @@
+ }
+ }
+ if (run_batch && (next_batch < next_job)) {
++ nothing_to_do = 0;
+ next_job = next_batch;
+ }
+ return next_job;
+@@ -631,6 +709,11 @@
+ if (optind < argc)
+ pabort("non-option arguments - not allowed");
+
++ sigaction(SIGCHLD, NULL, &act);
++ act.sa_handler = release_zombie;
++ act.sa_flags = SA_NOCLDSTOP;
++ sigaction(SIGCHLD, &act, NULL);
++
+ if (!run_as_daemon) {
+ now = time(NULL);
+ run_loop();
+@@ -646,10 +729,6 @@
+ sigaction(SIGHUP, NULL, &act);
+ act.sa_handler = sdummy;
+ sigaction(SIGHUP, &act, NULL);
+-
+- sigaction(SIGCHLD, NULL, &act);
+- act.sa_handler = SIG_IGN;
+- sigaction(SIGCHLD, &act, NULL);
+
+ sigaction(SIGTERM, NULL, &act);
+ act.sa_handler = set_term;
+--- at-3.1.8.orig/panic.c
++++ at-3.1.8/panic.c
+@@ -41,6 +41,7 @@
+ /* Local headers */
+
+ #include "panic.h"
++#include "privs.h"
+ #include "at.h"
+
+ /* File scope variables */
+@@ -72,12 +73,15 @@
+ va_list args;
+
+ va_start(args, fmt);
+- vsprintf(buf, fmt, args);
++ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ perror(buf);
+- if (fcreated)
++ if (fcreated) {
++ PRIV_START
+ unlink(atfile);
++ PRIV_END
++ }
+
+ exit(EXIT_FAILURE);
+ }
+@@ -88,7 +92,7 @@
+ /* Print usage and exit.
+ */
+ fprintf(stderr, "Usage: at [-V] [-q x] [-f file] [-m] time\n"
+- " atq [-V] [-q x] [-v]\n"
++ " atq [-V] [-q x]\n"
+ " atrm [-V] [-q x] job ...\n"
+ " batch [-V] [-f file] [-m]\n");
+ exit(EXIT_FAILURE);
+--- at-3.1.8.orig/perm.c
++++ at-3.1.8/perm.c
+@@ -43,7 +43,13 @@
+
+ /* Macros */
+
+-#define MAXUSERID 10
++#if defined(DEBUG_PERM_C)
++#define ETCDIR "../test/etc"
++#undef PRIV_START
++#define PRIV_START while(0)
++#undef PRIV_END
++#define PRIV_END while(0)
++#endif
+
+ /* Structures and unions */
+
+@@ -54,66 +60,87 @@
+
+ /* Function declarations */
+
+-static int check_for_user(FILE * fp, const char *name);
++static int user_in_file(const char *path, const char *name);
+
+ /* Local functions */
+
++/*
++ */
+ static int
+-check_for_user(FILE * fp, const char *name)
++user_in_file(const char *path, const char *name)
+ {
+- char *buffer;
+- size_t len;
+- int found = 0;
+-
+- len = strlen(name);
+- buffer = mymalloc(len + 2);
+-
+- while (fgets(buffer, len + 2, fp) != NULL) {
+- if ((strncmp(name, buffer, len) == 0) &&
+- (buffer[len] == '\n')) {
+- found = 1;
+- break;
+- }
+- }
+- fclose(fp);
+- free(buffer);
+- return found;
+-}
+-/* Global functions */
+-int
+-check_permission()
+-{
+- FILE *fp;
+- uid_t uid = geteuid();
+- struct passwd *pentry;
++ FILE *fp;
++ char buffer[256];
++ int found = 0;
++ int c = '\n';
++
++ PRIV_START;
++ fp = fopen( path, "r");
++ PRIV_END;
++
++ if ( fp == NULL )
++ return -1;
++
++
++ while ( !found && fgets(buffer, sizeof(buffer), fp) != NULL) {
++ size_t llen = strlen(buffer);
+
+- if (uid == 0)
+- return 1;
++ c = buffer[llen-1];
+
+- if ((pentry = getpwuid(uid)) == NULL) {
+- perror("Cannot access user database");
+- exit(EXIT_FAILURE);
+- }
+- PRIV_START
++ if (c == '\n')
++ buffer[llen-1] = '\0';
++ while (c != '\n' && c != EOF)
++ c = fgetc(fp);
++
++ found = (strcmp(buffer, name)==0);
++ }
+
+- fp = fopen(ETCDIR "/at.allow", "r");
++ fclose(fp);
+
+- PRIV_END
++ if (c == EOF) {
++ fprintf(stderr, "%s: incomplete last line.\n", path);
++ }
++
++ return found;
++}
+
+- if (fp != NULL) {
+- return check_for_user(fp, pentry->pw_name);
+- } else {
+
+- PRIV_START
++/* Global functions */
++int
++check_permission()
++{
++ uid_t uid = geteuid();
++ struct passwd *pentry;
++ int allow = 0, deny = 1;
++
++ if (uid == 0)
++ return 1;
++
++ if ((pentry = getpwuid(uid)) == NULL) {
++ perror("Cannot access user database");
++ exit(EXIT_FAILURE);
++ }
++
++ allow = user_in_file(ETCDIR "/at.allow", pentry->pw_name);
++ if (allow==0 || allow==1)
++ return allow;
++
++ /* There was an error while looking for pw_name in at.allow.
++ * Check at.deny only when at.allow doesn't exist.
++ */
++
++ deny = user_in_file(ETCDIR "/at.deny", pentry->pw_name);
++ return deny == 0;
++}
+
+- fp = fopen(ETCDIR "/at.deny", "r");
+
+- PRIV_END
++#if defined(DEBUG_PERM_C)
+
+- if (fp != NULL) {
+- return !check_for_user(fp, pentry->pw_name);
+- }
+- perror("at.deny");
+- }
+- return 0;
++int
++main(int argc, char *argv[])
++{
++ printf("check_permission() ==> %d\n", check_permission());
++ return 0;
+ }
++
++#endif
+--- at-3.1.8.orig/daemon.c
++++ at-3.1.8/daemon.c
+@@ -72,7 +72,7 @@
+ va_list args;
+
+ va_start(args, fmt);
+- vsprintf(buf, fmt, args);
++ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ if (daemon_debug) {
+@@ -90,7 +90,7 @@
+ va_list args;
+
+ va_start(args, fmt);
+- vsprintf(buf, fmt, args);
++ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ if (daemon_debug) {
+@@ -127,6 +127,7 @@
+ }
+ }
+ old_umask = umask(S_IWGRP | S_IWOTH);
++ (void) setsid();
+
+ PRIV_START
+
+--- at-3.1.8.orig/y.tab.c
++++ at-3.1.8/y.tab.c
+@@ -1,45 +1,45 @@
+
+-/* A Bison parser, made from parsetime.y with Bison version GNU Bison version 1.22
+- */
++/* A Bison parser, made from parsetime.y
++ by GNU Bison version 1.28 */
+
+ #define YYBISON 1 /* Identify Bison output. */
+
+-#define INT 258
+-#define NOW 259
+-#define AM 260
+-#define PM 261
+-#define NOON 262
+-#define MIDNIGHT 263
+-#define TEATIME 264
+-#define SUN 265
+-#define MON 266
+-#define TUE 267
+-#define WED 268
+-#define THU 269
+-#define FRI 270
+-#define SAT 271
+-#define TODAY 272
+-#define TOMORROW 273
+-#define NEXT 274
+-#define MINUTE 275
+-#define HOUR 276
+-#define DAY 277
+-#define WEEK 278
+-#define MONTH 279
+-#define YEAR 280
+-#define JAN 281
+-#define FEB 282
+-#define MAR 283
+-#define APR 284
+-#define MAY 285
+-#define JUN 286
+-#define JUL 287
+-#define AUG 288
+-#define SEP 289
+-#define OCT 290
+-#define NOV 291
+-#define DEC 292
+-#define WORD 293
++#define INT 257
++#define NOW 258
++#define AM 259
++#define PM 260
++#define NOON 261
++#define MIDNIGHT 262
++#define TEATIME 263
++#define SUN 264
++#define MON 265
++#define TUE 266
++#define WED 267
++#define THU 268
++#define FRI 269
++#define SAT 270
++#define TODAY 271
++#define TOMORROW 272
++#define NEXT 273
++#define MINUTE 274
++#define HOUR 275
++#define DAY 276
++#define WEEK 277
++#define MONTH 278
++#define YEAR 279
++#define JAN 280
++#define FEB 281
++#define MAR 282
++#define APR 283
++#define MAY 284
++#define JUN 285
++#define JUL 286
++#define AUG 287
++#define SEP 288
++#define OCT 289
++#define NOV 290
++#define DEC 291
++#define WORD 292
+
+ #line 1 "parsetime.y"
+
+@@ -55,30 +55,16 @@
+ static int isgmt;
+ static int time_only;
+
++extern int yyerror(char *s);
++extern int yylex();
++
+ int add_date(int number, int period);
+
+-#line 17 "parsetime.y"
++#line 20 "parsetime.y"
+ typedef union {
+ char * charval;
+ int intval;
+ } YYSTYPE;
+-
+-#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
+-
+ #include <stdio.h>
+
+ #ifndef __cplusplus
+@@ -89,11 +75,11 @@
+
+
+
+-#define YYFINAL 100
++#define YYFINAL 104
+ #define YYFLAG -32768
+ #define YYNTBASE 47
+
+-#define YYTRANSLATE(x) ((unsigned)(x) <= 293 ? yytranslate[x] : 67)
++#define YYTRANSLATE(x) ((unsigned)(x) <= 292 ? yytranslate[x] : 69)
+
+ static const char yytranslate[] = { 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+@@ -121,176 +107,203 @@
+ 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, 15,
+- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+- 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+- 36, 37, 38
++ 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
++ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
++ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
++ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
++ 37, 38
+ };
+
+ #if YYDEBUG != 0
+ static const short yyprhs[] = { 0,
+- 0, 2, 5, 8, 12, 15, 19, 21, 23, 26,
+- 29, 31, 33, 36, 40, 45, 48, 52, 57, 63,
+- 65, 67, 69, 72, 77, 79, 81, 83, 89, 95,
+- 99, 102, 106, 112, 116, 119, 122, 126, 128, 130,
+- 132, 134, 136, 138, 140, 142, 144, 146, 148, 150,
+- 152, 154, 156, 158, 160, 162, 164, 166, 168, 170,
+- 172, 174, 176, 178, 180, 182, 184, 186, 188, 190,
+- 192, 194, 196, 198, 200, 202, 204
++ 0, 2, 4, 7, 10, 14, 16, 18, 21, 23,
++ 25, 27, 28, 30, 33, 37, 42, 45, 49, 54,
++ 60, 62, 64, 66, 69, 73, 78, 80, 82, 84,
++ 90, 96, 100, 103, 107, 113, 115, 117, 121, 124,
++ 127, 131, 133, 135, 137, 139, 141, 143, 145, 147,
++ 149, 151, 153, 155, 157, 159, 161, 163, 165, 167,
++ 169, 171, 173, 175, 177, 179, 181, 183, 185, 187,
++ 189, 191, 193, 195, 197, 199, 201, 203, 205, 207,
++ 209
+ };
+
+-static const short yyrhs[] = { 50,
+- 0, 50, 51, 0, 50, 52, 0, 50, 51, 52,
+- 0, 50, 53, 0, 50, 51, 53, 0, 48, 0,
+- 49, 0, 49, 52, 0, 49, 53, 0, 4, 0,
+- 55, 0, 55, 56, 0, 57, 66, 58, 0, 57,
+- 66, 58, 56, 0, 57, 59, 0, 57, 59, 56,
+- 0, 57, 66, 58, 59, 0, 57, 66, 58, 59,
+- 56, 0, 7, 0, 8, 0, 9, 0, 60, 62,
+- 0, 60, 62, 39, 63, 0, 64, 0, 17, 0,
+- 18, 0, 63, 40, 61, 40, 62, 0, 62, 41,
+- 61, 41, 63, 0, 62, 41, 61, 0, 62, 60,
+- 0, 62, 60, 63, 0, 61, 42, 62, 42, 63,
+- 0, 43, 65, 54, 0, 19, 54, 0, 19, 64,
+- 0, 40, 65, 54, 0, 20, 0, 21, 0, 22,
+- 0, 23, 0, 24, 0, 25, 0, 3, 0, 38,
+- 0, 55, 0, 3, 0, 5, 0, 6, 0, 26,
+- 0, 27, 0, 28, 0, 29, 0, 30, 0, 31,
+- 0, 32, 0, 33, 0, 34, 0, 35, 0, 36,
+- 0, 37, 0, 3, 0, 3, 0, 3, 0, 10,
+- 0, 11, 0, 12, 0, 13, 0, 14, 0, 15,
+- 0, 16, 0, 3, 0, 44, 0, 45, 0, 41,
+- 0, 46, 0, 39, 0
++static const short yyrhs[] = { 52,
++ 0, 51, 0, 51, 52, 0, 50, 53, 0, 50,
++ 52, 53, 0, 48, 0, 49, 0, 49, 53, 0,
++ 4, 0, 18, 0, 51, 0, 0, 57, 0, 57,
++ 58, 0, 59, 68, 60, 0, 59, 68, 60, 58,
++ 0, 59, 61, 0, 59, 61, 58, 0, 59, 68,
++ 60, 61, 0, 59, 68, 60, 61, 58, 0, 7,
++ 0, 8, 0, 9, 0, 62, 64, 0, 62, 64,
++ 65, 0, 62, 64, 39, 65, 0, 66, 0, 17,
++ 0, 18, 0, 65, 40, 63, 40, 64, 0, 64,
++ 41, 63, 41, 65, 0, 64, 41, 63, 0, 64,
++ 62, 0, 64, 62, 65, 0, 63, 42, 64, 42,
++ 65, 0, 54, 0, 55, 0, 43, 67, 56, 0,
++ 19, 56, 0, 19, 66, 0, 40, 67, 56, 0,
++ 20, 0, 21, 0, 22, 0, 23, 0, 24, 0,
++ 25, 0, 3, 0, 38, 0, 57, 0, 3, 0,
++ 5, 0, 6, 0, 26, 0, 27, 0, 28, 0,
++ 29, 0, 30, 0, 31, 0, 32, 0, 33, 0,
++ 34, 0, 35, 0, 36, 0, 37, 0, 3, 0,
++ 3, 0, 3, 0, 10, 0, 11, 0, 12, 0,
++ 13, 0, 14, 0, 15, 0, 16, 0, 3, 0,
++ 44, 0, 45, 0, 41, 0, 46, 0, 39, 0
+ };
+
+ #endif
+
+ #if YYDEBUG != 0
+ static const short yyrline[] = { 0,
+- 39, 43, 44, 45, 46, 47, 48, 51, 52, 53,
+- 56, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+- 72, 78, 85, 86, 87, 91, 92, 96, 97, 98,
+- 99, 100, 101, 104, 108, 112, 118, 124, 125, 126,
+- 127, 128, 129, 132, 157, 170, 173, 183, 184, 197,
+- 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+- 208, 211, 225, 238, 261, 262, 263, 264, 265, 266,
+- 267, 270, 280, 281, 282, 283, 284
++ 42, 43, 47, 48, 49, 50, 53, 54, 57, 58,
++ 64, 65, 67, 68, 69, 70, 71, 72, 73, 74,
++ 75, 80, 86, 93, 94, 95, 96, 100, 101, 105,
++ 106, 107, 108, 109, 110, 113, 114, 116, 120, 124,
++ 130, 136, 137, 138, 139, 140, 141, 144, 215, 228,
++ 231, 241, 251, 264, 265, 266, 267, 268, 269, 270,
++ 271, 272, 273, 274, 275, 278, 292, 305, 328, 329,
++ 330, 331, 332, 333, 334, 337, 347, 348, 349, 350,
++ 351
+ };
++#endif
++
+
+-static const char * const yytname[] = { "$","error","$illegal.","INT","NOW",
++#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
++
++static const char * const yytname[] = { "$","error","$undefined.","INT","NOW",
+ "AM","PM","NOON","MIDNIGHT","TEATIME","SUN","MON","TUE","WED","THU","FRI","SAT",
+ "TODAY","TOMORROW","NEXT","MINUTE","HOUR","DAY","WEEK","MONTH","YEAR","JAN",
+ "FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC","WORD","','",
+-"'-'","'.'","'/'","'+'","':'","'\\''","'h'","timespec","nowspec","now","time",
+-"date","increment","decrement","inc_period","hr24clock_hr_min","timezone_name",
+-"hr24clock_hour","minute","am_pm","month_name","month_number","day_number","year_number",
+-"day_of_week","inc_number","time_sep",""
++"'-'","'.'","'/'","'+'","':'","'\\''","'h'","timespec","nowspec","now","time_or_not",
++"time","date","inc_or_dec","increment","decrement","inc_period","hr24clock_hr_min",
++"timezone_name","hr24clock_hour","minute","am_pm","month_name","month_number",
++"day_number","year_number","day_of_week","inc_number","time_sep", NULL
+ };
+ #endif
+
+ static const short yyr1[] = { 0,
+- 47, 47, 47, 47, 47, 47, 47, 48, 48, 48,
+- 49, 50, 50, 50, 50, 50, 50, 50, 50, 50,
++ 47, 47, 47, 47, 47, 47, 48, 48, 49, 49,
+ 50, 50, 51, 51, 51, 51, 51, 51, 51, 51,
+- 51, 51, 51, 52, 52, 52, 53, 54, 54, 54,
+- 54, 54, 54, 55, 56, 57, 58, 59, 59, 60,
+- 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+- 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
+- 64, 65, 66, 66, 66, 66, 66
++ 51, 51, 51, 52, 52, 52, 52, 52, 52, 52,
++ 52, 52, 52, 52, 52, 53, 53, 54, 54, 54,
++ 55, 56, 56, 56, 56, 56, 56, 57, 58, 59,
++ 60, 61, 61, 62, 62, 62, 62, 62, 62, 62,
++ 62, 62, 62, 62, 62, 63, 64, 65, 66, 66,
++ 66, 66, 66, 66, 66, 67, 68, 68, 68, 68,
++ 68
+ };
+
+ static const short yyr2[] = { 0,
+- 1, 2, 2, 3, 2, 3, 1, 1, 2, 2,
+- 1, 1, 2, 3, 4, 2, 3, 4, 5, 1,
+- 1, 1, 2, 4, 1, 1, 1, 5, 5, 3,
+- 2, 3, 5, 3, 2, 2, 3, 1, 1, 1,
++ 1, 1, 2, 2, 3, 1, 1, 2, 1, 1,
++ 1, 0, 1, 2, 3, 4, 2, 3, 4, 5,
++ 1, 1, 1, 2, 3, 4, 1, 1, 1, 5,
++ 5, 3, 2, 3, 5, 1, 1, 3, 2, 2,
++ 3, 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, 1, 1, 1
++ 1
+ };
+
+-static const short yydefact[] = { 0,
+- 44, 11, 20, 21, 22, 7, 8, 1, 12, 0,
+- 0, 0, 0, 9, 10, 63, 65, 66, 67, 68,
+- 69, 70, 71, 26, 27, 50, 51, 52, 53, 54,
+- 55, 56, 57, 58, 59, 60, 61, 2, 3, 5,
+- 0, 0, 0, 0, 25, 45, 13, 48, 49, 77,
+- 75, 73, 74, 76, 16, 0, 38, 39, 40, 41,
+- 42, 43, 35, 36, 72, 0, 0, 4, 6, 63,
+- 23, 0, 0, 31, 0, 17, 47, 14, 37, 34,
+- 0, 0, 62, 30, 64, 32, 0, 15, 18, 24,
+- 0, 0, 0, 19, 33, 29, 28, 0, 0, 0
++static const short yydefact[] = { 12,
++ 48, 9, 21, 22, 23, 69, 70, 71, 72, 73,
++ 74, 75, 28, 10, 54, 55, 56, 57, 58, 59,
++ 60, 61, 62, 63, 64, 65, 6, 7, 0, 11,
++ 1, 13, 0, 0, 0, 0, 0, 27, 0, 0,
++ 0, 8, 36, 37, 67, 29, 0, 4, 3, 49,
++ 14, 52, 53, 81, 79, 77, 78, 80, 17, 0,
++ 67, 24, 0, 0, 33, 0, 42, 43, 44, 45,
++ 46, 47, 39, 40, 76, 0, 0, 5, 18, 51,
++ 15, 68, 0, 25, 0, 66, 32, 34, 0, 41,
++ 38, 16, 19, 26, 0, 0, 0, 20, 35, 31,
++ 30, 0, 0, 0
+ };
+
+-static const short yydefgoto[] = { 98,
+- 6, 7, 8, 38, 14, 15, 63, 9, 47, 10,
+- 78, 55, 41, 42, 43, 44, 45, 66, 56
++static const short yydefgoto[] = { 102,
++ 27, 28, 29, 30, 31, 42, 43, 44, 73, 32,
++ 51, 33, 81, 59, 34, 35, 36, 37, 38, 76,
++ 60
+ };
+
+-static const short yypact[] = { 8,
+--32768,-32768,-32768,-32768,-32768,-32768, -14, 43, -4, 4,
+- 80, 5, 5,-32768,-32768, -12,-32768,-32768,-32768,-32768,
++static const short yypact[] = { 114,
++ -21,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+ -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+--32768,-32768,-32768,-32768,-32768,-32768,-32768, -14,-32768,-32768,
+- 10, -6, 81, -8,-32768,-32768,-32768,-32768,-32768,-32768,
+--32768,-32768,-32768,-32768, 9, 48,-32768,-32768,-32768,-32768,
+--32768,-32768,-32768,-32768,-32768, -2, -2,-32768,-32768,-32768,
+- 25, 10, 63, 64, 63,-32768,-32768, 1,-32768,-32768,
+- 64, 26,-32768, 41,-32768,-32768, 44,-32768, 9,-32768,
+- 64, 64, 10,-32768,-32768,-32768,-32768, 85, 87,-32768
++-32768,-32768,-32768,-32768,-32768,-32768,-32768, -13, 41, 79,
++-32768, -4, 4, 22, -14, 142, -8,-32768, 174, 33,
++ 33,-32768,-32768,-32768, -18,-32768, -13,-32768,-32768,-32768,
++-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 9, 58,
++-32768, 0, 22, 59, 61, 59,-32768,-32768,-32768,-32768,
++-32768,-32768,-32768,-32768,-32768, -5, -5,-32768,-32768,-32768,
++ 8,-32768, 61,-32768, 23,-32768, 25,-32768, 40,-32768,
++-32768,-32768, 9,-32768, 61, 61, 22,-32768,-32768,-32768,
++-32768, 83, 85,-32768
+ };
+
+ static const short yypgoto[] = {-32768,
+--32768,-32768,-32768,-32768, -5, 6, -42,-32768, -51,-32768,
+--32768, 11, 54, -10, -41, 7, 95, 106,-32768
++-32768,-32768,-32768,-32768, -22, -24,-32768,-32768, -65,-32768,
++ -55,-32768,-32768, 5, 51, -33, -34, 71, 49, 57,
++-32768
+ };
+
+
+-#define YYLAST 122
++#define YYLAST 199
+
+
+-static const short yytable[] = { 71,
+- -46, -46, 39, 76, 11, 48, 49, 65, 48, 49,
+- 1, 2, 70, 40, 3, 4, 5, 57, 58, 59,
+- 60, 61, 62, 79, 80, 12, 88, -64, 13, -62,
+- 82, 75, 68, 46, -46, 72, -46, 94, 46, -46,
+- -46, -46, 50, 69, 51, 16, 46, 52, 53, 54,
+- 77, 97, 17, 18, 19, 20, 21, 22, 23, 24,
+- 25, 11, 84, 81, 87, 83, 85, 91, 26, 27,
+- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+- 86, 92, 12, 93, 99, 13, 100, 90, 89, 17,
+- 18, 19, 20, 21, 22, 23, 74, 95, 96, 57,
+- 58, 59, 60, 61, 62, 64, 26, 27, 28, 29,
+- 30, 31, 32, 33, 34, 35, 36, 37, 67, 0,
+- 0, 73
++static const short yytable[] = { 62,
++ -50, -50, 82, 79, 48, 39, 47, 49, 52, 53,
++ 90, 91, 52, 53, 67, 68, 69, 70, 71, 72,
++ -66, -68, 78, -66, 61, 92, 40, 63, 85, 41,
++ 87, 66, 89, 50, -50, 75, -50, 98, 83, -50,
++ -50, -50, 54, 45, 55, 50, 50, 56, 57, 58,
++ 6, 7, 8, 9, 10, 11, 12, 13, 46, 39,
++ 80, 86, 101, 82, 95, 96, 15, 16, 17, 18,
++ 19, 20, 21, 22, 23, 24, 25, 26, -2, 97,
++ 40, 45, 103, 41, 104, 93, 65, 74, 6, 7,
++ 8, 9, 10, 11, 12, 13, 46, 77, 0, 0,
++ 0, 0, 0, 0, 15, 16, 17, 18, 19, 20,
++ 21, 22, 23, 24, 25, 26, 1, 2, 0, 0,
++ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
++ 13, 14, 84, 0, 0, 88, 0, 0, 0, 15,
++ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
++ 26, 0, 0, 94, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 99, 100, 15, 16, 17,
++ 18, 19, 20, 21, 22, 23, 24, 25, 26, 0,
++ 0, 0, 64, 6, 7, 8, 9, 10, 11, 12,
++ 0, 0, 0, 67, 68, 69, 70, 71, 72
+ };
+
+-static const short yycheck[] = { 41,
+- 5, 6, 8, 55, 19, 5, 6, 3, 5, 6,
+- 3, 4, 3, 8, 7, 8, 9, 20, 21, 22,
+- 23, 24, 25, 66, 67, 40, 78, 40, 43, 42,
+- 72, 40, 38, 38, 39, 42, 41, 89, 38, 44,
+- 45, 46, 39, 38, 41, 3, 38, 44, 45, 46,
+- 3, 93, 10, 11, 12, 13, 14, 15, 16, 17,
+- 18, 19, 73, 39, 75, 3, 3, 42, 26, 27,
+- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+- 74, 41, 40, 40, 0, 43, 0, 81, 78, 10,
+- 11, 12, 13, 14, 15, 16, 43, 91, 92, 20,
+- 21, 22, 23, 24, 25, 11, 26, 27, 28, 29,
+- 30, 31, 32, 33, 34, 35, 36, 37, 13, -1,
+- -1, 41
++static const short yycheck[] = { 34,
++ 5, 6, 3, 59, 29, 19, 29, 30, 5, 6,
++ 76, 77, 5, 6, 20, 21, 22, 23, 24, 25,
++ 42, 40, 47, 42, 3, 81, 40, 42, 63, 43,
++ 64, 40, 66, 38, 39, 3, 41, 93, 39, 44,
++ 45, 46, 39, 3, 41, 38, 38, 44, 45, 46,
++ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
++ 3, 3, 97, 3, 42, 41, 26, 27, 28, 29,
++ 30, 31, 32, 33, 34, 35, 36, 37, 0, 40,
++ 40, 3, 0, 43, 0, 81, 36, 39, 10, 11,
++ 12, 13, 14, 15, 16, 17, 18, 41, -1, -1,
++ -1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
++ 32, 33, 34, 35, 36, 37, 3, 4, -1, -1,
++ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
++ 17, 18, 62, -1, -1, 65, -1, -1, -1, 26,
++ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
++ 37, -1, -1, 83, -1, -1, -1, -1, -1, -1,
++ -1, -1, -1, -1, -1, 95, 96, 26, 27, 28,
++ 29, 30, 31, 32, 33, 34, 35, 36, 37, -1,
++ -1, -1, 41, 10, 11, 12, 13, 14, 15, 16,
++ -1, -1, -1, 20, 21, 22, 23, 24, 25
+ };
+ /* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+-#line 3 "/usr/lib/bison.simple"
++#line 3 "/usr/share/misc/bison.simple"
++/* This file comes from bison-1.28. */
+
+ /* Skeleton output parser for bison,
+- Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman
++ Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
+
+ 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)
++ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+@@ -300,42 +313,66 @@
+
+ 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. */
++ Foundation, Inc., 59 Temple Place - Suite 330,
++ Boston, MA 02111-1307, USA. */
+
++/* As a special exception, when this file is copied by Bison into a
++ Bison output file, you may use that output file without restriction.
++ This special exception was added by the Free Software Foundation
++ in version 1.24 of Bison. */
+
+-#ifndef alloca
++/* 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. */
++
++#ifndef YYSTACK_USE_ALLOCA
++#ifdef alloca
++#define YYSTACK_USE_ALLOCA
++#else /* alloca not defined */
+ #ifdef __GNUC__
++#define YYSTACK_USE_ALLOCA
+ #define alloca __builtin_alloca
+ #else /* not GNU C. */
+-#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
++#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
++#define YYSTACK_USE_ALLOCA
+ #include <alloca.h>
+ #else /* not sparc */
+-#if defined (MSDOS) && !defined (__TURBOC__)
++/* We think this test detects Watcom and Microsoft C. */
++/* This used to test MSDOS, but that is a bad idea
++ since that symbol is in the user namespace. */
++#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
++#if 0 /* No need for malloc.h, which pollutes the namespace;
++ instead, just don't use alloca. */
+ #include <malloc.h>
++#endif
+ #else /* not MSDOS, or __TURBOC__ */
+ #if defined(_AIX)
+-#include <malloc.h>
++/* I don't know what this was needed for, but it pollutes the namespace.
++ So I turned it off. rms, 2 May 1997. */
++/* #include <malloc.h> */
+ #pragma alloca
+-#else /* not MSDOS, __TURBOC__, or _AIX */
+-#ifdef __hpux
+-#ifdef __cplusplus
+-extern "C" {
+-void *alloca (unsigned int);
+-};
+-#else /* not __cplusplus */
+-void *alloca ();
+-#endif /* not __cplusplus */
++#define YYSTACK_USE_ALLOCA
++#else /* not MSDOS, or __TURBOC__, or _AIX */
++#if 0
++#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
++ and on HPUX 10. Eventually we can turn this on. */
++#define YYSTACK_USE_ALLOCA
++#define alloca __builtin_alloca
+ #endif /* __hpux */
++#endif
+ #endif /* not _AIX */
+ #endif /* not MSDOS, or __TURBOC__ */
+-#endif /* not sparc. */
+-#endif /* not GNU C. */
+-#endif /* alloca not defined. */
++#endif /* not sparc */
++#endif /* not GNU C */
++#endif /* alloca not defined */
++#endif /* YYSTACK_USE_ALLOCA not defined */
+
+-/* 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. */
++#ifdef YYSTACK_USE_ALLOCA
++#define YYSTACK_ALLOC alloca
++#else
++#define YYSTACK_ALLOC malloc
++#endif
+
+ /* Note: there must be only one dollar sign in this file.
+ It is replaced by the list of actions, each action
+@@ -345,8 +382,8 @@
+ #define yyclearin (yychar = YYEMPTY)
+ #define YYEMPTY -2
+ #define YYEOF 0
+-#define YYACCEPT return(0)
+-#define YYABORT return(1)
++#define YYACCEPT goto yyacceptlab
++#define YYABORT goto yyabortlab
+ #define YYERROR goto yyerrlab1
+ /* Like YYERROR except do call yyerror.
+ This remains here temporarily to ease the
+@@ -375,10 +412,18 @@
+
+ #ifdef YYPURE
+ #ifdef YYLSP_NEEDED
++#ifdef YYLEX_PARAM
++#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
++#else
+ #define YYLEX yylex(&yylval, &yylloc)
++#endif
++#else /* not YYLSP_NEEDED */
++#ifdef YYLEX_PARAM
++#define YYLEX yylex(&yylval, YYLEX_PARAM)
+ #else
+ #define YYLEX yylex(&yylval)
+ #endif
++#endif /* not YYLSP_NEEDED */
+ #endif
+
+ /* If nonreentrant, generate the variables here */
+@@ -419,24 +464,24 @@
+ #ifndef YYMAXDEPTH
+ #define YYMAXDEPTH 10000
+ #endif
+-
+-/* Prevent warning if -Wstrict-prototypes. */
+-#ifdef __GNUC__
+-int yyparse (void);
+-#endif
+ \f
++/* Define __yy_memcpy. Note that the size argument
++ should be passed with type unsigned int, because that is what the non-GCC
++ definitions require. With GCC, __builtin_memcpy takes an arg
++ of type size_t, but it can handle unsigned int. */
++
+ #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+-#define __yy_bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)
++#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+ #else /* not GNU C or C++ */
+ #ifndef __cplusplus
+
+ /* 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;
++__yy_memcpy (to, from, count)
+ char *to;
+- int count;
++ char *from;
++ unsigned int count;
+ {
+ register char *f = from;
+ register char *t = to;
+@@ -451,10 +496,10 @@
+ /* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+ static void
+-__yy_bcopy (char *from, char *to, int count)
++__yy_memcpy (char *to, char *from, unsigned int count)
+ {
+- register char *f = from;
+ register char *t = to;
++ register char *f = from;
+ register int i = count;
+
+ while (i-- > 0)
+@@ -464,9 +509,39 @@
+ #endif
+ #endif
+ \f
+-#line 184 "/usr/lib/bison.simple"
++#line 217 "/usr/share/misc/bison.simple"
++
++/* The user can define YYPARSE_PARAM as the name of an argument to be passed
++ into yyparse. The argument should have type void *.
++ It should actually point to an object.
++ Grammar actions can access the variable by casting it
++ to the proper pointer type. */
++
++#ifdef YYPARSE_PARAM
++#ifdef __cplusplus
++#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
++#define YYPARSE_PARAM_DECL
++#else /* not __cplusplus */
++#define YYPARSE_PARAM_ARG YYPARSE_PARAM
++#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
++#endif /* not __cplusplus */
++#else /* not YYPARSE_PARAM */
++#define YYPARSE_PARAM_ARG
++#define YYPARSE_PARAM_DECL
++#endif /* not YYPARSE_PARAM */
++
++/* Prevent warning if -Wstrict-prototypes. */
++#ifdef __GNUC__
++#ifdef YYPARSE_PARAM
++int yyparse (void *);
++#else
++int yyparse (void);
++#endif
++#endif
++
+ int
+-yyparse()
++yyparse(YYPARSE_PARAM_ARG)
++ YYPARSE_PARAM_DECL
+ {
+ register int yystate;
+ register int yyn;
+@@ -492,6 +567,7 @@
+ #endif
+
+ int yystacksize = YYINITDEPTH;
++ int yyfree_stacks = 0;
+
+ #ifdef YYPURE
+ int yychar;
+@@ -576,18 +652,32 @@
+ if (yystacksize >= YYMAXDEPTH)
+ {
+ yyerror("parser stack overflow");
++ if (yyfree_stacks)
++ {
++ free (yyss);
++ free (yyvs);
++#ifdef YYLSP_NEEDED
++ free (yyls);
++#endif
++ }
+ 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));
++#ifndef YYSTACK_USE_ALLOCA
++ yyfree_stacks = 1;
++#endif
++ yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
++ __yy_memcpy ((char *)yyss, (char *)yyss1,
++ size * (unsigned int) sizeof (*yyssp));
++ yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
++ __yy_memcpy ((char *)yyvs, (char *)yyvs1,
++ size * (unsigned int) sizeof (*yyvsp));
+ #ifdef YYLSP_NEEDED
+- yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
+- __yy_bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
++ yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
++ __yy_memcpy ((char *)yyls, (char *)yyls1,
++ size * (unsigned int) sizeof (*yylsp));
+ #endif
+ #endif /* no yyoverflow */
+
+@@ -747,102 +837,154 @@
+
+ switch (yyn) {
+
+-case 1:
+-#line 40 "parsetime.y"
++case 2:
++#line 44 "parsetime.y"
+ {
+ time_only = 1;
+ ;
+ break;}
+-case 20:
+-#line 68 "parsetime.y"
++case 10:
++#line 59 "parsetime.y"
++{
++ add_date(1, DAY);
++ ;
++ break;}
++case 21:
++#line 76 "parsetime.y"
+ {
+ exectm.tm_hour = 12;
+ exectm.tm_min = 0;
+ ;
+ break;}
+-case 21:
+-#line 73 "parsetime.y"
++case 22:
++#line 81 "parsetime.y"
+ {
+ exectm.tm_hour = 0;
+ exectm.tm_min = 0;
+ add_date(1, DAY);
+ ;
+ break;}
+-case 22:
+-#line 79 "parsetime.y"
++case 23:
++#line 87 "parsetime.y"
+ {
+ exectm.tm_hour = 16;
+ exectm.tm_min = 0;
+ ;
+ break;}
+-case 25:
+-#line 88 "parsetime.y"
++case 27:
++#line 97 "parsetime.y"
+ {
+- add_date ((7 + yyvsp[0].intval - exectm.tm_wday) %7 + 1, DAY);
++ add_date ((6 + yyvsp[0].intval - exectm.tm_wday) %7 + 1, DAY);
+ ;
+ break;}
+-case 27:
+-#line 93 "parsetime.y"
++case 29:
++#line 102 "parsetime.y"
+ {
+ add_date(1, DAY);
+ ;
+ break;}
+-case 34:
+-#line 105 "parsetime.y"
++case 38:
++#line 117 "parsetime.y"
+ {
+ add_date(yyvsp[-1].intval, yyvsp[0].intval);
+ ;
+ break;}
+-case 35:
+-#line 109 "parsetime.y"
++case 39:
++#line 121 "parsetime.y"
+ {
+ add_date(1, yyvsp[0].intval);
+ ;
+ break;}
+-case 36:
+-#line 113 "parsetime.y"
++case 40:
++#line 125 "parsetime.y"
+ {
+ add_date ((6 + yyvsp[0].intval - exectm.tm_wday) %7 +1, DAY);
+ ;
+ break;}
+-case 37:
+-#line 119 "parsetime.y"
++case 41:
++#line 131 "parsetime.y"
+ {
+ add_date(-yyvsp[-1].intval, yyvsp[0].intval);
+ ;
+ break;}
+-case 38:
+-#line 124 "parsetime.y"
++case 42:
++#line 136 "parsetime.y"
+ { yyval.intval = MINUTE ; ;
+ break;}
+-case 39:
+-#line 125 "parsetime.y"
++case 43:
++#line 137 "parsetime.y"
+ { yyval.intval = HOUR ; ;
+ break;}
+-case 40:
+-#line 126 "parsetime.y"
++case 44:
++#line 138 "parsetime.y"
+ { yyval.intval = DAY ; ;
+ break;}
+-case 41:
+-#line 127 "parsetime.y"
++case 45:
++#line 139 "parsetime.y"
+ { yyval.intval = WEEK ; ;
+ break;}
+-case 42:
+-#line 128 "parsetime.y"
++case 46:
++#line 140 "parsetime.y"
+ { yyval.intval = MONTH ; ;
+ break;}
+-case 43:
+-#line 129 "parsetime.y"
++case 47:
++#line 141 "parsetime.y"
+ { yyval.intval = YEAR ; ;
+ break;}
+-case 44:
+-#line 133 "parsetime.y"
++case 48:
++#line 145 "parsetime.y"
+ {
+- exectm.tm_min = -1;
+- exectm.tm_hour = -1;
+ if (strlen(yyvsp[0].charval) == 4) {
++ exectm.tm_min = -1;
++ exectm.tm_hour = -1;
+ sscanf(yyvsp[0].charval, "%2d %2d", &exectm.tm_hour,
+ &exectm.tm_min);
++ } else if (strlen(yyvsp[0].charval) >= 5 && strlen(yyvsp[0].charval) <= 8) {
++ /* Ok, this is a kluge. I hate design errors... -Joey */
++ char shallot[5];
++ char *onion;
++
++ onion=yyvsp[0].charval;
++ memset (shallot, 0, sizeof (shallot));
++ if (strlen(yyvsp[0].charval) == 5 || strlen(yyvsp[0].charval) == 7) {
++ strncpy (shallot,onion,1);
++ onion++;
++ } else {
++ strncpy (shallot,onion,2);
++ onion+=2;
++ }
++ sscanf(shallot, "%d", &exectm.tm_mon);
++
++ if (exectm.tm_mon < 1 || exectm.tm_mon > 12) {
++ yyerror("Error in month number");
++ YYERROR;
++ }
++ exectm.tm_mon--;
++
++ memset (shallot, 0, sizeof (shallot));
++ strncpy (shallot,onion,2);
++ sscanf(shallot, "%d", &exectm.tm_mday);
++ if (exectm.tm_mday < 0 || exectm.tm_mday > 31)
++ {
++ yyerror("Error in day of month");
++ YYERROR;
++ }
++
++ onion+=2;
++ memset (shallot, 0, sizeof (shallot));
++ strncpy (shallot,onion,4);
++ if ( sscanf(shallot, "%d", &exectm.tm_year) != 1) {
++ yyerror("Error in year");
++ YYERROR;
++ }
++ if (exectm.tm_year < 70) {
++ exectm.tm_year += 100;
++ }
++ else if (exectm.tm_year > 1900) {
++ exectm.tm_year -= 1900;
++ }
++
++ free (yyvsp[0].charval);
+ }
+ else {
+ sscanf(yyvsp[0].charval, "%d", &exectm.tm_hour);
+@@ -855,13 +997,13 @@
+ YYERROR;
+ }
+ if (exectm.tm_hour > 24 || exectm.tm_hour < 0) {
+- yyerror("Problem in minutes specification");
++ yyerror("Problem in hours specification");
+ YYERROR;
+ }
+ ;
+ break;}
+-case 45:
+-#line 158 "parsetime.y"
++case 49:
++#line 216 "parsetime.y"
+ {
+ if (strcasecmp(yyvsp[0].charval,"utc") == 0) {
+ isgmt = 1;
+@@ -873,8 +1015,8 @@
+ free(yyvsp[0].charval);
+ ;
+ break;}
+-case 47:
+-#line 174 "parsetime.y"
++case 51:
++#line 232 "parsetime.y"
+ {
+ if (sscanf(yyvsp[0].charval, "%d", &exectm.tm_min) != 1) {
+ yyerror("Error in minute");
+@@ -883,8 +1025,20 @@
+ free(yyvsp[0].charval);
+ ;
+ break;}
+-case 49:
+-#line 185 "parsetime.y"
++case 52:
++#line 242 "parsetime.y"
++{
++ if (exectm.tm_hour > 12) {
++ yyerror("Hour too large for AM");
++ YYERROR;
++ }
++ else if (exectm.tm_hour == 12) {
++ exectm.tm_hour = 0;
++ }
++ ;
++ break;}
++case 53:
++#line 252 "parsetime.y"
+ {
+ if (exectm.tm_hour > 12) {
+ yyerror("Hour too large for PM");
+@@ -895,56 +1049,56 @@
+ }
+ ;
+ break;}
+-case 50:
+-#line 197 "parsetime.y"
++case 54:
++#line 264 "parsetime.y"
+ { exectm.tm_mon = 0; ;
+ break;}
+-case 51:
+-#line 198 "parsetime.y"
++case 55:
++#line 265 "parsetime.y"
+ { exectm.tm_mon = 1; ;
+ break;}
+-case 52:
+-#line 199 "parsetime.y"
++case 56:
++#line 266 "parsetime.y"
+ { exectm.tm_mon = 2; ;
+ break;}
+-case 53:
+-#line 200 "parsetime.y"
++case 57:
++#line 267 "parsetime.y"
+ { exectm.tm_mon = 3; ;
+ break;}
+-case 54:
+-#line 201 "parsetime.y"
++case 58:
++#line 268 "parsetime.y"
+ { exectm.tm_mon = 4; ;
+ break;}
+-case 55:
+-#line 202 "parsetime.y"
++case 59:
++#line 269 "parsetime.y"
+ { exectm.tm_mon = 5; ;
+ break;}
+-case 56:
+-#line 203 "parsetime.y"
++case 60:
++#line 270 "parsetime.y"
+ { exectm.tm_mon = 6; ;
+ break;}
+-case 57:
+-#line 204 "parsetime.y"
++case 61:
++#line 271 "parsetime.y"
+ { exectm.tm_mon = 7; ;
+ break;}
+-case 58:
+-#line 205 "parsetime.y"
++case 62:
++#line 272 "parsetime.y"
+ { exectm.tm_mon = 8; ;
+ break;}
+-case 59:
+-#line 206 "parsetime.y"
++case 63:
++#line 273 "parsetime.y"
+ { exectm.tm_mon = 9; ;
+ break;}
+-case 60:
+-#line 207 "parsetime.y"
++case 64:
++#line 274 "parsetime.y"
+ { exectm.tm_mon =10; ;
+ break;}
+-case 61:
+-#line 208 "parsetime.y"
++case 65:
++#line 275 "parsetime.y"
+ { exectm.tm_mon =11; ;
+ break;}
+-case 62:
+-#line 212 "parsetime.y"
++case 66:
++#line 279 "parsetime.y"
+ {
+ {
+ int mnum = -1;
+@@ -959,8 +1113,8 @@
+ }
+ ;
+ break;}
+-case 63:
+-#line 226 "parsetime.y"
++case 67:
++#line 293 "parsetime.y"
+ {
+ exectm.tm_mday = -1;
+ sscanf(yyvsp[0].charval, "%d", &exectm.tm_mday);
+@@ -972,8 +1126,8 @@
+ free(yyvsp[0].charval);
+ ;
+ break;}
+-case 64:
+-#line 239 "parsetime.y"
++case 68:
++#line 306 "parsetime.y"
+ {
+ {
+ int ynum;
+@@ -994,36 +1148,36 @@
+ }
+ ;
+ break;}
+-case 65:
+-#line 261 "parsetime.y"
++case 69:
++#line 328 "parsetime.y"
+ { yyval.intval = 0; ;
+ break;}
+-case 66:
+-#line 262 "parsetime.y"
++case 70:
++#line 329 "parsetime.y"
+ { yyval.intval = 1; ;
+ break;}
+-case 67:
+-#line 263 "parsetime.y"
++case 71:
++#line 330 "parsetime.y"
+ { yyval.intval = 2; ;
+ break;}
+-case 68:
+-#line 264 "parsetime.y"
++case 72:
++#line 331 "parsetime.y"
+ { yyval.intval = 3; ;
+ break;}
+-case 69:
+-#line 265 "parsetime.y"
++case 73:
++#line 332 "parsetime.y"
+ { yyval.intval = 4; ;
+ break;}
+-case 70:
+-#line 266 "parsetime.y"
++case 74:
++#line 333 "parsetime.y"
+ { yyval.intval = 5; ;
+ break;}
+-case 71:
+-#line 267 "parsetime.y"
++case 75:
++#line 334 "parsetime.y"
+ { yyval.intval = 6; ;
+ break;}
+-case 72:
+-#line 271 "parsetime.y"
++case 76:
++#line 338 "parsetime.y"
+ {
+ if (sscanf(yyvsp[0].charval, "%d", &yyval.intval) != 1) {
+ yyerror("Unknown increment");
+@@ -1034,7 +1188,7 @@
+ break;}
+ }
+ /* the action file gets copied in in place of this dollarsign */
+-#line 465 "/usr/lib/bison.simple"
++#line 543 "/usr/share/misc/bison.simple"
+ \f
+ yyvsp -= yylen;
+ yyssp -= yylen;
+@@ -1229,8 +1383,32 @@
+
+ yystate = yyn;
+ goto yynewstate;
++
++ yyacceptlab:
++ /* YYACCEPT comes here. */
++ if (yyfree_stacks)
++ {
++ free (yyss);
++ free (yyvs);
++#ifdef YYLSP_NEEDED
++ free (yyls);
++#endif
++ }
++ return 0;
++
++ yyabortlab:
++ /* YYABORT comes here. */
++ if (yyfree_stacks)
++ {
++ free (yyss);
++ free (yyvs);
++#ifdef YYLSP_NEEDED
++ free (yyls);
++#endif
++ }
++ return 1;
+ }
+-#line 287 "parsetime.y"
++#line 354 "parsetime.y"
+
+
+
+@@ -1266,6 +1444,24 @@
+ }
+
+ #ifdef TEST_PARSER
++/*
++
++Here are some lines to test:
++
++./parsetest 7AM Mar 24 2000
++./parsetest 7AM Mar 24 00
++./parsetest 7AM 032400
++./parsetest 7AM 03/24/00
++./parsetest 7AM 24.03.00
++./parsetest 7AM Mar 24
++
++./parsetest 03242000
++./parsetest noon 03242000
++./parsetest 5:30
++./parsetest 4pm + 3 days
++./parsetest 10am Jul 31
++
++ */
+ int
+ main(int argc, char **argv)
+ {
+--- at-3.1.8.orig/y.tab.h
++++ at-3.1.8/y.tab.h
+@@ -2,42 +2,42 @@
+ char * charval;
+ int intval;
+ } YYSTYPE;
+-#define INT 258
+-#define NOW 259
+-#define AM 260
+-#define PM 261
+-#define NOON 262
+-#define MIDNIGHT 263
+-#define TEATIME 264
+-#define SUN 265
+-#define MON 266
+-#define TUE 267
+-#define WED 268
+-#define THU 269
+-#define FRI 270
+-#define SAT 271
+-#define TODAY 272
+-#define TOMORROW 273
+-#define NEXT 274
+-#define MINUTE 275
+-#define HOUR 276
+-#define DAY 277
+-#define WEEK 278
+-#define MONTH 279
+-#define YEAR 280
+-#define JAN 281
+-#define FEB 282
+-#define MAR 283
+-#define APR 284
+-#define MAY 285
+-#define JUN 286
+-#define JUL 287
+-#define AUG 288
+-#define SEP 289
+-#define OCT 290
+-#define NOV 291
+-#define DEC 292
+-#define WORD 293
++#define INT 257
++#define NOW 258
++#define AM 259
++#define PM 260
++#define NOON 261
++#define MIDNIGHT 262
++#define TEATIME 263
++#define SUN 264
++#define MON 265
++#define TUE 266
++#define WED 267
++#define THU 268
++#define FRI 269
++#define SAT 270
++#define TODAY 271
++#define TOMORROW 272
++#define NEXT 273
++#define MINUTE 274
++#define HOUR 275
++#define DAY 276
++#define WEEK 277
++#define MONTH 278
++#define YEAR 279
++#define JAN 280
++#define FEB 281
++#define MAR 282
++#define APR 283
++#define MAY 284
++#define JUN 285
++#define JUL 286
++#define AUG 287
++#define SEP 288
++#define OCT 289
++#define NOV 290
++#define DEC 291
++#define WORD 292
+
+
+ extern YYSTYPE yylval;
+--- at-3.1.8.orig/lex.yy.c
++++ at-3.1.8/lex.yy.c
+@@ -1,7 +1,7 @@
+ /* A lexical scanner generated by flex */
+
+ /* Scanner skeleton version:
+- * $Header$
++ * $Header$
+ */
+
+ #define FLEX_SCANNER
+@@ -126,6 +126,7 @@
+ { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
++ YY_RESTORE_YY_MORE_OFFSET \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+@@ -235,7 +236,7 @@
+ #define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+ YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+-YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str ));
++YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+ YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+ static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+@@ -456,6 +457,7 @@
+ #define REJECT reject_used_but_not_detected
+ #define yymore() yymore_used_but_not_detected
+ #define YY_MORE_ADJ 0
++#define YY_RESTORE_YY_MORE_OFFSET
+ char *yytext;
+ #line 1 "parsetime.l"
+ #define INITIAL 0
+@@ -491,7 +493,7 @@
+ result = 1; \
+ } \
+ } while(0)
+-#line 495 "lex.yy.c"
++#line 497 "lex.yy.c"
+
+ /* Macros after this point can all be overridden by user definitions in
+ * section 1.
+@@ -513,6 +515,10 @@
+ static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+ #endif
+
++#ifdef YY_NEED_STRLEN
++static int yy_flex_strlen YY_PROTO(( yyconst char * ));
++#endif
++
+ #ifndef YY_NO_INPUT
+ #ifdef __cplusplus
+ static int yyinput YY_PROTO(( void ));
+@@ -641,7 +647,7 @@
+ #line 36 "parsetime.l"
+
+
+-#line 645 "lex.yy.c"
++#line 651 "lex.yy.c"
+
+ if ( yy_init )
+ {
+@@ -919,7 +925,7 @@
+ #line 77 "parsetime.l"
+ ECHO;
+ YY_BREAK
+-#line 923 "lex.yy.c"
++#line 929 "lex.yy.c"
+ case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+@@ -930,6 +936,7 @@
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
++ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ {
+@@ -1075,7 +1082,7 @@
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+- /* We matched a singled characater, the EOB, so
++ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+@@ -1102,7 +1109,7 @@
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+- yy_n_chars = 0;
++ yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+ else
+ {
+@@ -1157,6 +1164,8 @@
+ /* Read in more data. */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
++
++ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ if ( yy_n_chars == 0 )
+@@ -1281,7 +1290,8 @@
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+- yy_n_chars = yy_current_buffer->yy_buf_size;
++ yy_current_buffer->yy_n_chars =
++ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+@@ -1319,19 +1329,31 @@
+
+ else
+ { /* need more input */
+- yytext_ptr = yy_c_buf_p;
++ int offset = yy_c_buf_p - yytext_ptr;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
++ case EOB_ACT_LAST_MATCH:
++ /* This happens because yy_g_n_b()
++ * sees that we've accumulated a
++ * token and flags that we need to
++ * try matching the token before
++ * proceeding. But for input(),
++ * there's no matching to consider.
++ * So convert the EOB_ACT_LAST_MATCH
++ * to EOB_ACT_END_OF_FILE.
++ */
++
++ /* Reset buffer status. */
++ yyrestart( yyin );
++
++ /* fall through */
++
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+- {
+- yy_c_buf_p =
+- yytext_ptr + YY_MORE_ADJ;
+ return EOF;
+- }
+
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+@@ -1343,17 +1365,8 @@
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+- yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
++ yy_c_buf_p = yytext_ptr + offset;
+ break;
+-
+- case EOB_ACT_LAST_MATCH:
+-#ifdef __cplusplus
+- YY_FATAL_ERROR(
+- "unexpected last match in yyinput()" );
+-#else
+- YY_FATAL_ERROR(
+- "unexpected last match in input()" );
+-#endif
+ }
+ }
+ }
+@@ -1517,6 +1530,9 @@
+ #endif
+
+ {
++ if ( ! b )
++ return;
++
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+@@ -1576,17 +1592,17 @@
+
+ #ifndef YY_NO_SCAN_STRING
+ #ifdef YY_USE_PROTOS
+-YY_BUFFER_STATE yy_scan_string( yyconst char *str )
++YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+ #else
+-YY_BUFFER_STATE yy_scan_string( str )
+-yyconst char *str;
++YY_BUFFER_STATE yy_scan_string( yy_str )
++yyconst char *yy_str;
+ #endif
+ {
+ int len;
+- for ( len = 0; str[len]; ++len )
++ for ( len = 0; yy_str[len]; ++len )
+ ;
+
+- return yy_scan_bytes( str, len );
++ return yy_scan_bytes( yy_str, len );
+ }
+ #endif
+
+@@ -1707,7 +1723,7 @@
+ { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+- yy_c_buf_p = yytext + n - YY_MORE_ADJ; \
++ yy_c_buf_p = yytext + n; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+@@ -1730,6 +1746,22 @@
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
++ }
++#endif
++
++#ifdef YY_NEED_STRLEN
++#ifdef YY_USE_PROTOS
++static int yy_flex_strlen( yyconst char *s )
++#else
++static int yy_flex_strlen( s )
++yyconst char *s;
++#endif
++ {
++ register int n;
++ for ( n = 0; s[n]; ++n )
++ ;
++
++ return n;
+ }
+ #endif
+
+--- at-3.1.8.orig/Makefile.in
++++ at-3.1.8/Makefile.in
+@@ -131,6 +133,7 @@
+
+ clean:
+ rm -f subs.sed *.o *.s at atd core a.out *~ $(CLONES) *.bak stamp-built
++ rm -f parsetest
+
+ distclean: clean
+ rm -rf at.1 atd.8 atrun.8 config.cache atrun config.h \
+@@ -144,6 +147,9 @@
+
+ Filelist.asc: Filelist
+ pgp -sba Filelist
++
++parsetest: lex.yy.c y.tab.c
++ $(CC) -o parsetest $(CFLAGS) $(DEFS) -DTEST_PARSER -DNEED_YYWRAP lex.yy.c y.tab.c
+
+ .depend: $(CSRCS)
+ gcc $(CFLAGS) $(DEFS) -MM $(CSRCS) > .depend
+--- at-3.1.8.orig/parsetime.y
++++ at-3.1.8/parsetime.y
+@@ -11,6 +11,9 @@
+ static int isgmt;
+ static int time_only;
+
++extern int yyerror(char *s);
++extern int yylex();
++
+ int add_date(int number, int period);
+ %}
+
+@@ -36,26 +39,31 @@
+
+ %start timespec
+ %%
+-timespec : time
++timespec : date
++ | time
+ {
+ time_only = 1;
+ }
+ | time date
+- | time increment
+- | time date increment
+- | time decrement
+- | time date decrement
++ | time_or_not inc_or_dec
++ | time_or_not date inc_or_dec
+ | nowspec
+ ;
+
+ nowspec : now
+- | now increment
+- | now decrement
++ | now inc_or_dec
+ ;
+
+ now : NOW
++ | TOMORROW
++ {
++ add_date(1, DAY);
++ }
+ ;
+
++time_or_not : time
++ |
++
+ time : hr24clock_hr_min
+ | hr24clock_hr_min timezone_name
+ | hr24clock_hour time_sep minute
+@@ -83,10 +91,11 @@
+ ;
+
+ date : month_name day_number
++ | month_name day_number year_number
+ | month_name day_number ',' year_number
+ | day_of_week
+ {
+- add_date ((7 + $1 - exectm.tm_wday) %7 + 1, DAY);
++ add_date ((6 + $1 - exectm.tm_wday) %7 + 1, DAY);
+ }
+ | TODAY
+ | TOMORROW
+@@ -101,6 +110,9 @@
+ | month_number '/' day_number '/' year_number
+ ;
+
++inc_or_dec : increment
++ | decrement
++
+ increment : '+' inc_number inc_period
+ {
+ add_date($2, $3);
+@@ -131,11 +143,57 @@
+
+ hr24clock_hr_min: INT
+ {
+- exectm.tm_min = -1;
+- exectm.tm_hour = -1;
+ if (strlen($1) == 4) {
++ exectm.tm_min = -1;
++ exectm.tm_hour = -1;
+ sscanf($1, "%2d %2d", &exectm.tm_hour,
+ &exectm.tm_min);
++ } else if (strlen($1) >= 5 && strlen($1) <= 8) {
++ /* Ok, this is a kluge. I hate design errors... -Joey */
++ char shallot[5];
++ char *onion;
++
++ onion=$1;
++ memset (shallot, 0, sizeof (shallot));
++ if (strlen($1) == 5 || strlen($1) == 7) {
++ strncpy (shallot,onion,1);
++ onion++;
++ } else {
++ strncpy (shallot,onion,2);
++ onion+=2;
++ }
++ sscanf(shallot, "%d", &exectm.tm_mon);
++
++ if (exectm.tm_mon < 1 || exectm.tm_mon > 12) {
++ yyerror("Error in month number");
++ YYERROR;
++ }
++ exectm.tm_mon--;
++
++ memset (shallot, 0, sizeof (shallot));
++ strncpy (shallot,onion,2);
++ sscanf(shallot, "%d", &exectm.tm_mday);
++ if (exectm.tm_mday < 0 || exectm.tm_mday > 31)
++ {
++ yyerror("Error in day of month");
++ YYERROR;
++ }
++
++ onion+=2;
++ memset (shallot, 0, sizeof (shallot));
++ strncpy (shallot,onion,4);
++ if ( sscanf(shallot, "%d", &exectm.tm_year) != 1) {
++ yyerror("Error in year");
++ YYERROR;
++ }
++ if (exectm.tm_year < 70) {
++ exectm.tm_year += 100;
++ }
++ else if (exectm.tm_year > 1900) {
++ exectm.tm_year -= 1900;
++ }
++
++ free ($1);
+ }
+ else {
+ sscanf($1, "%d", &exectm.tm_hour);
+@@ -148,7 +206,7 @@
+ YYERROR;
+ }
+ if (exectm.tm_hour > 24 || exectm.tm_hour < 0) {
+- yyerror("Problem in minutes specification");
++ yyerror("Problem in hours specification");
+ YYERROR;
+ }
+ }
+@@ -181,6 +239,15 @@
+ ;
+
+ am_pm : AM
++ {
++ if (exectm.tm_hour > 12) {
++ yyerror("Hour too large for AM");
++ YYERROR;
++ }
++ else if (exectm.tm_hour == 12) {
++ exectm.tm_hour = 0;
++ }
++ }
+ | PM
+ {
+ if (exectm.tm_hour > 12) {
+@@ -319,6 +386,24 @@
+ }
+
+ #ifdef TEST_PARSER
++/*
++
++Here are some lines to test:
++
++./parsetest 7AM Mar 24 2000
++./parsetest 7AM Mar 24 00
++./parsetest 7AM 032400
++./parsetest 7AM 03/24/00
++./parsetest 7AM 24.03.00
++./parsetest 7AM Mar 24
++
++./parsetest 03242000
++./parsetest noon 03242000
++./parsetest 5:30
++./parsetest 4pm + 3 days
++./parsetest 10am Jul 31
++
++ */
+ int
+ main(int argc, char **argv)
+ {