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