Module Name:    src
Committed By:   christos
Date:           Fri Dec 24 03:37:37 UTC 2010

Modified Files:
        src/lib/libutil: parsedate.y

Log Message:
make this thread-safe. We could use localtime_tz and make it even better,
but not now.


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/lib/libutil/parsedate.y

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libutil/parsedate.y
diff -u src/lib/libutil/parsedate.y:1.8 src/lib/libutil/parsedate.y:1.9
--- src/lib/libutil/parsedate.y:1.8	Tue Dec 21 13:13:02 2010
+++ src/lib/libutil/parsedate.y	Thu Dec 23 22:37:37 2010
@@ -62,32 +62,26 @@
 } MERIDIAN;
 
 
-/*
-**  Global variables.  We could get rid of most of these by using a good
-**  union as the yacc stack.  (This routine was originally written before
-**  yacc had the %union construct.)  Maybe someday; right now we only use
-**  the %union very rarely.
-*/
-static const char *yyInput;
-static DSTMODE	yyDSTmode;
-static time_t	yyDayOrdinal;
-static time_t	yyDayNumber;
-static int	yyHaveDate;
-static int	yyHaveDay;
-static int	yyHaveRel;
-static int	yyHaveTime;
-static int	yyHaveZone;
-static time_t	yyTimezone;
-static time_t	yyDay;
-static time_t	yyHour;
-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;
-
+struct dateinfo {
+	DSTMODE	yyDSTmode;
+	time_t	yyDayOrdinal;
+	time_t	yyDayNumber;
+	int	yyHaveDate;
+	int	yyHaveDay;
+	int	yyHaveRel;
+	int	yyHaveTime;
+	int	yyHaveZone;
+	time_t	yyTimezone;
+	time_t	yyDay;
+	time_t	yyHour;
+	time_t	yyMinutes;
+	time_t	yyMonth;
+	time_t	yySeconds;
+	time_t	yyYear;
+	MERIDIAN	yyMeridian;
+	time_t	yyRelMonth;
+	time_t	yyRelSeconds;
+};
 %}
 
 %union {
@@ -102,6 +96,11 @@
 %type	<Number>	tSEC_UNIT tSNUMBER tUNUMBER tZONE
 %type	<Meridian>	tMERIDIAN o_merid
 
+%parse-param	{ struct dateinfo *param }
+%parse-param 	{ const char **yyInput }
+%lex-param	{ const char **yyInput }
+%pure-parser
+
 %%
 
 spec	: /* NULL */
@@ -109,43 +108,43 @@
 	;
 
 item	: time {
-	    yyHaveTime++;
+	    param->yyHaveTime++;
 	}
 	| zone {
-	    yyHaveZone++;
+	    param->yyHaveZone++;
 	}
 	| date {
-	    yyHaveDate++;
+	    param->yyHaveDate++;
 	}
 	| day {
-	    yyHaveDay++;
+	    param->yyHaveDay++;
 	}
 	| rel {
-	    yyHaveRel++;
+	    param->yyHaveRel++;
 	}
 	| cvsstamp {
-	    yyHaveTime++;
-	    yyHaveDate++;
-	    yyHaveZone++;
+	    param->yyHaveTime++;
+	    param->yyHaveDate++;
+	    param->yyHaveZone++;
 	}
 	| epochdate {
-	    yyHaveTime++;
-	    yyHaveDate++;
-	    yyHaveZone++;
+	    param->yyHaveTime++;
+	    param->yyHaveDate++;
+	    param->yyHaveZone++;
 	}
 	| number
 	;
 
 cvsstamp: tUNUMBER '.' tUNUMBER '.' tUNUMBER '.' tUNUMBER '.' tUNUMBER '.' tUNUMBER {
-	    yyYear = $1;
-	    if (yyYear < 100) yyYear += 1900;
-	    yyMonth = $3;
-	    yyDay = $5;
-	    yyHour = $7;
-	    yyMinutes = $9;
-	    yySeconds = $11;
-	    yyDSTmode = DSToff;
-	    yyTimezone = 0;
+	    param->yyYear = $1;
+	    if (param->yyYear < 100) param->yyYear += 1900;
+	    param->yyMonth = $3;
+	    param->yyDay = $5;
+	    param->yyHour = $7;
+	    param->yyMinutes = $9;
+	    param->yySeconds = $11;
+	    param->yyDSTmode = DSToff;
+	    param->yyTimezone = 0;
 	}
 	;
 
@@ -153,205 +152,205 @@
             time_t    when = $2;
             struct tm tmbuf;
             if (gmtime_r(&when, &tmbuf) != NULL) {
-		yyYear = tmbuf.tm_year + 1900;
-		yyMonth = tmbuf.tm_mon + 1;
-		yyDay = tmbuf.tm_mday;
-
-		yyHour = tmbuf.tm_hour;
-		yyMinutes = tmbuf.tm_min;
-		yySeconds = tmbuf.tm_sec;
+		param->yyYear = tmbuf.tm_year + 1900;
+		param->yyMonth = tmbuf.tm_mon + 1;
+		param->yyDay = tmbuf.tm_mday;
+
+		param->yyHour = tmbuf.tm_hour;
+		param->yyMinutes = tmbuf.tm_min;
+		param->yySeconds = tmbuf.tm_sec;
 	    } else {
-		yyYear = EPOCH;
-		yyMonth = 1;
-		yyDay = 1;
-
-		yyHour = 0;
-		yyMinutes = 0;
-		yySeconds = 0;
+		param->yyYear = EPOCH;
+		param->yyMonth = 1;
+		param->yyDay = 1;
+
+		param->yyHour = 0;
+		param->yyMinutes = 0;
+		param->yySeconds = 0;
 	    }
-	    yyDSTmode = DSToff;
-	    yyTimezone = 0;
+	    param->yyDSTmode = DSToff;
+	    param->yyTimezone = 0;
 	}
 	;
 
 time	: tUNUMBER tMERIDIAN {
-	    yyHour = $1;
-	    yyMinutes = 0;
-	    yySeconds = 0;
-	    yyMeridian = $2;
+	    param->yyHour = $1;
+	    param->yyMinutes = 0;
+	    param->yySeconds = 0;
+	    param->yyMeridian = $2;
 	}
 	| tUNUMBER ':' tUNUMBER o_merid {
-	    yyHour = $1;
-	    yyMinutes = $3;
-	    yySeconds = 0;
-	    yyMeridian = $4;
+	    param->yyHour = $1;
+	    param->yyMinutes = $3;
+	    param->yySeconds = 0;
+	    param->yyMeridian = $4;
 	}
 	| tUNUMBER ':' tUNUMBER tSNUMBER {
-	    yyHour = $1;
-	    yyMinutes = $3;
-	    yyMeridian = MER24;
-	    yyDSTmode = DSToff;
-	    yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
+	    param->yyHour = $1;
+	    param->yyMinutes = $3;
+	    param->yyMeridian = MER24;
+	    param->yyDSTmode = DSToff;
+	    param->yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
 	}
 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
