home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / tcl / tclX6.5c / src / tclXgetdate.y < prev    next >
Encoding:
Text File  |  1992-12-19  |  17.2 KB  |  572 lines

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