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