cvsdist a5082c
diff -u at-3.1.8-orig/parsetime.l at-3.1.8/parsetime.l
cvsdist a5082c
--- at-3.1.8-orig/parsetime.l	Sun Sep 28 13:26:30 1997
cvsdist a5082c
+++ at-3.1.8/parsetime.l	Sat Jan 26 14:18:10 2002
cvsdist a5082c
@@ -32,7 +32,6 @@
cvsdist a5082c
     } while(0)
cvsdist a5082c
 %}
cvsdist a5082c
 
cvsdist a5082c
-WORD		[a-z][a-z0-9]+
cvsdist a5082c
 %%
cvsdist a5082c
 
cvsdist a5082c
 now		{ COPY_TOK ; return NOW; }
cvsdist a5082c
@@ -57,6 +56,7 @@
cvsdist a5082c
 day(s)?		{ COPY_TOK ; return DAY; }
cvsdist a5082c
 week(s)?	{ COPY_TOK ; return WEEK; }
cvsdist a5082c
 month(s)?	{ COPY_TOK ; return MONTH; }
cvsdist a5082c
+year(s)?	{ COPY_TOK ; return YEAR; }
cvsdist a5082c
 jan(uary)?	{ COPY_TOK ; return JAN; }
cvsdist a5082c
 feb(ruary)?	{ COPY_TOK ; return FEB; }
cvsdist a5082c
 mar(ch)?	{ COPY_TOK ; return MAR; }
cvsdist a5082c
@@ -69,9 +69,16 @@
cvsdist a5082c
 oct(ober)?	{ COPY_TOK ; return OCT; }
cvsdist a5082c
 nov(ember)?	{ COPY_TOK ; return NOV; }
cvsdist a5082c
 dec(ember)?	{ COPY_TOK ; return DEC; }
cvsdist a5082c
+utc		{ COPY_TOK ; return UTC; }
cvsdist a5082c
+[0-9]{1}	{ COPY_TOK ; COPY_VAL; return INT1DIGIT; }
cvsdist a5082c
+[0-9]{2}	{ COPY_TOK ; COPY_VAL; return INT2DIGIT; }
cvsdist a5082c
+[0-9]{4}	{ COPY_TOK ; COPY_VAL; return INT4DIGIT; }
cvsdist a5082c
+[0-9]{5,8}	{ COPY_TOK ; COPY_VAL; return INT5_8DIGIT; }
cvsdist a5082c
 [0-9]+		{ COPY_TOK ; COPY_VAL; return INT; }
