|
|
1.1 root 1: %token ID MONTH DAY MERIDIAN NUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
2: %{
3: /* Steven M. Bellovin (unc!smb) */
4: /* Dept. of Computer Science */
5: /* University of North Carolina at Chapel Hill */
6: /* @(#)getdate.y 2.12 4/16/85 */
7:
8: #include <sys/types.h>
9: #ifdef USG
10: struct timeb
11: {
12: time_t time;
13: unsigned short millitm;
14: short timezone;
15: short dstflag;
16: };
17: #else
18: #include <sys/timeb.h>
19: #endif
20: #include <ctype.h>
21:
22: #include "defs.h"
23: #if defined(BSD4_2) || defined (BSD4_1C)
24: #include <sys/time.h>
25: #else sane
26: #include <time.h>
27: #endif sane
28:
29: #define NULL 0
30: #define daysec (24L*60L*60L)
31: static int timeflag, zoneflag, dateflag, dayflag, relflag;
32: static time_t relsec, relmonth;
33: static int hh, mm, ss, merid, daylight;
34: static int dayord, dayreq;
35: static int month, day, year;
36: static int ourzone;
37: #define AM 1
38: #define PM 2
39: #define DAYLIGHT 1
40: #define STANDARD 2
41: #define MAYBE 3
42: %}
43:
44: %%
45: timedate: /* empty */
46: | timedate item;
47:
48: item: tspec =
49: {timeflag++;}
50: | zone =
51: {zoneflag++;}
52: | dtspec =
53: {dateflag++;}
54: | dyspec =
55: {dayflag++;}
56: | rspec =
57: {relflag++;}
58: | nspec;
59:
60: nspec: NUMBER =
61: {if (timeflag && dateflag && !relflag) year = $1;
62: else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
63:
64: tspec: NUMBER MERIDIAN =
65: {hh = $1; mm = 0; ss = 0; merid = $2;}
66: | NUMBER ':' NUMBER =
67: {hh = $1; mm = $3; merid = 24;}
68: | NUMBER ':' NUMBER MERIDIAN =
69: {hh = $1; mm = $3; merid = $4;}
70: | NUMBER ':' NUMBER ':' NUMBER =
71: {hh = $1; mm = $3; ss = $5; merid = 24;}
72: | NUMBER ':' NUMBER ':' NUMBER MERIDIAN =
73: {hh = $1; mm = $3; ss = $5; merid = $6;};
74:
75: zone: ZONE =
76: {ourzone = $1; daylight = STANDARD;}
77: | DAYZONE =
78: {ourzone = $1; daylight = DAYLIGHT;};
79:
80: dyspec: DAY =
81: {dayord = 1; dayreq = $1;}
82: | DAY ',' =
83: {dayord = 1; dayreq = $1;}
84: | NUMBER DAY =
85: {dayord = $1; dayreq = $2;};
86:
87: dtspec: NUMBER '/' NUMBER =
88: {month = $1; day = $3;}
89: | NUMBER '/' NUMBER '/' NUMBER =
90: {month = $1; day = $3; year = $5;}
91: | MONTH NUMBER =
92: {month = $1; day = $2;}
93: | MONTH NUMBER ',' NUMBER =
94: {month = $1; day = $2; year = $4;}
95: | NUMBER MONTH =
96: {month = $2; day = $1;}
97: | NUMBER MONTH NUMBER =
98: {month = $2; day = $1; year = $3;};
99:
100:
101: rspec: NUMBER UNIT =
102: {relsec += 60L * $1 * $2;}
103: | NUMBER MUNIT =
104: {relmonth += $1 * $2;}
105: | NUMBER SUNIT =
106: {relsec += $1;}
107: | UNIT =
108: {relsec += 60L * $1;}
109: | MUNIT =
110: {relmonth += $1;}
111: | SUNIT =
112: {relsec++;}
113: | rspec AGO =
114: {relsec = -relsec; relmonth = -relmonth;};
115: %%
116:
117: static int mdays[12] =
118: {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
119: #define epoch 1970
120:
121: extern struct tm *localtime();
122: time_t dateconv(mm, dd, yy, h, m, s, mer, zone, dayflag)
123: int mm, dd, yy, h, m, s, mer, zone, dayflag;
124: {
125: time_t tod, jdate;
126: register int i;
127: time_t timeconv();
128:
129: if (yy < 0) yy = -yy;
130: if (yy < 100) yy += 1900;
131: mdays[1] = 28 + (yy%4 == 0 && (yy%100 != 0 || yy%400 == 0));
132: if (yy < epoch || yy > 1999 || mm < 1 || mm > 12 ||
133: dd < 1 || dd > mdays[--mm]) return (-1);
134: jdate = dd-1;
135: for (i=0; i<mm; i++) jdate += mdays[i];
136: for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
137: jdate *= daysec;
138: jdate += zone * 60L;
139: if ((tod = timeconv(h, m, s, mer)) < 0) return (-1);
140: jdate += tod;
141: if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
142: jdate += -1*60*60;
143: return (jdate);
144: }
145:
146: time_t dayconv(ord, day, now) int ord, day; time_t now;
147: {
148: register struct tm *loctime;
149: time_t tod;
150: time_t daylcorr();
151:
152: tod = now;
153: loctime = localtime(&tod);
154: tod += daysec * ((day - loctime->tm_wday + 7) % 7);
155: tod += 7*daysec*(ord<=0?ord:ord-1);
156: return daylcorr(tod, now);
157: }
158:
159: time_t timeconv(hh, mm, ss, mer) register int hh, mm, ss, mer;
160: {
161: if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (-1);
162: switch (mer) {
163: case AM: if (hh < 1 || hh > 12) return(-1);
164: return (60L * ((hh%12)*60L + mm)+ss);
165: case PM: if (hh < 1 || hh > 12) return(-1);
166: return (60L * ((hh%12 +12)*60L + mm)+ss);
167: case 24: if (hh < 0 || hh > 23) return (-1);
168: return (60L * (hh*60L + mm)+ss);
169: default: return (-1);
170: }
171: }
172: time_t monthadd(sdate, relmonth) time_t sdate, relmonth;
173: {
174: struct tm *ltime;
175: time_t dateconv();
176: time_t daylcorr();
177: int mm, yy;
178:
179: if (relmonth == 0) return 0;
180: ltime = localtime(&sdate);
181: mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
182: yy = mm/12;
183: mm = mm%12 + 1;
184: return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
185: ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
186: }
187:
188: time_t daylcorr(future, now) time_t future, now;
189: {
190: int fdayl, nowdayl;
191:
192: nowdayl = (localtime(&now)->tm_hour+1) % 24;
193: fdayl = (localtime(&future)->tm_hour+1) % 24;
194: return (future-now) + 60L*60L*(nowdayl-fdayl);
195: }
196:
197: static char *lptr;
198:
199: yylex()
200: {
201: extern int yylval;
202: int sign;
203: register char c;
204: register char *p;
205: char idbuf[20];
206: int pcnt;
207:
208: for (;;) {
209: while (isspace(*lptr)) lptr++;
210:
211: if (isdigit(c = *lptr) || c == '-' || c == '+') {
212: if (c== '-' || c == '+') {
213: if (c=='-') sign = -1;
214: else sign = 1;
215: if (!isdigit(*++lptr)) {
216: /* yylval = sign; return (NUMBER); */
217: return yylex(); /* skip the '-' sign */
218: }
219: } else sign = 1;
220: yylval = 0;
221: while (isdigit(c = *lptr++)) yylval = 10*yylval + c - '0';
222: yylval *= sign;
223: lptr--;
224: return (NUMBER);
225:
226: } else if (isalpha(c)) {
227: p = idbuf;
228: while (isalpha(c = *lptr++) || c=='.')
229: *p++ = c;
230: *p = '\0';
231: lptr--;
232: return (lookup(idbuf));
233: }
234:
235: else if (c == '(') {
236: pcnt = 0;
237: do {
238: c = *lptr++;
239: if (c == '\0') return(c);
240: else if (c == '(') pcnt++;
241: else if (c == ')') pcnt--;
242: } while (pcnt > 0);
243: }
244:
245: else return (*lptr++);
246: }
247: }
248:
249: struct table {
250: char *name;
251: int type, value;
252: };
253:
254: struct table mdtab[] = {
255: {"January", MONTH, 1},
256: {"February", MONTH, 2},
257: {"March", MONTH, 3},
258: {"April", MONTH, 4},
259: {"May", MONTH, 5},
260: {"June", MONTH, 6},
261: {"July", MONTH, 7},
262: {"August", MONTH, 8},
263: {"September", MONTH, 9},
264: {"Sept", MONTH, 9},
265: {"October", MONTH, 10},
266: {"November", MONTH, 11},
267: {"December", MONTH, 12},
268:
269: {"Sunday", DAY, 0},
270: {"Monday", DAY, 1},
271: {"Tuesday", DAY, 2},
272: {"Tues", DAY, 2},
273: {"Wednesday", DAY, 3},
274: {"Wednes", DAY, 3},
275: {"Thursday", DAY, 4},
276: {"Thur", DAY, 4},
277: {"Thurs", DAY, 4},
278: {"Friday", DAY, 5},
279: {"Saturday", DAY, 6},
280: {0, 0, 0}};
281:
282: #define HRS *60
283: #define HALFHR 30
284: struct table mztab[] = {
285: {"a.m.", MERIDIAN, AM},
286: {"am", MERIDIAN, AM},
287: {"p.m.", MERIDIAN, PM},
288: {"pm", MERIDIAN, PM},
289: {"nst", ZONE, 3 HRS + HALFHR}, /* Newfoundland */
290: {"n.s.t.", ZONE, 3 HRS + HALFHR},
291: {"ast", ZONE, 4 HRS}, /* Atlantic */
292: {"a.s.t.", ZONE, 4 HRS},
293: {"adt", DAYZONE, 4 HRS},
294: {"a.d.t.", DAYZONE, 4 HRS},
295: {"est", ZONE, 5 HRS}, /* Eastern */
296: {"e.s.t.", ZONE, 5 HRS},
297: {"edt", DAYZONE, 5 HRS},
298: {"e.d.t.", DAYZONE, 5 HRS},
299: {"cst", ZONE, 6 HRS}, /* Central */
300: {"c.s.t.", ZONE, 6 HRS},
301: {"cdt", DAYZONE, 6 HRS},
302: {"c.d.t.", DAYZONE, 6 HRS},
303: {"mst", ZONE, 7 HRS}, /* Mountain */
304: {"m.s.t.", ZONE, 7 HRS},
305: {"mdt", DAYZONE, 7 HRS},
306: {"m.d.t.", DAYZONE, 7 HRS},
307: {"pst", ZONE, 8 HRS}, /* Pacific */
308: {"p.s.t.", ZONE, 8 HRS},
309: {"pdt", DAYZONE, 8 HRS},
310: {"p.d.t.", DAYZONE, 8 HRS},
311: {"yst", ZONE, 9 HRS}, /* Yukon */
312: {"y.s.t.", ZONE, 9 HRS},
313: {"ydt", DAYZONE, 9 HRS},
314: {"y.d.t.", DAYZONE, 9 HRS},
315: {"hst", ZONE, 10 HRS}, /* Hawaii */
316: {"h.s.t.", ZONE, 10 HRS},
317: {"hdt", DAYZONE, 10 HRS},
318: {"h.d.t.", DAYZONE, 10 HRS},
319:
320: {"gmt", ZONE, 0 HRS},
321: {"g.m.t.", ZONE, 0 HRS},
322: {"bst", DAYZONE, 0 HRS}, /* British Summer Time */
323: {"b.s.t.", DAYZONE, 0 HRS},
324: {"eet", ZONE, 0 HRS}, /* European Eastern Time */
325: {"e.e.t.", ZONE, 0 HRS},
326: {"eest", DAYZONE, 0 HRS}, /* European Eastern Summer Time */
327: {"e.e.s.t.", DAYZONE, 0 HRS},
328: {"met", ZONE, -1 HRS}, /* Middle European Time */
329: {"m.e.t.", ZONE, -1 HRS},
330: {"mest", DAYZONE, -1 HRS}, /* Middle European Summer Time */
331: {"m.e.s.t.", DAYZONE, -1 HRS},
332: {"wet", ZONE, -2 HRS }, /* Western European Time */
333: {"w.e.t.", ZONE, -2 HRS },
334: {"west", DAYZONE, -2 HRS}, /* Western European Summer Time */
335: {"w.e.s.t.", DAYZONE, -2 HRS},
336:
337: {"jst", ZONE, -9 HRS}, /* Japan Standard Time */
338: {"j.s.t.", ZONE, -9 HRS}, /* Japan Standard Time */
339: /* No daylight savings time */
340:
341: {"aest", ZONE, -10 HRS}, /* Australian Eastern Time */
342: {"a.e.s.t.", ZONE, -10 HRS},
343: {"aesst", DAYZONE, -10 HRS}, /* Australian Eastern Summer Time */
344: {"a.e.s.s.t.", DAYZONE, -10 HRS},
345: {"acst", ZONE, -(9 HRS + HALFHR)}, /* Australian Central Time */
346: {"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
347: {"acsst", DAYZONE, -(9 HRS + HALFHR)}, /* Australian Central Summer */
348: {"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
349: {"awst", ZONE, -8 HRS}, /* Australian Western Time */
350: {"a.w.s.t.", ZONE, -8 HRS}, /* (no daylight time there, I'm told */
351: {0, 0, 0}};
352:
353: struct table unittb[] = {
354: {"year", MUNIT, 12},
355: {"month", MUNIT, 1},
356: {"fortnight", UNIT, 14*24*60},
357: {"week", UNIT, 7*24*60},
358: {"day", UNIT, 1*24*60},
359: {"hour", UNIT, 60},
360: {"minute", UNIT, 1},
361: {"min", UNIT, 1},
362: {"second", SUNIT, 1},
363: {"sec", SUNIT, 1},
364: {0, 0, 0}};
365:
366: struct table othertb[] = {
367: {"tomorrow", UNIT, 1*24*60},
368: {"yesterday", UNIT, -1*24*60},
369: {"today", UNIT, 0},
370: {"now", UNIT, 0},
371: {"last", NUMBER, -1},
372: {"this", UNIT, 0},
373: {"next", NUMBER, 2},
374: {"first", NUMBER, 1},
375: /* {"second", NUMBER, 2}, */
376: {"third", NUMBER, 3},
377: {"fourth", NUMBER, 4},
378: {"fifth", NUMBER, 5},
379: {"sixth", NUMBER, 6},
380: {"seventh", NUMBER, 7},
381: {"eigth", NUMBER, 8},
382: {"ninth", NUMBER, 9},
383: {"tenth", NUMBER, 10},
384: {"eleventh", NUMBER, 11},
385: {"twelfth", NUMBER, 12},
386: {"ago", AGO, 1},
387: {0, 0, 0}};
388:
389: struct table milzone[] = {
390: {"a", ZONE, 1 HRS},
391: {"b", ZONE, 2 HRS},
392: {"c", ZONE, 3 HRS},
393: {"d", ZONE, 4 HRS},
394: {"e", ZONE, 5 HRS},
395: {"f", ZONE, 6 HRS},
396: {"g", ZONE, 7 HRS},
397: {"h", ZONE, 8 HRS},
398: {"i", ZONE, 9 HRS},
399: {"k", ZONE, 10 HRS},
400: {"l", ZONE, 11 HRS},
401: {"m", ZONE, 12 HRS},
402: {"n", ZONE, -1 HRS},
403: {"o", ZONE, -2 HRS},
404: {"p", ZONE, -3 HRS},
405: {"q", ZONE, -4 HRS},
406: {"r", ZONE, -5 HRS},
407: {"s", ZONE, -6 HRS},
408: {"t", ZONE, -7 HRS},
409: {"u", ZONE, -8 HRS},
410: {"v", ZONE, -9 HRS},
411: {"w", ZONE, -10 HRS},
412: {"x", ZONE, -11 HRS},
413: {"y", ZONE, -12 HRS},
414: {"z", ZONE, 0 HRS},
415: {0, 0, 0}};
416:
417: lookup(id) char *id;
418: {
419: #define gotit (yylval=i->value, i->type)
420: #define getid for(j=idvar, k=id; *j++ = *k++; )
421:
422: char idvar[20];
423: register char *j, *k;
424: register struct table *i;
425: int abbrev;
426:
427: getid;
428: if (strlen(idvar) == 3) abbrev = 1;
429: else if (strlen(idvar) == 4 && idvar[3] == '.') {
430: abbrev = 1;
431: idvar[3] = '\0';
432: }
433: else abbrev = 0;
434:
435: if (islower(*idvar)) *idvar = toupper(*idvar);
436:
437: for (i = mdtab; i->name; i++) {
438: k = idvar;
439: for (j = i->name; *j++ == *k++;) {
440: if (abbrev && j==i->name+3) return gotit;
441: if (j[-1] == 0) return gotit;
442: }
443: }
444:
445: getid;
446: for (i = mztab; i->name; i++)
447: if (strcmp(i->name, idvar) == 0) return gotit;
448:
449: for (j = idvar; *j; j++) if (isupper(*j)) *j = tolower(*j);
450: for (i=mztab; i->name; i++)
451: if (strcmp(i->name, idvar) == 0) return gotit;
452:
453: getid;
454: for (i=unittb; i->name; i++)
455: if (strcmp(i->name, idvar) == 0) return gotit;
456:
457: if (idvar[strlen(idvar)-1] == 's') idvar[strlen(idvar)-1] = '\0';
458: for (i=unittb; i->name; i++)
459: if (strcmp(i->name, idvar) == 0) return gotit;
460:
461: getid;
462: for (i = othertb; i->name; i++)
463: if (strcmp(i->name, idvar) == 0) return gotit;
464:
465: getid;
466: if (strlen(idvar) == 1 && isalpha(*idvar)) {
467: if (isupper(*idvar)) *idvar = tolower(*idvar);
468: for (i = milzone; i->name; i++)
469: if (strcmp(i->name, idvar) == 0) return gotit;
470: }
471:
472: return(ID);
473: }
474:
475: time_t getdate(p, now) char *p; struct timeb *now;
476: {
477: #define mcheck(f) if (f>1) err++
478: time_t monthadd();
479: int err;
480: struct tm *lt;
481: struct timeb ftz;
482:
483: time_t sdate, tod;
484:
485: lptr = p;
486: if (now == ((struct timeb *) NULL)) {
487: now = &ftz;
488: ftime(&ftz);
489: }
490: lt = localtime(&now->time);
491: year = lt->tm_year;
492: month = lt->tm_mon+1;
493: day = lt->tm_mday;
494: relsec = 0; relmonth = 0;
495: timeflag=zoneflag=dateflag=dayflag=relflag=0;
496: ourzone = now->timezone;
497: daylight = MAYBE;
498: hh = mm = ss = 0;
499: merid = 24;
500:
501: if (err = yyparse()) return (-1);
502:
503: mcheck(timeflag);
504: mcheck(zoneflag);
505: mcheck(dateflag);
506: mcheck(dayflag);
507:
508: if (err) return (-1);
509: if (dateflag || timeflag || dayflag) {
510: sdate = dateconv(month,day,year,hh,mm,ss,merid,ourzone,daylight);
511: if (sdate < 0) return -1;
512: }
513: else {
514: sdate = now->time;
515: if (relflag == 0)
516: sdate -= (lt->tm_sec + lt->tm_min*60 +
517: lt->tm_hour*(60L*60L));
518: }
519:
520: sdate += relsec;
521: sdate += monthadd(sdate, relmonth);
522:
523: if (dayflag && !dateflag) {
524: tod = dayconv(dayord, dayreq, sdate);
525: sdate += tod;
526: }
527:
528: return sdate;
529: }
530:
531: yyerror(s) char *s;
532: {}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.