/*
* tclDate.c --
*
* This file is generated from a yacc grammar defined in
* the file tclGetDate.y. It should not be edited directly.
*
* Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* @(#) tclDate.c 1.29 97/01/30 10:50:33
*/
#include "tclInt.h"
#include "tclPort.h"
#ifdef MAC_TCL
#else
#endif
/*
* The offset of tm_year of struct tm returned by localtime, gmtime, etc.
* I don't know how universal this is; K&R II, the NetBSD manpages, and
* ../compat/strftime.c all agree that tm_year is the year-1900. However,
* some systems may have a different value. This #define should be the
* same as in ../compat/strftime.c.
*/
/*
* An entry in the lexical lookup table.
*/
typedef struct _TABLE {
char *name;
int type;
} TABLE;
/*
* Daylight-savings mode: on, off, or not yet known.
*/
typedef enum _DSTMODE {
} DSTMODE;
/*
* Meridian: am, pm, or 24-hour style.
*/
typedef enum _MERIDIAN {
} MERIDIAN;
/*
* Global variables. We could get rid of most of these by using a good
* union as the yacc stack. (This routine was originally written before
* yacc had the %union construct.) Maybe someday; right now we only use
* the %union very rarely.
*/
static char *TclDateInput;
static int TclDateHaveDate;
static int TclDateHaveDay;
static int TclDateHaveRel;
static int TclDateHaveTime;
static int TclDateHaveZone;
/*
* Prototypes of internal functions.
*/
static void
TclDateerror _ANSI_ARGS_((char *s));
static time_t
static int
static time_t
static time_t
static int
static int
static int
TclDatelex _ANSI_ARGS_((void));
int
TclDateparse _ANSI_ARGS_((void));
typedef union
#ifdef __cplusplus
#endif
{
} YYSTYPE;
#ifdef __cplusplus
#ifndef TclDateerror
void TclDateerror(const char *);
#endif
#ifndef TclDatelex
#ifdef __EXTERN_C__
extern "C" { int TclDatelex(void); }
#else
int TclDatelex(void);
#endif
#endif
int TclDateparse(void);
#endif
extern int TclDatechar;
extern int TclDateerrflag;
typedef int TclDatetabelem;
#ifndef YYMAXDEPTH
#endif
#if YYMAXDEPTH > 0
#else /* user does initial allocation */
int *TclDates;
#endif
/*
* Month and day table.
*/
{ "sunday", tDAY, 0 },
{ NULL }
};
/*
* Time units table.
*/
{ NULL }
};
/*
* Assorted relative-time words.
*/
{ "today", tMINUTE_UNIT, 0 },
{ "now", tMINUTE_UNIT, 0 },
{ "this", tMINUTE_UNIT, 0 },
#if 0
/* { "second", tUNUMBER, 2 }, */
#endif
{ "epoch", tEPOCH, 0 },
{ NULL }
};
/*
* The timezone table. (Note: This table was modified to not use any floating
* point constants to work around an SGI compiler bug).
*/
#if 0
/* For completeness. BST is also British Summer, and GST is
* also Guam Standard. */
#endif
#if 0
/* For completeness. NST is also Newfoundland Stanard, nad SST is
* also Swedish Summer. */
#endif /* 0 */
/* ADDED BY Marco Nijdam */
/* End ADDED */
{ NULL }
};
/*
* Military timezone table.
*/
{ NULL }
};
/*
* Dump error messages in the bit bucket.
*/
static void
TclDateerror(s)
char *s;
{
}
static time_t
{
return -1;
switch (Meridian) {
case MER24:
return -1;
case MERam:
return -1;
case MERpm:
return -1;
}
return -1; /* Should never be reached */
}
static int
{
31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
int i;
? 29 : 28;
return -1;
Julian += DaysInMonth[i];
} else {
}
Julian *= SECSPERDAY;
return -1;
return 0;
}
static time_t
{
}
static time_t
{
}
static int
{
if (RelMonth == 0) {
*TimePtr = 0;
return 0;
}
return -1;
return 0;
}
static int
char *buff;
{
register char *p;
register char *q;
int i;
int abbrev;
/*
* Make it lowercase.
*/
for (p = buff; *p; p++) {
}
}
return tMERIDIAN;
}
return tMERIDIAN;
}
/*
* See if we have an abbreviation for a month.
*/
abbrev = 1;
abbrev = 1;
} else {
abbrev = 0;
}
if (abbrev) {
}
}
}
}
}
}
}
/*
* Strip off any plural and try the units table again.
*/
if (buff[i] == 's') {
buff[i] = '\0';
}
}
}
}
}
/*
* Military timezones.
*/
}
}
}
/*
* Drop out any periods and try the timezone table again.
*/
for (i = 0, p = q = buff; *q; q++)
if (*q != '.') {
*p++ = *q;
} else {
i++;
}
*p = '\0';
if (i) {
}
}
}
return tID;
}
static int
{
register char c;
register char *p;
int Count;
int sign;
for ( ; ; ) {
while (isspace((unsigned char) (*TclDateInput))) {
TclDateInput++;
}
if (c == '-' || c == '+') {
if (!isdigit(*++TclDateInput)) {
/*
* skip the '-' sign
*/
continue;
}
} else {
sign = 0;
}
}
TclDateInput--;
if (sign < 0) {
}
}
*p++ = c;
}
}
*p = '\0';
TclDateInput--;
return LookupWord(buff);
}
if (c != '(') {
return *TclDateInput++;
}
Count = 0;
do {
c = *TclDateInput++;
if (c == '\0') {
return c;
} else if (c == '(') {
Count++;
} else if (c == ')') {
Count--;
}
} while (Count > 0);
}
}
/*
* Specify zone is of -50000 to force GMT. (This allows BST to work).
*/
int
char *p;
unsigned long now;
long zone;
unsigned long *timePtr;
{
int thisyear;
TclDateInput = p;
if (zone == -50000) {
TclDateTimezone = 0;
} else {
}
TclDateHour = 0;
TclDateMinutes = 0;
TclDateSeconds = 0;
TclDateRelSeconds = 0;
TclDateRelMonth = 0;
TclDateHaveDate = 0;
TclDateHaveDay = 0;
TclDateHaveRel = 0;
TclDateHaveTime = 0;
TclDateHaveZone = 0;
TclDateHaveDay > 1) {
return -1;
}
if (TclDateYear < 0) {
}
/*
* The following line handles years that are specified using
* only two digits. The line of code below implements a policy
* where two digit dates always refer to the hundered years
* after TM_YEAR_BASE - which is all dates in the 1900's.
*/
if (TclDateYear < 100) {
}
return -1;
}
} else {
if (!TclDateHaveRel) {
}
}
return -1;
}
if (TclDateHaveDay && !TclDateHaveDate) {
}
return 0;
}
-1, 1,
0, -1,
-2, 0,
};
14, 11, 23, 28, 17, 12, 19, 18, 16, 9,
10, 13, 42, 21, 46, 45, 44, 48, 41, 37,
36, 35, 32, 29, 34, 33, 31, 43, 39, 38,
30, 15, 8, 7, 6, 5, 4, 3, 2, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 47, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 22, 0, 0, 20, 25, 24, 27,
26, 42, 0, 0, 0, 0, 40 };
-10000000, -258,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000, -45,
-267,-10000000, -244,-10000000, -14, -231, -240,-10000000,-10000000,-10000000,
-10000000, -246,-10000000, -247, -248,-10000000,-10000000,-10000000,-10000000, -15,
-10000000,-10000000,-10000000,-10000000,-10000000, -40, -20,-10000000, -251,-10000000,
-10000000, -252,-10000000, -253,-10000000, -249,-10000000,-10000000,-10000000 };
0, 28, 39, 38, 37, 36, 35, 34, 33, 32,
31 };
0, 2, 2, 3, 3, 3, 3, 3, 3, 4,
4, 4, 4, 4, 5, 5, 5, 7, 7, 7,
6, 6, 6, 6, 6, 6, 6, 8, 8, 10,
10, 10, 10, 10, 10, 10, 10, 10, 9, 1,
1 };
0, 0, 4, 3, 3, 3, 3, 3, 2, 5,
9, 9, 13, 13, 5, 3, 3, 3, 5, 5,
7, 11, 5, 9, 5, 3, 7, 5, 2, 5,
5, 3, 5, 5, 3, 5, 5, 3, 3, 1,
3 };
-10000000, -2, -3, -4, -5, -6, -7, -8, -9, 267,
268, 259, 263, 269, 258, -10, 266, 262, 265, 264,
261, 58, 258, 47, 263, 262, 265, 264, 270, 267,
44, 257, 262, 265, 264, 267, 267, 267, 44, -1,
266, 58, 261, 47, 267, 267, 267, -1, 266 };
1, -2, 2, 3, 4, 5, 6, 7, 8, 38,
15, 16, 0, 25, 17, 28, 0, 31, 34, 37,
9, 0, 19, 0, 24, 29, 33, 36, 14, 22,
18, 27, 30, 32, 35, 39, 20, 26, 0, 10,
11, 0, 40, 0, 23, 39, 21, 12, 13 };
typedef struct
#ifdef __cplusplus
#endif
#ifndef YYDEBUG
#endif
#if YYDEBUG
{
"tAGO", 257,
"tDAY", 258,
"tDAYZONE", 259,
"tID", 260,
"tMERIDIAN", 261,
"tMINUTE_UNIT", 262,
"tMONTH", 263,
"tMONTH_UNIT", 264,
"tSEC_UNIT", 265,
"tSNUMBER", 266,
"tUNUMBER", 267,
"tZONE", 268,
"tEPOCH", 269,
"tDST", 270,
"-unknown-", -1 /* ends search */
};
char * TclDatereds[] =
{
"-no such reduction-",
"spec : /* empty */",
"spec : spec item",
"item : time",
"item : zone",
"item : date",
"item : day",
"item : rel",
"item : number",
"time : tUNUMBER tMERIDIAN",
"time : tUNUMBER ':' tUNUMBER o_merid",
"time : tUNUMBER ':' tUNUMBER tSNUMBER",
"time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
"time : tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER",
"zone : tZONE tDST",
"zone : tZONE",
"zone : tDAYZONE",
"day : tDAY",
"day : tDAY ','",
"day : tUNUMBER tDAY",
"date : tUNUMBER '/' tUNUMBER",
"date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
"date : tMONTH tUNUMBER",
"date : tMONTH tUNUMBER ',' tUNUMBER",
"date : tUNUMBER tMONTH",
"date : tEPOCH",
"date : tUNUMBER tMONTH tUNUMBER",
"rel : relunit tAGO",
"rel : relunit",
"relunit : tUNUMBER tMINUTE_UNIT",
"relunit : tSNUMBER tMINUTE_UNIT",
"relunit : tMINUTE_UNIT",
"relunit : tSNUMBER tSEC_UNIT",
"relunit : tUNUMBER tSEC_UNIT",
"relunit : tSEC_UNIT",
"relunit : tSNUMBER tMONTH_UNIT",
"relunit : tUNUMBER tMONTH_UNIT",
"relunit : tMONTH_UNIT",
"number : tUNUMBER",
"o_merid : /* empty */",
"o_merid : tMERIDIAN",
};
#endif /* YYDEBUG */
/*
* Copyright (c) 1993 by Sun Microsystems, Inc.
*/
/*
** Skeleton parser driver for yacc output
*/
/*
** yacc user known macros and defines
*/
#define YYACCEPT return(0)
{\
{\
TclDateerror( "syntax error - cannot backup" );\
goto TclDateerrlab;\
}\
TclDatechar = newtoken;\
TclDatestate = *TclDateps;\
TclDatelval = newvalue;\
goto TclDatenewstate;\
}
#ifndef YYDEBUG
#endif
/*
** user known globals
*/
/*
** driver internal defines
*/
/*
** global variables used by the parser
*/
#ifdef YYNMBCHARS
/*
** TclDatecvtok - return a token if i is a wchar_t value that exceeds 255.
** If i<255, i itself is the token. If i>255 but the neither
** of the 30th or 31st bit is on, i is already a token.
*/
#if defined(__STDC__) || defined(__cplusplus)
int TclDatecvtok(int i)
#else
int TclDatecvtok(i) int i;
#endif
{
int first = 0;
int mid;
wchar_t j;
if(i&0x60000000){/*Must convert to a token. */
return i;/*Giving up*/
}
if( j==i ){/*Found*/
}else if( j<i ){
}else{
}
}
/*No entry in the table.*/
return i;/* Giving up.*/
}else{/* i is already a token. */
return i;
}
}
#else/*!YYNMBCHARS*/
#endif/*!YYNMBCHARS*/
/*
** TclDateparse - return 0 if worked, 1 if syntax error not recovered from
*/
#if defined(__STDC__) || defined(__cplusplus)
int TclDateparse(void)
#else
int TclDateparse()
#endif
{
#if defined(__cplusplus) || defined(lint)
/*
hacks to please C++ and lint - goto's inside switch should never be
executed; TclDatepvt is set to 0 to avoid "used before set" warning.
*/
static int __yaccpar_lint_hack__ = 0;
switch (__yaccpar_lint_hack__)
{
case 1: goto TclDateerrlab;
case 2: goto TclDatenewstate;
}
TclDatepvt = 0;
#endif
/*
** Initialize externals - TclDateparse may be called more than once
*/
TclDatestate = 0;
TclDatetmp = 0;
TclDatenerrs = 0;
TclDateerrflag = 0;
TclDatechar = -1;
#if YYMAXDEPTH <= 0
if (TclDatemaxdepth <= 0)
{
if ((TclDatemaxdepth = YYEXPAND(0)) <= 0)
{
TclDateerror("yacc initialization error");
}
}
#endif
{
goto TclDatestack; /* moved from 6 lines above to here to please C++ */
/*
** get globals into registers.
** branch to here only if YYBACKUP was called.
*/
goto TclDate_newstate;
/*
** get globals into registers.
** either we just started, or we just finished a reduction
*/
/*
** top of for (;;) loop while no reductions done
*/
/*
** put a state and value onto the stacks
*/
#if YYDEBUG
/*
** if debugging, look up token value in list of value vs.
** name pairs. 0 and negative (-1) are special values.
** Note: linear search is used since time is not a real
** consideration while debugging.
*/
if ( TclDatedebug )
{
register int TclDate_i;
if ( TclDatechar == 0 )
printf( "end-of-file\n" );
else if ( TclDatechar < 0 )
printf( "-none-\n" );
else
{
TclDate_i++ )
{
break;
}
}
}
#endif /* YYDEBUG */
{
/*
** reallocate and recover. Note that pointers
** have to be reset, or bad things will happen
*/
int TclDatenewmax;
#ifdef YYEXPAND
#else
{
if (newTclDates != 0 && newTclDatev != 0)
{
}
else
TclDatenewmax = 0; /* failed */
}
else /* not first time */
{
TclDatenewmax = 0; /* failed */
}
#endif
{
TclDateerror( "yacc stack overflow" );
}
}
*++TclDate_pv = TclDateval;
/*
** we have a new state - find out what to do
*/
goto TclDatedefault; /* simple state */
#if YYDEBUG
/*
** if debugging, need to mark whether new token grabbed
*/
TclDatetmp = TclDatechar < 0;
#endif
TclDatechar = 0; /* reached EOF */
#if YYDEBUG
if ( TclDatedebug && TclDatetmp )
{
register int TclDate_i;
printf( "Received token " );
if ( TclDatechar == 0 )
printf( "end-of-file\n" );
else if ( TclDatechar < 0 )
printf( "-none-\n" );
else
{
TclDate_i++ )
{
break;
}
}
}
#endif /* YYDEBUG */
goto TclDatedefault;
{
TclDatechar = -1;
if ( TclDateerrflag > 0 )
goto TclDate_stack;
}
{
#if YYDEBUG
TclDatetmp = TclDatechar < 0;
#endif
TclDatechar = 0; /* reached EOF */
#if YYDEBUG
if ( TclDatedebug && TclDatetmp )
{
register int TclDate_i;
printf( "Received token " );
if ( TclDatechar == 0 )
printf( "end-of-file\n" );
else if ( TclDatechar < 0 )
printf( "-none-\n" );
else
{
for ( TclDate_i = 0;
TclDate_i++ )
{
== TclDatechar )
{
break;
}
}
}
}
#endif /* YYDEBUG */
/*
** look through exception table
*/
{
while ( ( *TclDatexi != -1 ) ||
{
TclDatexi += 2;
}
while ( ( *(TclDatexi += 2) >= 0 ) &&
( *TclDatexi != TclDatechar ) )
;
}
}
/*
** check for syntax error
*/
if ( TclDate_n == 0 ) /* have an error */
{
/* no worry about speed here! */
switch ( TclDateerrflag )
{
case 0: /* new error */
TclDateerror( "syntax error" );
goto skip_init;
/*
** get globals into registers.
** we have a user generated syntax type error
*/
TclDatenerrs++;
/* FALLTHRU */
case 1:
case 2: /* incompletely recovered error */
/* try again... */
TclDateerrflag = 3;
/*
** find state where "error" is a legal
** shift action
*/
while ( TclDate_ps >= TclDates )
{
/*
** simulate shift of "error"
*/
goto TclDate_stack;
}
/*
** current state has no shift on
** "error", pop stack
*/
#if YYDEBUG
if ( TclDatedebug )
TclDate_ps[-1] );
#endif
TclDate_ps--;
TclDate_pv--;
}
/*
** there is no state on stack with "error" as
** a valid shift. give up.
*/
case 3: /* no shift yet; eat a token */
#if YYDEBUG
/*
** if debugging, look up token in list of
** pairs. 0 and negative shouldn't occur,
** but since timing doesn't matter when
** debugging, it doesn't hurt to leave the
** tests here.
*/
if ( TclDatedebug )
{
register int TclDate_i;
printf( "Error recovery discards " );
if ( TclDatechar == 0 )
printf( "token end-of-file\n" );
else if ( TclDatechar < 0 )
printf( "token -none-\n" );
else
{
for ( TclDate_i = 0;
TclDate_i++ )
{
== TclDatechar )
{
break;
}
}
printf( "token %s\n",
}
}
#endif /* YYDEBUG */
if ( TclDatechar == 0 ) /* reached EOF. quit */
TclDatechar = -1;
goto TclDate_newstate;
}
}/* end if ( TclDate_n == 0 ) */
/*
** reduction by production TclDate_n
** put stack tops, etc. so things right after switch
*/
#if YYDEBUG
/*
** if debugging, print the string that is the user's
** specification of the reduction which is just about
** to be done.
*/
if ( TclDatedebug )
printf( "Reduce by (%d) \"%s\"\n",
#endif
/*
** Look in goto table for next state
** Sorry about using TclDate_state here as temporary
** register variable, but why not, if it works...
** If TclDater2[ TclDate_n ] doesn't have the low order bit
** set, then there is no action to be done for
** this reduction. So, no saving & unsaving of
** registers done. The only difference between the
** code just after the if and the body of the if is
** the goto TclDate_stack in the body. This way the test
** can be made before the choice of what to do is needed.
*/
{
/* length of production doubled with extra bit */
if ( !( TclDate_len & 01 ) )
{
TclDate_len >>= 1;
if ( TclDate_state >= YYLAST ||
{
}
goto TclDate_stack;
}
TclDate_len >>= 1;
if ( TclDate_state >= YYLAST ||
{
}
}
/* save until reenter driver code */
}
/*
** code supplied by user is placed in this switch
*/
switch( TclDatetmp )
{
case 3:{
} break;
case 4:{
} break;
case 5:{
} break;
case 6:{
} break;
case 7:{
} break;
case 9:{
TclDateMinutes = 0;
TclDateSeconds = 0;
} break;
case 10:{
TclDateSeconds = 0;
} break;
case 11:{
} break;
case 12:{
} break;
case 13:{
} break;
case 14:{
} break;
case 15:{
} break;
case 16:{
} break;
case 17:{
TclDateDayOrdinal = 1;
} break;
case 18:{
TclDateDayOrdinal = 1;
} break;
case 19:{
} break;
case 20:{
} break;
case 21:{
} break;
case 22:{
} break;
case 23:{
} break;
case 24:{
} break;
case 25:{
TclDateMonth = 1;
TclDateDay = 1;
TclDateYear = EPOCH;
} break;
case 26:{
} break;
case 27:{
} break;
case 29:{
} break;
case 30:{
} break;
case 31:{
} break;
case 32:{
} break;
case 33:{
} break;
case 34:{
} break;
case 35:{
} break;
case 36:{
} break;
case 37:{
} break;
case 38:{
} else {
TclDateHour = 0;
} else {
}
TclDateSeconds = 0;
}
} break;
case 39:{
} break;
case 40:{
} break;
}
goto TclDatestack; /* reset registers in driver code */
}