summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2005-04-23 18:38:32 +0000
committerkientzle <kientzle@FreeBSD.org>2005-04-23 18:38:32 +0000
commit2fe0aef3f15e63074c9daa39a2e03a5d1b0db8a3 (patch)
treea4ecf7696b5177f9b10c0edb15fa808111253e20 /usr.bin
parent47cfd711c77f00faf0e75f838246f0ae88874eeb (diff)
downloadFreeBSD-src-2fe0aef3f15e63074c9daa39a2e03a5d1b0db8a3.zip
FreeBSD-src-2fe0aef3f15e63074c9daa39a2e03a5d1b0db8a3.tar.gz
Overhaul getdate.y. In particular, remove minutes-based logic
(combine with existing seconds-based), treat '-' as punctuation rather than a negative number indicator (eliminates several special cases), use a single list of special words instead of several separate lists, use table-driven abbreviation logic (eliminate duplicate word entries and special-case abbreviation and plural handling). The result is shorter, simpler (judging from comments, earlier maintainers didn't understand the special handling for "negative years"), handles more cases (e.g., "tu" is now a recognized abbreviation for "tuesday", "3rd" is now equivalent to "third") and it has 2 fewer shift/reduce conflicts.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/tar/getdate.y1260
1 files changed, 574 insertions, 686 deletions
diff --git a/usr.bin/tar/getdate.y b/usr.bin/tar/getdate.y
index 9f85c36..cc838c1 100644
--- a/usr.bin/tar/getdate.y
+++ b/usr.bin/tar/getdate.y
@@ -1,5 +1,16 @@
%{
/*
+ * March 2005: Further modified and simplified by Tim Kientzle:
+ * Eliminate minutes-based calculations (just do everything in
+ * seconds), have lexer only recognize unsigned integers (handle '+'
+ * and '-' characters in grammar), combine tables into one table with
+ * explicit abbreviation notes, do am/pm adjustments in the grammar
+ * (eliminate some state variables and post-processing). Among other
+ * things, these changes eliminated two shift/reduce conflicts. (Went
+ * from 10 to 8.)
+ */
+
+/*
** Originally written by Steven M. Bellovin <smb@research.att.com> while
** at the University of North Carolina at Chapel Hill. Later tweaked by
** a couple of people on Usenet. Completely overhauled by Rich $alz
@@ -36,16 +47,6 @@ time_t get_date(char *);
#define SECSPERDAY (24L * 60L * 60L)
/*
-** An entry in the lexical lookup table.
-*/
-typedef struct _TABLE {
- const char *name;
- int type;
- time_t value;
-} TABLE;
-
-
-/*
** Daylight-savings mode: on, off, or not yet known.
*/
typedef enum _DSTMODE {
@@ -53,11 +54,9 @@ typedef enum _DSTMODE {
} DSTMODE;
/*
-** Meridian: am, pm, or 24-hour style.
+** Meridian: am or pm.
*/
-typedef enum _MERIDIAN {
- MERam, MERpm, MER24
-} MERIDIAN;
+enum { tAM, tPM };
/*
** Global variables. We could get rid of most of these by using a good
@@ -66,6 +65,7 @@ typedef enum _MERIDIAN {
** the %union very rarely.
*/
static char *yyInput;
+
static DSTMODE yyDSTmode;
static time_t yyDayOrdinal;
static time_t yyDayNumber;
@@ -81,7 +81,6 @@ static time_t yyMinutes;
static time_t yyMonth;
static time_t yySeconds;
static time_t yyYear;
-static MERIDIAN yyMeridian;
static time_t yyRelMonth;
static time_t yyRelSeconds;
@@ -89,15 +88,13 @@ static time_t yyRelSeconds;
%union {
time_t Number;
- enum _MERIDIAN Meridian;
}
-%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
-%token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST
+%token tAGO tDAY tDAYZONE tAMPM tMONTH tMONTH_UNIT tSEC_UNIT tUNUMBER
+%token tZONE tDST
-%type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
-%type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE
-%type <Meridian> tMERIDIAN o_merid
+%type <Number> tDAY tDAYZONE tMONTH tMONTH_UNIT
+%type <Number> tSEC_UNIT tUNUMBER tZONE tAMPM
%%
@@ -105,388 +102,391 @@ spec : /* NULL */
| spec item
;
-item : time {
- yyHaveTime++;
- }
- | zone {
- yyHaveZone++;
- }
- | date {
- yyHaveDate++;
- }
- | day {
- yyHaveDay++;
- }
- | rel {
- yyHaveRel++;
- }
+item : time { yyHaveTime++; }
+ | zone { yyHaveZone++; }
+ | date { yyHaveDate++; }
+ | day { yyHaveDay++; }
+ | rel { yyHaveRel++; }
| number
;
-time : tUNUMBER tMERIDIAN {
- yyHour = $1;
- yyMinutes = 0;
- yySeconds = 0;
- yyMeridian = $2;
- }
- | tUNUMBER ':' tUNUMBER o_merid {
- yyHour = $1;
- yyMinutes = $3;
- yySeconds = 0;
- yyMeridian = $4;
- }
- | tUNUMBER ':' tUNUMBER tSNUMBER {
- yyHour = $1;
- yyMinutes = $3;
- yyMeridian = MER24;
- yyDSTmode = DSToff;
- yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
- }
- | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
- yyHour = $1;
- yyMinutes = $3;
- yySeconds = $5;
- yyMeridian = $6;
- }
- | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
- yyHour = $1;
- yyMinutes = $3;
- yySeconds = $5;
- yyMeridian = MER24;
- yyDSTmode = DSToff;
- yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
+time : tUNUMBER tAMPM {
+ /* "7am" */
+ yyHour = $1;
+ if (yyHour == 12)
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ if ($2 == tPM)
+ yyHour += 12;
+ }
+ | bare_time {
+ /* "7:12:18" "19:17" */
+ }
+ | bare_time tAMPM {
+ /* "7:12pm", "12:20:13am" */
+ if (yyHour == 12)
+ yyHour = 0;
+ if ($2 == tPM)
+ yyHour += 12;
+ }
+ | bare_time '+' tUNUMBER {
+ /* "7:14+0700" */
+ yyDSTmode = DSToff;
+ yyTimezone = - ($3 % 100 + ($3 / 100) * 60);
+ }
+ | bare_time '-' tUNUMBER {
+ /* "19:14:12-0530" */
+ yyDSTmode = DSToff;
+ yyTimezone = + ($3 % 100 + ($3 / 100) * 60);
+ }
+ ;
+
+bare_time : tUNUMBER ':' tUNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = 0;
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
}
;
zone : tZONE {
- yyTimezone = $1;
- yyDSTmode = DSToff;
+ yyTimezone = $1;
+ yyDSTmode = DSToff;
}
| tDAYZONE {
- yyTimezone = $1;
- yyDSTmode = DSTon;
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
}
- |
- tZONE tDST {
- yyTimezone = $1;
- yyDSTmode = DSTon;
+ | tZONE tDST {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
}
;
day : tDAY {
- yyDayOrdinal = 1;
- yyDayNumber = $1;
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
}
| tDAY ',' {
- yyDayOrdinal = 1;
- yyDayNumber = $1;
+ /* "tue," "wednesday," */
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
}
| tUNUMBER tDAY {
- yyDayOrdinal = $1;
- yyDayNumber = $2;
+ /* "second tues" "3 wed" */
+ yyDayOrdinal = $1;
+ yyDayNumber = $2;
}
;
date : tUNUMBER '/' tUNUMBER {
- yyMonth = $1;
- yyDay = $3;
+ /* "1/15" */
+ yyMonth = $1;
+ yyDay = $3;
}
| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
- if ($1 >= 13) {
- /* First number is big: 2004/01/29, 99/02/17 */
+ if ($1 >= 13) {
+ /* First number is big: 2004/01/29, 99/02/17 */
+ yyYear = $1;
+ yyMonth = $3;
+ yyDay = $5;
+ } else if (($5 >= 13) || ($3 >= 13)) {
+ /* Last number is big: 01/07/98 */
+ /* Middle number is big: 01/29/04 */
+ yyMonth = $1;
+ yyDay = $3;
+ yyYear = $5;
+ } else {
+ /* No significant clues: 02/03/04 */
+ yyMonth = $1;
+ yyDay = $3;
+ yyYear = $5;
+ }
+ }
+ | tUNUMBER '-' tUNUMBER '-' tUNUMBER {
+ /* ISO 8601 format. yyyy-mm-dd. */
yyYear = $1;
yyMonth = $3;
yyDay = $5;
- } else if (($5 >= 13) || ($3 >= 13)) {
- /* Last number is big: 01/07/98 */
- /* Middle number is big: 01/29/04 */
- yyMonth = $1;
- yyDay = $3;
- yyYear = $5;
- } else {
- /* No significant clues: 02/03/04 */
- yyMonth = $1;
- yyDay = $3;
- yyYear = $5;
- }
- }
- | tUNUMBER tSNUMBER tSNUMBER {
- /* ISO 8601 format. yyyy-mm-dd. */
- yyYear = $1;
- yyMonth = -$2;
- yyDay = -$3;
}
- | tUNUMBER tMONTH tSNUMBER {
- /* e.g. 17-JUN-1992. */
- yyDay = $1;
- yyMonth = $2;
- yyYear = -$3;
+ | tUNUMBER '-' tMONTH '-' tUNUMBER {
+ if ($1 > 31) {
+ /* e.g. 1992-Jun-17 */
+ yyYear = $1;
+ yyMonth = $3;
+ yyDay = $5;
+ } else {
+ /* e.g. 17-JUN-1992. */
+ yyDay = $1;
+ yyMonth = $3;
+ yyYear = $5;
+ }
}
| tMONTH tUNUMBER {
- yyMonth = $1;
- yyDay = $2;
+ /* "May 3" */
+ yyMonth = $1;
+ yyDay = $2;
}
| tMONTH tUNUMBER ',' tUNUMBER {
- yyMonth = $1;
- yyDay = $2;
- yyYear = $4;
+ /* "June 17, 2001" */
+ yyMonth = $1;
+ yyDay = $2;
+ yyYear = $4;
}
| tUNUMBER tMONTH {
- yyMonth = $2;
- yyDay = $1;
+ /* "12 Sept" */
+ yyDay = $1;
+ yyMonth = $2;
}
| tUNUMBER tMONTH tUNUMBER {
- yyMonth = $2;
- yyDay = $1;
- yyYear = $3;
+ /* "12 Sept 1997" */
+ yyDay = $1;
+ yyMonth = $2;
+ yyYear = $3;
}
;
rel : relunit tAGO {
- yyRelSeconds = -yyRelSeconds;
- yyRelMonth = -yyRelMonth;
+ yyRelSeconds = -yyRelSeconds;
+ yyRelMonth = -yyRelMonth;
}
| relunit
;
-relunit : tUNUMBER tMINUTE_UNIT {
- yyRelSeconds += $1 * $2 * 60L;
- }
- | tSNUMBER tMINUTE_UNIT {
- yyRelSeconds += $1 * $2 * 60L;
+relunit : '-' tUNUMBER tSEC_UNIT {
+ /* "-3 hours" */
+ yyRelSeconds -= $2 * $3;
}
- | tMINUTE_UNIT {
- yyRelSeconds += $1 * 60L;
- }
- | tSNUMBER tSEC_UNIT {
- yyRelSeconds += $1;
+ | '+' tUNUMBER tSEC_UNIT {
+ /* "+1 minute" */
+ yyRelSeconds += $2 * $3;
}
| tUNUMBER tSEC_UNIT {
- yyRelSeconds += $1;
+ /* "1 day" */
+ yyRelSeconds += $1;
}
| tSEC_UNIT {
- yyRelSeconds++;
+ /* "hour" */
+ yyRelSeconds++;
+ }
+ | '-' tUNUMBER tMONTH_UNIT {
+ /* "-3 months" */
+ yyRelMonth -= $2 * $3;
}
- | tSNUMBER tMONTH_UNIT {
- yyRelMonth += $1 * $2;
+ | '+' tUNUMBER tMONTH_UNIT {
+ /* "+5 years" */
+ yyRelMonth += $2 * $3;
}
| tUNUMBER tMONTH_UNIT {
- yyRelMonth += $1 * $2;
+ /* "2 years" */
+ yyRelMonth += $1 * $2;
}
| tMONTH_UNIT {
- yyRelMonth += $1;
+ /* "6 months" */
+ yyRelMonth += $1;
}
;
number : tUNUMBER {
- if (yyHaveTime && yyHaveDate && !yyHaveRel)
- yyYear = $1;
- else {
- if($1>10000) {
- yyHaveDate++;
- yyDay= ($1)%100;
- yyMonth= ($1/100)%100;
- yyYear = $1/10000;
- }
+ if (yyHaveTime && yyHaveDate && !yyHaveRel)
+ yyYear = $1;
else {
- yyHaveTime++;
- if ($1 < 100) {
- yyHour = $1;
- yyMinutes = 0;
- }
- else {
- yyHour = $1 / 100;
- yyMinutes = $1 % 100;
- }
- yySeconds = 0;
- yyMeridian = MER24;
- }
- }
+ if($1>10000) {
+ /* "20040301" */
+ yyHaveDate++;
+ yyDay= ($1)%100;
+ yyMonth= ($1/100)%100;
+ yyYear = $1/10000;
+ }
+ else {
+ /* "513" is same as "5:13" */
+ yyHaveTime++;
+ if ($1 < 100) {
+ yyHour = $1;
+ yyMinutes = 0;
+ }
+ else {
+ yyHour = $1 / 100;
+ yyMinutes = $1 % 100;
+ }
+ yySeconds = 0;
+ }
+ }
}
;
-o_merid : /* NULL */ {
- $$ = MER24;
- }
- | tMERIDIAN {
- $$ = $1;
- }
- ;
%%
-/* Month and day table. */
-static TABLE const MonthDayTable[] = {
- { "january", tMONTH, 1 },
- { "february", tMONTH, 2 },
- { "march", tMONTH, 3 },
- { "april", tMONTH, 4 },
- { "may", tMONTH, 5 },
- { "june", tMONTH, 6 },
- { "july", tMONTH, 7 },
- { "august", tMONTH, 8 },
- { "september", tMONTH, 9 },
- { "sept", tMONTH, 9 },
- { "october", tMONTH, 10 },
- { "november", tMONTH, 11 },
- { "december", tMONTH, 12 },
- { "sunday", tDAY, 0 },
- { "monday", tDAY, 1 },
- { "tuesday", tDAY, 2 },
- { "tues", tDAY, 2 },
- { "wednesday", tDAY, 3 },
- { "wednes", tDAY, 3 },
- { "thursday", tDAY, 4 },
- { "thur", tDAY, 4 },
- { "thurs", tDAY, 4 },
- { "friday", tDAY, 5 },
- { "saturday", tDAY, 6 },
- { NULL, 0, 0 }
-};
-
-/* Time units table. */
-static TABLE const UnitsTable[] = {
- { "year", tMONTH_UNIT, 12 },
- { "month", tMONTH_UNIT, 1 },
- { "fortnight", tMINUTE_UNIT, 14 * 24 * 60 },
- { "week", tMINUTE_UNIT, 7 * 24 * 60 },
- { "day", tMINUTE_UNIT, 1 * 24 * 60 },
- { "hour", tMINUTE_UNIT, 60 },
- { "minute", tMINUTE_UNIT, 1 },
- { "min", tMINUTE_UNIT, 1 },
- { "second", tSEC_UNIT, 1 },
- { "sec", tSEC_UNIT, 1 },
- { NULL, 0, 0 }
-};
-
-/* Assorted relative-time words. */
-static TABLE const OtherTable[] = {
- { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
- { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
- { "today", tMINUTE_UNIT, 0 },
- { "now", tMINUTE_UNIT, 0 },
- { "last", tUNUMBER, -1 },
- { "this", tMINUTE_UNIT, 0 },
- { "next", tUNUMBER, 2 },
- { "first", tUNUMBER, 1 },
-/* { "second", tUNUMBER, 2 }, */
- { "third", tUNUMBER, 3 },
- { "fourth", tUNUMBER, 4 },
- { "fifth", tUNUMBER, 5 },
- { "sixth", tUNUMBER, 6 },
- { "seventh", tUNUMBER, 7 },
- { "eighth", tUNUMBER, 8 },
- { "ninth", tUNUMBER, 9 },
- { "tenth", tUNUMBER, 10 },
- { "eleventh", tUNUMBER, 11 },
- { "twelfth", tUNUMBER, 12 },
- { "ago", tAGO, 1 },
- { NULL, 0, 0 }
-};
-
-/* The timezone table. */
-/* Some of these are commented out because a time_t can't store a float. */
-static TABLE const TimezoneTable[] = {
- { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
- { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
- { "utc", tZONE, HOUR( 0) },
- { "wet", tZONE, HOUR( 0) }, /* Western European */
- { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
- { "wat", tZONE, HOUR( 1) }, /* West Africa */
- { "at", tZONE, HOUR( 2) }, /* Azores */
-#if 0
- /* For completeness. BST is also British Summer, and GST is
- * also Guam Standard. */
- { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
- { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
-#endif
- { "nft", tZONE, HOUR(3)+30 }, /* Newfoundland */
- { "nst", tZONE, HOUR(3)+30 }, /* Newfoundland Standard */
- { "ndt", tDAYZONE, HOUR(3)+30 }, /* Newfoundland Daylight */
- { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
- { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
- { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
- { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
- { "cst", tZONE, HOUR( 6) }, /* Central Standard */
- { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
- { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
- { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
- { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
- { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
- { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
- { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
- { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
- { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
- { "cat", tZONE, HOUR(10) }, /* Central Alaska */
- { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
- { "nt", tZONE, HOUR(11) }, /* Nome */
- { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
- { "cet", tZONE, -HOUR(1) }, /* Central European */
- { "met", tZONE, -HOUR(1) }, /* Middle European */
- { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
- { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
- { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
- { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
- { "fwt", tZONE, -HOUR(1) }, /* French Winter */
- { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
- { "eet", tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */
- { "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
- { "it", tZONE, -HOUR(3)-30 },/* Iran */
- { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
- { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
- { "ist", tZONE, -HOUR(5)-30 },/* Indian Standard */
- { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
-#if 0
- /* For completeness. NST is also Newfoundland Stanard, and SST is
- * also Swedish Summer. */
- { "nst", tZONE, -HOUR(6.5) },/* North Sumatra */
- { "sst", tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */
-#endif /* 0 */
- { "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
- { "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
- { "jt", tZONE, -HOUR(7)-30 },/* Java (3pm in Cronusland!) */
- { "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
- { "jst", tZONE, -HOUR(9) }, /* Japan Standard, USSR Zone 8 */
- { "cast", tZONE, -HOUR(9)-30 },/* Central Australian Standard */
- { "cadt", tDAYZONE, -HOUR(9)-30 },/* Central Australian Daylight */
- { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
- { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
- { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
- { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
- { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
- { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
- { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
- { NULL, 0, 0 }
-};
-
-/* Military timezone table. */
-static TABLE const MilitaryTable[] = {
- { "a", tZONE, HOUR( 1) },
- { "b", tZONE, HOUR( 2) },
- { "c", tZONE, HOUR( 3) },
- { "d", tZONE, HOUR( 4) },
- { "e", tZONE, HOUR( 5) },
- { "f", tZONE, HOUR( 6) },
- { "g", tZONE, HOUR( 7) },
- { "h", tZONE, HOUR( 8) },
- { "i", tZONE, HOUR( 9) },
- { "k", tZONE, HOUR( 10) },
- { "l", tZONE, HOUR( 11) },
- { "m", tZONE, HOUR( 12) },
- { "n", tZONE, HOUR(- 1) },
- { "o", tZONE, HOUR(- 2) },
- { "p", tZONE, HOUR(- 3) },
- { "q", tZONE, HOUR(- 4) },
- { "r", tZONE, HOUR(- 5) },
- { "s", tZONE, HOUR(- 6) },
- { "t", tZONE, HOUR(- 7) },
- { "u", tZONE, HOUR(- 8) },
- { "v", tZONE, HOUR(- 9) },
- { "w", tZONE, HOUR(-10) },
- { "x", tZONE, HOUR(-11) },
- { "y", tZONE, HOUR(-12) },
- { "z", tZONE, HOUR( 0) },
- { NULL, 0, 0 }
+static struct TABLE {
+ size_t abbrev;
+ const char *name;
+ int type;
+ time_t value;
+} const TimeWords[] = {
+ /* am/pm */
+ { 0, "am", tAMPM, tAM },
+ { 0, "pm", tAMPM, tPM },
+
+ /* Month names. */
+ { 3, "january", tMONTH, 1 },
+ { 3, "february", tMONTH, 2 },
+ { 3, "march", tMONTH, 3 },
+ { 3, "april", tMONTH, 4 },
+ { 3, "may", tMONTH, 5 },
+ { 3, "june", tMONTH, 6 },
+ { 3, "july", tMONTH, 7 },
+ { 3, "august", tMONTH, 8 },
+ { 3, "september", tMONTH, 9 },
+ { 3, "october", tMONTH, 10 },
+ { 3, "november", tMONTH, 11 },
+ { 3, "december", tMONTH, 12 },
+
+ /* Days of the week. */
+ { 2, "sunday", tDAY, 0 },
+ { 3, "monday", tDAY, 1 },
+ { 2, "tuesday", tDAY, 2 },
+ { 3, "wednesday", tDAY, 3 },
+ { 2, "thursday", tDAY, 4 },
+ { 2, "friday", tDAY, 5 },
+ { 2, "saturday", tDAY, 6 },
+
+ /* Timezones: Offsets are in minutes. */
+ { 0, "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
+ { 0, "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
+ { 0, "utc", tZONE, HOUR( 0) },
+ { 0, "wet", tZONE, HOUR( 0) }, /* Western European */
+ { 0, "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
+ { 0, "wat", tZONE, HOUR( 1) }, /* West Africa */
+ { 0, "at", tZONE, HOUR( 2) }, /* Azores */
+ /* { 0, "bst", tZONE, HOUR( 3) }, */ /* Brazil Standard: Conflict */
+ /* { 0, "gst", tZONE, HOUR( 3) }, */ /* Greenland Standard: Conflict*/
+ { 0, "nft", tZONE, HOUR(3)+30 }, /* Newfoundland */
+ { 0, "nst", tZONE, HOUR(3)+30 }, /* Newfoundland Standard */
+ { 0, "ndt", tDAYZONE, HOUR(3)+30 }, /* Newfoundland Daylight */
+ { 0, "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
+ { 0, "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
+ { 0, "est", tZONE, HOUR( 5) }, /* Eastern Standard */
+ { 0, "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
+ { 0, "cst", tZONE, HOUR( 6) }, /* Central Standard */
+ { 0, "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
+ { 0, "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
+ { 0, "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
+ { 0, "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
+ { 0, "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
+ { 0, "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
+ { 0, "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
+ { 0, "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
+ { 0, "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
+ { 0, "cat", tZONE, HOUR(10) }, /* Central Alaska */
+ { 0, "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
+ { 0, "nt", tZONE, HOUR(11) }, /* Nome */
+ { 0, "idlw", tZONE, HOUR(12) }, /* Intl Date Line West */
+ { 0, "cet", tZONE, -HOUR(1) }, /* Central European */
+ { 0, "met", tZONE, -HOUR(1) }, /* Middle European */
+ { 0, "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
+ { 0, "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
+ { 0, "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
+ { 0, "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
+ { 0, "fwt", tZONE, -HOUR(1) }, /* French Winter */
+ { 0, "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
+ { 0, "eet", tZONE, -HOUR(2) }, /* Eastern Eur, USSR Zone 1 */
+ { 0, "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
+ { 0, "it", tZONE, -HOUR(3)-30 },/* Iran */
+ { 0, "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
+ { 0, "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
+ { 0, "ist", tZONE, -HOUR(5)-30 },/* Indian Standard */
+ { 0, "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
+ /* { 0, "nst", tZONE, -HOUR(6.5) }, */ /* North Sumatra: Conflict */
+ /* { 0, "sst", tZONE, -HOUR(7) }, */ /* So Sumatra, USSR 6: Conflict */
+ { 0, "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
+ { 0, "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
+ { 0, "jt", tZONE, -HOUR(7)-30 },/* Java (3pm in Cronusland!)*/
+ { 0, "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
+ { 0, "jst", tZONE, -HOUR(9) }, /* Japan Std, USSR Zone 8 */
+ { 0, "cast", tZONE, -HOUR(9)-30 },/* Central Australian Std */
+ { 0, "cadt", tDAYZONE, -HOUR(9)-30 },/* Central Australian Daylt */
+ { 0, "east", tZONE, -HOUR(10) }, /* Eastern Australian Std */
+ { 0, "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylt */
+ { 0, "gst", tZONE, -HOUR(10) }, /* Guam Std, USSR Zone 9 */
+ { 0, "nzt", tZONE, -HOUR(12) }, /* New Zealand */
+ { 0, "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
+ { 0, "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
+ { 0, "idle", tZONE, -HOUR(12) }, /* Intl Date Line East */
+
+ { 0, "dst", tDST, 0 },
+
+ /* Time units. */
+ { 4, "years", tMONTH_UNIT, 12 },
+ { 5, "months", tMONTH_UNIT, 1 },
+ { 9, "fortnights", tSEC_UNIT, 14 * 24 * 60 * 60 },
+ { 4, "weeks", tSEC_UNIT, 7 * 24 * 60 * 60 },
+ { 3, "days", tSEC_UNIT, 1 * 24 * 60 * 60 },
+ { 4, "hours", tSEC_UNIT, 60 * 60 },
+ { 3, "minutes", tSEC_UNIT, 60 },
+ { 3, "seconds", tSEC_UNIT, 1 },
+
+ /* Relative-time words. */
+ { 0, "tomorrow", tSEC_UNIT, 1 * 24 * 60 * 60 },
+ { 0, "yesterday", tSEC_UNIT, -1 * 24 * 60 * 60 },
+ { 0, "today", tSEC_UNIT, 0 },
+ { 0, "now", tSEC_UNIT, 0 },
+ { 0, "last", tUNUMBER, -1 },
+ { 0, "this", tSEC_UNIT, 0 },
+ { 0, "next", tUNUMBER, 2 },
+ { 0, "first", tUNUMBER, 1 },
+ { 0, "1st", tUNUMBER, 1 },
+/* { 0, "second", tUNUMBER, 2 }, */
+ { 0, "2nd", tUNUMBER, 2 },
+ { 0, "third", tUNUMBER, 3 },
+ { 0, "3rd", tUNUMBER, 3 },
+ { 0, "fourth", tUNUMBER, 4 },
+ { 0, "4th", tUNUMBER, 4 },
+ { 0, "fifth", tUNUMBER, 5 },
+ { 0, "5th", tUNUMBER, 5 },
+ { 0, "sixth", tUNUMBER, 6 },
+ { 0, "seventh", tUNUMBER, 7 },
+ { 0, "eighth", tUNUMBER, 8 },
+ { 0, "ninth", tUNUMBER, 9 },
+ { 0, "tenth", tUNUMBER, 10 },
+ { 0, "eleventh", tUNUMBER, 11 },
+ { 0, "twelfth", tUNUMBER, 12 },
+ { 0, "ago", tAGO, 1 },
+
+ /* Military timezones. */
+ { 0, "a", tZONE, HOUR( 1) },
+ { 0, "b", tZONE, HOUR( 2) },
+ { 0, "c", tZONE, HOUR( 3) },
+ { 0, "d", tZONE, HOUR( 4) },
+ { 0, "e", tZONE, HOUR( 5) },
+ { 0, "f", tZONE, HOUR( 6) },
+ { 0, "g", tZONE, HOUR( 7) },
+ { 0, "h", tZONE, HOUR( 8) },
+ { 0, "i", tZONE, HOUR( 9) },
+ { 0, "k", tZONE, HOUR( 10) },
+ { 0, "l", tZONE, HOUR( 11) },
+ { 0, "m", tZONE, HOUR( 12) },
+ { 0, "n", tZONE, HOUR(- 1) },
+ { 0, "o", tZONE, HOUR(- 2) },
+ { 0, "p", tZONE, HOUR(- 3) },
+ { 0, "q", tZONE, HOUR(- 4) },
+ { 0, "r", tZONE, HOUR(- 5) },
+ { 0, "s", tZONE, HOUR(- 6) },
+ { 0, "t", tZONE, HOUR(- 7) },
+ { 0, "u", tZONE, HOUR(- 8) },
+ { 0, "v", tZONE, HOUR(- 9) },
+ { 0, "w", tZONE, HOUR(-10) },
+ { 0, "x", tZONE, HOUR(-11) },
+ { 0, "y", tZONE, HOUR(-12) },
+ { 0, "z", tZONE, HOUR( 0) },
+
+ /* End of table. */
+ { 0, NULL, 0, 0 }
};
@@ -494,291 +494,194 @@ static TABLE const MilitaryTable[] = {
/* ARGSUSED */
static int
-yyerror(const char *s __unused)
+yyerror(const char *s)
{
- return 0;
+ (void)s;
+ return 0;
}
-
static time_t
-ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
+ToSeconds(time_t Hours, time_t Minutes, time_t Seconds)
{
- if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
- return -1;
- switch (Meridian) {
- case MER24:
+ if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+ return -1;
if (Hours < 0 || Hours > 23)
- return -1;
- return (Hours * 60L + Minutes) * 60L + Seconds;
- case MERam:
- if (Hours < 1 || Hours > 12)
- return -1;
- if (Hours == 12)
- Hours = 0;
+ return -1;
return (Hours * 60L + Minutes) * 60L + Seconds;
- case MERpm:
- if (Hours < 1 || Hours > 12)
- return -1;
- if (Hours == 12)
- Hours = 0;
- return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
- default:
- abort ();
- }
- /* NOTREACHED */
}
/* Year is either
- * A negative number, which means to use its absolute value (why?)
- * A number from 0 to 99, which means a year from 1970 to 2069, or
- * The actual year (>=100). */
+ * A number from 0 to 99, which means a year from 1970 to 2069, or
+ * The actual year (>=100). */
static time_t
Convert(time_t Month, time_t Day, time_t Year,
- time_t Hours, time_t Minutes, time_t Seconds,
- MERIDIAN Meridian, DSTMODE DSTmode)
+ time_t Hours, time_t Minutes, time_t Seconds, DSTMODE DSTmode)
{
- static int DaysInMonth[12] = {
- 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
- time_t tod;
- time_t Julian;
- int i;
-
- if (Year < 0)
- Year = -Year;
- if (Year < 69)
- Year += 2000;
- else if (Year < 100)
- Year += 1900;
- DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
- ? 29 : 28;
- /* Checking for 2038 bogusly assumes that time_t is 32 bits. But
- I'm too lazy to try to check for time_t overflow in another way. */
- if (Year < EPOCH || Year > 2038
- || Month < 1 || Month > 12
- /* Lint fluff: "conversion from long may lose accuracy" */
- || Day < 1 || Day > DaysInMonth[(int)--Month])
- return -1;
-
- for (Julian = Day - 1, i = 0; i < Month; i++)
- Julian += DaysInMonth[i];
- for (i = EPOCH; i < Year; i++)
- Julian += 365 + (i % 4 == 0);
- Julian *= SECSPERDAY;
- Julian += yyTimezone * 60L;
- if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
- return -1;
- Julian += tod;
- if (DSTmode == DSTon
- || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
- Julian -= 60 * 60;
- return Julian;
+ static int DaysInMonth[12] = {
+ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ time_t tod;
+ time_t Julian;
+ int i;
+
+ if (Year < 69)
+ Year += 2000;
+ else if (Year < 100)
+ Year += 1900;
+ DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+ ? 29 : 28;
+ /* Checking for 2038 bogusly assumes that time_t is 32 bits. But
+ I'm too lazy to try to check for time_t overflow in another way. */
+ if (Year < EPOCH || Year > 2038
+ || Month < 1 || Month > 12
+ /* Lint fluff: "conversion from long may lose accuracy" */
+ || Day < 1 || Day > DaysInMonth[(int)--Month])
+ return -1;
+
+ Julian = Day - 1;
+ for (i = 0; i < Month; i++)
+ Julian += DaysInMonth[i];
+ for (i = EPOCH; i < Year; i++)
+ Julian += 365 + (i % 4 == 0);
+ Julian *= SECSPERDAY;
+ Julian += yyTimezone * 60L;
+ if ((tod = ToSeconds(Hours, Minutes, Seconds)) < 0)
+ return -1;
+ Julian += tod;
+ if (DSTmode == DSTon
+ || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
+ Julian -= 60 * 60;
+ return Julian;
}
static time_t
DSTcorrect(time_t Start, time_t Future)
{
- time_t StartDay;
- time_t FutureDay;
+ time_t StartDay;
+ time_t FutureDay;
- StartDay = (localtime(&Start)->tm_hour + 1) % 24;
- FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
- return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+ StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+ FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+ return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
}
static time_t
RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
{
- struct tm *tm;
- time_t now;
-
- now = Start;
- tm = localtime(&now);
- now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
- now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
- return DSTcorrect(Start, now);
+ struct tm *tm;
+ time_t now;
+
+ now = Start;
+ tm = localtime(&now);
+ now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
+ now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+ return DSTcorrect(Start, now);
}
static time_t
RelativeMonth(time_t Start, time_t RelMonth)
{
- struct tm *tm;
- time_t Month;
- time_t Year;
-
- if (RelMonth == 0)
- return 0;
- tm = localtime(&Start);
- Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
- Year = Month / 12;
- Month = Month % 12 + 1;
- return DSTcorrect(Start,
+ struct tm *tm;
+ time_t Month;
+ time_t Year;
+
+ if (RelMonth == 0)
+ return 0;
+ tm = localtime(&Start);
+ Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
+ Year = Month / 12;
+ Month = Month % 12 + 1;
+ return DSTcorrect(Start,
Convert(Month, (time_t)tm->tm_mday, Year,
(time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
- MER24, DSTmaybe));
+ DSTmaybe));
}
-
static int
-LookupWord(char *buff)
+yylex(void)
{
- char *p;
- char *q;
- const TABLE *tp;
- int i;
- int abbrev;
-
- /* Make it lowercase. */
- for (p = buff; *p; p++)
- if (isupper(*p))
- *p = tolower(*p);
-
- if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
- yylval.Meridian = MERam;
- return tMERIDIAN;
- }
- if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
- yylval.Meridian = MERpm;
- return tMERIDIAN;
- }
-
- /* See if we have an abbreviation for a month. */
- if (strlen(buff) == 3)
- abbrev = 1;
- else if (strlen(buff) == 4 && buff[3] == '.') {
- abbrev = 1;
- buff[3] = '\0';
- }
- else
- abbrev = 0;
-
- for (tp = MonthDayTable; tp->name; tp++) {
- if (abbrev) {
- if (strncmp(buff, tp->name, 3) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
- }
- else if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
- }
-
- for (tp = TimezoneTable; tp->name; tp++)
- if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
-
- if (strcmp(buff, "dst") == 0)
- return tDST;
+ char c;
+ char buff[64];
+
+ for ( ; ; ) {
+ while (isspace(*yyInput))
+ yyInput++;
+
+ /* Skip parenthesized comments. */
+ if (*yyInput == '(') {
+ int Count = 0;
+ do {
+ c = *yyInput++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ Count++;
+ else if (c == ')')
+ Count--;
+ } while (Count > 0);
+ continue;
+ }
- for (tp = UnitsTable; tp->name; tp++)
- if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
+ /* Try the next token in the word table first. */
+ /* This allows us to match "2nd", for example. */
+ {
+ char *src = yyInput;
+ const struct TABLE *tp;
+ unsigned i = 0;
+
+ /* Force to lowercase and strip '.' characters. */
+ while (*src != '\0'
+ && (isalnum(*src) || *src == '.')
+ && i < sizeof(buff)-1) {
+ if (*src != '.') {
+ if (isupper(*src))
+ buff[i++] = tolower(*src);
+ else
+ buff[i++] = *src;
+ }
+ src++;
+ }
+ buff[i++] = '\0';
+
+ /*
+ * Find the first match. If the word can be
+ * abbreviated, make sure we match at least
+ * the minimum abbreviation.
+ */
+ for (tp = TimeWords; tp->name; tp++) {
+ size_t abbrev = tp->abbrev;
+ if (abbrev == 0)
+ abbrev = strlen(tp->name);
+ if (strlen(buff) >= abbrev
+ && strncmp(tp->name, buff, strlen(buff))
+ == 0) {
+ /* Skip over token. */
+ yyInput = src;
+ /* Return the match. */
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+ }
- /* Strip off any plural and try the units table again. */
- i = strlen(buff) - 1;
- if (buff[i] == 's') {
- buff[i] = '\0';
- for (tp = UnitsTable; tp->name; tp++)
- if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
- buff[i] = 's'; /* Put back for "this" in OtherTable. */
- }
+ /*
+ * Not in the word table, maybe it's a number. Note:
+ * Because '-' and '+' have other special meanings, I
+ * don't deal with signed numbers here.
+ */
+ if (isdigit(c = *yyInput)) {
+ for (yylval.Number = 0; isdigit(c = *yyInput++); )
+ yylval.Number = 10 * yylval.Number + c - '0';
+ yyInput--;
+ return (tUNUMBER);
+ }
- for (tp = OtherTable; tp->name; tp++)
- if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
+ return (*yyInput++);
}
-
- /* Military timezones. */
- if (buff[1] == '\0' && isalpha(*buff)) {
- for (tp = MilitaryTable; tp->name; tp++)
- if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
- }
-
- /* Drop out any periods and try the timezone table again. */
- for (i = 0, p = q = buff; *q; q++)
- if (*q != '.')
- *p++ = *q;
- else
- i++;
- *p = '\0';
- if (i)
- for (tp = TimezoneTable; tp->name; tp++)
- if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
-
- return tID;
-}
-
-
-static int
-yylex(void)
-{
- char c;
- char *p;
- char buff[20];
- int Count;
- int sign;
-
- for ( ; ; ) {
- while (isspace(*yyInput))
- yyInput++;
-
- if (isdigit(c = *yyInput) || c == '-' || c == '+') {
- if (c == '-' || c == '+') {
- sign = c == '-' ? -1 : 1;
- if (!isdigit(*++yyInput))
- /* skip the '-' sign */
- continue;
- }
- else
- sign = 0;
- for (yylval.Number = 0; isdigit(c = *yyInput++); )
- yylval.Number = 10 * yylval.Number + c - '0';
- yyInput--;
- if (sign < 0)
- yylval.Number = -yylval.Number;
- return sign ? tSNUMBER : tUNUMBER;
- }
- if (isalpha(c)) {
- for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
- if (p < &buff[sizeof buff - 1])
- *p++ = c;
- *p = '\0';
- yyInput--;
- return LookupWord(buff);
- }
- if (c != '(')
- return *yyInput++;
- Count = 0;
- do {
- c = *yyInput++;
- if (c == '\0')
- return c;
- if (c == '(')
- Count++;
- else if (c == ')')
- Count--;
- } while (Count > 0);
- }
}
#define TM_YEAR_ORIGIN 1900
@@ -787,109 +690,98 @@ yylex(void)
static long
difftm (struct tm *a, struct tm *b)
{
- int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
- int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
- int days = (
- /* difference in day of year */
- a->tm_yday - b->tm_yday
- /* + intervening leap days */
- + ((ay >> 2) - (by >> 2))
- - (ay/100 - by/100)
- + ((ay/100 >> 2) - (by/100 >> 2))
- /* + difference in years * 365 */
- + (long)(ay-by) * 365
- );
- return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
- + (a->tm_min - b->tm_min))
- + (a->tm_sec - b->tm_sec));
+ int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+ int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+ int days = (
+ /* difference in day of year */
+ a->tm_yday - b->tm_yday
+ /* + intervening leap days */
+ + ((ay >> 2) - (by >> 2))
+ - (ay/100 - by/100)
+ + ((ay/100 >> 2) - (by/100 >> 2))
+ /* + difference in years * 365 */
+ + (long)(ay-by) * 365
+ );
+ return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
}
time_t
get_date(char *p)
{
- struct tm *tm, gmt;
- time_t Start;
- time_t tod;
- time_t nowtime;
- long tzone;
-
- yyInput = p;
-
- struct tm *gmt_ptr;
-
- (void)time (&nowtime);
-
- gmt_ptr = gmtime (&nowtime);
- if (gmt_ptr != NULL)
- {
- /* Make a copy, in case localtime modifies *tm (I think
- that comment now applies to *gmt_ptr, but I am too
- lazy to dig into how gmtime and locatime allocate the
- structures they return pointers to). */
- gmt = *gmt_ptr;
- }
+ struct tm *tm;
+ struct tm gmt, *gmt_ptr;
+ time_t Start;
+ time_t tod;
+ time_t nowtime;
+ long tzone;
- if (! (tm = localtime (&nowtime)))
- return -1;
-
- if (gmt_ptr != NULL)
- tzone = difftm (&gmt, tm) / 60;
- else
- /* We are on a system like VMS, where the system clock is
- in local time and the system has no concept of timezones.
- Hopefully we can fake this out (for the case in which the
- user specifies no timezone) by just saying the timezone
- is zero. */
- tzone = 0;
-
- if(tm->tm_isdst)
- tzone += 60;
-
- tm = localtime(&nowtime);
- yyYear = tm->tm_year + 1900;
- yyMonth = tm->tm_mon + 1;
- yyDay = tm->tm_mday;
- yyTimezone = tzone;
- yyDSTmode = DSTmaybe;
- yyHour = 0;
- yyMinutes = 0;
- yySeconds = 0;
- yyMeridian = MER24;
- yyRelSeconds = 0;
- yyRelMonth = 0;
- yyHaveDate = 0;
- yyHaveDay = 0;
- yyHaveRel = 0;
- yyHaveTime = 0;
- yyHaveZone = 0;
-
- if (yyparse()
- || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
- return -1;
-
- if (yyHaveDate || yyHaveTime || yyHaveDay) {
- Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
- yyMeridian, yyDSTmode);
- if (Start < 0)
- return -1;
- }
- else {
- Start = nowtime;
- if (!yyHaveRel)
- Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
- }
+ yyInput = p;
- Start += yyRelSeconds;
- Start += RelativeMonth(Start, yyRelMonth);
+ (void)time (&nowtime);
- if (yyHaveDay && !yyHaveDate) {
- tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
- Start += tod;
- }
+ gmt_ptr = gmtime (&nowtime);
+ if (gmt_ptr != NULL) {
+ /* Copy, in case localtime and gmtime use the same buffer. */
+ gmt = *gmt_ptr;
+ }
+
+ if (! (tm = localtime (&nowtime)))
+ return -1;
- /* Have to do *something* with a legitimate -1 so it's distinguishable
- * from the error return value. (Alternately could set errno on error.) */
- return Start == -1 ? 0 : Start;
+ if (gmt_ptr != NULL)
+ tzone = difftm (&gmt, tm) / 60;
+ else
+ /* This system doesn't understand timezones; fake it. */
+ tzone = 0;
+ if(tm->tm_isdst)
+ tzone += 60;
+
+ yyYear = tm->tm_year + 1900;
+ yyMonth = tm->tm_mon + 1;
+ yyDay = tm->tm_mday;
+ yyTimezone = tzone;
+ yyDSTmode = DSTmaybe;
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyRelSeconds = 0;
+ yyRelMonth = 0;
+ yyHaveDate = 0;
+ yyHaveDay = 0;
+ yyHaveRel = 0;
+ yyHaveTime = 0;
+ yyHaveZone = 0;
+
+ if (yyparse()
+ || yyHaveTime > 1 || yyHaveZone > 1
+ || yyHaveDate > 1 || yyHaveDay > 1)
+ return -1;
+
+ if (yyHaveDate || yyHaveTime || yyHaveDay) {
+ Start = Convert(yyMonth, yyDay, yyYear,
+ yyHour, yyMinutes, yySeconds, yyDSTmode);
+ if (Start < 0)
+ return -1;
+ } else {
+ Start = nowtime;
+ if (!yyHaveRel)
+ Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
+ }
+
+ Start += yyRelSeconds;
+ Start += RelativeMonth(Start, yyRelMonth);
+
+ if (yyHaveDay && !yyHaveDate) {
+ tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+ Start += tod;
+ }
+
+ /* Have to do *something* with a legitimate -1 so it's
+ * distinguishable from the error return value. (Alternately
+ * could set errno on error.) */
+ return Start == -1 ? 0 : Start;
}
@@ -897,21 +789,17 @@ get_date(char *p)
/* ARGSUSED */
int
-main(int ac, char *av[])
+main(int argc, char **argv)
{
- char buff[128];
time_t d;
- (void)printf("Enter date, or blank line to exit.\n\t> ");
- (void)fflush(stdout);
- while (gets(buff) && buff[0]) {
- d = get_date(buff, (struct timeb *)NULL);
- if (d == -1)
- (void)printf("Bad format - couldn't convert.\n");
- else
- (void)printf("%s", ctime(&d));
- (void)printf("\t> ");
- (void)fflush(stdout);
+ while (*++argv != NULL) {
+ (void)printf("Input: %s\n", *argv);
+ d = get_date(*argv);
+ if (d == -1)
+ (void)printf("Bad format - couldn't convert.\n");
+ else
+ (void)printf("Output: %s\n", ctime(&d));
}
exit(0);
/* NOTREACHED */
OpenPOWER on IntegriCloud