home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / dev / misc / hwgrcs / src / rcs.rcsfiles / partime.c,v < prev    next >
Encoding:
Text File  |  1995-06-25  |  19.2 KB  |  773 lines

  1. head    5.6;
  2. branch    5.6.1;
  3. access;
  4. symbols
  5.     HWGRCSP12F:5.6.1.1
  6.     HWGRCSP11F:5.6.1.1
  7.     HWGRCSP10F:5.6.1.1
  8.     HWGRCSP9:5.6.1.1
  9.     HWGRCSP8F:5.6.1.1
  10.     HWGRCSP7F:5.6.1.1
  11.     HWGRCSP6F:5.6.1.1
  12.     HWGRCSP5F:5.6.1.1
  13.     HWGRCSp4:5.6.1.1
  14.     HWGRCSp3:5.6.1
  15.     HWGRCS_Fish:5.6.1
  16.     HWGRCS:5.6.1;
  17. locks; strict;
  18. comment    @ * @;
  19.  
  20.  
  21. 5.6
  22. date    91.08.19.03.13.55;    author eggert;    state Exp;
  23. branches
  24.     5.6.1.1;
  25. next    ;
  26.  
  27. 5.6.1.1
  28. date    93.01.18.14.37.44;    author heinz;    state Exp;
  29. branches;
  30. next    ;
  31.  
  32.  
  33. desc
  34. @Checked in with -k 16.jan.93 HWG
  35. @
  36.  
  37.  
  38. 5.6
  39. log
  40. @checked in with -k by heinz at 1993/01/17 01:53:17
  41. @
  42. text
  43. @/*
  44.  * PARTIME        parse date/time string into a TM structure
  45.  *
  46.  * Returns:
  47.  *    0 if parsing failed
  48.  *    else time values in specified TM structure and zone (unspecified values
  49.  *        set to TMNULL)
  50.  * Notes:
  51.  *    This code is quasi-public; it may be used freely in like software.
  52.  *    It is not to be sold, nor used in licensed software without
  53.  *    permission of the author.
  54.  *    For everyone's benefit, please report bugs and improvements!
  55.  *     Copyright 1980 by Ken Harrenstien, SRI International.
  56.  *    (ARPANET: KLH @@ SRI)
  57.  */
  58.  
  59. /* Hacknotes:
  60.  *    If parsing changed so that no backup needed, could perhaps modify
  61.  *        to use a FILE input stream.  Need terminator, though.
  62.  *    Perhaps should return 0 on success, else a non-zero error val?
  63.  */
  64.  
  65. /* $Log: partime.c,v $
  66.  * Revision 5.6  1991/08/19  03:13:55  eggert
  67.  * Update timezones.
  68.  *
  69.  * Revision 5.5  1991/04/21  11:58:18  eggert
  70.  * Don't put , just before } in initializer.
  71.  *
  72.  * Revision 5.4  1990/10/04  06:30:15  eggert
  73.  * Remove date vs time heuristics that fail between 2000 and 2400.
  74.  * Check for overflow when lexing an integer.
  75.  * Parse 'Jan 10 LT' as 'Jan 10, LT', not 'Jan, 10 LT'.
  76.  *
  77.  * Revision 5.3  1990/09/24  18:56:31  eggert
  78.  * Update timezones.
  79.  *
  80.  * Revision 5.2  1990/09/04  08:02:16  eggert
  81.  * Don't parse two-digit years, because it won't work after 1999/12/31.
  82.  * Don't permit 'Aug Aug'.
  83.  *
  84.  * Revision 5.1  1990/08/29  07:13:49  eggert
  85.  * Be able to parse our own date format.  Don't assume year<10000.
  86.  *
  87.  * Revision 5.0  1990/08/22  08:12:40  eggert
  88.  * Switch to GMT and fix the bugs exposed thereby.  Update timezones.
  89.  * Ansify and Posixate.  Fix peekahead and int-size bugs.
  90.  *
  91.  * Revision 1.4  89/05/01  14:48:46  narten
  92.  * fixed #ifdef DEBUG construct
  93.  * 
  94.  * Revision 1.3  88/08/28  14:53:40  eggert
  95.  * Remove unportable "#endif XXX"s.
  96.  * 
  97.  * Revision 1.2  87/03/27  14:21:53  jenkins
  98.  * Port to suns
  99.  * 
  100.  * Revision 1.1  82/05/06  11:38:26  wft
  101.  * Initial revision
  102.  * 
  103.  */
  104.  
  105. #include "rcsbase.h"
  106.  
  107. libId(partId, "$Id: partime.c,v 5.6 1991/08/19 03:13:55 eggert Exp $")
  108.  
  109. #define given(v) (0 <= (v))
  110. #define TMNULL (-1) /* Items not given are given this value */
  111. #define TZ_OFFSET (24*60) /* TMNULL  <  zone_offset - TZ_OFFSET */
  112.  
  113. struct tmwent {
  114.     char const *went;
  115.     short wval;
  116.     char wflgs;
  117.     char wtype;
  118. };
  119.     /* wflgs */
  120. #define TWTIME 02    /* Word is a time value (absence implies date) */
  121. #define TWDST  04    /* Word is a DST-type timezone */
  122.     /* wtype */
  123. #define TM_MON    1    /* month name */
  124. #define TM_WDAY    2    /* weekday name */
  125. #define TM_ZON    3    /* time zone name */
  126. #define TM_LT    4    /* local time */
  127. #define TM_DST    5    /* daylight savings time */
  128. #define TM_12    6    /* AM, PM, NOON, or MIDNIGHT */
  129.     /* wval (for wtype==TM_12) */
  130. #define T12_AM 1
  131. #define T12_PM 2
  132. #define T12_NOON 12
  133. #define T12_MIDNIGHT 0
  134.  
  135. static struct tmwent const tmwords [] = {
  136.     {"january",      0, 0, TM_MON},
  137.     {"february",     1, 0, TM_MON},
  138.     {"march",        2, 0, TM_MON},
  139.     {"april",        3, 0, TM_MON},
  140.     {"may",          4, 0, TM_MON},
  141.     {"june",         5, 0, TM_MON},
  142.     {"july",         6, 0, TM_MON},
  143.     {"august",       7, 0, TM_MON},
  144.     {"september",    8, 0, TM_MON},
  145.     {"october",      9, 0, TM_MON},
  146.     {"november",     10, 0, TM_MON},
  147.     {"december",     11, 0, TM_MON},
  148.  
  149.     {"sunday",       0, 0, TM_WDAY},
  150.     {"monday",       1, 0, TM_WDAY},
  151.     {"tuesday",      2, 0, TM_WDAY},
  152.     {"wednesday",    3, 0, TM_WDAY},
  153.     {"thursday",     4, 0, TM_WDAY},
  154.     {"friday",       5, 0, TM_WDAY},
  155.     {"saturday",     6, 0, TM_WDAY},
  156.  
  157.     {"gmt",          0*60, TWTIME, TM_ZON},   /* Greenwich */
  158.     {"utc",          0*60, TWTIME, TM_ZON},
  159.     {"ut",           0*60, TWTIME, TM_ZON},
  160.     {"cut",         0*60, TWTIME, TM_ZON},
  161.  
  162.     {"nzst",        -12*60, TWTIME, TM_ZON},  /* New Zealand */
  163.     {"jst",         -9*60, TWTIME, TM_ZON},   /* Japan */
  164.     {"kst",         -9*60, TWTIME, TM_ZON},   /* Korea */
  165.     {"ist",         -5*60-30, TWTIME, TM_ZON},/* India */
  166.     {"eet",         -2*60, TWTIME, TM_ZON},   /* Eastern Europe */
  167.     {"cet",         -1*60, TWTIME, TM_ZON},   /* Central Europe */
  168.     {"met",         -1*60, TWTIME, TM_ZON},   /* Middle Europe */
  169.     {"wet",          0*60, TWTIME, TM_ZON},   /* Western Europe */
  170.     {"nst",          3*60+30, TWTIME, TM_ZON},/* Newfoundland */
  171.     {"ast",          4*60, TWTIME, TM_ZON},   /* Atlantic */
  172.     {"est",          5*60, TWTIME, TM_ZON},   /* Eastern */
  173.     {"cst",          6*60, TWTIME, TM_ZON},   /* Central */
  174.     {"mst",          7*60, TWTIME, TM_ZON},   /* Mountain */
  175.     {"pst",          8*60, TWTIME, TM_ZON},   /* Pacific */
  176.     {"akst",         9*60, TWTIME, TM_ZON},   /* Alaska */
  177.     {"hast",         10*60, TWTIME, TM_ZON},  /* Hawaii-Aleutian */
  178.     {"hst",          10*60, TWTIME, TM_ZON},  /* Hawaii */
  179.     {"sst",          11*60, TWTIME, TM_ZON},  /* Samoa */
  180.  
  181.     {"nzdt",        -12*60, TWTIME+TWDST, TM_ZON},    /* New Zealand */
  182.     {"kdt",         -9*60, TWTIME+TWDST, TM_ZON},     /* Korea */
  183.     {"bst",          0*60, TWTIME+TWDST, TM_ZON},     /* Britain */
  184.     {"ndt",         3*60+30, TWTIME+TWDST, TM_ZON},  /* Newfoundland */
  185.     {"adt",          4*60, TWTIME+TWDST, TM_ZON},     /* Atlantic */
  186.     {"edt",          5*60, TWTIME+TWDST, TM_ZON},     /* Eastern */
  187.     {"cdt",          6*60, TWTIME+TWDST, TM_ZON},     /* Central */
  188.     {"mdt",          7*60, TWTIME+TWDST, TM_ZON},     /* Mountain */
  189.     {"pdt",          8*60, TWTIME+TWDST, TM_ZON},     /* Pacific */
  190.     {"akdt",         9*60, TWTIME+TWDST, TM_ZON},     /* Alaska */
  191.     {"hadt",         10*60, TWTIME+TWDST, TM_ZON},    /* Hawaii-Aleutian */
  192.  
  193. #if 0
  194.     /*
  195.      * The following names are duplicates or are not well attested.
  196.      * A standard is needed.
  197.      */
  198.     {"east",        -10*60, TWTIME, TM_ZON},  /* Eastern Australia */
  199.     {"cast",        -9*60-30, TWTIME, TM_ZON},/* Central Australia */
  200.     {"cst",         -8*60, TWTIME, TM_ZON},   /* China */
  201.     {"hkt",         -8*60, TWTIME, TM_ZON},   /* Hong Kong */
  202.     {"sst",         -8*60, TWTIME, TM_ZON},   /* Singapore */
  203.     {"wast",        -8*60, TWTIME, TM_ZON},   /* Western Australia */
  204.     {"?",        -6*60-30, TWTIME, TM_ZON},/* Burma */
  205.     {"?",           -4*60-30, TWTIME, TM_ZON},/* Afghanistan */
  206.     {"it",          -3*60-30, TWTIME, TM_ZON},/* Iran */
  207.     {"ist",         -2*60, TWTIME, TM_ZON},   /* Israel */
  208.     {"mez",        -1*60, TWTIME, TM_ZON},   /* Mittel-Europaeische Zeit */
  209.     {"ast",          1*60, TWTIME, TM_ZON},   /* Azores */
  210.     {"fst",          2*60, TWTIME, TM_ZON},   /* Fernando de Noronha */
  211.     {"bst",          3*60, TWTIME, TM_ZON},   /* Brazil */
  212.     {"wst",          4*60, TWTIME, TM_ZON},   /* Western Brazil */
  213.     {"ast",          5*60, TWTIME, TM_ZON},   /* Acre Brazil */
  214.     {"?",            9*60+30, TWTIME, TM_ZON},/* Marquesas */
  215.     {"?",         12*60, TWTIME, TM_ZON},  /* Kwajalein */
  216.  
  217.     {"eadt",        -10*60, TWTIME+TWDST, TM_ZON},    /* Eastern Australia */
  218.     {"cadt",        -9*60-30, TWTIME+TWDST, TM_ZON},  /* Central Australia */
  219.     {"cdt",         -8*60, TWTIME+TWDST, TM_ZON},     /* China */
  220.     {"wadt",        -8*60, TWTIME+TWDST, TM_ZON},     /* Western Australia */
  221.     {"idt",         -2*60, TWTIME+TWDST, TM_ZON},     /* Israel */
  222.     {"eest",        -2*60, TWTIME+TWDST, TM_ZON},     /* Eastern Europe */
  223.     {"cest",        -1*60, TWTIME+TWDST, TM_ZON},     /* Central Europe */
  224.     {"mest",        -1*60, TWTIME+TWDST, TM_ZON},     /* Middle Europe */
  225.     {"mesz",    -1*60, TWTIME+TWDST, TM_ZON},      /* Mittel-Europaeische Sommerzeit */
  226.     {"west",         0*60, TWTIME+TWDST, TM_ZON},     /* Western Europe */
  227.     {"adt",          1*60, TWTIME+TWDST, TM_ZON},      /* Azores */
  228.     {"fdt",          2*60, TWTIME+TWDST, TM_ZON},     /* Fernando de Noronha */
  229.     {"edt",          3*60, TWTIME+TWDST, TM_ZON},     /* Eastern Brazil */
  230.     {"wdt",          4*60, TWTIME+TWDST, TM_ZON},     /* Western Brazil */
  231.     {"adt",          5*60, TWTIME+TWDST, TM_ZON},     /* Acre Brazil */
  232. #endif
  233.  
  234.     {"lt",           0, TWTIME, TM_LT},       /* local time */
  235.     {"dst",          1*60, TWTIME, TM_DST},      /* daylight savings time */
  236.     {"ddst",         2*60, TWTIME, TM_DST},      /* double dst */
  237.  
  238.     {"am",           T12_AM,    TWTIME, TM_12},
  239.     {"pm",           T12_PM,    TWTIME, TM_12},
  240.     {"noon",         T12_NOON,    TWTIME, TM_12},
  241.     {"midnight",     T12_MIDNIGHT,    TWTIME, TM_12},
  242.  
  243.     {0, 0, 0, 0}    /* Zero entry to terminate searches */
  244. };
  245.  
  246. struct token {
  247.     char const *tcp;/* pointer to string */
  248.     int tcnt;    /* # chars */
  249.     char tbrk;    /* "break" char */
  250.     char tbrkl;    /* last break char */
  251.     char tflg;    /* 0 = alpha, 1 = numeric */
  252.     union {         /* Resulting value; */
  253.         int tnum;/* either a #, or */
  254.         struct tmwent const *ttmw;/* a ptr to a tmwent.  */
  255.     } tval;
  256. };
  257.  
  258. static struct tmwent const*ptmatchstr P((char const*,int,struct tmwent const*));
  259. static int pt12hack P((struct tm *,int));
  260. static int ptitoken P((struct token *));
  261. static int ptstash P((int *,int));
  262. static int pttoken P((struct token *));
  263.  
  264.     static int
  265. goodzone(t, offset, am)
  266.     register struct token const *t;
  267.     int offset;
  268.     int *am;
  269. {
  270.     register int m;
  271.     if (
  272.         t->tflg  &&
  273.         t->tcnt == 4+offset  &&
  274.         (m = t->tval.tnum) <= 2400  &&
  275.         isdigit(t->tcp[offset]) &&
  276.         (m%=100) < 60
  277.     ) {
  278.         m += t->tval.tnum/100 * 60;
  279.         if (t->tcp[offset-1]=='+')
  280.             m = -m;
  281.         *am = m;
  282.         return 1;
  283.     }
  284.     return 0;
  285. }
  286.  
  287.     int
  288. partime(astr, atm, zone)
  289. char const *astr;
  290. register struct tm *atm;
  291. int *zone;
  292. {
  293.     register int i;
  294.     struct token btoken, atoken;
  295.     int zone_offset; /* minutes west of GMT, plus TZ_OFFSET */
  296.     register char const *cp;
  297.     register char ch;
  298.     int ord, midnoon;
  299.     int *atmfield, dst, m;
  300.     int got1 = 0;
  301.  
  302.     atm->tm_sec = TMNULL;
  303.     atm->tm_min = TMNULL;
  304.     atm->tm_hour = TMNULL;
  305.     atm->tm_mday = TMNULL;
  306.     atm->tm_mon = TMNULL;
  307.     atm->tm_year = TMNULL;
  308.     atm->tm_wday = TMNULL;
  309.     atm->tm_yday = TMNULL;
  310.     midnoon = TMNULL;        /* and our own temp stuff */
  311.     zone_offset = TMNULL;
  312.     dst = TMNULL;
  313.     btoken.tcnt = btoken.tbrk = 0;
  314.     btoken.tcp = astr;
  315.  
  316.     for (;; got1=1) {
  317.     if (!ptitoken(&btoken))                /* Get a token */
  318.       {     if(btoken.tval.tnum) return(0);         /* Read error? */
  319.         if (given(midnoon))            /* EOF, wrap up */
  320.             if (!pt12hack(atm, midnoon))
  321.                 return 0;
  322.         if (!given(atm->tm_min))
  323.             atm->tm_min = 0;
  324.         *zone  =
  325.                 (given(zone_offset) ? zone_offset-TZ_OFFSET : 0)
  326.             -    (given(dst) ? dst : 0);
  327.         return got1;
  328.       }
  329.     if(btoken.tflg == 0)        /* Alpha? */
  330.       {     i = btoken.tval.ttmw->wval;
  331.         switch (btoken.tval.ttmw->wtype) {
  332.           default:
  333.             return 0;
  334.           case TM_MON:
  335.             atmfield = &atm->tm_mon;
  336.             break;
  337.           case TM_WDAY:
  338.             atmfield = &atm->tm_wday;
  339.             break;
  340.           case TM_DST:
  341.             atmfield = &dst;
  342.             break;
  343.           case TM_LT:
  344.             if (ptstash(&dst, 0))
  345.                 return 0;
  346.             i = 48*60; /* local time magic number -- see maketime() */
  347.             /* fall into */
  348.           case TM_ZON:
  349.             i += TZ_OFFSET;
  350.             if (btoken.tval.ttmw->wflgs & TWDST)
  351.                 if (ptstash(&dst, 60))
  352.                     return 0;
  353.             /* Peek ahead for offset immediately afterwards. */
  354.             if (
  355.                 (btoken.tbrk=='-' || btoken.tbrk=='+') &&
  356.                 (atoken=btoken, ++atoken.tcnt, ptitoken(&atoken)) &&
  357.                 goodzone(&atoken, 0, &m)
  358.             ) {
  359.                 i += m;
  360.                 btoken = atoken;
  361.             }
  362.             atmfield = &zone_offset;
  363.             break;
  364.           case TM_12:
  365.             atmfield = &midnoon;
  366.         }
  367.         if (ptstash(atmfield, i))
  368.             return(0);        /* ERR: val already set */
  369.         continue;
  370.       }
  371.  
  372.     /* Token is number.  Lots of hairy heuristics. */
  373.     if (!isdigit(*btoken.tcp)) {
  374.         if (!goodzone(&btoken, 1, &m))
  375.             return 0;
  376.         zone_offset = TZ_OFFSET + m;
  377.         continue;
  378.     }
  379.  
  380.     i = btoken.tval.tnum;   /* Value now known to be valid; get it. */
  381.     if (btoken.tcnt == 3)    /*  3 digits = HMM   */
  382.       {
  383. hhmm4:        if (ptstash(&atm->tm_min, i%100))
  384.             return(0);        /* ERR: min conflict */
  385.         i /= 100;
  386. hh2:            if (ptstash(&atm->tm_hour, i))
  387.             return(0);        /* ERR: hour conflict */
  388.         continue;
  389.       }
  390.  
  391.     if (4 < btoken.tcnt)
  392.         goto year4; /* far in the future */
  393.     if(btoken.tcnt == 4)    /* 4 digits = YEAR or HHMM */
  394.       {    if (given(atm->tm_year)) goto hhmm4;    /* Already got yr? */
  395.         if (given(atm->tm_hour)) goto year4;    /* Already got hr? */
  396.         if(btoken.tbrk == ':')            /* HHMM:SS ? */
  397.             if ( ptstash(&atm->tm_hour, i/100)
  398.               || ptstash(&atm->tm_min, i%100))
  399.                 return(0);        /* ERR: hr/min clash */
  400.             else goto coltm2;        /* Go handle SS */
  401.         if(btoken.tbrk != ',' && btoken.tbrk != '/'
  402.           && (atoken=btoken, ptitoken(&atoken))    /* Peek */
  403.           && ( atoken.tflg
  404.              ? !isdigit(*atoken.tcp)
  405.              : atoken.tval.ttmw->wflgs & TWTIME)) /* HHMM-ZON */
  406.             goto hhmm4;
  407.         goto year4;            /* Give up, assume year. */
  408.       }
  409.  
  410.     /* From this point on, assume tcnt == 1 or 2 */
  411.     /* 2 digits = MM, DD, or HH (MM and SS caught at coltime) */
  412.     if(btoken.tbrk == ':')        /* HH:MM[:SS] */
  413.         goto coltime;        /*  must be part of time. */
  414.     if (31 < i)
  415.         return 0;
  416.  
  417.     /* Check for numerical-format date */
  418.     for (cp = "/-."; ch = *cp++;)
  419.       {    ord = (ch == '.' ? 0 : 1);    /* n/m = D/M or M/D */
  420.         if(btoken.tbrk == ch)            /* "NN-" */
  421.           {    if(btoken.tbrkl != ch)
  422.               {
  423.                 atoken = btoken;
  424.                 atoken.tcnt++;
  425.                 if (ptitoken(&atoken)
  426.                   && atoken.tflg == 0
  427.                   && atoken.tval.ttmw->wtype == TM_MON)
  428.                     goto dd2;
  429.                 if(ord)goto mm2; else goto dd2; /* "NN-" */
  430.               }                /* "-NN-" */
  431.             if (!given(atm->tm_mday)
  432.               && given(atm->tm_year))    /* If "YYYY-NN-" */
  433.                 goto mm2;        /* then always MM */
  434.             if(ord)goto dd2; else goto mm2;
  435.           }
  436.         if(btoken.tbrkl == ch            /* "-NN" */
  437.           && given(ord ? atm->tm_mon : atm->tm_mday))
  438.             if (!given(ord ? atm->tm_mday : atm->tm_mon)) /* MM/DD */
  439.                 if(ord)goto dd2; else goto mm2;
  440.       }
  441.  
  442.     /* Now reduced to choice between HH and DD */
  443.     if (given(atm->tm_hour)) goto dd2;    /* Have hour? Assume day. */
  444.     if (given(atm->tm_mday)) goto hh2;    /* Have day? Assume hour. */
  445.     if (given(atm->tm_mon)) goto dd2;    /* Have month? Assume day. */
  446.     if(i > 24) goto dd2;            /* Impossible HH means DD */
  447.     atoken = btoken;
  448.     if (!ptitoken(&atoken))            /* Read ahead! */
  449.         if(atoken.tval.tnum) return(0); /* ERR: bad token */
  450.         else goto dd2;            /* EOF, assume day. */
  451.     if ( atoken.tflg
  452.        ? !isdigit(*atoken.tcp)
  453.        : atoken.tval.ttmw->wflgs & TWTIME)
  454.         /* If next token is a time spec, assume hour */
  455.         goto hh2;        /* e.g. "3 PM", "11-EDT"  */
  456.  
  457. dd2:    if (ptstash(&atm->tm_mday, i))    /* Store day (1 based) */
  458.         return(0);
  459.     continue;
  460.  
  461. mm2:    if (ptstash(&atm->tm_mon, i-1))    /* Store month (make zero based) */
  462.         return(0);
  463.     continue;
  464.  
  465. year4:    if ((i-=1900) < 0  ||  ptstash(&atm->tm_year, i)) /* Store year-1900 */
  466.         return(0);        /* ERR: year conflict */
  467.     continue;
  468.  
  469.     /* Hack HH:MM[[:]SS] */
  470. coltime:
  471.     if (ptstash(&atm->tm_hour, i)) return 0;
  472.     if (!ptitoken(&btoken))
  473.         return(!btoken.tval.tnum);
  474.     if(!btoken.tflg) return(0);    /* ERR: HH:<alpha> */
  475.     if(btoken.tcnt == 4)        /* MMSS */
  476.         if (ptstash(&atm->tm_min, btoken.tval.tnum/100)
  477.           || ptstash(&atm->tm_sec, btoken.tval.tnum%100))
  478.             return(0);
  479.         else continue;
  480.     if(btoken.tcnt != 2
  481.       || ptstash(&atm->tm_min, btoken.tval.tnum))
  482.         return(0);        /* ERR: MM bad */
  483.     if (btoken.tbrk != ':') continue;    /* Seconds follow? */
  484. coltm2:    if (!ptitoken(&btoken))
  485.         return(!btoken.tval.tnum);
  486.     if(!btoken.tflg || btoken.tcnt != 2    /* Verify SS */
  487.       || ptstash(&atm->tm_sec, btoken.tval.tnum))
  488.         return(0);        /* ERR: SS bad */
  489.     }
  490. }
  491.  
  492. /* Store date/time value, return 0 if successful.
  493.  * Fail if entry is already set.
  494.  */
  495.     static int
  496. ptstash(adr,val)
  497. int *adr;
  498. int val;
  499. {    register int *a;
  500.     if (given(*(a=adr)))
  501.         return 1;
  502.     *a = val;
  503.     return(0);
  504. }
  505.  
  506. /* This subroutine is invoked for AM, PM, NOON and MIDNIGHT when wrapping up
  507.  * just prior to returning from partime.
  508.  */
  509.     static int
  510. pt12hack(tm, aval)
  511. register struct tm *tm;
  512. register int aval;
  513. {    register int h = tm->tm_hour;
  514.     switch (aval) {
  515.       case T12_AM:
  516.       case T12_PM:
  517.         if (h > 12)
  518.             return 0;
  519.         if (h == 12)
  520.             tm->tm_hour = 0;
  521.         if (aval == T12_PM)
  522.             tm->tm_hour += 12;
  523.         break;
  524.       default:
  525.         if (0 < tm->tm_min  ||  0 < tm->tm_sec)
  526.             return 0;
  527.         if (!given(h) || h==12)
  528.             tm->tm_hour = aval;
  529.         else if (aval==T12_MIDNIGHT  &&  (h==0 || h==24))
  530.             return 0;
  531.     }
  532.     return 1;
  533. }
  534.  
  535. /* Get a token and identify it to some degree.
  536.  * Returns 0 on failure; token.tval will be 0 for normal EOF, otherwise
  537.  * hit error of some sort
  538.  */
  539.  
  540.     static int
  541. ptitoken(tkp)
  542. register struct token *tkp;
  543. {
  544.     register char const *cp;
  545.     register int i, j, k;
  546.  
  547.     if (!pttoken(tkp))
  548. #ifdef DEBUG
  549.         {
  550.         VOID printf("EOF\n");
  551.         return(0);
  552.         }
  553. #else
  554.         return(0);
  555. #endif    
  556.     cp = tkp->tcp;
  557.  
  558. #ifdef DEBUG
  559.     VOID printf("Token: \"%.*s\" ", tkp->tcnt, cp);
  560. #endif
  561.  
  562.     if (tkp->tflg) {
  563.         i = tkp->tcnt;
  564.         if (*cp == '+' || *cp == '-') {
  565.             cp++;
  566.             i--;
  567.         }
  568.         while (0 <= --i) {
  569.             j = tkp->tval.tnum*10;
  570.             k = j + (*cp++ - '0');
  571.             if (j/10 != tkp->tval.tnum  ||  k < j) {
  572.                 /* arithmetic overflow */
  573.                 tkp->tval.tnum = 1;
  574.                 return 0;
  575.             }
  576.             tkp->tval.tnum = k;
  577.         }
  578.     } else if (!(tkp->tval.ttmw  =  ptmatchstr(cp, tkp->tcnt, tmwords)))
  579.       {
  580. #ifdef DEBUG
  581.         VOID printf("Not found!\n");
  582. #endif
  583.         tkp->tval.tnum = 1;
  584.         return 0;
  585.       }
  586.  
  587. #ifdef DEBUG
  588.     if(tkp->tflg)
  589.         VOID printf("Val: %d.\n",tkp->tval.tnum);
  590.     else VOID printf("Found: \"%s\", val: %d, type %d\n",
  591.         tkp->tval.ttmw->went,tkp->tval.ttmw->wval,tkp->tval.ttmw->wtype);
  592. #endif
  593.  
  594.     return(1);
  595. }
  596.  
  597. /* Read token from input string into token structure */
  598.     static int
  599. pttoken(tkp)
  600. register struct token *tkp;
  601. {
  602.     register char const *cp;
  603.     register int c;
  604.     char const *astr;
  605.  
  606.     tkp->tcp = astr = cp = tkp->tcp + tkp->tcnt;
  607.     tkp->tbrkl = tkp->tbrk;        /* Set "last break" */
  608.     tkp->tcnt = tkp->tbrk = tkp->tflg = 0;
  609.     tkp->tval.tnum = 0;
  610.  
  611.     while(c = *cp++)
  612.       {    switch(c)
  613.           {    case ' ': case '\t':    /* Flush all whitespace */
  614.             case '\r': case '\n':
  615.             case '\v': case '\f':
  616.                 if (!tkp->tcnt) {    /* If no token yet */
  617.                     tkp->tcp = cp;    /* ignore the brk */
  618.                     continue;    /* and go on. */
  619.                 }
  620.                 /* fall into */
  621.             case '(': case ')':    /* Perhaps any non-alphanum */
  622.             case '-': case ',':    /* shd qualify as break? */
  623.             case '+':
  624.             case '/': case ':': case '.':    /* Break chars */
  625.                 if(tkp->tcnt == 0)    /* If no token yet */
  626.                   {    tkp->tcp = cp;    /* ignore the brk */
  627.                     tkp->tbrkl = c;
  628.                       continue;    /* and go on. */
  629.                   }
  630.                 tkp->tbrk = c;
  631.                 return(tkp->tcnt);
  632.           }
  633.         if (!tkp->tcnt++) {        /* If first char of token, */
  634.             if (isdigit(c)) {
  635.                 tkp->tflg = 1;
  636.                 if (astr<cp-2 && (cp[-2]=='-'||cp[-2]=='+')) {
  637.                     /* timezone is break+sign+digit */
  638.                     tkp->tcp--;
  639.                     tkp->tcnt++;
  640.                 }
  641.             }
  642.         } else if ((isdigit(c)!=0) != tkp->tflg) { /* else check type */
  643.             tkp->tbrk = c;
  644.             return --tkp->tcnt;    /* Wrong type, back up */
  645.         }
  646.       }
  647.     return(tkp->tcnt);        /* When hit EOF */
  648. }
  649.  
  650.  
  651.     static struct tmwent const *
  652. ptmatchstr(astr,cnt,astruc)
  653.     char const *astr;
  654.     int cnt;
  655.     struct tmwent const *astruc;
  656. {
  657.     register char const *cp, *mp;
  658.     register int c;
  659.     struct tmwent const *lastptr;
  660.     int i;
  661.  
  662.     lastptr = 0;
  663.     for(;mp = astruc->went; astruc += 1)
  664.       {    cp = astr;
  665.         for(i = cnt; i > 0; i--)
  666.           {
  667.             switch (*cp++ - (c = *mp++))
  668.               {    case 0: continue;    /* Exact match */
  669.                 case 'A'-'a':
  670.                     if (ctab[c] == Letter)
  671.                     continue;
  672.               }
  673.             break;
  674.           }
  675.         if(i==0)
  676.             if (!*mp) return astruc;    /* Exact match */
  677.             else if(lastptr) return(0);    /* Ambiguous */
  678.             else lastptr = astruc;        /* 1st ambig */
  679.       }
  680.     return lastptr;
  681. }
  682. @
  683.  
  684.  
  685. 5.6.1.1
  686. log
  687. @Start of the AMIGA port of RCS 5.6. I call it HWGRCS now ;^)
  688. @
  689. text
  690. @@
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.  
  733.  
  734.  
  735.  
  736.  
  737.  
  738.  
  739.  
  740.  
  741.  
  742.  
  743.  
  744.  
  745.  
  746.  
  747.  
  748.  
  749.  
  750.  
  751.  
  752.  
  753.  
  754.  
  755.  
  756.  
  757.  
  758.  
  759.  
  760.  
  761.  
  762.  
  763.  
  764.  
  765.  
  766.  
  767.  
  768.  
  769.  
  770.  
  771.  
  772.  
  773.