10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * Openvision retains the copyright to derivative works of
50Sstevel@tonic-gate * this source code. Do *NOT* create a derivative of this
60Sstevel@tonic-gate * source code before consulting with your legal department.
70Sstevel@tonic-gate * Do *NOT* integrate *ANY* of this source code into another
80Sstevel@tonic-gate * product before consulting with your legal department.
90Sstevel@tonic-gate *
100Sstevel@tonic-gate * For further information, read the top-level Openvision
110Sstevel@tonic-gate * copyright which is contained in the top-level MIT Kerberos
120Sstevel@tonic-gate * copyright.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
150Sstevel@tonic-gate *
160Sstevel@tonic-gate */
170Sstevel@tonic-gate
180Sstevel@tonic-gate
190Sstevel@tonic-gate %{
200Sstevel@tonic-gate /*
21*2881Smp153739 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
220Sstevel@tonic-gate * Use is subject to license terms.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
260Sstevel@tonic-gate
270Sstevel@tonic-gate /*
28*2881Smp153739 ** Originally written by Steven M. Bellovin <smb@research.att.com> while
29*2881Smp153739 ** at the University of North Carolina at Chapel Hill. Later tweaked by
30*2881Smp153739 ** a couple of people on Usenet. Completely overhauled by Rich $alz
31*2881Smp153739 ** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
32*2881Smp153739 ** send any email to Rich.
33*2881Smp153739 **
34*2881Smp153739 ** This grammar has nine shift/reduce conflicts.
35*2881Smp153739 **
36*2881Smp153739 ** This code is in the public domain and has no copyright.
37*2881Smp153739 */
38*2881Smp153739 /* SUPPRESS 287 on yaccpar_sccsid *//* Unusd static variable */
39*2881Smp153739 /* SUPPRESS 288 on yyerrlab *//* Label unused */
400Sstevel@tonic-gate
410Sstevel@tonic-gate #ifdef HAVE_CONFIG_H
42*2881Smp153739 #if defined (emacs) || defined (CONFIG_BROKETS)
430Sstevel@tonic-gate #include <config.h>
440Sstevel@tonic-gate #else
450Sstevel@tonic-gate #include "config.h"
460Sstevel@tonic-gate #endif
470Sstevel@tonic-gate #endif
480Sstevel@tonic-gate #include <string.h>
490Sstevel@tonic-gate
50*2881Smp153739 /* Since the code of getdate.y is not included in the Emacs executable
51*2881Smp153739 itself, there is no need to #define static in this file. Even if
52*2881Smp153739 the code were included in the Emacs executable, it probably
53*2881Smp153739 wouldn't do any harm to #undef it here; this will only cause
54*2881Smp153739 problems if we try to write to a static variable, which I don't
55*2881Smp153739 think this code needs to do. */
560Sstevel@tonic-gate #ifdef emacs
570Sstevel@tonic-gate #undef static
580Sstevel@tonic-gate #endif
590Sstevel@tonic-gate
60*2881Smp153739 /* The following block of alloca-related preprocessor directives is here
61*2881Smp153739 solely to allow compilation by non GNU-C compilers of the C parser
62*2881Smp153739 produced from this file by old versions of bison. Newer versions of
63*2881Smp153739 bison include a block similar to this one in bison.simple. */
640Sstevel@tonic-gate
650Sstevel@tonic-gate #ifdef __GNUC__
660Sstevel@tonic-gate #undef alloca
67*2881Smp153739 #define alloca __builtin_alloca
680Sstevel@tonic-gate #else
690Sstevel@tonic-gate #ifdef HAVE_ALLOCA_H
700Sstevel@tonic-gate #include <alloca.h>
710Sstevel@tonic-gate #else
720Sstevel@tonic-gate #ifdef _AIX /* for Bison */
73*2881Smp153739 #pragma alloca
740Sstevel@tonic-gate #else
75*2881Smp153739 void *alloca ();
760Sstevel@tonic-gate #endif
770Sstevel@tonic-gate #endif
780Sstevel@tonic-gate #endif
790Sstevel@tonic-gate
800Sstevel@tonic-gate #include <stdio.h>
810Sstevel@tonic-gate #include <ctype.h>
820Sstevel@tonic-gate
83*2881Smp153739 #if defined(HAVE_STDLIB_H)
84*2881Smp153739 #include <stdlib.h>
85*2881Smp153739 #endif
86*2881Smp153739
87*2881Smp153739 /* The code at the top of get_date which figures out the offset of the
88*2881Smp153739 current time zone checks various CPP symbols to see if special
89*2881Smp153739 tricks are need, but defaults to using the gettimeofday system call.
90*2881Smp153739 Include <sys/time.h> if that will be used. */
910Sstevel@tonic-gate
920Sstevel@tonic-gate #if defined(vms)
930Sstevel@tonic-gate
940Sstevel@tonic-gate #include <types.h>
950Sstevel@tonic-gate #include <time.h>
960Sstevel@tonic-gate
970Sstevel@tonic-gate #else
980Sstevel@tonic-gate
990Sstevel@tonic-gate #include <sys/types.h>
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate #ifdef TIME_WITH_SYS_TIME
1020Sstevel@tonic-gate #include <sys/time.h>
1030Sstevel@tonic-gate #include <time.h>
1040Sstevel@tonic-gate #else
1050Sstevel@tonic-gate #ifdef HAVE_SYS_TIME_H
1060Sstevel@tonic-gate #include <sys/time.h>
1070Sstevel@tonic-gate #else
1080Sstevel@tonic-gate #include <time.h>
1090Sstevel@tonic-gate #endif
1100Sstevel@tonic-gate #endif
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate #ifdef timezone
1130Sstevel@tonic-gate #undef timezone /* needed for sgi */
1140Sstevel@tonic-gate #endif
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate /*
117*2881Smp153739 ** We use the obsolete `struct my_timeb' as part of our interface!
118*2881Smp153739 ** Since the system doesn't have it, we define it here;
119*2881Smp153739 ** our callers must do likewise.
120*2881Smp153739 */
1210Sstevel@tonic-gate struct my_timeb {
1220Sstevel@tonic-gate time_t time; /* Seconds since the epoch */
1230Sstevel@tonic-gate unsigned short millitm; /* Field not used */
1240Sstevel@tonic-gate short timezone; /* Minutes west of GMT */
1250Sstevel@tonic-gate short dstflag; /* Field not used */
1260Sstevel@tonic-gate };
1270Sstevel@tonic-gate #endif /* defined(vms) */
1280Sstevel@tonic-gate
129*2881Smp153739 #if defined (STDC_HEADERS) || defined (USG)
1300Sstevel@tonic-gate #include <string.h>
1310Sstevel@tonic-gate #endif
1320Sstevel@tonic-gate
133*2881Smp153739 /* Some old versions of bison generate parsers that use bcopy.
134*2881Smp153739 That loses on systems that don't provide the function, so we have
135*2881Smp153739 to redefine it here. */
136*2881Smp153739 #ifndef bcopy
137*2881Smp153739 #define bcopy(from, to, len) memcpy ((to), (from), (len))
1380Sstevel@tonic-gate #endif
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate /*
1410Sstevel@tonic-gate * The following is a hack so that it is easy to internationalize
1420Sstevel@tonic-gate * statically declared strings. We define a wrapper function here that
1430Sstevel@tonic-gate * will be a replacement for gettext. We the make gettext a macro that
1440Sstevel@tonic-gate * just returns its argument, which now can be used with statically defined
1450Sstevel@tonic-gate * strings. The conquence of this is that GETTEXT must be used to translate
1460Sstevel@tonic-gate * a string at runtime and gettext must be used around string literals so
1470Sstevel@tonic-gate * that xgettext command can extract them to a portable object database file.
1480Sstevel@tonic-gate *
1490Sstevel@tonic-gate * Thus to translate a string literal that is an argument to a function foo
1500Sstevel@tonic-gate * the following will have to be performed:
1510Sstevel@tonic-gate *
1520Sstevel@tonic-gate * foo(GETTEXT(gettext("This is a test")));
1530Sstevel@tonic-gate *
1540Sstevel@tonic-gate * The inner gettext call is for xgettext command to extract the string.
1550Sstevel@tonic-gate * The C preprossesor will reduce the above to:
1560Sstevel@tonic-gate *
1570Sstevel@tonic-gate * foo(GETTEXT(("This ia a test"));
1580Sstevel@tonic-gate */
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate #include <libintl.h>
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate static char *
GETTEXT(const char * msgid)1630Sstevel@tonic-gate GETTEXT(const char *msgid)
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate return (gettext(msgid));
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate #define gettext(s) (s)
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate extern struct tm *gmtime();
1720Sstevel@tonic-gate extern struct tm *localtime();
1730Sstevel@tonic-gate
174*2881Smp153739 #define yyparse getdate_yyparse
175*2881Smp153739 #define yylex getdate_yylex
176*2881Smp153739 #define yyerror getdate_yyerror
1770Sstevel@tonic-gate
178*2881Smp153739 static int getdate_yylex (void);
179*2881Smp153739 static int getdate_yyerror (char *);
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate
182*2881Smp153739 #define EPOCH 1970
1830Sstevel@tonic-gate #define EPOCH_END 2099 /* Solaris 64 bit can support this at this point */
184*2881Smp153739 #define HOUR(x) ((time_t)(x) * 60)
185*2881Smp153739 #define SECSPERDAY (24L * 60L * 60L)
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate /*
189*2881Smp153739 ** An entry in the lexical lookup table.
190*2881Smp153739 */
1910Sstevel@tonic-gate typedef struct _TABLE {
1920Sstevel@tonic-gate char *name;
1930Sstevel@tonic-gate int type;
1940Sstevel@tonic-gate time_t value;
1950Sstevel@tonic-gate } TABLE;
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate /*
199*2881Smp153739 ** Daylight-savings mode: on, off, or not yet known.
200*2881Smp153739 */
2010Sstevel@tonic-gate typedef enum _DSTMODE {
2020Sstevel@tonic-gate DSTon, DSToff, DSTmaybe
2030Sstevel@tonic-gate } DSTMODE;
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate /*
206*2881Smp153739 ** Meridian: am, pm, or 24-hour style.
207*2881Smp153739 */
2080Sstevel@tonic-gate typedef enum _MERIDIAN {
2090Sstevel@tonic-gate MERam, MERpm, MER24
2100Sstevel@tonic-gate } MERIDIAN;
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate /*
214*2881Smp153739 ** Global variables. We could get rid of most of these by using a good
215*2881Smp153739 ** union as the yacc stack. (This routine was originally written before
216*2881Smp153739 ** yacc had the %union construct.) Maybe someday; right now we only use
217*2881Smp153739 ** the %union very rarely.
218*2881Smp153739 */
2190Sstevel@tonic-gate static char *yyInput;
2200Sstevel@tonic-gate static DSTMODE yyDSTmode;
2210Sstevel@tonic-gate static time_t yyDayOrdinal;
2220Sstevel@tonic-gate static time_t yyDayNumber;
2230Sstevel@tonic-gate static int yyHaveDate;
2240Sstevel@tonic-gate static int yyHaveDay;
2250Sstevel@tonic-gate static int yyHaveRel;
2260Sstevel@tonic-gate static int yyHaveTime;
2270Sstevel@tonic-gate static int yyHaveZone;
2280Sstevel@tonic-gate static time_t yyTimezone;
2290Sstevel@tonic-gate static time_t yyDay;
2300Sstevel@tonic-gate static time_t yyHour;
2310Sstevel@tonic-gate static time_t yyMinutes;
2320Sstevel@tonic-gate static time_t yyMonth;
2330Sstevel@tonic-gate static time_t yySeconds;
2340Sstevel@tonic-gate static time_t yyYear;
2350Sstevel@tonic-gate static MERIDIAN yyMeridian;
2360Sstevel@tonic-gate static time_t yyRelMonth;
2370Sstevel@tonic-gate static time_t yyRelSeconds;
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate %}
2400Sstevel@tonic-gate
2410Sstevel@tonic-gate %union {
2420Sstevel@tonic-gate time_t Number;
2430Sstevel@tonic-gate enum _MERIDIAN Meridian;
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate %token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
2470Sstevel@tonic-gate %token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST tNEVER
2480Sstevel@tonic-gate
2490Sstevel@tonic-gate %type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
2500Sstevel@tonic-gate %type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE
2510Sstevel@tonic-gate %type <Meridian> tMERIDIAN o_merid
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate %%
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate spec : /* NULL */
2560Sstevel@tonic-gate | spec item
257*2881Smp153739 | tNEVER {
2580Sstevel@tonic-gate yyYear = 1970;
2590Sstevel@tonic-gate yyMonth = 1;
2600Sstevel@tonic-gate yyDay = 1;
2610Sstevel@tonic-gate yyHour = yyMinutes = yySeconds = 0;
2620Sstevel@tonic-gate yyDSTmode = DSToff;
2630Sstevel@tonic-gate yyTimezone = 0; /* gmt */
2640Sstevel@tonic-gate yyHaveDate++;
265*2881Smp153739 }
2660Sstevel@tonic-gate ;
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate item : time {
2690Sstevel@tonic-gate yyHaveTime++;
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate | zone {
2720Sstevel@tonic-gate yyHaveZone++;
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate | date {
2750Sstevel@tonic-gate yyHaveDate++;
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate | day {
2780Sstevel@tonic-gate yyHaveDay++;
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate | rel {
2810Sstevel@tonic-gate yyHaveRel++;
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate ;
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate time : tUNUMBER tMERIDIAN {
2860Sstevel@tonic-gate yyHour = $1;
2870Sstevel@tonic-gate yyMinutes = 0;
2880Sstevel@tonic-gate yySeconds = 0;
2890Sstevel@tonic-gate yyMeridian = $2;
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate | tUNUMBER ':' tUNUMBER o_merid {
2920Sstevel@tonic-gate yyHour = $1;
2930Sstevel@tonic-gate yyMinutes = $3;
2940Sstevel@tonic-gate yySeconds = 0;
2950Sstevel@tonic-gate yyMeridian = $4;
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate | tUNUMBER ':' tUNUMBER tSNUMBER {
2980Sstevel@tonic-gate yyHour = $1;
2990Sstevel@tonic-gate yyMinutes = $3;
3000Sstevel@tonic-gate yyMeridian = MER24;
3010Sstevel@tonic-gate yyDSTmode = DSToff;
3020Sstevel@tonic-gate yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
3030Sstevel@tonic-gate }
3040Sstevel@tonic-gate | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
3050Sstevel@tonic-gate yyHour = $1;
3060Sstevel@tonic-gate yyMinutes = $3;
3070Sstevel@tonic-gate yySeconds = $5;
3080Sstevel@tonic-gate yyMeridian = $6;
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
3110Sstevel@tonic-gate yyHour = $1;
3120Sstevel@tonic-gate yyMinutes = $3;
3130Sstevel@tonic-gate yySeconds = $5;
3140Sstevel@tonic-gate yyMeridian = MER24;
3150Sstevel@tonic-gate yyDSTmode = DSToff;
3160Sstevel@tonic-gate yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate ;
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate zone : tZONE {
3210Sstevel@tonic-gate yyTimezone = $1;
3220Sstevel@tonic-gate yyDSTmode = DSToff;
3230Sstevel@tonic-gate }
3240Sstevel@tonic-gate | tDAYZONE {
3250Sstevel@tonic-gate yyTimezone = $1;
3260Sstevel@tonic-gate yyDSTmode = DSTon;
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate |
329*2881Smp153739 tZONE tDST {
3300Sstevel@tonic-gate yyTimezone = $1;
3310Sstevel@tonic-gate yyDSTmode = DSTon;
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate ;
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate day : tDAY {
3360Sstevel@tonic-gate yyDayOrdinal = 1;
3370Sstevel@tonic-gate yyDayNumber = $1;
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate | tDAY ',' {
3400Sstevel@tonic-gate yyDayOrdinal = 1;
3410Sstevel@tonic-gate yyDayNumber = $1;
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate | tUNUMBER tDAY {
3440Sstevel@tonic-gate yyDayOrdinal = $1;
3450Sstevel@tonic-gate yyDayNumber = $2;
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate ;
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate date : tUNUMBER '/' tUNUMBER {
3500Sstevel@tonic-gate yyMonth = $1;
3510Sstevel@tonic-gate yyDay = $3;
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
3540Sstevel@tonic-gate yyMonth = $1;
3550Sstevel@tonic-gate yyDay = $3;
3560Sstevel@tonic-gate yyYear = $5;
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate | tUNUMBER tSNUMBER tSNUMBER {
3590Sstevel@tonic-gate /* ISO 8601 format. yyyy-mm-dd. */
3600Sstevel@tonic-gate yyYear = $1;
3610Sstevel@tonic-gate yyMonth = -$2;
3620Sstevel@tonic-gate yyDay = -$3;
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate | tUNUMBER tMONTH tSNUMBER {
3650Sstevel@tonic-gate /* e.g. 17-JUN-1992. */
3660Sstevel@tonic-gate yyDay = $1;
3670Sstevel@tonic-gate yyMonth = $2;
3680Sstevel@tonic-gate yyYear = -$3;
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate | tMONTH tUNUMBER {
3710Sstevel@tonic-gate yyMonth = $1;
3720Sstevel@tonic-gate yyDay = $2;
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate | tMONTH tUNUMBER ',' tUNUMBER {
3750Sstevel@tonic-gate yyMonth = $1;
3760Sstevel@tonic-gate yyDay = $2;
3770Sstevel@tonic-gate yyYear = $4;
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate | tUNUMBER tMONTH {
3800Sstevel@tonic-gate yyMonth = $2;
3810Sstevel@tonic-gate yyDay = $1;
3820Sstevel@tonic-gate }
3830Sstevel@tonic-gate | tUNUMBER tMONTH tUNUMBER {
3840Sstevel@tonic-gate yyMonth = $2;
3850Sstevel@tonic-gate yyDay = $1;
3860Sstevel@tonic-gate yyYear = $3;
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate ;
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate rel : relunit tAGO {
3910Sstevel@tonic-gate yyRelSeconds = -yyRelSeconds;
3920Sstevel@tonic-gate yyRelMonth = -yyRelMonth;
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate | relunit
3950Sstevel@tonic-gate ;
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate relunit : tUNUMBER tMINUTE_UNIT {
3980Sstevel@tonic-gate yyRelSeconds += $1 * $2 * 60L;
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate | tSNUMBER tMINUTE_UNIT {
4010Sstevel@tonic-gate yyRelSeconds += $1 * $2 * 60L;
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate | tMINUTE_UNIT {
4040Sstevel@tonic-gate yyRelSeconds += $1 * 60L;
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate | tSNUMBER tSEC_UNIT {
4070Sstevel@tonic-gate yyRelSeconds += $1;
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate | tUNUMBER tSEC_UNIT {
4100Sstevel@tonic-gate yyRelSeconds += $1;
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate | tSEC_UNIT {
4130Sstevel@tonic-gate yyRelSeconds++;
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate | tSNUMBER tMONTH_UNIT {
4160Sstevel@tonic-gate yyRelMonth += $1 * $2;
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate | tUNUMBER tMONTH_UNIT {
4190Sstevel@tonic-gate yyRelMonth += $1 * $2;
4200Sstevel@tonic-gate }
4210Sstevel@tonic-gate | tMONTH_UNIT {
4220Sstevel@tonic-gate yyRelMonth += $1;
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate ;
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate o_merid : /* NULL */ {
4270Sstevel@tonic-gate $$ = MER24;
4280Sstevel@tonic-gate }
4290Sstevel@tonic-gate | tMERIDIAN {
4300Sstevel@tonic-gate $$ = $1;
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate ;
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate %%
4350Sstevel@tonic-gate
4360Sstevel@tonic-gate /* Month and day table. */
4370Sstevel@tonic-gate static TABLE const MonthDayTable[] = {
4380Sstevel@tonic-gate { gettext("january"), tMONTH, 1 },
4390Sstevel@tonic-gate { gettext("february"), tMONTH, 2 },
4400Sstevel@tonic-gate { gettext("march"), tMONTH, 3 },
4410Sstevel@tonic-gate { gettext("april"), tMONTH, 4 },
4420Sstevel@tonic-gate { gettext("may"), tMONTH, 5 },
4430Sstevel@tonic-gate { gettext("june"), tMONTH, 6 },
4440Sstevel@tonic-gate { gettext("july"), tMONTH, 7 },
4450Sstevel@tonic-gate { gettext("august"), tMONTH, 8 },
4460Sstevel@tonic-gate { gettext("september"), tMONTH, 9 },
4470Sstevel@tonic-gate { gettext("sept"), tMONTH, 9 },
4480Sstevel@tonic-gate { gettext("october"), tMONTH, 10 },
4490Sstevel@tonic-gate { gettext("november"), tMONTH, 11 },
4500Sstevel@tonic-gate { gettext("december"), tMONTH, 12 },
4510Sstevel@tonic-gate { gettext("sunday"), tDAY, 0 },
4520Sstevel@tonic-gate { gettext("monday"), tDAY, 1 },
4530Sstevel@tonic-gate { gettext("tuesday"), tDAY, 2 },
4540Sstevel@tonic-gate { gettext("tues"), tDAY, 2 },
4550Sstevel@tonic-gate { gettext("wednesday"), tDAY, 3 },
4560Sstevel@tonic-gate { gettext("wednes"), tDAY, 3 },
4570Sstevel@tonic-gate { gettext("thursday"), tDAY, 4 },
4580Sstevel@tonic-gate { gettext("thur"), tDAY, 4 },
4590Sstevel@tonic-gate { gettext("thurs"), tDAY, 4 },
4600Sstevel@tonic-gate { gettext("friday"), tDAY, 5 },
4610Sstevel@tonic-gate { gettext("saturday"), tDAY, 6 },
4620Sstevel@tonic-gate { NULL }
4630Sstevel@tonic-gate };
4640Sstevel@tonic-gate
4650Sstevel@tonic-gate /* Time units table. */
4660Sstevel@tonic-gate static TABLE const UnitsTable[] = {
4670Sstevel@tonic-gate { gettext("year"), tMONTH_UNIT, 12 },
4680Sstevel@tonic-gate { gettext("month"), tMONTH_UNIT, 1 },
4690Sstevel@tonic-gate { gettext("fortnight"), tMINUTE_UNIT, 14 * 24 * 60 },
4700Sstevel@tonic-gate { gettext("week"), tMINUTE_UNIT, 7 * 24 * 60 },
4710Sstevel@tonic-gate { gettext("day"), tMINUTE_UNIT, 1 * 24 * 60 },
4720Sstevel@tonic-gate { gettext("hour"), tMINUTE_UNIT, 60 },
4730Sstevel@tonic-gate { gettext("minute"), tMINUTE_UNIT, 1 },
4740Sstevel@tonic-gate { gettext("min"), tMINUTE_UNIT, 1 },
4750Sstevel@tonic-gate { gettext("second"), tSEC_UNIT, 1 },
4760Sstevel@tonic-gate { gettext("sec"), tSEC_UNIT, 1 },
4770Sstevel@tonic-gate { NULL }
4780Sstevel@tonic-gate };
4790Sstevel@tonic-gate
4800Sstevel@tonic-gate /* Assorted relative-time words. */
4810Sstevel@tonic-gate static TABLE const OtherTable[] = {
4820Sstevel@tonic-gate { gettext("tomorrow"), tMINUTE_UNIT, 1 * 24 * 60 },
4830Sstevel@tonic-gate { gettext("yesterday"), tMINUTE_UNIT, -1 * 24 * 60 },
4840Sstevel@tonic-gate { gettext("today"), tMINUTE_UNIT, 0 },
4850Sstevel@tonic-gate { gettext("now"), tMINUTE_UNIT, 0 },
4860Sstevel@tonic-gate { gettext("last"), tUNUMBER, -1 },
4870Sstevel@tonic-gate { gettext("this"), tMINUTE_UNIT, 0 },
4880Sstevel@tonic-gate { gettext("next"), tUNUMBER, 2 },
4890Sstevel@tonic-gate { gettext("first"), tUNUMBER, 1 },
4900Sstevel@tonic-gate /* { gettext("second"), tUNUMBER, 2 }, */
4910Sstevel@tonic-gate { gettext("third"), tUNUMBER, 3 },
4920Sstevel@tonic-gate { gettext("fourth"), tUNUMBER, 4 },
4930Sstevel@tonic-gate { gettext("fifth"), tUNUMBER, 5 },
4940Sstevel@tonic-gate { gettext("sixth"), tUNUMBER, 6 },
4950Sstevel@tonic-gate { gettext("seventh"), tUNUMBER, 7 },
4960Sstevel@tonic-gate { gettext("eighth"), tUNUMBER, 8 },
4970Sstevel@tonic-gate { gettext("ninth"), tUNUMBER, 9 },
4980Sstevel@tonic-gate { gettext("tenth"), tUNUMBER, 10 },
4990Sstevel@tonic-gate { gettext("eleventh"), tUNUMBER, 11 },
5000Sstevel@tonic-gate { gettext("twelfth"), tUNUMBER, 12 },
5010Sstevel@tonic-gate { gettext("ago"), tAGO, 1 },
5020Sstevel@tonic-gate { gettext("never"), tNEVER, 0 },
5030Sstevel@tonic-gate { NULL }
5040Sstevel@tonic-gate };
5050Sstevel@tonic-gate
5060Sstevel@tonic-gate /* The timezone table. */
5070Sstevel@tonic-gate /* Some of these are commented out because a time_t can't store a float. */
5080Sstevel@tonic-gate static TABLE const TimezoneTable[] = {
509*2881Smp153739 { gettext("gmt"), tZONE, HOUR( 0) }, /* Greenwich Mean */
510*2881Smp153739 { gettext("ut"), tZONE, HOUR( 0) }, /* Universal (Coordinated) */
511*2881Smp153739 { gettext("utc"), tZONE, HOUR( 0) },
512*2881Smp153739 { gettext("wet"), tZONE, HOUR( 0) }, /* Western European */
513*2881Smp153739 { gettext("bst"), tDAYZONE, HOUR( 0) }, /* British Summer */
514*2881Smp153739 { gettext("wat"), tZONE, HOUR( 1) }, /* West Africa */
515*2881Smp153739 { gettext("at"), tZONE, HOUR( 2) }, /* Azores */
5160Sstevel@tonic-gate #if 0
517*2881Smp153739 /* For completeness. BST is also British Summer, and GST is
518*2881Smp153739 * also Guam Standard. */
519*2881Smp153739 { gettext("bst"), tZONE, HOUR( 3) }, /* Brazil Standard */
520*2881Smp153739 { gettext("gst"), tZONE, HOUR( 3) }, /* Greenland Standard */
5210Sstevel@tonic-gate #endif
5220Sstevel@tonic-gate #if 0
5230Sstevel@tonic-gate { gettext("nft"), tZONE, HOUR(3.5) }, /* Newfoundland */
5240Sstevel@tonic-gate { gettext("nst"), tZONE, HOUR(3.5) }, /* Newfoundland Standard */
5250Sstevel@tonic-gate { gettext("ndt"), tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */
5260Sstevel@tonic-gate #endif
5270Sstevel@tonic-gate { gettext("ast"), tZONE, HOUR( 4) }, /* Atlantic Standard */
5280Sstevel@tonic-gate { gettext("adt"), tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
5290Sstevel@tonic-gate { gettext("est"), tZONE, HOUR( 5) }, /* Eastern Standard */
5300Sstevel@tonic-gate { gettext("edt"), tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
5310Sstevel@tonic-gate { gettext("cst"), tZONE, HOUR( 6) }, /* Central Standard */
5320Sstevel@tonic-gate { gettext("cdt"), tDAYZONE, HOUR( 6) }, /* Central Daylight */
5330Sstevel@tonic-gate { gettext("mst"), tZONE, HOUR( 7) }, /* Mountain Standard */
5340Sstevel@tonic-gate { gettext("mdt"), tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
5350Sstevel@tonic-gate { gettext("pst"), tZONE, HOUR( 8) }, /* Pacific Standard */
5360Sstevel@tonic-gate { gettext("pdt"), tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
5370Sstevel@tonic-gate { gettext("yst"), tZONE, HOUR( 9) }, /* Yukon Standard */
5380Sstevel@tonic-gate { gettext("ydt"), tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
5390Sstevel@tonic-gate { gettext("hst"), tZONE, HOUR(10) }, /* Hawaii Standard */
5400Sstevel@tonic-gate { gettext("hdt"), tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
5410Sstevel@tonic-gate { gettext("cat"), tZONE, HOUR(10) }, /* Central Alaska */
5420Sstevel@tonic-gate { gettext("ahst"), tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
5430Sstevel@tonic-gate { gettext("nt"), tZONE, HOUR(11) }, /* Nome */
5440Sstevel@tonic-gate { gettext("idlw"), tZONE, HOUR(12) }, /* International Date Line West */
5450Sstevel@tonic-gate { gettext("cet"), tZONE, -HOUR(1) }, /* Central European */
5460Sstevel@tonic-gate { gettext("met"), tZONE, -HOUR(1) }, /* Middle European */
5470Sstevel@tonic-gate { gettext("mewt"), tZONE, -HOUR(1) }, /* Middle European Winter */
5480Sstevel@tonic-gate { gettext("mest"), tDAYZONE, -HOUR(1) }, /* Middle European Summer */
5490Sstevel@tonic-gate { gettext("swt"), tZONE, -HOUR(1) }, /* Swedish Winter */
5500Sstevel@tonic-gate { gettext("sst"), tDAYZONE, -HOUR(1) }, /* Swedish Summer */
5510Sstevel@tonic-gate { gettext("fwt"), tZONE, -HOUR(1) }, /* French Winter */
5520Sstevel@tonic-gate { gettext("fst"), tDAYZONE, -HOUR(1) }, /* French Summer */
5530Sstevel@tonic-gate { gettext("eet"), tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */
5540Sstevel@tonic-gate { gettext("bt"), tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
5550Sstevel@tonic-gate #if 0
5560Sstevel@tonic-gate { gettext("it"), tZONE, -HOUR(3.5) },/* Iran */
5570Sstevel@tonic-gate #endif
5580Sstevel@tonic-gate { gettext("zp4"), tZONE, -HOUR(4) }, /* USSR Zone 3 */
5590Sstevel@tonic-gate { gettext("zp5"), tZONE, -HOUR(5) }, /* USSR Zone 4 */
5600Sstevel@tonic-gate #if 0
5610Sstevel@tonic-gate { gettext("ist"), tZONE, -HOUR(5.5) },/* Indian Standard */
5620Sstevel@tonic-gate #endif
5630Sstevel@tonic-gate { gettext("zp6"), tZONE, -HOUR(6) }, /* USSR Zone 5 */
5640Sstevel@tonic-gate #if 0
565*2881Smp153739 /* For completeness. NST is also Newfoundland Stanard, and SST is
566*2881Smp153739 * also Swedish Summer. */
567*2881Smp153739 { gettext("nst"), tZONE, -HOUR(6.5) },/* North Sumatra */
568*2881Smp153739 { gettext("sst"), tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */
5690Sstevel@tonic-gate #endif /* 0 */
5700Sstevel@tonic-gate { gettext("wast"), tZONE, -HOUR(7) }, /* West Australian Standard */
5710Sstevel@tonic-gate { gettext("wadt"), tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
5720Sstevel@tonic-gate #if 0
5730Sstevel@tonic-gate { gettext("jt"), tZONE, -HOUR(7.5) },/* Java (3pm in Cronusland!) */
5740Sstevel@tonic-gate #endif
5750Sstevel@tonic-gate { gettext("cct"), tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
5760Sstevel@tonic-gate { gettext("jst"), tZONE, -HOUR(9) }, /* Japan Standard, USSR Zone 8 */
5770Sstevel@tonic-gate { gettext("kst"), tZONE, -HOUR(9) }, /* Korean Standard */
5780Sstevel@tonic-gate #if 0
5790Sstevel@tonic-gate { gettext("cast"), tZONE, -HOUR(9.5) },/* Central Australian Standard */
5800Sstevel@tonic-gate { gettext("cadt"), tDAYZONE, -HOUR(9.5) },/* Central Australian Daylight */
5810Sstevel@tonic-gate #endif
5820Sstevel@tonic-gate { gettext("east"), tZONE, -HOUR(10) }, /* Eastern Australian Standard */
5830Sstevel@tonic-gate { gettext("eadt"), tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
5840Sstevel@tonic-gate { gettext("gst"), tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
5850Sstevel@tonic-gate { gettext("kdt"), tZONE, -HOUR(10) }, /* Korean Daylight */
5860Sstevel@tonic-gate { gettext("nzt"), tZONE, -HOUR(12) }, /* New Zealand */
5870Sstevel@tonic-gate { gettext("nzst"), tZONE, -HOUR(12) }, /* New Zealand Standard */
5880Sstevel@tonic-gate { gettext("nzdt"), tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
5890Sstevel@tonic-gate { gettext("idle"), tZONE, -HOUR(12) }, /* International Date Line East */
5900Sstevel@tonic-gate { NULL }
5910Sstevel@tonic-gate };
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate /* ARGSUSED */
5940Sstevel@tonic-gate static int
yyerror(s)5950Sstevel@tonic-gate yyerror(s)
596*2881Smp153739 char *s;
5970Sstevel@tonic-gate {
598*2881Smp153739 return 0;
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate
6020Sstevel@tonic-gate static time_t
ToSeconds(Hours,Minutes,Seconds,Meridian)603*2881Smp153739 ToSeconds(Hours, Minutes, Seconds, Meridian)
604*2881Smp153739 time_t Hours;
605*2881Smp153739 time_t Minutes;
606*2881Smp153739 time_t Seconds;
607*2881Smp153739 MERIDIAN Meridian;
6080Sstevel@tonic-gate {
609*2881Smp153739 if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
610*2881Smp153739 return -1;
611*2881Smp153739 switch (Meridian) {
612*2881Smp153739 case MER24:
613*2881Smp153739 if (Hours < 0 || Hours > 23)
614*2881Smp153739 return -1;
615*2881Smp153739 return (Hours * 60L + Minutes) * 60L + Seconds;
616*2881Smp153739 case MERam:
617*2881Smp153739 if (Hours < 1 || Hours > 12)
618*2881Smp153739 return -1;
619*2881Smp153739 return (Hours * 60L + Minutes) * 60L + Seconds;
620*2881Smp153739 case MERpm:
621*2881Smp153739 if (Hours < 1 || Hours > 12)
622*2881Smp153739 return -1;
623*2881Smp153739 return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
624*2881Smp153739 default:
625*2881Smp153739 abort ();
626*2881Smp153739 }
627*2881Smp153739 /* NOTREACHED */
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate /*
6310Sstevel@tonic-gate * From hh:mm:ss [am|pm] mm/dd/yy [tz], compute and return the number
6320Sstevel@tonic-gate * of seconds since 00:00:00 1/1/70 GMT.
6330Sstevel@tonic-gate */
6340Sstevel@tonic-gate static time_t
Convert(Month,Day,Year,Hours,Minutes,Seconds,Meridian,DSTmode)635*2881Smp153739 Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
636*2881Smp153739 time_t Month;
637*2881Smp153739 time_t Day;
638*2881Smp153739 time_t Year;
639*2881Smp153739 time_t Hours;
640*2881Smp153739 time_t Minutes;
641*2881Smp153739 time_t Seconds;
642*2881Smp153739 MERIDIAN Meridian;
643*2881Smp153739 DSTMODE DSTmode;
6440Sstevel@tonic-gate {
645*2881Smp153739 static int DaysInMonth[12] = {
646*2881Smp153739 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
647*2881Smp153739 };
648*2881Smp153739 time_t tod;
649*2881Smp153739 time_t Julian;
650*2881Smp153739 int i;
6510Sstevel@tonic-gate
652*2881Smp153739 if (Year < 0)
653*2881Smp153739 Year = -Year;
654*2881Smp153739 if (Year < 1900)
655*2881Smp153739 Year += 1900;
656*2881Smp153739 DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
657*2881Smp153739 ? 29 : 28;
658*2881Smp153739 if (Year < EPOCH
659*2881Smp153739 || Year > EPOCH_END
660*2881Smp153739 || Month < 1 || Month > 12
661*2881Smp153739 /* Lint fluff: "conversion from long may lose accuracy" */
662*2881Smp153739 || Day < 1 || Day > DaysInMonth[(int)--Month])
663*2881Smp153739 return -1;
6640Sstevel@tonic-gate
665*2881Smp153739 for (Julian = Day - 1, i = 0; i < Month; i++)
666*2881Smp153739 Julian += DaysInMonth[i];
667*2881Smp153739 for (i = EPOCH; i < Year; i++)
668*2881Smp153739 Julian += 365 + ((i % 4 == 0) && ((Year % 100 != 0) ||
669*2881Smp153739 (Year % 400 == 0)));
670*2881Smp153739 Julian *= SECSPERDAY;
671*2881Smp153739 Julian += yyTimezone * 60L;
672*2881Smp153739 if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
673*2881Smp153739 return -1;
674*2881Smp153739 Julian += tod;
675*2881Smp153739 if (DSTmode == DSTon
676*2881Smp153739 || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
677*2881Smp153739 Julian -= 60 * 60;
678*2881Smp153739 return Julian;
6790Sstevel@tonic-gate }
6800Sstevel@tonic-gate
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate static time_t
DSTcorrect(Start,Future)6830Sstevel@tonic-gate DSTcorrect(Start, Future)
684*2881Smp153739 time_t Start;
685*2881Smp153739 time_t Future;
6860Sstevel@tonic-gate {
687*2881Smp153739 time_t StartDay;
688*2881Smp153739 time_t FutureDay;
6890Sstevel@tonic-gate
690*2881Smp153739 StartDay = (localtime(&Start)->tm_hour + 1) % 24;
691*2881Smp153739 FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
692*2881Smp153739 return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
6930Sstevel@tonic-gate }
6940Sstevel@tonic-gate
6950Sstevel@tonic-gate
6960Sstevel@tonic-gate static time_t
RelativeDate(Start,DayOrdinal,DayNumber)6970Sstevel@tonic-gate RelativeDate(Start, DayOrdinal, DayNumber)
698*2881Smp153739 time_t Start;
699*2881Smp153739 time_t DayOrdinal;
700*2881Smp153739 time_t DayNumber;
7010Sstevel@tonic-gate {
702*2881Smp153739 struct tm *tm;
703*2881Smp153739 time_t now;
7040Sstevel@tonic-gate
705*2881Smp153739 now = Start;
706*2881Smp153739 tm = localtime(&now);
707*2881Smp153739 now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
708*2881Smp153739 now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
709*2881Smp153739 return DSTcorrect(Start, now);
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate
7120Sstevel@tonic-gate
7130Sstevel@tonic-gate static time_t
RelativeMonth(Start,RelMonth)714*2881Smp153739 RelativeMonth(Start, RelMonth)
715*2881Smp153739 time_t Start;
716*2881Smp153739 time_t RelMonth;
7170Sstevel@tonic-gate {
718*2881Smp153739 struct tm *tm;
719*2881Smp153739 time_t Month;
720*2881Smp153739 time_t Year;
721*2881Smp153739 time_t ret;
7220Sstevel@tonic-gate
723*2881Smp153739 if (RelMonth == 0)
724*2881Smp153739 return 0;
725*2881Smp153739 tm = localtime(&Start);
726*2881Smp153739 Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
727*2881Smp153739 Year = Month / 12;
728*2881Smp153739 Month = Month % 12 + 1;
7290Sstevel@tonic-gate ret = Convert(Month, (time_t)tm->tm_mday, Year,
730*2881Smp153739 (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
731*2881Smp153739 MER24, DSTmaybe);
7320Sstevel@tonic-gate if (ret == -1)
733*2881Smp153739 return ret;
7340Sstevel@tonic-gate return DSTcorrect(Start, ret);
7350Sstevel@tonic-gate }
7360Sstevel@tonic-gate
7370Sstevel@tonic-gate
7380Sstevel@tonic-gate static int
LookupWord(buff)739*2881Smp153739 LookupWord(buff)
740*2881Smp153739 char *buff;
7410Sstevel@tonic-gate {
742*2881Smp153739 register char *p;
743*2881Smp153739 register char *q;
744*2881Smp153739 register const TABLE *tp;
745*2881Smp153739 int i;
746*2881Smp153739 int abbrev;
747*2881Smp153739
748*2881Smp153739 /* Make it lowercase. */
749*2881Smp153739 for (p = buff; *p; p++)
750*2881Smp153739 if (isupper((int) *p))
751*2881Smp153739 *p = tolower((int) *p);
7520Sstevel@tonic-gate
753*2881Smp153739 if (strcmp(buff, gettext("am")) == 0 || strcmp(buff, gettext("a.m.")) == 0) {
754*2881Smp153739 yylval.Meridian = MERam;
755*2881Smp153739 return tMERIDIAN;
756*2881Smp153739 }
757*2881Smp153739 if (strcmp(buff, gettext("pm")) == 0 ||
758*2881Smp153739 strcmp(buff, gettext("p.m.")) == 0) {
759*2881Smp153739 yylval.Meridian = MERpm;
760*2881Smp153739 return tMERIDIAN;
761*2881Smp153739 }
7620Sstevel@tonic-gate
763*2881Smp153739 /* See if we have an abbreviation for a month. */
764*2881Smp153739 if (strlen(buff) == 3)
765*2881Smp153739 abbrev = 1;
766*2881Smp153739 else if (strlen(buff) == 4 && buff[3] == '.') {
767*2881Smp153739 abbrev = 1;
768*2881Smp153739 buff[3] = '\0';
769*2881Smp153739 }
770*2881Smp153739 else
771*2881Smp153739 abbrev = 0;
772*2881Smp153739
773*2881Smp153739 for (tp = MonthDayTable; tp->name; tp++) {
774*2881Smp153739 if (abbrev) {
775*2881Smp153739 if (strncmp(buff, GETTEXT(tp->name), 3) == 0) {
776*2881Smp153739 yylval.Number = tp->value;
777*2881Smp153739 return tp->type;
778*2881Smp153739 }
7790Sstevel@tonic-gate }
780*2881Smp153739 else if (strcmp(buff, GETTEXT(tp->name)) == 0) {
781*2881Smp153739 yylval.Number = tp->value;
782*2881Smp153739 return tp->type;
7830Sstevel@tonic-gate }
784*2881Smp153739 }
7850Sstevel@tonic-gate
786*2881Smp153739 for (tp = TimezoneTable; tp->name; tp++)
787*2881Smp153739 if (strcmp(buff, GETTEXT(tp->name)) == 0) {
788*2881Smp153739 yylval.Number = tp->value;
789*2881Smp153739 return tp->type;
7900Sstevel@tonic-gate }
7910Sstevel@tonic-gate
792*2881Smp153739 if (strcmp(buff, gettext("dst")) == 0)
793*2881Smp153739 return tDST;
7940Sstevel@tonic-gate
795*2881Smp153739 for (tp = UnitsTable; tp->name; tp++)
796*2881Smp153739 if (strcmp(buff, GETTEXT(tp->name)) == 0) {
797*2881Smp153739 yylval.Number = tp->value;
798*2881Smp153739 return tp->type;
799*2881Smp153739 }
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate /* Strip off any plural and try the units table again. */
802*2881Smp153739 i = strlen(buff) - 1;
803*2881Smp153739 if (buff[i] == 's') {
804*2881Smp153739 buff[i] = '\0';
805*2881Smp153739 for (tp = UnitsTable; tp->name; tp++)
806*2881Smp153739 if (strcmp(buff, GETTEXT(tp->name)) == 0) {
807*2881Smp153739 yylval.Number = tp->value;
808*2881Smp153739 return tp->type;
809*2881Smp153739 }
810*2881Smp153739 buff[i] = 's'; /* Put back for "this" in OtherTable. */
811*2881Smp153739 }
812*2881Smp153739
813*2881Smp153739 for (tp = OtherTable; tp->name; tp++)
814*2881Smp153739 if (strcmp(buff, GETTEXT(tp->name)) == 0) {
815*2881Smp153739 yylval.Number = tp->value;
816*2881Smp153739 return tp->type;
8170Sstevel@tonic-gate }
8180Sstevel@tonic-gate
819*2881Smp153739 /* Drop out any periods and try the timezone table again. */
820*2881Smp153739 for (i = 0, p = q = buff; *q; q++)
821*2881Smp153739 if (*q != '.')
822*2881Smp153739 *p++ = *q;
823*2881Smp153739 else
824*2881Smp153739 i++;
825*2881Smp153739 *p = '\0';
826*2881Smp153739 if (i)
827*2881Smp153739 for (tp = TimezoneTable; tp->name; tp++)
828*2881Smp153739 if (strcmp(buff, GETTEXT(tp->name)) == 0) {
829*2881Smp153739 yylval.Number = tp->value;
830*2881Smp153739 return tp->type;
831*2881Smp153739 }
8320Sstevel@tonic-gate
833*2881Smp153739 return tID;
8340Sstevel@tonic-gate }
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate
8370Sstevel@tonic-gate static int
yylex()8380Sstevel@tonic-gate yylex()
8390Sstevel@tonic-gate {
840*2881Smp153739 register char c;
841*2881Smp153739 register char *p;
842*2881Smp153739 char buff[20];
843*2881Smp153739 int Count;
844*2881Smp153739 int sign;
8450Sstevel@tonic-gate
846*2881Smp153739 for ( ; ; ) {
847*2881Smp153739 while (isspace((int) *yyInput))
848*2881Smp153739 yyInput++;
8490Sstevel@tonic-gate
850*2881Smp153739 c = *yyInput;
851*2881Smp153739 if (isdigit((int) c) || c == '-' || c == '+') {
852*2881Smp153739 if (c == '-' || c == '+') {
853*2881Smp153739 sign = c == '-' ? -1 : 1;
854*2881Smp153739 if (!isdigit((int) (*++yyInput)))
855*2881Smp153739 /* skip the '-' sign */
856*2881Smp153739 continue;
857*2881Smp153739 }
858*2881Smp153739 else
859*2881Smp153739 sign = 0;
860*2881Smp153739 for (yylval.Number = 0; isdigit((int) (c = *yyInput++)); )
861*2881Smp153739 yylval.Number = 10 * yylval.Number + c - '0';
862*2881Smp153739 yyInput--;
863*2881Smp153739 if (sign < 0)
864*2881Smp153739 yylval.Number = -yylval.Number;
865*2881Smp153739 return sign ? tSNUMBER : tUNUMBER;
8660Sstevel@tonic-gate }
867*2881Smp153739 if (isalpha((int) c)) {
868*2881Smp153739 for (p = buff; isalpha((int) (c = *yyInput++)) || c == '.'; )
869*2881Smp153739 if (p < &buff[sizeof buff - 1])
870*2881Smp153739 *p++ = c;
871*2881Smp153739 *p = '\0';
872*2881Smp153739 yyInput--;
873*2881Smp153739 return LookupWord(buff);
874*2881Smp153739 }
875*2881Smp153739 if (c != '(')
876*2881Smp153739 return *yyInput++;
877*2881Smp153739 Count = 0;
878*2881Smp153739 do {
879*2881Smp153739 c = *yyInput++;
880*2881Smp153739 if (c == '\0')
881*2881Smp153739 return c;
882*2881Smp153739 if (c == '(')
883*2881Smp153739 Count++;
884*2881Smp153739 else if (c == ')')
885*2881Smp153739 Count--;
886*2881Smp153739 } while (Count > 0);
887*2881Smp153739 }
8880Sstevel@tonic-gate }
8890Sstevel@tonic-gate
8900Sstevel@tonic-gate
891*2881Smp153739 #define TM_YEAR_ORIGIN 1900
8920Sstevel@tonic-gate
8930Sstevel@tonic-gate /* Yield A - B, measured in seconds. */
8940Sstevel@tonic-gate static time_t
difftm(a,b)895*2881Smp153739 difftm(a, b)
896*2881Smp153739 struct tm *a, *b;
8970Sstevel@tonic-gate {
898*2881Smp153739 int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
899*2881Smp153739 int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
900*2881Smp153739 return
901*2881Smp153739 (
902*2881Smp153739 (
903*2881Smp153739 (
904*2881Smp153739 /* difference in day of year */
905*2881Smp153739 a->tm_yday - b->tm_yday
906*2881Smp153739 /* + intervening leap days */
907*2881Smp153739 + ((ay >> 2) - (by >> 2))
908*2881Smp153739 - (ay/100 - by/100)
909*2881Smp153739 + ((ay/100 >> 2) - (by/100 >> 2))
910*2881Smp153739 /* + difference in years * 365 */
911*2881Smp153739 + (time_t)(ay-by) * 365
912*2881Smp153739 )*24 + (a->tm_hour - b->tm_hour)
913*2881Smp153739 )*60 + (a->tm_min - b->tm_min)
914*2881Smp153739 )*60 + (a->tm_sec - b->tm_sec);
9150Sstevel@tonic-gate }
9160Sstevel@tonic-gate
917*2881Smp153739 /* For get_date extern declaration compatibility check... yuck. */
918*2881Smp153739 #include <krb5.h>
919*2881Smp153739 #include "kadmin.h"
920*2881Smp153739
9210Sstevel@tonic-gate time_t
get_date(p)922*2881Smp153739 get_date(p)
923*2881Smp153739 char *p;
9240Sstevel@tonic-gate {
925*2881Smp153739 struct my_timeb *now = NULL;
926*2881Smp153739 struct tm *tm, gmt;
927*2881Smp153739 struct my_timeb ftz;
928*2881Smp153739 time_t Start;
929*2881Smp153739 time_t tod;
9300Sstevel@tonic-gate time_t delta;
9310Sstevel@tonic-gate
932*2881Smp153739 yyInput = p;
933*2881Smp153739 if (now == NULL) {
934*2881Smp153739 now = &ftz;
9350Sstevel@tonic-gate
936*2881Smp153739 ftz.time = time((time_t *) 0);
9370Sstevel@tonic-gate
938*2881Smp153739 if (! (tm = gmtime (&ftz.time)))
939*2881Smp153739 return -1;
940*2881Smp153739 gmt = *tm; /* Make a copy, in case localtime modifies *tm. */
941*2881Smp153739 ftz.timezone = difftm (&gmt, localtime (&ftz.time)) / 60;
942*2881Smp153739 }
9430Sstevel@tonic-gate
944*2881Smp153739 tm = localtime(&now->time);
945*2881Smp153739 yyYear = tm->tm_year;
946*2881Smp153739 yyMonth = tm->tm_mon + 1;
947*2881Smp153739 yyDay = tm->tm_mday;
948*2881Smp153739 yyTimezone = now->timezone;
949*2881Smp153739 yyDSTmode = DSTmaybe;
950*2881Smp153739 yyHour = 0;
951*2881Smp153739 yyMinutes = 0;
952*2881Smp153739 yySeconds = 0;
953*2881Smp153739 yyMeridian = MER24;
954*2881Smp153739 yyRelSeconds = 0;
955*2881Smp153739 yyRelMonth = 0;
956*2881Smp153739 yyHaveDate = 0;
957*2881Smp153739 yyHaveDay = 0;
958*2881Smp153739 yyHaveRel = 0;
959*2881Smp153739 yyHaveTime = 0;
960*2881Smp153739 yyHaveZone = 0;
9610Sstevel@tonic-gate
962*2881Smp153739 /*
963*2881Smp153739 * When yyparse returns, zero or more of yyHave{Time,Zone,Date,Day,Rel}
964*2881Smp153739 * will have been incremented. The value is number of items of
965*2881Smp153739 * that type that were found; for all but Rel, more than one is
966*2881Smp153739 * illegal.
967*2881Smp153739 *
968*2881Smp153739 * For each yyHave indicator, the following values are set:
969*2881Smp153739 *
970*2881Smp153739 * yyHaveTime:
971*2881Smp153739 * yyHour, yyMinutes, yySeconds: hh:mm:ss specified, initialized
972*2881Smp153739 * to zeros above
973*2881Smp153739 * yyMeridian: MERam, MERpm, or MER24
974*2881Smp153739 * yyTimeZone: time zone specified in minutes
975*2881Smp153739 * yyDSTmode: DSToff if yyTimeZone is set, otherwise unchanged
976*2881Smp153739 * (initialized above to DSTmaybe)
977*2881Smp153739 *
978*2881Smp153739 * yyHaveZone:
979*2881Smp153739 * yyTimezone: as above
980*2881Smp153739 * yyDSTmode: DSToff if a non-DST zone is specified, otherwise DSTon
981*2881Smp153739 * XXX don't understand interaction with yyHaveTime zone info
982*2881Smp153739 *
983*2881Smp153739 * yyHaveDay:
984*2881Smp153739 * yyDayNumber: 0-6 for Sunday-Saturday
985*2881Smp153739 * yyDayOrdinal: val specified with day ("second monday",
986*2881Smp153739 * Ordinal=2), otherwise 1
987*2881Smp153739 *
988*2881Smp153739 * yyHaveDate:
989*2881Smp153739 * yyMonth, yyDay, yyYear: mm/dd/yy specified, initialized to
990*2881Smp153739 * today above
991*2881Smp153739 *
992*2881Smp153739 * yyHaveRel:
993*2881Smp153739 * yyRelSeconds: seconds specified with MINUTE_UNITs ("3 hours") or
994*2881Smp153739 * SEC_UNITs ("30 seconds")
995*2881Smp153739 * yyRelMonth: months specified with MONTH_UNITs ("3 months", "1
996*2881Smp153739 * year")
997*2881Smp153739 *
998*2881Smp153739 * The code following yyparse turns these values into a single
999*2881Smp153739 * date stamp.
1000*2881Smp153739 */
1001*2881Smp153739 if (yyparse()
1002*2881Smp153739 || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
1003*2881Smp153739 return -1;
10040Sstevel@tonic-gate
1005*2881Smp153739 /*
1006*2881Smp153739 * If an absolute time specified, set Start to the equivalent Unix
1007*2881Smp153739 * timestamp. Otherwise, set Start to now, and if we do not have
1008*2881Smp153739 * a relatime time (ie: only yyHaveZone), decrement Start to the
1009*2881Smp153739 * beginning of today.
1010*2881Smp153739 *
1011*2881Smp153739 * By having yyHaveDay in the "absolute" list, "next Monday" means
1012*2881Smp153739 * midnight next Monday. Otherwise, "next Monday" would mean the
1013*2881Smp153739 * time right now, next Monday. It's not clear to me why the
1014*2881Smp153739 * current behavior is preferred.
1015*2881Smp153739 */
1016*2881Smp153739 if (yyHaveDate || yyHaveTime || yyHaveDay) {
1017*2881Smp153739 Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
1018*2881Smp153739 yyMeridian, yyDSTmode);
1019*2881Smp153739 if (Start < 0)
1020*2881Smp153739 return -1;
1021*2881Smp153739 }
1022*2881Smp153739 else {
1023*2881Smp153739 Start = now->time;
1024*2881Smp153739 if (!yyHaveRel)
1025*2881Smp153739 Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
1026*2881Smp153739 }
10270Sstevel@tonic-gate
1028*2881Smp153739 /*
1029*2881Smp153739 * Add in the relative time specified. RelativeMonth adds in the
1030*2881Smp153739 * months, accounting for the fact that the actual length of "3
1031*2881Smp153739 * months" depends on where you start counting.
1032*2881Smp153739 *
1033*2881Smp153739 * XXX By having this separate from the previous block, we are
1034*2881Smp153739 * allowing dates like "10:00am 3 months", which means 3 months
1035*2881Smp153739 * from 10:00am today, or even "1/1/99 two days" which means two
1036*2881Smp153739 * days after 1/1/99.
1037*2881Smp153739 *
1038*2881Smp153739 * XXX Shouldn't this only be done if yyHaveRel, just for
1039*2881Smp153739 * thoroughness?
1040*2881Smp153739 */
1041*2881Smp153739 Start += yyRelSeconds;
10420Sstevel@tonic-gate delta = RelativeMonth(Start, yyRelMonth);
10430Sstevel@tonic-gate if (delta == (time_t) -1)
1044*2881Smp153739 return -1;
10450Sstevel@tonic-gate Start += delta;
10460Sstevel@tonic-gate
1047*2881Smp153739 /*
1048*2881Smp153739 * Now, if you specified a day of week and counter, add it in. By
1049*2881Smp153739 * disallowing Date but allowing Time, you can say "5pm next
1050*2881Smp153739 * monday".
1051*2881Smp153739 *
1052*2881Smp153739 * XXX The yyHaveDay && !yyHaveDate restriction should be enforced
1053*2881Smp153739 * above and be able to cause failure.
1054*2881Smp153739 */
1055*2881Smp153739 if (yyHaveDay && !yyHaveDate) {
1056*2881Smp153739 tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
1057*2881Smp153739 Start += tod;
1058*2881Smp153739 }
10590Sstevel@tonic-gate
1060*2881Smp153739 /* Have to do *something* with a legitimate -1 so it's distinguishable
1061*2881Smp153739 * from the error return value. (Alternately could set errno on error.) */
1062*2881Smp153739 return Start == -1 ? 0 : Start;
10630Sstevel@tonic-gate }
10640Sstevel@tonic-gate
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate #if defined(TEST)
10670Sstevel@tonic-gate
10680Sstevel@tonic-gate /* ARGSUSED */
main(ac,av)1069*2881Smp153739 main(ac, av)
1070*2881Smp153739 int ac;
1071*2881Smp153739 char *av[];
10720Sstevel@tonic-gate {
1073*2881Smp153739 char buff[128];
1074*2881Smp153739 time_t d;
10750Sstevel@tonic-gate
1076*2881Smp153739 (void)printf(gettext("Enter date, or blank line to exit.\n\t> "));
1077*2881Smp153739 (void)fflush(stdout);
1078*2881Smp153739 while (gets(buff) && buff[0]) {
1079*2881Smp153739 d = get_date(buff, (struct my_timeb *)NULL);
1080*2881Smp153739 if (d == -1)
1081*2881Smp153739 (void)printf(
1082*2881Smp153739 gettext("Bad format - couldn't convert.\n"));
1083*2881Smp153739 else
1084*2881Smp153739 (void)printf("%s", ctime(&d));
1085*2881Smp153739 (void)printf("\t> ");
10860Sstevel@tonic-gate (void)fflush(stdout);
1087*2881Smp153739 }
1088*2881Smp153739 exit(0);
1089*2881Smp153739 /* NOTREACHED */
10900Sstevel@tonic-gate }
10910Sstevel@tonic-gate #endif /* defined(TEST) */
1092