changeset 29175:a9f6931419d9

Adjust getdate's grammar to accept a slightly more regular language. E.g., accept "YYYYMMDD +N days" as well as "YYYYMMDD N days". Before, the former was rejected. * lib/getdate.y (digits_to_date_time): New function, factored out of ... (number): ...here. Just call digits_to_date_time. (hybrid): New non-terminal to handle an <unsigned number, signed relative offset> sequence consistently.
author Ondřej Vašík <ovasik@redhat.com>
date Thu, 22 Nov 2007 22:13:20 +0100
parents a9281f205548
children c47ccf70d67c
files ChangeLog lib/getdate.y
diffstat 2 files changed, 68 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Nov 18 11:51:26 2007 +0100
+++ b/ChangeLog	Thu Nov 22 22:13:20 2007 +0100
@@ -1,3 +1,15 @@
+2007-11-22  Ondřej Vašík  <ovasik@redhat.com>
+	and Jim Meyering  <meyering@redhat.com>
+
+	Adjust getdate' grammar to accept a slightly more regular language.
+	E.g., accept "YYYYMMDD +N days" as well as "YYYYMMDD N days".
+	Before, the former was rejected.
+	* lib/getdate.y (digits_to_date_time): New function, factored
+	out of ...
+	(number): ...here.  Just call digits_to_date_time.
+	(hybrid): New non-terminal to handle an <unsigned number,
+	signed relative offset> sequence consistently.
+
 2007-11-18  Jim Meyering  <meyering@redhat.com>
 
 	Pull my changes from coreutils:
--- a/lib/getdate.y	Sun Nov 18 11:51:26 2007 +0100
+++ b/lib/getdate.y	Thu Nov 22 22:13:20 2007 +0100
@@ -208,6 +208,45 @@
 static int yyerror (parser_control const *, char const *);
 static long int time_zone_hhmm (textint, long int);
 
+/* Extract into *PC any date and time info from a string of digits
+   of the form e.g., YYYYMMDD, YYMMDD, HHMM, HH (and sometimes YYY,
+   YYYY, ...).  */
+static void
+digits_to_date_time (parser_control *pc, textint text_int)
+{
+  if (pc->dates_seen && ! pc->year.digits
+      && ! pc->rels_seen && (pc->times_seen || 2 < text_int.digits))
+    pc->year = text_int;
+  else
+    {
+      if (4 < text_int.digits)
+	{
+	  pc->dates_seen++;
+	  pc->day = text_int.value % 100;
+	  pc->month = (text_int.value / 100) % 100;
+	  pc->year.value = text_int.value / 10000;
+	  pc->year.digits = text_int.digits - 4;
+	}
+      else
+	{
+	  pc->times_seen++;
+	  if (text_int.digits <= 2)
+	    {
+	      pc->hour = text_int.value;
+	      pc->minutes = 0;
+	    }
+	  else
+	    {
+	      pc->hour = text_int.value / 100;
+	      pc->minutes = text_int.value % 100;
+	    }
+	  pc->seconds.tv_sec = 0;
+	  pc->seconds.tv_nsec = 0;
+	  pc->meridian = MER24;
+	}
+    }
+}
+
 %}
 
 /* We want a reentrant parser, even if the TZ manipulation and the calls to
@@ -277,6 +316,7 @@
   | rel
       { pc->rels_seen = true; }
   | number
+  | hybrid
   ;
 
 time:
@@ -552,38 +592,23 @@
 
 number:
     tUNUMBER
+      { digits_to_date_time (pc, $1); }
+  ;
+
+hybrid:
+    tUNUMBER relunit_snumber
       {
-	if (pc->dates_seen && ! pc->year.digits
-	    && ! pc->rels_seen && (pc->times_seen || 2 < $1.digits))
-	  pc->year = $1;
-	else
-	  {
-	    if (4 < $1.digits)
-	      {
-		pc->dates_seen++;
-		pc->day = $1.value % 100;
-		pc->month = ($1.value / 100) % 100;
-		pc->year.value = $1.value / 10000;
-		pc->year.digits = $1.digits - 4;
-	      }
-	    else
-	      {
-		pc->times_seen++;
-		if ($1.digits <= 2)
-		  {
-		    pc->hour = $1.value;
-		    pc->minutes = 0;
-		  }
-		else
-		  {
-		    pc->hour = $1.value / 100;
-		    pc->minutes = $1.value % 100;
-		  }
-		pc->seconds.tv_sec = 0;
-		pc->seconds.tv_nsec = 0;
-		pc->meridian = MER24;
-	      }
-	  }
+	/* Hybrid all-digit and relative offset, so that we accept e.g.,
+	   "YYYYMMDD +N days" as well as "YYYYMMDD N days".  */
+	digits_to_date_time (pc, $1);
+	pc->rel.ns += $2.ns;
+	pc->rel.seconds += $2.seconds;
+	pc->rel.minutes += $2.minutes;
+	pc->rel.hour += $2.hour;
+	pc->rel.day += $2.day;
+	pc->rel.month += $2.month;
+	pc->rel.year += $2.year;
+	pc->rels_seen = true;
       }
   ;