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: {}