-	    yyHour = $1;
-	    yyMinutes = $3;
-	    yySeconds = $5;
-	    yyMeridian = $6;
+	    param->yyHour = $1;
+	    param->yyMinutes = $3;
+	    param->yySeconds = $5;
+	    param->yyMeridian = $6;
 	}
 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
-	    yyHour = $1;
-	    yyMinutes = $3;
-	    yySeconds = $5;
-	    yyMeridian = MER24;
-	    yyDSTmode = DSToff;
-	    yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
+	    param->yyHour = $1;
+	    param->yyMinutes = $3;
+	    param->yySeconds = $5;
+	    param->yyMeridian = MER24;
+	    param->yyDSTmode = DSToff;
+	    param->yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
 	}
 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER '.' tUNUMBER {
-	    yyHour = $1;
-	    yyMinutes = $3;
-	    yySeconds = $5;
-	    yyMeridian = MER24;
-	    yyDSTmode = DSToff;
+	    param->yyHour = $1;
+	    param->yyMinutes = $3;
+	    param->yySeconds = $5;
+	    param->yyMeridian = MER24;
+	    param->yyDSTmode = DSToff;
 /* XXX: Do nothing with millis */
-/*	    yyTimezone = ($7 % 100 + ($7 / 100) * 60); */
+/*	    param->yyTimezone = ($7 % 100 + ($7 / 100) * 60); */
 	}
 	;
 
 zone	: tZONE {
-	    yyTimezone = $1;
-	    yyDSTmode = DSToff;
+	    param->yyTimezone = $1;
+	    param->yyDSTmode = DSToff;
 	}
 	| tDAYZONE {
-	    yyTimezone = $1;
-	    yyDSTmode = DSTon;
+	    param->yyTimezone = $1;
+	    param->yyDSTmode = DSTon;
 	}
 	|
 	  tZONE tDST {
-	    yyTimezone = $1;
-	    yyDSTmode = DSTon;
+	    param->yyTimezone = $1;
+	    param->yyDSTmode = DSTon;
 	}
 	;
 
 day	: tDAY {
-	    yyDayOrdinal = 1;
-	    yyDayNumber = $1;
+	    param->yyDayOrdinal = 1;
+	    param->yyDayNumber = $1;
 	}
 	| tDAY ',' {
-	    yyDayOrdinal = 1;
-	    yyDayNumber = $1;
+	    param->yyDayOrdinal = 1;
+	    param->yyDayNumber = $1;
 	}
 	| tUNUMBER tDAY {
-	    yyDayOrdinal = $1;
-	    yyDayNumber = $2;
+	    param->yyDayOrdinal = $1;
+	    param->yyDayNumber = $2;
 	}
 	;
 
 date	: tUNUMBER '/' tUNUMBER {
-	    yyMonth = $1;
-	    yyDay = $3;
+	    param->yyMonth = $1;
+	    param->yyDay = $3;
 	}
 	| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
 	    if ($1 >= 100) {
-		yyYear = $1;
-		yyMonth = $3;
-		yyDay = $5;
+		param->yyYear = $1;
+		param->yyMonth = $3;
+		param->yyDay = $5;
 	    } else {
-		yyMonth = $1;
-		yyDay = $3;
-		yyYear = $5;
+		param->yyMonth = $1;
+		param->yyDay = $3;
+		param->yyYear = $5;
 	    }
 	}
 	| tUNUMBER tSNUMBER tSNUMBER {
 	    /* ISO 8601 format.  yyyy-mm-dd.  */
-	    yyYear = $1;
-	    yyMonth = -$2;
-	    yyDay = -$3;
+	    param->yyYear = $1;
+	    param->yyMonth = -$2;
+	    param->yyDay = -$3;
 	}
 	| tUNUMBER tMONTH tSNUMBER {
 	    /* e.g. 17-JUN-1992.  */
-	    yyDay = $1;
-	    yyMonth = $2;
-	    yyYear = -$3;
+	    param->yyDay = $1;
+	    param->yyMonth = $2;
+	    param->yyYear = -$3;
 	}
 	| tMONTH tUNUMBER {
-	    yyMonth = $1;
-	    yyDay = $2;
+	    param->yyMonth = $1;
+	    param->yyDay = $2;
 	}
 	| tMONTH tUNUMBER ',' tUNUMBER {
-	    yyMonth = $1;
-	    yyDay = $2;
-	    yyYear = $4;
+	    param->yyMonth = $1;
+	    param->yyDay = $2;
+	    param->yyYear = $4;
 	}
 	| tUNUMBER tMONTH {
-	    yyMonth = $2;
-	    yyDay = $1;
+	    param->yyMonth = $2;
+	    param->yyDay = $1;
 	}
 	| tUNUMBER tMONTH tUNUMBER {
-	    yyMonth = $2;
-	    yyDay = $1;
-	    yyYear = $3;
+	    param->yyMonth = $2;
+	    param->yyDay = $1;
+	    param->yyYear = $3;
 	}
 	;
 
 rel	: relunit tAGO {
-	    yyRelSeconds = -yyRelSeconds;
-	    yyRelMonth = -yyRelMonth;
+	    param->yyRelSeconds = -param->yyRelSeconds;
+	    param->yyRelMonth = -param->yyRelMonth;
 	}
 	| relunit
 	;
 
 relunit	: tUNUMBER tMINUTE_UNIT {
-	    yyRelSeconds += $1 * $2 * 60L;
+	    param->yyRelSeconds += $1 * $2 * 60L;
 	}
 	| tSNUMBER tMINUTE_UNIT {
-	    yyRelSeconds += $1 * $2 * 60L;
+	    param->yyRelSeconds += $1 * $2 * 60L;
 	}
 	| tMINUTE_UNIT {
-	    yyRelSeconds += $1 * 60L;
+	    param->yyRelSeconds += $1 * 60L;
 	}
 	| tSNUMBER tSEC_UNIT {
-	    yyRelSeconds += $1;
+	    param->yyRelSeconds += $1;
 	}
 	| tUNUMBER tSEC_UNIT {
-	    yyRelSeconds += $1;
+	    param->yyRelSeconds += $1;
 	}
 	| tSEC_UNIT {
-	    yyRelSeconds++;
+	    param->yyRelSeconds++;
 	}
 	| tSNUMBER tMONTH_UNIT {
-	    yyRelMonth += $1 * $2;
+	    param->yyRelMonth += $1 * $2;
 	}
 	| tUNUMBER tMONTH_UNIT {
-	    yyRelMonth += $1 * $2;
+	    param->yyRelMonth += $1 * $2;
 	}
 	| tMONTH_UNIT {
-	    yyRelMonth += $1;
+	    param->yyRelMonth += $1;
 	}
 	;
 
 number	: tUNUMBER {
-	    if (yyHaveTime && yyHaveDate && !yyHaveRel)
-		yyYear = $1;
+	    if (param->yyHaveTime && param->yyHaveDate && !param->yyHaveRel)
+		param->yyYear = $1;
 	    else {
 		if($1>10000) {
-		    yyHaveDate++;
-		    yyDay= ($1)%100;
-		    yyMonth= ($1/100)%100;
-		    yyYear = $1/10000;
+		    param->yyHaveDate++;
+		    param->yyDay= ($1)%100;
+		    param->yyMonth= ($1/100)%100;
+		    param->yyYear = $1/10000;
 		}
 		else {
-		    yyHaveTime++;
+		    param->yyHaveTime++;
 		    if ($1 < 100) {
-			yyHour = $1;
-			yyMinutes = 0;
+			param->yyHour = $1;
+			param->yyMinutes = 0;
 		    }
 		    else {
-		    	yyHour = $1 / 100;
-		    	yyMinutes = $1 % 100;
+		    	param->yyHour = $1 / 100;
+		    	param->yyMinutes = $1 % 100;
 		    }
-		    yySeconds = 0;
-		    yyMeridian = MER24;
+		    param->yySeconds = 0;
+		    param->yyMeridian = MER24;
 	        }
 	    }
 	}
