📄 getdate.y
字号:
%expect 10%{/*** Originally written by Steven M. Bellovin <smb@research.att.com> while** at the University of North Carolina at Chapel Hill. Later tweaked by** a couple of people on Usenet. Completely overhauled by Rich $alz** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;**** Major hack to coerce it into use with the Equivalence Portable** Windows Library.**** This grammar has 10 shift/reduce conflicts.**** This code is in the public domain and has no copyright.*//* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable *//* SUPPRESS 288 on yyerrlab *//* Label unused */#include <time.h>#include <string.h>#include <ctype.h>#ifdef _MSC_VER#pragma warning(disable:4131 4701)#define STDAPICALLTYPE __stdcall#define MSDOS#else#define STDAPICALLTYPE#endifextern int STDAPICALLTYPE PTimeGetChar(void * stream);extern void STDAPICALLTYPE PTimeUngetChar(void * stream, int c);int STDAPICALLTYPE PTimeGetDateOrder();int STDAPICALLTYPE PTimeIsMonthName(const char *, int, int);int STDAPICALLTYPE PTimeIsDayName(const char *, int, int);#define EPOCH 1970#define HOUR(x) ((time_t)(x) * 60)#define SECSPERDAY (24L * 60L * 60L)/*** An entry in the lexical lookup table.*/typedef struct _TABLE { char *name; int type; time_t value;} TABLE;/*** Daylight-savings mode: on, off, or not yet known.*/typedef enum _DSTMODE { DSTon, DSToff, DSTmaybe} DSTMODE;/*** Meridian: am, pm, or 24-hour style.*/typedef enum _MERIDIAN { MERam, MERpm, MER24} 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.*/struct Variables { void *yyInput; DSTMODE yyDSTmode; time_t yyDayOrdinal; time_t yyDayNumber; int yyHaveDate; int yyHaveDay; int yyHaveRel; int yyHaveTime; int yyHaveZone; time_t yyTimezone; time_t yyDay; time_t yyHour; time_t yyMinutes; time_t yyMonth; time_t yySeconds; time_t yyYear; MERIDIAN yyMeridian; time_t yyRelMonth; time_t yyRelSeconds;};#define VARIABLE ((struct Variables*)parseParam)#define YYPURE#define YYLEX_PARAM VARIABLE->yyInput#define YYPARSE_PARAM parseParam#define yyparse PTime_yyparse#define yylex PTime_yylex#define yyerror PTime_yyerrorstatic int yyparse(void *); #ifdef __GNUC__static int yyerror();static int yylex();#endifstatic void SetPossibleDate(struct Variables*, time_t, time_t, time_t);%}%union { time_t Number; enum _MERIDIAN Meridian;}%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT%token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST%type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT%type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE%type <Meridian> tMERIDIAN o_merid%%spec : /* NULL */ | spec item ;item : time { VARIABLE->yyHaveTime++; } | zone { VARIABLE->yyHaveZone++; } | date { VARIABLE->yyHaveDate++; } | day { VARIABLE->yyHaveDay++; } | rel { VARIABLE->yyHaveRel++; } | number ;time : tUNUMBER tMERIDIAN { VARIABLE->yyHour = $1; VARIABLE->yyMinutes = 0; VARIABLE->yySeconds = 0; VARIABLE->yyMeridian = $2; } | tUNUMBER ':' tUNUMBER o_merid { VARIABLE->yyHour = $1; VARIABLE->yyMinutes = $3; VARIABLE->yySeconds = 0; VARIABLE->yyMeridian = $4; } | tUNUMBER ':' tUNUMBER tSNUMBER { VARIABLE->yyHour = $1; VARIABLE->yyMinutes = $3; VARIABLE->yyMeridian = MER24; VARIABLE->yyDSTmode = DSToff; VARIABLE->yyTimezone = - ($4 % 100 + ($4 / 100) * 60); } | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid { VARIABLE->yyHour = $1; VARIABLE->yyMinutes = $3; VARIABLE->yySeconds = $5; VARIABLE->yyMeridian = $6; } | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER { VARIABLE->yyHour = $1; VARIABLE->yyMinutes = $3; VARIABLE->yySeconds = $5; VARIABLE->yyMeridian = MER24; VARIABLE->yyDSTmode = DSToff; VARIABLE->yyTimezone = - ($6 % 100 + ($6 / 100) * 60); } ;zone : tZONE { VARIABLE->yyTimezone = $1; VARIABLE->yyDSTmode = DSToff; } | tDAYZONE { VARIABLE->yyTimezone = $1; VARIABLE->yyDSTmode = DSTon; } | tZONE tDST { VARIABLE->yyTimezone = $1; VARIABLE->yyDSTmode = DSTon; } ;day : tDAY { VARIABLE->yyDayOrdinal = 1; VARIABLE->yyDayNumber = $1; } | tDAY ',' { VARIABLE->yyDayOrdinal = 1; VARIABLE->yyDayNumber = $1; } | tUNUMBER tDAY { VARIABLE->yyDayOrdinal = $1; VARIABLE->yyDayNumber = $2; } ;date : tUNUMBER '/' tUNUMBER { SetPossibleDate(VARIABLE, $1, $3, VARIABLE->yyYear); } | tUNUMBER '/' tUNUMBER '/' tUNUMBER { SetPossibleDate(VARIABLE, $1, $3, $5); } | tUNUMBER tSNUMBER tSNUMBER { /* ISO 8601 format. yyyy-mm-dd. */ if ($1 > 31) { VARIABLE->yyYear = $1; VARIABLE->yyMonth = -$2; VARIABLE->yyDay = -$3; } else SetPossibleDate(VARIABLE, $1, -$2, -$3); } | tUNUMBER tMONTH tSNUMBER { /* e.g. 17-JUN-1992. */ VARIABLE->yyDay = $1; VARIABLE->yyMonth = $2; VARIABLE->yyYear = -$3; } | tMONTH tUNUMBER { VARIABLE->yyMonth = $1; VARIABLE->yyDay = $2; } | tMONTH tUNUMBER ',' tUNUMBER { VARIABLE->yyMonth = $1; VARIABLE->yyDay = $2; VARIABLE->yyYear = $4; } | tUNUMBER tMONTH { VARIABLE->yyMonth = $2; VARIABLE->yyDay = $1; } | tUNUMBER tMONTH tUNUMBER { VARIABLE->yyMonth = $2; VARIABLE->yyDay = $1; VARIABLE->yyYear = $3; } ;rel : relunit tAGO { VARIABLE->yyRelSeconds = -VARIABLE->yyRelSeconds; VARIABLE->yyRelMonth = -VARIABLE->yyRelMonth; } | relunit ;relunit : tUNUMBER tMINUTE_UNIT { VARIABLE->yyRelSeconds += $1 * $2 * 60L; } | tSNUMBER tMINUTE_UNIT { VARIABLE->yyRelSeconds += $1 * $2 * 60L; } | tMINUTE_UNIT { VARIABLE->yyRelSeconds += $1 * 60L; } | tSNUMBER tSEC_UNIT { VARIABLE->yyRelSeconds += $1; } | tUNUMBER tSEC_UNIT { VARIABLE->yyRelSeconds += $1; } | tSEC_UNIT { VARIABLE->yyRelSeconds++; } | tSNUMBER tMONTH_UNIT { VARIABLE->yyRelMonth += $1 * $2; } | tUNUMBER tMONTH_UNIT { VARIABLE->yyRelMonth += $1 * $2; } | tMONTH_UNIT { VARIABLE->yyRelMonth += $1; } ;number : tUNUMBER { if (VARIABLE->yyHaveTime && VARIABLE->yyHaveDate && !VARIABLE->yyHaveRel) VARIABLE->yyYear = $1; else { if($1>10000) { VARIABLE->yyHaveDate++; VARIABLE->yyDay= ($1)%100; VARIABLE->yyMonth= ($1/100)%100; VARIABLE->yyYear = $1/10000; } else { VARIABLE->yyHaveTime++; if ($1 < 100) { VARIABLE->yyHour = $1; VARIABLE->yyMinutes = 0; } else { VARIABLE->yyHour = $1 / 100; VARIABLE->yyMinutes = $1 % 100; } VARIABLE->yySeconds = 0; VARIABLE->yyMeridian = MER24; } } } ;o_merid : /* NULL */ { $$ = MER24; } | tMERIDIAN { $$ = $1; } ;%%/* Month and day table. */static TABLE const MonthDayTable[] = { { "january", tMONTH, 1 }, { "february", tMONTH, 2 }, { "march", tMONTH, 3 }, { "april", tMONTH, 4 }, { "may", tMONTH, 5 }, { "june", tMONTH, 6 }, { "july", tMONTH, 7 }, { "august", tMONTH, 8 }, { "september", tMONTH, 9 }, { "sept", tMONTH, 9 }, { "october", tMONTH, 10 }, { "november", tMONTH, 11 }, { "december", tMONTH, 12 }, { "sunday", tDAY, 0 }, { "monday", tDAY, 1 }, { "tuesday", tDAY, 2 }, { "tues", tDAY, 2 }, { "wednesday", tDAY, 3 }, { "wednes", tDAY, 3 }, { "thursday", tDAY, 4 }, { "thur", tDAY, 4 }, { "thurs", tDAY, 4 }, { "friday", tDAY, 5 }, { "saturday", tDAY, 6 }, { NULL }};/* Time units table. */static TABLE const UnitsTable[] = { { "year", tMONTH_UNIT, 12 }, { "month", tMONTH_UNIT, 1 }, { "fortnight", tMINUTE_UNIT, 14 * 24 * 60 }, { "week", tMINUTE_UNIT, 7 * 24 * 60 }, { "day", tMINUTE_UNIT, 1 * 24 * 60 }, { "hour", tMINUTE_UNIT, 60 }, { "minute", tMINUTE_UNIT, 1 }, { "min", tMINUTE_UNIT, 1 }, { "second", tSEC_UNIT, 1 }, { "sec", tSEC_UNIT, 1 }, { NULL }};/* Assorted relative-time words. */static TABLE const OtherTable[] = { { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 }, { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 }, { "today", tMINUTE_UNIT, 0 }, { "now", tMINUTE_UNIT, 0 }, { "last", tUNUMBER, -1 }, { "this", tMINUTE_UNIT, 0 }, { "next", tUNUMBER, 2 }, { "first", tUNUMBER, 1 },/* { "second", tUNUMBER, 2 }, */ { "third", tUNUMBER, 3 }, { "fourth", tUNUMBER, 4 }, { "fifth", tUNUMBER, 5 }, { "sixth", tUNUMBER, 6 }, { "seventh", tUNUMBER, 7 }, { "eighth", tUNUMBER, 8 }, { "ninth", tUNUMBER, 9 }, { "tenth", tUNUMBER, 10 }, { "eleventh", tUNUMBER, 11 }, { "twelfth", tUNUMBER, 12 }, { "ago", tAGO, 1 }, { NULL }};/* The timezone table. *//* Some of these are commented out because a time_t can't store a float. */static TABLE const TimezoneTable[] = { { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */ { "utc", tZONE, HOUR( 0) }, { "wet", tZONE, HOUR( 0) }, /* Western European */ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */ { "wat", tZONE, HOUR( 1) }, /* West Africa */ { "at", tZONE, HOUR( 2) }, /* Azores */#if 0 /* For completeness. BST is also British Summer, and GST is * also Guam Standard. */ { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */ { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */#endif#if 0 { "nft", tZONE, HOUR(3.5) }, /* Newfoundland */ { "nst", tZONE, HOUR(3.5) }, /* Newfoundland Standard */ { "ndt", tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */#endif { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */ { "cst", tZONE, HOUR( 6) }, /* Central Standard */ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */ { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */ { "cat", tZONE, HOUR(10) }, /* Central Alaska */ { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */ { "nt", tZONE, HOUR(11) }, /* Nome */ { "idlw", tZONE, HOUR(12) }, /* International Date Line West */ { "cet", tZONE, -HOUR(1) }, /* Central European */ { "met", tZONE, -HOUR(1) }, /* Middle European */ { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */ { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */ { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */ { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */ { "fwt", tZONE, -HOUR(1) }, /* French Winter */ { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */ { "eet", tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */ { "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */#if 0 { "it", tZONE, -HOUR(3.5) },/* Iran */#endif { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */ { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */#if 0 { "ist", tZONE, -HOUR(5.5) },/* Indian Standard */#endif { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */#if 0 /* For completeness. NST is also Newfoundland Stanard, and SST is * also Swedish Summer. */ { "nst", tZONE, -HOUR(6.5) },/* North Sumatra */ { "sst", tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */#endif /* 0 */ { "wast", tZONE, -HOUR(7) }, /* West Australian Standard */ { "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */#if 0 { "jt", tZONE, -HOUR(7.5) },/* Java (3pm in Cronusland!) */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -