home *** CD-ROM | disk | FTP | other *** search
/ pc.louisiana.edu/pub/unix/ / Louisiana_UNIX.tar / Louisiana_UNIX / date+.zoo / getdate.y < prev    next >
Text File  |  1991-10-15  |  13KB  |  580 lines

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