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