home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-03-05 | 47.8 KB | 1,625 lines |
- ! * Initial revision
- ! *
- ! */
-
- ! /* minimal changes needed to get this file to work for CVS rather than RCS */
- ! /* #include "rcsbase.h" */
- ! #include <ctype.h>
- ! #include <time.h>
- ! #include "cvs.h"
- ! #define libId(x,y) static char x[] = y;
- ! #define P(x) ()
- ! #if !__STDC__
- ! # define const
- #endif
- + /* see also `RCS' in comment below */
- +
- + libId(partId, "$Id: partime.c,v 1.1.1.1 91/01/18 12:18:12 berliner Exp $")
-
- + #define given(v) (0 <= (v))
- + #define TMNULL (-1) /* Items not given are given this value */
- + #define TZ_OFFSET (24*60) /* TMNULL < zone_offset - TZ_OFFSET */
- +
- struct tmwent {
- ! const char *went;
- ! short wval;
- char wflgs;
- char wtype;
- };
- /* wflgs */
- #define TWTIME 02 /* Word is a time value (absence implies date) */
- #define TWDST 04 /* Word is a DST-type timezone */
- ! /* wtype */
- ! #define TM_MON 1 /* month name */
- ! #define TM_WDAY 2 /* weekday name */
- ! #define TM_ZON 3 /* time zone name */
- ! #define TM_LT 4 /* local time */
- ! #define TM_DST 5 /* daylight savings time */
- ! #define TM_12 6 /* AM, PM, NOON, or MIDNIGHT */
- ! /* wval (for wtype==TM_12) */
- ! #define T12_AM 1
- ! #define T12_PM 2
- ! #define T12_NOON 12
- ! #define T12_MIDNIGHT 0
-
- ! static const struct tmwent tmwords [] = {
- {"january", 0, 0, TM_MON},
- {"february", 1, 0, TM_MON},
- {"march", 2, 0, TM_MON},
- ***************
- *** 75,119 ****
- {"saturday", 6, 0, TM_WDAY},
-
- {"gmt", 0*60, TWTIME, TM_ZON}, /* Greenwich */
- ! {"gst", 0*60, TWTIME, TM_ZON},
- ! {"gdt", 0*60, TWTIME+TWDST, TM_ZON}, /* ?? */
-
- {"ast", 4*60, TWTIME, TM_ZON}, /* Atlantic */
- {"est", 5*60, TWTIME, TM_ZON}, /* Eastern */
- {"cst", 6*60, TWTIME, TM_ZON}, /* Central */
- {"mst", 7*60, TWTIME, TM_ZON}, /* Mountain */
- {"pst", 8*60, TWTIME, TM_ZON}, /* Pacific */
- ! {"yst", 9*60, TWTIME, TM_ZON}, /* Yukon */
- {"hst", 10*60, TWTIME, TM_ZON}, /* Hawaii */
- ! {"bst", 11*60, TWTIME, TM_ZON}, /* Bering */
-
- {"adt", 4*60, TWTIME+TWDST, TM_ZON}, /* Atlantic */
- {"edt", 5*60, TWTIME+TWDST, TM_ZON}, /* Eastern */
- {"cdt", 6*60, TWTIME+TWDST, TM_ZON}, /* Central */
- {"mdt", 7*60, TWTIME+TWDST, TM_ZON}, /* Mountain */
- {"pdt", 8*60, TWTIME+TWDST, TM_ZON}, /* Pacific */
- ! {"ydt", 9*60, TWTIME+TWDST, TM_ZON}, /* Yukon */
- ! {"hdt", 10*60, TWTIME+TWDST, TM_ZON}, /* Hawaii */
- ! {"bdt", 11*60, TWTIME+TWDST, TM_ZON}, /* Bering */
- !
- ! {"daylight", 1, TWTIME+TWDST, TM_ZON}, /* Local Daylight */
- ! {"standard", 1, TWTIME, TM_ZON}, /* Local Standard */
- ! {"std", 1, TWTIME, TM_ZON}, /* " " */
- !
- ! {"am", 1, TWTIME, TM_AMPM},
- ! {"pm", 2, TWTIME, TM_AMPM},
- ! {"noon", 12,TWTIME+TW1200, 0}, /* Special frobs */
- ! {"midnight", 0, TWTIME+TW1200, 0},
- ! {"at", (long)ptnoise, TWSPEC, 0}, /* Noise word */
-
- {0, 0, 0, 0}, /* Zero entry to terminate searches */
- };
-
- - #define TMWILD (-2) /* Value meaning item specified as wild-card */
- - /* (May use someday...) */
- -
- struct token {
- ! char *tcp; /* pointer to string */
- int tcnt; /* # chars */
- char tbrk; /* "break" char */
- char tbrkl; /* last break char */
- --- 123,230 ----
- {"saturday", 6, 0, TM_WDAY},
-
- {"gmt", 0*60, TWTIME, TM_ZON}, /* Greenwich */
- ! {"utc", 0*60, TWTIME, TM_ZON},
- ! {"ut", 0*60, TWTIME, TM_ZON},
-
- + {"nzst", -12*60, TWTIME, TM_ZON}, /* New Zealand */
- + {"jst", -9*60, TWTIME, TM_ZON}, /* Japan */
- + {"kst", -9*60, TWTIME, TM_ZON}, /* Korea */
- + {"ist", -5*60-30, TWTIME, TM_ZON},/* India */
- + {"eet", -2*60, TWTIME, TM_ZON}, /* Eastern Europe */
- + {"cet", -1*60, TWTIME, TM_ZON}, /* Central Europe */
- + {"met", -1*60, TWTIME, TM_ZON}, /* Middle Europe */
- + {"wet", 0*60, TWTIME, TM_ZON}, /* Western Europe */
- + {"nst", 3*60+30, TWTIME, TM_ZON},/* Newfoundland */
- {"ast", 4*60, TWTIME, TM_ZON}, /* Atlantic */
- {"est", 5*60, TWTIME, TM_ZON}, /* Eastern */
- {"cst", 6*60, TWTIME, TM_ZON}, /* Central */
- {"mst", 7*60, TWTIME, TM_ZON}, /* Mountain */
- {"pst", 8*60, TWTIME, TM_ZON}, /* Pacific */
- ! {"akst", 9*60, TWTIME, TM_ZON}, /* Alaska */
- ! {"hast", 10*60, TWTIME, TM_ZON}, /* Hawaii-Aleutian */
- {"hst", 10*60, TWTIME, TM_ZON}, /* Hawaii */
- ! {"sst", 11*60, TWTIME, TM_ZON}, /* Samoa */
-
- + {"nzdt", -12*60, TWTIME+TWDST, TM_ZON}, /* New Zealand */
- + {"kdt", -9*60, TWTIME+TWDST, TM_ZON}, /* Korea */
- + {"bst", 0*60, TWTIME+TWDST, TM_ZON}, /* Britain */
- + {"ndt", 2*60+30, TWTIME+TWDST, TM_ZON}, /*Newfoundland (DDST)*/
- {"adt", 4*60, TWTIME+TWDST, TM_ZON}, /* Atlantic */
- {"edt", 5*60, TWTIME+TWDST, TM_ZON}, /* Eastern */
- {"cdt", 6*60, TWTIME+TWDST, TM_ZON}, /* Central */
- {"mdt", 7*60, TWTIME+TWDST, TM_ZON}, /* Mountain */
- {"pdt", 8*60, TWTIME+TWDST, TM_ZON}, /* Pacific */
- ! {"akdt", 9*60, TWTIME+TWDST, TM_ZON}, /* Alaska */
- ! {"hadt", 10*60, TWTIME+TWDST, TM_ZON}, /* Hawaii-Aleutian */
- !
- ! #if 0
- ! /*
- ! * The following names are duplicates or are not well attested.
- ! * A standard is needed.
- ! */
- ! {"?st", -13*60, TWTIME, TM_ZON}, /* Uelen */
- ! {"?st", -11*60, TWTIME, TM_ZON}, /* Magadan */
- ! {"east", -10*60, TWTIME, TM_ZON}, /* Eastern Australia */
- ! {"cast", -9*60-30, TWTIME, TM_ZON},/* Central Australia */
- ! {"cst", -8*60, TWTIME, TM_ZON}, /* China */
- ! {"hkt", -8*60, TWTIME, TM_ZON}, /* Hong Kong */
- ! {"sst", -8*60, TWTIME, TM_ZON}, /* Singapore */
- ! {"wast", -8*60, TWTIME, TM_ZON}, /* Western Australia */
- ! {"?st", -7*60, TWTIME, TM_ZON}, /* Novosibirsk */
- ! {"jt", -7*60-30, TWTIME, TM_ZON},/* Java */
- ! {"nst", -6*60-30, TWTIME, TM_ZON},/* North Sumatra */
- ! {"?st", -6*60, TWTIME, TM_ZON}, /* Tashkent */
- ! {"?st", -5*60, TWTIME, TM_ZON}, /* Sverdlovsk */
- ! {"?", -4*60-30, TWTIME, TM_ZON},/* Afghanistan */
- ! {"?st", -4*60, TWTIME, TM_ZON}, /* Rostov */
- ! {"it", -3*60-30, TWTIME, TM_ZON},/* Iran */
- ! {"?st", -3*60, TWTIME, TM_ZON}, /* Moscow */
- ! {"ist", -2*60, TWTIME, TM_ZON}, /* Israel */
- ! {"ast", 1*60, TWTIME, TM_ZON}, /* Azores */
- ! {"fst", 2*60, TWTIME, TM_ZON}, /* Fernando de Noronha */
- ! {"bst", 3*60, TWTIME, TM_ZON}, /* Brazil */
- ! {"wst", 4*60, TWTIME, TM_ZON}, /* Western Brazil */
- ! {"ast", 5*60, TWTIME, TM_ZON}, /* Acre Brazil */
- ! {"?", 9*60+30, TWTIME, TM_ZON},/* Marquesas */
- ! {"?st", 12*60, TWTIME, TM_ZON}, /* Kwajalein */
- !
- ! {"?dt", -13*60, TWTIME+TWDST, TM_ZON}, /* Uelen */
- ! {"?dt", -11*60, TWTIME+TWDST, TM_ZON}, /* Magadan */
- ! {"eadt", -10*60, TWTIME+TWDST, TM_ZON}, /* Eastern Australia */
- ! {"cadt", -9*60-30, TWTIME+TWDST, TM_ZON}, /* Central Australia */
- ! {"cdt", -8*60, TWTIME+TWDST, TM_ZON}, /* China */
- ! {"wadt", -8*60, TWTIME+TWDST, TM_ZON}, /* Western Australia */
- ! {"?dt", -7*60, TWTIME+TWDST, TM_ZON}, /* Novosibirsk */
- ! {"?dt", -6*60, TWTIME+TWDST, TM_ZON}, /* Tashkent */
- ! {"?dt", -5*60, TWTIME+TWDST, TM_ZON}, /* Sverdlovsk */
- ! {"?dt", -4*60, TWTIME+TWDST, TM_ZON}, /* Rostov */
- ! {"?dt", -3*60, TWTIME+TWDST, TM_ZON}, /* Moscow */
- ! {"idt", -2*60, TWTIME+TWDST, TM_ZON}, /* Israel */
- ! {"eest", -2*60, TWTIME+TWDST, TM_ZON}, /* Eastern Europe */
- ! {"cest", -1*60, TWTIME+TWDST, TM_ZON}, /* Central Europe */
- ! {"mest", -1*60, TWTIME+TWDST, TM_ZON}, /* Middle Europe */
- ! {"west", 0*60, TWTIME+TWDST, TM_ZON}, /* Western Europe */
- ! {"adt", 1*60, TWTIME+TWDST, TM_ZON}, /* Azores */
- ! {"fdt", 2*60, TWTIME+TWDST, TM_ZON}, /* Fernando de Noronha */
- ! {"edt", 3*60, TWTIME+TWDST, TM_ZON}, /* Eastern Brazil */
- ! {"wdt", 4*60, TWTIME+TWDST, TM_ZON}, /* Western Brazil */
- ! {"adt", 5*60, TWTIME+TWDST, TM_ZON}, /* Acre Brazil */
- ! #endif
- !
- ! {"lt", 0, TWTIME, TM_LT}, /* local time */
- ! {"dst", 1*60, TWTIME, TM_DST}, /* daylight savings time */
- ! {"ddst", 2*60, TWTIME, TM_DST}, /* double dst */
- !
- ! {"am", T12_AM, TWTIME, TM_12},
- ! {"pm", T12_PM, TWTIME, TM_12},
- ! {"noon", T12_NOON, TWTIME, TM_12},
- ! {"midnight", T12_MIDNIGHT, TWTIME, TM_12},
-
- {0, 0, 0, 0}, /* Zero entry to terminate searches */
- };
-
- struct token {
- ! const char *tcp;/* pointer to string */
- int tcnt; /* # chars */
- char tbrk; /* "break" char */
- char tbrkl; /* last break char */
- ***************
- *** 120,227 ****
- char tflg; /* 0 = alpha, 1 = numeric */
- union { /* Resulting value; */
- int tnum;/* either a #, or */
- ! struct tmwent *ttmw;/* ptr to a tmwent. */
- } tval;
- };
-
- ! partime(astr, atm)
- ! char *astr;
- ! struct tm *atm;
- ! { register int *tp;
- ! register struct tmwent *twp;
- ! register int i;
- ! struct token btoken, atoken;
- ! char *cp, ch;
- ! int ord, midnoon;
- ! int (*aproc)();
- !
- ! tp = (int *)atm;
- ! zaptime(tp); /* Initialize the TM structure */
- ! midnoon = TMNULL; /* and our own temp stuff */
- ! btoken.tcnt = btoken.tbrkl = 0;
- ! btoken.tcp = astr;
-
- ! domore:
- ! if(!ptitoken(btoken.tcp+btoken.tcnt,&btoken)) /* Get a token */
- { if(btoken.tval.tnum) return(0); /* Read error? */
- ! if(midnoon != TMNULL) /* EOF, wrap up */
- ! return(pt12hack(tp, midnoon));
- ! return(1); /* Win return! */
- }
- if(btoken.tflg == 0) /* Alpha? */
- ! { twp = btoken.tval.ttmw; /* Yes, get ptr to entry */
- ! if(twp->wflgs&TWSPEC) /* Special alpha crock */
- ! { aproc = (int (*) ()) (twp->wval);
- ! if(!(*aproc)(tp, twp, &btoken))
- ! return(0); /* ERR: special word err */
- ! goto domore;
- ! }
- ! if(twp->wflgs&TW1200)
- ! if(ptstash(&midnoon,(int)twp->wval))
- ! return(0); /* ERR: noon/midnite clash */
- ! else goto domore;
- ! if(ptstash(&tp[twp->wtype],(int)twp->wval))
- return(0); /* ERR: val already set */
- ! if(twp->wtype == TM_ZON) /* If was zone, hack DST */
- ! if(ptstash(&tp[TM_ISDST],(twp->wflgs&TWDST)))
- ! return(0); /* ERR: DST conflict */
- ! goto domore;
- }
-
- /* Token is number. Lots of hairy heuristics. */
- ! if(btoken.tcnt >= 7) /* More than 6 digits in string? */
- ! return(0); /* ERR: number too big */
- ! if(btoken.tcnt == 6) /* 6 digits = HHMMSS. Needs special crock */
- ! { /* since 6 digits are too big for integer! */
- ! i = (btoken.tcp[0]-'0')*10 /* Gobble 1st 2 digits */
- ! + btoken.tcp[1]-'0';
- ! btoken.tcnt = 2; /* re-read last 4 chars */
- ! goto coltime;
- ! }
-
- i = btoken.tval.tnum; /* Value now known to be valid; get it. */
- ! if( btoken.tcnt == 5 /* 5 digits = HMMSS */
- ! || btoken.tcnt == 3) /* 3 digits = HMM */
- ! { if(btoken.tcnt != 3)
- ! if(ptstash(&tp[TM_SEC], i%100))
- ! return(0); /* ERR: sec conflict */
- ! else i /= 100;
- ! hhmm4: if(ptstash(&tp[TM_MIN], i%100))
- return(0); /* ERR: min conflict */
- i /= 100;
- ! hh2: if(ptstash(&tp[TM_HOUR], i))
- return(0); /* ERR: hour conflict */
- ! goto domore;
- }
-
- if(btoken.tcnt == 4) /* 4 digits = YEAR or HHMM */
- ! { if(tp[TM_YEAR] != TMNULL) goto hhmm4; /* Already got yr? */
- ! if(tp[TM_HOUR] != TMNULL) goto year4; /* Already got hr? */
- ! if((i%100) > 59) goto year4; /* MM >= 60? */
- if(btoken.tbrk == ':') /* HHMM:SS ? */
- ! if( ptstash(&tp[TM_HOUR],i/100)
- ! || ptstash(&tp[TM_MIN], i%100))
- return(0); /* ERR: hr/min clash */
- else goto coltm2; /* Go handle SS */
- if(btoken.tbrk != ',' && btoken.tbrk != '/'
- ! && ptitoken(btoken.tcp+btoken.tcnt,&atoken) /* Peek */
- ! && atoken.tflg == 0 /* alpha */
- ! && (atoken.tval.ttmw->wflgs&TWTIME)) /* HHMM-ZON */
- goto hhmm4;
- ! if(btoken.tbrkl == '-' /* DD-Mon-YYYY */
- ! || btoken.tbrkl == ',' /* Mon DD, YYYY */
- ! || btoken.tbrkl == '/' /* MM/DD/YYYY */
- ! || btoken.tbrkl == '.' /* DD.MM.YYYY */
- ! || btoken.tbrk == '-' /* YYYY-MM-DD */
- ! ) goto year4;
- ! goto hhmm4; /* Give up, assume HHMM. */
- }
-
- /* From this point on, assume tcnt == 1 or 2 */
- ! /* 2 digits = YY, MM, DD, or HH (MM and SS caught at coltime) */
- if(btoken.tbrk == ':') /* HH:MM[:SS] */
- goto coltime; /* must be part of time. */
- ! if(i > 31) goto yy2; /* If >= 32, only YY poss. */
-
- /* Check for numerical-format date */
- for (cp = "/-."; ch = *cp++;)
- --- 231,398 ----
- char tflg; /* 0 = alpha, 1 = numeric */
- union { /* Resulting value; */
- int tnum;/* either a #, or */
- ! const struct tmwent *ttmw;/* ptr to a tmwent. */
- } tval;
- };
-
- ! static const struct tmwent*ptmatchstr P((const char*,int,const struct tmwent*));
- ! static int pt12hack P((struct tm *,int));
- ! static int ptitoken P((struct token *));
- ! static int ptstash P((int *,int));
- ! static int pttoken P((struct token *));
- !
- ! static int
- ! goodzone(t, offset, am)
- ! register const struct token *t;
- ! int offset;
- ! int *am;
- ! {
- ! register int m;
- ! if (
- ! t->tflg &&
- ! t->tcnt == 4+offset &&
- ! (m = t->tval.tnum) <= 2400 &&
- ! isdigit(t->tcp[offset]) &&
- ! (m%=100) < 60
- ! ) {
- ! m += t->tval.tnum/100 * 60;
- ! if (t->tcp[offset-1]=='+')
- ! m = -m;
- ! *am = m;
- ! return 1;
- ! }
- ! return 0;
- ! }
- !
- ! int
- ! partime(astr, atm, zone)
- ! const char *astr;
- ! register struct tm *atm;
- ! int *zone;
- ! {
- ! register int i;
- ! struct token btoken, atoken;
- ! int zone_offset; /* minutes west of GMT, plus TZ_OFFSET */
- ! register const char *cp;
- ! register char ch;
- ! int ord, midnoon;
- ! int *atmfield, dst, m;
- ! int got1 = 0;
- !
- ! atm->tm_sec = TMNULL;
- ! atm->tm_min = TMNULL;
- ! atm->tm_hour = TMNULL;
- ! atm->tm_mday = TMNULL;
- ! atm->tm_mon = TMNULL;
- ! atm->tm_year = TMNULL;
- ! atm->tm_wday = TMNULL;
- ! atm->tm_yday = TMNULL;
- ! midnoon = TMNULL; /* and our own temp stuff */
- ! zone_offset = TMNULL;
- ! dst = TMNULL;
- ! btoken.tcnt = btoken.tbrk = 0;
- ! btoken.tcp = astr;
-
- ! for (;; got1=1) {
- ! if (!ptitoken(&btoken)) /* Get a token */
- { if(btoken.tval.tnum) return(0); /* Read error? */
- ! if (given(midnoon)) /* EOF, wrap up */
- ! if (!pt12hack(atm, midnoon))
- ! return 0;
- ! if (!given(atm->tm_min))
- ! atm->tm_min = 0;
- ! *zone =
- ! (given(zone_offset) ? zone_offset-TZ_OFFSET : 0)
- ! - (given(dst) ? dst : 0);
- ! return got1;
- }
- if(btoken.tflg == 0) /* Alpha? */
- ! { i = btoken.tval.ttmw->wval;
- ! switch (btoken.tval.ttmw->wtype) {
- ! default:
- ! return 0;
- ! case TM_MON:
- ! atmfield = &atm->tm_mon;
- ! break;
- ! case TM_WDAY:
- ! atmfield = &atm->tm_wday;
- ! break;
- ! case TM_DST:
- ! atmfield = &dst;
- ! break;
- ! case TM_LT:
- ! if (ptstash(&dst, 0))
- ! return 0;
- ! i = 48*60; /* local time magic number -- see maketime() */
- ! /* fall into */
- ! case TM_ZON:
- ! i += TZ_OFFSET;
- ! if (btoken.tval.ttmw->wflgs & TWDST)
- ! if (ptstash(&dst, 60))
- ! return 0;
- ! /* Peek ahead for offset immediately afterwards. */
- ! if (
- ! (btoken.tbrk=='-' || btoken.tbrk=='+') &&
- ! (atoken=btoken, ++atoken.tcnt, ptitoken(&atoken)) &&
- ! goodzone(&atoken, 0, &m)
- ! ) {
- ! i += m;
- ! btoken = atoken;
- ! }
- ! atmfield = &zone_offset;
- ! break;
- ! case TM_12:
- ! atmfield = &midnoon;
- ! }
- ! if (ptstash(atmfield, i))
- return(0); /* ERR: val already set */
- ! continue;
- }
-
- /* Token is number. Lots of hairy heuristics. */
- ! if (!isdigit(*btoken.tcp)) {
- ! if (!goodzone(&btoken, 1, &m))
- ! return 0;
- ! zone_offset = TZ_OFFSET + m;
- ! continue;
- ! }
-
- i = btoken.tval.tnum; /* Value now known to be valid; get it. */
- ! if (btoken.tcnt == 3) /* 3 digits = HMM */
- ! {
- ! hhmm4: if (ptstash(&atm->tm_min, i%100))
- return(0); /* ERR: min conflict */
- i /= 100;
- ! hh2: if (ptstash(&atm->tm_hour, i))
- return(0); /* ERR: hour conflict */
- ! continue;
- }
-
- + if (4 < btoken.tcnt)
- + goto year4; /* far in the future */
- if(btoken.tcnt == 4) /* 4 digits = YEAR or HHMM */
- ! { if (given(atm->tm_year)) goto hhmm4; /* Already got yr? */
- ! if (given(atm->tm_hour)) goto year4; /* Already got hr? */
- if(btoken.tbrk == ':') /* HHMM:SS ? */
- ! if ( ptstash(&atm->tm_hour, i/100)
- ! || ptstash(&atm->tm_min, i%100))
- return(0); /* ERR: hr/min clash */
- else goto coltm2; /* Go handle SS */
- if(btoken.tbrk != ',' && btoken.tbrk != '/'
- ! && (atoken=btoken, ptitoken(&atoken)) /* Peek */
- ! && ( atoken.tflg
- ! ? !isdigit(*atoken.tcp)
- ! : atoken.tval.ttmw->wflgs & TWTIME)) /* HHMM-ZON */
- goto hhmm4;
- ! goto year4; /* Give up, assume year. */
- }
-
- /* From this point on, assume tcnt == 1 or 2 */
- ! /* 2 digits = MM, DD, or HH (MM and SS caught at coltime) */
- if(btoken.tbrk == ':') /* HH:MM[:SS] */
- goto coltime; /* must be part of time. */
- ! if (31 < i)
- ! return 0;
-
- /* Check for numerical-format date */
- for (cp = "/-."; ch = *cp++;)
- ***************
- *** 228,416 ****
- { ord = (ch == '.' ? 0 : 1); /* n/m = D/M or M/D */
- if(btoken.tbrk == ch) /* "NN-" */
- { if(btoken.tbrkl != ch)
- ! { if(ptitoken(btoken.tcp+btoken.tcnt,&atoken)
- && atoken.tflg == 0
- && atoken.tval.ttmw->wtype == TM_MON)
- goto dd2;
- if(ord)goto mm2; else goto dd2; /* "NN-" */
- } /* "-NN-" */
- ! if(tp[TM_DAY] == TMNULL
- ! && tp[TM_YEAR] != TMNULL) /* If "YY-NN-" */
- goto mm2; /* then always MM */
- if(ord)goto dd2; else goto mm2;
- }
- if(btoken.tbrkl == ch /* "-NN" */
- ! && tp[ord ? TM_MON : TM_DAY] != TMNULL)
- ! if(tp[ord ? TM_DAY : TM_MON] == TMNULL) /* MM/DD */
- if(ord)goto dd2; else goto mm2;
- - else goto yy2; /* "-YY" */
- }
-
- - /* At this point only YY, DD, and HH are left.
- - * YY is very unlikely since value is <= 32 and there was
- - * no numerical format date. Make one last try at YY
- - * before dropping through to DD vs HH code.
- - */
- - if(btoken.tcnt == 2 /* If 2 digits */
- - && tp[TM_HOUR] != TMNULL /* and already have hour */
- - && tp[TM_DAY] != TMNULL /* and day, but */
- - && tp[TM_YEAR] == TMNULL) /* no year, then assume */
- - goto yy2; /* that's what we have. */
- -
- /* Now reduced to choice between HH and DD */
- ! if(tp[TM_HOUR] != TMNULL) goto dd2; /* Have hour? Assume day. */
- ! if(tp[TM_DAY] != TMNULL) goto hh2; /* Have day? Assume hour. */
- if(i > 24) goto dd2; /* Impossible HH means DD */
- ! if(!ptitoken(btoken.tcp+btoken.tcnt, &atoken)) /* Read ahead! */
- if(atoken.tval.tnum) return(0); /* ERR: bad token */
- else goto dd2; /* EOF, assume day. */
- ! if( atoken.tflg == 0 /* If next token is an alpha */
- ! && atoken.tval.ttmw->wflgs&TWTIME) /* time-spec, assume hour */
- goto hh2; /* e.g. "3 PM", "11-EDT" */
-
- ! dd2: if(ptstash(&tp[TM_DAY],i)) /* Store day (1 based) */
- return(0);
- ! goto domore;
-
- ! mm2: if(ptstash(&tp[TM_MON], i-1)) /* Store month (make zero based) */
- return(0);
- ! goto domore;
-
- ! yy2: i += 1900;
- ! year4: if(ptstash(&tp[TM_YEAR],i)) /* Store year (full number) */
- return(0); /* ERR: year conflict */
- ! goto domore;
-
- /* Hack HH:MM[[:]SS] */
- coltime:
- ! if(ptstash(&tp[TM_HOUR],i)) return(0);
- ! if(!ptitoken(btoken.tcp+btoken.tcnt,&btoken))
- return(!btoken.tval.tnum);
- if(!btoken.tflg) return(0); /* ERR: HH:<alpha> */
- if(btoken.tcnt == 4) /* MMSS */
- ! if(ptstash(&tp[TM_MIN],btoken.tval.tnum/100)
- ! || ptstash(&tp[TM_SEC],btoken.tval.tnum%100))
- return(0);
- ! else goto domore;
- if(btoken.tcnt != 2
- ! || ptstash(&tp[TM_MIN],btoken.tval.tnum))
- return(0); /* ERR: MM bad */
- ! if(btoken.tbrk != ':') goto domore; /* Seconds follow? */
- ! coltm2: if(!ptitoken(btoken.tcp+btoken.tcnt,&btoken))
- return(!btoken.tval.tnum);
- if(!btoken.tflg || btoken.tcnt != 2 /* Verify SS */
- ! || ptstash(&tp[TM_SEC], btoken.tval.tnum))
- return(0); /* ERR: SS bad */
- ! goto domore;
- }
-
- /* Store date/time value, return 0 if successful.
- ! * Fails if entry already set to a different value.
- */
- ptstash(adr,val)
- int *adr;
- { register int *a;
- ! if( *(a=adr) != TMNULL)
- ! return(*a != val);
- *a = val;
- return(0);
- }
-
- ! /* This subroutine is invoked for NOON or MIDNIGHT when wrapping up
- * just prior to returning from partime.
- */
- ! pt12hack(atp, aval)
- ! int *atp, aval;
- ! { register int *tp, i, h;
- ! tp = atp;
- ! if (((i=tp[TM_MIN]) && i != TMNULL) /* Ensure mins, secs */
- ! || ((i=tp[TM_SEC]) && i != TMNULL)) /* are 0 or unspec'd */
- ! return(0); /* ERR: MM:SS not 00:00 */
- ! i = aval; /* Get 0 or 12 (midnite or noon) */
- ! if ((h = tp[TM_HOUR]) == TMNULL /* If hour unspec'd, win */
- ! || h == 12) /* or if 12:00 (matches either) */
- ! tp[TM_HOUR] = i; /* Then set time */
- ! else if(!(i == 0 /* Nope, but if midnight and */
- ! &&(h == 0 || h == 24))) /* time matches, can pass. */
- ! return(0); /* ERR: HH conflicts */
- ! tp[TM_AMPM] = TMNULL; /* Always reset this value if won */
- ! return(1);
- }
-
- - /* Null routine for no-op tokens */
- -
- - ptnoise() { return(1); }
- -
- /* Get a token and identify it to some degree.
- * Returns 0 on failure; token.tval will be 0 for normal EOF, otherwise
- * hit error of some sort
- */
-
- ! ptitoken(astr, tkp)
- register struct token *tkp;
- - char *astr;
- {
- ! register char *cp;
- ! register int i;
-
- ! tkp->tval.tnum = 0;
- ! if(pttoken(astr,tkp) == 0)
- #ifdef DEBUG
- ! VOID printf("EOF\n");
- ! #endif DEBUG
- return(0);
- cp = tkp->tcp;
-
- #ifdef DEBUG
- ! i = cp[tkp->tcnt];
- ! cp[tkp->tcnt] = 0;
- ! VOID printf("Token: \"%s\" ",cp);
- ! cp[tkp->tcnt] = i;
- ! #endif DEBUG
- !
- ! if(tkp->tflg)
- ! for(i = tkp->tcnt; i > 0; i--)
- ! tkp->tval.tnum = (int)tkp->tval.tnum*10 + ((*cp++)-'0');
- ! else
- ! { i = ptmatchstr(cp, tkp->tcnt, tmwords);
- ! tkp->tval.tnum = i ? i : -1; /* Set -1 for error */
-
- #ifdef DEBUG
- ! if(!i) VOID printf("Not found!\n");
- ! #endif DEBUG
- !
- ! if(!i) return(0);
- }
-
- #ifdef DEBUG
- if(tkp->tflg)
- VOID printf("Val: %d.\n",tkp->tval.tnum);
- ! else VOID printf("Found: \"%s\", val: %d., type %d\n",
- tkp->tval.ttmw->went,tkp->tval.ttmw->wval,tkp->tval.ttmw->wtype);
- ! #endif DEBUG
-
- return(1);
- }
-
- /* Read token from input string into token structure */
- ! pttoken(astr,tkp)
- register struct token *tkp;
- - char *astr;
- {
- ! register char *cp;
- register int c;
-
- ! tkp->tcp = cp = astr;
- tkp->tbrkl = tkp->tbrk; /* Set "last break" */
- tkp->tcnt = tkp->tbrk = tkp->tflg = 0;
-
- while(c = *cp++)
- { switch(c)
- { case ' ': case '\t': /* Flush all whitespace */
- ! while((c = *cp++) && isspace(c));
- ! cp--; /* Drop thru to handle brk */
- case '(': case ')': /* Perhaps any non-alphanum */
- case '-': case ',': /* shd qualify as break? */
- case '/': case ':': case '.': /* Break chars */
- if(tkp->tcnt == 0) /* If no token yet */
- { tkp->tcp = cp; /* ignore the brk */
- --- 399,606 ----
- { ord = (ch == '.' ? 0 : 1); /* n/m = D/M or M/D */
- if(btoken.tbrk == ch) /* "NN-" */
- { if(btoken.tbrkl != ch)
- ! {
- ! atoken = btoken;
- ! atoken.tcnt++;
- ! if (ptitoken(&atoken)
- && atoken.tflg == 0
- && atoken.tval.ttmw->wtype == TM_MON)
- goto dd2;
- if(ord)goto mm2; else goto dd2; /* "NN-" */
- } /* "-NN-" */
- ! if (!given(atm->tm_mday)
- ! && given(atm->tm_year)) /* If "YYYY-NN-" */
- goto mm2; /* then always MM */
- if(ord)goto dd2; else goto mm2;
- }
- if(btoken.tbrkl == ch /* "-NN" */
- ! && given(ord ? atm->tm_mon : atm->tm_mday))
- ! if (!given(ord ? atm->tm_mday : atm->tm_mon)) /* MM/DD */
- if(ord)goto dd2; else goto mm2;
- }
-
- /* Now reduced to choice between HH and DD */
- ! if (given(atm->tm_hour)) goto dd2; /* Have hour? Assume day. */
- ! if (given(atm->tm_mday)) goto hh2; /* Have day? Assume hour. */
- ! if (given(atm->tm_mon)) goto dd2; /* Have month? Assume day. */
- if(i > 24) goto dd2; /* Impossible HH means DD */
- ! atoken = btoken;
- ! if (!ptitoken(&atoken)) /* Read ahead! */
- if(atoken.tval.tnum) return(0); /* ERR: bad token */
- else goto dd2; /* EOF, assume day. */
- ! if ( atoken.tflg
- ! ? !isdigit(*atoken.tcp)
- ! : atoken.tval.ttmw->wflgs & TWTIME)
- ! /* If next token is a time spec, assume hour */
- goto hh2; /* e.g. "3 PM", "11-EDT" */
-
- ! dd2: if (ptstash(&atm->tm_mday, i)) /* Store day (1 based) */
- return(0);
- ! continue;
-
- ! mm2: if (ptstash(&atm->tm_mon, i-1)) /* Store month (make zero based) */
- return(0);
- ! continue;
-
- ! year4: if ((i-=1900) < 0 || ptstash(&atm->tm_year, i)) /* Store year-1900 */
- return(0); /* ERR: year conflict */
- ! continue;
-
- /* Hack HH:MM[[:]SS] */
- coltime:
- ! if (ptstash(&atm->tm_hour, i)) return 0;
- ! if (!ptitoken(&btoken))
- return(!btoken.tval.tnum);
- if(!btoken.tflg) return(0); /* ERR: HH:<alpha> */
- if(btoken.tcnt == 4) /* MMSS */
- ! if (ptstash(&atm->tm_min, btoken.tval.tnum/100)
- ! || ptstash(&atm->tm_sec, btoken.tval.tnum%100))
- return(0);
- ! else continue;
- if(btoken.tcnt != 2
- ! || ptstash(&atm->tm_min, btoken.tval.tnum))
- return(0); /* ERR: MM bad */
- ! if (btoken.tbrk != ':') continue; /* Seconds follow? */
- ! coltm2: if (!ptitoken(&btoken))
- return(!btoken.tval.tnum);
- if(!btoken.tflg || btoken.tcnt != 2 /* Verify SS */
- ! || ptstash(&atm->tm_sec, btoken.tval.tnum))
- return(0); /* ERR: SS bad */
- ! }
- }
-
- /* Store date/time value, return 0 if successful.
- ! * Fail if entry is already set.
- */
- + static int
- ptstash(adr,val)
- int *adr;
- + int val;
- { register int *a;
- ! if (given(*(a=adr)))
- ! return 1;
- *a = val;
- return(0);
- }
-
- ! /* This subroutine is invoked for AM, PM, NOON and MIDNIGHT when wrapping up
- * just prior to returning from partime.
- */
- ! static int
- ! pt12hack(tm, aval)
- ! register struct tm *tm;
- ! register int aval;
- ! { register int h = tm->tm_hour;
- ! switch (aval) {
- ! case T12_AM:
- ! case T12_PM:
- ! if (h > 12)
- ! return 0;
- ! if (h == 12)
- ! tm->tm_hour = 0;
- ! if (aval == T12_PM)
- ! tm->tm_hour += 12;
- ! break;
- ! default:
- ! if (0 < tm->tm_min || 0 < tm->tm_sec)
- ! return 0;
- ! if (!given(h) || h==12)
- ! tm->tm_hour = aval;
- ! else if (aval==T12_MIDNIGHT && (h==0 || h==24))
- ! return 0;
- ! }
- ! return 1;
- }
-
- /* Get a token and identify it to some degree.
- * Returns 0 on failure; token.tval will be 0 for normal EOF, otherwise
- * hit error of some sort
- */
-
- ! static int
- ! ptitoken(tkp)
- register struct token *tkp;
- {
- ! register const char *cp;
- ! register int i, j, k;
-
- ! if (!pttoken(tkp))
- #ifdef DEBUG
- ! {
- ! VOID printf("EOF\n");
- ! return(0);
- ! }
- ! #else
- return(0);
- + #endif
- cp = tkp->tcp;
-
- #ifdef DEBUG
- ! VOID printf("Token: \"%.*s\" ", tkp->tcnt, cp);
- ! #endif
-
- + if (tkp->tflg) {
- + i = tkp->tcnt;
- + if (*cp == '+' || *cp == '-') {
- + cp++;
- + i--;
- + }
- + while (0 <= --i) {
- + j = tkp->tval.tnum*10;
- + k = j + (*cp++ - '0');
- + if (j/10 != tkp->tval.tnum || k < j) {
- + /* arithmetic overflow */
- + tkp->tval.tnum = 1;
- + return 0;
- + }
- + tkp->tval.tnum = k;
- + }
- + } else if (!(tkp->tval.ttmw = ptmatchstr(cp, tkp->tcnt, tmwords)))
- + {
- #ifdef DEBUG
- ! VOID printf("Not found!\n");
- ! #endif
- ! tkp->tval.tnum = 1;
- ! return 0;
- }
-
- #ifdef DEBUG
- if(tkp->tflg)
- VOID printf("Val: %d.\n",tkp->tval.tnum);
- ! else VOID printf("Found: \"%s\", val: %d, type %d\n",
- tkp->tval.ttmw->went,tkp->tval.ttmw->wval,tkp->tval.ttmw->wtype);
- ! #endif
-
- return(1);
- }
-
- /* Read token from input string into token structure */
- ! static int
- ! pttoken(tkp)
- register struct token *tkp;
- {
- ! register const char *cp;
- register int c;
- + const char *astr;
-
- ! tkp->tcp = astr = cp = tkp->tcp + tkp->tcnt;
- tkp->tbrkl = tkp->tbrk; /* Set "last break" */
- tkp->tcnt = tkp->tbrk = tkp->tflg = 0;
- + tkp->tval.tnum = 0;
-
- while(c = *cp++)
- { switch(c)
- { case ' ': case '\t': /* Flush all whitespace */
- ! case '\r': case '\n':
- ! case '\v': case '\f':
- ! if (!tkp->tcnt) { /* If no token yet */
- ! tkp->tcp = cp; /* ignore the brk */
- ! continue; /* and go on. */
- ! }
- ! /* fall into */
- case '(': case ')': /* Perhaps any non-alphanum */
- case '-': case ',': /* shd qualify as break? */
- + case '+':
- case '/': case ':': case '.': /* Break chars */
- if(tkp->tcnt == 0) /* If no token yet */
- { tkp->tcp = cp; /* ignore the brk */
- ***************
- *** 420,476 ****
- tkp->tbrk = c;
- return(tkp->tcnt);
- }
- ! if(tkp->tcnt == 0) /* If first char of token, */
- ! tkp->tflg = isdigit(c); /* determine type */
- ! if(( isdigit(c) && tkp->tflg) /* If not first, make sure */
- ! ||(!isdigit(c) && !tkp->tflg)) /* char matches type */
- ! tkp->tcnt++; /* Win, add to token. */
- ! else {
- ! cp--; /* Wrong type, back up */
- tkp->tbrk = c;
- ! return(tkp->tcnt);
- ! }
- }
- return(tkp->tcnt); /* When hit EOF */
- }
-
-
- ptmatchstr(astr,cnt,astruc)
- ! char *astr;
- ! int cnt;
- ! struct tmwent *astruc;
- ! { register char *cp, *mp;
- register int c;
- ! struct tmwent *lastptr;
- ! struct integ { int word; }; /* For getting at array ptr */
- int i;
-
- lastptr = 0;
- ! for(;mp = (char *)((struct integ *)astruc)->word; astruc += 1)
- { cp = astr;
- for(i = cnt; i > 0; i--)
- ! { switch((c = *cp++) ^ *mp++) /* XOR the chars */
- { case 0: continue; /* Exact match */
- ! case 040: if(isalpha(c))
- continue;
- }
- break;
- }
- if(i==0)
- ! if(*mp == 0) return((unsigned int)astruc); /* Exact match */
- else if(lastptr) return(0); /* Ambiguous */
- else lastptr = astruc; /* 1st ambig */
- }
- ! return((unsigned int)lastptr);
- ! }
- !
- !
- !
- ! zaptime(tp)
- ! register int *tp;
- ! /* clears tm structure pointed to by tp */
- ! { register int i;
- ! i = (sizeof (struct tm))/(sizeof (int));
- ! do *tp++ = TMNULL; /* Set entry to "unspecified" */
- ! while(--i); /* Faster than FOR */
- }
- --- 610,662 ----
- tkp->tbrk = c;
- return(tkp->tcnt);
- }
- ! if (!tkp->tcnt++) { /* If first char of token, */
- ! if (isdigit(c)) {
- ! tkp->tflg = 1;
- ! if (astr<cp-2 && (cp[-2]=='-'||cp[-2]=='+')) {
- ! /* timezone is break+sign+digit */
- ! tkp->tcp--;
- ! tkp->tcnt++;
- ! }
- ! }
- ! } else if ((isdigit(c)!=0) != tkp->tflg) { /* else check type */
- tkp->tbrk = c;
- ! return --tkp->tcnt; /* Wrong type, back up */
- ! }
- }
- return(tkp->tcnt); /* When hit EOF */
- }
-
-
- + static const struct tmwent *
- ptmatchstr(astr,cnt,astruc)
- ! const char *astr;
- ! int cnt;
- ! const struct tmwent *astruc;
- ! {
- ! register const char *cp, *mp;
- register int c;
- ! const struct tmwent *lastptr;
- int i;
-
- lastptr = 0;
- ! for(;mp = astruc->went; astruc += 1)
- { cp = astr;
- for(i = cnt; i > 0; i--)
- ! {
- ! switch (*cp++ - (c = *mp++))
- { case 0: continue; /* Exact match */
- ! case 'A'-'a':
- ! /* `if (ctab[c]==Letter)' in RCS */
- ! if (islower(c))
- continue;
- }
- break;
- }
- if(i==0)
- ! if (!*mp) return astruc; /* Exact match */
- else if(lastptr) return(0); /* Ambiguous */
- else lastptr = astruc; /* 1st ambig */
- }
- ! return lastptr;
- }
- diff -c src/patch.c:1.6 src/patch.c:1.6.1.1
- *** src/patch.c:1.6 Wed Feb 6 11:32:13 1991
- --- src/patch.c Wed Feb 6 11:32:14 1991
- ***************
- *** 1,5 ****
- #ifndef lint
- ! static char rcsid[] = "$Id: patch.c,v 1.6 90/02/14 10:01:33 berliner Exp $";
- #endif !lint
-
- /*
- --- 1,5 ----
- #ifndef lint
- ! static char rcsid[] = "$Id: patch.c,v 1.6.1.1 91/01/18 12:18:45 berliner Exp $";
- #endif !lint
-
- /*
- ***************
- *** 22,29 ****
- #include <ctype.h>
- #include "cvs.h"
-
- - extern long maketime();
- -
- extern char update_dir[];
- extern DBM *open_module();
- extern int force_tag_match;
- --- 22,27 ----
- ***************
- *** 106,112 ****
- error(0, "must specify at least one revision/date!");
- }
- if (date1[0] != '\0' && date2[0] != '\0') {
- ! if (strcmp(date1, date2) >= 0)
- error(0, "second date must come after first date!");
- }
- (void) signal(SIGHUP, patch_cleanup);
- --- 104,110 ----
- error(0, "must specify at least one revision/date!");
- }
- if (date1[0] != '\0' && date2[0] != '\0') {
- ! if (datecmp(date1, date2) >= 0)
- error(0, "second date must come after first date!");
- }
- (void) signal(SIGHUP, patch_cleanup);
- ***************
- *** 379,395 ****
- if (*cp && (semi = index(cp, ';')) != NULL) {
- ret = 0;
- *semi = '\0';
- ! ftm = &tm;
- ! zaptime((int *)ftm);
- ! (void) sscanf(cp, DATEFORM, &ftm->tm_year, &ftm->tm_mon,
- ! &ftm->tm_mday, &ftm->tm_hour, &ftm->tm_min,
- ! &ftm->tm_sec);
- ! ftm->tm_mon--;
- ! revdate = (time_t)maketime(ftm) - 1;
- ! ftm = localtime(&revdate);
- ! (void) sprintf(date, DATEFORM, ftm->tm_year, ftm->tm_mon+1,
- ! ftm->tm_mday, ftm->tm_hour, ftm->tm_min,
- ! ftm->tm_sec);
- }
- break;
- }
- --- 377,383 ----
- if (*cp && (semi = index(cp, ';')) != NULL) {
- ret = 0;
- *semi = '\0';
- ! semi[-1]--; /* This works even if semi[-1] was '0'. */
- }
- break;
- }
- diff -c src/patchlevel.h:1.1 src/patchlevel.h:1.1.1.1
- *** src/patchlevel.h:1.1 Wed Feb 6 11:32:12 1991
- --- src/patchlevel.h Wed Feb 6 11:32:12 1991
- ***************
- *** 1,3 ****
- ! /* $Id: patchlevel.h,v 1.1 89/11/20 00:06:30 berliner Exp $ */
-
- ! #define PATCHLEVEL 0
- --- 1,3 ----
- ! /* $Id: patchlevel.h,v 1.1.1.1 91/01/18 12:19:46 berliner Exp $ */
-
- ! #define PATCHLEVEL 2
- diff -c src/rcstime.h:1.1 src/rcstime.h:removed
- *** src/rcstime.h:1.1 Wed Feb 6 11:32:08 1991
- --- src/rcstime.h Wed Feb 6 11:32:08 1991
- ***************
- *** 1,42 ****
- - #define TIMEID "$Id: rcstime.h,v 1.1 89/05/09 11:51:03 berliner Exp $"
- -
- - /* Structure for use by time manipulating subroutines.
- - * The following library routines use it:
- - * libc: ctime, localtime, gmtime, asctime
- - * libcx: partime, maketime (may not be installed yet)
- - */
- -
- - struct tm { /* See defines below for allowable ranges */
- - int tm_sec;
- - int tm_min;
- - int tm_hour;
- - int tm_mday;
- - int tm_mon;
- - int tm_year;
- - int tm_wday;
- - int tm_yday;
- - int tm_isdst;
- - int tm_zon; /* NEW: mins westward of Greenwich */
- - int tm_ampm; /* NEW: 1 if AM, 2 if PM */
- - };
- -
- - #define LCLZONE (5*60) /* Until V7 ftime(2) works, this defines local zone*/
- - #define TMNULL (-1) /* Items not specified are given this value
- - * in order to distinguish null specs from zero
- - * specs. This is only used by partime and
- - * maketime. */
- -
- - /* Indices into TM structure */
- - #define TM_SEC 0 /* 0-59 */
- - #define TM_MIN 1 /* 0-59 */
- - #define TM_HOUR 2 /* 0-23 */
- - #define TM_MDAY 3 /* 1-31 day of month */
- - #define TM_DAY TM_MDAY /* " synonym */
- - #define TM_MON 4 /* 0-11 */
- - #define TM_YEAR 5 /* (year-1900) (year) */
- - #define TM_WDAY 6 /* 0-6 day of week (0 = Sunday) */
- - #define TM_YDAY 7 /* 0-365 day of year */
- - #define TM_ISDST 8 /* 0 Std, 1 DST */
- - /* New stuff */
- - #define TM_ZON 9 /* 0-(24*60) minutes west of Greenwich */
- - #define TM_AMPM 10 /* 1 AM, 2 PM */
- --- 0 ----
- diff -c src/subr.c:1.14 src/subr.c:1.14.1.2
- *** src/subr.c:1.14 Wed Feb 6 11:32:11 1991
- --- src/subr.c Wed Feb 6 11:32:11 1991
- ***************
- *** 1,5 ****
- #ifndef lint
- ! static char rcsid[] = "$Id: subr.c,v 1.14 89/11/20 09:51:10 berliner Exp $";
- #endif !lint
-
- /*
- --- 1,5 ----
- #ifndef lint
- ! static char rcsid[] = "$Id: subr.c,v 1.14.1.2 91/01/29 19:46:20 berliner Exp $";
- #endif !lint
-
- /*
- ***************
- *** 114,120 ****
-
- if (stat(file, &sb) < 0)
- return (0);
- ! return ((sb.st_mode & S_IFMT) & S_IFDIR);
- }
-
- /*
- --- 114,120 ----
-
- if (stat(file, &sb) < 0)
- return (0);
- ! return ((sb.st_mode & S_IFMT) == S_IFDIR);
- }
-
- /*
- ***************
- *** 125,133 ****
- {
- struct stat sb;
-
- if (lstat(file, &sb) < 0)
- return (0);
- ! return ((sb.st_mode & S_IFMT) & S_IFLNK);
- }
-
- /*
- --- 125,137 ----
- {
- struct stat sb;
-
- + #ifdef S_IFLNK
- if (lstat(file, &sb) < 0)
- return (0);
- ! return ((sb.st_mode & S_IFMT) == S_IFLNK);
- ! #else
- ! return (0);
- ! #endif
- }
-
- /*
- diff -c src/tag.c:1.19 src/tag.c:1.19.1.2
- *** src/tag.c:1.19 Wed Feb 6 11:32:10 1991
- --- src/tag.c Wed Feb 6 11:32:10 1991
- ***************
- *** 1,5 ****
- #ifndef lint
- ! static char rcsid[] = "$Id: tag.c,v 1.19 89/11/19 23:40:46 berliner Exp $";
- #endif !lint
-
- /*
- --- 1,5 ----
- #ifndef lint
- ! static char rcsid[] = "$Id: tag.c,v 1.19.1.2 91/01/29 19:45:54 berliner Exp $";
- #endif !lint
-
- /*
- ***************
- *** 180,185 ****
- --- 180,205 ----
- {
- char version[50];
-
- + #ifdef S_IFLNK
- + /*
- + * Ooops.. if there is a symbolic link in the source repository
- + * which points to a normal file, rcs will do its file renaming
- + * mumbo-jumbo and blow away the symbolic link; this is essentially
- + * like a copy-on-commit RCS revision control file, but I consider
- + * it a bug. Instead, read the contents of the link and recursively
- + * tag the link contents (which may be a symlink itself...).
- + */
- + if (islink(rcs) && isfile(rcs)) {
- + char link_name[MAXPATHLEN];
- + int count;
- +
- + if ((count = readlink(rcs, link_name, sizeof(link_name))) != -1) {
- + link_name[count] = '\0';
- + return (tag_file(link_name));
- + }
- + }
- + #endif
- +
- if (delete) {
- /*
- * If -d is specified, "force_tag_match" is set, so that this call
- ***************
- *** 210,220 ****
- }
- Version_Number(rcs, numtag, Date, version);
- if (version[0] == '\0') {
- ! if (!really_quiet) {
- warn(0, "cannot find tag '%s' for %s", numtag[0] ? numtag : "head",
- rcs);
- }
- ! return (1);
- }
- if (isdigit(numtag[0]) && strcmp(numtag, version) != 0) {
- /*
- --- 230,241 ----
- }
- Version_Number(rcs, numtag, Date, version);
- if (version[0] == '\0') {
- ! if (!quiet) {
- warn(0, "cannot find tag '%s' for %s", numtag[0] ? numtag : "head",
- rcs);
- + return (1);
- }
- ! return (0);
- }
- if (isdigit(numtag[0]) && strcmp(numtag, version) != 0) {
- /*
- diff -c src/update.c:1.27 src/update.c:1.27.1.2
- *** src/update.c:1.27 Wed Feb 6 11:32:16 1991
- --- src/update.c Wed Feb 6 11:32:16 1991
- ***************
- *** 1,5 ****
- #ifndef lint
- ! static char rcsid[] = "$Id: update.c,v 1.27 89/11/19 23:40:48 berliner Exp $";
- #endif !lint
-
- /*
- --- 1,5 ----
- #ifndef lint
- ! static char rcsid[] = "$Id: update.c,v 1.27.1.2 91/02/06 18:30:07 berliner Exp $";
- #endif !lint
-
- /*
- ***************
- *** 111,117 ****
- if (!isdir(CVSADM)) {
- if (!quiet)
- warn(0, "warning: no %s directory found", CVSADM);
- ! err += update_descend(update_recursive);
- return (err);
- }
- Name_Repository();
- --- 111,132 ----
- if (!isdir(CVSADM)) {
- if (!quiet)
- warn(0, "warning: no %s directory found", CVSADM);
- ! if (argc <= 0) {
- ! err += update_descend(update_recursive);
- ! } else {
- ! int i;
- !
- ! for (i = 0; i < argc; i++) {
- ! if (isdir(argv[i])) {
- ! (void) strcat(Dlist, " ");
- ! (void) strcat(Dlist, argv[i]);
- ! } else {
- ! warn(0, "nothing known about %s", argv[i]);
- ! err++;
- ! }
- ! }
- ! err += update_process_lists();
- ! }
- return (err);
- }
- Name_Repository();
- ***************
- *** 175,180 ****
- --- 190,196 ----
- update_Files = 1;
- (void) strcpy(User, cp);
- Scratch_Entry(User);
- + (void) unlink(User);
- }
- /*
- * Olist is the "needs checking out" list.
- ***************
- *** 349,359 ****
- strcmp(dp->d_name, CVSLCK) == 0)
- continue;
- (void) sprintf(fname, "%s/%s", Repository, dp->d_name);
- if (!isdir(fname))
- continue;
- ! if (isdir(dp->d_name))
- continue;
- ! if (isfile(dp->d_name)) {
- warn(0, "file %s should be a directory; please move it", dp->d_name);
- err++;
- } else {
- --- 365,376 ----
- strcmp(dp->d_name, CVSLCK) == 0)
- continue;
- (void) sprintf(fname, "%s/%s", Repository, dp->d_name);
- + (void) sprintf(tmp, "%s/%s", dp->d_name, CVSADM);
- if (!isdir(fname))
- continue;
- ! if (islink(dp->d_name) || isdir(tmp))
- continue;
- ! if (!isdir(dp->d_name) && isfile(dp->d_name)) {
- warn(0, "file %s should be a directory; please move it", dp->d_name);
- err++;
- } else {
- diff -c src/version_number.c:1.16 src/version_number.c:1.16.1.2
- *** src/version_number.c:1.16 Wed Feb 6 11:32:09 1991
- --- src/version_number.c Wed Feb 6 11:32:09 1991
- ***************
- *** 1,5 ****
- #ifndef lint
- ! static char rcsid[] = "$Id: version_number.c,v 1.16 89/11/19 23:20:35 berliner Exp $";
- #endif !lint
-
- /*
- --- 1,5 ----
- #ifndef lint
- ! static char rcsid[] = "$Id: version_number.c,v 1.16.1.2 91/01/29 07:20:26 berliner Exp $";
- #endif !lint
-
- /*
- ***************
- *** 67,72 ****
- --- 67,73 ----
- (void) strcpy(vers, rev);
- }
- } else {
- + if (!force_tag_match)
- (void) strcpy(vers, rev);
- }
- }
- ***************
- *** 100,105 ****
- --- 101,107 ----
- if (fgets(line, sizeof(line), fp) == NULL)
- return;
- if (strncmp(line, RCSHEAD, sizeof(RCSHEAD) - 1) != 0 ||
- + !isspace(line[sizeof(RCSHEAD) - 1]) ||
- (cp = rindex(line, ';')) == NULL)
- return;
- *cp = '\0'; /* strip the ';' */
- ***************
- *** 119,124 ****
- --- 121,127 ----
- if (fgets(line, sizeof(line), fp) == NULL)
- return;
- if (strncmp(line, RCSBRANCH, sizeof(RCSBRANCH) - 1) == 0 &&
- + isspace(line[sizeof(RCSBRANCH) - 1]) &&
- (cp = rindex(line, ';')) != NULL) {
- *cp = '\0'; /* strip the ';' */
- if ((cp = rindex(line, ' ')) == NULL &&
- ***************
- *** 149,156 ****
- * the highest numbered branch off "rev", if necessary.
- */
- get_branch(fp, rev);
- ! if (tag[0] == '\0' || isdigit(tag[0]) || symtag_matched < 0)
- ! (void) strcpy(vers, rev);
- }
-
- /*
- --- 152,161 ----
- * the highest numbered branch off "rev", if necessary.
- */
- get_branch(fp, rev);
- ! if (tag[0] == '\0' || isdigit(tag[0]) || symtag_matched < 0) {
- ! if ((numdots(rev) & 1) != 0)
- ! (void) strcpy(vers, rev);
- ! }
- }
-
- /*
- ***************
- *** 172,196 ****
- char *rev;
- char *vers;
- {
- ! char line[MAXLINELEN], tagdot[50];
- char *cp, *cprev;
- - int tagdots, tagdotlen;
-
- if (isdigit(tag[0])) {
- ! while (tag[strlen(tag)] == '.')
- ! tag[strlen(tag)] = '\0'; /* strip trailing dots */
- ! (void) sprintf(tagdot, "%s.", tag);
- ! tagdotlen = strlen(tagdot);
- ! tagdots = numdots(tag);
- }
- while (fgets(line, sizeof(line), fp) != NULL) {
- if (strncmp(line, RCSDESC, sizeof(RCSDESC) - 1) == 0) {
- - /*
- - * Use head, or a partial branch match found with the strncmp
- - * call with tagdot below
- - */
- rewind(fp);
- ! return (1);
- }
- /*
- * For numeric tags, the RCS file contains the revision
- --- 177,197 ----
- char *rev;
- char *vers;
- {
- ! char line[MAXLINELEN];
- char *cp, *cprev;
-
- if (isdigit(tag[0])) {
- ! while (tag[strlen(tag)-1] == '.')
- ! tag[strlen(tag)-1] = '\0'; /* strip trailing dots */
- ! if ((numdots(tag) & 1) == 0) {
- ! (void) strcpy(rev, tag);
- ! return (1); /* let get_branch() figure it out */
- ! }
- }
- while (fgets(line, sizeof(line), fp) != NULL) {
- if (strncmp(line, RCSDESC, sizeof(RCSDESC) - 1) == 0) {
- rewind(fp);
- ! return (1); /* use head */
- }
- /*
- * For numeric tags, the RCS file contains the revision
- ***************
- *** 204,221 ****
- (void) strcpy(vers, line);
- return (0); /* a match for a numeric tag */
- }
- - if (strncmp(tagdot, line, tagdotlen) == 0) {
- - if ((tagdots & 1) == 0 && numdots(line) == tagdots+1)
- - (void) strcpy(rev, line);
- - }
- continue;
- }
- if (strncmp(line, RCSSYMBOL, sizeof(RCSSYMBOL)-1)!=0 ||
- ! (cp = rindex(line, ';')) == NULL)
- ! continue;
- ! *cp = ' '; /* strip the ';' */
- ! if ((cp = index(line, ' ')) == NULL &&
- ! (cp = index(line, '\t')) == NULL)
- continue;
- /*
- * A rather ugly loop to process the "symbols" line. I would
- --- 205,214 ----
- (void) strcpy(vers, line);
- return (0); /* a match for a numeric tag */
- }
- continue;
- }
- if (strncmp(line, RCSSYMBOL, sizeof(RCSSYMBOL)-1)!=0 ||
- ! !isspace(line[sizeof(RCSSYMBOL) - 1]))
- continue;
- /*
- * A rather ugly loop to process the "symbols" line. I would
- ***************
- *** 222,233 ****
- * really rather use strtok(), but other above me already are,
- * and strtok() blows up in this case.
- */
- ! while (cp && *cp) {
- while (isspace(*cp))
- cp++;
- /* symbols and revisions are separated by a colon */
- if ((cprev = index(cp, ':')) == NULL) {
- ! while (*cp && !isspace(*cp))
- cp++;
- continue;
- }
- --- 215,234 ----
- * really rather use strtok(), but other above me already are,
- * and strtok() blows up in this case.
- */
- ! for (cp = line + sizeof(RCSSYMBOL); cp; ) {
- while (isspace(*cp))
- cp++;
- + if (*cp == ';')
- + break;
- + if (!*cp) {
- + if (fgets(line, sizeof(line), fp) == NULL)
- + return 0;
- + cp = line;
- + continue;
- + }
- /* symbols and revisions are separated by a colon */
- if ((cprev = index(cp, ':')) == NULL) {
- ! while (*cp && !isspace(*cp) && *cp!=';')
- cp++;
- continue;
- }
- ***************
- *** 245,253 ****
- (void) strcpy(rev, cprev);
- return (-1); /* look for branches off rev */
- } else {
- ! while (!isspace(*cp))
- cp++;
- - cp++;
- }
- }
- return (1);
- --- 246,253 ----
- (void) strcpy(rev, cprev);
- return (-1); /* look for branches off rev */
- } else {
- ! while (!isspace(*cp) && *cp!=';')
- cp++;
- }
- }
- return (1);
- ***************
- *** 282,288 ****
- *cp = '\0'; /* strip the newline */
- if (numdots(line) == dots+1 &&
- strncmp(line, branch, len) == 0) {
- ! if (strcmp(branch, line) <= 0)
- (void) strcpy(rev, line);
- }
- }
- --- 282,288 ----
- *cp = '\0'; /* strip the newline */
- if (numdots(line) == dots+1 &&
- strncmp(line, branch, len) == 0) {
- ! if ((numdots(rev) & 1) == 0 || strcmp(rev, line) <= 0)
- (void) strcpy(rev, line);
- }
- }
- ***************
- *** 342,348 ****
- char *cp, *semi;
-
- last_rev[0] = '\0';
- ! (void) strcpy(curdate, "00"); /* what happens at 2000 ad? */
- (void) sprintf(date_dot, "%s.", rev);
- date_dotlen = strlen(date_dot);
- date_dots = numdots(rev);
- --- 342,348 ----
- char *cp, *semi;
-
- last_rev[0] = '\0';
- ! curdate[0] = '\0';
- (void) sprintf(date_dot, "%s.", rev);
- date_dotlen = strlen(date_dot);
- date_dots = numdots(rev);
- ***************
- *** 360,365 ****
- --- 360,366 ----
- continue;
- }
- if (strncmp(line, RCSDATE, sizeof(RCSDATE) - 1) == 0 &&
- + isspace(line[sizeof(RCSDATE) - 1]) &&
- last_rev[0] != '\0') {
- for (cp = line; *cp && !isspace(*cp); cp++)
- ;
- ***************
- *** 367,373 ****
- cp++;
- if (*cp && (semi = index(cp, ';')) != NULL) {
- *semi = '\0'; /* strip the semicolon */
- ! if (strcmp(cp, date) <= 0 && strcmp(cp, curdate) >= 0) {
- (void) strcpy(curdate, cp);
- (void) strcpy(version, last_rev);
- }
- --- 368,374 ----
- cp++;
- if (*cp && (semi = index(cp, ';')) != NULL) {
- *semi = '\0'; /* strip the semicolon */
- ! if (datecmp(cp, date) <= 0 && datecmp(cp, curdate) >= 0) {
- (void) strcpy(curdate, cp);
- (void) strcpy(version, last_rev);
- }
- ***************
- *** 374,377 ****
- --- 375,391 ----
- }
- }
- }
- + }
- +
- + /*
- + * Compare two dates in RCS format.
- + * Beware the change in format on January 1, 2000,
- + * when years go from 2-digit to full format.
- + */
- + int
- + datecmp(date1, date2)
- + char *date1, *date2;
- + {
- + int length_diff = strlen(date1) - strlen(date2);
- + return length_diff ? length_diff : strcmp(date1, date2);
- }
-
-