cvsdist a5082c
+[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{2}([0-9]{2})?	{ COPY_TOK ; COPY_VAL; return DOTTEDDATE; }
cvsdist a5082c
+[0-9]{2}([0-9]{2})?-[0-9]{1,2}-[0-9]{1,2}	{ COPY_TOK ; COPY_VAL; return HYPHENDATE; }
cvsdist a5082c
+[012]?[0-9][:'h,.][0-9]{2}	{ COPY_TOK ; COPY_VAL; return HOURMIN; }
cvsdist a5082c
 [ \t\n]		;
cvsdist a5082c
-{WORD}		{ COPY_TOK ; COPY_VAL; return WORD; }
cvsdist a5082c
 .		{ COPY_TOK ; return yytext[0]; }
cvsdist a5082c
 
cvsdist a5082c
 %%
cvsdist a5082c
diff -u at-3.1.8-orig/parsetime.y at-3.1.8/parsetime.y
cvsdist a5082c
--- at-3.1.8-orig/parsetime.y	Thu Jan 17 22:15:27 2002
cvsdist a5082c
+++ at-3.1.8/parsetime.y	Sat Jan 26 14:25:25 2002
cvsdist a5082c
@@ -22,6 +22,13 @@
cvsdist a5082c
 	int		intval;
cvsdist a5082c
 }
cvsdist a5082c
 
cvsdist a5082c
+%token  <charval> DOTTEDDATE
cvsdist a5082c
+%token  <charval> HYPHENDATE
cvsdist a5082c
+%token  <charval> HOURMIN
cvsdist a5082c
+%token  <charval> INT1DIGIT
cvsdist a5082c
+%token  <charval> INT2DIGIT
cvsdist a5082c
+%token  <charval> INT4DIGIT
cvsdist a5082c
+%token  <charval> INT5_8DIGIT
cvsdist a5082c
 %token  <charval> INT
cvsdist a5082c
 %token  NOW
cvsdist a5082c
 %token  AM PM
cvsdist a5082c
@@ -31,48 +38,61 @@
cvsdist a5082c
 %token  NEXT
cvsdist a5082c
 %token  MINUTE HOUR DAY WEEK MONTH YEAR
cvsdist a5082c
 %token  JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
cvsdist a5082c
-%token  <charval> WORD
cvsdist a5082c
+%token  UTC
cvsdist a5082c
 
cvsdist a5082c
-%type <intval> inc_period
cvsdist a5082c
-%type <intval> inc_number
cvsdist a5082c
+%type <charval> concatenated_date
cvsdist a5082c
+%type <charval> hr24clock_hr_min
cvsdist a5082c
+%type <charval> int1_2digit
cvsdist a5082c
+%type <charval> int2_or_4digit
cvsdist a5082c
+%type <charval> integer
cvsdist a5082c
+%type <intval> inc_dec_period
cvsdist a5082c
+%type <intval> inc_dec_number
cvsdist a5082c
 %type <intval> day_of_week
cvsdist a5082c
 
cvsdist a5082c
 %start timespec
cvsdist a5082c
 %%
cvsdist a5082c
-timespec        : date
cvsdist a5082c
+timespec        : spec_base
cvsdist a5082c
+		| spec_base inc_or_dec
cvsdist a5082c
+		    {
cvsdist a5082c
+			time_only = 0;
cvsdist a5082c
+
cvsdist a5082c
+		    }
cvsdist a5082c
+                ;
cvsdist a5082c
+
cvsdist a5082c
+spec_base	: date
cvsdist a5082c
 		| time
cvsdist a5082c
 		    {
cvsdist a5082c
 			time_only = 1;
cvsdist a5082c
 		    }
cvsdist a5082c
                 | time date
cvsdist a5082c
-                | time_or_not inc_or_dec
cvsdist a5082c
-                | time_or_not date inc_or_dec
cvsdist a5082c
-                | nowspec
cvsdist a5082c
-                ;
cvsdist a5082c
+                | NOW
cvsdist a5082c
+		;
cvsdist a5082c
 
cvsdist a5082c
-nowspec         : now
cvsdist a5082c
-                | now inc_or_dec
cvsdist a5082c
+time		: time_base
cvsdist a5082c
+		| time_base timezone_name
cvsdist a5082c
                 ;
cvsdist a5082c
 
cvsdist a5082c
-now		: NOW 
cvsdist a5082c
-                | TOMORROW
cvsdist a5082c
-		   {
cvsdist a5082c
-			add_date(1, DAY);
cvsdist a5082c
-		   }
cvsdist a5082c
-		;
cvsdist a5082c
-
cvsdist a5082c
-time_or_not     : time
cvsdist a5082c
-		|
cvsdist a5082c
+time_base	: hr24clock_hr_min
cvsdist a5082c
+		    {
cvsdist a5082c
+			exectm.tm_min = -1;
cvsdist a5082c
+			exectm.tm_hour = -1;
cvsdist a5082c
+			sscanf($1, "%2d %2d", &exectm.tm_hour,
cvsdist a5082c
+			    &exectm.tm_min);
cvsdist a5082c
+			free($1);
cvsdist a5082c
 
cvsdist a5082c
-time            : hr24clock_hr_min
cvsdist a5082c
-                | hr24clock_hr_min timezone_name
cvsdist a5082c
-                | hr24clock_hour time_sep minute
cvsdist a5082c
-                | hr24clock_hour time_sep minute timezone_name
cvsdist a5082c
-                | hr24clock_hour am_pm
cvsdist a5082c
-                | hr24clock_hour am_pm timezone_name
cvsdist a5082c
-                | hr24clock_hour time_sep minute am_pm
cvsdist a5082c
-                | hr24clock_hour time_sep minute am_pm timezone_name
cvsdist a5082c
-                | NOON
cvsdist a5082c
+			if (exectm.tm_min > 60 || exectm.tm_min < 0) {
cvsdist a5082c
+			    yyerror("Problem in minutes specification");
cvsdist a5082c
+			    YYERROR;
cvsdist a5082c
+			}
cvsdist a5082c
+			if (exectm.tm_hour > 24 || exectm.tm_hour < 0) {
cvsdist a5082c
+			    yyerror("Problem in hours specification");
cvsdist a5082c
+			    YYERROR;
cvsdist a5082c
+		        }
cvsdist a5082c
+		    }
cvsdist a5082c
+		| time_hour am_pm
cvsdist a5082c
+		| time_hour_min
cvsdist a5082c
+		| time_hour_min am_pm
cvsdist a5082c
+		| NOON
cvsdist a5082c
 		    {
cvsdist a5082c
 			exectm.tm_hour = 12;
cvsdist a5082c
 			exectm.tm_min = 0;
cvsdist a5082c
@@ -81,128 +101,23 @@
cvsdist a5082c
 		    {
cvsdist a5082c
 			exectm.tm_hour = 0;
cvsdist a5082c
 			exectm.tm_min = 0;
cvsdist a5082c
-			add_date(1, DAY);
cvsdist a5082c
 		    }
cvsdist a5082c
 		| TEATIME
cvsdist a5082c
 		    {
cvsdist a5082c
 			exectm.tm_hour = 16;
cvsdist a5082c
 			exectm.tm_min = 0;
cvsdist a5082c
 		    }
cvsdist a5082c
-                ;
cvsdist a5082c
-
cvsdist a5082c
-date            : month_name day_number
cvsdist a5082c
-                | month_name day_number year_number
cvsdist a5082c
-                | month_name day_number ',' year_number
cvsdist a5082c
-                | day_of_week
cvsdist a5082c
-		   {
cvsdist a5082c
-		       add_date ((6 + $1 - exectm.tm_wday) %7 + 1, DAY);
cvsdist a5082c
-		   }
cvsdist a5082c
-                | TODAY
cvsdist a5082c
-                | TOMORROW
cvsdist a5082c
-		   {
cvsdist a5082c
-			add_date(1, DAY);
cvsdist a5082c
-		   }
cvsdist a5082c
-		| year_number '-' month_number '-' day_number
cvsdist a5082c
-		| day_number '.' month_number '.' year_number
cvsdist a5082c
-		| day_number '.' month_number
cvsdist a5082c
-		| day_number month_name
cvsdist a5082c
-		| day_number month_name year_number
cvsdist a5082c
-		| month_number '/' day_number '/' year_number
cvsdist a5082c
-                ;
cvsdist a5082c
-
cvsdist a5082c
-inc_or_dec	: increment
cvsdist a5082c
-		| decrement
cvsdist a5082c
-
cvsdist a5082c
-increment       : '+' inc_number inc_period
cvsdist a5082c
-		    {
cvsdist a5082c
-		        add_date($2, $3);
cvsdist a5082c
-		    }
cvsdist a5082c
-                | NEXT inc_period		
cvsdist a5082c
-		    {
cvsdist a5082c
-			add_date(1, $2);
cvsdist a5082c
-		    }
cvsdist a5082c
-		| NEXT day_of_week
cvsdist a5082c
-		    {
cvsdist a5082c
-			add_date ((6 + $2 - exectm.tm_wday) %7 +1, DAY);
cvsdist a5082c
-		    }
cvsdist a5082c
-                ;
cvsdist a5082c
-
cvsdist a5082c
-decrement	: '-' inc_number inc_period
cvsdist a5082c
-		    {
cvsdist a5082c
-			add_date(-$2, $3);
cvsdist a5082c
-		    }
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-inc_period      : MINUTE { $$ = MINUTE ; }
cvsdist a5082c
-                | HOUR	 { $$ = HOUR ; }
cvsdist a5082c
-                | DAY	 { $$ = DAY ; }
cvsdist a5082c
-                | WEEK   { $$ = WEEK ; }
cvsdist a5082c
-                | MONTH  { $$ = MONTH ; }
cvsdist a5082c
-                | YEAR   { $$ = YEAR ; }
cvsdist a5082c
-                ;
cvsdist a5082c
+hr24clock_hr_min: INT4DIGIT
cvsdist a5082c
+		;
cvsdist a5082c
 
cvsdist a5082c
-hr24clock_hr_min: INT
cvsdist a5082c
+time_hour	: int1_2digit
cvsdist a5082c
 		    {
cvsdist a5082c
-			if (strlen($1) == 4) {
cvsdist a5082c
-			    exectm.tm_min = -1;
cvsdist a5082c
-			    exectm.tm_hour = -1;
cvsdist a5082c
-			    sscanf($1, "%2d %2d", &exectm.tm_hour,
cvsdist a5082c
-				&exectm.tm_min);
cvsdist a5082c
-			} else if (strlen($1) >= 5 && strlen($1) <= 8) {
cvsdist a5082c
-				/* Ok, this is a kluge.  I hate design errors...  -Joey */
cvsdist a5082c
-				char shallot[5];
cvsdist a5082c
-				char *onion;
cvsdist a5082c
-
cvsdist a5082c
-				onion=$1;
cvsdist a5082c
-				memset (shallot, 0, sizeof (shallot));
cvsdist a5082c
-				if (strlen($1) == 5 || strlen($1) == 7) {
cvsdist a5082c
-				    strncpy (shallot,onion,1);
cvsdist a5082c
-				    onion++;
cvsdist a5082c
-				} else {
cvsdist a5082c
-				    strncpy (shallot,onion,2);
cvsdist a5082c
-				    onion+=2;
cvsdist a5082c
-				}
cvsdist a5082c
-				sscanf(shallot, "%d", &exectm.tm_mon);
cvsdist a5082c
-
cvsdist a5082c
-				if (exectm.tm_mon < 1 || exectm.tm_mon > 12) {
cvsdist a5082c
-				    yyerror("Error in month number");
cvsdist a5082c
-				    YYERROR;
cvsdist a5082c
-				}
cvsdist a5082c
-				exectm.tm_mon--;
cvsdist a5082c
-
cvsdist a5082c
-				memset (shallot, 0, sizeof (shallot));
cvsdist a5082c
-				strncpy (shallot,onion,2);
cvsdist a5082c
-			    	sscanf(shallot, "%d", &exectm.tm_mday);
cvsdist a5082c
-				if (exectm.tm_mday < 0 || exectm.tm_mday > 31)
cvsdist a5082c
-				{
cvsdist a5082c
-				    yyerror("Error in day of month");
cvsdist a5082c
-				    YYERROR;
cvsdist a5082c
-				}
cvsdist a5082c
-
cvsdist a5082c
-				onion+=2;
cvsdist a5082c
-				memset (shallot, 0, sizeof (shallot));
cvsdist a5082c
-				strncpy (shallot,onion,4);
cvsdist a5082c
-				if ( sscanf(shallot, "%d", &exectm.tm_year) != 1) {
cvsdist a5082c
-				    yyerror("Error in year");
cvsdist a5082c
-				    YYERROR;
cvsdist a5082c
-				}
cvsdist a5082c
-				if (exectm.tm_year < 70) {
cvsdist a5082c
-				    exectm.tm_year += 100;
cvsdist a5082c
-				}
cvsdist a5082c
-				else if (exectm.tm_year > 1900) {
cvsdist a5082c
-				    exectm.tm_year -= 1900;
cvsdist a5082c
-				}
cvsdist a5082c
-			}
cvsdist a5082c
-			else {
cvsdist a5082c
-			    sscanf($1, "%d", &exectm.tm_hour);
cvsdist a5082c
-			    exectm.tm_min = 0;
cvsdist a5082c
-			}
cvsdist a5082c
+			sscanf($1, "%d", &exectm.tm_hour);
cvsdist a5082c
+			exectm.tm_min = 0;
cvsdist a5082c
 			free($1);
cvsdist a5082c
 
cvsdist a5082c
-			if (exectm.tm_min > 60 || exectm.tm_min < 0) {
cvsdist a5082c
-			    yyerror("Problem in minutes specification");
cvsdist a5082c
-			    YYERROR;
cvsdist a5082c
-			}
cvsdist a5082c
 			if (exectm.tm_hour > 24 || exectm.tm_hour < 0) {
cvsdist a5082c
 			    yyerror("Problem in hours specification");
cvsdist a5082c
 			    YYERROR;
cvsdist a5082c
@@ -210,29 +125,22 @@
cvsdist a5082c
 		    }
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-timezone_name	: WORD
cvsdist a5082c
+time_hour_min	: HOURMIN
cvsdist a5082c
 		    {
cvsdist a5082c
-			if (strcasecmp($1,"utc") == 0) {
cvsdist a5082c
-			    isgmt = 1;
cvsdist a5082c
-			}
cvsdist a5082c
-			else {
cvsdist a5082c
-			    yyerror("Only UTC timezone is supported");
cvsdist a5082c
-			    YYERROR;
cvsdist a5082c
-			}
cvsdist a5082c
+			exectm.tm_min = -1;
cvsdist a5082c
+			exectm.tm_hour = -1;
cvsdist a5082c
+			sscanf($1, "%d %*c %d", &exectm.tm_hour,
cvsdist a5082c
+			    &exectm.tm_min);
cvsdist a5082c
 			free($1);
cvsdist a5082c
-		    }
cvsdist a5082c
-		;
cvsdist a5082c
-
cvsdist a5082c
-hr24clock_hour	: hr24clock_hr_min
cvsdist a5082c
-		;
cvsdist a5082c
 
cvsdist a5082c
-minute		: INT
cvsdist a5082c
-                    {
cvsdist a5082c
-			if (sscanf($1, "%d", &exectm.tm_min) != 1) {
cvsdist a5082c
-			    yyerror("Error in minute");
cvsdist a5082c
+			if (exectm.tm_min > 60 || exectm.tm_min < 0) {
cvsdist a5082c
+			    yyerror("Problem in minutes specification");
cvsdist a5082c
+			    YYERROR;
cvsdist a5082c
+			}
cvsdist a5082c
+			if (exectm.tm_hour > 24 || exectm.tm_hour < 0) {
cvsdist a5082c
+			    yyerror("Problem in hours specification");
cvsdist a5082c
 			    YYERROR;
cvsdist a5082c
 		        }
cvsdist a5082c
-			free($1);
cvsdist a5082c
 		    }
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
@@ -258,6 +166,171 @@
cvsdist a5082c
 		    }
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
+timezone_name	: UTC
cvsdist a5082c
+		    {
cvsdist a5082c
+			isgmt = 1;
cvsdist a5082c
+		    }
cvsdist a5082c
+		;
cvsdist a5082c
+
cvsdist a5082c
+date            : month_name day_number
cvsdist a5082c
+                | month_name day_number year_number
cvsdist a5082c
+                | month_name day_number ',' year_number
cvsdist a5082c
+                | day_of_week
cvsdist a5082c
+		   {
cvsdist a5082c
+		       add_date ((6 + $1 - exectm.tm_wday) %7 + 1, DAY);
cvsdist a5082c
+		   }
cvsdist a5082c
+                | TODAY
cvsdist a5082c
+                | TOMORROW
cvsdist a5082c
+		   {
cvsdist a5082c
+			add_date(1, DAY);
cvsdist a5082c
+		   }
cvsdist a5082c
+		| HYPHENDATE
cvsdist a5082c
+		   {
cvsdist a5082c
+			int ynum = -1;
cvsdist a5082c
+			int mnum = -1;
cvsdist a5082c
+			int dnum = -1;
cvsdist a5082c
+
cvsdist a5082c
+			if (sscanf($1, "%d %*c %d %*c %d", &ynum, &mnum, &dnum) != 3) {
cvsdist a5082c
+			    yyerror("Error in hypenated date");
cvsdist a5082c
+			    YYERROR;
cvsdist a5082c
+			}
cvsdist a5082c
+
cvsdist a5082c
+			if (mnum < 1 || mnum > 12) {
cvsdist a5082c
+			    yyerror("Error in month number");
cvsdist a5082c
+			    YYERROR;
cvsdist a5082c
+			}
cvsdist a5082c
+			exectm.tm_mon = mnum -1;
cvsdist a5082c
+
cvsdist a5082c
+			if (ynum < 70) {
cvsdist a5082c
+			    ynum += 100;
cvsdist a5082c
+			}
cvsdist a5082c
+			else if (ynum > 1900) {
cvsdist a5082c
+			    ynum -= 1900;
cvsdist a5082c
+			}
cvsdist a5082c
+			exectm.tm_year = ynum ;
cvsdist a5082c
+
cvsdist a5082c
+			if (   dnum < 0
cvsdist a5082c
+			    || ((mnum ==  1 || mnum ==  3 || mnum ==  5 ||
cvsdist a5082c
+			         mnum ==  7 || mnum ==  8 || mnum == 10 ||
cvsdist a5082c
+				 mnum == 12) && dnum > 31)
cvsdist a5082c
+			    || ((mnum ==  4 || mnum ==  6 || mnum ==  9 ||
cvsdist a5082c
+			         mnum == 11) && dnum > 30)
cvsdist a5082c
+			    || (mnum ==  2 && dnum > 29 &&  __isleap(ynum+1900))
cvsdist a5082c
+			    || (mnum ==  2 && dnum > 28 && !__isleap(ynum+1900))
cvsdist a5082c
+			   )
cvsdist a5082c
+			{
cvsdist a5082c
+			    yyerror("Error in day of month");
cvsdist a5082c
+			    YYERROR; 
cvsdist a5082c
+			}
cvsdist a5082c
+			exectm.tm_mday = dnum;
cvsdist a5082c
+
cvsdist a5082c
+			free($1);
cvsdist a5082c
+		   }
cvsdist a5082c
+		| DOTTEDDATE
cvsdist a5082c
+		   {
cvsdist a5082c
+			int ynum = -1;
cvsdist a5082c
+			int mnum = -1;
cvsdist a5082c
+			int dnum = -1;
cvsdist a5082c
+
cvsdist a5082c
+			if (sscanf($1, "%d %*c %d %*c %d", &dnum, &mnum, &ynum) != 3) {
cvsdist a5082c
+			    yyerror("Error in dotted date");
cvsdist a5082c
+			    YYERROR;
cvsdist a5082c
+			}
cvsdist a5082c
+
cvsdist a5082c
+			if (mnum < 1 || mnum > 12) {
cvsdist a5082c
+			    yyerror("Error in month number");
cvsdist a5082c
+			    YYERROR;
cvsdist a5082c
+			}
cvsdist a5082c
+			exectm.tm_mon = mnum -1;
cvsdist a5082c
+
cvsdist a5082c
+			if (ynum < 70) {
cvsdist a5082c
+			    ynum += 100;
cvsdist a5082c
+			}
cvsdist a5082c
+			else if (ynum > 1900) {
cvsdist a5082c
+			    ynum -= 1900;
cvsdist a5082c
+			}
cvsdist a5082c
+			exectm.tm_year = ynum ;
cvsdist a5082c
+
cvsdist a5082c
+			if (   dnum < 0
cvsdist a5082c
+			    || ((mnum ==  1 || mnum ==  3 || mnum ==  5 ||
cvsdist a5082c
+			         mnum ==  7 || mnum ==  8 || mnum == 10 ||
cvsdist a5082c
+				 mnum == 12) && dnum > 31)
cvsdist a5082c
+			    || ((mnum ==  4 || mnum ==  6 || mnum ==  9 ||
cvsdist a5082c
+			         mnum == 11) && dnum > 30)
cvsdist a5082c
+			    || (mnum ==  2 && dnum > 29 &&  __isleap(ynum+1900))
cvsdist a5082c
+			    || (mnum ==  2 && dnum > 28 && !__isleap(ynum+1900))
cvsdist a5082c
+			   )
cvsdist a5082c
+			{
cvsdist a5082c
+			    yyerror("Error in day of month");
cvsdist a5082c
+			    YYERROR; 
cvsdist a5082c
+			}
cvsdist a5082c
+			exectm.tm_mday = dnum;
cvsdist a5082c
+
cvsdist a5082c
+			free($1);
cvsdist a5082c
+		   }
cvsdist a5082c
+		| day_number month_name
cvsdist a5082c
+		| day_number month_name year_number
cvsdist a5082c
+		| month_number '/' day_number '/' year_number
cvsdist a5082c
+		| concatenated_date
cvsdist a5082c
+		    {
cvsdist a5082c
+			/* Ok, this is a kluge.  I hate design errors...  -Joey */
cvsdist a5082c
+			char shallot[5];
cvsdist a5082c
+			char *onion;
cvsdist a5082c
+
cvsdist a5082c
+			onion=$1;
cvsdist a5082c
+			memset (shallot, 0, sizeof (shallot));
cvsdist a5082c
+			if (strlen($1) == 5 || strlen($1) == 7) {
cvsdist a5082c
+			    strncpy (shallot,onion,1);
cvsdist a5082c
+			    onion++;
cvsdist a5082c
+			} else {
cvsdist a5082c
+			    strncpy (shallot,onion,2);
cvsdist a5082c
+			    onion+=2;
cvsdist a5082c
+			}
cvsdist a5082c
+			sscanf(shallot, "%d", &exectm.tm_mon);
cvsdist a5082c
+
cvsdist a5082c
+			if (exectm.tm_mon < 1 || exectm.tm_mon > 12) {
cvsdist a5082c
+			    yyerror("Error in month number");
cvsdist a5082c
+			    YYERROR;
cvsdist a5082c
+			}
cvsdist a5082c
+			exectm.tm_mon--;
cvsdist a5082c
+
cvsdist a5082c
+			memset (shallot, 0, sizeof (shallot));
cvsdist a5082c
+			strncpy (shallot,onion,2);
cvsdist a5082c
+		    	sscanf(shallot, "%d", &exectm.tm_mday);
cvsdist a5082c
+			if (exectm.tm_mday < 0 || exectm.tm_mday > 31)
cvsdist a5082c
+			{
cvsdist a5082c
+			    yyerror("Error in day of month");
cvsdist a5082c
+			    YYERROR;
cvsdist a5082c
+			}
cvsdist a5082c
+
cvsdist a5082c
+			onion+=2;
cvsdist a5082c
+			memset (shallot, 0, sizeof (shallot));
cvsdist a5082c
+			strncpy (shallot,onion,4);
cvsdist a5082c
+			if ( sscanf(shallot, "%d", &exectm.tm_year) != 1) {
cvsdist a5082c
+			    yyerror("Error in year");
cvsdist a5082c
+			    YYERROR;
cvsdist a5082c
+			}
cvsdist a5082c
+			if (exectm.tm_year < 70) {
cvsdist a5082c
+			    exectm.tm_year += 100;
cvsdist a5082c
+			}
cvsdist a5082c
+			else if (exectm.tm_year > 1900) {
cvsdist a5082c
+			    exectm.tm_year -= 1900;
cvsdist a5082c
+			}
cvsdist a5082c
+
cvsdist a5082c
+			free ($1);
cvsdist a5082c
+		    }
cvsdist a5082c
+                | NEXT inc_dec_period		
cvsdist a5082c
+		    {
cvsdist a5082c
+			add_date(1, $2);
cvsdist a5082c
+		    }
cvsdist a5082c
+		| NEXT day_of_week
cvsdist a5082c
+		    {
cvsdist a5082c
+			add_date ((6 + $2 - exectm.tm_wday) %7 +1, DAY);
cvsdist a5082c
+		    }
cvsdist a5082c
+                ;
cvsdist a5082c
+
cvsdist a5082c
+concatenated_date: INT5_8DIGIT
cvsdist a5082c
+		;
cvsdist a5082c
 
cvsdist a5082c
 month_name	: JAN { exectm.tm_mon = 0; }
cvsdist a5082c
 		| FEB { exectm.tm_mon = 1; }
cvsdist a5082c
@@ -273,7 +346,7 @@
cvsdist a5082c
 		| DEC { exectm.tm_mon =11; }
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-month_number	: INT
cvsdist a5082c
+month_number	: int1_2digit
cvsdist a5082c
 		    {
cvsdist a5082c
 			{
cvsdist a5082c
 			    int mnum = -1;
cvsdist a5082c
@@ -287,7 +360,9 @@
cvsdist a5082c
 			    free($1);
cvsdist a5082c
 			}
cvsdist a5082c
 		    }
cvsdist a5082c
-day_number	: INT
cvsdist a5082c
+		;
cvsdist a5082c
+
cvsdist a5082c
+day_number	: int1_2digit
cvsdist a5082c
                      {
cvsdist a5082c
 			exectm.tm_mday = -1;
cvsdist a5082c
 			sscanf($1, "%d", &exectm.tm_mday);
cvsdist a5082c
@@ -300,7 +375,7 @@
cvsdist a5082c
 		     }
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-year_number	: INT
cvsdist a5082c
+year_number	: int2_or_4digit
cvsdist a5082c
 		    { 
cvsdist a5082c
 			{
cvsdist a5082c
 			    int ynum;
cvsdist a5082c
@@ -322,7 +397,6 @@
cvsdist a5082c
 		    }
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-
cvsdist a5082c
 day_of_week	: SUN { $$ = 0; }
cvsdist a5082c
 		| MON { $$ = 1; }
cvsdist a5082c
 		| TUE { $$ = 2; }
cvsdist a5082c
@@ -332,7 +406,23 @@
cvsdist a5082c
 		| SAT { $$ = 6; }
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-inc_number	: INT
cvsdist a5082c
+inc_or_dec	: increment
cvsdist a5082c
+		| decrement
cvsdist a5082c
+		;
cvsdist a5082c
+
cvsdist a5082c
+increment       : '+' inc_dec_number inc_dec_period
cvsdist a5082c
+		    {
cvsdist a5082c
+		        add_date($2, $3);
cvsdist a5082c
+		    }
cvsdist a5082c
+                ;
cvsdist a5082c
+
cvsdist a5082c
+decrement	: '-' inc_dec_number inc_dec_period
cvsdist a5082c
+		    {
cvsdist a5082c
+			add_date(-$2, $3);
cvsdist a5082c
+		    }
cvsdist a5082c
+		;
cvsdist a5082c
+
cvsdist a5082c
+inc_dec_number	: integer
cvsdist a5082c
 		    {
cvsdist a5082c
 			if (sscanf($1, "%d", &$$) != 1) {
cvsdist a5082c
 			    yyerror("Unknown increment");
cvsdist a5082c
@@ -342,11 +432,27 @@
cvsdist a5082c
 		    }
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-time_sep	: ':'
cvsdist a5082c
-		| '\''
cvsdist a5082c
-		| '.'
cvsdist a5082c
-		| 'h'
cvsdist a5082c
-		| ','
cvsdist a5082c
+inc_dec_period	: MINUTE { $$ = MINUTE ; }
cvsdist a5082c
+		| HOUR	 { $$ = HOUR   ; }
cvsdist a5082c
+		| DAY	 { $$ = DAY    ; }
cvsdist a5082c
+		| WEEK   { $$ = WEEK   ; }
cvsdist a5082c
+		| MONTH  { $$ = MONTH  ; }
cvsdist a5082c
+		| YEAR   { $$ = YEAR   ; }
cvsdist a5082c
+		;
cvsdist a5082c
+
cvsdist a5082c
+int1_2digit	: INT1DIGIT
cvsdist a5082c
+		| INT2DIGIT
cvsdist a5082c
+		;
cvsdist a5082c
+
cvsdist a5082c
+int2_or_4digit	: INT2DIGIT
cvsdist a5082c
+		| INT4DIGIT
cvsdist a5082c
+		;
cvsdist a5082c
+
cvsdist a5082c
+integer		: INT
cvsdist a5082c
+		| INT1DIGIT
cvsdist a5082c
+		| INT2DIGIT
cvsdist a5082c
+		| INT4DIGIT
cvsdist a5082c
+		| INT5_8DIGIT
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
 %%
cvsdist a5082c
@@ -370,10 +476,7 @@
cvsdist a5082c
 	if (exectime == (time_t)-1)
cvsdist a5082c
 	    return 0;
cvsdist a5082c
 	if (isgmt) {
cvsdist a5082c
-	    exectime += timezone;
cvsdist a5082c
-	    if (daylight) {
cvsdist a5082c
-		exectime -= 3600;
cvsdist a5082c
-	    }
cvsdist a5082c
+	    exectime -= timezone;
cvsdist a5082c
 	}
cvsdist a5082c
 	if (time_only && (currtime > exectime)) {
cvsdist a5082c
 	    exectime += 24*3600;
cvsdist a5082c
@@ -386,39 +489,29 @@
cvsdist a5082c
 }
cvsdist a5082c
 
cvsdist a5082c
 #ifdef TEST_PARSER
cvsdist a5082c
-/*
cvsdist a5082c
-
cvsdist a5082c
-Here are some lines to test:
cvsdist a5082c
-
cvsdist a5082c
-./parsetest 7AM Mar 24 2000
cvsdist a5082c
-./parsetest 7AM Mar 24 00
cvsdist a5082c
-./parsetest 7AM 032400
cvsdist a5082c
-./parsetest 7AM 03/24/00
cvsdist a5082c
-./parsetest 7AM 24.03.00
cvsdist a5082c
-./parsetest 7AM Mar 24
cvsdist a5082c
-
cvsdist a5082c
-./parsetest 03242000
cvsdist a5082c
-./parsetest noon 03242000
cvsdist a5082c
-./parsetest 5:30
cvsdist a5082c
-./parsetest 4pm + 3 days
cvsdist a5082c
-./parsetest 10am Jul 31
cvsdist a5082c
-
cvsdist a5082c
- */
cvsdist a5082c
+ 
cvsdist a5082c
 int
cvsdist a5082c
 main(int argc, char **argv)
cvsdist a5082c
 {
cvsdist a5082c
+    int retval = 1;
cvsdist a5082c
     time_t res;
cvsdist a5082c
     res = parsetime(argc-1, &argv[1]);
cvsdist a5082c
+    if (time_only) {
cvsdist a5082c
+	fprintf(stderr, "time_only = 1\n");
cvsdist a5082c
+    }
cvsdist a5082c
     if (res > 0) {
cvsdist a5082c
 	printf("%s",ctime(&res));
cvsdist a5082c
+	retval = 0;
cvsdist a5082c
     }
cvsdist a5082c
     else {
cvsdist a5082c
 	printf("Ooops...\n");
cvsdist a5082c
+	retval = 1;
cvsdist a5082c
     }
cvsdist a5082c
-    return 0;
cvsdist a5082c
+    return retval;
cvsdist a5082c
 }
cvsdist a5082c
 
cvsdist a5082c
 #endif
cvsdist a5082c
+
cvsdist a5082c
 int yyerror(char *s)
cvsdist a5082c
 {
cvsdist a5082c
     if (last_token == NULL)
cvsdist a5082c
@@ -430,12 +523,36 @@
cvsdist a5082c
 void
cvsdist a5082c
 add_seconds(struct tm *tm, long numsec)
cvsdist a5082c
 {
cvsdist a5082c
+    struct tm basetm = *tm;
cvsdist a5082c
     time_t timeval;
cvsdist a5082c
+
cvsdist a5082c
     timeval = mktime(tm);
cvsdist a5082c
     if (timeval == (time_t)-1)
cvsdist a5082c
         timeval = (time_t)0;
cvsdist a5082c
     timeval += numsec;
cvsdist a5082c
     *tm = *localtime(&timeval);
cvsdist a5082c
+
cvsdist a5082c
+    /*
cvsdist a5082c
+     * Adjust +-1 hour when moving in or out of DST
cvsdist a5082c
+     */
cvsdist a5082c
+
cvsdist a5082c
+    if (daylight > 0)	/* Only check if DST is used here */
cvsdist a5082c
+    {
cvsdist a5082c
+	/* Set tm_isdst on &basetm and tm */
cvsdist a5082c
+	(void) mktime(&basetm);
cvsdist a5082c
+	(void) mktime(tm);
cvsdist a5082c
+
cvsdist a5082c
+	if      (basetm.tm_isdst > 0 && tm->tm_isdst < 1)
cvsdist a5082c
+	{   /* DST to no DST */
cvsdist a5082c
+	    timeval += 3600l;
cvsdist a5082c
+	    *tm = *localtime(&timeval);
cvsdist a5082c
+	}
cvsdist a5082c
+	else if (basetm.tm_isdst < 1 && tm->tm_isdst > 0)
cvsdist a5082c
+	{   /* no DST to DST */
cvsdist a5082c
+	    timeval -= 3600l;
cvsdist a5082c
+	    *tm = *localtime(&timeval);
cvsdist a5082c
+	}
cvsdist a5082c
+    }
cvsdist a5082c
 }
cvsdist a5082c
 
cvsdist a5082c
 int
cvsdist a5082c
@@ -468,6 +585,10 @@
cvsdist a5082c
 	    }
cvsdist a5082c
 	    exectm.tm_mon = newmonth % 12;
cvsdist a5082c
 	    number += newmonth / 12 ;
cvsdist a5082c
+
cvsdist a5082c
+	    /* Recalculate tm_isdst so we don't get a +-1 hour creep */
cvsdist a5082c
+	    exectm.tm_isdst = -1;
cvsdist a5082c
+	    (void) mktime(&exectm);
cvsdist a5082c
 	}
cvsdist a5082c
 	if (number == 0) {
cvsdist a5082c
 	    break;
cvsdist a5082c
@@ -476,6 +597,9 @@
cvsdist a5082c
 
cvsdist a5082c
     case YEAR:
cvsdist a5082c
 	exectm.tm_year += number;
cvsdist a5082c
+	/* Recalculate tm_isdst so we don't get a +-1 hour creep */
cvsdist a5082c
+	exectm.tm_isdst = -1;
cvsdist a5082c
+	(void) mktime(&exectm);
cvsdist a5082c
 	break;
cvsdist a5082c
 
cvsdist a5082c
     default:
cvsdist a5082c
@@ -483,5 +607,6 @@
cvsdist a5082c
 	fprintf(stderr,"Unexpected case %d\n", period);
cvsdist a5082c
 	abort();
cvsdist a5082c
     }
cvsdist a5082c
+
cvsdist a5082c
     return 0;
cvsdist a5082c
 }
cvsdist a5082c
diff -u at-3.1.8-orig/timespec at-3.1.8/timespec
cvsdist a5082c
--- at-3.1.8-orig/timespec	Wed Mar 12 12:11:05 1997
cvsdist a5082c
+++ at-3.1.8/timespec	Sat Jan 26 14:18:10 2002
cvsdist a5082c
@@ -2,6 +2,13 @@
cvsdist a5082c
  * Abbreviated version of the yacc grammar used by at(1).
cvsdist a5082c
  */
cvsdist a5082c
 
cvsdist a5082c
+%token  <charval> DOTTEDDATE
cvsdist a5082c
+%token  <charval> HYPHENDATE
cvsdist a5082c
+%token  <charval> HOURMIN
cvsdist a5082c
+%token  <charval> INT1DIGIT
cvsdist a5082c
+%token  <charval> INT2DIGIT
cvsdist a5082c
+%token  <charval> INT4DIGIT
cvsdist a5082c
+%token  <charval> INT5_8DIGIT
cvsdist a5082c
 %token  <charval> INT
cvsdist a5082c
 %token  NOW
cvsdist a5082c
 %token  AM PM
cvsdist a5082c
@@ -11,100 +18,115 @@
cvsdist a5082c
 %token  NEXT
cvsdist a5082c
 %token  MINUTE HOUR DAY WEEK MONTH YEAR
cvsdist a5082c
 %token  JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
cvsdist a5082c
-%token  <charval> WORD
cvsdist a5082c
+%token  UTC
cvsdist a5082c
 
cvsdist a5082c
-%type <intval> inc_period
cvsdist a5082c
-%type <intval> inc_number
cvsdist a5082c
+%type <charval> concatenated_date
cvsdist a5082c
+%type <charval> hr24clock_hr_min
cvsdist a5082c
+%type <charval> int1_2digit
cvsdist a5082c
+%type <charval> int2_or_4digit
cvsdist a5082c
+%type <charval> integer
cvsdist a5082c
+%type <intval> inc_dec_period
cvsdist a5082c
+%type <intval> inc_dec_number
cvsdist a5082c
 %type <intval> day_of_week
cvsdist a5082c
 
cvsdist a5082c
 %start timespec
cvsdist a5082c
 %%
cvsdist a5082c
-timespec        : time
cvsdist a5082c
-                | time date
cvsdist a5082c
-                | time increment
cvsdist a5082c
-                | time date increment
cvsdist a5082c
-		| time decrement
cvsdist a5082c
-		| time date decrement
cvsdist a5082c
-                | nowspec
cvsdist a5082c
-                ;
cvsdist a5082c
-
cvsdist a5082c
-nowspec         : now
cvsdist a5082c
-                | now increment
cvsdist a5082c
-		| now decrement
cvsdist a5082c
+timespec        : spec_base
cvsdist a5082c
+		| spec_base inc_or_dec
cvsdist a5082c
                 ;
cvsdist a5082c
 
cvsdist a5082c
-now		: NOW 
cvsdist a5082c
+spec_base	: date
cvsdist a5082c
+		| time
cvsdist a5082c
+                | time date
cvsdist a5082c
+                | NOW
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-time            : hr24clock_hr_min
cvsdist a5082c
-                | hr24clock_hr_min timezone_name
cvsdist a5082c
-                | hr24clock_hour time_sep minute
cvsdist a5082c
-                | hr24clock_hour time_sep minute timezone_name
cvsdist a5082c
-                | hr24clock_hour am_pm
cvsdist a5082c
-                | hr24clock_hour am_pm timezone_name
cvsdist a5082c
-                | hr24clock_hour time_sep minute am_pm
cvsdist a5082c
-                | hr24clock_hour time_sep minute am_pm timezone_name
cvsdist a5082c
-                | NOON
cvsdist a5082c
+time		: time_base
cvsdist a5082c
+		| time_base timezone_name
cvsdist a5082c
+                ;
cvsdist a5082c
+
cvsdist a5082c
+time_base	: hr24clock_hr_min
cvsdist a5082c
+		| time_hour am_pm
cvsdist a5082c
+		| time_hour_min
cvsdist a5082c
+		| time_hour_min am_pm
cvsdist a5082c
+		| NOON
cvsdist a5082c
                 | MIDNIGHT
cvsdist a5082c
 		| TEATIME
cvsdist a5082c
-                ;
cvsdist a5082c
+		;
cvsdist a5082c
+
cvsdist a5082c
+hr24clock_hr_min: INT4DIGIT
cvsdist a5082c
+		;
cvsdist a5082c
+
cvsdist a5082c
+time_hour	: int1_2digit
cvsdist a5082c
+		;
cvsdist a5082c
+
cvsdist a5082c
+time_hour_min	: HOURMIN
cvsdist a5082c
+		;
cvsdist a5082c
+
cvsdist a5082c
+am_pm		: AM
cvsdist a5082c
+		| PM
cvsdist a5082c
+		;
cvsdist a5082c
+
cvsdist a5082c
+timezone_name	: UTC
cvsdist a5082c
+		;
cvsdist a5082c
 
cvsdist a5082c
 date            : month_name day_number
cvsdist a5082c
+                | month_name day_number year_number
cvsdist a5082c
                 | month_name day_number ',' year_number
cvsdist a5082c
                 | day_of_week
cvsdist a5082c
                 | TODAY
cvsdist a5082c
                 | TOMORROW
cvsdist a5082c
-		| year_number '-' month_number '-' day_number
cvsdist a5082c
-		| day_number '.' month_number '.' year_number
cvsdist a5082c
-		| day_number '.' month_number
cvsdist a5082c
+		| HYPHENDATE
cvsdist a5082c
+		| DOTTEDDATE
cvsdist a5082c
 		| day_number month_name
cvsdist a5082c
 		| day_number month_name year_number
cvsdist a5082c
 		| month_number '/' day_number '/' year_number
cvsdist a5082c
-                ;
cvsdist a5082c
-
cvsdist a5082c
-increment       : '+' inc_number inc_period
cvsdist a5082c
-                | NEXT inc_period		
cvsdist a5082c
+		| concatenated_date
cvsdist a5082c
+                | NEXT inc_dec_period		
cvsdist a5082c
 		| NEXT day_of_week
cvsdist a5082c
                 ;
cvsdist a5082c
 
cvsdist a5082c
-decrement	: '-' inc_number inc_period
cvsdist a5082c
+concatenated_date: INT5_8DIGIT
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-inc_period      : MINUTE | HOUR | DAY | WEEK | MONTH | YEAR
cvsdist a5082c
+month_name	: JAN | FEB | MAR | APR | MAY | JUN
cvsdist a5082c
+		| JUL | AUG | SEP | OCT | NOV | DEC
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-hr24clock_hr_min: INT
cvsdist a5082c
+month_number	: int1_2digit
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-timezone_name	: WORD
cvsdist a5082c
+day_number	: int1_2digit
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-hr24clock_hour	: hr24clock_hr_min
cvsdist a5082c
+year_number	: int2_or_4digit
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-minute		: INT
cvsdist a5082c
+day_of_week	: SUN | MON | TUE | WED | THU | FRI | SAT
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-am_pm		: AM | PM
cvsdist a5082c
+inc_or_dec	: increment | decrement
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-month_name	: JAN | FEB | MAR | APR | MAY | JUN | JUL
cvsdist a5082c
-		| AUG | SEP | OCT | NOV | DEC
cvsdist a5082c
-		;
cvsdist a5082c
+increment       : '+' inc_dec_number inc_dec_period
cvsdist a5082c
+                ;
cvsdist a5082c
 
cvsdist a5082c
-month_number	: INT
cvsdist a5082c
+decrement	: '-' inc_dec_number inc_dec_period
cvsdist a5082c
 		;
cvsdist a5082c
-day_number	: INT
cvsdist a5082c
+
cvsdist a5082c
+inc_dec_number	: integer
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-year_number	: INT
cvsdist a5082c
+inc_dec_period	: MINUTE | HOUR | DAY | WEEK | MONTH | YEAR
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-day_of_week	: SUN | MON | TUE | WED | THU | FRI | SAT
cvsdist a5082c
+int1_2digit	: INT1DIGIT | INT2DIGIT
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-inc_number	: INT
cvsdist a5082c
+int2_or_4digit	: INT2DIGIT | INT4DIGIT
cvsdist a5082c
 		;
cvsdist a5082c
 
cvsdist a5082c
-time_sep	: ':' | '\'' | '.' | 'h' | ','
cvsdist a5082c
+integer		: INT | INT1DIGIT | INT2DIGIT | INT4DIGIT | INT5_8DIGIT
cvsdist a5082c
 		;
cvsdist a5082c
+
cvsdist a5082c
+%%