xref: /illumos-gate/usr/src/cmd/krb5/kadmin/cli/getdate.y (revision 2a8bcb4e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  *	Openvision retains the copyright to derivative works of
57c478bd9Sstevel@tonic-gate  *	this source code.  Do *NOT* create a derivative of this
67c478bd9Sstevel@tonic-gate  *	source code before consulting with your legal department.
77c478bd9Sstevel@tonic-gate  *	Do *NOT* integrate *ANY* of this source code into another
87c478bd9Sstevel@tonic-gate  *	product before consulting with your legal department.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  *	For further information, read the top-level Openvision
117c478bd9Sstevel@tonic-gate  *	copyright which is contained in the top-level MIT Kerberos
127c478bd9Sstevel@tonic-gate  *	copyright.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
157c478bd9Sstevel@tonic-gate  *
167c478bd9Sstevel@tonic-gate  */
177c478bd9Sstevel@tonic-gate 
187c478bd9Sstevel@tonic-gate 
197c478bd9Sstevel@tonic-gate %{
207c478bd9Sstevel@tonic-gate /*
2156a424ccSmp  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
227c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
2656a424ccSmp **  Originally written by Steven M. Bellovin <smb@research.att.com> while
2756a424ccSmp **  at the University of North Carolina at Chapel Hill.  Later tweaked by
2856a424ccSmp **  a couple of people on Usenet.  Completely overhauled by Rich $alz
2956a424ccSmp **  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
3056a424ccSmp **  send any email to Rich.
3156a424ccSmp **
3256a424ccSmp **  This grammar has nine shift/reduce conflicts.
3356a424ccSmp **
3456a424ccSmp **  This code is in the public domain and has no copyright.
3556a424ccSmp */
3656a424ccSmp /* SUPPRESS 287 on yaccpar_sccsid *//* Unusd static variable */
3756a424ccSmp /* SUPPRESS 288 on yyerrlab *//* Label unused */
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #ifdef HAVE_CONFIG_H
4056a424ccSmp #if defined (emacs) || defined (CONFIG_BROKETS)
417c478bd9Sstevel@tonic-gate #include <config.h>
427c478bd9Sstevel@tonic-gate #else
437c478bd9Sstevel@tonic-gate #include "config.h"
447c478bd9Sstevel@tonic-gate #endif
457c478bd9Sstevel@tonic-gate #endif
467c478bd9Sstevel@tonic-gate #include <string.h>
477c478bd9Sstevel@tonic-gate 
4856a424ccSmp /* Since the code of getdate.y is not included in the Emacs executable
4956a424ccSmp    itself, there is no need to #define static in this file.  Even if
5056a424ccSmp    the code were included in the Emacs executable, it probably
5156a424ccSmp    wouldn't do any harm to #undef it here; this will only cause
5256a424ccSmp    problems if we try to write to a static variable, which I don't
5356a424ccSmp    think this code needs to do.  */
547c478bd9Sstevel@tonic-gate #ifdef emacs
557c478bd9Sstevel@tonic-gate #undef static
567c478bd9Sstevel@tonic-gate #endif
577c478bd9Sstevel@tonic-gate 
5856a424ccSmp /* The following block of alloca-related preprocessor directives is here
5956a424ccSmp    solely to allow compilation by non GNU-C compilers of the C parser
6056a424ccSmp    produced from this file by old versions of bison.  Newer versions of
6156a424ccSmp    bison include a block similar to this one in bison.simple.  */
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate #ifdef __GNUC__
647c478bd9Sstevel@tonic-gate #undef alloca
6556a424ccSmp #define alloca __builtin_alloca
667c478bd9Sstevel@tonic-gate #else
677c478bd9Sstevel@tonic-gate #ifdef HAVE_ALLOCA_H
687c478bd9Sstevel@tonic-gate #include <alloca.h>
697c478bd9Sstevel@tonic-gate #else
707c478bd9Sstevel@tonic-gate #ifdef _AIX /* for Bison */
7156a424ccSmp  #pragma alloca
727c478bd9Sstevel@tonic-gate #else
7356a424ccSmp void *alloca ();
747c478bd9Sstevel@tonic-gate #endif
757c478bd9Sstevel@tonic-gate #endif
767c478bd9Sstevel@tonic-gate #endif
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate #include <stdio.h>
797c478bd9Sstevel@tonic-gate #include <ctype.h>
807c478bd9Sstevel@tonic-gate 
8156a424ccSmp #if defined(HAVE_STDLIB_H)
8256a424ccSmp #include <stdlib.h>
8356a424ccSmp #endif
8456a424ccSmp 
8556a424ccSmp /* The code at the top of get_date which figures out the offset of the
8656a424ccSmp    current time zone checks various CPP symbols to see if special
8756a424ccSmp    tricks are need, but defaults to using the gettimeofday system call.
8856a424ccSmp    Include <sys/time.h> if that will be used.  */
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate #if	defined(vms)
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #include <types.h>
937c478bd9Sstevel@tonic-gate #include <time.h>
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate #else
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate #include <sys/types.h>
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate #ifdef TIME_WITH_SYS_TIME
1007c478bd9Sstevel@tonic-gate #include <sys/time.h>
1017c478bd9Sstevel@tonic-gate #include <time.h>
1027c478bd9Sstevel@tonic-gate #else
1037c478bd9Sstevel@tonic-gate #ifdef HAVE_SYS_TIME_H
1047c478bd9Sstevel@tonic-gate #include <sys/time.h>
1057c478bd9Sstevel@tonic-gate #else
1067c478bd9Sstevel@tonic-gate #include <time.h>
1077c478bd9Sstevel@tonic-gate #endif
1087c478bd9Sstevel@tonic-gate #endif
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate #ifdef timezone
1117c478bd9Sstevel@tonic-gate #undef timezone /* needed for sgi */
1127c478bd9Sstevel@tonic-gate #endif
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate /*
11556a424ccSmp ** We use the obsolete `struct my_timeb' as part of our interface!
11656a424ccSmp ** Since the system doesn't have it, we define it here;
11756a424ccSmp ** our callers must do likewise.
11856a424ccSmp */
1197c478bd9Sstevel@tonic-gate struct my_timeb {
1207c478bd9Sstevel@tonic-gate     time_t		time;		/* Seconds since the epoch	*/
1217c478bd9Sstevel@tonic-gate     unsigned short	millitm;	/* Field not used		*/
1227c478bd9Sstevel@tonic-gate     short		timezone;	/* Minutes west of GMT		*/
1237c478bd9Sstevel@tonic-gate     short		dstflag;	/* Field not used		*/
1247c478bd9Sstevel@tonic-gate };
1257c478bd9Sstevel@tonic-gate #endif	/* defined(vms) */
1267c478bd9Sstevel@tonic-gate 
12756a424ccSmp #if defined (STDC_HEADERS) || defined (USG)
1287c478bd9Sstevel@tonic-gate #include <string.h>
1297c478bd9Sstevel@tonic-gate #endif
1307c478bd9Sstevel@tonic-gate 
13156a424ccSmp /* Some old versions of bison generate parsers that use bcopy.
13256a424ccSmp    That loses on systems that don't provide the function, so we have
13356a424ccSmp    to redefine it here.  */
13456a424ccSmp #ifndef bcopy
13556a424ccSmp #define bcopy(from, to, len) memcpy ((to), (from), (len))
1367c478bd9Sstevel@tonic-gate #endif
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate  * The following is a hack so that it is easy to internationalize
1407c478bd9Sstevel@tonic-gate  * statically declared strings. We define a wrapper function here that
1417c478bd9Sstevel@tonic-gate  * will be a replacement for gettext. We the make gettext a macro that
1427c478bd9Sstevel@tonic-gate  * just returns its argument, which now can be used with statically defined
1437c478bd9Sstevel@tonic-gate  * strings. The conquence of this is that GETTEXT must be used to translate
1447c478bd9Sstevel@tonic-gate  * a string at runtime and gettext must be used around string literals so
1457c478bd9Sstevel@tonic-gate  * that xgettext command can extract them to a portable object database file.
1467c478bd9Sstevel@tonic-gate  *
1477c478bd9Sstevel@tonic-gate  * Thus to translate a string literal that is an argument to a function foo
1487c478bd9Sstevel@tonic-gate  * the following will have to be performed:
1497c478bd9Sstevel@tonic-gate  *
1507c478bd9Sstevel@tonic-gate  *              foo(GETTEXT(gettext("This is a test")));
1517c478bd9Sstevel@tonic-gate  *
1527c478bd9Sstevel@tonic-gate  * The inner gettext call is for xgettext command to extract the string.
1537c478bd9Sstevel@tonic-gate  * The C preprossesor will reduce the above to:
1547c478bd9Sstevel@tonic-gate  *
1557c478bd9Sstevel@tonic-gate  *              foo(GETTEXT(("This ia a test"));
1567c478bd9Sstevel@tonic-gate  */
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate #include <libintl.h>
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate static char *
GETTEXT(const char * msgid)1617c478bd9Sstevel@tonic-gate GETTEXT(const char *msgid)
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate 	return (gettext(msgid));
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate #define	gettext(s) (s)
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate extern struct tm	*gmtime();
1707c478bd9Sstevel@tonic-gate extern struct tm	*localtime();
1717c478bd9Sstevel@tonic-gate 
17256a424ccSmp #define yyparse getdate_yyparse
17356a424ccSmp #define yylex getdate_yylex
17456a424ccSmp #define yyerror getdate_yyerror
1757c478bd9Sstevel@tonic-gate 
17656a424ccSmp static int getdate_yylex (void);
17756a424ccSmp static int getdate_yyerror (char *);
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 
18056a424ccSmp #define EPOCH		1970
1817c478bd9Sstevel@tonic-gate #define EPOCH_END	2099  /* Solaris 64 bit can support this at this point */
18256a424ccSmp #define HOUR(x)		((time_t)(x) * 60)
18356a424ccSmp #define SECSPERDAY	(24L * 60L * 60L)
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate /*
18756a424ccSmp **  An entry in the lexical lookup table.
18856a424ccSmp */
1897c478bd9Sstevel@tonic-gate typedef struct _TABLE {
1907c478bd9Sstevel@tonic-gate     char	*name;
1917c478bd9Sstevel@tonic-gate     int		type;
1927c478bd9Sstevel@tonic-gate     time_t	value;
1937c478bd9Sstevel@tonic-gate } TABLE;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate /*
19756a424ccSmp **  Daylight-savings mode:  on, off, or not yet known.
19856a424ccSmp */
1997c478bd9Sstevel@tonic-gate typedef enum _DSTMODE {
2007c478bd9Sstevel@tonic-gate     DSTon, DSToff, DSTmaybe
2017c478bd9Sstevel@tonic-gate } DSTMODE;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate /*
20456a424ccSmp **  Meridian:  am, pm, or 24-hour style.
20556a424ccSmp */
2067c478bd9Sstevel@tonic-gate typedef enum _MERIDIAN {
2077c478bd9Sstevel@tonic-gate     MERam, MERpm, MER24
2087c478bd9Sstevel@tonic-gate } MERIDIAN;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate /*
21256a424ccSmp **  Global variables.  We could get rid of most of these by using a good
21356a424ccSmp **  union as the yacc stack.  (This routine was originally written before
21456a424ccSmp **  yacc had the %union construct.)  Maybe someday; right now we only use
21556a424ccSmp **  the %union very rarely.
21656a424ccSmp */
2177c478bd9Sstevel@tonic-gate static char	*yyInput;
2187c478bd9Sstevel@tonic-gate static DSTMODE	yyDSTmode;
2197c478bd9Sstevel@tonic-gate static time_t	yyDayOrdinal;
2207c478bd9Sstevel@tonic-gate static time_t	yyDayNumber;
2217c478bd9Sstevel@tonic-gate static int	yyHaveDate;
2227c478bd9Sstevel@tonic-gate static int	yyHaveDay;
2237c478bd9Sstevel@tonic-gate static int	yyHaveRel;
2247c478bd9Sstevel@tonic-gate static int	yyHaveTime;
2257c478bd9Sstevel@tonic-gate static int	yyHaveZone;
2267c478bd9Sstevel@tonic-gate static time_t	yyTimezone;
2277c478bd9Sstevel@tonic-gate static time_t	yyDay;
2287c478bd9Sstevel@tonic-gate static time_t	yyHour;
2297c478bd9Sstevel@tonic-gate static time_t	yyMinutes;
2307c478bd9Sstevel@tonic-gate static time_t	yyMonth;
2317c478bd9Sstevel@tonic-gate static time_t	yySeconds;
2327c478bd9Sstevel@tonic-gate static time_t	yyYear;
2337c478bd9Sstevel@tonic-gate static MERIDIAN	yyMeridian;
2347c478bd9Sstevel@tonic-gate static time_t	yyRelMonth;
2357c478bd9Sstevel@tonic-gate static time_t	yyRelSeconds;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate %}
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate %union {
2407c478bd9Sstevel@tonic-gate     time_t		Number;
2417c478bd9Sstevel@tonic-gate     enum _MERIDIAN	Meridian;
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate %token	tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
2457c478bd9Sstevel@tonic-gate %token	tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST tNEVER
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate %type	<Number>	tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
2487c478bd9Sstevel@tonic-gate %type	<Number>	tSEC_UNIT tSNUMBER tUNUMBER tZONE
2497c478bd9Sstevel@tonic-gate %type	<Meridian>	tMERIDIAN o_merid
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate %%
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate spec	: /* NULL */
2547c478bd9Sstevel@tonic-gate 	| spec item
25556a424ccSmp         | tNEVER {
2567c478bd9Sstevel@tonic-gate 	    yyYear = 1970;
2577c478bd9Sstevel@tonic-gate 	    yyMonth = 1;
2587c478bd9Sstevel@tonic-gate 	    yyDay = 1;
2597c478bd9Sstevel@tonic-gate 	    yyHour = yyMinutes = yySeconds = 0;
2607c478bd9Sstevel@tonic-gate 	    yyDSTmode = DSToff;
2617c478bd9Sstevel@tonic-gate 	    yyTimezone = 0; /* gmt */
2627c478bd9Sstevel@tonic-gate 	    yyHaveDate++;
26356a424ccSmp         }
2647c478bd9Sstevel@tonic-gate 	;
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate item	: time {
2677c478bd9Sstevel@tonic-gate 	    yyHaveTime++;
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 	| zone {
2707c478bd9Sstevel@tonic-gate 	    yyHaveZone++;
2717c478bd9Sstevel@tonic-gate 	}
2727c478bd9Sstevel@tonic-gate 	| date {
2737c478bd9Sstevel@tonic-gate 	    yyHaveDate++;
2747c478bd9Sstevel@tonic-gate 	}
2757c478bd9Sstevel@tonic-gate 	| day {
2767c478bd9Sstevel@tonic-gate 	    yyHaveDay++;
2777c478bd9Sstevel@tonic-gate 	}
2787c478bd9Sstevel@tonic-gate 	| rel {
2797c478bd9Sstevel@tonic-gate 	    yyHaveRel++;
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate 	;
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate time	: tUNUMBER tMERIDIAN {
2847c478bd9Sstevel@tonic-gate 	    yyHour = $1;
2857c478bd9Sstevel@tonic-gate 	    yyMinutes = 0;
2867c478bd9Sstevel@tonic-gate 	    yySeconds = 0;
2877c478bd9Sstevel@tonic-gate 	    yyMeridian = $2;
2887c478bd9Sstevel@tonic-gate 	}
2897c478bd9Sstevel@tonic-gate 	| tUNUMBER ':' tUNUMBER o_merid {
2907c478bd9Sstevel@tonic-gate 	    yyHour = $1;
2917c478bd9Sstevel@tonic-gate 	    yyMinutes = $3;
2927c478bd9Sstevel@tonic-gate 	    yySeconds = 0;
2937c478bd9Sstevel@tonic-gate 	    yyMeridian = $4;
2947c478bd9Sstevel@tonic-gate 	}
2957c478bd9Sstevel@tonic-gate 	| tUNUMBER ':' tUNUMBER tSNUMBER {
2967c478bd9Sstevel@tonic-gate 	    yyHour = $1;
2977c478bd9Sstevel@tonic-gate 	    yyMinutes = $3;
2987c478bd9Sstevel@tonic-gate 	    yyMeridian = MER24;
2997c478bd9Sstevel@tonic-gate 	    yyDSTmode = DSToff;
3007c478bd9Sstevel@tonic-gate 	    yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
3037c478bd9Sstevel@tonic-gate 	    yyHour = $1;
3047c478bd9Sstevel@tonic-gate 	    yyMinutes = $3;
3057c478bd9Sstevel@tonic-gate 	    yySeconds = $5;
3067c478bd9Sstevel@tonic-gate 	    yyMeridian = $6;
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
3097c478bd9Sstevel@tonic-gate 	    yyHour = $1;
3107c478bd9Sstevel@tonic-gate 	    yyMinutes = $3;
3117c478bd9Sstevel@tonic-gate 	    yySeconds = $5;
3127c478bd9Sstevel@tonic-gate 	    yyMeridian = MER24;
3137c478bd9Sstevel@tonic-gate 	    yyDSTmode = DSToff;
3147c478bd9Sstevel@tonic-gate 	    yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
3157c478bd9Sstevel@tonic-gate 	}
3167c478bd9Sstevel@tonic-gate 	;
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate zone	: tZONE {
3197c478bd9Sstevel@tonic-gate 	    yyTimezone = $1;
3207c478bd9Sstevel@tonic-gate 	    yyDSTmode = DSToff;
3217c478bd9Sstevel@tonic-gate 	}
3227c478bd9Sstevel@tonic-gate 	| tDAYZONE {
3237c478bd9Sstevel@tonic-gate 	    yyTimezone = $1;
3247c478bd9Sstevel@tonic-gate 	    yyDSTmode = DSTon;
3257c478bd9Sstevel@tonic-gate 	}
3267c478bd9Sstevel@tonic-gate 	|
32756a424ccSmp 	  tZONE tDST {
3287c478bd9Sstevel@tonic-gate 	    yyTimezone = $1;
3297c478bd9Sstevel@tonic-gate 	    yyDSTmode = DSTon;
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate 	;
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate day	: tDAY {
3347c478bd9Sstevel@tonic-gate 	    yyDayOrdinal = 1;
3357c478bd9Sstevel@tonic-gate 	    yyDayNumber = $1;
3367c478bd9Sstevel@tonic-gate 	}
3377c478bd9Sstevel@tonic-gate 	| tDAY ',' {
3387c478bd9Sstevel@tonic-gate 	    yyDayOrdinal = 1;
3397c478bd9Sstevel@tonic-gate 	    yyDayNumber = $1;
3407c478bd9Sstevel@tonic-gate 	}
3417c478bd9Sstevel@tonic-gate 	| tUNUMBER tDAY {
3427c478bd9Sstevel@tonic-gate 	    yyDayOrdinal = $1;
3437c478bd9Sstevel@tonic-gate 	    yyDayNumber = $2;
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate 	;
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate date	: tUNUMBER '/' tUNUMBER {
3487c478bd9Sstevel@tonic-gate 	    yyMonth = $1;
3497c478bd9Sstevel@tonic-gate 	    yyDay = $3;
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 	| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
3527c478bd9Sstevel@tonic-gate 	    yyMonth = $1;
3537c478bd9Sstevel@tonic-gate 	    yyDay = $3;
3547c478bd9Sstevel@tonic-gate 	    yyYear = $5;
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate 	| tUNUMBER tSNUMBER tSNUMBER {
3577c478bd9Sstevel@tonic-gate 	    /* ISO 8601 format.  yyyy-mm-dd.  */
3587c478bd9Sstevel@tonic-gate 	    yyYear = $1;
3597c478bd9Sstevel@tonic-gate 	    yyMonth = -$2;
3607c478bd9Sstevel@tonic-gate 	    yyDay = -$3;
3617c478bd9Sstevel@tonic-gate 	}
3627c478bd9Sstevel@tonic-gate 	| tUNUMBER tMONTH tSNUMBER {
3637c478bd9Sstevel@tonic-gate 	    /* e.g. 17-JUN-1992.  */
3647c478bd9Sstevel@tonic-gate 	    yyDay = $1;
3657c478bd9Sstevel@tonic-gate 	    yyMonth = $2;
3667c478bd9Sstevel@tonic-gate 	    yyYear = -$3;
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate 	| tMONTH tUNUMBER {
3697c478bd9Sstevel@tonic-gate 	    yyMonth = $1;
3707c478bd9Sstevel@tonic-gate 	    yyDay = $2;
3717c478bd9Sstevel@tonic-gate 	}
3727c478bd9Sstevel@tonic-gate 	| tMONTH tUNUMBER ',' tUNUMBER {
3737c478bd9Sstevel@tonic-gate 	    yyMonth = $1;
3747c478bd9Sstevel@tonic-gate 	    yyDay = $2;
3757c478bd9Sstevel@tonic-gate 	    yyYear = $4;
3767c478bd9Sstevel@tonic-gate 	}
3777c478bd9Sstevel@tonic-gate 	| tUNUMBER tMONTH {
3787c478bd9Sstevel@tonic-gate 	    yyMonth = $2;
3797c478bd9Sstevel@tonic-gate 	    yyDay = $1;
3807c478bd9Sstevel@tonic-gate 	}
3817c478bd9Sstevel@tonic-gate 	| tUNUMBER tMONTH tUNUMBER {
3827c478bd9Sstevel@tonic-gate 	    yyMonth = $2;
3837c478bd9Sstevel@tonic-gate 	    yyDay = $1;
3847c478bd9Sstevel@tonic-gate 	    yyYear = $3;
3857c478bd9Sstevel@tonic-gate 	}
3867c478bd9Sstevel@tonic-gate 	;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate rel	: relunit tAGO {
3897c478bd9Sstevel@tonic-gate 	    yyRelSeconds = -yyRelSeconds;
3907c478bd9Sstevel@tonic-gate 	    yyRelMonth = -yyRelMonth;
3917c478bd9Sstevel@tonic-gate 	}
3927c478bd9Sstevel@tonic-gate 	| relunit
3937c478bd9Sstevel@tonic-gate 	;
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate relunit	: tUNUMBER tMINUTE_UNIT {
3967c478bd9Sstevel@tonic-gate 	    yyRelSeconds += $1 * $2 * 60L;
3977c478bd9Sstevel@tonic-gate 	}
3987c478bd9Sstevel@tonic-gate 	| tSNUMBER tMINUTE_UNIT {
3997c478bd9Sstevel@tonic-gate 	    yyRelSeconds += $1 * $2 * 60L;
4007c478bd9Sstevel@tonic-gate 	}
4017c478bd9Sstevel@tonic-gate 	| tMINUTE_UNIT {
4027c478bd9Sstevel@tonic-gate 	    yyRelSeconds += $1 * 60L;
4037c478bd9Sstevel@tonic-gate 	}
4047c478bd9Sstevel@tonic-gate 	| tSNUMBER tSEC_UNIT {
4057c478bd9Sstevel@tonic-gate 	    yyRelSeconds += $1;
4067c478bd9Sstevel@tonic-gate 	}
4077c478bd9Sstevel@tonic-gate 	| tUNUMBER tSEC_UNIT {
4087c478bd9Sstevel@tonic-gate 	    yyRelSeconds += $1;
4097c478bd9Sstevel@tonic-gate 	}
4107c478bd9Sstevel@tonic-gate 	| tSEC_UNIT {
4117c478bd9Sstevel@tonic-gate 	    yyRelSeconds++;
4127c478bd9Sstevel@tonic-gate 	}
4137c478bd9Sstevel@tonic-gate 	| tSNUMBER tMONTH_UNIT {
4147c478bd9Sstevel@tonic-gate 	    yyRelMonth += $1 * $2;
4157c478bd9Sstevel@tonic-gate 	}
4167c478bd9Sstevel@tonic-gate 	| tUNUMBER tMONTH_UNIT {
4177c478bd9Sstevel@tonic-gate 	    yyRelMonth += $1 * $2;
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate 	| tMONTH_UNIT {
4207c478bd9Sstevel@tonic-gate 	    yyRelMonth += $1;
4217c478bd9Sstevel@tonic-gate 	}
4227c478bd9Sstevel@tonic-gate 	;
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate o_merid	: /* NULL */ {
4257c478bd9Sstevel@tonic-gate 	    $$ = MER24;
4267c478bd9Sstevel@tonic-gate 	}
4277c478bd9Sstevel@tonic-gate 	| tMERIDIAN {
4287c478bd9Sstevel@tonic-gate 	    $$ = $1;
4297c478bd9Sstevel@tonic-gate 	}
4307c478bd9Sstevel@tonic-gate 	;
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate %%
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate /* Month and day table. */
4357c478bd9Sstevel@tonic-gate static TABLE const MonthDayTable[] = {
4367c478bd9Sstevel@tonic-gate 	{ gettext("january"),	tMONTH,  1 },
4377c478bd9Sstevel@tonic-gate 	{ gettext("february"),	tMONTH,  2 },
4387c478bd9Sstevel@tonic-gate 	{ gettext("march"),	tMONTH,  3 },
4397c478bd9Sstevel@tonic-gate 	{ gettext("april"),	tMONTH,  4 },
4407c478bd9Sstevel@tonic-gate 	{ gettext("may"),	tMONTH,  5 },
4417c478bd9Sstevel@tonic-gate 	{ gettext("june"),	tMONTH,  6 },
4427c478bd9Sstevel@tonic-gate 	{ gettext("july"),	tMONTH,  7 },
4437c478bd9Sstevel@tonic-gate 	{ gettext("august"),	tMONTH,  8 },
4447c478bd9Sstevel@tonic-gate 	{ gettext("september"),	tMONTH,  9 },
4457c478bd9Sstevel@tonic-gate 	{ gettext("sept"),	tMONTH,  9 },
4467c478bd9Sstevel@tonic-gate 	{ gettext("october"),	tMONTH, 10 },
4477c478bd9Sstevel@tonic-gate 	{ gettext("november"),	tMONTH, 11 },
4487c478bd9Sstevel@tonic-gate 	{ gettext("december"),	tMONTH, 12 },
4497c478bd9Sstevel@tonic-gate 	{ gettext("sunday"),	tDAY, 0 },
4507c478bd9Sstevel@tonic-gate 	{ gettext("monday"),	tDAY, 1 },
4517c478bd9Sstevel@tonic-gate 	{ gettext("tuesday"),	tDAY, 2 },
4527c478bd9Sstevel@tonic-gate 	{ gettext("tues"),	tDAY, 2 },
4537c478bd9Sstevel@tonic-gate 	{ gettext("wednesday"),	tDAY, 3 },
4547c478bd9Sstevel@tonic-gate 	{ gettext("wednes"),	tDAY, 3 },
4557c478bd9Sstevel@tonic-gate 	{ gettext("thursday"),	tDAY, 4 },
4567c478bd9Sstevel@tonic-gate 	{ gettext("thur"),	tDAY, 4 },
4577c478bd9Sstevel@tonic-gate 	{ gettext("thurs"),	tDAY, 4 },
4587c478bd9Sstevel@tonic-gate 	{ gettext("friday"),	tDAY, 5 },
4597c478bd9Sstevel@tonic-gate 	{ gettext("saturday"),	tDAY, 6 },
4607c478bd9Sstevel@tonic-gate 	{ NULL }
4617c478bd9Sstevel@tonic-gate };
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate /* Time units table. */
4647c478bd9Sstevel@tonic-gate static TABLE const UnitsTable[] = {
4657c478bd9Sstevel@tonic-gate 	{ gettext("year"),		tMONTH_UNIT,	12 },
4667c478bd9Sstevel@tonic-gate 	{ gettext("month"),		tMONTH_UNIT,	1 },
4677c478bd9Sstevel@tonic-gate 	{ gettext("fortnight"),	tMINUTE_UNIT,	14 * 24 * 60 },
4687c478bd9Sstevel@tonic-gate 	{ gettext("week"),		tMINUTE_UNIT,	7 * 24 * 60 },
4697c478bd9Sstevel@tonic-gate 	{ gettext("day"),		tMINUTE_UNIT,	1 * 24 * 60 },
4707c478bd9Sstevel@tonic-gate 	{ gettext("hour"),		tMINUTE_UNIT,	60 },
4717c478bd9Sstevel@tonic-gate 	{ gettext("minute"),	tMINUTE_UNIT,	1 },
4727c478bd9Sstevel@tonic-gate 	{ gettext("min"),		tMINUTE_UNIT,	1 },
4737c478bd9Sstevel@tonic-gate 	{ gettext("second"),	tSEC_UNIT,	1 },
4747c478bd9Sstevel@tonic-gate 	{ gettext("sec"),		tSEC_UNIT,	1 },
4757c478bd9Sstevel@tonic-gate 	{ NULL }
4767c478bd9Sstevel@tonic-gate };
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate /* Assorted relative-time words. */
4797c478bd9Sstevel@tonic-gate static TABLE const OtherTable[] = {
4807c478bd9Sstevel@tonic-gate 	{ gettext("tomorrow"),	tMINUTE_UNIT,	1 * 24 * 60 },
4817c478bd9Sstevel@tonic-gate 	{ gettext("yesterday"),	tMINUTE_UNIT,	-1 * 24 * 60 },
4827c478bd9Sstevel@tonic-gate 	{ gettext("today"),	tMINUTE_UNIT,	0 },
4837c478bd9Sstevel@tonic-gate 	{ gettext("now"),	tMINUTE_UNIT,	0 },
4847c478bd9Sstevel@tonic-gate 	{ gettext("last"),	tUNUMBER,	-1 },
4857c478bd9Sstevel@tonic-gate 	{ gettext("this"),	tMINUTE_UNIT,	0 },
4867c478bd9Sstevel@tonic-gate 	{ gettext("next"),	tUNUMBER,	2 },
4877c478bd9Sstevel@tonic-gate 	{ gettext("first"),	tUNUMBER,	1 },
4887c478bd9Sstevel@tonic-gate 	/*  { gettext("second"),	tUNUMBER,	2 }, */
4897c478bd9Sstevel@tonic-gate 	{ gettext("third"),	tUNUMBER,	3 },
4907c478bd9Sstevel@tonic-gate 	{ gettext("fourth"),	tUNUMBER,	4 },
4917c478bd9Sstevel@tonic-gate 	{ gettext("fifth"),	tUNUMBER,	5 },
4927c478bd9Sstevel@tonic-gate 	{ gettext("sixth"),	tUNUMBER,	6 },
4937c478bd9Sstevel@tonic-gate 	{ gettext("seventh"),	tUNUMBER,	7 },
4947c478bd9Sstevel@tonic-gate 	{ gettext("eighth"),	tUNUMBER,	8 },
4957c478bd9Sstevel@tonic-gate 	{ gettext("ninth"),	tUNUMBER,	9 },
4967c478bd9Sstevel@tonic-gate 	{ gettext("tenth"),	tUNUMBER,	10 },
4977c478bd9Sstevel@tonic-gate 	{ gettext("eleventh"),	tUNUMBER,	11 },
4987c478bd9Sstevel@tonic-gate 	{ gettext("twelfth"),	tUNUMBER,	12 },
4997c478bd9Sstevel@tonic-gate 	{ gettext("ago"),	tAGO,		1 },
5007c478bd9Sstevel@tonic-gate 	{ gettext("never"),	tNEVER,		0 },
5017c478bd9Sstevel@tonic-gate 	{ NULL }
5027c478bd9Sstevel@tonic-gate };
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate /* The timezone table. */
5057c478bd9Sstevel@tonic-gate /* Some of these are commented out because a time_t can't store a float. */
5067c478bd9Sstevel@tonic-gate static TABLE const TimezoneTable[] = {
50756a424ccSmp 	{ gettext("gmt"),	tZONE,     HOUR( 0) },	/* Greenwich Mean */
50856a424ccSmp 	{ gettext("ut"),	tZONE,     HOUR( 0) },	/* Universal (Coordinated) */
50956a424ccSmp 	{ gettext("utc"),	tZONE,     HOUR( 0) },
51056a424ccSmp 	{ gettext("wet"),	tZONE,     HOUR( 0) },	/* Western European */
51156a424ccSmp 	{ gettext("bst"),	tDAYZONE,  HOUR( 0) },	/* British Summer */
51256a424ccSmp 	{ gettext("wat"),	tZONE,     HOUR( 1) },	/* West Africa */
51356a424ccSmp 	{ gettext("at"),	tZONE,     HOUR( 2) },	/* Azores */
5147c478bd9Sstevel@tonic-gate #if	0
51556a424ccSmp     /* For completeness.  BST is also British Summer, and GST is
51656a424ccSmp      * also Guam Standard. */
51756a424ccSmp     { gettext("bst"),	tZONE,     HOUR( 3) },	/* Brazil Standard */
51856a424ccSmp     { gettext("gst"),	tZONE,     HOUR( 3) },	/* Greenland Standard */
5197c478bd9Sstevel@tonic-gate #endif
5207c478bd9Sstevel@tonic-gate #if 0
5217c478bd9Sstevel@tonic-gate 	{ gettext("nft"),	tZONE,     HOUR(3.5) },	/* Newfoundland */
5227c478bd9Sstevel@tonic-gate 	{ gettext("nst"),	tZONE,     HOUR(3.5) },	/* Newfoundland Standard */
5237c478bd9Sstevel@tonic-gate 	{ gettext("ndt"),	tDAYZONE,  HOUR(3.5) },	/* Newfoundland Daylight */
5247c478bd9Sstevel@tonic-gate #endif
5257c478bd9Sstevel@tonic-gate 	{ gettext("ast"),	tZONE,     HOUR( 4) },	/* Atlantic Standard */
5267c478bd9Sstevel@tonic-gate 	{ gettext("adt"),	tDAYZONE,  HOUR( 4) },	/* Atlantic Daylight */
5277c478bd9Sstevel@tonic-gate 	{ gettext("est"),	tZONE,     HOUR( 5) },	/* Eastern Standard */
5287c478bd9Sstevel@tonic-gate 	{ gettext("edt"),	tDAYZONE,  HOUR( 5) },	/* Eastern Daylight */
5297c478bd9Sstevel@tonic-gate 	{ gettext("cst"),	tZONE,     HOUR( 6) },	/* Central Standard */
5307c478bd9Sstevel@tonic-gate 	{ gettext("cdt"),	tDAYZONE,  HOUR( 6) },	/* Central Daylight */
5317c478bd9Sstevel@tonic-gate 	{ gettext("mst"),	tZONE,     HOUR( 7) },	/* Mountain Standard */
5327c478bd9Sstevel@tonic-gate 	{ gettext("mdt"),	tDAYZONE,  HOUR( 7) },	/* Mountain Daylight */
5337c478bd9Sstevel@tonic-gate 	{ gettext("pst"),	tZONE,     HOUR( 8) },	/* Pacific Standard */
5347c478bd9Sstevel@tonic-gate 	{ gettext("pdt"),	tDAYZONE,  HOUR( 8) },	/* Pacific Daylight */
5357c478bd9Sstevel@tonic-gate 	{ gettext("yst"),	tZONE,     HOUR( 9) },	/* Yukon Standard */
5367c478bd9Sstevel@tonic-gate 	{ gettext("ydt"),	tDAYZONE,  HOUR( 9) },	/* Yukon Daylight */
5377c478bd9Sstevel@tonic-gate 	{ gettext("hst"),	tZONE,     HOUR(10) },	/* Hawaii Standard */
5387c478bd9Sstevel@tonic-gate 	{ gettext("hdt"),	tDAYZONE,  HOUR(10) },	/* Hawaii Daylight */
5397c478bd9Sstevel@tonic-gate 	{ gettext("cat"),	tZONE,     HOUR(10) },	/* Central Alaska */
5407c478bd9Sstevel@tonic-gate 	{ gettext("ahst"),	tZONE,     HOUR(10) },	/* Alaska-Hawaii Standard */
5417c478bd9Sstevel@tonic-gate 	{ gettext("nt"),	tZONE,     HOUR(11) },	/* Nome */
5427c478bd9Sstevel@tonic-gate 	{ gettext("idlw"),	tZONE,     HOUR(12) },	/* International Date Line West */
5437c478bd9Sstevel@tonic-gate 	{ gettext("cet"),	tZONE,     -HOUR(1) },	/* Central European */
5447c478bd9Sstevel@tonic-gate 	{ gettext("met"),	tZONE,     -HOUR(1) },	/* Middle European */
5457c478bd9Sstevel@tonic-gate 	{ gettext("mewt"),	tZONE,     -HOUR(1) },	/* Middle European Winter */
5467c478bd9Sstevel@tonic-gate 	{ gettext("mest"),	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
5477c478bd9Sstevel@tonic-gate 	{ gettext("swt"),	tZONE,     -HOUR(1) },	/* Swedish Winter */
5487c478bd9Sstevel@tonic-gate 	{ gettext("sst"),	tDAYZONE,  -HOUR(1) },	/* Swedish Summer */
5497c478bd9Sstevel@tonic-gate 	{ gettext("fwt"),	tZONE,     -HOUR(1) },	/* French Winter */
5507c478bd9Sstevel@tonic-gate 	{ gettext("fst"),	tDAYZONE,  -HOUR(1) },	/* French Summer */
5517c478bd9Sstevel@tonic-gate 	{ gettext("eet"),	tZONE,     -HOUR(2) },	/* Eastern Europe, USSR Zone 1 */
5527c478bd9Sstevel@tonic-gate 	{ gettext("bt"),	tZONE,     -HOUR(3) },	/* Baghdad, USSR Zone 2 */
5537c478bd9Sstevel@tonic-gate #if 0
5547c478bd9Sstevel@tonic-gate 	{ gettext("it"),	tZONE,     -HOUR(3.5) },/* Iran */
5557c478bd9Sstevel@tonic-gate #endif
5567c478bd9Sstevel@tonic-gate 	{ gettext("zp4"),	tZONE,     -HOUR(4) },	/* USSR Zone 3 */
5577c478bd9Sstevel@tonic-gate 	{ gettext("zp5"),	tZONE,     -HOUR(5) },	/* USSR Zone 4 */
5587c478bd9Sstevel@tonic-gate #if 0
5597c478bd9Sstevel@tonic-gate 	{ gettext("ist"),	tZONE,     -HOUR(5.5) },/* Indian Standard */
5607c478bd9Sstevel@tonic-gate #endif
5617c478bd9Sstevel@tonic-gate 	{ gettext("zp6"),	tZONE,     -HOUR(6) },	/* USSR Zone 5 */
5627c478bd9Sstevel@tonic-gate #if	0
56356a424ccSmp     /* For completeness.  NST is also Newfoundland Stanard, and SST is
56456a424ccSmp      * also Swedish Summer. */
56556a424ccSmp     { gettext("nst"),	tZONE,     -HOUR(6.5) },/* North Sumatra */
56656a424ccSmp     { gettext("sst"),	tZONE,     -HOUR(7) },	/* South Sumatra, USSR Zone 6 */
5677c478bd9Sstevel@tonic-gate #endif	/* 0 */
5687c478bd9Sstevel@tonic-gate 	{ gettext("wast"),	tZONE,     -HOUR(7) },	/* West Australian Standard */
5697c478bd9Sstevel@tonic-gate 	{ gettext("wadt"),	tDAYZONE,  -HOUR(7) },	/* West Australian Daylight */
5707c478bd9Sstevel@tonic-gate #if 0
5717c478bd9Sstevel@tonic-gate 	{ gettext("jt"),	tZONE,     -HOUR(7.5) },/* Java (3pm in Cronusland!) */
5727c478bd9Sstevel@tonic-gate #endif
5737c478bd9Sstevel@tonic-gate 	{ gettext("cct"),	tZONE,     -HOUR(8) },	/* China Coast, USSR Zone 7 */
5747c478bd9Sstevel@tonic-gate 	{ gettext("jst"),	tZONE,     -HOUR(9) },	/* Japan Standard, USSR Zone 8 */
5757c478bd9Sstevel@tonic-gate 	{ gettext("kst"),	tZONE,     -HOUR(9) },	/* Korean Standard */
5767c478bd9Sstevel@tonic-gate #if 0
5777c478bd9Sstevel@tonic-gate 	{ gettext("cast"),	tZONE,     -HOUR(9.5) },/* Central Australian Standard */
5787c478bd9Sstevel@tonic-gate 	{ gettext("cadt"),	tDAYZONE,  -HOUR(9.5) },/* Central Australian Daylight */
5797c478bd9Sstevel@tonic-gate #endif
5807c478bd9Sstevel@tonic-gate 	{ gettext("east"),	tZONE,     -HOUR(10) },	/* Eastern Australian Standard */
5817c478bd9Sstevel@tonic-gate 	{ gettext("eadt"),	tDAYZONE,  -HOUR(10) },	/* Eastern Australian Daylight */
5827c478bd9Sstevel@tonic-gate 	{ gettext("gst"),	tZONE,     -HOUR(10) },	/* Guam Standard, USSR Zone 9 */
5837c478bd9Sstevel@tonic-gate 	{ gettext("kdt"),	tZONE,     -HOUR(10) },	/* Korean Daylight */
5847c478bd9Sstevel@tonic-gate 	{ gettext("nzt"),	tZONE,     -HOUR(12) },	/* New Zealand */
5857c478bd9Sstevel@tonic-gate 	{ gettext("nzst"),	tZONE,     -HOUR(12) },	/* New Zealand Standard */
5867c478bd9Sstevel@tonic-gate 	{ gettext("nzdt"),	tDAYZONE,  -HOUR(12) },	/* New Zealand Daylight */
5877c478bd9Sstevel@tonic-gate 	{ gettext("idle"),	tZONE,     -HOUR(12) },	/* International Date Line East */
5887c478bd9Sstevel@tonic-gate 	{  NULL  }
5897c478bd9Sstevel@tonic-gate };
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate /* ARGSUSED */
5927c478bd9Sstevel@tonic-gate static int
yyerror(s)5937c478bd9Sstevel@tonic-gate yyerror(s)
59456a424ccSmp     char	*s;
5957c478bd9Sstevel@tonic-gate {
59656a424ccSmp   return 0;
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate static time_t
ToSeconds(Hours,Minutes,Seconds,Meridian)60156a424ccSmp ToSeconds(Hours, Minutes, Seconds, Meridian)
60256a424ccSmp     time_t	Hours;
60356a424ccSmp     time_t	Minutes;
60456a424ccSmp     time_t	Seconds;
60556a424ccSmp     MERIDIAN	Meridian;
6067c478bd9Sstevel@tonic-gate {
60756a424ccSmp     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
60856a424ccSmp 	return -1;
60956a424ccSmp     switch (Meridian) {
61056a424ccSmp     case MER24:
61156a424ccSmp 	if (Hours < 0 || Hours > 23)
61256a424ccSmp 	    return -1;
61356a424ccSmp 	return (Hours * 60L + Minutes) * 60L + Seconds;
61456a424ccSmp     case MERam:
61556a424ccSmp 	if (Hours < 1 || Hours > 12)
61656a424ccSmp 	    return -1;
61756a424ccSmp 	return (Hours * 60L + Minutes) * 60L + Seconds;
61856a424ccSmp     case MERpm:
61956a424ccSmp 	if (Hours < 1 || Hours > 12)
62056a424ccSmp 	    return -1;
62156a424ccSmp 	return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
62256a424ccSmp     default:
62356a424ccSmp 	abort ();
62456a424ccSmp     }
62556a424ccSmp     /* NOTREACHED */
6267c478bd9Sstevel@tonic-gate }
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate /*
6297c478bd9Sstevel@tonic-gate  * From hh:mm:ss [am|pm] mm/dd/yy [tz], compute and return the number
6307c478bd9Sstevel@tonic-gate  * of seconds since 00:00:00 1/1/70 GMT.
6317c478bd9Sstevel@tonic-gate  */
6327c478bd9Sstevel@tonic-gate static time_t
Convert(Month,Day,Year,Hours,Minutes,Seconds,Meridian,DSTmode)63356a424ccSmp Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
63456a424ccSmp     time_t	Month;
63556a424ccSmp     time_t	Day;
63656a424ccSmp     time_t	Year;
63756a424ccSmp     time_t	Hours;
63856a424ccSmp     time_t	Minutes;
63956a424ccSmp     time_t	Seconds;
64056a424ccSmp     MERIDIAN	Meridian;
64156a424ccSmp     DSTMODE	DSTmode;
6427c478bd9Sstevel@tonic-gate {
64356a424ccSmp     static int DaysInMonth[12] = {
64456a424ccSmp 	31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
64556a424ccSmp     };
64656a424ccSmp     time_t	tod;
64756a424ccSmp     time_t	Julian;
64856a424ccSmp     int		i;
64956a424ccSmp 
65056a424ccSmp     if (Year < 0)
65156a424ccSmp 	Year = -Year;
65256a424ccSmp     if (Year < 1900)
65356a424ccSmp 	Year += 1900;
65456a424ccSmp     DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
65556a424ccSmp 		    ? 29 : 28;
65656a424ccSmp     if (Year < EPOCH
65756a424ccSmp 	|| Year > EPOCH_END
65856a424ccSmp 	|| Month < 1 || Month > 12
65956a424ccSmp 	/* Lint fluff:  "conversion from long may lose accuracy" */
66056a424ccSmp 	|| Day < 1 || Day > DaysInMonth[(int)--Month])
66156a424ccSmp 	 return -1;
66256a424ccSmp 
66356a424ccSmp     for (Julian = Day - 1, i = 0; i < Month; i++)
66456a424ccSmp 	Julian += DaysInMonth[i];
66556a424ccSmp     for (i = EPOCH; i < Year; i++)
66656a424ccSmp 	 Julian += 365 + ((i % 4 == 0) && ((Year % 100 != 0) ||
66756a424ccSmp 					   (Year % 400 == 0)));
66856a424ccSmp     Julian *= SECSPERDAY;
66956a424ccSmp     Julian += yyTimezone * 60L;
67056a424ccSmp     if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
67156a424ccSmp 	return -1;
67256a424ccSmp     Julian += tod;
67356a424ccSmp     if (DSTmode == DSTon
67456a424ccSmp      || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
67556a424ccSmp 	Julian -= 60 * 60;
67656a424ccSmp     return Julian;
6777c478bd9Sstevel@tonic-gate }
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate static time_t
DSTcorrect(Start,Future)6817c478bd9Sstevel@tonic-gate DSTcorrect(Start, Future)
68256a424ccSmp     time_t	Start;
68356a424ccSmp     time_t	Future;
6847c478bd9Sstevel@tonic-gate {
68556a424ccSmp     time_t	StartDay;
68656a424ccSmp     time_t	FutureDay;
6877c478bd9Sstevel@tonic-gate 
68856a424ccSmp     StartDay = (localtime(&Start)->tm_hour + 1) % 24;
68956a424ccSmp     FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
69056a424ccSmp     return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
6917c478bd9Sstevel@tonic-gate }
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate static time_t
RelativeDate(Start,DayOrdinal,DayNumber)6957c478bd9Sstevel@tonic-gate RelativeDate(Start, DayOrdinal, DayNumber)
69656a424ccSmp     time_t	Start;
69756a424ccSmp     time_t	DayOrdinal;
69856a424ccSmp     time_t	DayNumber;
6997c478bd9Sstevel@tonic-gate {
70056a424ccSmp     struct tm	*tm;
70156a424ccSmp     time_t	now;
70256a424ccSmp 
70356a424ccSmp     now = Start;
70456a424ccSmp     tm = localtime(&now);
70556a424ccSmp     now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
70656a424ccSmp     now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
70756a424ccSmp     return DSTcorrect(Start, now);
7087c478bd9Sstevel@tonic-gate }
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate static time_t
RelativeMonth(Start,RelMonth)71256a424ccSmp RelativeMonth(Start, RelMonth)
71356a424ccSmp     time_t	Start;
71456a424ccSmp     time_t	RelMonth;
7157c478bd9Sstevel@tonic-gate {
71656a424ccSmp     struct tm	*tm;
71756a424ccSmp     time_t	Month;
71856a424ccSmp     time_t	Year;
71956a424ccSmp     time_t	ret;
72056a424ccSmp 
72156a424ccSmp     if (RelMonth == 0)
72256a424ccSmp 	return 0;
72356a424ccSmp     tm = localtime(&Start);
72456a424ccSmp     Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
72556a424ccSmp     Year = Month / 12;
72656a424ccSmp     Month = Month % 12 + 1;
7277c478bd9Sstevel@tonic-gate     ret = Convert(Month, (time_t)tm->tm_mday, Year,
72856a424ccSmp 		  (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
72956a424ccSmp 		  MER24, DSTmaybe);
7307c478bd9Sstevel@tonic-gate     if (ret == -1)
73156a424ccSmp       return ret;
7327c478bd9Sstevel@tonic-gate     return DSTcorrect(Start, ret);
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate static int
LookupWord(buff)73756a424ccSmp LookupWord(buff)
73856a424ccSmp     char		*buff;
7397c478bd9Sstevel@tonic-gate {
74056a424ccSmp     register char	*p;
74156a424ccSmp     register char	*q;
74256a424ccSmp     register const TABLE	*tp;
74356a424ccSmp     int			i;
74456a424ccSmp     int			abbrev;
74556a424ccSmp 
74656a424ccSmp     /* Make it lowercase. */
74756a424ccSmp     for (p = buff; *p; p++)
74856a424ccSmp 	if (isupper((int) *p))
74956a424ccSmp 	    *p = tolower((int) *p);
75056a424ccSmp 
75156a424ccSmp     if (strcmp(buff, gettext("am")) == 0 || strcmp(buff, gettext("a.m.")) == 0) {
75256a424ccSmp 	yylval.Meridian = MERam;
75356a424ccSmp 	return tMERIDIAN;
75456a424ccSmp     }
75556a424ccSmp     if (strcmp(buff, gettext("pm")) == 0 ||
7567c478bd9Sstevel@tonic-gate 	    strcmp(buff, gettext("p.m.")) == 0) {
75756a424ccSmp 	yylval.Meridian = MERpm;
75856a424ccSmp 	return tMERIDIAN;
75956a424ccSmp     }
76056a424ccSmp 
76156a424ccSmp     /* See if we have an abbreviation for a month. */
76256a424ccSmp     if (strlen(buff) == 3)
76356a424ccSmp 	abbrev = 1;
76456a424ccSmp     else if (strlen(buff) == 4 && buff[3] == '.') {
76556a424ccSmp 	abbrev = 1;
76656a424ccSmp 	buff[3] = '\0';
76756a424ccSmp     }
76856a424ccSmp     else
76956a424ccSmp 	abbrev = 0;
77056a424ccSmp 
77156a424ccSmp     for (tp = MonthDayTable; tp->name; tp++) {
77256a424ccSmp 	if (abbrev) {
77356a424ccSmp 	    if (strncmp(buff, GETTEXT(tp->name), 3) == 0) {
77456a424ccSmp 		yylval.Number = tp->value;
77556a424ccSmp 		return tp->type;
77656a424ccSmp 	    }
7777c478bd9Sstevel@tonic-gate 	}
77856a424ccSmp 	else if (strcmp(buff, GETTEXT(tp->name)) == 0) {
77956a424ccSmp 	    yylval.Number = tp->value;
78056a424ccSmp 	    return tp->type;
7817c478bd9Sstevel@tonic-gate 	}
78256a424ccSmp     }
7837c478bd9Sstevel@tonic-gate 
78456a424ccSmp     for (tp = TimezoneTable; tp->name; tp++)
78556a424ccSmp 	if (strcmp(buff, GETTEXT(tp->name)) == 0) {
78656a424ccSmp 	    yylval.Number = tp->value;
78756a424ccSmp 	    return tp->type;
78856a424ccSmp 	}
7897c478bd9Sstevel@tonic-gate 
79056a424ccSmp     if (strcmp(buff, gettext("dst")) == 0)
79156a424ccSmp 	return tDST;
7927c478bd9Sstevel@tonic-gate 
79356a424ccSmp     for (tp = UnitsTable; tp->name; tp++)
79456a424ccSmp 	if (strcmp(buff, GETTEXT(tp->name)) == 0) {
79556a424ccSmp 	    yylval.Number = tp->value;
79656a424ccSmp 	    return tp->type;
79756a424ccSmp 	}
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate     /* Strip off any plural and try the units table again. */
80056a424ccSmp     i = strlen(buff) - 1;
80156a424ccSmp     if (buff[i] == 's') {
80256a424ccSmp 	buff[i] = '\0';
80356a424ccSmp 	for (tp = UnitsTable; tp->name; tp++)
80456a424ccSmp 	    if (strcmp(buff, GETTEXT(tp->name)) == 0) {
80556a424ccSmp 		yylval.Number = tp->value;
80656a424ccSmp 		return tp->type;
80756a424ccSmp 	    }
80856a424ccSmp 	buff[i] = 's';		/* Put back for "this" in OtherTable. */
80956a424ccSmp     }
81056a424ccSmp 
81156a424ccSmp     for (tp = OtherTable; tp->name; tp++)
81256a424ccSmp 	if (strcmp(buff, GETTEXT(tp->name)) == 0) {
81356a424ccSmp 	    yylval.Number = tp->value;
81456a424ccSmp 	    return tp->type;
8157c478bd9Sstevel@tonic-gate 	}
8167c478bd9Sstevel@tonic-gate 
81756a424ccSmp     /* Drop out any periods and try the timezone table again. */
81856a424ccSmp     for (i = 0, p = q = buff; *q; q++)
81956a424ccSmp 	if (*q != '.')
82056a424ccSmp 	    *p++ = *q;
82156a424ccSmp 	else
82256a424ccSmp 	    i++;
82356a424ccSmp     *p = '\0';
82456a424ccSmp     if (i)
82556a424ccSmp 	for (tp = TimezoneTable; tp->name; tp++)
82656a424ccSmp 	    if (strcmp(buff, GETTEXT(tp->name)) == 0) {
82756a424ccSmp 		yylval.Number = tp->value;
82856a424ccSmp 		return tp->type;
82956a424ccSmp 	    }
83056a424ccSmp 
83156a424ccSmp     return tID;
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate static int
yylex()8367c478bd9Sstevel@tonic-gate yylex()
8377c478bd9Sstevel@tonic-gate {
83856a424ccSmp     register char	c;
83956a424ccSmp     register char	*p;
84056a424ccSmp     char		buff[20];
84156a424ccSmp     int			Count;
84256a424ccSmp     int			sign;
84356a424ccSmp 
84456a424ccSmp     for ( ; ; ) {
84556a424ccSmp 	while (isspace((int) *yyInput))
84656a424ccSmp 	    yyInput++;
84756a424ccSmp 
84856a424ccSmp 	c = *yyInput;
84956a424ccSmp 	if (isdigit((int) c) || c == '-' || c == '+') {
85056a424ccSmp 	    if (c == '-' || c == '+') {
85156a424ccSmp 		sign = c == '-' ? -1 : 1;
85256a424ccSmp 		if (!isdigit((int) (*++yyInput)))
85356a424ccSmp 		    /* skip the '-' sign */
85456a424ccSmp 		    continue;
85556a424ccSmp 	    }
85656a424ccSmp 	    else
85756a424ccSmp 		sign = 0;
85856a424ccSmp 	    for (yylval.Number = 0; isdigit((int) (c = *yyInput++)); )
85956a424ccSmp 		yylval.Number = 10 * yylval.Number + c - '0';
86056a424ccSmp 	    yyInput--;
86156a424ccSmp 	    if (sign < 0)
86256a424ccSmp 		yylval.Number = -yylval.Number;
86356a424ccSmp 	    return sign ? tSNUMBER : tUNUMBER;
8647c478bd9Sstevel@tonic-gate 	}
86556a424ccSmp 	if (isalpha((int) c)) {
86656a424ccSmp 	    for (p = buff; isalpha((int) (c = *yyInput++)) || c == '.'; )
86756a424ccSmp 		if (p < &buff[sizeof buff - 1])
86856a424ccSmp 		    *p++ = c;
86956a424ccSmp 	    *p = '\0';
87056a424ccSmp 	    yyInput--;
87156a424ccSmp 	    return LookupWord(buff);
87256a424ccSmp 	}
87356a424ccSmp 	if (c != '(')
87456a424ccSmp 	    return *yyInput++;
87556a424ccSmp 	Count = 0;
87656a424ccSmp 	do {
87756a424ccSmp 	    c = *yyInput++;
87856a424ccSmp 	    if (c == '\0')
87956a424ccSmp 		return c;
88056a424ccSmp 	    if (c == '(')
88156a424ccSmp 		Count++;
88256a424ccSmp 	    else if (c == ')')
88356a424ccSmp 		Count--;
88456a424ccSmp 	} while (Count > 0);
88556a424ccSmp     }
8867c478bd9Sstevel@tonic-gate }
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate 
88956a424ccSmp #define TM_YEAR_ORIGIN 1900
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate /* Yield A - B, measured in seconds.  */
8927c478bd9Sstevel@tonic-gate static time_t
difftm(a,b)89356a424ccSmp difftm(a, b)
89456a424ccSmp      struct tm *a, *b;
8957c478bd9Sstevel@tonic-gate {
89656a424ccSmp   int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
89756a424ccSmp   int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
89856a424ccSmp   return
89956a424ccSmp     (
90056a424ccSmp      (
90156a424ccSmp       (
90256a424ccSmp        /* difference in day of year */
90356a424ccSmp        a->tm_yday - b->tm_yday
90456a424ccSmp        /* + intervening leap days */
90556a424ccSmp        +  ((ay >> 2) - (by >> 2))
90656a424ccSmp        -  (ay/100 - by/100)
90756a424ccSmp        +  ((ay/100 >> 2) - (by/100 >> 2))
90856a424ccSmp        /* + difference in years * 365 */
90956a424ccSmp        +  (time_t)(ay-by) * 365
91056a424ccSmp        )*24 + (a->tm_hour - b->tm_hour)
91156a424ccSmp       )*60 + (a->tm_min - b->tm_min)
91256a424ccSmp      )*60 + (a->tm_sec - b->tm_sec);
9137c478bd9Sstevel@tonic-gate }
9147c478bd9Sstevel@tonic-gate 
91556a424ccSmp /* For get_date extern declaration compatibility check... yuck.  */
91656a424ccSmp #include <krb5.h>
91756a424ccSmp #include "kadmin.h"
91856a424ccSmp 
9197c478bd9Sstevel@tonic-gate time_t
get_date(p)92056a424ccSmp get_date(p)
92156a424ccSmp     char		*p;
9227c478bd9Sstevel@tonic-gate {
92356a424ccSmp     struct my_timeb	*now = NULL;
92456a424ccSmp     struct tm		*tm, gmt;
92556a424ccSmp     struct my_timeb	ftz;
92656a424ccSmp     time_t		Start;
92756a424ccSmp     time_t		tod;
9287c478bd9Sstevel@tonic-gate     time_t		delta;
9297c478bd9Sstevel@tonic-gate 
93056a424ccSmp     yyInput = p;
93156a424ccSmp     if (now == NULL) {
93256a424ccSmp         now = &ftz;
93356a424ccSmp 
93456a424ccSmp 	ftz.time = time((time_t *) 0);
93556a424ccSmp 
93656a424ccSmp 	if (! (tm = gmtime (&ftz.time)))
93756a424ccSmp 	    return -1;
93856a424ccSmp 	gmt = *tm;	/* Make a copy, in case localtime modifies *tm.  */
93956a424ccSmp 	ftz.timezone = difftm (&gmt, localtime (&ftz.time)) / 60;
94056a424ccSmp     }
94156a424ccSmp 
94256a424ccSmp     tm = localtime(&now->time);
94356a424ccSmp     yyYear = tm->tm_year;
94456a424ccSmp     yyMonth = tm->tm_mon + 1;
94556a424ccSmp     yyDay = tm->tm_mday;
94656a424ccSmp     yyTimezone = now->timezone;
94756a424ccSmp     yyDSTmode = DSTmaybe;
94856a424ccSmp     yyHour = 0;
94956a424ccSmp     yyMinutes = 0;
95056a424ccSmp     yySeconds = 0;
95156a424ccSmp     yyMeridian = MER24;
95256a424ccSmp     yyRelSeconds = 0;
95356a424ccSmp     yyRelMonth = 0;
95456a424ccSmp     yyHaveDate = 0;
95556a424ccSmp     yyHaveDay = 0;
95656a424ccSmp     yyHaveRel = 0;
95756a424ccSmp     yyHaveTime = 0;
95856a424ccSmp     yyHaveZone = 0;
95956a424ccSmp 
96056a424ccSmp     /*
961*2a8bcb4eSToomas Soome      * When yyparse returns, zero or more of yyHave{Time,Zone,Date,Day,Rel}
96256a424ccSmp      * will have been incremented.  The value is number of items of
96356a424ccSmp      * that type that were found; for all but Rel, more than one is
96456a424ccSmp      * illegal.
96556a424ccSmp      *
96656a424ccSmp      * For each yyHave indicator, the following values are set:
96756a424ccSmp      *
96856a424ccSmp      * yyHaveTime:
96956a424ccSmp      *	yyHour, yyMinutes, yySeconds: hh:mm:ss specified, initialized
97056a424ccSmp      *				      to zeros above
97156a424ccSmp      *	yyMeridian: MERam, MERpm, or MER24
97256a424ccSmp      *	yyTimeZone: time zone specified in minutes
97356a424ccSmp      *  yyDSTmode: DSToff if yyTimeZone is set, otherwise unchanged
97456a424ccSmp      *		   (initialized above to DSTmaybe)
97556a424ccSmp      *
97656a424ccSmp      * yyHaveZone:
97756a424ccSmp      *  yyTimezone: as above
97856a424ccSmp      *  yyDSTmode: DSToff if a non-DST zone is specified, otherwise DSTon
97956a424ccSmp      *	XXX don't understand interaction with yyHaveTime zone info
98056a424ccSmp      *
98156a424ccSmp      * yyHaveDay:
98256a424ccSmp      *	yyDayNumber: 0-6 for Sunday-Saturday
98356a424ccSmp      *  yyDayOrdinal: val specified with day ("second monday",
98456a424ccSmp      *		      Ordinal=2), otherwise 1
98556a424ccSmp      *
98656a424ccSmp      * yyHaveDate:
98756a424ccSmp      *	yyMonth, yyDay, yyYear: mm/dd/yy specified, initialized to
98856a424ccSmp      *				today above
98956a424ccSmp      *
99056a424ccSmp      * yyHaveRel:
99156a424ccSmp      *	yyRelSeconds: seconds specified with MINUTE_UNITs ("3 hours") or
99256a424ccSmp      *		      SEC_UNITs ("30 seconds")
99356a424ccSmp      *  yyRelMonth: months specified with MONTH_UNITs ("3 months", "1
99456a424ccSmp      *		     year")
99556a424ccSmp      *
99656a424ccSmp      * The code following yyparse turns these values into a single
99756a424ccSmp      * date stamp.
99856a424ccSmp      */
99956a424ccSmp     if (yyparse()
100056a424ccSmp      || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
100156a424ccSmp 	return -1;
100256a424ccSmp 
100356a424ccSmp     /*
100456a424ccSmp      * If an absolute time specified, set Start to the equivalent Unix
100556a424ccSmp      * timestamp.  Otherwise, set Start to now, and if we do not have
100656a424ccSmp      * a relatime time (ie: only yyHaveZone), decrement Start to the
100756a424ccSmp      * beginning of today.
100856a424ccSmp      *
100956a424ccSmp      * By having yyHaveDay in the "absolute" list, "next Monday" means
101056a424ccSmp      * midnight next Monday.  Otherwise, "next Monday" would mean the
101156a424ccSmp      * time right now, next Monday.  It's not clear to me why the
101256a424ccSmp      * current behavior is preferred.
101356a424ccSmp      */
101456a424ccSmp     if (yyHaveDate || yyHaveTime || yyHaveDay) {
101556a424ccSmp 	Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
101656a424ccSmp 		    yyMeridian, yyDSTmode);
101756a424ccSmp 	if (Start < 0)
101856a424ccSmp 	    return -1;
101956a424ccSmp     }
102056a424ccSmp     else {
102156a424ccSmp 	Start = now->time;
102256a424ccSmp 	if (!yyHaveRel)
102356a424ccSmp 	    Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
102456a424ccSmp     }
102556a424ccSmp 
102656a424ccSmp     /*
102756a424ccSmp      * Add in the relative time specified.  RelativeMonth adds in the
102856a424ccSmp      * months, accounting for the fact that the actual length of "3
102956a424ccSmp      * months" depends on where you start counting.
103056a424ccSmp      *
103156a424ccSmp      * XXX By having this separate from the previous block, we are
103256a424ccSmp      * allowing dates like "10:00am 3 months", which means 3 months
103356a424ccSmp      * from 10:00am today, or even "1/1/99 two days" which means two
103456a424ccSmp      * days after 1/1/99.
103556a424ccSmp      *
103656a424ccSmp      * XXX Shouldn't this only be done if yyHaveRel, just for
103756a424ccSmp      * thoroughness?
103856a424ccSmp      */
103956a424ccSmp     Start += yyRelSeconds;
10407c478bd9Sstevel@tonic-gate     delta = RelativeMonth(Start, yyRelMonth);
10417c478bd9Sstevel@tonic-gate     if (delta == (time_t) -1)
104256a424ccSmp       return -1;
10437c478bd9Sstevel@tonic-gate     Start += delta;
10447c478bd9Sstevel@tonic-gate 
104556a424ccSmp     /*
104656a424ccSmp      * Now, if you specified a day of week and counter, add it in.  By
104756a424ccSmp      * disallowing Date but allowing Time, you can say "5pm next
104856a424ccSmp      * monday".
104956a424ccSmp      *
105056a424ccSmp      * XXX The yyHaveDay && !yyHaveDate restriction should be enforced
105156a424ccSmp      * above and be able to cause failure.
105256a424ccSmp      */
105356a424ccSmp     if (yyHaveDay && !yyHaveDate) {
105456a424ccSmp 	tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
105556a424ccSmp 	Start += tod;
105656a424ccSmp     }
105756a424ccSmp 
105856a424ccSmp     /* Have to do *something* with a legitimate -1 so it's distinguishable
105956a424ccSmp      * from the error return value.  (Alternately could set errno on error.) */
106056a424ccSmp     return Start == -1 ? 0 : Start;
10617c478bd9Sstevel@tonic-gate }
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate #if	defined(TEST)
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate /* ARGSUSED */
main(ac,av)106756a424ccSmp main(ac, av)
106856a424ccSmp     int		ac;
106956a424ccSmp     char	*av[];
10707c478bd9Sstevel@tonic-gate {
107156a424ccSmp     char	buff[128];
107256a424ccSmp     time_t	d;
107356a424ccSmp 
107456a424ccSmp     (void)printf(gettext("Enter date, or blank line to exit.\n\t> "));
107556a424ccSmp     (void)fflush(stdout);
107656a424ccSmp     while (gets(buff) && buff[0]) {
107756a424ccSmp 	d = get_date(buff, (struct my_timeb *)NULL);
107856a424ccSmp 	if (d == -1)
107956a424ccSmp 	    (void)printf(
10807c478bd9Sstevel@tonic-gate 				gettext("Bad format - couldn't convert.\n"));
108156a424ccSmp 	else
108256a424ccSmp 	    (void)printf("%s", ctime(&d));
108356a424ccSmp 	(void)printf("\t> ");
108456a424ccSmp 	(void)fflush(stdout);
108556a424ccSmp     }
108656a424ccSmp     exit(0);
108756a424ccSmp     /* NOTREACHED */
10887c478bd9Sstevel@tonic-gate }
10897c478bd9Sstevel@tonic-gate #endif	/* defined(TEST) */
1090