home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 1 / GoldFishApril1994_CD2.img / d4xx / d473 / cnewssrc / cnews_src.lzh / libc / getdate.y < prev    next >
Text File  |  1990-05-30  |  13KB  |  557 lines

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