@@ -368,7 +367,7 @@
 %%
 
 /* Month and day table. */
-static TABLE const MonthDayTable[] = {
+static const TABLE const MonthDayTable[] = {
     { "january",	tMONTH,  1 },
     { "february",	tMONTH,  2 },
     { "march",		tMONTH,  3 },
@@ -397,7 +396,7 @@
 };
 
 /* Time units table. */
-static TABLE const UnitsTable[] = {
+static const TABLE const UnitsTable[] = {
     { "year",		tMONTH_UNIT,	12 },
     { "month",		tMONTH_UNIT,	1 },
     { "fortnight",	tMINUTE_UNIT,	14 * 24 * 60 },
@@ -412,7 +411,7 @@
 };
 
 /* Assorted relative-time words. */
-static TABLE const OtherTable[] = {
+static const TABLE const OtherTable[] = {
     { "tomorrow",	tMINUTE_UNIT,	1 * 24 * 60 },
     { "yesterday",	tMINUTE_UNIT,	-1 * 24 * 60 },
     { "today",		tMINUTE_UNIT,	0 },
@@ -450,7 +449,7 @@
 
 /* The timezone table. */
 /* Some of these are commented out because a time_t can't store a float. */
-static TABLE const TimezoneTable[] = {
+static const TABLE const TimezoneTable[] = {
     { "gmt",	tZONE,     HOUR( 0) },	/* Greenwich Mean */
     { "ut",	tZONE,     HOUR( 0) },	/* Universal (Coordinated) */
     { "utc",	tZONE,     HOUR( 0) },
@@ -534,7 +533,7 @@
 };
 
 /* Military timezone table. */
-static TABLE const MilitaryTable[] = {
+static const TABLE const MilitaryTable[] = {
     { "a",	tZONE,	HOUR(  1) },
     { "b",	tZONE,	HOUR(  2) },
     { "c",	tZONE,	HOUR(  3) },
@@ -568,7 +567,7 @@
 
 /* ARGSUSED */
 static int
-yyerror(const char *s __unused)
+yyerror(struct dateinfo *param, const char **inp, const char *s __unused)
 {
   return 0;
 }
@@ -626,6 +625,7 @@
     time_t	Hours,
     time_t	Minutes,
     time_t	Seconds,
+    time_t	Timezone,
     MERIDIAN	Meridian,
     DSTMODE	DSTmode
 )
@@ -671,9 +671,8 @@
     if (oJulian > Julian)
 	return -1;
     oJulian = Julian;
-
-    Julian += yyTimezone * 60L;
-    if (oJulian > Julian && yyTimezone > 0)
+    Julian += Timezone * 60L;
+    if (oJulian > Julian)
 	return -1;
     oJulian = Julian;
 
@@ -738,7 +737,8 @@
 static time_t
 RelativeMonth(
     time_t	Start,
-    time_t	RelMonth
+    time_t	RelMonth,
+    time_t	Timezone
 )
 {
     struct tm	*tm;
@@ -756,12 +756,12 @@
     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));
+		Timezone, MER24, DSTmaybe));
 }
 
 
 static int
-LookupWord(char *buff)
+LookupWord(YYSTYPE *yylval, char *buff)
 {
     register char	*p;
     register char	*q;
@@ -775,11 +775,11 @@
 	    *p = tolower((unsigned char)*p);
 
     if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
-	yylval.Meridian = MERam;
+	yylval->Meridian = MERam;
 	return tMERIDIAN;
     }
     if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
-	yylval.Meridian = MERpm;
+	yylval->Meridian = MERpm;
 	return tMERIDIAN;
     }
 
@@ -796,19 +796,19 @@
     for (tp = MonthDayTable; tp->name; tp++) {
 	if (abbrev) {
 	    if (strncmp(buff, tp->name, 3) == 0) {
-		yylval.Number = tp->value;
+		yylval->Number = tp->value;
 		return tp->type;
 	    }
 	}
 	else if (strcmp(buff, tp->name) == 0) {
-	    yylval.Number = tp->value;
+	    yylval->Number = tp->value;
 	    return tp->type;
 	}
     }
 
     for (tp = TimezoneTable; tp->name; tp++)
 	if (strcmp(buff, tp->name) == 0) {
-	    yylval.Number = tp->value;
+	    yylval->Number = tp->value;
 	    return tp->type;
 	}
 
@@ -817,7 +817,7 @@
 
     for (tp = UnitsTable; tp->name; tp++)
 	if (strcmp(buff, tp->name) == 0) {
-	    yylval.Number = tp->value;
+	    yylval->Number = tp->value;
 	    return tp->type;
 	}
 
@@ -827,7 +827,7 @@
 	buff[i] = '\0';
 	for (tp = UnitsTable; tp->name; tp++)
 	    if (strcmp(buff, tp->name) == 0) {
-		yylval.Number = tp->value;
+		yylval->Number = tp->value;
 		return tp->type;
 	    }
 	buff[i] = 's';		/* Put back for "this" in OtherTable. */
@@ -835,7 +835,7 @@
 
     for (tp = OtherTable; tp->name; tp++)
 	if (strcmp(buff, tp->name) == 0) {
-	    yylval.Number = tp->value;
+	    yylval->Number = tp->value;
 	    return tp->type;
 	}
 
@@ -843,7 +843,7 @@
     if (buff[1] == '\0' && isalpha((unsigned char)*buff)) {
 	for (tp = MilitaryTable; tp->name; tp++)
 	    if (strcmp(buff, tp->name) == 0) {
-		yylval.Number = tp->value;
+		yylval->Number = tp->value;
 		return tp->type;
 	    }
     }
@@ -858,7 +858,7 @@
     if (i)
 	for (tp = TimezoneTable; tp->name; tp++)
 	    if (strcmp(buff, tp->name) == 0) {
-		yylval.Number = tp->value;
+		yylval->Number = tp->value;
 		return tp->type;
 	    }
 
@@ -867,51 +867,54 @@
 
 
 static int
-yylex(void)
+yylex(YYSTYPE *yylval, const char **yyInput)
 {
     register char	c;
     register char	*p;
     char		buff[20];
     int			Count;
     int			sign;
+    const char		*inp = *yyInput;
 
     for ( ; ; ) {
-	while (isspace((unsigned char)*yyInput))
-	    yyInput++;
+	while (isspace((unsigned char)*inp))
+	    inp++;
 
-	if (isdigit((unsigned char)(c = *yyInput)) || c == '-' || c == '+') {
+	if (isdigit((unsigned char)(c = *inp)) || c == '-' || c == '+') {
 	    if (c == '-' || c == '+') {
 		sign = c == '-' ? -1 : 1;
-		if (!isdigit((unsigned char)*++yyInput))
+		if (!isdigit((unsigned char)*++inp))
 		    /* skip the '-' sign */
 		    continue;
 	    }
 	    else
 		sign = 0;
-	    for (yylval.Number = 0; isdigit((unsigned char)(c = *yyInput++)); )
-		yylval.Number = 10 * yylval.Number + c - '0';
-	    yyInput--;
+	    for (yylval->Number = 0; isdigit((unsigned char)(c = *inp++)); )
+		yylval->Number = 10 * yylval->Number + c - '0';
 	    if (sign < 0)
-		yylval.Number = -yylval.Number;
+		yylval->Number = -yylval->Number;
+	    *yyInput = --inp;
 	    return sign ? tSNUMBER : tUNUMBER;
 	}
 	if (isalpha((unsigned char)c)) {
-	    for (p = buff; isalpha((unsigned char)(c = *yyInput++)) || c == '.'; )
+	    for (p = buff; isalpha((unsigned char)(c = *inp++)) || c == '.'; )
 		if (p < &buff[sizeof buff - 1])
 		    *p++ = c;
 	    *p = '\0';
-	    yyInput--;
-	    return LookupWord(buff);
+	    *yyInput = --inp;
+	    return LookupWord(yylval, buff);
 	}
 	if (c == '@') {
-	    yyInput++;
+	    *yyInput = ++inp;
 	    return AT_SIGN;
 	}
-	if (c != '(')
-	    return *yyInput++;
+	if (c != '(') {
+	    *yyInput = ++inp;
+	    return c;
+	}
 	Count = 0;
 	do {
-	    c = *yyInput++;
+	    c = *inp++;
 	    if (c == '\0')
 		return c;
 	    if (c == '(')
@@ -953,8 +956,8 @@
     int			zonet;
     time_t		Start;
     time_t		tod, rm;
+    struct dateinfo	param;
 
-    yyInput = p;
     if (now == NULL || zone == NULL) {
         now = &nowt;
 	zone = &zonet;
@@ -980,47 +983,48 @@
 	if ((tm = localtime_r(now, &local)) == NULL)
 	    return -1;
     }
-    yyYear = tm->tm_year + 1900;
-    yyMonth = tm->tm_mon + 1;
-    yyDay = tm->tm_mday;
-    yyTimezone = *zone;
-    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);
+    param.yyYear = tm->tm_year + 1900;
+    param.yyMonth = tm->tm_mon + 1;
+    param.yyDay = tm->tm_mday;
+    param.yyTimezone = *zone;
+    param.yyDSTmode = DSTmaybe;
+    param.yyHour = 0;
+    param.yyMinutes = 0;
+    param.yySeconds = 0;
+    param.yyMeridian = MER24;
+    param.yyRelSeconds = 0;
+    param.yyRelMonth = 0;
+    param.yyHaveDate = 0;
+    param.yyHaveDay = 0;
+    param.yyHaveRel = 0;
+    param.yyHaveTime = 0;
+    param.yyHaveZone = 0;
+
+    if (yyparse(&param, &p) || param.yyHaveTime > 1 || param.yyHaveZone > 1 ||
+	param.yyHaveDate > 1 || param.yyHaveDay > 1)
+	return -1;
+
+    if (param.yyHaveDate || param.yyHaveTime || param.yyHaveDay) {
+	Start = Convert(param.yyMonth, param.yyDay, param.yyYear, param.yyHour,
+	    param.yyMinutes, param.yySeconds, param.yyTimezone,
+	    param.yyMeridian, param.yyDSTmode);
 	if (Start < 0)
 	    return -1;
     }
     else {
 	Start = *now;
-	if (!yyHaveRel)
+	if (!param.yyHaveRel)
 	    Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
     }
 
-    Start += yyRelSeconds;
-    rm = RelativeMonth(Start, yyRelMonth);
+    Start += param.yyRelSeconds;
+    rm = RelativeMonth(Start, param.yyRelMonth, param.yyTimezone);
     if (rm == -1)
 	return -1;
     Start += rm;
 
-    if (yyHaveDay && !yyHaveDate) {
-	tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+    if (param.yyHaveDay && !param.yyHaveDate) {
+	tod = RelativeDate(Start, param.yyDayOrdinal, param.yyDayNumber);
 	Start += tod;
     }
 

Reply via email to