rsalz@bbn.com (Rich Salz) (02/26/91)
Submitted-by: Brian Berliner <berliner@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@uunet.uu.net if you want that tool. # Contents: Patch02.02 # Wrapped by rsalz@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@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.