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