summaryrefslogtreecommitdiffstats
path: root/gnu
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1995-10-28 21:50:58 +0000
committerpeter <peter@FreeBSD.org>1995-10-28 21:50:58 +0000
commit822bceb624e3740412b90941feb1158d82f50edc (patch)
tree5072ccf03f140b698e07703cd04f14e6e4d75591 /gnu
parent9d7e3d8dc0cccad8e42e4822ffa52ee28b6f7d2f (diff)
downloadFreeBSD-src-822bceb624e3740412b90941feb1158d82f50edc.zip
FreeBSD-src-822bceb624e3740412b90941feb1158d82f50edc.tar.gz
First part of import conflict merge from rcs-5.7 import.
All those $Log$ entries, combined with the whitespace changes are a real pain. I'm committing this now, before it's completely finished to get it compiling and working again ASAP. Some of the FreeBSD specific features are not working in this commit yet (mainly rlog stuff and $FreeBSD$ support)
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/rcs/ci/ci.c583
-rw-r--r--gnu/usr.bin/rcs/co/co.1293
-rw-r--r--gnu/usr.bin/rcs/co/co.c366
-rw-r--r--gnu/usr.bin/rcs/ident/ident.c160
-rw-r--r--gnu/usr.bin/rcs/lib/Makefile4
-rw-r--r--gnu/usr.bin/rcs/lib/conf.h373
-rw-r--r--gnu/usr.bin/rcs/lib/maketime.c607
-rw-r--r--gnu/usr.bin/rcs/lib/merger.c2
-rw-r--r--gnu/usr.bin/rcs/lib/partime.c1253
-rw-r--r--gnu/usr.bin/rcs/lib/rcsbase.h337
-rw-r--r--gnu/usr.bin/rcs/lib/rcsedit.c997
-rw-r--r--gnu/usr.bin/rcs/lib/rcsfcmp.c115
-rw-r--r--gnu/usr.bin/rcs/lib/rcsfnms.c612
-rw-r--r--gnu/usr.bin/rcs/lib/rcsgen.c321
-rw-r--r--gnu/usr.bin/rcs/lib/rcskeep.c187
-rw-r--r--gnu/usr.bin/rcs/lib/rcskeys.c86
-rw-r--r--gnu/usr.bin/rcs/lib/rcslex.c829
-rw-r--r--gnu/usr.bin/rcs/lib/rcsrev.c479
-rw-r--r--gnu/usr.bin/rcs/lib/rcssyn.c408
-rw-r--r--gnu/usr.bin/rcs/lib/rcsutil.c833
-rw-r--r--gnu/usr.bin/rcs/rcs/rcs.c875
-rw-r--r--gnu/usr.bin/rcs/rcsdiff/rcsdiff.c240
-rw-r--r--gnu/usr.bin/rcs/rcsmerge/rcsmerge.c202
-rw-r--r--gnu/usr.bin/rcs/rlog/rlog.188
-rw-r--r--gnu/usr.bin/rcs/rlog/rlog.c481
25 files changed, 6301 insertions, 4430 deletions
diff --git a/gnu/usr.bin/rcs/ci/ci.c b/gnu/usr.bin/rcs/ci/ci.c
index 3d2e6f7..506f007 100644
--- a/gnu/usr.bin/rcs/ci/ci.c
+++ b/gnu/usr.bin/rcs/ci/ci.c
@@ -1,5 +1,7 @@
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Check in revisions of RCS files from working files. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -15,8 +17,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -25,18 +28,49 @@ Report problems and direct all questions to:
*/
/*
- * RCS checkin operation
- */
-/*******************************************************************
- * check revisions into RCS files
- *******************************************************************
- */
-
-
-
-/* $Log: ci.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:10 jkh
- * Updated GNU utilities
+ * $Log: ci.c,v $
+ * Revision 5.30 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.29 1995/06/01 16:23:43 eggert
+ * (main): Add -kb.
+ * Use `cmpdate', not `cmpnum', to compare dates.
+ * This is for MKS RCS's incompatible 20th-century date format.
+ * Don't worry about errno after ftruncate fails.
+ * Fix input file rewinding bug when large_memory && !maps_memory
+ * and checking in a branch tip.
+ *
+ * (fixwork): Fall back on chmod if fchmod fails, since it might be ENOSYS.
+ *
+ * Revision 5.28 1994/03/20 04:52:58 eggert
+ * Do not generate a corrupted RCS file if the user modifies the working file
+ * while `ci' is running.
+ * Do not remove the lock when `ci -l' reverts.
+ * Move buffer-flushes out of critical sections, since they aren't critical.
+ * Use ORCSerror to clean up after a fatal error.
+ * Specify subprocess input via file descriptor, not file name.
+ *
+ * Revision 5.27 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits. Don't print usage twice.
+ *
+ * Revision 5.26 1993/11/03 17:42:27 eggert
+ * Add -z. Don't subtract from RCS file timestamp even if -T.
+ * Scan for and use Name keyword if -k.
+ * Don't discard ignored phrases. Improve quality of diagnostics.
+ *
+ * Revision 5.25 1992/07/28 16:12:44 eggert
+ * Add -i, -j, -V. Check that working and RCS files are distinct.
+ *
+ * Revision 5.24 1992/02/17 23:02:06 eggert
+ * `-rREV' now just specifies a revision REV; only bare `-r' reverts to default.
+ * Add -T.
+ *
+ * Revision 5.23 1992/01/27 16:42:51 eggert
+ * Always unlock branchpoint if caller has a lock.
+ * Add support for bad_chmod_close, bad_creat0. lint -> RCS_lint
+ *
+ * Revision 5.22 1992/01/06 02:42:34 eggert
+ * Invoke utime() before chmod() to keep some buggy systems happy.
*
* Revision 5.21 1991/11/20 17:58:07 eggert
* Don't read the delta tree from a nonexistent RCS file.
@@ -217,16 +251,16 @@ struct Symrev {
};
static char const *getcurdate P((void));
-static int addbranch P((struct hshentry*,struct buf*));
+static int addbranch P((struct hshentry*,struct buf*,int));
static int addelta P((void));
static int addsyms P((char const*));
-static int fixwork P((mode_t,char const*));
+static int fixwork P((mode_t,time_t));
static int removelock P((struct hshentry*));
-static int xpandfile P((RILE*,char const*,struct hshentry const*,char const**));
+static int xpandfile P((RILE*,struct hshentry const*,char const**,int));
static struct cbuf getlogmsg P((void));
static void cleanup P((void));
static void incnum P((char const*,struct buf*));
-static void addassoclst P((int, char *));
+static void addassoclst P((int,char const*));
static FILE *exfile;
static RILE *workptr; /* working file pointer */
@@ -239,37 +273,41 @@ static struct hshentries *gendeltas; /* deltas to be generated */
static struct hshentry *targetdelta; /* old delta to be generated */
static struct hshentry newdelta; /* new delta to be inserted */
static struct stat workstat;
-static struct Symrev *assoclst, *lastassoc;
+static struct Symrev *assoclst, **nextassoc;
-mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
+mainProg(ciId, "ci", "$Id: ci.c,v 5.30 1995/06/16 06:19:24 eggert Exp $")
{
static char const cmdusage[] =
- "\nci usage: ci -{fklqru}[rev] -mmsg -{nN}name -sstate -t[textfile] -Vn file ...";
+ "\nci usage: ci -{fIklMqru}[rev] -d[date] -mmsg -{nN}name -sstate -ttext -T -Vn -wwho -xsuff -zzone file ...";
static char const default_state[] = DEFAULTSTATE;
char altdate[datesize];
char olddate[datesize];
- char newdatebuf[datesize], targetdatebuf[datesize];
+ char newdatebuf[datesize + zonelenmax];
+ char targetdatebuf[datesize + zonelenmax];
char *a, **newargv, *textfile;
char const *author, *krev, *rev, *state;
- char const *diffilename, *expfilename;
- char const *workdiffname, *newworkfilename;
- char const *mtime;
- int lockflag, lockthis, mtimeflag, removedlock;
+ char const *diffname, *expname;
+ char const *newworkname;
+ int initflag, mustread;
+ int lockflag, lockthis, mtimeflag, removedlock, Ttimeflag;
int r;
- int changedRCS, changework, newhead;
+ int changedRCS, changework, dolog, newhead;
int usestatdate; /* Use mod time of file for -d. */
mode_t newworkmode; /* mode for working file */
+ time_t mtime, wtime;
struct hshentry *workdelta;
setrid();
- author = rev = state = textfile = nil;
- lockflag = false;
+ author = rev = state = textfile = 0;
+ initflag = lockflag = mustread = false;
mtimeflag = false;
+ Ttimeflag = false;
altdate[0]= '\0'; /* empty alternate date for -d */
usestatdate=false;
suffixes = X_DEFAULT;
+ nextassoc = &assoclst;
argc = getRCSINIT(argc, argv, &newargv);
argv = newargv;
@@ -277,7 +315,13 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
switch (*a++) {
case 'r':
+ if (*a)
+ goto revno;
keepworkingfile = lockflag = false;
+ break;
+
+ case 'l':
+ keepworkingfile = lockflag = true;
revno:
if (*a) {
if (rev) warn("redefinition of revision number");
@@ -285,14 +329,18 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
}
break;
- case 'l':
- keepworkingfile=lockflag=true;
- goto revno;
-
case 'u':
keepworkingfile=true; lockflag=false;
goto revno;
+ case 'i':
+ initflag = true;
+ goto revno;
+
+ case 'j':
+ mustread = true;
+ goto revno;
+
case 'I':
interactiveflag = true;
goto revno;
@@ -313,7 +361,7 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
if (msg.size) redefined('m');
msg = cleanlogmsg(a, strlen(a));
if (!msg.size)
- warn("missing message for -m option");
+ error("missing message for -m option");
break;
case 'n':
@@ -321,7 +369,7 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
error("missing symbolic name after -n");
break;
}
- checksid(a);
+ checkssym(a);
addassoclst(false, a);
break;
@@ -330,7 +378,7 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
error("missing symbolic name after -N");
break;
}
- checksid(a);
+ checkssym(a);
addassoclst(true, a);
break;
@@ -340,7 +388,7 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
checksid(a);
state = a;
} else
- warn("missing state for -s option");
+ error("missing state for -s option");
break;
case 't':
@@ -353,7 +401,7 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
case 'd':
if (altdate[0] || usestatdate)
redefined('d');
- altdate[0] = 0;
+ altdate[0] = '\0';
if (!(usestatdate = !*a))
str2date(a, altdate);
break;
@@ -368,7 +416,7 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
checksid(a);
author = a;
} else
- warn("missing author for -w option");
+ error("missing author for -w option");
break;
case 'x':
@@ -379,26 +427,34 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
setRCSversion(*argv);
break;
+ case 'z':
+ zone_set(a);
+ break;
-
+ case 'T':
+ if (!*a) {
+ Ttimeflag = true;
+ break;
+ }
+ /* fall into */
default:
- faterror("unknown option: %s%s", *argv, cmdusage);
+ error("unknown option: %s%s", *argv, cmdusage);
};
} /* end processing of options */
- if (argc<1) faterror("no input file%s", cmdusage);
-
- /* now handle all filenames */
- do {
- targetdelta=nil;
+ /* Handle all pathnames. */
+ if (nerror) cleanup();
+ else if (argc < 1) faterror("no input file%s", cmdusage);
+ else for (; 0 < argc; cleanup(), ++argv, --argc) {
+ targetdelta = 0;
ffree();
- switch (pairfilenames(argc, argv, rcswriteopen, false, false)) {
+ switch (pairnames(argc, argv, rcswriteopen, mustread, false)) {
case -1: /* New RCS file */
# if has_setuid && has_getuid
if (euid() != ruid()) {
- error("setuid initial checkin prohibited; use `rcs -i -a' first");
+ workerror("setuid initial checkin prohibited; use `rcs -i -a' first");
continue;
}
# endif
@@ -409,38 +465,52 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
continue;
case 1: /* Normal checkin with prev . RCS file */
+ if (initflag) {
+ rcserror("already exists");
+ continue;
+ }
rcsinitflag = !Head;
}
- /* now RCSfilename contains the name of the RCS file, and
- * workfilename contains the name of the working file.
+ /*
+ * RCSname contains the name of the RCS file, and
+ * workname contains the name of the working file.
* If the RCS file exists, finptr contains the file descriptor for the
- * RCS file. The admin node is initialized.
- * RCSstat is set.
+ * RCS file, and RCSstat is set. The admin node is initialized.
*/
- diagnose("%s <-- %s\n", RCSfilename,workfilename);
+ diagnose("%s <-- %s\n", RCSname, workname);
- if (!(workptr = Iopen(workfilename, FOPEN_R_WORK, &workstat))) {
- eerror(workfilename);
+ if (!(workptr = Iopen(workname, FOPEN_R_WORK, &workstat))) {
+ eerror(workname);
continue;
}
- if (finptr && !checkaccesslist()) continue; /* give up */
+
+ if (finptr) {
+ if (same_file(RCSstat, workstat, 0)) {
+ rcserror("RCS file is the same as working file %s.",
+ workname
+ );
+ continue;
+ }
+ if (!checkaccesslist())
+ continue;
+ }
krev = rev;
if (keepflag) {
/* get keyword values from working file */
if (!getoldkeys(workptr)) continue;
if (!rev && !*(krev = prevrev.string)) {
- error("can't find a revision number in %s",workfilename);
+ workerror("can't find a revision number");
continue;
}
if (!*prevdate.string && *altdate=='\0' && usestatdate==false)
- warn("can't find a date in %s", workfilename);
+ workwarn("can't find a date");
if (!*prevauthor.string && !author)
- warn("can't find an author in %s", workfilename);
+ workwarn("can't find an author");
if (!*prevstate.string && !state)
- warn("can't find a state in %s", workfilename);
+ workwarn("can't find a state");
} /* end processing keepflag */
/* Read the delta tree. */
@@ -456,17 +526,20 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
continue;
newdelta.num = newdelnum.string;
- newdelta.branches=nil;
- newdelta.lockedby=nil; /*might be changed by addlock() */
+ newdelta.branches = 0;
+ newdelta.lockedby = 0; /* This might be changed by addlock(). */
newdelta.selector = true;
+ newdelta.name = 0;
+ clear_buf(&newdelta.ig);
+ clear_buf(&newdelta.igtext);
/* set author */
- if (author!=nil)
+ if (author)
newdelta.author=author; /* set author given by -w */
else if (keepflag && *prevauthor.string)
newdelta.author=prevauthor.string; /* preserve old author if possible*/
else newdelta.author=getcaller();/* otherwise use caller's id */
newdelta.state = default_state;
- if (state!=nil)
+ if (state)
newdelta.state=state; /* set state given by -s */
else if (keepflag && *prevstate.string)
newdelta.state=prevstate.string; /* preserve old state if possible */
@@ -482,9 +555,9 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
} else
newdelta.date = getcurdate(); /* use current date */
/* now check validity of date -- needed because of -d and -k */
- if (targetdelta!=nil &&
- cmpnum(newdelta.date,targetdelta->date) < 0) {
- error("Date %s precedes %s in existing revision %s.",
+ if (targetdelta &&
+ cmpdate(newdelta.date,targetdelta->date) < 0) {
+ rcserror("Date %s precedes %s in revision %s.",
date2str(newdelta.date, newdatebuf),
date2str(targetdelta->date, targetdatebuf),
targetdelta->num
@@ -493,48 +566,46 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
}
- if (lockflag && addlock(&newdelta) < 0) continue;
+ if (lockflag && addlock(&newdelta, true) < 0) continue;
+
+ if (keepflag && *prevname.string)
+ if (addsymbol(newdelta.num, prevname.string, false) < 0)
+ continue;
if (!addsyms(newdelta.num))
continue;
- putadmin(frewrite);
+ putadmin();
puttree(Head,frewrite);
putdesc(false,textfile);
- changework = Expand != OLD_EXPAND;
+ changework = Expand < MIN_UNCHANGED_EXPAND;
+ dolog = true;
lockthis = lockflag;
workdelta = &newdelta;
/* build rest of file */
if (rcsinitflag) {
- diagnose("initial revision: %s\n", newdelnum.string);
+ diagnose("initial revision: %s\n", newdelta.num);
/* get logmessage */
newdelta.log=getlogmsg();
- if (!putdftext(newdelnum.string,newdelta.log,workptr,frewrite,false)) continue;
+ putdftext(&newdelta, workptr, frewrite, false);
RCSstat.st_mode = workstat.st_mode;
+ RCSstat.st_nlink = 0;
changedRCS = true;
} else {
- diffilename = maketemp(0);
- workdiffname = workfilename;
- if (workdiffname[0] == '+') {
- /* Some diffs have options with leading '+'. */
- char *dp = ftnalloc(char, strlen(workfilename)+3);
- workdiffname = dp;
- *dp++ = '.';
- *dp++ = SLASH;
- VOID strcpy(dp, workfilename);
- }
+ diffname = maketemp(0);
newhead = Head == &newdelta;
if (!newhead)
foutptr = frewrite;
- expfilename = buildrevision(
+ expname = buildrevision(
gendeltas, targetdelta, (FILE*)0, false
);
if (
!forceciflag &&
+ strcmp(newdelta.state, targetdelta->state) == 0 &&
(changework = rcsfcmp(
- workptr, &workstat, expfilename, targetdelta
+ workptr, &workstat, expname, targetdelta
)) <= 0
) {
diagnose("file is unchanged; reverting to previous revision %s\n",
@@ -544,12 +615,8 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
diagnose("previous revision was not locked; ignoring -l option\n");
lockthis = 0;
}
- if (!(changedRCS =
- lockflag < removedlock
- || assoclst
- || newdelta.state != default_state
- && strcmp(newdelta.state, targetdelta->state) != 0
- ))
+ dolog = false;
+ if (! (changedRCS = lockflag<removedlock || assoclst))
workdelta = targetdelta;
else {
/*
@@ -558,20 +625,22 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
*/
long hwm = ftell(frewrite);
int bad_truncate;
- if (fseek(frewrite, 0L, SEEK_SET) != 0)
- Oerror();
+ Orewind(frewrite);
+
+ /*
+ * Work around a common ftruncate() bug:
+ * NFS won't let you truncate a file that you
+ * currently lack permissions for, even if you
+ * had permissions when you opened it.
+ * Also, Posix 1003.1b-1993 sec 5.6.7.2 p 128 l 1022
+ * says ftruncate might fail because it's not supported.
+ */
# if !has_ftruncate
- bad_truncate = 1;
-# else
- /*
- * Work around a common ftruncate() bug.
- * We can't rely on has_truncate, because we might
- * be using a filesystem exported to us via NFS.
- */
- bad_truncate = ftruncate(fileno(frewrite),(off_t)0);
- if (bad_truncate && errno != EACCES)
- Oerror();
+# undef ftruncate
+# define ftruncate(fd,length) (-1)
# endif
+ bad_truncate = ftruncate(fileno(frewrite), (off_t)0);
+
Irewind(finptr);
Lexinit();
getadmin();
@@ -584,11 +653,11 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
workdelta->log = targetdelta->log;
if (newdelta.state != default_state)
workdelta->state = newdelta.state;
- if (removedlock && removelock(workdelta)<0)
+ if (lockthis<removedlock && removelock(workdelta)<0)
continue;
if (!addsyms(workdelta->num))
continue;
- if (!dorewrite(true, true))
+ if (dorewrite(true, true) != 0)
continue;
fastcopy(finptr, frewrite);
if (bad_truncate)
@@ -598,48 +667,127 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
afputc('\n', frewrite);
}
} else {
+ int wfd = Ifileno(workptr);
+ struct stat checkworkstat;
+ char const *diffv[6 + !!OPEN_O_BINARY], **diffp;
+# if large_memory && !maps_memory
+ FILE *wfile = workptr->stream;
+ long wfile_off;
+# endif
+# if !has_fflush_input && !(large_memory && maps_memory)
+ off_t wfd_off;
+# endif
+
diagnose("new revision: %s; previous revision: %s\n",
- newdelnum.string, targetdelta->num
+ newdelta.num, targetdelta->num
);
newdelta.log = getlogmsg();
- switch (run((char*)0, diffilename,
- DIFF DIFF_FLAGS,
- newhead ? workdiffname : expfilename,
- newhead ? expfilename : workdiffname,
- (char*)0
- )) {
+# if !large_memory
+ Irewind(workptr);
+# if has_fflush_input
+ if (fflush(workptr) != 0)
+ Ierror();
+# endif
+# else
+# if !maps_memory
+ if (
+ (wfile_off = ftell(wfile)) == -1
+ || fseek(wfile, 0L, SEEK_SET) != 0
+# if has_fflush_input
+ || fflush(wfile) != 0
+# endif
+ )
+ Ierror();
+# endif
+# endif
+# if !has_fflush_input && !(large_memory && maps_memory)
+ wfd_off = lseek(wfd, (off_t)0, SEEK_CUR);
+ if (wfd_off == -1
+ || (wfd_off != 0
+ && lseek(wfd, (off_t)0, SEEK_SET) != 0))
+ Ierror();
+# endif
+ diffp = diffv;
+ *++diffp = DIFF;
+ *++diffp = DIFFFLAGS;
+# if OPEN_O_BINARY
+ if (Expand == BINARY_EXPAND)
+ *++diffp = "--binary";
+# endif
+ *++diffp = newhead ? "-" : expname;
+ *++diffp = newhead ? expname : "-";
+ *++diffp = 0;
+ switch (runv(wfd, diffname, diffv)) {
case DIFF_FAILURE: case DIFF_SUCCESS: break;
- default: faterror("diff failed");
+ default: rcsfaterror("diff failed");
}
+# if !has_fflush_input && !(large_memory && maps_memory)
+ if (lseek(wfd, wfd_off, SEEK_CUR) == -1)
+ Ierror();
+# endif
+# if large_memory && !maps_memory
+ if (fseek(wfile, wfile_off, SEEK_SET) != 0)
+ Ierror();
+# endif
if (newhead) {
Irewind(workptr);
- if (!putdftext(newdelnum.string,newdelta.log,workptr,frewrite,false)) continue;
- if (!putdtext(targetdelta->num,targetdelta->log,diffilename,frewrite,true)) continue;
+ putdftext(&newdelta, workptr, frewrite, false);
+ if (!putdtext(targetdelta,diffname,frewrite,true)) continue;
} else
- if (!putdtext(newdelnum.string,newdelta.log,diffilename,frewrite,true)) continue;
+ if (!putdtext(&newdelta,diffname,frewrite,true)) continue;
+
+ /*
+ * Check whether the working file changed during checkin,
+ * to avoid producing an inconsistent RCS file.
+ */
+ if (
+ fstat(wfd, &checkworkstat) != 0
+ || workstat.st_mtime != checkworkstat.st_mtime
+ || workstat.st_size != checkworkstat.st_size
+ ) {
+ workerror("file changed during checkin");
+ continue;
+ }
+
changedRCS = true;
}
}
- if (!donerewrite(changedRCS))
+
+ /* Deduce time_t of new revision if it is needed later. */
+ wtime = (time_t)-1;
+ if (mtimeflag | Ttimeflag)
+ wtime = date2time(workdelta->date);
+
+ if (donerewrite(changedRCS,
+ !Ttimeflag ? (time_t)-1
+ : finptr && wtime < RCSstat.st_mtime ? RCSstat.st_mtime
+ : wtime
+ ) != 0)
continue;
if (!keepworkingfile) {
Izclose(&workptr);
- r = un_link(workfilename); /* Get rid of old file */
+ r = un_link(workname); /* Get rid of old file */
} else {
newworkmode = WORKMODE(RCSstat.st_mode,
! (Expand==VAL_EXPAND || lockthis < StrictLocks)
);
- mtime = mtimeflag ? workdelta->date : (char const*)0;
+ mtime = mtimeflag ? wtime : (time_t)-1;
/* Expand if it might change or if we can't fix mode, time. */
if (changework || (r=fixwork(newworkmode,mtime)) != 0) {
Irewind(workptr);
/* Expand keywords in file. */
locker_expansion = lockthis;
+ workdelta->name =
+ namedrev(
+ assoclst ? assoclst->ssymbol
+ : keepflag && *prevname.string ? prevname.string
+ : rev,
+ workdelta
+ );
switch (xpandfile(
- workptr, workfilename,
- workdelta, &newworkfilename
+ workptr, workdelta, &newworkname, dolog
)) {
default:
continue;
@@ -654,24 +802,24 @@ mainProg(ciId, "ci", "$Id: ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp $")
break;
/* fall into */
case 1:
- if (!(r = setfiledate(newworkfilename,mtime))) {
- Izclose(&workptr);
- ignoreints();
- r = chnamemod(&exfile, newworkfilename, workfilename, newworkmode);
- keepdirtemp(newworkfilename);
- restoreints();
- }
+ Izclose(&workptr);
+ aflush(exfile);
+ ignoreints();
+ r = chnamemod(&exfile, newworkname,
+ workname, 1, newworkmode, mtime
+ );
+ keepdirtemp(newworkname);
+ restoreints();
}
}
}
if (r != 0) {
- eerror(workfilename);
+ eerror(workname);
continue;
}
diagnose("done\n");
- } while (cleanup(),
- ++argv, --argc >=1);
+ }
tempunlink();
exitmain(exitstatus);
@@ -685,16 +833,17 @@ cleanup()
Izclose(&workptr);
Ozclose(&exfile);
Ozclose(&fcopy);
- Ozclose(&frewrite);
+ ORCSclose();
dirtempunlink();
}
-#if lint
+#if RCS_lint
# define exiterr ciExit
#endif
- exiting void
+ void
exiterr()
{
+ ORCSerror();
dirtempunlink();
tempunlink();
_exit(EXIT_FAILURE);
@@ -713,26 +862,28 @@ addelta()
*/
{
register char *tp;
- register unsigned i;
+ register int i;
int removedlock;
- unsigned newdnumlength; /* actual length of new rev. num. */
+ int newdnumlength; /* actual length of new rev. num. */
newdnumlength = countnumflds(newdelnum.string);
if (rcsinitflag) {
/* this covers non-existing RCS file and a file initialized with rcs -i */
- if ((newdnumlength==0)&&(Dbranch!=nil)) {
+ if (newdnumlength==0 && Dbranch) {
bufscpy(&newdelnum, Dbranch);
newdnumlength = countnumflds(Dbranch);
}
if (newdnumlength==0) bufscpy(&newdelnum, "1.1");
else if (newdnumlength==1) bufscat(&newdelnum, ".1");
else if (newdnumlength>2) {
- error("Branch point doesn't exist for %s.",newdelnum.string);
+ rcserror("Branch point doesn't exist for revision %s.",
+ newdelnum.string
+ );
return -1;
} /* newdnumlength == 2 is OK; */
Head = &newdelta;
- newdelta.next=nil;
+ newdelta.next = 0;
return 0;
}
if (newdnumlength==0) {
@@ -755,11 +906,11 @@ addelta()
} else if (!targetdelta->next && countnumflds(targetdelta->num)>2) {
/* new tip revision on side branch */
targetdelta->next= &newdelta;
- newdelta.next = nil;
+ newdelta.next = 0;
} else {
/* middle revision; start a new branch */
bufscpy(&newdelnum, "");
- return addbranch(targetdelta,&newdelnum);
+ return addbranch(targetdelta, &newdelnum, 1);
}
incnum(targetdelta->num, &newdelnum);
return 1; /* successful use of existing lock */
@@ -768,7 +919,7 @@ addelta()
/* no existing lock; try Dbranch */
/* update newdelnum */
if (StrictLocks || !myself(RCSstat.st_uid)) {
- error("no lock set by %s",getcaller());
+ rcserror("no lock set by %s", getcaller());
return -1;
}
if (Dbranch) {
@@ -790,8 +941,9 @@ addelta()
bufscat(&newdelnum, ".1");
}
if (cmpnum(newdelnum.string,Head->num) <= 0) {
- error("deltanumber %s too low; must be higher than %s",
- newdelnum.string, Head->num);
+ rcserror("revision %s too low; must be higher than %s",
+ newdelnum.string, Head->num
+ );
return -1;
}
targetdelta = Head;
@@ -806,44 +958,46 @@ addelta()
/* put new revision on side branch */
/*first, get branch point */
tp = newdelnum.string;
- for (i = newdnumlength - (newdnumlength&1 ^ 1); (--i); )
+ for (i = newdnumlength - ((newdnumlength&1) ^ 1); --i; )
while (*tp++ != '.')
- ;
+ continue;
*--tp = 0; /* Kill final dot to get old delta temporarily. */
- if (!(targetdelta=genrevs(newdelnum.string,(char*)nil,(char*)nil,(char*)nil,&gendeltas)))
+ if (!(targetdelta=genrevs(newdelnum.string,(char*)0,(char*)0,(char*)0,&gendeltas)))
return -1;
if (cmpnum(targetdelta->num, newdelnum.string) != 0) {
- error("can't find branchpoint %s", newdelnum.string);
+ rcserror("can't find branch point %s", newdelnum.string);
return -1;
}
*tp = '.'; /* Restore final dot. */
- return addbranch(targetdelta,&newdelnum);
+ return addbranch(targetdelta, &newdelnum, 0);
}
}
static int
-addbranch(branchpoint,num)
+addbranch(branchpoint, num, removedlock)
struct hshentry *branchpoint;
struct buf *num;
+ int removedlock;
/* adds a new branch and branch delta at branchpoint.
* If num is the null string, appends the new branch, incrementing
* the highest branch number (initially 1), and setting the level number to 1.
* the new delta and branchhead are in globals newdelta and newbranch, resp.
* the new number is placed into num.
* Return -1 on error, 1 if a lock is removed, 0 otherwise.
+ * If REMOVEDLOCK is 1, a lock was already removed.
*/
{
struct branchhead *bhead, **btrail;
struct buf branchnum;
- int removedlock, result;
- unsigned field, numlength;
+ int result;
+ int field, numlength;
static struct branchhead newbranch; /* new branch to be inserted */
numlength = countnumflds(num->string);
- if (branchpoint->branches==nil) {
+ if (!branchpoint->branches) {
/* start first branch */
branchpoint->branches = &newbranch;
if (numlength==0) {
@@ -851,7 +1005,7 @@ addbranch(branchpoint,num)
bufscat(num, ".1.1");
} else if (numlength&1)
bufscat(num, ".1");
- newbranch.nextbranch=nil;
+ newbranch.nextbranch = 0;
} else if (numlength==0) {
/* append new branch to the end */
@@ -863,10 +1017,10 @@ addbranch(branchpoint,num)
incnum(branchnum.string, num);
bufautoend(&branchnum);
bufscat(num, ".1");
- newbranch.nextbranch=nil;
+ newbranch.nextbranch = 0;
} else {
/* place the branch properly */
- field = numlength - (numlength&1 ^ 1);
+ field = numlength - ((numlength&1) ^ 1);
/* field of branch number */
btrail = &branchpoint->branches;
while (0 < (result=cmpnumfld(num->string,(*btrail)->hsh->num,field))) {
@@ -885,17 +1039,22 @@ addbranch(branchpoint,num)
/* branch exists; append to end */
bufautobegin(&branchnum);
getbranchno(num->string, &branchnum);
- targetdelta=genrevs(branchnum.string,(char*)nil,
- (char*)nil,(char*)nil,&gendeltas);
+ targetdelta = genrevs(
+ branchnum.string, (char*)0, (char*)0, (char*)0,
+ &gendeltas
+ );
bufautoend(&branchnum);
if (!targetdelta)
return -1;
if (cmpnum(num->string,targetdelta->num) <= 0) {
- error("deltanumber %s too low; must be higher than %s",
- num->string,targetdelta->num);
+ rcserror("revision %s too low; must be higher than %s",
+ num->string, targetdelta->num
+ );
return -1;
}
- if (0 <= (removedlock = removelock(targetdelta))) {
+ if (!removedlock
+ && 0 <= (removedlock = removelock(targetdelta))
+ ) {
if (numlength&1)
incnum(targetdelta->num,num);
targetdelta->next = &newdelta;
@@ -906,8 +1065,11 @@ addbranch(branchpoint,num)
}
}
newbranch.hsh = &newdelta;
- newdelta.next=nil;
- return 0;
+ newdelta.next = 0;
+ if (branchpoint->lockedby)
+ if (strcmp(branchpoint->lockedby, getcaller()) == 0)
+ return removelock(branchpoint); /* This returns 1. */
+ return removedlock;
}
static int
@@ -917,7 +1079,7 @@ addsyms(num)
register struct Symrev *p;
for (p = assoclst; p; p = p->nextsym)
- if (!addsymbol(num, p->ssymbol, p->override))
+ if (addsymbol(num, p->ssymbol, p->override) < 0)
return false;
return true;
}
@@ -969,7 +1131,7 @@ struct hshentry * delta;
* return 0; return 1 if a lock is actually removed.
*/
{
- register struct lock *next, **trail;
+ register struct rcslock *next, **trail;
char const *num;
num=delta->num;
@@ -981,12 +1143,12 @@ struct hshentry * delta;
delta->lockedby = 0;
return 1;
} else {
- error("revision %s locked by %s",num,next->login);
+ rcserror("revision %s locked by %s", num, next->login);
return -1;
}
if (!StrictLocks && myself(RCSstat.st_uid))
return 0;
- error("no lock set by %s for revision %s", getcaller(), num);
+ rcserror("no lock set by %s for revision %s", getcaller(), num);
return -1;
}
@@ -997,76 +1159,70 @@ getcurdate()
/* Return a pointer to the current date. */
{
static char buffer[datesize]; /* date buffer */
- time_t t;
- if (!buffer[0]) {
- t = time((time_t *)0);
- if (t == -1)
- faterror("time not available");
- time2date(t, buffer);
- }
+ if (!buffer[0])
+ time2date(now(), buffer);
return buffer;
}
static int
#if has_prototypes
-fixwork(mode_t newworkmode, char const *mtime)
+fixwork(mode_t newworkmode, time_t mtime)
/* The `#if has_prototypes' is needed because mode_t might promote to int. */
#else
fixwork(newworkmode, mtime)
mode_t newworkmode;
- char const *mtime;
+ time_t mtime;
#endif
{
- int r;
return
1 < workstat.st_nlink
- || newworkmode&S_IWUSR && !myself(workstat.st_uid)
+ || (newworkmode&S_IWUSR && !myself(workstat.st_uid))
+ || setmtime(workname, mtime) != 0
? -1
- :
- workstat.st_mode != newworkmode
- &&
- (r =
-# if has_fchmod
- fchmod(Ifileno(workptr), newworkmode)
-# else
- chmod(workfilename, newworkmode)
-# endif
- ) != 0
- ? r
- :
- setfiledate(workfilename, mtime);
+ : workstat.st_mode == newworkmode ? 0
+#if has_fchmod
+ : fchmod(Ifileno(workptr), newworkmode) == 0 ? 0
+#endif
+#if bad_chmod_close
+ : -1
+#else
+ : chmod(workname, newworkmode)
+#endif
+ ;
}
static int
-xpandfile(unexfile, dir, delta, exfilename)
+xpandfile(unexfile, delta, exname, dolog)
RILE *unexfile;
- char const *dir;
struct hshentry const *delta;
- char const **exfilename;
+ char const **exname;
+ int dolog;
/*
* Read unexfile and copy it to a
- * file in dir, performing keyword substitution with data from delta.
+ * file, performing keyword substitution with data from delta.
* Return -1 if unsuccessful, 1 if expansion occurred, 0 otherwise.
* If successful, stores the stream descriptor into *EXFILEP
- * and its name into *EXFILENAME.
+ * and its name into *EXNAME.
*/
{
- char const *targetfname;
+ char const *targetname;
int e, r;
- targetfname = makedirtemp(dir, 1);
- if (!(exfile = fopen(targetfname, FOPEN_W_WORK))) {
- eerror(targetfname);
- error("can't expand working file");
+ targetname = makedirtemp(1);
+ if (!(exfile = fopenSafer(targetname, FOPEN_W_WORK))) {
+ eerror(targetname);
+ workerror("can't build working file");
return -1;
}
r = 0;
- if (Expand == OLD_EXPAND)
+ if (MIN_UNEXPAND <= Expand)
fastcopy(unexfile,exfile);
else {
for (;;) {
- e = expandline(unexfile,exfile,delta,false,(FILE*)nil);
+ e = expandline(
+ unexfile, exfile, delta, false, (FILE*)0, dolog
+ );
if (e < 0)
break;
r |= e;
@@ -1074,8 +1230,7 @@ xpandfile(unexfile, dir, delta, exfilename)
break;
}
}
- *exfilename = targetfname;
- aflush(exfile);
+ *exname = targetname;
return r & 1;
}
@@ -1116,7 +1271,7 @@ getlogmsg()
/* generate std. log message */
caller = getcaller();
i = sizeof(ciklog)+strlen(caller)+3;
- bufalloc(&logbuf, i+datesize);
+ bufalloc(&logbuf, i + datesize + zonelenmax);
tp = logbuf.string;
VOID sprintf(tp, "%s%s at ", ciklog, caller);
VOID date2str(getcurdate(), tp+i);
@@ -1150,19 +1305,15 @@ getlogmsg()
static void
addassoclst(flag, sp)
-int flag;
-char * sp;
+ int flag;
+ char const *sp;
{
struct Symrev *pt;
pt = talloc(struct Symrev);
pt->ssymbol = sp;
pt->override = flag;
- pt->nextsym = nil;
- if (lastassoc)
- lastassoc->nextsym = pt;
- else
- assoclst = pt;
- lastassoc = pt;
- return;
+ pt->nextsym = 0;
+ *nextassoc = pt;
+ nextassoc = &pt->nextsym;
}
diff --git a/gnu/usr.bin/rcs/co/co.1 b/gnu/usr.bin/rcs/co/co.1
index 1fce152..8d0a6e7 100644
--- a/gnu/usr.bin/rcs/co/co.1
+++ b/gnu/usr.bin/rcs/co/co.1
@@ -2,9 +2,10 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: co.1,v 1.1.1.1 1993/06/18 04:22:11 jkh Exp $
-.ds g \&\s-1UTC\s0
+.Id $Id: co.1,v 5.13 1995/06/01 16:23:43 eggert Exp $
+.ds i \&\s-1ISO\s0
.ds r \&\s-1RCS\s0
+.ds u \&\s-1UTC\s0
.if n .ds - \%--
.if t .ds - \(em
.TH CO 1 \*(Dt GNU
@@ -23,12 +24,12 @@ all others denote working files.
Names are paired as explained in
.BR ci (1).
.PP
-Revisions of an \*r file may be checked out locked or unlocked. Locking a
+Revisions of an \*r file can be checked out locked or unlocked. Locking a
revision prevents overlapping updates. A revision checked out for reading or
processing (e.g., compiling) need not be locked. A revision checked out
for editing and later checkin must normally be locked. Checkout with locking
fails if the revision to be checked out is currently locked by another user.
-(A lock may be broken with
+(A lock can be broken with
.BR rcs "(1).)\ \&"
Checkout with locking also requires the caller to be on the access list of
the \*r file, unless he is the owner of the
@@ -51,7 +52,7 @@ on the default branch (normally the trunk, see the
.B \-b
option of
.BR rcs (1)).
-A revision or branch number may be attached
+A revision or branch number can be attached
to any of the options
.BR \-f ,
.BR \-I ,
@@ -73,7 +74,7 @@ retrieve from a single branch, the
.I selected
branch,
which is either specified by one of
-.BR \-f,
+.BR \-f ,
\&.\|.\|.,
.BR \-u ,
or the default branch.
@@ -88,7 +89,7 @@ always performs keyword substitution (see below).
.TP
.BR \-r [\f2rev\fP]
retrieves the latest revision whose number is less than or equal to
-.I rev.
+.IR rev .
If
.I rev
indicates a branch rather than a revision,
@@ -108,7 +109,16 @@ is
.B co
determines the revision number from keyword values in the working file.
Otherwise, a revision is composed of one or more numeric or symbolic fields
-separated by periods. The numeric equivalent of a symbolic field
+separated by periods.
+If
+.I rev
+begins with a period,
+then the default branch (normally the trunk) is prepended to it.
+If
+.I rev
+is a branch number followed by a period,
+then the latest revision on that branch is used.
+The numeric equivalent of a symbolic field
is specified with the
.B \-n
option of the commands
@@ -141,14 +151,6 @@ See also
.SM "FILE MODES"
below.
.TP
-.B \-K\f2keywordlist\fP
-Exclude or include keyword expansion when checking out a file.
-By default all keywords are expanded, you can turn individual
-keywords off with
-.BR \-K\f2eKeyword\fP
-or on with
-.BR \-K\f2iKeyword\fP .
-.TP
.B \-kkv
Generate keyword strings using the default form, e.g.\&
.B "$\&Revision: \*(Rv $"
@@ -174,7 +176,7 @@ Like
except that a locker's name is always inserted
if the given revision is currently locked.
.TP
-.BR \-kk
+.B \-kk
Generate only keyword names in keyword strings; omit their values.
See
.SM "KEYWORD SUBSTITUTION"
@@ -184,11 +186,17 @@ For example, for the
keyword, generate the string
.B $\&Revision$
instead of
-.BR "$\&Revision: \*(Rv $".
+.BR "$\&Revision: \*(Rv $" .
This option is useful to ignore differences due to keyword substitution
when comparing different revisions of a file.
+Log messages are inserted after
+.B $\&Log$
+keywords even if
+.B \-kk
+is specified,
+since this tends to be more useful when merging changes.
.TP
-.BR \-ko
+.B \-ko
Generate the old keyword string,
present in the working file just before it was checked in.
For example, for the
@@ -198,18 +206,33 @@ keyword, generate the string
instead of
.B "$\&Revision: \*(Rv $"
if that is how the string appeared when the file was checked in.
-This can be useful for binary file formats
+This can be useful for file formats
that cannot tolerate any changes to substrings
that happen to take the form of keyword strings.
.TP
-.BR \-kv
+.B \-kb
+Generate a binary image of the old keyword string.
+This acts like
+.BR \-ko ,
+except it performs all working file input and output in binary mode.
+This makes little difference on Posix and Unix hosts,
+but on DOS-like hosts one should use
+.B "rcs\ \-i\ \-kb"
+to initialize an \*r file intended to be used for binary files.
+Also, on all hosts,
+.BR rcsmerge (1)
+normally refuses to merge files when
+.B \-kb
+is in effect.
+.TP
+.B \-kv
Generate only keyword values for keyword strings.
For example, for the
.B Revision
keyword, generate the string
.B \*(Rv
instead of
-.BR "$\&Revision: \*(Rv $".
+.BR "$\&Revision: \*(Rv $" .
This can help generate files in programming languages where it is hard to
strip keyword delimiters like
.B "$\&Revision:\ $"
@@ -241,8 +264,8 @@ even if the standard input is not a terminal.
.BI \-d date
retrieves the latest revision on the selected branch whose checkin date/time is
less than or equal to
-.I date.
-The date and time may be given in free format.
+.IR date .
+The date and time can be given in free format.
The time zone
.B LT
stands for local time;
@@ -251,38 +274,43 @@ For example, the following
.IR date s
are equivalent
if local time is January 11, 1990, 8pm Pacific Standard Time,
-eight hours west of Coordinated Universal Time (\*g):
+eight hours west of Coordinated Universal Time (\*u):
.RS
.LP
.RS
.nf
.ta \w'\f3Thu, 11 Jan 1990 20:00:00 \-0800\fP 'u
-.ne 9
+.ne 10
\f38:00 pm lt\fP
-\f34:00 AM, Jan. 12, 1990\fP note: default is \*g
-\f31990/01/12 04:00:00\fP \*r date format
+\f34:00 AM, Jan. 12, 1990\fP default is \*u
+\f31990-01-12 04:00:00+00\fP \*i 8601 (\*u)
+\f31990-01-11 20:00:00\-08\fP \*i 8601 (local time)
+\f31990/01/12 04:00:00\fP traditional \*r format
\f3Thu Jan 11 20:00:00 1990 LT\fP output of \f3ctime\fP(3) + \f3LT\fP
\f3Thu Jan 11 20:00:00 PST 1990\fP output of \f3date\fP(1)
\f3Fri Jan 12 04:00:00 GMT 1990\fP
-\f3Thu, 11 Jan 1990 20:00:00 \-0800\fP
-\f3Fri-JST, 1990, 1pm Jan 12\fP
-\f312-January-1990, 04:00-WET\fP
+\f3Thu, 11 Jan 1990 20:00:00 \-0800\fP Internet RFC 822
+\f312-January-1990, 04:00 WET\fP
.ta 4n +4n +4n +4n
.fi
.RE
.LP
-Most fields in the date and time may be defaulted.
-The default time zone is \*g.
+Most fields in the date and time can be defaulted.
+The default time zone is normally \*u, but this can be overridden by the
+.B \-z
+option.
The other defaults are determined in the order year, month, day,
hour, minute, and second (most to least significant). At least one of these
fields must be provided. For omitted fields that are of higher significance
than the highest provided field, the time zone's current values are assumed.
For all other omitted fields,
the lowest possible values are assumed.
-For example, the date
+For example, without
+.BR \-z ,
+the date
.B "20, 10:30"
defaults to
-10:30:00 \*g of the 20th of the \*g time zone's current month and year.
+10:30:00 \*u of the 20th of the \*u time zone's current month and year.
The date/time must be quoted if it contains spaces.
.RE
.TP
@@ -294,12 +322,22 @@ Use this option with care; it can confuse
.TP
.BI \-s state
retrieves the latest revision on the selected branch whose state is set to
-.I state.
+.IR state .
+.TP
+.B \-T
+Preserve the modification time on the \*r file
+even if the \*r file changes because a lock is added or removed.
+This option can suppress extensive recompilation caused by a
+.BR make (1)
+dependency of some other copy of the working file on the \*r file.
+Use this option with care; it can suppress recompilation even when it is needed,
+i.e. when the change of lock
+would mean a change to keyword strings in the other working file.
.TP
.BR \-w [\f2login\fP]
retrieves the latest revision on the selected branch which was checked in
by the user with login name
-.I login.
+.IR login .
If the argument
.I login
is
@@ -307,7 +345,7 @@ omitted, the caller's login is assumed.
.TP
.BI \-j joinlist
generates a new revision which is the join of the revisions on
-.I joinlist.
+.IR joinlist .
This option is largely obsoleted by
.BR rcsmerge (1)
but is retained for backwards compatibility.
@@ -327,7 +365,7 @@ For the initial such pair,
.I rev1
denotes the revision selected
by the above options
-.BR \-f,
+.BR \-f ,
\&.\|.\|.,
.BR \-w .
For all other pairs,
@@ -343,13 +381,13 @@ joins revisions
and
.I rev3
with respect to
-.I rev2.
+.IR rev2 .
This means that all changes that transform
.I rev2
into
.I rev1
are applied to a copy of
-.I rev3.
+.IR rev3 .
This is particularly useful if
.I rev1
and
@@ -380,7 +418,7 @@ reports overlaps as described in
.PP
For the initial pair,
.I rev2
-may be omitted. The default is the common
+can be omitted. The default is the common
ancestor.
If any of the arguments indicate branches, the latest revisions
on those branches are assumed.
@@ -389,22 +427,28 @@ The options
and
.B \-u
lock or unlock
-.I rev1.
+.IR rev1 .
.RE
.TP
+.BI \-V
+Print \*r's version number.
+.TP
.BI \-V n
Emulate \*r version
.I n,
where
.I n
-may be
+can be
.BR 3 ,
.BR 4 ,
or
.BR 5 .
-This may be useful when interchanging \*r files with others who are
+This can be useful when interchanging \*r files with others who are
running older versions of \*r.
To see which version of \*r your correspondents are running, have them invoke
+.BR "rcs \-V" ;
+this works with newer versions of \*r.
+If it doesn't work, have them invoke
.B rlog
on an \*r file;
if none of the first few lines of output contain the string
@@ -412,15 +456,14 @@ if none of the first few lines of output contain the string
it is version 3;
if the dates' years have just two digits, it is version 4;
otherwise, it is version 5.
-An \*r file generated while emulating version 3 will lose its default branch.
-An \*r revision generated while emulating version 4 or earlier will have
-a timestamp that is off by up to 13 hours.
-A revision extracted while emulating version 4 or earlier will contain
-dates of the form
+An \*r file generated while emulating version 3 loses its default branch.
+An \*r revision generated while emulating version 4 or earlier has
+a time stamp that is off by up to 13 hours.
+A revision extracted while emulating version 4 or earlier contains
+abbreviated dates of the form
.IB yy / mm / dd
-instead of
-.IB yyyy / mm / dd
-and may also contain different white space in the substitution for
+and can also contain different white space and line prefixes
+in the substitution for
.BR $\&Log$ .
.TP
.BI \-x "suffixes"
@@ -430,6 +473,46 @@ to characterize \*r files.
See
.BR ci (1)
for details.
+.TP
+.BI \-z zone
+specifies the date output format in keyword substitution,
+and specifies the default time zone for
+.I date
+in the
+.BI \-d date
+option.
+The
+.I zone
+should be empty, a numeric \*u offset, or the special string
+.B LT
+for local time.
+The default is an empty
+.IR zone ,
+which uses the traditional \*r format of \*u without any time zone indication
+and with slashes separating the parts of the date;
+otherwise, times are output in \*i 8601 format with time zone indication.
+For example, if local time is January 11, 1990, 8pm Pacific Standard Time,
+eight hours west of \*u,
+then the time is output as follows:
+.RS
+.LP
+.RS
+.nf
+.ta \w'\f3\-z+05:30\fP 'u +\w'\f31990-01-11 09:30:00+05:30\fP 'u
+.ne 4
+\f2option\fP \f2time output\fP
+\f3\-z\fP \f31990/01/12 04:00:00\fP \f2(default)\fP
+\f3\-zLT\fP \f31990-01-11 20:00:00\-08\fP
+\f3\-z+05:30\fP \f31990-01-12 09:30:00+05:30\fP
+.ta 4n +4n +4n +4n
+.fi
+.RE
+.LP
+The
+.B \-z
+option does not affect dates stored in \*r files,
+which are always \*u.
+.RE
.SH "KEYWORD SUBSTITUTION"
Strings of the form
.BI $ keyword $
@@ -444,7 +527,7 @@ where
and
.I value
are pairs listed below.
-Keywords may be embedded in literal strings
+Keywords can be embedded in literal strings
or comments to identify a revision.
.PP
Initially, the user enters strings of the form
@@ -467,12 +550,18 @@ Keywords and their corresponding values:
The login name of the user who checked in the revision.
.TP
.B $\&Date$
-The date and time (\*g) the revision was checked in.
+The date and time the revision was checked in.
+With
+.BI \-z zone
+a numeric time zone offset is appended; otherwise, the date is \*u.
.TP
.B $\&Header$
A standard header containing the full pathname of the \*r file, the
-revision number, the date (\*g), the author, the state,
+revision number, the date and time, the author, the state,
and the locker (if locked).
+With
+.BI \-z zone
+a numeric time zone offset is appended to the date; otherwise, the date is \*u.
.TP
.B $\&Id$
Same as
@@ -485,7 +574,10 @@ The login name of the user who locked the revision (empty if not locked).
.B $\&Log$
The log message supplied during checkin, preceded by a header
containing the \*r filename, the revision number, the author, and the date
-(\*g).
+and time.
+With
+.BI \-z zone
+a numeric time zone offset is appended; otherwise, the date is \*u.
Existing log messages are
.I not
replaced.
@@ -493,6 +585,58 @@ Instead, the new log message is inserted after
.BR $\&Log: .\|.\|. $ .
This is useful for
accumulating a complete change log in a source file.
+.RS
+.LP
+Each inserted line is prefixed by the string that prefixes the
+.B $\&Log$
+line. For example, if the
+.B $\&Log$
+line is
+.RB \*(lq "//\ $\&Log: tan.cc\ $" \*(rq,
+\*r prefixes each line of the log with
+.RB \*(lq "//\ " \*(rq.
+This is useful for languages with comments that go to the end of the line.
+The convention for other languages is to use a
+.RB \*(lq " \(** " \(rq
+prefix inside a multiline comment.
+For example, the initial log comment of a C program
+conventionally is of the following form:
+.RS
+.LP
+.nf
+.ft 3
+.ne 3
+/\(**
+.in +\w'/'u
+\(** $\&Log$
+\(**/
+.in
+.ft
+.fi
+.RE
+.LP
+For backwards compatibility with older versions of \*r, if the log prefix is
+.B /\(**
+or
+.B (\(**
+surrounded by optional white space, inserted log lines contain a space
+instead of
+.B /
+or
+.BR ( ;
+however, this usage is obsolescent and should not be relied on.
+.RE
+.TP
+.B $\&Name$
+The symbolic name used to check out the revision, if any.
+For example,
+.B "co\ \-rJoe"
+generates
+.BR "$\&Name:\ Joe\ $" .
+Plain
+.B co
+generates just
+.BR "$\&Name:\ \ $" .
.TP
.B $\&RCSfile$
The name of the \*r file without a path.
@@ -510,6 +654,22 @@ option of
.BR rcs (1)
or
.BR ci (1).
+.PP
+The following characters in keyword values are represented by escape sequences
+to keep keyword strings well-formed.
+.LP
+.RS
+.nf
+.ne 6
+.ta \w'newline 'u
+\f2char escape sequence\fP
+tab \f3\et\fP
+newline \f3\en\fP
+space \f3\e040
+$ \e044
+\e \e\e\fP
+.fi
+.RE
.SH "FILE MODES"
The working file inherits the read and execute permissions from the \*r
file. In addition, the owner write permission is turned on, unless
@@ -531,7 +691,10 @@ is given, the working file is deleted without asking.
.B co
accesses files much as
.BR ci (1)
-does, except that it does not need to read the working file.
+does, except that it does not need to read the working file
+unless a revision number of
+.B $
+is specified.
.SH ENVIRONMENT
.TP
.B \s-1RCSINIT\s0
@@ -547,14 +710,14 @@ The exit status is zero if and only if all operations were successful.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
-Revision Number: \*(Rv; Release Date: \*(Dt.
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
-Copyright \(co 1982, 1988, 1989 by Walter F. Tichy.
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
-Copyright \(co 1990, 1991 by Paul Eggert.
+Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
.SH "SEE ALSO"
-ci(1), ctime(3), date(1), ident(1), make(1),
-rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1),
+rcsintro(1), ci(1), ctime(3), date(1), ident(1), make(1),
+rcs(1), rcsclean(1), rcsdiff(1), rcsmerge(1), rlog(1),
rcsfile(5)
.br
Walter F. Tichy,
@@ -570,8 +733,4 @@ by writing them differently. In nroff and troff, this is done by embedding the
null-character
.B \e&
into the keyword.
-.SH BUGS
-The
-.B \-d
-option sometimes gets confused, and accepts no date before 1970.
.br
diff --git a/gnu/usr.bin/rcs/co/co.c b/gnu/usr.bin/rcs/co/co.c
index 6a1579d..4e6b8c4 100644
--- a/gnu/usr.bin/rcs/co/co.c
+++ b/gnu/usr.bin/rcs/co/co.c
@@ -1,5 +1,7 @@
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Check out working files from revisions of RCS files. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -15,8 +17,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -25,25 +28,40 @@ Report problems and direct all questions to:
*/
/*
- * RCS checkout operation
- */
-/*****************************************************************************
- * check out revisions from RCS files
- *****************************************************************************
- */
-
-
-/* $Log: co.c,v $
- * Revision 1.2 1994/05/14 07:00:10 rgrimes
- * Add new option -K from David Dawes that allows you to turn on and off
- * specific keyword substitution during a rcs co command.
- * Add the new keyword FreeBSD that is IDENTICAL in operation to $Id$.
+ * $Log: co.c,v $
+ * Revision 5.18 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.17 1995/06/01 16:23:43 eggert
+ * (main, preparejoin): Pass argument instead of using `join' static variable.
+ * (main): Add -kb.
+ *
+ * Revision 5.16 1994/03/17 14:05:48 eggert
+ * Move buffer-flushes out of critical sections, since they aren't critical.
+ * Use ORCSerror to clean up after a fatal error. Remove lint.
+ * Specify subprocess input via file descriptor, not file name.
+ *
+ * Revision 5.15 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits. Don't print usage twice.
+ *
+ * Revision 5.14 1993/11/03 17:42:27 eggert
+ * Add -z. Generate a value for the Name keyword.
+ * Don't arbitrarily limit the number of joins.
+ * Improve quality of diagnostics.
*
- * Revision 1.1.1.1 1993/06/18 04:22:11 jkh
- * Updated GNU utilities
+ * Revision 5.13 1992/07/28 16:12:44 eggert
+ * Add -V. Check that working and RCS files are distinct.
+ *
+ * Revision 5.12 1992/02/17 23:02:08 eggert
+ * Add -T.
+ *
+ * Revision 5.11 1992/01/24 18:44:19 eggert
+ * Add support for bad_creat0. lint -> RCS_lint
+ *
+ * Revision 5.10 1992/01/06 02:42:34 eggert
+ * Update usage string.
*
* Revision 5.9 1991/10/07 17:32:46 eggert
- * ci -u src/RCS/co.c,v src/co.c <<\.
* -k affects just working file, not RCS file.
*
* Revision 5.8 1991/08/19 03:13:55 eggert
@@ -151,17 +169,19 @@ Report problems and direct all questions to:
#include "rcsbase.h"
+static char *addjoin P((char*));
static char const *getancestor P((char const*,char const*));
static int buildjoin P((char const*));
-static int preparejoin P((void));
+static int preparejoin P((char*));
static int rmlock P((struct hshentry const*));
static int rmworkfile P((void));
static void cleanup P((void));
static char const quietarg[] = "-q";
-static char const *expandarg, *join, *suffixarg, *versionarg, *incexcarg;
-static char const *joinlist[joinlength]; /* revisions to be joined */
+static char const *expandarg, *suffixarg, *versionarg, *zonearg;
+static char const **joinlist; /* revisions to be joined */
+static int joinlength;
static FILE *neworkptr;
static int exitstatus;
static int forceflag;
@@ -172,25 +192,31 @@ static struct hshentries *gendeltas; /* deltas to be generated */
static struct hshentry *targetdelta; /* final delta to be generated */
static struct stat workstat;
-mainProg(coId, "co", "$Id: co.c,v 1.2 1994/05/14 07:00:10 rgrimes Exp $")
+mainProg(coId, "co", "$Id: co.c,v 5.18 1995/06/16 06:19:24 eggert Exp $")
{
static char const cmdusage[] =
- "\nco usage: co -{flpqru}[rev] -ddate -jjoinlist -sstate -w[login] -Vn file ...";
+ "\nco usage: co -{fIlMpqru}[rev] -ddate -jjoins -ksubst -sstate -T -w[who] -Vn -xsuff -zzone file ...";
- char *a, **newargv;
+ char *a, *joinflag, **newargv;
char const *author, *date, *rev, *state;
- char const *joinfilename, *newdate, *neworkfilename;
+ char const *joinname, *newdate, *neworkname;
int changelock; /* 1 if a lock has been changed, -1 if error */
int expmode, r, tostdout, workstatstat;
+ int Ttimeflag;
struct buf numericrev; /* expanded revision number */
char finaldate[datesize];
+# if OPEN_O_BINARY
+ int stdout_mode = 0;
+# endif
setrid();
- author = date = rev = state = nil;
+ author = date = rev = state = 0;
+ joinflag = 0;
bufautobegin(&numericrev);
expmode = -1;
suffixes = X_DEFAULT;
tostdout = false;
+ Ttimeflag = false;
argc = getRCSINIT(argc, argv, &newargv);
argv = newargv;
@@ -211,14 +237,14 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1994/05/14 07:00:10 rgrimes Exp $")
case 'l':
if (lockflag < 0) {
- warn("-l overrides -u.");
+ warn("-u overridden by -l.");
}
lockflag = 1;
goto revno;
case 'u':
if (0 < lockflag) {
- warn("-l overrides -u.");
+ warn("-l overridden by -u.");
}
lockflag = -1;
goto revno;
@@ -244,8 +270,8 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1994/05/14 07:00:10 rgrimes Exp $")
case 'j':
if (*a) {
- if (join) redefined('j');
- join = a;
+ if (joinflag) redefined('j');
+ joinflag = a;
}
break;
@@ -260,6 +286,12 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1994/05/14 07:00:10 rgrimes Exp $")
}
break;
+ case 'T':
+ if (*a)
+ goto unknown;
+ Ttimeflag = true;
+ break;
+
case 'w':
if (author) redefined('w');
if (*a)
@@ -278,10 +310,11 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1994/05/14 07:00:10 rgrimes Exp $")
setRCSversion(versionarg);
break;
- case 'K': /* set keyword inclusions/exclusions */
- incexcarg = *argv;
- setIncExc(incexcarg);
+ case 'z':
+ zonearg = *argv;
+ zone_set(a);
break;
+
case 'k': /* set keyword expand mode */
expandarg = *argv;
if (0 <= expmode) redefined('k');
@@ -289,69 +322,81 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1994/05/14 07:00:10 rgrimes Exp $")
break;
/* fall into */
default:
- faterror("unknown option: %s%s", *argv, cmdusage);
+ unknown:
+ error("unknown option: %s%s", *argv, cmdusage);
};
} /* end of option processing */
- if (argc<1) faterror("no input file%s", cmdusage);
- if (tostdout)
-# if text_equals_binary_stdio || text_work_stdio
- workstdout = stdout;
-# else
- if (!(workstdout = fdopen(STDOUT_FILENO, FOPEN_W_WORK)))
- efaterror("stdout");
-# endif
-
- /* now handle all filenames */
- do {
+ /* Now handle all pathnames. */
+ if (nerror) cleanup();
+ else if (argc < 1) faterror("no input file%s", cmdusage);
+ else for (; 0 < argc; cleanup(), ++argv, --argc) {
ffree();
- if (pairfilenames(argc, argv, lockflag?rcswriteopen:rcsreadopen, true, false) <= 0)
+ if (pairnames(argc, argv, lockflag?rcswriteopen:rcsreadopen, true, false) <= 0)
continue;
- /* now RCSfilename contains the name of the RCS file, and finptr
- * points at it. workfilename contains the name of the working file.
+ /*
+ * RCSname contains the name of the RCS file, and finptr
+ * points at it. workname contains the name of the working file.
* Also, RCSstat has been set.
*/
- diagnose("%s --> %s\n", RCSfilename,tostdout?"stdout":workfilename);
+ diagnose("%s --> %s\n", RCSname, tostdout?"standard output":workname);
workstatstat = -1;
if (tostdout) {
- neworkfilename = 0;
- neworkptr = workstdout;
+# if OPEN_O_BINARY
+ int newmode = Expand==BINARY_EXPAND ? OPEN_O_BINARY : 0;
+ if (stdout_mode != newmode) {
+ stdout_mode = newmode;
+ oflush();
+ VOID setmode(STDOUT_FILENO, newmode);
+ }
+# endif
+ neworkname = 0;
+ neworkptr = workstdout = stdout;
} else {
- workstatstat = stat(workfilename, &workstat);
- neworkfilename = makedirtemp(workfilename, 1);
- if (!(neworkptr = fopen(neworkfilename, FOPEN_W_WORK))) {
+ workstatstat = stat(workname, &workstat);
+ if (workstatstat == 0 && same_file(RCSstat, workstat, 0)) {
+ rcserror("RCS file is the same as working file %s.",
+ workname
+ );
+ continue;
+ }
+ neworkname = makedirtemp(1);
+ if (!(neworkptr = fopenSafer(neworkname, FOPEN_W_WORK))) {
if (errno == EACCES)
- error("%s: parent directory isn't writable",
- workfilename
- );
+ workerror("permission denied on parent directory");
else
- eerror(neworkfilename);
+ eerror(neworkname);
continue;
}
}
gettree(); /* reads in the delta tree */
- if (Head==nil) {
+ if (!Head) {
/* no revisions; create empty file */
diagnose("no revisions present; generating empty revision 0.0\n");
+ if (lockflag)
+ warn(
+ "no revisions, so nothing can be %slocked",
+ lockflag < 0 ? "un" : ""
+ );
Ozclose(&fcopy);
if (workstatstat == 0)
if (!rmworkfile()) continue;
changelock = 0;
newdate = 0;
- /* Can't reserve a delta, so don't call addlock */
} else {
- if (rev!=nil) {
+ int locks = lockflag ? findlock(false, &targetdelta) : 0;
+ if (rev) {
/* expand symbolic revision number */
if (!expandsym(rev, &numericrev))
continue;
- } else
- switch (lockflag<0 ? findlock(false,&targetdelta) : 0) {
+ } else {
+ switch (locks) {
default:
continue;
case 0:
@@ -361,6 +406,7 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1994/05/14 07:00:10 rgrimes Exp $")
bufscpy(&numericrev, targetdelta->num);
break;
}
+ }
/* get numbers of deltas to be generated */
if (!(targetdelta=genrevs(numericrev.string,date,author,state,&gendeltas)))
continue;
@@ -371,23 +417,24 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1994/05/14 07:00:10 rgrimes Exp $")
: lockflag == 0 ?
0
:
- addlock(targetdelta);
+ addlock(targetdelta, true);
if (
- changelock < 0 ||
- changelock && !checkaccesslist() ||
- !dorewrite(lockflag, changelock)
+ changelock < 0
+ || (changelock && !checkaccesslist())
+ || dorewrite(lockflag, changelock) != 0
)
continue;
if (0 <= expmode)
Expand = expmode;
if (0 < lockflag && Expand == VAL_EXPAND) {
- error("cannot combine -kv and -l");
+ rcserror("cannot combine -kv and -l");
continue;
}
- if (join && !preparejoin()) continue;
+ if (joinflag && !preparejoin(joinflag))
+ continue;
diagnose("revision %s%s\n",targetdelta->num,
0<lockflag ? " (locked)" :
@@ -401,10 +448,11 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1994/05/14 07:00:10 rgrimes Exp $")
getdesc(false); /* don't echo*/
locker_expansion = 0 < lockflag;
- joinfilename = buildrevision(
+ targetdelta->name = namedrev(rev, targetdelta);
+ joinname = buildrevision(
gendeltas, targetdelta,
- join&&tostdout ? (FILE*)0 : neworkptr,
- Expand!=OLD_EXPAND
+ joinflag&&tostdout ? (FILE*)0 : neworkptr,
+ Expand < MIN_UNEXPAND
);
# if !large_memory
if (fcopy == neworkptr)
@@ -414,46 +462,48 @@ mainProg(coId, "co", "$Id: co.c,v 1.2 1994/05/14 07:00:10 rgrimes Exp $")
finptr, MADV_SEQUENTIAL
);
- if (!donerewrite(changelock))
+ if (donerewrite(changelock,
+ Ttimeflag ? RCSstat.st_mtime : (time_t)-1
+ ) != 0)
continue;
+ if (changelock) {
+ locks += lockflag;
+ if (1 < locks)
+ rcswarn("You now have %d locks.", locks);
+ }
+
newdate = targetdelta->date;
- if (join) {
+ if (joinflag) {
newdate = 0;
- if (!joinfilename) {
+ if (!joinname) {
aflush(neworkptr);
- joinfilename = neworkfilename;
+ joinname = neworkname;
}
- if (!buildjoin(joinfilename))
+ if (Expand == BINARY_EXPAND)
+ workerror("merging binary files");
+ if (!buildjoin(joinname))
continue;
}
}
if (!tostdout) {
- r = 0;
- if (mtimeflag && newdate) {
- if (!join)
- aflush(neworkptr);
- r = setfiledate(neworkfilename, newdate);
- }
- if (r == 0) {
- ignoreints();
- r = chnamemod(&neworkptr, neworkfilename, workfilename,
- WORKMODE(RCSstat.st_mode,
- !(Expand==VAL_EXPAND || lockflag<=0&&StrictLocks)
- )
- );
- keepdirtemp(neworkfilename);
- restoreints();
- }
+ mode_t m = WORKMODE(RCSstat.st_mode,
+ ! (Expand==VAL_EXPAND || (lockflag<=0 && StrictLocks))
+ );
+ time_t t = mtimeflag&&newdate ? date2time(newdate) : (time_t)-1;
+ aflush(neworkptr);
+ ignoreints();
+ r = chnamemod(&neworkptr, neworkname, workname, 1, m, t);
+ keepdirtemp(neworkname);
+ restoreints();
if (r != 0) {
- eerror(workfilename);
- error("see %s", neworkfilename);
+ eerror(workname);
+ error("see %s", neworkname);
continue;
}
diagnose("done\n");
}
- } while (cleanup(),
- ++argv, --argc >=1);
+ }
tempunlink();
Ofclose(workstdout);
@@ -466,7 +516,7 @@ cleanup()
{
if (nerror) exitstatus = EXIT_FAILURE;
Izclose(&finptr);
- Ozclose(&frewrite);
+ ORCSclose();
# if !large_memory
if (fcopy!=workstdout) Ozclose(&fcopy);
# endif
@@ -474,12 +524,13 @@ cleanup()
dirtempunlink();
}
-#if lint
+#if RCS_lint
# define exiterr coExit
#endif
- exiting void
+ void
exiterr()
{
+ ORCSerror();
dirtempunlink();
tempunlink();
_exit(EXIT_FAILURE);
@@ -492,7 +543,8 @@ exiterr()
static int
rmworkfile()
-/* Function: prepares to remove workfilename, if it exists, and if
+/*
+ * Prepare to remove workname, if it exists, and if
* it is read-only.
* Otherwise (file writable):
* if !quietmode asks the user whether to really delete it (default: fail);
@@ -503,12 +555,12 @@ rmworkfile()
if (workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH) && !forceflag) {
/* File is writable */
if (!yesorno(false, "writable %s exists%s; remove it? [ny](n): ",
- workfilename,
+ workname,
myself(workstat.st_uid) ? "" : ", and you do not own it"
)) {
error(!quietflag && ttystdin()
? "checkout aborted"
- : "writable %s exists; checkout aborted", workfilename);
+ : "writable %s exists; checkout aborted", workname);
return false;
}
}
@@ -525,31 +577,33 @@ rmlock(delta)
* 0 if there is no lock on delta,
* and 1 if a lock was found and removed.
*/
-{ register struct lock * next, * trail;
+{ register struct rcslock * next, * trail;
char const *num;
- struct lock dummy;
+ struct rcslock dummy;
int whomatch, nummatch;
num=delta->num;
dummy.nextlock=next=Locks;
trail = &dummy;
- while (next!=nil) {
+ while (next) {
whomatch = strcmp(getcaller(), next->login);
nummatch=strcmp(num,next->delta->num);
if ((whomatch==0) && (nummatch==0)) break;
/*found a lock on delta by caller*/
if ((whomatch!=0)&&(nummatch==0)) {
- error("revision %s locked by %s; use co -r or rcs -u",num,next->login);
+ rcserror("revision %s locked by %s; use co -r or rcs -u",
+ num, next->login
+ );
return -1;
}
trail=next;
next=next->nextlock;
}
- if (next!=nil) {
+ if (next) {
/*found one; delete it */
trail->nextlock=next->nextlock;
Locks=dummy.nextlock;
- next->delta->lockedby=nil; /* reset locked-by */
+ next->delta->lockedby = 0;
return 1; /*success*/
} else return 0; /*no lock on delta*/
}
@@ -562,15 +616,15 @@ rmlock(delta)
*****************************************************************/
- static char const *
+ static char *
addjoin(joinrev)
char *joinrev;
/* Add joinrev's number to joinlist, yielding address of char past joinrev,
- * or nil if no such revision exists.
+ * or 0 if no such revision exists.
*/
{
register char *j;
- register struct hshentry const *d;
+ register struct hshentry *d;
char terminator;
struct buf numrev;
struct hshentries *joindeltas;
@@ -592,32 +646,32 @@ addjoin(joinrev)
bufautobegin(&numrev);
d = 0;
if (expandsym(joinrev, &numrev))
- d = genrevs(numrev.string,(char*)nil,(char*)nil,(char*)nil,&joindeltas);
+ d = genrevs(numrev.string,(char*)0,(char*)0,(char*)0,&joindeltas);
bufautoend(&numrev);
*j = terminator;
if (d) {
joinlist[++lastjoin] = d->num;
return j;
}
- return nil;
+ return 0;
}
static int
-preparejoin()
-/* Function: Parses a join list pointed to by join and places pointers to the
+preparejoin(j)
+ register char *j;
+/* Parse join list J and place pointers to the
* revision numbers into joinlist.
*/
{
- register char const *j;
-
- j=join;
lastjoin= -1;
for (;;) {
while ((*j==' ')||(*j=='\t')||(*j==',')) j++;
if (*j=='\0') break;
if (lastjoin>=joinlength-2) {
- error("too many joins");
- return(false);
+ joinlist =
+ (joinlength *= 2) == 0
+ ? tnalloc(char const *, joinlength = 16)
+ : trealloc(char const *, joinlist, joinlength);
}
if (!(j = addjoin(j))) return false;
while ((*j==' ') || (*j=='\t')) j++;
@@ -627,8 +681,7 @@ preparejoin()
if (*j!='\0') {
if (!(j = addjoin(j))) return false;
} else {
- error("join pair incomplete");
- return false;
+ rcsfaterror("join pair incomplete");
}
} else {
if (lastjoin==0) { /* first pair */
@@ -639,15 +692,13 @@ preparejoin()
if (!(joinlist[0] = getancestor(targetdelta->num,joinlist[1])))
return false;
} else {
- error("join pair incomplete");
- return false;
+ rcsfaterror("join pair incomplete");
}
}
}
- if (lastjoin<1) {
- error("empty join");
- return false;
- } else return true;
+ if (lastjoin < 1)
+ rcsfaterror("empty join");
+ return true;
}
@@ -655,13 +706,13 @@ preparejoin()
static char const *
getancestor(r1, r2)
char const *r1, *r2;
-/* Yield the common ancestor of r1 and r2 if successful, nil otherwise.
+/* Yield the common ancestor of r1 and r2 if successful, 0 otherwise.
* Work reliably only if r1 and r2 are not branch numbers.
*/
{
static struct buf t1, t2;
- unsigned l1, l2, l3;
+ int l1, l2, l3;
char const *r;
l1 = countnumflds(r1);
@@ -674,16 +725,16 @@ getancestor(r1, r2)
/* This will terminate since r1 and r2 are not the same; see above. */
if (l3==0) {
/* no common prefix; common ancestor on main trunk */
- VOID partialno(&t1, r1, l1>2 ? (unsigned)2 : l1);
- VOID partialno(&t2, r2, l2>2 ? (unsigned)2 : l2);
+ VOID partialno(&t1, r1, l1>2 ? 2 : l1);
+ VOID partialno(&t2, r2, l2>2 ? 2 : l2);
r = cmpnum(t1.string,t2.string)<0 ? t1.string : t2.string;
if (cmpnum(r,r1)!=0 && cmpnum(r,r2)!=0)
return r;
} else if (cmpnumfld(r1, r2, l3+1)!=0)
return partialno(&t1,r1,l3);
}
- error("common ancestor of %s and %s undefined", r1, r2);
- return nil;
+ rcserror("common ancestor of %s and %s undefined", r1, r2);
+ return 0;
}
@@ -700,7 +751,7 @@ buildjoin(initialfile)
struct buf subs;
char const *rev2, *rev3;
int i;
- char const *cov[10], *mergev[12];
+ char const *cov[10], *mergev[11];
char const **p;
bufautobegin(&commarg);
@@ -708,22 +759,19 @@ buildjoin(initialfile)
rev2 = maketemp(0);
rev3 = maketemp(3); /* buildrevision() may use 1 and 2 */
- cov[0] = nil;
- /* cov[1] setup below */
- cov[2] = CO;
- /* cov[3] setup below */
- p = &cov[4];
+ cov[1] = CO;
+ /* cov[2] setup below */
+ p = &cov[3];
if (expandarg) *p++ = expandarg;
if (suffixarg) *p++ = suffixarg;
if (versionarg) *p++ = versionarg;
+ if (zonearg) *p++ = zonearg;
*p++ = quietarg;
- *p++ = RCSfilename;
- *p = nil;
+ *p++ = RCSname;
+ *p = 0;
- mergev[0] = nil;
- mergev[1] = nil;
- mergev[2] = MERGE;
- mergev[3] = mergev[5] = "-L";
+ mergev[1] = MERGE;
+ mergev[2] = mergev[4] = "-L";
/* rest of mergev setup below */
i=0;
@@ -740,28 +788,26 @@ buildjoin(initialfile)
diagnose("revision %s\n",joinlist[i]);
bufscpy(&commarg, "-p");
bufscat(&commarg, joinlist[i]);
- cov[1] = rev2;
- cov[3] = commarg.string;
- if (runv(cov))
+ cov[2] = commarg.string;
+ if (runv(-1, rev2, cov))
goto badmerge;
diagnose("revision %s\n",joinlist[i+1]);
bufscpy(&commarg, "-p");
bufscat(&commarg, joinlist[i+1]);
- cov[1] = rev3;
- cov[3] = commarg.string;
- if (runv(cov))
+ cov[2] = commarg.string;
+ if (runv(-1, rev3, cov))
goto badmerge;
diagnose("merging...\n");
- mergev[4] = subs.string;
- mergev[6] = joinlist[i+1];
- p = &mergev[7];
+ mergev[3] = subs.string;
+ mergev[5] = joinlist[i+1];
+ p = &mergev[6];
if (quietflag) *p++ = quietarg;
if (lastjoin<=i+2 && workstdout) *p++ = "-p";
*p++ = initialfile;
*p++ = rev2;
*p++ = rev3;
- *p = nil;
- switch (runv(mergev)) {
+ *p = 0;
+ switch (runv(-1, (char*)0, mergev)) {
case DIFF_FAILURE: case DIFF_SUCCESS:
break;
default:
diff --git a/gnu/usr.bin/rcs/ident/ident.c b/gnu/usr.bin/rcs/ident/ident.c
index e3e723c..2d45530 100644
--- a/gnu/usr.bin/rcs/ident/ident.c
+++ b/gnu/usr.bin/rcs/ident/ident.c
@@ -1,5 +1,7 @@
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Identify RCS keyword strings in files. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -15,8 +17,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -25,12 +28,25 @@ Report problems and direct all questions to:
*/
/*
- * RCS identification operation
- */
-
-/* $Log: ident.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:11 jkh
- * Updated GNU utilities
+ * $Log: ident.c,v $
+ * Revision 5.9 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.8 1995/06/01 16:23:43 eggert
+ * (exiterr, reportError): New functions, needed for DOS and OS/2 ports.
+ * (scanfile): Use them.
+ *
+ * Revision 5.7 1994/03/20 04:52:58 eggert
+ * Remove `exiting' from identExit.
+ *
+ * Revision 5.6 1993/11/09 17:40:15 eggert
+ * Add -V.
+ *
+ * Revision 5.5 1993/11/03 17:42:27 eggert
+ * Test for char == EOF, not char < 0.
+ *
+ * Revision 5.4 1992/01/24 18:44:19 eggert
+ * lint -> RCS_lint
*
* Revision 5.3 1991/09/10 22:15:46 eggert
* Open files with FOPEN_R, not FOPEN_R_WORK,
@@ -84,85 +100,123 @@ Report problems and direct all questions to:
#include "rcsbase.h"
static int match P((FILE*));
-static void scanfile P((FILE*,char const*,int));
+static int scanfile P((FILE*,char const*,int));
+static void reportError P((char const*));
-mainProg(identId, "ident", "$Id: ident.c,v 1.1.1.1 1993/06/18 04:22:11 jkh Exp $")
+mainProg(identId, "ident", "$Id: ident.c,v 5.9 1995/06/16 06:19:24 eggert Exp $")
/* Ident searches the named files for all occurrences
- * of the pattern $keyword:...$, where the keywords are
- * Author, Date, Header, Id, Log, RCSfile, Revision, Source, and State.
+ * of the pattern $@: text $ where @ is a keyword.
*/
{
FILE *fp;
- int quiet;
+ int quiet = 0;
int status = EXIT_SUCCESS;
+ char const *a;
- if ((quiet = argc > 1 && strcmp("-q",argv[1])==0)) {
- argc--; argv++;
- }
+ while ((a = *++argv) && *a=='-')
+ while (*++a)
+ switch (*a) {
+ case 'q':
+ quiet = 1;
+ break;
- if (argc<2)
- scanfile(stdin, (char*)0, quiet);
+ case 'V':
+ VOID printf("RCS version %s\n", RCS_version_string);
+ quiet = -1;
+ break;
+
+ default:
+ VOID fprintf(stderr,
+ "ident: usage: ident -{qV} [file...]\n"
+ );
+ exitmain(EXIT_FAILURE);
+ break;
+ }
+
+ if (0 <= quiet)
+ if (!a)
+ VOID scanfile(stdin, (char*)0, quiet);
+ else
+ do {
+ if (!(fp = fopen(a, FOPEN_RB))) {
+ reportError(a);
+ status = EXIT_FAILURE;
+ } else if (
+ scanfile(fp, a, quiet) != 0
+ || (argv[1] && putchar('\n') == EOF)
+ )
+ break;
+ } while ((a = *++argv));
- while ( --argc > 0 ) {
- if (!(fp = fopen(*++argv, FOPEN_R))) {
- VOID fprintf(stderr, "%s error: can't open %s\n", cmdid, *argv);
- status = EXIT_FAILURE;
- } else {
- scanfile(fp, *argv, quiet);
- if (argc>1) VOID putchar('\n');
- }
- }
if (ferror(stdout) || fclose(stdout)!=0) {
- VOID fprintf(stderr, "%s error: write error\n", cmdid);
+ reportError("standard output");
status = EXIT_FAILURE;
}
exitmain(status);
}
-#if lint
- exiting void identExit() { _exit(EXIT_FAILURE); }
+#if RCS_lint
+# define exiterr identExit
#endif
-
+ void
+exiterr()
+{
+ _exit(EXIT_FAILURE);
+}
static void
+reportError(s)
+ char const *s;
+{
+ int e = errno;
+ VOID fprintf(stderr, "%s error: ", cmdid);
+ errno = e;
+ perror(s);
+}
+
+
+ static int
scanfile(file, name, quiet)
register FILE *file;
char const *name;
int quiet;
/* Function: scan an open file with descriptor file for keywords.
- * Return false if there's a read error.
+ * Return -1 if there's a write error; exit immediately on a read error.
*/
{
register int c;
- if (name)
+ if (name) {
VOID printf("%s:\n", name);
- else
- name = "input";
+ if (ferror(stdout))
+ return -1;
+ } else
+ name = "standard input";
c = 0;
- for (;;) {
- if (c < 0) {
- if (feof(file))
- break;
- if (ferror(file))
- goto read_error;
- }
+ while (c != EOF || ! (feof(file)|ferror(file))) {
if (c == KDELIM) {
if ((c = match(file)))
continue;
+ if (ferror(stdout))
+ return -1;
quiet = true;
}
c = getc(file);
}
+ if (ferror(file) || fclose(file) != 0) {
+ reportError(name);
+ /*
+ * The following is equivalent to exit(EXIT_FAILURE), but we invoke
+ * exiterr to keep lint happy. The DOS and OS/2 ports need exiterr.
+ */
+ VOID fflush(stderr);
+ VOID fflush(stdout);
+ exiterr();
+ }
if (!quiet)
VOID fprintf(stderr, "%s warning: no id keywords in %s\n", cmdid, name);
- if (fclose(file) == 0)
- return;
-
- read_error:
- VOID fprintf(stderr, "%s error: %s: read error\n", cmdid, name);
- exit(EXIT_FAILURE);
+ return 0;
}
@@ -177,7 +231,7 @@ match(fp) /* group substring between two KDELIM's; then do pattern match */
tp = line;
while ((c = getc(fp)) != VDELIM) {
- if (c < 0)
+ if (c == EOF && feof(fp) | ferror(fp))
return c;
switch (ctab[c]) {
case LETTER: case Letter:
@@ -196,7 +250,7 @@ match(fp) /* group substring between two KDELIM's; then do pattern match */
return c ? c : '\n';
*tp++ = c;
while( (c = getc(fp)) != KDELIM ) {
- if (c < 0 && feof(fp) | ferror(fp))
+ if (c == EOF && feof(fp) | ferror(fp))
return c;
switch (ctab[c]) {
default:
@@ -212,6 +266,6 @@ match(fp) /* group substring between two KDELIM's; then do pattern match */
return c;
*tp++ = c; /*append trailing KDELIM*/
*tp = '\0';
- VOID fprintf(stdout, " %c%s\n", KDELIM, line);
+ VOID printf(" %c%s\n", KDELIM, line);
return 0;
}
diff --git a/gnu/usr.bin/rcs/lib/Makefile b/gnu/usr.bin/rcs/lib/Makefile
index a69000b..0170d4a 100644
--- a/gnu/usr.bin/rcs/lib/Makefile
+++ b/gnu/usr.bin/rcs/lib/Makefile
@@ -4,8 +4,8 @@
LIB = rcs
SRCS = maketime.c partime.c rcsedit.c rcsfcmp.c rcsfnms.c rcsgen.c \
- rcskeep.c rcskeys.c rcslex.c rcsmap.c rcsrev.c rcssyn.c rcsutil.c \
- merger.c
+ rcskeep.c rcskeys.c rcslex.c rcsmap.c rcsrev.c rcssyn.c rcstime.c \
+ rcsutil.c merger.c version.c
NOPROFILE=noprofile
diff --git a/gnu/usr.bin/rcs/lib/conf.h b/gnu/usr.bin/rcs/lib/conf.h
index b8f4abd..ceae147 100644
--- a/gnu/usr.bin/rcs/lib/conf.h
+++ b/gnu/usr.bin/rcs/lib/conf.h
@@ -1,6 +1,6 @@
/* RCS compile-time configuration */
- /* $Id: conf.h,v 1.2 1994/08/05 22:33:44 wollman Exp $ */
+ /* $Id: conf.sh,v 5.25 1995/06/16 06:19:24 eggert Exp $ */
/*
* This file is generated automatically.
@@ -10,7 +10,8 @@
*/
#define exitmain(n) return n /* how to exit from main() */
-/* #define _POSIX_SOURCE */ /* Define this if Posix + strict Standard C. */
+/* #define _POSIX_C_SOURCE 2147483647L */ /* if strict C + Posix 1003.1b-1993 or later */
+/* #define _POSIX_SOURCE */ /* if strict C + Posix 1003.1-1990 */
#include <errno.h>
#include <stdio.h>
@@ -22,48 +23,28 @@
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
+/* #include <mach/mach.h> */
+/* #include <net/errno.h> */
#include <pwd.h>
+/* #include <siginfo.h> */
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/wait.h>
+/* #include <ucontext.h> */
#include <unistd.h>
#include <utime.h>
/* #include <vfork.h> */
-/* Define the following symbols to be 1 or 0. */
-#define has_sys_dir_h 1 /* Does #include <sys/dir.h> work? */
+/* Define boolean symbols to be 0 (false, the default), or 1 (true). */
#define has_sys_param_h 1 /* Does #include <sys/param.h> work? */
+/* extern int errno; */ /* Uncomment if <errno.h> doesn't declare errno. */
#define has_readlink 1 /* Does readlink() work? */
+#define readlink_isreg_errno EINVAL /* errno after readlink on regular file */
-/* #undef NAME_MAX */ /* Uncomment this if NAME_MAX is broken. */
-
-#if !defined(NAME_MAX) && !defined(_POSIX_NAME_MAX)
-# if has_sys_dir_h
-# include <sys/dir.h>
-# endif
-# ifndef NAME_MAX
-# ifndef MAXNAMLEN
-# define MAXNAMLEN 14
-# endif
-# define NAME_MAX MAXNAMLEN
-# endif
-#endif
-#if !defined(PATH_MAX) && !defined(_POSIX_PATH_MAX)
-# if has_sys_param_h
-# include <sys/param.h>
-# define included_sys_param_h 1
-# endif
-# ifndef PATH_MAX
-# ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-# endif
-# define PATH_MAX (MAXPATHLEN-1)
-# endif
-#endif
#if has_readlink && !defined(MAXSYMLINKS)
-# if has_sys_param_h && !included_sys_param_h
+# if has_sys_param_h
# include <sys/param.h>
# endif
# ifndef MAXSYMLINKS
@@ -71,13 +52,10 @@
# endif
#endif
-/* Comment out the keyword definitions below if the keywords work. */
-/* #define const */
-/* #define volatile */
-
/* Comment out the typedefs below if the types are already declared. */
/* Fix any uncommented typedefs that are wrong. */
/* typedef int mode_t; */
+/* typedef long off_t; */
/* typedef int pid_t; */
/* typedef int sig_atomic_t; */
/* typedef unsigned size_t; */
@@ -85,11 +63,44 @@
/* typedef long time_t; */
/* typedef int uid_t; */
-/* Define the following symbols to be 1 or 0. */
+/* Comment out the keyword definitions below if the keywords work. */
+/* #define const */
+/* #define volatile */
+
+/* Define boolean symbols to be 0 (false, the default), or 1 (true). */
#define has_prototypes 1 /* Do function prototypes work? */
#define has_stdarg 1 /* Does <stdarg.h> work? */
-#define has_varargs 0 /* Does <varargs.h> work? */
+/* #define has_varargs ? */ /* Does <varargs.h> work? */
#define va_start_args 2 /* How many args does va_start() take? */
+
+#if O_BINARY
+ /* Text and binary i/o behave differently. */
+ /* This is incompatible with Posix and Unix. */
+# define FOPEN_RB "rb"
+# define FOPEN_R_WORK (Expand==BINARY_EXPAND ? "r" : "rb")
+# define FOPEN_WB "wb"
+# define FOPEN_W_WORK (Expand==BINARY_EXPAND ? "w" : "wb")
+# define FOPEN_WPLUS_WORK (Expand==BINARY_EXPAND ? "w+" : "w+b")
+# define OPEN_O_BINARY O_BINARY
+#else
+ /*
+ * Text and binary i/o behave the same.
+ * Omit "b", since some nonstandard hosts reject it.
+ */
+# define FOPEN_RB "r"
+# define FOPEN_R_WORK "r"
+# define FOPEN_WB "w"
+# define FOPEN_W_WORK "w"
+# define FOPEN_WPLUS_WORK "w+"
+# define OPEN_O_BINARY 0
+#endif
+
+/* This may need changing on non-Unix systems (notably DOS). */
+#define OPEN_CREAT_READONLY (S_IRUSR|S_IRGRP|S_IROTH) /* lock file mode */
+#define OPEN_O_LOCK 0 /* extra open flags for creating lock file */
+#define OPEN_O_WRONLY O_WRONLY /* main open flag for creating a lock file */
+
+/* Define or comment out the following symbols as needed. */
#if has_prototypes
# define P(params) params
#else
@@ -113,106 +124,114 @@
#else
# define vararg_start(ap,p) va_start(ap)
#endif
-
-#define text_equals_binary_stdio 1 /* Does stdio treat text like binary? */
-#define text_work_stdio 0 /* Text i/o for working file, binary for RCS file? */
-#if text_equals_binary_stdio
- /* Text and binary i/o behave the same, or binary i/o does not work. */
-# define FOPEN_R "r"
-# define FOPEN_W "w"
-# define FOPEN_WPLUS "w+"
-#else
- /* Text and binary i/o behave differently. */
- /* This is incompatible with Posix and Unix. */
-# define FOPEN_R "rb"
-# define FOPEN_W "wb"
-# define FOPEN_WPLUS "w+b"
-#endif
-#if text_work_stdio
-# define FOPEN_R_WORK "r"
-# define FOPEN_W_WORK "w"
-# define FOPEN_WPLUS_WORK "w+"
+#define bad_chmod_close 0 /* Can chmod() close file descriptors? */
+#define bad_creat0 0 /* Do writes fail after creat(f,0)? */
+#define bad_fopen_wplus 0 /* Does fopen(f,"w+") fail to truncate f? */
+#define getlogin_is_secure 0 /* Is getlogin() secure? Usually it's not. */
+#define has_attribute_noreturn 1 /* Does __attribute__((noreturn)) work? */
+#if has_attribute_noreturn
+# define exiting __attribute__((noreturn))
#else
-# define FOPEN_R_WORK FOPEN_R
-# define FOPEN_W_WORK FOPEN_W
-# define FOPEN_WPLUS_WORK FOPEN_WPLUS
+# define exiting
#endif
-
-/* Define or comment out the following symbols as needed. */
-#define bad_fopen_wplus 0 /* Does fopen(f,FOPEN_WPLUS) fail to truncate f? */
-#define getlogin_is_secure 0 /* Is getlogin() secure? Usually it's not. */
#define has_dirent 1 /* Do opendir(), readdir(), closedir() work? */
+#define void_closedir 0 /* Does closedir() yield void? */
#define has_fchmod 1 /* Does fchmod() work? */
-#define has_fputs 0 /* Does fputs() work? */
+#define has_fflush_input 0 /* Does fflush() work on input files? */
+#define has_fputs 1 /* Does fputs() work? */
#define has_ftruncate 1 /* Does ftruncate() work? */
#define has_getuid 1 /* Does getuid() work? */
#define has_getpwuid 1 /* Does getpwuid() work? */
-#define has_link 1 /* Does link() work? */
#define has_memcmp 1 /* Does memcmp() work? */
#define has_memcpy 1 /* Does memcpy() work? */
#define has_memmove 1 /* Does memmove() work? */
-#define has_madvise 0 /* Does madvise() work? */
+#define has_map_fd 0 /* Does map_fd() work? */
#define has_mmap 1 /* Does mmap() work on regular files? */
+#define has_madvise 0 /* Does madvise() work? */
+#define mmap_signal SIGBUS /* signal received if you reference nonexistent part of mmapped file */
#define has_rename 1 /* Does rename() work? */
#define bad_a_rename 0 /* Does rename(A,B) fail if A is unwritable? */
#define bad_b_rename 0 /* Does rename(A,B) fail if B is unwritable? */
+#define bad_NFS_rename 0 /* Can rename(A,B) falsely report success? */
+/* typedef int void; */ /* Some ancient compilers need this. */
#define VOID (void) /* 'VOID e;' discards the value of an expression 'e'. */
-#define has_seteuid 0 /* Does seteuid() work? See README. */
+#define has_seteuid 1 /* Does seteuid() work? See ../INSTALL.RCS. */
+#define has_setreuid 0 /* Does setreuid() work? See ../INSTALL.RCS. */
#define has_setuid 1 /* Does setuid() exist? */
+#define has_sigaction 1 /* Does struct sigaction work? */
+#define has_sa_sigaction 0 /* Does struct sigaction have sa_sigaction? */
#define has_signal 1 /* Does signal() work? */
-#define signal_args P((int)) /* arguments of signal handlers */
#define signal_type void /* type returned by signal handlers */
#define sig_zaps_handler 0 /* Must a signal handler reinvoke signal()? */
-#define has_sigaction 1 /* Does struct sigaction work? */
/* #define has_sigblock ? */ /* Does sigblock() work? */
/* #define sigmask(s) (1 << ((s)-1)) */ /* Yield mask for signal number. */
-#define has_sys_siglist 0 /* Does sys_siglist[] work? */
typedef size_t fread_type; /* type returned by fread() and fwrite() */
typedef size_t freadarg_type; /* type of their size arguments */
typedef void *malloc_type; /* type returned by malloc() */
#define has_getcwd 1 /* Does getcwd() work? */
/* #define has_getwd ? */ /* Does getwd() work? */
+#define needs_getabsname 0 /* Must we define getabsname? */
#define has_mktemp 1 /* Does mktemp() work? */
#define has_NFS 1 /* Might NFS be used? */
+#define has_psiginfo 0 /* Does psiginfo() work? */
+#define has_psignal 1 /* Does psignal() work? */
+/* #define has_si_errno ? */ /* Does siginfo_t have si_errno? */
+/* #define has_sys_siglist ? */ /* Does sys_siglist[] work? */
/* #define strchr index */ /* Use old-fashioned name for strchr()? */
/* #define strrchr rindex */ /* Use old-fashioned name for strrchr()? */
#define bad_unlink 0 /* Does unlink() fail on unwritable files? */
#define has_vfork 1 /* Does vfork() work? */
#define has_fork 1 /* Does fork() work? */
#define has_spawn 0 /* Does spawn*() work? */
-#define has_wait 1 /* Does wait() work? */
#define has_waitpid 1 /* Does waitpid() work? */
+#define bad_wait_if_SIGCHLD_ignored 0 /* Does ignoring SIGCHLD break wait()? */
#define RCS_SHELL "/bin/sh" /* shell to run RCS subprograms */
+#define has_printf_dot 1 /* Does "%.2d" print leading 0? */
#define has_vfprintf 1 /* Does vfprintf() work? */
+#define has_attribute_format_printf 1 /* Does __attribute__((format(printf,N,N+1))) work? */
+#if has_attribute_format_printf
+# define printf_string(m, n) __attribute__((format(printf, m, n)))
+#else
+# define printf_string(m, n)
+#endif
+#if has_attribute_format_printf && has_attribute_noreturn
+ /* Work around a bug in GCC 2.5.x. */
+# define printf_string_exiting(m, n) __attribute__((format(printf, m, n), noreturn))
+#else
+# define printf_string_exiting(m, n) printf_string(m, n) exiting
+#endif
/* #define has__doprintf ? */ /* Does _doprintf() work? */
/* #define has__doprnt ? */ /* Does _doprnt() work? */
/* #undef EXIT_FAILURE */ /* Uncomment this if EXIT_FAILURE is broken. */
#define large_memory 1 /* Can main memory hold entire RCS files? */
-/* #undef ULONG_MAX */ /* Uncomment this if ULONG_MAX is broken (e.g. < 0). */
-/* struct utimbuf { time_t actime, modtime; }; */ /* Uncomment this if needed. */
-#define CO "/usr/bin/co" /* name of 'co' program */
+#ifndef LONG_MAX
+#define LONG_MAX 2147483647L /* long maximum */
+#endif
+/* Do struct stat s and t describe the same file? Answer d if unknown. */
+#define same_file(s,t,d) ((s).st_ino==(t).st_ino && (s).st_dev==(t).st_dev)
+#define has_utimbuf 1 /* Does struct utimbuf work? */
+#define CO "/usr/local/bin/co" /* name of 'co' program */
#define COMPAT2 0 /* Are version 2 files supported? */
-#define DATEFORM "%.2d.%.2d.%.2d.%.2d.%.2d.%.2d" /* e.g. 01.01.01.01.01.01 */
#define DIFF "/usr/bin/diff" /* name of 'diff' program */
#define DIFF3 "/usr/bin/diff3" /* name of 'diff3' program */
-#define DIFF3_A 1 /* Does diff3 have an -A option? */
#define DIFF3_BIN 1 /* Is diff3 user-visible (not the /usr/lib auxiliary)? */
-#define DIFF_FLAGS , "-an" /* Make diff output suitable for RCS. */
-#define DIFF_L 1 /* Does diff -L work? */
+#define DIFFFLAGS "-an" /* Make diff output suitable for RCS. */
+#define DIFF_L 1 /* Does diff -L work? */
#define DIFF_SUCCESS 0 /* DIFF status if no differences are found */
#define DIFF_FAILURE 1 /* DIFF status if differences are found */
#define DIFF_TROUBLE 2 /* DIFF status if trouble */
#define ED "/bin/ed" /* name of 'ed' program (used only if !DIFF3_BIN) */
-#define MERGE "/usr/bin/merge" /* name of 'merge' program */
+#define MERGE "/usr/local/bin/merge" /* name of 'merge' program */
#define TMPDIR "/tmp" /* default directory for temporary files */
-#define SLASH '/' /* principal pathname separator */
-#define SLASHes '/' /* `case SLASHes:' labels all pathname separators */
-#define isSLASH(c) ((c) == SLASH) /* Is arg a pathname separator? */
+#define SLASH '/' /* principal filename separator */
+#define SLASHes '/' /* `case SLASHes:' labels all filename separators */
+#define isSLASH(c) ((c) == SLASH) /* Is arg a filename separator? */
#define ROOTPATH(p) isSLASH((p)[0]) /* Is p an absolute pathname? */
#define X_DEFAULT ",v/" /* default value for -x option */
+#define SLASHSLASH_is_SLASH 1 /* Are // and / the same directory? */
+#define ALL_ABSOLUTE 1 /* Do all subprograms satisfy ROOTPATH? */
#define DIFF_ABSOLUTE 1 /* Is ROOTPATH(DIFF) true? */
-#define ALL_ABSOLUTE 1 /* Are all subprograms absolute pathnames? */
-#define SENDMAIL "/usr/bin/mail" /* how to send mail */
+#define SENDMAIL "/usr/sbin/sendmail" /* how to send mail */
#define TZ_must_be_set 0 /* Must TZ be set for gmtime() to work? */
@@ -220,40 +239,21 @@ typedef void *malloc_type; /* type returned by malloc() */
/* Adjust the following declarations as needed. */
-#if __GNUC__ && !__STRICT_ANSI__
-# define exiting volatile /* GCC extension: function cannot return */
-#else
-# define exiting
-#endif
+/* The rest is for the benefit of non-standard, traditional hosts. */
+/* Don't bother to declare functions that in traditional hosts do not appear, */
+/* or are declared in .h files, or return int or void. */
-#if has_ftruncate
- int ftruncate P((int,off_t));
-#endif
-/* <sys/mman.h> */
-#if has_madvise
- int madvise P((caddr_t,size_t,int));
-#endif
-#if has_mmap
- caddr_t mmap P((caddr_t,size_t,int,int,int,off_t));
- int munmap P((caddr_t,size_t));
+/* traditional BSD */
+
+#if has_sys_siglist && !defined(sys_siglist)
+ extern char const * const sys_siglist[];
#endif
/* Posix (ISO/IEC 9945-1: 1990 / IEEE Std 1003.1-1990) */
-/* These definitions are for the benefit of non-Posix hosts, and */
-/* Posix hosts that have Standard C compilers but traditional include files. */
-/* Unfortunately, mixed-up hosts are all too common. */
/* <fcntl.h> */
-#ifdef F_DUPFD
- int fcntl P((int,int,...));
-#else
- int dup2 P((int,int));
-#endif
-#ifndef O_BINARY /* some non-Posix hosts need O_BINARY */
-# define O_BINARY 0 /* no effect on Posix */
-#endif
#ifdef O_CREAT
# define open_can_creat 1
#else
@@ -263,43 +263,12 @@ typedef void *malloc_type; /* type returned by malloc() */
# define O_RDWR 2
# define O_CREAT 01000
# define O_TRUNC 02000
- int creat P((char const*,mode_t));
#endif
#ifndef O_EXCL
-# define O_EXCL 0
-#endif
-
-/* <pwd.h> */
-#if has_getpwuid
- struct passwd *getpwuid P((uid_t));
-#endif
-
-/* <signal.h> */
-#if has_sigaction
- int sigaction P((int,struct sigaction const*,struct sigaction*));
- int sigaddset P((sigset_t*,int));
- int sigemptyset P((sigset_t*));
-#else
-#if has_sigblock
- /* BSD */
- int sigblock P((int));
- int sigmask P((int));
- int sigsetmask P((int));
-#endif
+#define O_EXCL 0
#endif
-/* <stdio.h> */
-FILE *fdopen P((int,char const*));
-int fileno P((FILE*));
-
/* <sys/stat.h> */
-int chmod P((char const*,mode_t));
-int fstat P((int,struct stat*));
-int stat P((char const*,struct stat*));
-mode_t umask P((mode_t));
-#if has_fchmod
- int fchmod P((int,mode_t));
-#endif
#ifndef S_IRUSR
# ifdef S_IREAD
# define S_IRUSR S_IREAD
@@ -327,164 +296,100 @@ mode_t umask P((mode_t));
# endif
#endif
#ifndef S_ISREG
-# define S_ISREG(n) (((n) & S_IFMT) == S_IFREG)
+#define S_ISREG(n) (((n) & S_IFMT) == S_IFREG)
#endif
/* <sys/wait.h> */
-#if has_wait
- pid_t wait P((int*));
-#endif
#ifndef WEXITSTATUS
-# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
-# undef WIFEXITED /* Avoid 4.3BSD incompatibility with Posix. */
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#undef WIFEXITED /* Avoid 4.3BSD incompatibility with Posix. */
#endif
#ifndef WIFEXITED
-# define WIFEXITED(stat_val) (!((stat_val) & 255))
+#define WIFEXITED(stat_val) (((stat_val) & 0377) == 0)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(stat_val) ((stat_val) & 0177)
+#undef WIFSIGNALED /* Avoid 4.3BSD incompatibility with Posix. */
+#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(stat_val) ((unsigned)(stat_val) - 1 < 0377)
#endif
/* <unistd.h> */
char *getlogin P((void));
-int close P((int));
-int isatty P((int));
-int link P((char const*,char const*));
-int open P((char const*,int,...));
-int unlink P((char const*));
-int _filbuf P((FILE*)); /* keeps lint quiet in traditional C */
-int _flsbuf P((int,FILE*)); /* keeps lint quiet in traditional C */
-long pathconf P((char const*,int));
-ssize_t write P((int,void const*,size_t));
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
# define STDOUT_FILENO 1
# define STDERR_FILENO 2
#endif
-#if has_fork
-# if !has_vfork
-# undef vfork
-# define vfork fork
-# endif
- pid_t vfork P((void)); /* vfork is nonstandard but faster */
+#if has_fork && !has_vfork
+# undef vfork
+# define vfork fork
#endif
#if has_getcwd || !has_getwd
char *getcwd P((char*,size_t));
#else
char *getwd P((char*));
#endif
-#if has_getuid
- uid_t getuid P((void));
-#endif
-#if has_readlink
-/* ssize_t readlink P((char const*,char*,size_t)); *//* BSD; not standard yet */
-#endif
-#if has_setuid
-# if !has_seteuid
-# undef seteuid
-# define seteuid setuid
-# endif
- int seteuid P((uid_t));
- uid_t geteuid P((void));
+#if has_setuid && !has_seteuid
+# undef seteuid
+# define seteuid setuid
#endif
#if has_spawn
- int spawnv P((int,char const*,char*const*));
# if ALL_ABSOLUTE
# define spawn_RCS spawnv
# else
# define spawn_RCS spawnvp
- int spawnvp P((int,char const*,char*const*));
# endif
#else
- int execv P((char const*,char*const*));
# if ALL_ABSOLUTE
# define exec_RCS execv
# else
# define exec_RCS execvp
- int execvp P((char const*,char*const*));
# endif
#endif
/* utime.h */
-int utime P((char const*,struct utimbuf const*));
+#if !has_utimbuf
+ struct utimbuf { time_t actime, modtime; };
+#endif
/* Standard C library */
-/* These definitions are for the benefit of hosts that have */
-/* traditional C include files, possibly with Standard C compilers. */
-/* Unfortunately, mixed-up hosts are all too common. */
-
-/* <errno.h> */
-extern int errno;
-
-/* <limits.h> */
-#ifndef ULONG_MAX
- /* This does not work in #ifs, but it's good enough for us. */
-# define ULONG_MAX ((unsigned long)-1)
-#endif
-
-/* <signal.h> */
-#if has_signal
- signal_type (*signal P((int,signal_type(*)signal_args)))signal_args;
-#endif
/* <stdio.h> */
-FILE *fopen P((char const*,char const*));
-fread_type fread P((void*,freadarg_type,freadarg_type,FILE*));
-fread_type fwrite P((void const*,freadarg_type,freadarg_type,FILE*));
-int fclose P((FILE*));
-int feof P((FILE*));
-int ferror P((FILE*));
-int fflush P((FILE*));
-int fprintf P((FILE*,char const*,...));
-int fputs P((char const*,FILE*));
-int fseek P((FILE*,long,int));
-int printf P((char const*,...));
-int rename P((char const*,char const*));
-int sprintf P((char*,char const*,...));
-/* long ftell P((FILE*)); */
-void clearerr P((FILE*));
-void perror P((char const*));
#ifndef L_tmpnam
-# define L_tmpnam 32 /* power of 2 > sizeof("/usr/tmp/xxxxxxxxxxxxxxx") */
+#define L_tmpnam 32 /* power of 2 > sizeof("/usr/tmp/xxxxxxxxxxxxxxx") */
#endif
#ifndef SEEK_SET
-# define SEEK_SET 0
+#define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
#endif
#if has_mktemp
char *mktemp P((char*)); /* traditional */
#else
char *tmpnam P((char*));
#endif
-#if has_vfprintf
- int vfprintf P((FILE*,char const*,va_list));
-#else
-#if has__doprintf
- void _doprintf P((FILE*,char const*,va_list)); /* Minix */
-#else
- void _doprnt P((char const*,va_list,FILE*)); /* BSD */
-#endif
-#endif
/* <stdlib.h> */
char *getenv P((char const*));
+void _exit P((int)) exiting;
+void exit P((int)) exiting;
malloc_type malloc P((size_t));
malloc_type realloc P((malloc_type,size_t));
-void free P((malloc_type));
#ifndef EXIT_FAILURE
-# define EXIT_FAILURE 1
+#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
-#endif
-#if !has_fork && !has_spawn
- int system P((char const*));
+#define EXIT_SUCCESS 0
#endif
/* <string.h> */
char *strcpy P((char*,char const*));
char *strchr P((char const*,int));
char *strrchr P((char const*,int));
-int memcmp P((void const*,void const*,size_t));
-int strcmp P((char const*,char const*));
-size_t strlen P((char const*));
void *memcpy P((void*,void const*,size_t));
#if has_memmove
void *memmove P((void*,void const*,size_t));
diff --git a/gnu/usr.bin/rcs/lib/maketime.c b/gnu/usr.bin/rcs/lib/maketime.c
index b87d744..bf14bb9 100644
--- a/gnu/usr.bin/rcs/lib/maketime.c
+++ b/gnu/usr.bin/rcs/lib/maketime.c
@@ -1,347 +1,344 @@
-#
-/*
- * MAKETIME derive 32-bit time value from TM structure.
- *
- * Usage:
- * int zone; Minutes west of GMT, or
- * 48*60 for localtime
- * time_t t;
- * struct tm *tp; Pointer to TM structure from <time.h>
- * t = maketime(tp,zone);
- *
- * Returns:
- * -1 if failure; parameter out of range or nonsensical.
- * else time-value.
- * Notes:
- * This code is quasi-public; it may be used freely in like software.
- * It is not to be sold, nor used in licensed software without
- * permission of the author.
- * For everyone's benefit, please report bugs and improvements!
- * Copyright 1981 by Ken Harrenstien, SRI International.
- * (ARPANET: KLH @ SRI)
- */
-/* $Log: maketime.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
- * Updated GNU utilities
- *
- * Revision 5.3 1991/08/19 03:13:55 eggert
- * Add setfiledate, str2time, TZ_must_be_set.
- *
- * Revision 5.2 1990/11/01 05:03:30 eggert
- * Remove lint.
- *
- * Revision 5.1 1990/10/04 06:30:13 eggert
- * Calculate the GMT offset of 'xxx LT' as of xxx, not as of now.
- * Don't assume time_t is 32 bits. Fix bugs near epoch and near end of time.
- *
- * Revision 5.0 1990/08/22 08:12:38 eggert
- * Switch to GMT and fix the bugs exposed thereby.
- * Permit dates past 1999/12/31. Ansify and Posixate.
- *
- * Revision 1.8 88/11/08 13:54:53 narten
- * allow negative timezones (-24h <= x <= 24h)
- *
- * Revision 1.7 88/08/28 14:47:52 eggert
- * Allow cc -R. Remove unportable "#endif XXX"s.
- *
- * Revision 1.6 87/12/18 17:05:58 narten
- * include rcsparam.h
- *
- * Revision 1.5 87/12/18 11:35:51 narten
- * maketime.c: fixed USG code - you have tgo call "tzset" in order to have
- * "timezone" set. ("localtime" calls it, but it's probably better not to
- * count on "localtime" having been called.)
- *
- * Revision 1.4 87/10/18 10:26:57 narten
- * Updating version numbers. Changes relative to 1.0 are actually
- * relative to 1.2
- *
- * Revision 1.3 87/09/24 13:58:45 narten
- * Sources now pass through lint (if you ignore printf/sprintf/fprintf
- * warnings)
- *
- * Revision 1.2 87/03/27 14:21:48 jenkins
- * Port to suns
- *
- * Revision 1.2 83/12/05 10:12:56 wft
- * added cond. compilation for USG Unix; long timezone;
- *
- * Revision 1.1 82/05/06 11:38:00 wft
- * Initial revision
- *
- */
-
-
-#include "rcsbase.h"
-
-libId(maketId, "$Id: maketime.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp $")
-
-static struct tm const *time2tm P((time_t));
-
-#define given(v) (0 <= (v)) /* Negative values are unspecified. */
-
-static int const daytb[] = {
- /* # days in year thus far, indexed by month (0-12!!) */
- 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
-};
+/* Convert struct partime into time_t. */
- static time_t
-maketime(atm,zone)
- struct tm const *atm;
- int zone;
-{
- register struct tm const *tp;
- register int i;
- int year, yday, mon, day, hour, min, sec, leap, localzone;
- int attempts;
- time_t t, tres;
-
- attempts = 2;
- localzone = zone==48*60;
- tres = -1;
- year = mon = day = 0; /* Keep lint happy. */
-
- do {
-
- if (localzone || !given(atm->tm_year)) {
- if (tres == -1)
- if ((tres = time((time_t*)0)) == -1)
- return -1;
- tp = time2tm(tres);
- /* Get breakdowns of default time, adjusting to zone. */
- year = tp->tm_year; /* Use to set up defaults */
- yday = tp->tm_yday;
- mon = tp->tm_mon;
- day = tp->tm_mday;
- hour = tp->tm_hour;
- min = tp->tm_min;
- if (localzone) {
- tp = localtime(&tres);
- zone =
- min - tp->tm_min + 60*(
- hour - tp->tm_hour + 24*(
- /* If years differ, it's by one day. */
- year - tp->tm_year
- ? year - tp->tm_year
- : yday - tp->tm_yday));
- }
- /* Adjust the default day, month and year according to zone. */
- if ((min -= zone) < 0) {
- if (hour-(59-min)/60 < 0 && --day <= 0) {
- if (--mon < 0) {
- --year;
- mon = 11;
- }
- day = daytb[mon+1] - daytb[mon] + (mon==1&&!(year&3));
- }
- } else
- if (
- 24 <= hour+min/60 &&
- daytb[mon+1] - daytb[mon] + (mon==1&&!(year&3)) < ++day
- ) {
- if (11 < ++mon) {
- ++year;
- mon = 0;
- }
- day = 1;
- }
- }
- if (zone < -24*60 || 24*60 < zone)
- return -1;
+/* Copyright 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+This file is part of RCS.
-#ifdef DEBUG
-printf("first YMD: %d %d %d\n",year,mon,day);
-#endif
- tp = atm;
-
- /* First must find date, using specified year, month, day.
- * If one of these is unspecified, it defaults either to the
- * current date (if no more global spec was given) or to the
- * zero-value for that spec (i.e. a more global spec was seen).
- * Reject times that do not fit in time_t,
- * without assuming that time_t is 32 bits or is signed.
- */
- if (given(tp->tm_year))
- {
- year = tp->tm_year;
- mon = 0; /* Since year was given, default */
- day = 1; /* for remaining specs is zero */
- }
- if (year < 69) /* 1969/12/31 OK in some timezones. */
- return -1; /* ERR: year out of range */
- leap = !(year&3) && (year%100 || !((year+300)%400));
- year -= 70; /* UNIX time starts at 1970 */
+RCS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
- /*
- * Find day of year.
- */
- {
- if (given(tp->tm_mon))
- { mon = tp->tm_mon; /* Month was specified */
- day = 1; /* so set remaining default */
- }
- if (11 < (unsigned)mon)
- return -1; /* ERR: bad month */
- if (given(tp->tm_mday)) day = tp->tm_mday;
- if(day < 1
- || (((daytb[mon+1]-daytb[mon]) < day)
- && (day!=29 || mon!=1 || !leap) ))
- return -1; /* ERR: bad day */
- yday = daytb[mon] /* Add # of days in months so far */
- + ((leap /* Leap year, and past Feb? If */
- && mon>1)? 1:0) /* so, add leap day for this year */
- + day-1; /* And finally add # days this mon */
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
- }
- if (leap+365 <= (unsigned)yday)
- return -1; /* ERR: bad YDAY */
-
- if (year < 0) {
- if (yday != 364)
- return -1; /* ERR: too early */
- t = -1;
- } else {
- tres = year*365; /* Get # days of years so far */
- if (tres/365 != year)
- return -1; /* ERR: overflow */
- t = tres
- + ((year+1)>>2) /* plus # of leap days since 1970 */
- + yday; /* and finally add # days this year */
- if (t+4 < tres)
- return -1; /* ERR: overflow */
- }
- tres = t;
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- if (given(i = tp->tm_wday)) /* Check WDAY if present */
- if (i != (tres+4)%7) /* 1970/01/01 was Thu = 4 */
- return -1; /* ERR: bad WDAY */
+Report problems and direct all questions to:
-#ifdef DEBUG
-printf("YMD: %d %d %d, T=%ld\n",year,mon,day,tres);
-#endif
- /*
- * Now determine time. If not given, default to zeros
- * (since time is always the least global spec)
- */
- tres *= 86400L; /* Get # seconds (24*60*60) */
- if (tres/86400L != t)
- return -1; /* ERR: overflow */
- hour = min = sec = 0;
- if (given(tp->tm_hour)) hour = tp->tm_hour;
- if (given(tp->tm_min )) min = tp->tm_min;
- if (given(tp->tm_sec )) sec = tp->tm_sec;
- if (60 <= (unsigned)min || 60 < (unsigned)sec)
- return -1; /* ERR: MS out of range */
- if (24 <= (unsigned)hour)
- if(hour != 24 || (min+sec) !=0) /* Allow 24:00 */
- return -1; /* ERR: H out of range */
-
- t = tres;
- tres += sec + 60L*(zone + min + 60*hour);
-
-#ifdef DEBUG
-printf("HMS: %d %d %d T=%ld\n",hour,min,sec,tres);
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+#if has_conf_h
+# include "conf.h"
+#else
+# ifdef __STDC__
+# define P(x) x
+# else
+# define const
+# define P(x) ()
+# endif
+# include <stdlib.h>
+# include <time.h>
#endif
- if (!localzone) /* check for overflow */
- return (year<0 ? (tres<0||86400L<=tres) : tres<t) ? -1 : tres;
-
- /* Check results; LT may have had a different GMT offset back then. */
- tp = localtime(&tres);
- if (given(atm->tm_sec) && atm->tm_sec != tp->tm_sec)
- return -1; /* If seconds don't match, we're in trouble. */
- if (!(
- given(atm->tm_min) && atm->tm_min != tp->tm_min ||
- given(atm->tm_hour) && atm->tm_hour != tp->tm_hour ||
- given(atm->tm_mday) && atm->tm_mday != tp->tm_mday ||
- given(atm->tm_mon) && atm->tm_mon != tp->tm_mon ||
- given(atm->tm_year) && atm->tm_year != tp->tm_year
- ))
- return tres; /* Everything matches. */
-
- } while (--attempts);
-
- return -1;
+#include "partime.h"
+#include "maketime.h"
+
+char const maketId[]
+ = "$Id: maketime.c,v 5.11 1995/06/16 06:19:24 eggert Exp $";
+
+static int isleap P((int));
+static int month_days P((struct tm const*));
+static time_t maketime P((struct partime const*,time_t));
+
+/*
+* For maximum portability, use only localtime and gmtime.
+* Make no assumptions about the time_t epoch or the range of time_t values.
+* Avoid mktime because it's not universal and because there's no easy,
+* portable way for mktime to yield the inverse of gmtime.
+*/
+
+#define TM_YEAR_ORIGIN 1900
+
+ static int
+isleap(y)
+ int y;
+{
+ return (y&3) == 0 && (y%100 != 0 || y%400 == 0);
+}
+
+static int const month_yday[] = {
+ /* days in year before start of months 0-12 */
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+};
+
+/* Yield the number of days in TM's month. */
+ static int
+month_days(tm)
+ struct tm const *tm;
+{
+ int m = tm->tm_mon;
+ return month_yday[m+1] - month_yday[m]
+ + (m==1 && isleap(tm->tm_year + TM_YEAR_ORIGIN));
}
/*
-* Convert Unix time to struct tm format.
-* Use Coordinated Universal Time (UTC) if version 5 or newer;
-* use local time otherwise.
+* Convert UNIXTIME to struct tm form.
+* Use gmtime if available and if !LOCALZONE, localtime otherwise.
*/
- static struct tm const *
-time2tm(unixtime)
+ struct tm *
+time2tm(unixtime, localzone)
time_t unixtime;
+ int localzone;
{
- struct tm const *tm;
+ struct tm *tm;
# if TZ_must_be_set
static char const *TZ;
if (!TZ && !(TZ = getenv("TZ")))
- faterror("TZ is not set");
+ faterror("The TZ environment variable is not set; please set it to your timezone");
# endif
- if (!(tm = (RCSversion<VERSION(5) ? localtime : gmtime)(&unixtime)))
- faterror("UTC is not available; perhaps TZ is not set?");
+ if (localzone || !(tm = gmtime(&unixtime)))
+ tm = localtime(&unixtime);
return tm;
}
+/* Yield A - B, measured in seconds. */
+ time_t
+difftm(a, b)
+ struct tm const *a, *b;
+{
+ int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+ int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+ int difference_in_day_of_year = a->tm_yday - b->tm_yday;
+ int intervening_leap_days = (
+ ((ay >> 2) - (by >> 2))
+ - (ay/100 - by/100)
+ + ((ay/100 >> 2) - (by/100 >> 2))
+ );
+ time_t difference_in_years = ay - by;
+ time_t difference_in_days = (
+ difference_in_years*365
+ + (intervening_leap_days + difference_in_day_of_year)
+ );
+ return
+ (
+ (
+ 24*difference_in_days
+ + (a->tm_hour - b->tm_hour)
+ )*60 + (a->tm_min - b->tm_min)
+ )*60 + (a->tm_sec - b->tm_sec);
+}
+
/*
-* Convert Unix time to RCS format.
-* For compatibility with older versions of RCS,
-* dates before AD 2000 are stored without the leading "19".
+* Adjust time T by adding SECONDS. SECONDS must be at most 24 hours' worth.
+* Adjust only T's year, mon, mday, hour, min and sec members;
+* plus adjust wday if it is defined.
*/
void
-time2date(unixtime,date)
- time_t unixtime;
- char date[datesize];
+adjzone(t, seconds)
+ register struct tm *t;
+ long seconds;
{
- register struct tm const *tm = time2tm(unixtime);
- VOID sprintf(date, DATEFORM,
- tm->tm_year + (tm->tm_year<100 ? 0 : 1900),
- tm->tm_mon+1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec
- );
+ /*
+ * This code can be off by a second if SECONDS is not a multiple of 60,
+ * if T is local time, and if a leap second happens during this minute.
+ * But this bug has never occurred, and most likely will not ever occur.
+ * Liberia, the last country for which SECONDS % 60 was nonzero,
+ * switched to UTC in May 1972; the first leap second was in June 1972.
+ */
+ int leap_second = t->tm_sec == 60;
+ long sec = seconds + (t->tm_sec - leap_second);
+ if (sec < 0) {
+ if ((t->tm_min -= (59-sec)/60) < 0) {
+ if ((t->tm_hour -= (59-t->tm_min)/60) < 0) {
+ t->tm_hour += 24;
+ if (TM_DEFINED(t->tm_wday) && --t->tm_wday < 0)
+ t->tm_wday = 6;
+ if (--t->tm_mday <= 0) {
+ if (--t->tm_mon < 0) {
+ --t->tm_year;
+ t->tm_mon = 11;
+ }
+ t->tm_mday = month_days(t);
+ }
+ }
+ t->tm_min += 24 * 60;
+ }
+ sec += 24L * 60 * 60;
+ } else
+ if (60 <= (t->tm_min += sec/60))
+ if (24 <= (t->tm_hour += t->tm_min/60)) {
+ t->tm_hour -= 24;
+ if (TM_DEFINED(t->tm_wday) && ++t->tm_wday == 7)
+ t->tm_wday = 0;
+ if (month_days(t) < ++t->tm_mday) {
+ if (11 < ++t->tm_mon) {
+ ++t->tm_year;
+ t->tm_mon = 0;
+ }
+ t->tm_mday = 1;
+ }
+ }
+ t->tm_min %= 60;
+ t->tm_sec = (int) (sec%60) + leap_second;
}
+/*
+* Convert TM to time_t, using localtime if LOCALZONE and gmtime otherwise.
+* Use only TM's year, mon, mday, hour, min, and sec members.
+* Ignore TM's old tm_yday and tm_wday, but fill in their correct values.
+* Yield -1 on failure (e.g. a member out of range).
+* Posix 1003.1-1990 doesn't allow leap seconds, but some implementations
+* have them anyway, so allow them if localtime/gmtime does.
+*/
+ time_t
+tm2time(tm, localzone)
+ struct tm *tm;
+ int localzone;
+{
+ /* Cache the most recent t,tm pairs; 1 for gmtime, 1 for localtime. */
+ static time_t t_cache[2];
+ static struct tm tm_cache[2];
+
+ time_t d, gt;
+ struct tm const *gtm;
+ /*
+ * The maximum number of iterations should be enough to handle any
+ * combinations of leap seconds, time zone rule changes, and solar time.
+ * 4 is probably enough; we use a bigger number just to be safe.
+ */
+ int remaining_tries = 8;
+
+ /* Avoid subscript errors. */
+ if (12 <= (unsigned)tm->tm_mon)
+ return -1;
+
+ tm->tm_yday = month_yday[tm->tm_mon] + tm->tm_mday
+ - (tm->tm_mon<2 || ! isleap(tm->tm_year + TM_YEAR_ORIGIN));
+
+ /* Make a first guess. */
+ gt = t_cache[localzone];
+ gtm = gt ? &tm_cache[localzone] : time2tm(gt,localzone);
+
+ /* Repeatedly use the error from the guess to improve the guess. */
+ while ((d = difftm(tm, gtm)) != 0) {
+ if (--remaining_tries == 0)
+ return -1;
+ gt += d;
+ gtm = time2tm(gt,localzone);
+ }
+ t_cache[localzone] = gt;
+ tm_cache[localzone] = *gtm;
+
+ /*
+ * Check that the guess actually matches;
+ * overflow can cause difftm to yield 0 even on differing times,
+ * or tm may have members out of range (e.g. bad leap seconds).
+ */
+ if ( (tm->tm_year ^ gtm->tm_year)
+ | (tm->tm_mon ^ gtm->tm_mon)
+ | (tm->tm_mday ^ gtm->tm_mday)
+ | (tm->tm_hour ^ gtm->tm_hour)
+ | (tm->tm_min ^ gtm->tm_min)
+ | (tm->tm_sec ^ gtm->tm_sec))
+ return -1;
+ tm->tm_wday = gtm->tm_wday;
+ return gt;
+}
+/*
+* Check *PT and convert it to time_t.
+* If it is incompletely specified, use DEFAULT_TIME to fill it out.
+* Use localtime if PT->zone is the special value TM_LOCAL_ZONE.
+* Yield -1 on failure.
+* ISO 8601 day-of-year and week numbers are not yet supported.
+*/
static time_t
-str2time(source)
- char const *source;
-/* Parse a free-format date in SOURCE, yielding a Unix format time. */
+maketime(pt, default_time)
+ struct partime const *pt;
+ time_t default_time;
{
- int zone;
- time_t unixtime;
- struct tm parseddate;
+ int localzone, wday;
+ struct tm tm;
+ struct tm *tm0 = 0;
+ time_t r;
+
+ tm0 = 0; /* Keep gcc -Wall happy. */
+ localzone = pt->zone==TM_LOCAL_ZONE;
+
+ tm = pt->tm;
+
+ if (TM_DEFINED(pt->ymodulus) || !TM_DEFINED(tm.tm_year)) {
+ /* Get tm corresponding to current time. */
+ tm0 = time2tm(default_time, localzone);
+ if (!localzone)
+ adjzone(tm0, pt->zone);
+ }
+
+ if (TM_DEFINED(pt->ymodulus))
+ tm.tm_year +=
+ (tm0->tm_year + TM_YEAR_ORIGIN)/pt->ymodulus * pt->ymodulus;
+ else if (!TM_DEFINED(tm.tm_year)) {
+ /* Set default year, month, day from current time. */
+ tm.tm_year = tm0->tm_year + TM_YEAR_ORIGIN;
+ if (!TM_DEFINED(tm.tm_mon)) {
+ tm.tm_mon = tm0->tm_mon;
+ if (!TM_DEFINED(tm.tm_mday))
+ tm.tm_mday = tm0->tm_mday;
+ }
+ }
+
+ /* Convert from partime year (Gregorian) to Posix year. */
+ tm.tm_year -= TM_YEAR_ORIGIN;
+
+ /* Set remaining default fields to be their minimum values. */
+ if (!TM_DEFINED(tm.tm_mon)) tm.tm_mon = 0;
+ if (!TM_DEFINED(tm.tm_mday)) tm.tm_mday = 1;
+ if (!TM_DEFINED(tm.tm_hour)) tm.tm_hour = 0;
+ if (!TM_DEFINED(tm.tm_min)) tm.tm_min = 0;
+ if (!TM_DEFINED(tm.tm_sec)) tm.tm_sec = 0;
- if (!partime(source, &parseddate, &zone))
- faterror("can't parse date/time: %s", source);
- if ((unixtime = maketime(&parseddate, zone)) == -1)
- faterror("bad date/time: %s", source);
- return unixtime;
+ if (!localzone)
+ adjzone(&tm, -pt->zone);
+ wday = tm.tm_wday;
+
+ /* Convert and fill in the rest of the tm. */
+ r = tm2time(&tm, localzone);
+
+ /* Check weekday. */
+ if (r != -1 && TM_DEFINED(wday) && wday != tm.tm_wday)
+ return -1;
+
+ return r;
}
- void
-str2date(source, target)
+/* Parse a free-format date in SOURCE, yielding a Unix format time. */
+ time_t
+str2time(source, default_time, default_zone)
char const *source;
- char target[datesize];
-/* Parse a free-format date in SOURCE, convert it
- * into RCS internal format, and store the result into TARGET.
- */
+ time_t default_time;
+ long default_zone;
{
- time2date(str2time(source), target);
+ struct partime pt;
+
+ if (*partime(source, &pt))
+ return -1;
+ if (pt.zone == TM_UNDEFINED_ZONE)
+ pt.zone = default_zone;
+ return maketime(&pt, default_time);
}
+#if TEST
+#include <stdio.h>
int
-setfiledate(file, date)
- char const *file, date[datesize];
-/* Set the access and modification time of FILE to DATE. */
+main(argc, argv) int argc; char **argv;
{
- static struct utimbuf times; /* static so unused fields are zero */
- char datebuf[datesize];
-
- if (!date)
- return 0;
- times.actime = times.modtime = str2time(date2str(date, datebuf));
- return utime(file, &times);
+ time_t default_time = time((time_t *)0);
+ long default_zone = argv[1] ? atol(argv[1]) : 0;
+ char buf[1000];
+ while (gets(buf)) {
+ time_t t = str2time(buf, default_time, default_zone);
+ printf("%s", asctime(gmtime(&t)));
+ }
+ return 0;
}
+#endif
diff --git a/gnu/usr.bin/rcs/lib/merger.c b/gnu/usr.bin/rcs/lib/merger.c
index 003e0a6..fd36d26 100644
--- a/gnu/usr.bin/rcs/lib/merger.c
+++ b/gnu/usr.bin/rcs/lib/merger.c
@@ -77,7 +77,7 @@ merge(tostdout, edarg, label, argv)
for (i=3; 0<=--i; )
a[i] = normalize_arg(argv[i], &b[i]);
-
+
if (!edarg)
edarg = "-E";
diff --git a/gnu/usr.bin/rcs/lib/partime.c b/gnu/usr.bin/rcs/lib/partime.c
index 6c2c2a1..4246566 100644
--- a/gnu/usr.bin/rcs/lib/partime.c
+++ b/gnu/usr.bin/rcs/lib/partime.c
@@ -1,642 +1,701 @@
-/*
- * PARTIME parse date/time string into a TM structure
- *
- * Returns:
- * 0 if parsing failed
- * else time values in specified TM structure and zone (unspecified values
- * set to TMNULL)
- * Notes:
- * This code is quasi-public; it may be used freely in like software.
- * It is not to be sold, nor used in licensed software without
- * permission of the author.
- * For everyone's benefit, please report bugs and improvements!
- * Copyright 1980 by Ken Harrenstien, SRI International.
- * (ARPANET: KLH @ SRI)
- */
-
-/* Hacknotes:
- * If parsing changed so that no backup needed, could perhaps modify
- * to use a FILE input stream. Need terminator, though.
- * Perhaps should return 0 on success, else a non-zero error val?
- */
-
-/* $Log: partime.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
- * Updated GNU utilities
- *
- * Revision 5.6 1991/08/19 03:13:55 eggert
- * Update timezones.
- *
- * Revision 5.5 1991/04/21 11:58:18 eggert
- * Don't put , just before } in initializer.
- *
- * Revision 5.4 1990/10/04 06:30:15 eggert
- * Remove date vs time heuristics that fail between 2000 and 2400.
- * Check for overflow when lexing an integer.
- * Parse 'Jan 10 LT' as 'Jan 10, LT', not 'Jan, 10 LT'.
- *
- * Revision 5.3 1990/09/24 18:56:31 eggert
- * Update timezones.
- *
- * Revision 5.2 1990/09/04 08:02:16 eggert
- * Don't parse two-digit years, because it won't work after 1999/12/31.
- * Don't permit 'Aug Aug'.
- *
- * Revision 5.1 1990/08/29 07:13:49 eggert
- * Be able to parse our own date format. Don't assume year<10000.
- *
- * Revision 5.0 1990/08/22 08:12:40 eggert
- * Switch to GMT and fix the bugs exposed thereby. Update timezones.
- * Ansify and Posixate. Fix peekahead and int-size bugs.
- *
- * Revision 1.4 89/05/01 14:48:46 narten
- * fixed #ifdef DEBUG construct
- *
- * Revision 1.3 88/08/28 14:53:40 eggert
- * Remove unportable "#endif XXX"s.
- *
- * Revision 1.2 87/03/27 14:21:53 jenkins
- * Port to suns
- *
- * Revision 1.1 82/05/06 11:38:26 wft
- * Initial revision
- *
- */
-
-#include "rcsbase.h"
-
-libId(partId, "$Id: partime.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp $")
-
-#define given(v) (0 <= (v))
-#define TMNULL (-1) /* Items not given are given this value */
-#define TZ_OFFSET (24*60) /* TMNULL < zone_offset - TZ_OFFSET */
-
-struct tmwent {
- char const *went;
- short wval;
- char wflgs;
- char wtype;
-};
- /* wflgs */
-#define TWTIME 02 /* Word is a time value (absence implies date) */
-#define TWDST 04 /* Word is a DST-type timezone */
- /* wtype */
-#define TM_MON 1 /* month name */
-#define TM_WDAY 2 /* weekday name */
-#define TM_ZON 3 /* time zone name */
-#define TM_LT 4 /* local time */
-#define TM_DST 5 /* daylight savings time */
-#define TM_12 6 /* AM, PM, NOON, or MIDNIGHT */
- /* wval (for wtype==TM_12) */
-#define T12_AM 1
-#define T12_PM 2
-#define T12_NOON 12
-#define T12_MIDNIGHT 0
-
-static struct tmwent const tmwords [] = {
- {"january", 0, 0, TM_MON},
- {"february", 1, 0, TM_MON},
- {"march", 2, 0, TM_MON},
- {"april", 3, 0, TM_MON},
- {"may", 4, 0, TM_MON},
- {"june", 5, 0, TM_MON},
- {"july", 6, 0, TM_MON},
- {"august", 7, 0, TM_MON},
- {"september", 8, 0, TM_MON},
- {"october", 9, 0, TM_MON},
- {"november", 10, 0, TM_MON},
- {"december", 11, 0, TM_MON},
-
- {"sunday", 0, 0, TM_WDAY},
- {"monday", 1, 0, TM_WDAY},
- {"tuesday", 2, 0, TM_WDAY},
- {"wednesday", 3, 0, TM_WDAY},
- {"thursday", 4, 0, TM_WDAY},
- {"friday", 5, 0, TM_WDAY},
- {"saturday", 6, 0, TM_WDAY},
-
- {"gmt", 0*60, TWTIME, TM_ZON}, /* Greenwich */
- {"utc", 0*60, TWTIME, TM_ZON},
- {"ut", 0*60, TWTIME, TM_ZON},
- {"cut", 0*60, TWTIME, TM_ZON},
-
- {"nzst", -12*60, TWTIME, TM_ZON}, /* New Zealand */
- {"jst", -9*60, TWTIME, TM_ZON}, /* Japan */
- {"kst", -9*60, TWTIME, TM_ZON}, /* Korea */
- {"ist", -5*60-30, TWTIME, TM_ZON},/* India */
- {"eet", -2*60, TWTIME, TM_ZON}, /* Eastern Europe */
- {"cet", -1*60, TWTIME, TM_ZON}, /* Central Europe */
- {"met", -1*60, TWTIME, TM_ZON}, /* Middle Europe */
- {"wet", 0*60, TWTIME, TM_ZON}, /* Western Europe */
- {"nst", 3*60+30, TWTIME, TM_ZON},/* Newfoundland */
- {"ast", 4*60, TWTIME, TM_ZON}, /* Atlantic */
- {"est", 5*60, TWTIME, TM_ZON}, /* Eastern */
- {"cst", 6*60, TWTIME, TM_ZON}, /* Central */
- {"mst", 7*60, TWTIME, TM_ZON}, /* Mountain */
- {"pst", 8*60, TWTIME, TM_ZON}, /* Pacific */
- {"akst", 9*60, TWTIME, TM_ZON}, /* Alaska */
- {"hast", 10*60, TWTIME, TM_ZON}, /* Hawaii-Aleutian */
- {"hst", 10*60, TWTIME, TM_ZON}, /* Hawaii */
- {"sst", 11*60, TWTIME, TM_ZON}, /* Samoa */
-
- {"nzdt", -12*60, TWTIME+TWDST, TM_ZON}, /* New Zealand */
- {"kdt", -9*60, TWTIME+TWDST, TM_ZON}, /* Korea */
- {"bst", 0*60, TWTIME+TWDST, TM_ZON}, /* Britain */
- {"ndt", 3*60+30, TWTIME+TWDST, TM_ZON}, /* Newfoundland */
- {"adt", 4*60, TWTIME+TWDST, TM_ZON}, /* Atlantic */
- {"edt", 5*60, TWTIME+TWDST, TM_ZON}, /* Eastern */
- {"cdt", 6*60, TWTIME+TWDST, TM_ZON}, /* Central */
- {"mdt", 7*60, TWTIME+TWDST, TM_ZON}, /* Mountain */
- {"pdt", 8*60, TWTIME+TWDST, TM_ZON}, /* Pacific */
- {"akdt", 9*60, TWTIME+TWDST, TM_ZON}, /* Alaska */
- {"hadt", 10*60, TWTIME+TWDST, TM_ZON}, /* Hawaii-Aleutian */
+/* Parse a string, yielding a struct partime that describes it. */
-#if 0
- /*
- * The following names are duplicates or are not well attested.
- * A standard is needed.
- */
- {"east", -10*60, TWTIME, TM_ZON}, /* Eastern Australia */
- {"cast", -9*60-30, TWTIME, TM_ZON},/* Central Australia */
- {"cst", -8*60, TWTIME, TM_ZON}, /* China */
- {"hkt", -8*60, TWTIME, TM_ZON}, /* Hong Kong */
- {"sst", -8*60, TWTIME, TM_ZON}, /* Singapore */
- {"wast", -8*60, TWTIME, TM_ZON}, /* Western Australia */
- {"?", -6*60-30, TWTIME, TM_ZON},/* Burma */
- {"?", -4*60-30, TWTIME, TM_ZON},/* Afghanistan */
- {"it", -3*60-30, TWTIME, TM_ZON},/* Iran */
- {"ist", -2*60, TWTIME, TM_ZON}, /* Israel */
- {"mez", -1*60, TWTIME, TM_ZON}, /* Mittel-Europaeische Zeit */
- {"ast", 1*60, TWTIME, TM_ZON}, /* Azores */
- {"fst", 2*60, TWTIME, TM_ZON}, /* Fernando de Noronha */
- {"bst", 3*60, TWTIME, TM_ZON}, /* Brazil */
- {"wst", 4*60, TWTIME, TM_ZON}, /* Western Brazil */
- {"ast", 5*60, TWTIME, TM_ZON}, /* Acre Brazil */
- {"?", 9*60+30, TWTIME, TM_ZON},/* Marquesas */
- {"?", 12*60, TWTIME, TM_ZON}, /* Kwajalein */
-
- {"eadt", -10*60, TWTIME+TWDST, TM_ZON}, /* Eastern Australia */
- {"cadt", -9*60-30, TWTIME+TWDST, TM_ZON}, /* Central Australia */
- {"cdt", -8*60, TWTIME+TWDST, TM_ZON}, /* China */
- {"wadt", -8*60, TWTIME+TWDST, TM_ZON}, /* Western Australia */
- {"idt", -2*60, TWTIME+TWDST, TM_ZON}, /* Israel */
- {"eest", -2*60, TWTIME+TWDST, TM_ZON}, /* Eastern Europe */
- {"cest", -1*60, TWTIME+TWDST, TM_ZON}, /* Central Europe */
- {"mest", -1*60, TWTIME+TWDST, TM_ZON}, /* Middle Europe */
- {"mesz", -1*60, TWTIME+TWDST, TM_ZON}, /* Mittel-Europaeische Sommerzeit */
- {"west", 0*60, TWTIME+TWDST, TM_ZON}, /* Western Europe */
- {"adt", 1*60, TWTIME+TWDST, TM_ZON}, /* Azores */
- {"fdt", 2*60, TWTIME+TWDST, TM_ZON}, /* Fernando de Noronha */
- {"edt", 3*60, TWTIME+TWDST, TM_ZON}, /* Eastern Brazil */
- {"wdt", 4*60, TWTIME+TWDST, TM_ZON}, /* Western Brazil */
- {"adt", 5*60, TWTIME+TWDST, TM_ZON}, /* Acre Brazil */
+/* Copyright 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+#if has_conf_h
+# include "conf.h"
+#else
+# ifdef __STDC__
+# define P(x) x
+# else
+# define const
+# define P(x) ()
+# endif
+# include <limits.h>
+# include <time.h>
#endif
- {"lt", 0, TWTIME, TM_LT}, /* local time */
- {"dst", 1*60, TWTIME, TM_DST}, /* daylight savings time */
- {"ddst", 2*60, TWTIME, TM_DST}, /* double dst */
+#include <ctype.h>
+#undef isdigit
+#define isdigit(c) (((unsigned)(c)-'0') <= 9) /* faster than stock */
+
+#include "partime.h"
+
+char const partimeId[]
+ = "$Id: partime.c,v 5.13 1995/06/16 06:19:24 eggert Exp $";
- {"am", T12_AM, TWTIME, TM_12},
- {"pm", T12_PM, TWTIME, TM_12},
- {"noon", T12_NOON, TWTIME, TM_12},
- {"midnight", T12_MIDNIGHT, TWTIME, TM_12},
- {0, 0, 0, 0} /* Zero entry to terminate searches */
+/* Lookup tables for names of months, weekdays, time zones. */
+
+#define NAME_LENGTH_MAXIMUM 4
+
+struct name_val {
+ char name[NAME_LENGTH_MAXIMUM];
+ int val;
};
-struct token {
- char const *tcp;/* pointer to string */
- int tcnt; /* # chars */
- char tbrk; /* "break" char */
- char tbrkl; /* last break char */
- char tflg; /* 0 = alpha, 1 = numeric */
- union { /* Resulting value; */
- int tnum;/* either a #, or */
- struct tmwent const *ttmw;/* a ptr to a tmwent. */
- } tval;
+
+static char const *parse_decimal P((char const*,int,int,int,int,int*,int*));
+static char const *parse_fixed P((char const*,int,int*));
+static char const *parse_pattern_letter P((char const*,int,struct partime*));
+static char const *parse_prefix P((char const*,struct partime*,int*));
+static char const *parse_ranged P((char const*,int,int,int,int*));
+static int lookup P((char const*,struct name_val const[]));
+static int merge_partime P((struct partime*, struct partime const*));
+static void undefine P((struct partime*));
+
+
+static struct name_val const month_names[] = {
+ {"jan",0}, {"feb",1}, {"mar",2}, {"apr",3}, {"may",4}, {"jun",5},
+ {"jul",6}, {"aug",7}, {"sep",8}, {"oct",9}, {"nov",10}, {"dec",11},
+ {"", TM_UNDEFINED}
};
-static struct tmwent const*ptmatchstr P((char const*,int,struct tmwent const*));
-static int pt12hack P((struct tm *,int));
-static int ptitoken P((struct token *));
-static int ptstash P((int *,int));
-static int pttoken P((struct token *));
+static struct name_val const weekday_names[] = {
+ {"sun",0}, {"mon",1}, {"tue",2}, {"wed",3}, {"thu",4}, {"fri",5}, {"sat",6},
+ {"", TM_UNDEFINED}
+};
+
+#define hr60nonnegative(t) ((t)/100 * 60 + (t)%100)
+#define hr60(t) ((t)<0 ? -hr60nonnegative(-(t)) : hr60nonnegative(t))
+#define zs(t,s) {s, hr60(t)}
+#define zd(t,s,d) zs(t, s), zs((t)+100, d)
+
+static struct name_val const zone_names[] = {
+ zs(-1000, "hst"), /* Hawaii */
+ zd(-1000,"hast","hadt"),/* Hawaii-Aleutian */
+ zd(- 900,"akst","akdt"),/* Alaska */
+ zd(- 800, "pst", "pdt"),/* Pacific */
+ zd(- 700, "mst", "mdt"),/* Mountain */
+ zd(- 600, "cst", "cdt"),/* Central */
+ zd(- 500, "est", "edt"),/* Eastern */
+ zd(- 400, "ast", "adt"),/* Atlantic */
+ zd(- 330, "nst", "ndt"),/* Newfoundland */
+ zs( 000, "utc"), /* Coordinated Universal */
+ zs( 000, "cut"), /* " */
+ zs( 000, "ut"), /* Universal */
+ zs( 000, "z"), /* Zulu (required by ISO 8601) */
+ zd( 000, "gmt", "bst"),/* Greenwich Mean, British Summer */
+ zs( 000, "wet"), /* Western Europe */
+ zs( 100, "met"), /* Middle Europe */
+ zs( 100, "cet"), /* Central Europe */
+ zs( 200, "eet"), /* Eastern Europe */
+ zs( 530, "ist"), /* India */
+ zd( 900, "jst", "jdt"),/* Japan */
+ zd( 900, "kst", "kdt"),/* Korea */
+ zd( 1200,"nzst","nzdt"),/* New Zealand */
+ { "lt", 1 },
+#if 0
+ /* The following names are duplicates or are not well attested. */
+ zs(-1100, "sst"), /* Samoa */
+ zs(-1000, "tht"), /* Tahiti */
+ zs(- 930, "mqt"), /* Marquesas */
+ zs(- 900, "gbt"), /* Gambier */
+ zd(- 900, "yst", "ydt"),/* Yukon - name is no longer used */
+ zs(- 830, "pit"), /* Pitcairn */
+ zd(- 500, "cst", "cdt"),/* Cuba */
+ zd(- 500, "ast", "adt"),/* Acre */
+ zd(- 400, "wst", "wdt"),/* Western Brazil */
+ zd(- 400, "ast", "adt"),/* Andes */
+ zd(- 400, "cst", "cdt"),/* Chile */
+ zs(- 300, "wgt"), /* Western Greenland */
+ zd(- 300, "est", "edt"),/* Eastern South America */
+ zs(- 300, "mgt"), /* Middle Greenland */
+ zd(- 200, "fst", "fdt"),/* Fernando de Noronha */
+ zs(- 100, "egt"), /* Eastern Greenland */
+ zs(- 100, "aat"), /* Atlantic Africa */
+ zs(- 100, "act"), /* Azores and Canaries */
+ zs( 000, "wat"), /* West Africa */
+ zs( 100, "cat"), /* Central Africa */
+ zd( 100, "mez","mesz"),/* Mittel-Europaeische Zeit */
+ zs( 200, "sat"), /* South Africa */
+ zd( 200, "ist", "idt"),/* Israel */
+ zs( 300, "eat"), /* East Africa */
+ zd( 300, "ast", "adt"),/* Arabia */
+ zd( 300, "msk", "msd"),/* Moscow */
+ zd( 330, "ist", "idt"),/* Iran */
+ zs( 400, "gst"), /* Gulf */
+ zs( 400, "smt"), /* Seychelles & Mascarene */
+ zd( 400, "esk", "esd"),/* Yekaterinburg */
+ zd( 400, "bsk", "bsd"),/* Baku */
+ zs( 430, "aft"), /* Afghanistan */
+ zd( 500, "osk", "osd"),/* Omsk */
+ zs( 500, "pkt"), /* Pakistan */
+ zd( 500, "tsk", "tsd"),/* Tashkent */
+ zs( 545, "npt"), /* Nepal */
+ zs( 600, "bgt"), /* Bangladesh */
+ zd( 600, "nsk", "nsd"),/* Novosibirsk */
+ zs( 630, "bmt"), /* Burma */
+ zs( 630, "cct"), /* Cocos */
+ zs( 700, "ict"), /* Indochina */
+ zs( 700, "jvt"), /* Java */
+ zd( 700, "isk", "isd"),/* Irkutsk */
+ zs( 800, "hkt"), /* Hong Kong */
+ zs( 800, "pst"), /* Philippines */
+ zs( 800, "sgt"), /* Singapore */
+ zd( 800, "cst", "cdt"),/* China */
+ zd( 800, "ust", "udt"),/* Ulan Bator */
+ zd( 800, "wst", "wst"),/* Western Australia */
+ zd( 800, "ysk", "ysd"),/* Yakutsk */
+ zs( 900, "blt"), /* Belau */
+ zs( 900, "mlt"), /* Moluccas */
+ zd( 900, "vsk", "vsd"),/* Vladivostok */
+ zd( 930, "cst", "cst"),/* Central Australia */
+ zs( 1000, "gst"), /* Guam */
+ zd( 1000, "gsk", "gsd"),/* Magadan */
+ zd( 1000, "est", "est"),/* Eastern Australia */
+ zd( 1100,"lhst","lhst"),/* Lord Howe */
+ zd( 1100, "psk", "psd"),/* Petropavlovsk-Kamchatski */
+ zs( 1100,"ncst"), /* New Caledonia */
+ zs( 1130,"nrft"), /* Norfolk */
+ zd( 1200, "ask", "asd"),/* Anadyr */
+ zs( 1245,"nz-chat"), /* Chatham */
+ zs( 1300, "tgt"), /* Tongatapu */
+#endif
+ {"", -1}
+};
static int
-goodzone(t, offset, am)
- register struct token const *t;
- int offset;
- int *am;
+lookup (s, table)
+ char const *s;
+ struct name_val const table[];
+/* Look for a prefix of S in TABLE, returning val for first matching entry. */
{
- register int m;
- if (
- t->tflg &&
- t->tcnt == 4+offset &&
- (m = t->tval.tnum) <= 2400 &&
- isdigit(t->tcp[offset]) &&
- (m%=100) < 60
- ) {
- m += t->tval.tnum/100 * 60;
- if (t->tcp[offset-1]=='+')
- m = -m;
- *am = m;
- return 1;
+ int j;
+ char buf[NAME_LENGTH_MAXIMUM];
+
+ for (j = 0; j < NAME_LENGTH_MAXIMUM; j++) {
+ unsigned char c = *s++;
+ buf[j] = isupper (c) ? tolower (c) : c;
+ if (!isalpha (c))
+ break;
+ }
+ for (; table[0].name[0]; table++)
+ for (j = 0; buf[j] == table[0].name[j]; )
+ if (++j == NAME_LENGTH_MAXIMUM || !table[0].name[j])
+ goto done;
+ done:
+ return table[0].val;
+}
+
+
+ static void
+undefine (t) struct partime *t;
+/* Set *T to ``undefined'' values. */
+{
+ t->tm.tm_sec = t->tm.tm_min = t->tm.tm_hour = t->tm.tm_mday = t->tm.tm_mon
+ = t->tm.tm_year = t->tm.tm_wday = t->tm.tm_yday
+ = t->ymodulus = t->yweek
+ = TM_UNDEFINED;
+ t->zone = TM_UNDEFINED_ZONE;
+}
+
+/*
+* Array of patterns to look for in a date string.
+* Order is important: we look for the first matching pattern
+* whose values do not contradict values that we already know about.
+* See `parse_pattern_letter' below for the meaning of the pattern codes.
+*/
+static char const * const patterns[] = {
+ /*
+ * These traditional patterns must come first,
+ * to prevent an ISO 8601 format from misinterpreting their prefixes.
+ */
+ "E_n_y", "x", /* RFC 822 */
+ "E_n", "n_E", "n", "t:m:s_A", "t:m_A", "t_A", /* traditional */
+ "y/N/D$", /* traditional RCS */
+
+ /* ISO 8601:1988 formats, generalized a bit. */
+ "y-N-D$", "4ND$", "Y-N$",
+ "RND$", "-R=N$", "-R$", "--N=D$", "N=DT",
+ "--N$", "---D$", "DT",
+ "Y-d$", "4d$", "R=d$", "-d$", "dT",
+ "y-W-X", "yWX", "y=W",
+ "-r-W-X", "r-W-XT", "-rWX", "rWXT", "-W=X", "W=XT", "-W",
+ "-w-X", "w-XT", "---X$", "XT", "4$",
+ "T",
+ "h:m:s$", "hms$", "h:m$", "hm$", "h$", "-m:s$", "-ms$", "-m$", "--s$",
+ "Y", "Z",
+
+ 0
+};
+
+ static char const *
+parse_prefix (str, t, pi) char const *str; struct partime *t; int *pi;
+/*
+* Parse an initial prefix of STR, setting *T accordingly.
+* Return the first character after the prefix, or 0 if it couldn't be parsed.
+* Start with pattern *PI; if success, set *PI to the next pattern to try.
+* Set *PI to -1 if we know there are no more patterns to try;
+* if *PI is initially negative, give up immediately.
+*/
+{
+ int i = *pi;
+ char const *pat;
+ unsigned char c;
+
+ if (i < 0)
+ return 0;
+
+ /* Remove initial noise. */
+ while (!isalnum (c = *str) && c != '-' && c != '+') {
+ if (!c) {
+ undefine (t);
+ *pi = -1;
+ return str;
+ }
+ str++;
}
+
+ /* Try a pattern until one succeeds. */
+ while ((pat = patterns[i++]) != 0) {
+ char const *s = str;
+ undefine (t);
+ do {
+ if (!(c = *pat++)) {
+ *pi = i;
+ return s;
+ }
+ } while ((s = parse_pattern_letter (s, c, t)) != 0);
+ }
+
return 0;
}
- int
-partime(astr, atm, zone)
-char const *astr;
-register struct tm *atm;
-int *zone;
+ static char const *
+parse_fixed (s, digits, res) char const *s; int digits, *res;
+/*
+* Parse an initial prefix of S of length DIGITS; it must be a number.
+* Store the parsed number into *RES.
+* Return the first character after the prefix, or 0 if it couldn't be parsed.
+*/
{
- register int i;
- struct token btoken, atoken;
- int zone_offset; /* minutes west of GMT, plus TZ_OFFSET */
- register char const *cp;
- register char ch;
- int ord, midnoon;
- int *atmfield, dst, m;
- int got1 = 0;
-
- atm->tm_sec = TMNULL;
- atm->tm_min = TMNULL;
- atm->tm_hour = TMNULL;
- atm->tm_mday = TMNULL;
- atm->tm_mon = TMNULL;
- atm->tm_year = TMNULL;
- atm->tm_wday = TMNULL;
- atm->tm_yday = TMNULL;
- midnoon = TMNULL; /* and our own temp stuff */
- zone_offset = TMNULL;
- dst = TMNULL;
- btoken.tcnt = btoken.tbrk = 0;
- btoken.tcp = astr;
-
- for (;; got1=1) {
- if (!ptitoken(&btoken)) /* Get a token */
- { if(btoken.tval.tnum) return(0); /* Read error? */
- if (given(midnoon)) /* EOF, wrap up */
- if (!pt12hack(atm, midnoon))
- return 0;
- if (!given(atm->tm_min))
- atm->tm_min = 0;
- *zone =
- (given(zone_offset) ? zone_offset-TZ_OFFSET : 0)
- - (given(dst) ? dst : 0);
- return got1;
- }
- if(btoken.tflg == 0) /* Alpha? */
- { i = btoken.tval.ttmw->wval;
- switch (btoken.tval.ttmw->wtype) {
- default:
+ int n = 0;
+ char const *lim = s + digits;
+ while (s < lim) {
+ unsigned d = *s++ - '0';
+ if (9 < d)
return 0;
- case TM_MON:
- atmfield = &atm->tm_mon;
- break;
- case TM_WDAY:
- atmfield = &atm->tm_wday;
- break;
- case TM_DST:
- atmfield = &dst;
+ n = 10*n + d;
+ }
+ *res = n;
+ return s;
+}
+
+ static char const *
+parse_ranged (s, digits, lo, hi, res) char const *s; int digits, lo, hi, *res;
+/*
+* Parse an initial prefix of S of length DIGITS;
+* it must be a number in the range LO through HI.
+* Store the parsed number into *RES.
+* Return the first character after the prefix, or 0 if it couldn't be parsed.
+*/
+{
+ s = parse_fixed (s, digits, res);
+ return s && lo<=*res && *res<=hi ? s : 0;
+}
+
+ static char const *
+parse_decimal (s, digits, lo, hi, resolution, res, fres)
+ char const *s;
+ int digits, lo, hi, resolution, *res, *fres;
+/*
+* Parse an initial prefix of S of length DIGITS;
+* it must be a number in the range LO through HI
+* and it may be followed by a fraction that is to be computed using RESOLUTION.
+* Store the parsed number into *RES; store the fraction times RESOLUTION,
+* rounded to the nearest integer, into *FRES.
+* Return the first character after the prefix, or 0 if it couldn't be parsed.
+*/
+{
+ s = parse_fixed (s, digits, res);
+ if (s && lo<=*res && *res<=hi) {
+ int f = 0;
+ if ((s[0]==',' || s[0]=='.') && isdigit ((unsigned char) s[1])) {
+ char const *s1 = ++s;
+ int num10 = 0, denom10 = 10, product;
+ while (isdigit ((unsigned char) *++s))
+ denom10 *= 10;
+ s = parse_fixed (s1, s - s1, &num10);
+ product = num10*resolution;
+ f = (product + (denom10>>1)) / denom10;
+ f -= f & (product%denom10 == denom10>>1); /* round to even */
+ if (f < 0 || product/resolution != num10)
+ return 0; /* overflow */
+ }
+ *fres = f;
+ return s;
+ }
+ return 0;
+}
+
+ char *
+parzone (s, zone) char const *s; long *zone;
+/*
+* Parse an initial prefix of S; it must denote a time zone.
+* Set *ZONE to the number of seconds east of GMT,
+* or to TM_LOCAL_ZONE if it is the local time zone.
+* Return the first character after the prefix, or 0 if it couldn't be parsed.
+*/
+{
+ char sign;
+ int hh, mm, ss;
+ int minutesEastOfUTC;
+ long offset, z;
+
+ /*
+ * The formats are LT, n, n DST, nDST, no, o
+ * where n is a time zone name
+ * and o is a time zone offset of the form [-+]hh[:mm[:ss]].
+ */
+ switch (*s) {
+ case '-': case '+':
+ z = 0;
break;
- case TM_LT:
- if (ptstash(&dst, 0))
+
+ default:
+ minutesEastOfUTC = lookup (s, zone_names);
+ if (minutesEastOfUTC == -1)
return 0;
- i = 48*60; /* local time magic number -- see maketime() */
- /* fall into */
- case TM_ZON:
- i += TZ_OFFSET;
- if (btoken.tval.ttmw->wflgs & TWDST)
- if (ptstash(&dst, 60))
- return 0;
- /* Peek ahead for offset immediately afterwards. */
+
+ /* Don't bother to check rest of spelling. */
+ while (isalpha ((unsigned char) *s))
+ s++;
+
+ /* Don't modify LT. */
+ if (minutesEastOfUTC == 1) {
+ *zone = TM_LOCAL_ZONE;
+ return (char *) s;
+ }
+
+ z = minutesEastOfUTC * 60L;
+
+ /* Look for trailing " DST". */
+ if (
+ (s[-1]=='T' || s[-1]=='t') &&
+ (s[-2]=='S' || s[-2]=='s') &&
+ (s[-3]=='D' || s[-3]=='t')
+ )
+ goto trailing_dst;
+ while (isspace ((unsigned char) *s))
+ s++;
if (
- (btoken.tbrk=='-' || btoken.tbrk=='+') &&
- (atoken=btoken, ++atoken.tcnt, ptitoken(&atoken)) &&
- goodzone(&atoken, 0, &m)
+ (s[0]=='D' || s[0]=='d') &&
+ (s[1]=='S' || s[1]=='s') &&
+ (s[2]=='T' || s[2]=='t')
) {
- i += m;
- btoken = atoken;
+ s += 3;
+ trailing_dst:
+ *zone = z + 60*60;
+ return (char *) s;
+ }
+
+ switch (*s) {
+ case '-': case '+': break;
+ default: return (char *) s;
}
- atmfield = &zone_offset;
- break;
- case TM_12:
- atmfield = &midnoon;
- }
- if (ptstash(atmfield, i))
- return(0); /* ERR: val already set */
- continue;
- }
-
- /* Token is number. Lots of hairy heuristics. */
- if (!isdigit(*btoken.tcp)) {
- if (!goodzone(&btoken, 1, &m))
- return 0;
- zone_offset = TZ_OFFSET + m;
- continue;
}
+ sign = *s++;
- i = btoken.tval.tnum; /* Value now known to be valid; get it. */
- if (btoken.tcnt == 3) /* 3 digits = HMM */
- {
-hhmm4: if (ptstash(&atm->tm_min, i%100))
- return(0); /* ERR: min conflict */
- i /= 100;
-hh2: if (ptstash(&atm->tm_hour, i))
- return(0); /* ERR: hour conflict */
- continue;
- }
-
- if (4 < btoken.tcnt)
- goto year4; /* far in the future */
- if(btoken.tcnt == 4) /* 4 digits = YEAR or HHMM */
- { if (given(atm->tm_year)) goto hhmm4; /* Already got yr? */
- if (given(atm->tm_hour)) goto year4; /* Already got hr? */
- if(btoken.tbrk == ':') /* HHMM:SS ? */
- if ( ptstash(&atm->tm_hour, i/100)
- || ptstash(&atm->tm_min, i%100))
- return(0); /* ERR: hr/min clash */
- else goto coltm2; /* Go handle SS */
- if(btoken.tbrk != ',' && btoken.tbrk != '/'
- && (atoken=btoken, ptitoken(&atoken)) /* Peek */
- && ( atoken.tflg
- ? !isdigit(*atoken.tcp)
- : atoken.tval.ttmw->wflgs & TWTIME)) /* HHMM-ZON */
- goto hhmm4;
- goto year4; /* Give up, assume year. */
- }
-
- /* From this point on, assume tcnt == 1 or 2 */
- /* 2 digits = MM, DD, or HH (MM and SS caught at coltime) */
- if(btoken.tbrk == ':') /* HH:MM[:SS] */
- goto coltime; /* must be part of time. */
- if (31 < i)
+ if (!(s = parse_ranged (s, 2, 0, 23, &hh)))
return 0;
-
- /* Check for numerical-format date */
- for (cp = "/-."; ch = *cp++;)
- { ord = (ch == '.' ? 0 : 1); /* n/m = D/M or M/D */
- if(btoken.tbrk == ch) /* "NN-" */
- { if(btoken.tbrkl != ch)
- {
- atoken = btoken;
- atoken.tcnt++;
- if (ptitoken(&atoken)
- && atoken.tflg == 0
- && atoken.tval.ttmw->wtype == TM_MON)
- goto dd2;
- if(ord)goto mm2; else goto dd2; /* "NN-" */
- } /* "-NN-" */
- if (!given(atm->tm_mday)
- && given(atm->tm_year)) /* If "YYYY-NN-" */
- goto mm2; /* then always MM */
- if(ord)goto dd2; else goto mm2;
- }
- if(btoken.tbrkl == ch /* "-NN" */
- && given(ord ? atm->tm_mon : atm->tm_mday))
- if (!given(ord ? atm->tm_mday : atm->tm_mon)) /* MM/DD */
- if(ord)goto dd2; else goto mm2;
- }
-
- /* Now reduced to choice between HH and DD */
- if (given(atm->tm_hour)) goto dd2; /* Have hour? Assume day. */
- if (given(atm->tm_mday)) goto hh2; /* Have day? Assume hour. */
- if (given(atm->tm_mon)) goto dd2; /* Have month? Assume day. */
- if(i > 24) goto dd2; /* Impossible HH means DD */
- atoken = btoken;
- if (!ptitoken(&atoken)) /* Read ahead! */
- if(atoken.tval.tnum) return(0); /* ERR: bad token */
- else goto dd2; /* EOF, assume day. */
- if ( atoken.tflg
- ? !isdigit(*atoken.tcp)
- : atoken.tval.ttmw->wflgs & TWTIME)
- /* If next token is a time spec, assume hour */
- goto hh2; /* e.g. "3 PM", "11-EDT" */
-
-dd2: if (ptstash(&atm->tm_mday, i)) /* Store day (1 based) */
- return(0);
- continue;
-
-mm2: if (ptstash(&atm->tm_mon, i-1)) /* Store month (make zero based) */
- return(0);
- continue;
-
-year4: if ((i-=1900) < 0 || ptstash(&atm->tm_year, i)) /* Store year-1900 */
- return(0); /* ERR: year conflict */
- continue;
-
- /* Hack HH:MM[[:]SS] */
-coltime:
- if (ptstash(&atm->tm_hour, i)) return 0;
- if (!ptitoken(&btoken))
- return(!btoken.tval.tnum);
- if(!btoken.tflg) return(0); /* ERR: HH:<alpha> */
- if(btoken.tcnt == 4) /* MMSS */
- if (ptstash(&atm->tm_min, btoken.tval.tnum/100)
- || ptstash(&atm->tm_sec, btoken.tval.tnum%100))
- return(0);
- else continue;
- if(btoken.tcnt != 2
- || ptstash(&atm->tm_min, btoken.tval.tnum))
- return(0); /* ERR: MM bad */
- if (btoken.tbrk != ':') continue; /* Seconds follow? */
-coltm2: if (!ptitoken(&btoken))
- return(!btoken.tval.tnum);
- if(!btoken.tflg || btoken.tcnt != 2 /* Verify SS */
- || ptstash(&atm->tm_sec, btoken.tval.tnum))
- return(0); /* ERR: SS bad */
- }
-}
-
-/* Store date/time value, return 0 if successful.
- * Fail if entry is already set.
- */
- static int
-ptstash(adr,val)
-int *adr;
-int val;
-{ register int *a;
- if (given(*(a=adr)))
- return 1;
- *a = val;
- return(0);
-}
-
-/* This subroutine is invoked for AM, PM, NOON and MIDNIGHT when wrapping up
- * just prior to returning from partime.
- */
- static int
-pt12hack(tm, aval)
-register struct tm *tm;
-register int aval;
-{ register int h = tm->tm_hour;
- switch (aval) {
- case T12_AM:
- case T12_PM:
- if (h > 12)
- return 0;
- if (h == 12)
- tm->tm_hour = 0;
- if (aval == T12_PM)
- tm->tm_hour += 12;
- break;
- default:
- if (0 < tm->tm_min || 0 < tm->tm_sec)
- return 0;
- if (!given(h) || h==12)
- tm->tm_hour = aval;
- else if (aval==T12_MIDNIGHT && (h==0 || h==24))
+ mm = ss = 0;
+ if (*s == ':')
+ s++;
+ if (isdigit ((unsigned char) *s)) {
+ if (!(s = parse_ranged (s, 2, 0, 59, &mm)))
return 0;
+ if (*s==':' && s[-3]==':' && isdigit ((unsigned char) s[1])) {
+ if (!(s = parse_ranged (s + 1, 2, 0, 59, &ss)))
+ return 0;
+ }
}
- return 1;
+ if (isdigit ((unsigned char) *s))
+ return 0;
+ offset = (hh*60 + mm)*60L + ss;
+ *zone = z + (sign=='-' ? -offset : offset);
+ /*
+ * ?? Are fractions allowed here?
+ * If so, they're not implemented.
+ */
+ return (char *) s;
}
-/* Get a token and identify it to some degree.
- * Returns 0 on failure; token.tval will be 0 for normal EOF, otherwise
- * hit error of some sort
- */
-
- static int
-ptitoken(tkp)
-register struct token *tkp;
+ static char const *
+parse_pattern_letter (s, c, t) char const *s; int c; struct partime *t;
+/*
+* Parse an initial prefix of S, matching the pattern whose code is C.
+* Set *T accordingly.
+* Return the first character after the prefix, or 0 if it couldn't be parsed.
+*/
{
- register char const *cp;
- register int i, j, k;
-
- if (!pttoken(tkp))
-#ifdef DEBUG
- {
- VOID printf("EOF\n");
- return(0);
- }
-#else
- return(0);
-#endif
- cp = tkp->tcp;
+ switch (c) {
+ case '$': /* The next character must be a non-digit. */
+ if (isdigit ((unsigned char) *s))
+ return 0;
+ break;
-#ifdef DEBUG
- VOID printf("Token: \"%.*s\" ", tkp->tcnt, cp);
-#endif
+ case '-': case '/': case ':':
+ /* These characters stand for themselves. */
+ if (*s++ != c)
+ return 0;
+ break;
- if (tkp->tflg) {
- i = tkp->tcnt;
- if (*cp == '+' || *cp == '-') {
- cp++;
- i--;
- }
- while (0 <= --i) {
- j = tkp->tval.tnum*10;
- k = j + (*cp++ - '0');
- if (j/10 != tkp->tval.tnum || k < j) {
- /* arithmetic overflow */
- tkp->tval.tnum = 1;
+ case '4': /* 4-digit year */
+ s = parse_fixed (s, 4, &t->tm.tm_year);
+ break;
+
+ case '=': /* optional '-' */
+ s += *s == '-';
+ break;
+
+ case 'A': /* AM or PM */
+ /*
+ * This matches the regular expression [AaPp][Mm]?.
+ * It must not be followed by a letter or digit;
+ * otherwise it would match prefixes of strings like "PST".
+ */
+ switch (*s++) {
+ case 'A': case 'a':
+ if (t->tm.tm_hour == 12)
+ t->tm.tm_hour = 0;
+ break;
+
+ case 'P': case 'p':
+ if (t->tm.tm_hour != 12)
+ t->tm.tm_hour += 12;
+ break;
+
+ default: return 0;
+ }
+ switch (*s) {
+ case 'M': case 'm': s++; break;
+ }
+ if (isalnum (*s))
return 0;
+ break;
+
+ case 'D': /* day of month [01-31] */
+ s = parse_ranged (s, 2, 1, 31, &t->tm.tm_mday);
+ break;
+
+ case 'd': /* day of year [001-366] */
+ s = parse_ranged (s, 3, 1, 366, &t->tm.tm_yday);
+ t->tm.tm_yday--;
+ break;
+
+ case 'E': /* extended day of month [1-9, 01-31] */
+ s = parse_ranged (s, (
+ isdigit ((unsigned char) s[0]) &&
+ isdigit ((unsigned char) s[1])
+ ) + 1, 1, 31, &t->tm.tm_mday);
+ break;
+
+ case 'h': /* hour [00-23 followed by optional fraction] */
+ {
+ int frac;
+ s = parse_decimal (s, 2, 0, 23, 60*60, &t->tm.tm_hour, &frac);
+ t->tm.tm_min = frac / 60;
+ t->tm.tm_sec = frac % 60;
}
- tkp->tval.tnum = k;
- }
- } else if (!(tkp->tval.ttmw = ptmatchstr(cp, tkp->tcnt, tmwords)))
- {
-#ifdef DEBUG
- VOID printf("Not found!\n");
-#endif
- tkp->tval.tnum = 1;
- return 0;
- }
+ break;
-#ifdef DEBUG
- if(tkp->tflg)
- VOID printf("Val: %d.\n",tkp->tval.tnum);
- else VOID printf("Found: \"%s\", val: %d, type %d\n",
- tkp->tval.ttmw->went,tkp->tval.ttmw->wval,tkp->tval.ttmw->wtype);
-#endif
+ case 'm': /* minute [00-59 followed by optional fraction] */
+ s = parse_decimal (s, 2, 0, 59, 60, &t->tm.tm_min, &t->tm.tm_sec);
+ break;
+
+ case 'n': /* month name [e.g. "Jan"] */
+ if (!TM_DEFINED (t->tm.tm_mon = lookup (s, month_names)))
+ return 0;
+ /* Don't bother to check rest of spelling. */
+ while (isalpha ((unsigned char) *s))
+ s++;
+ break;
+
+ case 'N': /* month [01-12] */
+ s = parse_ranged (s, 2, 1, 12, &t->tm.tm_mon);
+ t->tm.tm_mon--;
+ break;
- return(1);
+ case 'r': /* year % 10 (remainder in origin-0 decade) [0-9] */
+ s = parse_fixed (s, 1, &t->tm.tm_year);
+ t->ymodulus = 10;
+ break;
+
+ case_R:
+ case 'R': /* year % 100 (remainder in origin-0 century) [00-99] */
+ s = parse_fixed (s, 2, &t->tm.tm_year);
+ t->ymodulus = 100;
+ break;
+
+ case 's': /* second [00-60 followed by optional fraction] */
+ {
+ int frac;
+ s = parse_decimal (s, 2, 0, 60, 1, &t->tm.tm_sec, &frac);
+ t->tm.tm_sec += frac;
+ }
+ break;
+
+ case 'T': /* 'T' or 't' */
+ switch (*s++) {
+ case 'T': case 't': break;
+ default: return 0;
+ }
+ break;
+
+ case 't': /* traditional hour [1-9 or 01-12] */
+ s = parse_ranged (s, (
+ isdigit ((unsigned char) s[0]) && isdigit ((unsigned char) s[1])
+ ) + 1, 1, 12, &t->tm.tm_hour);
+ break;
+
+ case 'w': /* 'W' or 'w' only (stands for current week) */
+ switch (*s++) {
+ case 'W': case 'w': break;
+ default: return 0;
+ }
+ break;
+
+ case 'W': /* 'W' or 'w', followed by a week of year [00-53] */
+ switch (*s++) {
+ case 'W': case 'w': break;
+ default: return 0;
+ }
+ s = parse_ranged (s, 2, 0, 53, &t->yweek);
+ break;
+
+ case 'X': /* weekday (1=Mon ... 7=Sun) [1-7] */
+ s = parse_ranged (s, 1, 1, 7, &t->tm.tm_wday);
+ t->tm.tm_wday--;
+ break;
+
+ case 'x': /* weekday name [e.g. "Sun"] */
+ if (!TM_DEFINED (t->tm.tm_wday = lookup (s, weekday_names)))
+ return 0;
+ /* Don't bother to check rest of spelling. */
+ while (isalpha ((unsigned char) *s))
+ s++;
+ break;
+
+ case 'y': /* either R or Y */
+ if (
+ isdigit ((unsigned char) s[0]) &&
+ isdigit ((unsigned char) s[1]) &&
+ !isdigit ((unsigned char) s[2])
+ )
+ goto case_R;
+ /* fall into */
+ case 'Y': /* year in full [4 or more digits] */
+ {
+ int len = 0;
+ while (isdigit ((unsigned char) s[len]))
+ len++;
+ if (len < 4)
+ return 0;
+ s = parse_fixed (s, len, &t->tm.tm_year);
+ }
+ break;
+
+ case 'Z': /* time zone */
+ s = parzone (s, &t->zone);
+ break;
+
+ case '_': /* possibly empty sequence of non-alphanumerics */
+ while (!isalnum (*s) && *s)
+ s++;
+ break;
+
+ default: /* bad pattern */
+ return 0;
+ }
+ return s;
}
-/* Read token from input string into token structure */
static int
-pttoken(tkp)
-register struct token *tkp;
+merge_partime (t, u) struct partime *t; struct partime const *u;
+/*
+* If there is no conflict, merge into *T the additional information in *U
+* and return 0. Otherwise do nothing and return -1.
+*/
{
- register char const *cp;
- register int c;
- char const *astr;
-
- tkp->tcp = astr = cp = tkp->tcp + tkp->tcnt;
- tkp->tbrkl = tkp->tbrk; /* Set "last break" */
- tkp->tcnt = tkp->tbrk = tkp->tflg = 0;
- tkp->tval.tnum = 0;
-
- while(c = *cp++)
- { switch(c)
- { case ' ': case '\t': /* Flush all whitespace */
- case '\r': case '\n':
- case '\v': case '\f':
- if (!tkp->tcnt) { /* If no token yet */
- tkp->tcp = cp; /* ignore the brk */
- continue; /* and go on. */
- }
- /* fall into */
- case '(': case ')': /* Perhaps any non-alphanum */
- case '-': case ',': /* shd qualify as break? */
- case '+':
- case '/': case ':': case '.': /* Break chars */
- if(tkp->tcnt == 0) /* If no token yet */
- { tkp->tcp = cp; /* ignore the brk */
- tkp->tbrkl = c;
- continue; /* and go on. */
- }
- tkp->tbrk = c;
- return(tkp->tcnt);
- }
- if (!tkp->tcnt++) { /* If first char of token, */
- if (isdigit(c)) {
- tkp->tflg = 1;
- if (astr<cp-2 && (cp[-2]=='-'||cp[-2]=='+')) {
- /* timezone is break+sign+digit */
- tkp->tcp--;
- tkp->tcnt++;
- }
- }
- } else if ((isdigit(c)!=0) != tkp->tflg) { /* else check type */
- tkp->tbrk = c;
- return --tkp->tcnt; /* Wrong type, back up */
- }
- }
- return(tkp->tcnt); /* When hit EOF */
+# define conflict(a,b) ((a) != (b) && TM_DEFINED (a) && TM_DEFINED (b))
+ if (
+ conflict (t->tm.tm_sec, u->tm.tm_sec) ||
+ conflict (t->tm.tm_min, u->tm.tm_min) ||
+ conflict (t->tm.tm_hour, u->tm.tm_hour) ||
+ conflict (t->tm.tm_mday, u->tm.tm_mday) ||
+ conflict (t->tm.tm_mon, u->tm.tm_mon) ||
+ conflict (t->tm.tm_year, u->tm.tm_year) ||
+ conflict (t->tm.tm_wday, u->tm.tm_yday) ||
+ conflict (t->ymodulus, u->ymodulus) ||
+ conflict (t->yweek, u->yweek) ||
+ (
+ t->zone != u->zone &&
+ t->zone != TM_UNDEFINED_ZONE &&
+ u->zone != TM_UNDEFINED_ZONE
+ )
+ )
+ return -1;
+# undef conflict
+# define merge_(a,b) if (TM_DEFINED (b)) (a) = (b);
+ merge_ (t->tm.tm_sec, u->tm.tm_sec)
+ merge_ (t->tm.tm_min, u->tm.tm_min)
+ merge_ (t->tm.tm_hour, u->tm.tm_hour)
+ merge_ (t->tm.tm_mday, u->tm.tm_mday)
+ merge_ (t->tm.tm_mon, u->tm.tm_mon)
+ merge_ (t->tm.tm_year, u->tm.tm_year)
+ merge_ (t->tm.tm_wday, u->tm.tm_yday)
+ merge_ (t->ymodulus, u->ymodulus)
+ merge_ (t->yweek, u->yweek)
+# undef merge_
+ if (u->zone != TM_UNDEFINED_ZONE) t->zone = u->zone;
+ return 0;
}
-
- static struct tmwent const *
-ptmatchstr(astr,cnt,astruc)
- char const *astr;
- int cnt;
- struct tmwent const *astruc;
+ char *
+partime (s, t) char const *s; struct partime *t;
+/*
+* Parse a date/time prefix of S, putting the parsed result into *T.
+* Return the first character after the prefix.
+* The prefix may contain no useful information;
+* in that case, *T will contain only undefined values.
+*/
{
- register char const *cp, *mp;
- register int c;
- struct tmwent const *lastptr;
- int i;
-
- lastptr = 0;
- for(;mp = astruc->went; astruc += 1)
- { cp = astr;
- for(i = cnt; i > 0; i--)
- {
- switch (*cp++ - (c = *mp++))
- { case 0: continue; /* Exact match */
- case 'A'-'a':
- if (ctab[c] == Letter)
- continue;
- }
- break;
- }
- if(i==0)
- if (!*mp) return astruc; /* Exact match */
- else if(lastptr) return(0); /* Ambiguous */
- else lastptr = astruc; /* 1st ambig */
- }
- return lastptr;
+ struct partime p;
+
+ undefine (t);
+ while (*s) {
+ int i = 0;
+ char const *s1;
+ do {
+ if (!(s1 = parse_prefix (s, &p, &i)))
+ return (char *) s;
+ } while (merge_partime (t, &p) != 0);
+ s = s1;
+ }
+ return (char *) s;
}
diff --git a/gnu/usr.bin/rcs/lib/rcsbase.h b/gnu/usr.bin/rcs/lib/rcsbase.h
index 788ea5d..36ef8ab 100644
--- a/gnu/usr.bin/rcs/lib/rcsbase.h
+++ b/gnu/usr.bin/rcs/lib/rcsbase.h
@@ -1,11 +1,9 @@
+/* RCS common definitions and data structures */
-/*
- * RCS common definitions and data structures
- */
-#define RCSBASE "$Id: rcsbase.h,v 1.2 1994/05/14 07:00:20 rgrimes Exp $"
+#define RCSBASE "$Id: rcsbase.h,v 5.20 1995/06/16 06:19:24 eggert Exp $"
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -21,8 +19,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -30,26 +29,54 @@ Report problems and direct all questions to:
*/
-
-
-/*****************************************************************************
- * INSTRUCTIONS:
- * =============
- * See the Makefile for how to define C preprocessor symbols.
- * If you need to change the comment leaders, update the table comtable[]
- * in rcsfnms.c. (This can wait until you know what a comment leader is.)
- *****************************************************************************
- */
-
-
-/* $Log: rcsbase.h,v $
- * Revision 1.2 1994/05/14 07:00:20 rgrimes
- * Add new option -K from David Dawes that allows you to turn on and off
- * specific keyword substitution during a rcs co command.
- * Add the new keyword FreeBSD that is IDENTICAL in operation to $Id$.
+/*
+ * $Log: rcsbase.h,v $
+ * Revision 5.20 1995/06/16 06:19:24 eggert
+ * Update FSF address.
*
- * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
- * Updated GNU utilities
+ * Revision 5.19 1995/06/01 16:23:43 eggert
+ * (SIZEABLE_PATH): Don't depend on PATH_MAX: it's not worth configuring.
+ * (Ioffset_type,BINARY_EXPAND,MIN_UNEXPAND,MIN_UNCHANGED_EXPAND): New macros.
+ * (maps_memory): New macro; replaces many instances of `has_mmap'.
+ * (cacheptr): Renamed from cachetell.
+ * (struct RILE): New alternate name for RILE; the type is now recursive.
+ * (deallocate): New member for RILE, used for generic buffer deallocation.
+ * (cacheunget_): No longer take a failure arg; just call Ierror on failure.
+ * (struct rcslock): Renamed from struct lock, to avoid collisions with
+ * system headers on some hosts. All users changed.
+ * (basefilename): Renamed from basename, likewise.
+ * (dirtpname): Remove; no longer external.
+ * (dirlen, dateform): Remove; no longer used.
+ * (cmpdate, fopenSafer, fdSafer, readAccessFilenameBuffer): New functions.
+ * (zonelenmax): Increase to 9 for full ISO 8601 format.
+ * (catchmmapints): Depend on has_NFS.
+ *
+ * Revision 5.18 1994/03/17 14:05:48 eggert
+ * Add primitives for reading backwards from a RILE;
+ * this is needed to go back and find the $Log prefix.
+ * Specify subprocess input via file descriptor, not file name. Remove lint.
+ *
+ * Revision 5.17 1993/11/09 17:40:15 eggert
+ * Move RCS-specific time handling into rcstime.c.
+ * printf_string now takes two arguments, alas.
+ *
+ * Revision 5.16 1993/11/03 17:42:27 eggert
+ * Don't arbitrarily limit the number of joins. Remove `nil'.
+ * Add Name keyword. Don't discard ignored phrases.
+ * Add support for merge -A vs -E, and allow up to three labels.
+ * Improve quality of diagnostics and prototypes.
+ *
+ * Revision 5.15 1992/07/28 16:12:44 eggert
+ * Statement macro names now end in _.
+ *
+ * Revision 5.14 1992/02/17 23:02:22 eggert
+ * Add -T support. Work around NFS mmap SIGBUS problem.
+ *
+ * Revision 5.13 1992/01/24 18:44:19 eggert
+ * Add support for bad_creat0. lint -> RCS_lint
+ *
+ * Revision 5.12 1992/01/06 02:42:34 eggert
+ * while (E) ; -> while (E) continue;
*
* Revision 5.11 1991/10/07 17:32:46 eggert
* Support piece tables even if !has_mmap.
@@ -164,10 +191,10 @@ Report problems and direct all questions to:
#define EXIT_TROUBLE DIFF_TROUBLE
-#ifdef PATH_MAX
-# define SIZEABLE_PATH PATH_MAX /* size of a large path; not a hard limit */
-#else
+#ifdef _POSIX_PATH_MAX
# define SIZEABLE_PATH _POSIX_PATH_MAX
+#else
+# define SIZEABLE_PATH 255 /* size of a large path; not a hard limit */
#endif
/* for traditional C hosts with unusual size arguments */
@@ -196,8 +223,7 @@ Report problems and direct all questions to:
/* used in production environments. */
#define yearlength 16 /* (good through AD 9,999,999,999,999,999) */
-#define datesize (yearlength+16) /* size of output of DATEFORM */
-#define joinlength 20 /* number of joined revisions permitted */
+#define datesize (yearlength+16) /* size of output of time2date */
#define RCSTMPPREFIX '_' /* prefix for temp files in working dir */
#define KDELIM '$' /* delimiter for keywords */
#define VDELIM ':' /* separates keywords from values */
@@ -207,7 +233,6 @@ Report problems and direct all questions to:
#define true 1
#define false 0
-#define nil 0
/*
@@ -216,68 +241,79 @@ Report problems and direct all questions to:
* setupcache - sets up the local RILE cache, but does not initialize it
* cache, uncache - caches and uncaches the local RILE;
* (uncache,cache) is needed around functions that advance the RILE pointer
- * Igeteof(f,c,s) - get a char c from f, executing statement s at EOF
- * cachegeteof(c,s) - Igeteof applied to the local RILE
- * Iget(f,c) - like Igeteof, except EOF is an error
- * cacheget(c) - Iget applied to the local RILE
- * Ifileno, Irewind, Iseek, Itell - analogs to stdio routines
+ * Igeteof_(f,c,s) - get a char c from f, executing statement s at EOF
+ * cachegeteof_(c,s) - Igeteof_ applied to the local RILE
+ * Iget_(f,c) - like Igeteof_, except EOF is an error
+ * cacheget_(c) - Iget_ applied to the local RILE
+ * cacheunget_(f,c,s) - read c backwards from cached f, executing s at BOF
+ * Ifileno, Ioffset_type, Irewind, Itell - analogs to stdio routines
+ *
+ * By conventions, macros whose names end in _ are statements, not expressions.
+ * Following such macros with `; else' results in a syntax error.
*/
+#define maps_memory (has_map_fd || has_mmap)
+
#if large_memory
typedef unsigned char const *Iptr_type;
- typedef struct {
+ typedef struct RILE {
Iptr_type ptr, lim;
- unsigned char *base; /* for lint, not Iptr_type even if has_mmap */
-# if has_mmap
-# define Ifileno(f) ((f)->fd)
- int fd;
+ unsigned char *base; /* not Iptr_type for lint's sake */
+ unsigned char *readlim;
+ int fd;
+# if maps_memory
+ void (*deallocate) P((struct RILE *));
# else
-# define Ifileno(f) fileno((f)->stream)
FILE *stream;
- unsigned char *readlim;
# endif
} RILE;
-# if has_mmap
+# if maps_memory
# define declarecache register Iptr_type ptr, lim
# define setupcache(f) (lim = (f)->lim)
-# define Igeteof(f,c,s) if ((f)->ptr==(f)->lim) s else (c)= *(f)->ptr++
-# define cachegeteof(c,s) if (ptr==lim) s else (c)= *ptr++
+# define Igeteof_(f,c,s) if ((f)->ptr==(f)->lim) s else (c)= *(f)->ptr++;
+# define cachegeteof_(c,s) if (ptr==lim) s else (c)= *ptr++;
# else
+ int Igetmore P((RILE*));
# define declarecache register Iptr_type ptr; register RILE *rRILE
# define setupcache(f) (rRILE = (f))
-# define Igeteof(f,c,s) if ((f)->ptr==(f)->readlim && !Igetmore(f)) s else (c)= *(f)->ptr++
-# define cachegeteof(c,s) if (ptr==rRILE->readlim && !Igetmore(rRILE)) s else (c)= *ptr++
+# define Igeteof_(f,c,s) if ((f)->ptr==(f)->readlim && !Igetmore(f)) s else (c)= *(f)->ptr++;
+# define cachegeteof_(c,s) if (ptr==rRILE->readlim && !Igetmore(rRILE)) s else (c)= *ptr++;
# endif
# define uncache(f) ((f)->ptr = ptr)
# define cache(f) (ptr = (f)->ptr)
-# define Iget(f,c) Igeteof(f,c,Ieof();)
-# define cacheget(c) cachegeteof(c,Ieof();)
-# define Itell(f) ((f)->ptr)
-# define Iseek(f,p) ((f)->ptr = (p))
-# define Irewind(f) Iseek(f, (f)->base)
-# define cachetell() ptr
+# define Iget_(f,c) Igeteof_(f,c,Ieof();)
+# define cacheget_(c) cachegeteof_(c,Ieof();)
+# define cacheunget_(f,c) (c)=(--ptr)[-1];
+# define Ioffset_type size_t
+# define Itell(f) ((f)->ptr - (f)->base)
+# define Irewind(f) ((f)->ptr = (f)->base)
+# define cacheptr() ptr
+# define Ifileno(f) ((f)->fd)
#else
# define RILE FILE
# define declarecache register FILE *ptr
# define setupcache(f) (ptr = (f))
# define uncache(f)
# define cache(f)
-# define Igeteof(f,c,s) if(((c)=getc(f))<0){testIerror(f);if(feof(f))s}else
-# define cachegeteof(c,s) Igeteof(ptr,c,s)
-# define Iget(f,c) if (((c)=getc(f))<0) testIeof(f); else
-# define cacheget(c) Iget(ptr,c)
+# define Igeteof_(f,c,s) {if(((c)=getc(f))==EOF){testIerror(f);if(feof(f))s}}
+# define cachegeteof_(c,s) Igeteof_(ptr,c,s)
+# define Iget_(f,c) { if (((c)=getc(f))==EOF) testIeof(f); }
+# define cacheget_(c) Iget_(ptr,c)
+# define cacheunget_(f,c) if(fseek(ptr,-2L,SEEK_CUR))Ierror();else cacheget_(c)
+# define Ioffset_type long
+# define Itell(f) ftell(f)
# define Ifileno(f) fileno(f)
#endif
/* Print a char, but abort on write error. */
-#define aputc(c,o) if (putc(c,o)<0) testOerror(o); else
+#define aputc_(c,o) { if (putc(c,o)==EOF) testOerror(o); }
/* Get a character from an RCS file, perhaps copying to a new RCS file. */
-#define GETCeof(o,c,s) { cachegeteof(c,s); if (o) aputc(c,o); }
-#define GETC(o,c) { cacheget(c); if (o) aputc(c,o); }
+#define GETCeof_(o,c,s) { cachegeteof_(c,s) if (o) aputc_(c,o) }
+#define GETC_(o,c) { cacheget_(c) if (o) aputc_(c,o) }
-#define WORKMODE(RCSmode, writable) ((RCSmode)&~(S_IWUSR|S_IWGRP|S_IWOTH) | ((writable)?S_IWUSR:0))
+#define WORKMODE(RCSmode, writable) (((RCSmode)&(mode_t)~(S_IWUSR|S_IWGRP|S_IWOTH)) | ((writable)?S_IWUSR:0))
/* computes mode of working file: same as RCSmode, but write permission */
/* determined by writable */
@@ -294,7 +330,7 @@ enum tokens {
* there should be no overlap among SDELIM, KDELIM, and VDELIM
*/
-#define isdigit(c) ((unsigned)((c)-'0') <= 9) /* faster than ctab[c]==DIGIT */
+#define isdigit(c) (((unsigned)(c)-'0') <= 9) /* faster than ctab[c]==DIGIT */
@@ -321,13 +357,15 @@ struct hshentry {
char const * author; /* login of person checking in */
char const * lockedby; /* who locks the revision */
char const * state; /* state of revision (Exp by default) */
+ char const * name; /* name (if any) by which retrieved */
struct cbuf log; /* log message requested at checkin */
struct branchhead * branches; /* list of first revisions on branches*/
- struct cbuf ig; /* ignored phrases of revision */
+ struct cbuf ig; /* ignored phrases in admin part */
+ struct cbuf igtext; /* ignored phrases in deltatext part */
struct hshentry * next; /* next revision on same branch */
struct hshentry * nexthsh; /* next revision with same hash value */
- unsigned long insertlns;/* lines inserted (computed by rlog) */
- unsigned long deletelns;/* lines deleted (computed by rlog) */
+ long insertlns;/* lines inserted (computed by rlog) */
+ long deletelns;/* lines deleted (computed by rlog) */
char selector; /* true if selected, false if deleted */
};
@@ -350,10 +388,10 @@ struct access {
};
/* list element for locks */
-struct lock {
+struct rcslock {
char const * login;
struct hshentry * delta;
- struct lock * nextlock;
+ struct rcslock * nextlock;
};
/* list element for symbolic names */
@@ -366,12 +404,12 @@ struct assoc {
#define mainArgs (argc,argv) int argc; char **argv;
-#if lint
+#if RCS_lint
# define libId(name,rcsid)
# define mainProg(name,cmd,rcsid) int name mainArgs
#else
# define libId(name,rcsid) char const name[] = rcsid;
-# define mainProg(name,cmd,rcsid) char const copyright[] = "Copyright 1982,1988,1989 by Walter F. Tichy\nPurdue CS\nCopyright 1990,1991 by Paul Eggert", rcsbaseId[] = RCSBASE, cmdid[] = cmd; libId(name,rcsid) int main mainArgs
+# define mainProg(n,c,i) char const Copyright[] = "Copyright 1982,1988,1989 Walter F. Tichy, Purdue CS\nCopyright 1990,1991,1992,1993,1994,1995 Paul Eggert", baseid[] = RCSBASE, cmdid[] = c; libId(n,i) int main P((int,char**)); int main mainArgs
#endif
/*
@@ -384,15 +422,15 @@ struct assoc {
#define IDH "Id"
#define LOCKER "Locker"
#define LOG "Log"
+#define NAME "Name"
#define RCSFILE "RCSfile"
#define REVISION "Revision"
#define SOURCE "Source"
#define STATE "State"
-#define FREEBSD "FreeBSD"
#define keylength 8 /* max length of any of the above keywords */
enum markers { Nomatch, Author, Date, Header, Id,
- Locker, Log, RCSfile, Revision, Source, State, FreeBSD };
+ Locker, Log, Name, RCSfile, Revision, Source, State };
/* This must be in the same order as rcskeys.c's Keyword[] array. */
#define DELNUMFORM "\n\n%s\n%s\n"
@@ -402,39 +440,31 @@ enum markers { Nomatch, Author, Date, Header, Id,
/* main program */
extern char const cmdid[];
-exiting void exiterr P((void));
-
-/* maketime */
-int setfiledate P((char const*,char const[datesize]));
-void str2date P((char const*,char[datesize]));
-void time2date P((time_t,char[datesize]));
+void exiterr P((void)) exiting;
/* merge */
-int merge P((int,char const*const[2],char const*const[3]));
-
-/* partime */
-int partime P((char const*,struct tm*,int*));
+int merge P((int,char const*,char const*const[3],char const*const[3]));
/* rcsedit */
#define ciklogsize 23 /* sizeof("checked in with -k by ") */
extern FILE *fcopy;
-extern char const *resultfile;
+extern char const *resultname;
extern char const ciklog[ciklogsize];
extern int locker_expansion;
-extern struct buf dirtfname[];
-#define newRCSfilename (dirtfname[0].string)
RILE *rcswriteopen P((struct buf*,struct stat*,int));
-char const *makedirtemp P((char const*,int));
+char const *makedirtemp P((int));
char const *getcaller P((void));
-int addlock P((struct hshentry*));
+int addlock P((struct hshentry*,int));
int addsymbol P((char const*,char const*,int));
int checkaccesslist P((void));
-int chnamemod P((FILE**,char const*,char const*,mode_t));
-int donerewrite P((int));
+int chnamemod P((FILE**,char const*,char const*,int,mode_t,time_t));
+int donerewrite P((int,time_t));
int dorewrite P((int,int));
-int expandline P((RILE*,FILE*,struct hshentry const*,int,FILE*));
+int expandline P((RILE*,FILE*,struct hshentry const*,int,FILE*,int));
int findlock P((int,struct hshentry**));
-void aflush P((FILE*));
+int setmtime P((char const*,time_t));
+void ORCSclose P((void));
+void ORCSerror P((void));
void copystring P((void));
void dirtempunlink P((void));
void enterstring P((void));
@@ -459,20 +489,21 @@ void xpandstring P((struct hshentry const*));
int rcsfcmp P((RILE*,struct stat const*,char const*,struct hshentry const*));
/* rcsfnms */
-#define bufautobegin(b) ((void) ((b)->string = 0, (b)->size = 0))
+#define bufautobegin(b) clear_buf(b)
+#define clear_buf(b) (VOID ((b)->string = 0, (b)->size = 0))
extern FILE *workstdout;
-extern char *workfilename;
-extern char const *RCSfilename;
+extern char *workname;
+extern char const *RCSname;
extern char const *suffixes;
+extern int fdlock;
extern struct stat RCSstat;
RILE *rcsreadopen P((struct buf*,struct stat*,int));
char *bufenlarge P((struct buf*,char const**));
-char const *basename P((char const*));
+char const *basefilename P((char const*));
char const *getfullRCSname P((void));
char const *maketemp P((int));
char const *rcssuffix P((char const*));
-int pairfilenames P((int,char**,RILE*(*)P((struct buf*,struct stat*,int)),int,int));
-size_t dirlen P((char const*));
+int pairnames P((int,char**,RILE*(*)P((struct buf*,struct stat*,int)),int,int));
struct cbuf bufremember P((struct buf*,size_t));
void bufalloc P((struct buf*,size_t));
void bufautoend P((struct buf*));
@@ -486,15 +517,17 @@ extern int interactiveflag;
extern struct buf curlogbuf;
char const *buildrevision P((struct hshentries const*,struct hshentry*,FILE*,int));
int getcstdin P((void));
+int putdtext P((struct hshentry const*,char const*,FILE*,int));
int ttystdin P((void));
-int yesorno P((int,char const*,...));
+int yesorno P((int,char const*,...)) printf_string(2,3);
struct cbuf cleanlogmsg P((char*,size_t));
struct cbuf getsstdin P((char const*,char const*,char const*,struct buf*));
void putdesc P((int,char*));
+void putdftext P((struct hshentry const*,RILE*,FILE*,int));
/* rcskeep */
extern int prevkeys;
-extern struct buf prevauthor, prevdate, prevrev, prevstate;
+extern struct buf prevauthor, prevdate, prevname, prevrev, prevstate;
int getoldkeys P((RILE*));
/* rcskeys */
@@ -511,16 +544,19 @@ extern int hshenter;
extern int nerror;
extern int nextc;
extern int quietflag;
-extern unsigned long rcsline;
+extern long rcsline;
char const *getid P((void));
-exiting void efaterror P((char const*));
-exiting void enfaterror P((int,char const*));
-exiting void faterror P((char const*,...));
-exiting void fatserror P((char const*,...));
-exiting void Ieof P((void));
-exiting void Ierror P((void));
-exiting void Oerror P((void));
+void efaterror P((char const*)) exiting;
+void enfaterror P((int,char const*)) exiting;
+void fatcleanup P((int)) exiting;
+void faterror P((char const*,...)) printf_string_exiting(1,2);
+void fatserror P((char const*,...)) printf_string_exiting(1,2);
+void rcsfaterror P((char const*,...)) printf_string_exiting(1,2);
+void Ieof P((void)) exiting;
+void Ierror P((void)) exiting;
+void Oerror P((void)) exiting;
char *checkid P((char*,int));
+char *checksym P((char*,int));
int eoflex P((void));
int getkeyopt P((char const*));
int getlex P((enum tokens));
@@ -531,16 +567,19 @@ void Ifclose P((RILE*));
void Izclose P((RILE**));
void Lexinit P((void));
void Ofclose P((FILE*));
+void Orewind P((FILE*));
void Ozclose P((FILE**));
+void aflush P((FILE*));
void afputc P((int,FILE*));
-void aprintf P((FILE*,char const*,...));
+void aprintf P((FILE*,char const*,...)) printf_string(2,3);
void aputs P((char const*,FILE*));
void checksid P((char*));
-void diagnose P((char const*,...));
+void checkssym P((char*));
+void diagnose P((char const*,...)) printf_string(1,2);
void eerror P((char const*));
void eflush P((void));
void enerror P((int,char const*));
-void error P((char const*,...));
+void error P((char const*,...)) printf_string(1,2);
void fvfprintf P((FILE*,char const*,va_list));
void getkey P((char const*));
void getkeystring P((char const*));
@@ -549,10 +588,14 @@ void oflush P((void));
void printstring P((void));
void readstring P((void));
void redefined P((int));
+void rcserror P((char const*,...)) printf_string(1,2);
+void rcswarn P((char const*,...)) printf_string(1,2);
void testIerror P((FILE*));
void testOerror P((FILE*));
-void warn P((char const*,...));
+void warn P((char const*,...)) printf_string(1,2);
void warnignore P((void));
+void workerror P((char const*,...)) printf_string(1,2);
+void workwarn P((char const*,...)) printf_string(1,2);
#if has_madvise && has_mmap && large_memory
void advise_access P((RILE*,int));
# define if_advise_access(p,f,advice) if (p) advise_access(f,advice)
@@ -560,7 +603,7 @@ void warnignore P((void));
# define advise_access(f,advice)
# define if_advise_access(p,f,advice)
#endif
-#if has_mmap && large_memory
+#if large_memory && maps_memory
RILE *I_open P((char const*,struct stat*));
# define Iopen(f,m,s) I_open(f,s)
#else
@@ -572,18 +615,20 @@ void warnignore P((void));
#endif
/* rcsmap */
-extern const enum tokens ctab[];
+extern enum tokens const ctab[];
/* rcsrev */
-char *partialno P((struct buf*,char const*,unsigned));
+char *partialno P((struct buf*,char const*,int));
+char const *namedrev P((char const*,struct hshentry*));
char const *tiprev P((void));
+int cmpdate P((char const*,char const*));
int cmpnum P((char const*,char const*));
-int cmpnumfld P((char const*,char const*,unsigned));
-int compartial P((char const*,char const*,unsigned));
+int cmpnumfld P((char const*,char const*,int));
+int compartial P((char const*,char const*,int));
int expandsym P((char const*,struct buf*));
int fexpandsym P((char const*,struct buf*,RILE*));
struct hshentry *genrevs P((char const*,char const*,char const*,char const*,struct hshentries**));
-unsigned countnumflds P((char const*));
+int countnumflds P((char const*));
void getbranchno P((char const*,struct buf*));
/* rcssyn */
@@ -593,8 +638,12 @@ void getbranchno P((char const*,struct buf*));
#define KEY_EXPAND 2 /* -kk `$Keyword$' */
#define VAL_EXPAND 3 /* -kv `value' */
#define OLD_EXPAND 4 /* -ko use old string, omitting expansion */
+#define BINARY_EXPAND 5 /* -kb like -ko, but use binary mode I/O */
+#define MIN_UNEXPAND OLD_EXPAND /* min value for no logical expansion */
+#define MIN_UNCHANGED_EXPAND (OPEN_O_BINARY ? BINARY_EXPAND : OLD_EXPAND)
+ /* min value guaranteed to yield an identical file */
struct diffcmd {
- unsigned long
+ long
line1, /* number of first line */
nlines, /* number of lines affected */
adprev, /* previous 'a' line1+1 or 'd' line1 */
@@ -604,45 +653,55 @@ extern char const * Dbranch;
extern struct access * AccessList;
extern struct assoc * Symbols;
extern struct cbuf Comment;
-extern struct lock * Locks;
+extern struct cbuf Ignored;
+extern struct rcslock *Locks;
extern struct hshentry * Head;
extern int Expand;
extern int StrictLocks;
-extern unsigned TotalDeltas;
+extern int TotalDeltas;
extern char const *const expand_names[];
-extern char const Kdesc[];
-extern char const Klog[];
-extern char const Ktext[];
+extern char const
+ Kaccess[], Kauthor[], Kbranch[], Kcomment[],
+ Kdate[], Kdesc[], Kexpand[], Khead[], Klocks[], Klog[],
+ Knext[], Kstate[], Kstrict[], Ksymbols[], Ktext[];
+void unexpected_EOF P((void)) exiting;
int getdiffcmd P((RILE*,int,FILE*,struct diffcmd*));
-int putdftext P((char const*,struct cbuf,RILE*,FILE*,int));
-int putdtext P((char const*,struct cbuf,char const*,FILE*,int));
int str2expmode P((char const*));
void getadmin P((void));
void getdesc P((int));
void gettree P((void));
-void ignorephrase P((void));
+void ignorephrases P((char const*));
void initdiffcmd P((struct diffcmd*));
-void putadmin P((FILE*));
+void putadmin P((void));
void putstring P((FILE*,int,struct cbuf,int));
void puttree P((struct hshentry const*,FILE*));
+/* rcstime */
+#define zonelenmax 9 /* maxiumum length of time zone string, e.g. "+12:34:56" */
+char const *date2str P((char const[datesize],char[datesize + zonelenmax]));
+time_t date2time P((char const[datesize]));
+void str2date P((char const*,char[datesize]));
+void time2date P((time_t,char[datesize]));
+void zone_set P((char const*));
+
/* rcsutil */
extern int RCSversion;
+FILE *fopenSafer P((char const*,char const*));
char *cgetenv P((char const*));
char *fstr_save P((char const*));
char *str_save P((char const*));
-char const *date2str P((char const[datesize],char[datesize]));
char const *getusername P((int));
+int fdSafer P((int));
int getRCSINIT P((int,char**,char***));
-int run P((char const*,char const*,...));
-int runv P((char const**));
+int run P((int,char const*,...));
+int runv P((int,char const*,char const**));
malloc_type fremember P((malloc_type));
malloc_type ftestalloc P((size_t));
malloc_type testalloc P((size_t));
malloc_type testrealloc P((malloc_type,size_t));
#define ftalloc(T) ftnalloc(T,1)
#define talloc(T) tnalloc(T,1)
-#if lint
+#if RCS_lint
extern malloc_type lintalloc;
# define ftnalloc(T,n) (lintalloc = ftestalloc(sizeof(T)*(n)), (T*)0)
# define tnalloc(T,n) (lintalloc = testalloc(sizeof(T)*(n)), (T*)0)
@@ -654,6 +713,7 @@ malloc_type testrealloc P((malloc_type,size_t));
# define trealloc(T,p,n) ((T*) testrealloc((malloc_type)(p), sizeof(T)*(n)))
# define tfree(p) free((malloc_type)(p))
#endif
+time_t now P((void));
void awrite P((char const*,size_t,FILE*));
void fastcopy P((RILE*,FILE*));
void ffree P((void));
@@ -668,6 +728,14 @@ void setRCSversion P((char const*));
# define ignoreints()
# define restoreints()
#endif
+#if has_mmap && large_memory
+# if has_NFS && mmap_signal
+ void catchmmapints P((void));
+ void readAccessFilenameBuffer P((char const*,unsigned char const*));
+# else
+# define catchmmapints()
+# endif
+#endif
#if has_getuid
uid_t ruid P((void));
# define myself(u) ((u) == ruid())
@@ -684,3 +752,6 @@ void setRCSversion P((char const*));
# define seteid()
# define setrid()
#endif
+
+/* version */
+extern char const RCS_version_string[];
diff --git a/gnu/usr.bin/rcs/lib/rcsedit.c b/gnu/usr.bin/rcs/lib/rcsedit.c
index 32ff7e2..79408f3 100644
--- a/gnu/usr.bin/rcs/lib/rcsedit.c
+++ b/gnu/usr.bin/rcs/lib/rcsedit.c
@@ -1,15 +1,14 @@
-/*
- * RCS stream editor
- */
-/**********************************************************************************
+/* RCS stream editor */
+
+/******************************************************************************
* edits the input file according to a
* script from stdin, generated by diff -n
* performs keyword expansion
- **********************************************************************************
+ ******************************************************************************
*/
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -25,8 +24,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -34,15 +34,55 @@ Report problems and direct all questions to:
*/
-
-/* $Log: rcsedit.c,v $
- * Revision 1.2 1994/05/14 07:00:22 rgrimes
- * Add new option -K from David Dawes that allows you to turn on and off
- * specific keyword substitution during a rcs co command.
- * Add the new keyword FreeBSD that is IDENTICAL in operation to $Id$.
+/*
+ * $Log: rcsedit.c,v $
+ * Revision 5.19 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.18 1995/06/01 16:23:43 eggert
+ * (dirtpname): No longer external.
+ * (do_link): Simplify logic.
+ * (finisheditline, finishedit): Replace Iseek/Itell with what they stand for.
+ * (fopen_update_truncate): Replace `#if' with `if'.
+ * (keyreplace, makedirtemp): dirlen(x) -> basefilename(x)-x.
+ *
+ * (edit_string): Fix bug: if !large_memory, a bogus trailing `@' was output
+ * at the end of incomplete lines.
+ *
+ * (keyreplace): Do not assume that seeking backwards
+ * at the start of a file will fail; on some systems it succeeds.
+ * Convert C- and Pascal-style comment starts to ` *' in comment leader.
+ *
+ * (rcswriteopen): Use fdSafer to get safer file descriptor.
+ * Open RCS file with FOPEN_RB.
+ *
+ * (chnamemod): Work around bad_NFS_rename bug; don't ignore un_link result.
+ * Fall back on chmod if fchmod fails, since it might be ENOSYS.
*
- * Revision 1.1.1.1 1993/06/18 04:22:12 jkh
- * Updated GNU utilities
+ * (aflush): Move to rcslex.c.
+ *
+ * Revision 5.17 1994/03/20 04:52:58 eggert
+ * Normally calculate the $Log prefix from context, not from RCS file.
+ * Move setmtime here from rcsutil.c. Add ORCSerror. Remove lint.
+ *
+ * Revision 5.16 1993/11/03 17:42:27 eggert
+ * Add -z. Add Name keyword. If bad_unlink, ignore errno when unlink fails.
+ * Escape white space, $, and \ in keyword string file names.
+ * Don't output 2 spaces between date and time after Log.
+ *
+ * Revision 5.15 1992/07/28 16:12:44 eggert
+ * Some hosts have readlink but not ELOOP. Avoid `unsigned'.
+ * Preserve dates more systematically. Statement macro names now end in _.
+ *
+ * Revision 5.14 1992/02/17 23:02:24 eggert
+ * Add -T support.
+ *
+ * Revision 5.13 1992/01/24 18:44:19 eggert
+ * Add support for bad_chmod_close, bad_creat0.
+ *
+ * Revision 5.12 1992/01/06 02:42:34 eggert
+ * Add setmode parameter to chnamemod. addsymbol now reports changes.
+ * while (E) ; -> while (E) continue;
*
* Revision 5.11 1991/11/03 01:11:44 eggert
* Move the warning about link breaking to where they're actually being broken.
@@ -162,27 +202,36 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(editId, "$Id: rcsedit.c,v 1.2 1994/05/14 07:00:22 rgrimes Exp $")
-
-static void keyreplace P((enum markers,struct hshentry const*,FILE*));
+libId(editId, "$Id: rcsedit.c,v 5.19 1995/06/16 06:19:24 eggert Exp $")
+static void editEndsPrematurely P((void)) exiting;
+static void editLineNumberOverflow P((void)) exiting;
+static void escape_string P((FILE*,char const*));
+static void keyreplace P((enum markers,struct hshentry const*,int,RILE*,FILE*,int));
FILE *fcopy; /* result file descriptor */
-char const *resultfile; /* result file name */
+char const *resultname; /* result pathname */
int locker_expansion; /* should the locker name be appended to Id val? */
#if !large_memory
static RILE *fedit; /* edit file descriptor */
- static char const *editfile; /* edit pathname */
+ static char const *editname; /* edit pathname */
#endif
-static unsigned long editline; /* edit line counter; #lines before cursor */
+static long editline; /* edit line counter; #lines before cursor */
static long linecorr; /* #adds - #deletes in each edit run. */
/*used to correct editline in case file is not rewound after */
/* applying one delta */
-#define DIRTEMPNAMES 2
+/* indexes into dirtpname */
+#define lockdirtp_index 0
+#define newRCSdirtp_index bad_creat0
+#define newworkdirtp_index (newRCSdirtp_index+1)
+#define DIRTEMPNAMES (newworkdirtp_index + 1)
+
enum maker {notmade, real, effective};
-struct buf dirtfname[DIRTEMPNAMES]; /* unlink these when done */
-static enum maker volatile dirtfmaker[DIRTEMPNAMES]; /* if these are set */
+static struct buf dirtpname[DIRTEMPNAMES]; /* unlink these when done */
+static enum maker volatile dirtpmaker[DIRTEMPNAMES]; /* if these are set */
+#define lockname (dirtpname[lockdirtp_index].string)
+#define newRCSname (dirtpname[newRCSdirtp_index].string)
#if has_NFS || bad_unlink
@@ -195,17 +244,19 @@ un_link(s)
*/
{
# if bad_unlink
- int e;
if (unlink(s) == 0)
return 0;
- e = errno;
-# if has_NFS
- if (e == ENOENT)
- return 0;
-# endif
- if (chmod(s, S_IWUSR) != 0) {
- errno = e;
- return -1;
+ else {
+ int e = errno;
+ /*
+ * Forge ahead even if errno == ENOENT; some completely
+ * brain-damaged hosts (e.g. PCTCP 2.2) yield ENOENT
+ * even for existing unwritable files.
+ */
+ if (chmod(s, S_IWUSR) != 0) {
+ errno = e;
+ return -1;
+ }
}
# endif
# if has_NFS
@@ -220,38 +271,37 @@ un_link(s)
# if !has_NFS
# define do_link(s,t) link(s,t)
# else
+ static int do_link P((char const*,char const*));
static int
do_link(s, t)
char const *s, *t;
/* Link S to T, ignoring bogus EEXIST problems due to NFS failures. */
{
- struct stat sb, tb;
-
- if (link(s,t) == 0)
- return 0;
- if (errno != EEXIST)
- return -1;
- if (
- stat(s, &sb) == 0 &&
- stat(t, &tb) == 0 &&
- sb.st_ino == tb.st_ino &&
- sb.st_dev == tb.st_dev
- )
- return 0;
- errno = EEXIST;
- return -1;
+ int r = link(s, t);
+
+ if (r != 0 && errno == EEXIST) {
+ struct stat sb, tb;
+ if (
+ stat(s, &sb) == 0 &&
+ stat(t, &tb) == 0 &&
+ same_file(sb, tb, 0)
+ )
+ r = 0;
+ errno = EEXIST;
+ }
+ return r;
}
# endif
#endif
- static exiting void
+ static void
editEndsPrematurely()
{
fatserror("edit script ends prematurely");
}
- static exiting void
+ static void
editLineNumberOverflow()
{
fatserror("edit script refers to line past end of file");
@@ -263,11 +313,12 @@ editLineNumberOverflow()
#if has_memmove
# define movelines(s1, s2, n) VOID memmove(s1, s2, (n)*sizeof(Iptr_type))
#else
+ static void movelines P((Iptr_type*,Iptr_type const*,long));
static void
movelines(s1, s2, n)
register Iptr_type *s1;
register Iptr_type const *s2;
- register unsigned long n;
+ register long n;
{
if (s1 < s2)
do {
@@ -283,22 +334,26 @@ movelines(s1, s2, n)
}
#endif
+static void deletelines P((long,long));
+static void finisheditline P((RILE*,FILE*,Iptr_type,struct hshentry const*));
+static void insertline P((long,Iptr_type));
+static void snapshotline P((FILE*,Iptr_type));
+
/*
* `line' contains pointers to the lines in the currently `edited' file.
* It is a 0-origin array that represents linelim-gapsize lines.
- * line[0..gap-1] and line[gap+gapsize..linelim-1] contain pointers to lines.
- * line[gap..gap+gapsize-1] contains garbage.
+ * line[0 .. gap-1] and line[gap+gapsize .. linelim-1] hold pointers to lines.
+ * line[gap .. gap+gapsize-1] contains garbage.
*
* Any @s in lines are duplicated.
* Lines are terminated by \n, or (for a last partial line only) by single @.
*/
static Iptr_type *line;
-static unsigned long gap, gapsize, linelim;
-
+static size_t gap, gapsize, linelim;
static void
insertline(n, l)
- unsigned long n;
+ long n;
Iptr_type l;
/* Before line N, insert line L. N is 0-origin. */
{
@@ -324,10 +379,10 @@ insertline(n, l)
static void
deletelines(n, nlines)
- unsigned long n, nlines;
+ long n, nlines;
/* Delete lines N through N+NLINES-1. N is 0-origin. */
{
- unsigned long l = n + nlines;
+ long l = n + nlines;
if (linelim-gapsize < l || l < n)
editLineNumberOverflow();
if (l < gap)
@@ -348,7 +403,7 @@ snapshotline(f, l)
do {
if ((c = *l++) == SDELIM && *l++ != SDELIM)
return;
- aputc(c, f);
+ aputc_(c, f)
} while (c != '\n');
}
@@ -371,8 +426,8 @@ finisheditline(fin, fout, l, delta)
Iptr_type l;
struct hshentry const *delta;
{
- Iseek(fin, l);
- if (expandline(fin, fout, delta, true, (FILE*)0) < 0)
+ fin->ptr = l;
+ if (expandline(fin, fout, delta, true, (FILE*)0, true) < 0)
faterror("finisheditline internal error");
}
@@ -394,28 +449,27 @@ finishedit(delta, outfile, done)
else {
register Iptr_type *p, *lim, *l = line;
register RILE *fin = finptr;
- Iptr_type here = Itell(fin);
+ Iptr_type here = fin->ptr;
for (p=l, lim=l+gap; p<lim; )
finisheditline(fin, outfile, *p++, delta);
for (p+=gapsize, lim=l+linelim; p<lim; )
finisheditline(fin, outfile, *p++, delta);
- Iseek(fin, here);
+ fin->ptr = here;
}
}
}
-/* Open a temporary FILENAME for output, truncating any previous contents. */
-# define fopen_update_truncate(filename) fopen(filename, FOPEN_W_WORK)
+/* Open a temporary NAME for output, truncating any previous contents. */
+# define fopen_update_truncate(name) fopenSafer(name, FOPEN_W_WORK)
#else /* !large_memory */
+ static FILE * fopen_update_truncate P((char const*));
static FILE *
-fopen_update_truncate(filename)
- char const *filename;
+fopen_update_truncate(name)
+ char const *name;
{
-# if bad_fopen_wplus
- if (un_link(filename) != 0)
- efaterror(filename);
-# endif
- return fopen(filename, FOPEN_WPLUS_WORK);
+ if (bad_fopen_wplus && un_link(name) != 0)
+ efaterror(name);
+ return fopenSafer(name, FOPEN_WPLUS_WORK);
}
#endif
@@ -425,31 +479,31 @@ openfcopy(f)
FILE *f;
{
if (!(fcopy = f)) {
- if (!resultfile)
- resultfile = maketemp(2);
- if (!(fcopy = fopen_update_truncate(resultfile)))
- efaterror(resultfile);
+ if (!resultname)
+ resultname = maketemp(2);
+ if (!(fcopy = fopen_update_truncate(resultname)))
+ efaterror(resultname);
}
}
#if !large_memory
+ static void swapeditfiles P((FILE*));
static void
swapeditfiles(outfile)
FILE *outfile;
-/* Function: swaps resultfile and editfile, assigns fedit=fcopy,
+/* Function: swaps resultname and editname, assigns fedit=fcopy,
* and rewinds fedit for reading. Set fcopy to outfile if nonnull;
- * otherwise, set fcopy to be resultfile opened for reading and writing.
+ * otherwise, set fcopy to be resultname opened for reading and writing.
*/
{
char const *tmpptr;
editline = 0; linecorr = 0;
- if (fseek(fcopy, 0L, SEEK_SET) != 0)
- Oerror();
+ Orewind(fcopy);
fedit = fcopy;
- tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
+ tmpptr=editname; editname=resultname; resultname=tmpptr;
openfcopy(outfile);
}
@@ -458,7 +512,7 @@ snapshotedit(f)
FILE *f;
/* Copy the current state of the edits to F. */
{
- finishedit((struct hshentry *)nil, (FILE*)0, false);
+ finishedit((struct hshentry *)0, (FILE*)0, false);
fastcopy(fedit, f);
Irewind(fedit);
}
@@ -469,7 +523,7 @@ finishedit(delta, outfile, done)
FILE *outfile;
int done;
/* copy the rest of the edit file and close it (if it exists).
- * if delta!=nil, perform keyword substitution at the same time.
+ * if delta, perform keyword substitution at the same time.
* If DONE is set, we are finishing the last pass.
*/
{
@@ -479,8 +533,8 @@ finishedit(delta, outfile, done)
fe = fedit;
if (fe) {
fc = fcopy;
- if (delta!=nil) {
- while (1 < expandline(fe,fc,delta,false,(FILE*)0))
+ if (delta) {
+ while (1 < expandline(fe,fc,delta,false,(FILE*)0,true))
;
} else {
fastcopy(fe,fc);
@@ -497,13 +551,14 @@ finishedit(delta, outfile, done)
#if large_memory
# define copylines(upto,delta) (editline = (upto))
#else
+ static void copylines P((long,struct hshentry const*));
static void
-copylines(upto,delta)
- register unsigned long upto;
+copylines(upto, delta)
+ register long upto;
struct hshentry const *delta;
/*
* Copy input lines editline+1..upto from fedit to fcopy.
- * If delta != nil, keyword expansion is done simultaneously.
+ * If delta, keyword expansion is done simultaneously.
* editline is updated. Rewinds a file only if necessary.
*/
{
@@ -514,7 +569,7 @@ copylines(upto,delta)
if (upto < editline) {
/* swap files */
- finishedit((struct hshentry *)nil, (FILE*)0, false);
+ finishedit((struct hshentry *)0, (FILE*)0, false);
/* assumes edit only during last pass, from the beginning*/
}
fe = fedit;
@@ -522,15 +577,15 @@ copylines(upto,delta)
if (editline < upto)
if (delta)
do {
- if (expandline(fe,fc,delta,false,(FILE*)0) <= 1)
- editLineNumberOverflow();
+ if (expandline(fe,fc,delta,false,(FILE*)0,true) <= 1)
+ editLineNumberOverflow();
} while (++editline < upto);
else {
setupcache(fe); cache(fe);
do {
do {
- cachegeteof(c, editLineNumberOverflow(););
- aputc(c, fc);
+ cachegeteof_(c, editLineNumberOverflow();)
+ aputc_(c, fc)
} while (c != '\n');
} while (++editline < upto);
uncache(fe);
@@ -549,8 +604,8 @@ xpandstring(delta)
* If foutptr is nonnull, the string is also copied unchanged to foutptr.
*/
{
- while (1 < expandline(finptr,fcopy,delta,true,foutptr))
- ;
+ while (1 < expandline(finptr,fcopy,delta,true,foutptr,true))
+ continue;
}
@@ -574,7 +629,7 @@ copystring()
fcop = fcopy;
amidline = false;
for (;;) {
- GETC(frew,c);
+ GETC_(frew,c)
switch (c) {
case '\n':
++editline;
@@ -582,7 +637,7 @@ copystring()
amidline = false;
break;
case SDELIM:
- GETC(frew,c);
+ GETC_(frew,c)
if (c != SDELIM) {
/* end of string */
nextc = c;
@@ -595,7 +650,7 @@ copystring()
amidline = true;
break;
}
- aputc(c,fcop);
+ aputc_(c,fcop)
}
}
@@ -605,18 +660,18 @@ enterstring()
/* Like copystring, except the string is put into the edit data structure. */
{
#if !large_memory
- editfile = 0;
+ editname = 0;
fedit = 0;
editline = linecorr = 0;
- resultfile = maketemp(1);
- if (!(fcopy = fopen_update_truncate(resultfile)))
- efaterror(resultfile);
+ resultname = maketemp(1);
+ if (!(fcopy = fopen_update_truncate(resultname)))
+ efaterror(resultname);
copystring();
#else
register int c;
declarecache;
register FILE *frew;
- register unsigned long e, oe;
+ register long e, oe;
register int amidline, oamidline;
register Iptr_type optr;
register RILE *fin;
@@ -630,8 +685,8 @@ enterstring()
frew = foutptr;
amidline = false;
for (;;) {
- optr = cachetell();
- GETC(frew,c);
+ optr = cacheptr();
+ GETC_(frew,c)
oamidline = amidline;
oe = e;
switch (c) {
@@ -641,7 +696,7 @@ enterstring()
amidline = false;
break;
case SDELIM:
- GETC(frew,c);
+ GETC_(frew,c)
if (c != SDELIM) {
/* end of string */
nextc = c;
@@ -675,13 +730,13 @@ edit_string()
* Read an edit script from finptr and applies it to the edit file.
#if !large_memory
* The result is written to fcopy.
- * If delta!=nil, keyword expansion is performed simultaneously.
+ * If delta, keyword expansion is performed simultaneously.
* If running out of lines in fedit, fedit and fcopy are swapped.
- * editfile is the name of the file that goes with fedit.
+ * editname is the name of the file that goes with fedit.
#endif
* If foutptr is set, the edit script is also copied verbatim to foutptr.
* Assumes that all these files are open.
- * resultfile is the name of the file that goes with fcopy.
+ * resultname is the name of the file that goes with fcopy.
* Assumes the next input character from finptr is the first character of
* the edit script. Resets nextc on exit.
*/
@@ -692,13 +747,13 @@ edit_string()
register FILE *frew;
# if !large_memory
register FILE *f;
- unsigned long line_lim = ULONG_MAX;
+ long line_lim = LONG_MAX;
register RILE *fe;
# endif
- register unsigned long i;
+ register long i;
register RILE *fin;
# if large_memory
- register unsigned long j;
+ register long j;
# endif
struct diffcmd dc;
@@ -726,12 +781,13 @@ edit_string()
do {
/*skip next line*/
do {
- Igeteof(fe, c, { if (i!=1) editLineNumberOverflow(); line_lim = dc.dafter; break; } );
+ Igeteof_(fe, c, { if (i!=1) editLineNumberOverflow(); line_lim = dc.dafter; break; } )
} while (c != '\n');
} while (--i);
# endif
} else {
- copylines(dc.line1, delta); /*copy only; no delete*/
+ /* Copy lines without deleting any. */
+ copylines(dc.line1, delta);
i = dc.nlines;
# if large_memory
j = editline+linecorr;
@@ -741,7 +797,7 @@ edit_string()
f = fcopy;
if (delta)
do {
- switch (expandline(fin,f,delta,true,frew)) {
+ switch (expandline(fin,f,delta,true,frew,true)){
case 0: case 1:
if (i==1)
return;
@@ -756,17 +812,12 @@ edit_string()
cache(fin);
do {
# if large_memory
- insertline(j++, cachetell());
+ insertline(j++, cacheptr());
# endif
for (;;) {
- GETC(frew, c);
-# if !large_memory
- aputc(c, f);
-# endif
- if (c == '\n')
- break;
+ GETC_(frew, c)
if (c==SDELIM) {
- GETC(frew, c);
+ GETC_(frew, c)
if (c!=SDELIM) {
if (--i)
editEndsPrematurely();
@@ -775,6 +826,11 @@ edit_string()
return;
}
}
+# if !large_memory
+ aputc_(c, f)
+# endif
+ if (c == '\n')
+ break;
}
++rcsline;
} while (--i);
@@ -790,17 +846,18 @@ edit_string()
int
-expandline(infile, outfile, delta, delimstuffed, frewfile)
+expandline(infile, outfile, delta, delimstuffed, frewfile, dolog)
RILE *infile;
FILE *outfile, *frewfile;
struct hshentry const *delta;
- int delimstuffed;
+ int delimstuffed, dolog;
/*
* Read a line from INFILE and write it to OUTFILE.
+ * Do keyword expansion with data from DELTA.
* If DELIMSTUFFED is true, double SDELIM is replaced with single SDELIM.
- * Keyword expansion is performed with data from delta.
* If FREWFILE is set, copy the line unchanged to FREWFILE.
* DELIMSTUFFED must be true if FREWFILE is set.
+ * Append revision history to log only if DOLOG is set.
* Yields -1 if no data is copied, 0 if an incomplete line is copied,
* 2 if a complete line is copied; adds 1 to yield if expansion occurred.
*/
@@ -823,15 +880,15 @@ expandline(infile, outfile, delta, delimstuffed, frewfile)
r = -1;
for (;;) {
- if (ds) {
- GETC(frew, c);
- } else
- cachegeteof(c, goto uncache_exit;);
+ if (ds)
+ GETC_(frew, c)
+ else
+ cachegeteof_(c, goto uncache_exit;)
for (;;) {
switch (c) {
case SDELIM:
if (ds) {
- GETC(frew, c);
+ GETC_(frew, c)
if (c != SDELIM) {
/* end of string */
nextc=c;
@@ -840,13 +897,13 @@ expandline(infile, outfile, delta, delimstuffed, frewfile)
}
/* fall into */
default:
- aputc(c,out);
+ aputc_(c,out)
r = 0;
break;
case '\n':
rcsline += ds;
- aputc(c,out);
+ aputc_(c,out)
r = 2;
goto uncache_exit;
@@ -857,11 +914,11 @@ expandline(infile, outfile, delta, delimstuffed, frewfile)
tp = keyval.string;
*tp++ = KDELIM;
for (;;) {
- if (ds) {
- GETC(frew, c);
- } else
- cachegeteof(c, goto keystring_eof;);
- if (tp < keyval.string+keylength+1)
+ if (ds)
+ GETC_(frew, c)
+ else
+ cachegeteof_(c, goto keystring_eof;)
+ if (tp <= &keyval.string[keylength])
switch (ctab[c]) {
case LETTER: case Letter:
*tp++ = c;
@@ -884,17 +941,17 @@ expandline(infile, outfile, delta, delimstuffed, frewfile)
/* try to find closing KDELIM, and replace value */
tlim = keyval.string + keyval.size;
for (;;) {
- if (ds) {
- GETC(frew, c);
- } else
- cachegeteof(c, goto keystring_eof;);
+ if (ds)
+ GETC_(frew, c)
+ else
+ cachegeteof_(c, goto keystring_eof;)
if (c=='\n' || c==KDELIM)
break;
*tp++ =c;
if (tlim <= tp)
tp = bufenlarge(&keyval, &tlim);
if (c==SDELIM && ds) { /*skip next SDELIM */
- GETC(frew, c);
+ GETC_(frew, c)
if (c != SDELIM) {
/* end of string before closing KDELIM or newline */
nextc = c;
@@ -910,7 +967,9 @@ expandline(infile, outfile, delta, delimstuffed, frewfile)
}
}
/* now put out the new keyword value */
- keyreplace(matchresult,delta,out);
+ uncache(infile);
+ keyreplace(matchresult, delta, ds, infile, out, dolog);
+ cache(infile);
e = 1;
break;
}
@@ -927,117 +986,228 @@ expandline(infile, outfile, delta, delimstuffed, frewfile)
}
+ static void
+escape_string(out, s)
+ register FILE *out;
+ register char const *s;
+/* Output to OUT the string S, escaping chars that would break `ci -k'. */
+{
+ register char c;
+ for (;;)
+ switch ((c = *s++)) {
+ case 0: return;
+ case '\t': aputs("\\t", out); break;
+ case '\n': aputs("\\n", out); break;
+ case ' ': aputs("\\040", out); break;
+ case KDELIM: aputs("\\044", out); break;
+ case '\\': if (VERSION(5)<=RCSversion) {aputs("\\\\", out); break;}
+ /* fall into */
+ default: aputc_(c, out) break;
+ }
+}
+
char const ciklog[ciklogsize] = "checked in with -k by ";
static void
-keyreplace(marker,delta,out)
+keyreplace(marker, delta, delimstuffed, infile, out, dolog)
enum markers marker;
register struct hshentry const *delta;
+ int delimstuffed;
+ RILE *infile;
register FILE *out;
+ int dolog;
/* function: outputs the keyword value(s) corresponding to marker.
* Attributes are derived from delta.
*/
{
register char const *sp, *cp, *date;
- register char c;
+ register int c;
register size_t cs, cw, ls;
char const *sp1;
- char datebuf[datesize];
+ char datebuf[datesize + zonelenmax];
int RCSv;
+ int exp;
sp = Keyword[(int)marker];
-
- if (Expand == KEY_EXPAND) {
- aprintf(out, "%c%s%c", KDELIM, sp, KDELIM);
- return;
- }
-
- date= delta->date;
+ exp = Expand;
+ date = delta->date;
RCSv = RCSversion;
- if (Expand == KEYVAL_EXPAND || Expand == KEYVALLOCK_EXPAND)
- aprintf(out, "%c%s%c%c", KDELIM, sp, VDELIM,
+ if (exp != VAL_EXPAND)
+ aprintf(out, "%c%s", KDELIM, sp);
+ if (exp != KEY_EXPAND) {
+
+ if (exp != VAL_EXPAND)
+ aprintf(out, "%c%c", VDELIM,
marker==Log && RCSv<VERSION(5) ? '\t' : ' '
);
- switch (marker) {
- case Author:
+ switch (marker) {
+ case Author:
aputs(delta->author, out);
break;
- case Date:
+ case Date:
aputs(date2str(date,datebuf), out);
break;
- /*
- * The FreeBSD keyword is identical to Id.
- */
- case FreeBSD:
- case Id:
- case Header:
- aprintf(out, "%s %s %s %s %s",
- marker==Id || marker==FreeBSD || RCSv<VERSION(4)
- ? basename(RCSfilename)
- : getfullRCSname(),
+ case Id:
+ case Header:
+ escape_string(out,
+ marker==Id || RCSv<VERSION(4)
+ ? basefilename(RCSname)
+ : getfullRCSname()
+ );
+ aprintf(out, " %s %s %s %s",
delta->num,
date2str(date, datebuf),
delta->author,
RCSv==VERSION(3) && delta->lockedby ? "Locked"
: delta->state
);
- if (delta->lockedby!=nil)
+ if (delta->lockedby)
if (VERSION(5) <= RCSv) {
- if (locker_expansion || Expand==KEYVALLOCK_EXPAND)
+ if (locker_expansion || exp==KEYVALLOCK_EXPAND)
aprintf(out, " %s", delta->lockedby);
} else if (RCSv == VERSION(4))
aprintf(out, " Locker: %s", delta->lockedby);
break;
- case Locker:
+ case Locker:
if (delta->lockedby)
if (
locker_expansion
- || Expand == KEYVALLOCK_EXPAND
+ || exp == KEYVALLOCK_EXPAND
|| RCSv <= VERSION(4)
)
aputs(delta->lockedby, out);
break;
- case Log:
- case RCSfile:
- aputs(basename(RCSfilename), out);
+ case Log:
+ case RCSfile:
+ escape_string(out, basefilename(RCSname));
break;
- case Revision:
+ case Name:
+ if (delta->name)
+ aputs(delta->name, out);
+ break;
+ case Revision:
aputs(delta->num, out);
break;
- case Source:
- aputs(getfullRCSname(), out);
+ case Source:
+ escape_string(out, getfullRCSname());
break;
- case State:
+ case State:
aputs(delta->state, out);
break;
- default:
+ default:
break;
- }
- if (Expand == KEYVAL_EXPAND || Expand == KEYVALLOCK_EXPAND) {
+ }
+ if (exp != VAL_EXPAND)
afputc(' ', out);
- afputc(KDELIM, out);
}
- if (marker == Log) {
+ if (exp != VAL_EXPAND)
+ afputc(KDELIM, out);
+
+ if (marker == Log && dolog) {
+ struct buf leader;
+
sp = delta->log.string;
ls = delta->log.size;
if (sizeof(ciklog)-1<=ls && !memcmp(sp,ciklog,sizeof(ciklog)-1))
return;
+ bufautobegin(&leader);
+ if (RCSversion < VERSION(5)) {
+ cp = Comment.string;
+ cs = Comment.size;
+ } else {
+ int kdelim_found = 0;
+ Ioffset_type chars_read = Itell(infile);
+ declarecache;
+ setupcache(infile); cache(infile);
+
+ c = 0; /* Pacify `gcc -Wall'. */
+
+ /*
+ * Back up to the start of the current input line,
+ * setting CS to the number of characters before `$Log'.
+ */
+ cs = 0;
+ for (;;) {
+ if (!--chars_read)
+ goto done_backing_up;
+ cacheunget_(infile, c)
+ if (c == '\n')
+ break;
+ if (c == SDELIM && delimstuffed) {
+ if (!--chars_read)
+ break;
+ cacheunget_(infile, c)
+ if (c != SDELIM) {
+ cacheget_(c)
+ break;
+ }
+ }
+ cs += kdelim_found;
+ kdelim_found |= c==KDELIM;
+ }
+ cacheget_(c)
+ done_backing_up:;
+
+ /* Copy characters before `$Log' into LEADER. */
+ bufalloc(&leader, cs);
+ cp = leader.string;
+ for (cw = 0; cw < cs; cw++) {
+ leader.string[cw] = c;
+ if (c == SDELIM && delimstuffed)
+ cacheget_(c)
+ cacheget_(c)
+ }
+
+ /* Convert traditional C or Pascal leader to ` *'. */
+ for (cw = 0; cw < cs; cw++)
+ if (ctab[(unsigned char) cp[cw]] != SPACE)
+ break;
+ if (
+ cw+1 < cs
+ && cp[cw+1] == '*'
+ && (cp[cw] == '/' || cp[cw] == '(')
+ ) {
+ size_t i = cw+1;
+ for (;;)
+ if (++i == cs) {
+ warn(
+ "`%c* $Log' is obsolescent; use ` * $Log'.",
+ cp[cw]
+ );
+ leader.string[cw] = ' ';
+ break;
+ } else if (ctab[(unsigned char) cp[i]] != SPACE)
+ break;
+ }
+
+ /* Skip `$Log ... $' string. */
+ do {
+ cacheget_(c)
+ } while (c != KDELIM);
+ uncache(infile);
+ }
afputc('\n', out);
- cp = Comment.string;
- cw = cs = Comment.size;
awrite(cp, cs, out);
- /* oddity: 2 spaces between date and time, not 1 as usual */
- sp1 = strchr(date2str(date,datebuf), ' ');
- aprintf(out, "Revision %s %.*s %s %s",
- delta->num, (int)(sp1-datebuf), datebuf, sp1, delta->author
- );
+ sp1 = date2str(date, datebuf);
+ if (VERSION(5) <= RCSv) {
+ aprintf(out, "Revision %s %s %s",
+ delta->num, sp1, delta->author
+ );
+ } else {
+ /* oddity: 2 spaces between date and time, not 1 as usual */
+ sp1 = strchr(sp1, ' ');
+ aprintf(out, "Revision %s %.*s %s %s",
+ delta->num, (int)(sp1-datebuf), datebuf, sp1,
+ delta->author
+ );
+ }
/* Do not include state: it may change and is not updated. */
- /* Comment is the comment leader. */
+ cw = cs;
if (VERSION(5) <= RCSv)
for (; cw && (cp[cw-1]==' ' || cp[cw-1]=='\t'); --cw)
- ;
+ continue;
for (;;) {
afputc('\n', out);
awrite(cp, cw, out);
@@ -1056,10 +1226,12 @@ keyreplace(marker,delta,out)
} while (c != '\n');
}
}
+ bufautoend(&leader);
}
}
#if has_readlink
+ static int resolve_symlink P((struct buf*));
static int
resolve_symlink(L)
struct buf *L;
@@ -1075,7 +1247,7 @@ resolve_symlink(L)
size_t s;
ssize_t r;
struct buf bigbuf;
- unsigned linkcount = MAXSYMLINKS + 1;
+ int linkcount = MAXSYMLINKS;
b = a;
s = sizeof(a);
@@ -1085,21 +1257,29 @@ resolve_symlink(L)
bufalloc(&bigbuf, s<<1);
b = bigbuf.string;
s = bigbuf.size;
- } else if (!--linkcount) {
+ } else if (!linkcount--) {
+# ifndef ELOOP
+ /*
+ * Some pedantic Posix 1003.1-1990 hosts have readlink
+ * but not ELOOP. Approximate ELOOP with EMLINK.
+ */
+# define ELOOP EMLINK
+# endif
errno = ELOOP;
return -1;
} else {
/* Splice symbolic link into L. */
b[r] = '\0';
- L->string[ROOTPATH(b) ? (size_t)0 : dirlen(L->string)] = '\0';
+ L->string[
+ ROOTPATH(b) ? 0 : basefilename(L->string) - L->string
+ ] = '\0';
bufscat(L, b);
}
e = errno;
bufautoend(&bigbuf);
errno = e;
switch (e) {
- case ENXIO:
- case EINVAL: return 1;
+ case readlink_isreg_errno: return 1;
case ENOENT: return 0;
default: return -1;
}
@@ -1112,24 +1292,23 @@ rcswriteopen(RCSbuf, status, mustread)
struct stat *status;
int mustread;
/*
- * Create the lock file corresponding to RCSNAME.
- * Then try to open RCSNAME for reading and yield its FILE* descriptor.
+ * Create the lock file corresponding to RCSBUF.
+ * Then try to open RCSBUF for reading and yield its RILE* descriptor.
* Put its status into *STATUS too.
* MUSTREAD is true if the file must already exist, too.
* If all goes well, discard any previously acquired locks,
- * and set frewrite to the FILE* descriptor of the lock file,
- * which will eventually turn into the new RCS file.
+ * and set fdlock to the file descriptor of the RCS lockfile.
*/
{
register char *tp;
- register char const *sp, *RCSname, *x;
+ register char const *sp, *RCSpath, *x;
RILE *f;
size_t l;
- int e, exists, fdesc, previouslock, r;
+ int e, exists, fdesc, fdescSafer, r, waslocked;
struct buf *dirt;
struct stat statbuf;
- previouslock = frewrite != 0;
+ waslocked = 0 <= fdlock;
exists =
# if has_readlink
resolve_symlink(RCSbuf);
@@ -1137,7 +1316,7 @@ rcswriteopen(RCSbuf, status, mustread)
stat(RCSbuf->string, &statbuf) == 0 ? 1
: errno==ENOENT ? 0 : -1;
# endif
- if (exists < (mustread|previouslock))
+ if (exists < (mustread|waslocked))
/*
* There's an unusual problem with the RCS file;
* or the RCS file doesn't exist,
@@ -1145,26 +1324,26 @@ rcswriteopen(RCSbuf, status, mustread)
*/
return 0;
- RCSname = RCSbuf->string;
- sp = basename(RCSname);
- l = sp - RCSname;
- dirt = &dirtfname[previouslock];
- bufscpy(dirt, RCSname);
+ RCSpath = RCSbuf->string;
+ sp = basefilename(RCSpath);
+ l = sp - RCSpath;
+ dirt = &dirtpname[waslocked];
+ bufscpy(dirt, RCSpath);
tp = dirt->string + l;
- x = rcssuffix(RCSname);
+ x = rcssuffix(RCSpath);
# if has_readlink
if (!x) {
- error("symbolic link to non RCS filename `%s'", RCSname);
+ error("symbolic link to non RCS file `%s'", RCSpath);
errno = EINVAL;
return 0;
}
# endif
if (*sp == *x) {
- error("RCS filename `%s' incompatible with suffix `%s'", sp, x);
+ error("RCS pathname `%s' incompatible with suffix `%s'", sp, x);
errno = EINVAL;
return 0;
}
- /* Create a lock file whose name is a function of the RCS filename. */
+ /* Create a lock filename that is a function of the RCS filename. */
if (*x) {
/*
* The suffix is nonempty.
@@ -1184,38 +1363,41 @@ rcswriteopen(RCSbuf, status, mustread)
* with last char replaced by '_'.
*/
while ((*tp++ = *sp++))
- ;
+ continue;
tp -= 2;
if (*tp == '_') {
- error("RCS filename `%s' ends with `%c'", RCSname, *tp);
+ error("RCS pathname `%s' ends with `%c'", RCSpath, *tp);
errno = EINVAL;
return 0;
}
*tp = '_';
}
- sp = tp = dirt->string;
+ sp = dirt->string;
f = 0;
/*
* good news:
- * open(f, O_CREAT|O_EXCL|O_TRUNC|O_WRONLY, READONLY) is atomic
- * according to Posix 1003.1-1990.
+ * open(f, O_CREAT|O_EXCL|O_TRUNC|..., OPEN_CREAT_READONLY)
+ * is atomic according to Posix 1003.1-1990.
* bad news:
* NFS ignores O_EXCL and doesn't comply with Posix 1003.1-1990.
* good news:
- * (O_TRUNC,READONLY) normally guarantees atomicity even with NFS.
+ * (O_TRUNC,OPEN_CREAT_READONLY) normally guarantees atomicity
+ * even with NFS.
* bad news:
- * If you're root, (O_TRUNC,READONLY) doesn't guarantee atomicity.
+ * If you're root, (O_TRUNC,OPEN_CREAT_READONLY) doesn't
+ * guarantee atomicity.
* good news:
* Root-over-the-wire NFS access is rare for security reasons.
* This bug has never been reported in practice with RCS.
* So we don't worry about this bug.
*
* An even rarer NFS bug can occur when clients retry requests.
- * Suppose client A renames the lock file ",f," to "f,v"
- * at about the same time that client B creates ",f,",
+ * This can happen in the usual case of NFS over UDP.
+ * Suppose client A releases a lock by renaming ",f," to "f,v" at
+ * about the same time that client B obtains a lock by creating ",f,",
* and suppose A's first rename request is delayed, so A reissues it.
* The sequence of events might be:
* A sends rename(",f,", "f,v")
@@ -1228,20 +1410,20 @@ rcswriteopen(RCSbuf, status, mustread)
* This not only wrongly deletes B's lock, it removes the RCS file!
* Most NFS implementations have idempotency caches that usually prevent
* this scenario, but such caches are finite and can be overrun.
- * This problem afflicts programs that use the traditional
+ * This problem afflicts not only RCS, which uses open() and rename()
+ * to get and release locks; it also afflicts the traditional
* Unix method of using link() and unlink() to get and release locks,
- * as well as RCS's method of using open() and rename().
- * There is no easy workaround for either link-unlink or open-rename.
+ * and the less traditional method of using mkdir() and rmdir().
+ * There is no easy workaround.
* Any new method based on lockf() seemingly would be incompatible with
* the old methods; besides, lockf() is notoriously buggy under NFS.
* Since this problem afflicts scads of Unix programs, but is so rare
* that nobody seems to be worried about it, we won't worry either.
*/
-# define READONLY (S_IRUSR|S_IRGRP|S_IROTH)
# if !open_can_creat
-# define create(f) creat(f, READONLY)
+# define create(f) creat(f, OPEN_CREAT_READONLY)
# else
-# define create(f) open(f, O_BINARY|O_CREAT|O_EXCL|O_TRUNC|O_WRONLY, READONLY)
+# define create(f) open(f, OPEN_O_BINARY|OPEN_O_LOCK|OPEN_O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, OPEN_CREAT_READONLY)
# endif
catchints();
@@ -1253,34 +1435,35 @@ rcswriteopen(RCSbuf, status, mustread)
*/
seteid();
fdesc = create(sp);
+ fdescSafer = fdSafer(fdesc); /* Do it now; setrid might use stderr. */
e = errno;
setrid();
- if (fdesc < 0) {
- if (e == EACCES && stat(tp,&statbuf) == 0)
+ if (0 <= fdesc)
+ dirtpmaker[0] = effective;
+
+ if (fdescSafer < 0) {
+ if (e == EACCES && stat(sp,&statbuf) == 0)
/* The RCS file is busy. */
e = EEXIST;
} else {
- dirtfmaker[0] = effective;
e = ENOENT;
if (exists) {
- f = Iopen(RCSname, FOPEN_R, status);
+ f = Iopen(RCSpath, FOPEN_RB, status);
e = errno;
- if (f && previouslock) {
+ if (f && waslocked) {
/* Discard the previous lock in favor of this one. */
- Ozclose(&frewrite);
+ ORCSclose();
seteid();
- if ((r = un_link(newRCSfilename)) != 0)
- e = errno;
+ r = un_link(lockname);
+ e = errno;
setrid();
if (r != 0)
- enfaterror(e, newRCSfilename);
- bufscpy(&dirtfname[0], tp);
+ enfaterror(e, lockname);
+ bufscpy(&dirtpname[lockdirtp_index], sp);
}
}
- if (!(frewrite = fdopen(fdesc, FOPEN_W))) {
- efaterror(newRCSfilename);
- }
+ fdlock = fdescSafer;
}
restoreints();
@@ -1298,33 +1481,31 @@ keepdirtemp(name)
{
register int i;
for (i=DIRTEMPNAMES; 0<=--i; )
- if (dirtfname[i].string == name) {
- dirtfmaker[i] = notmade;
+ if (dirtpname[i].string == name) {
+ dirtpmaker[i] = notmade;
return;
}
faterror("keepdirtemp");
}
char const *
-makedirtemp(name, n)
- register char const *name;
- int n;
+makedirtemp(isworkfile)
+ int isworkfile;
/*
- * Have maketemp() do all the work if name is null.
- * Otherwise, create a unique filename in name's dir using n and name
- * and store it into the dirtfname[n].
- * Because of storage in tfnames, dirtempunlink() can unlink the file later.
- * Return a pointer to the filename created.
+ * Create a unique pathname and store it into dirtpname.
+ * Because of storage in tpnames, dirtempunlink() can unlink the file later.
+ * Return a pointer to the pathname created.
+ * If ISWORKFILE is 1, put it into the working file's directory;
+ * if 0, put the unique file in RCSfile's directory.
*/
{
register char *tp, *np;
register size_t dl;
register struct buf *bn;
+ register char const *name = isworkfile ? workname : RCSname;
- if (!name)
- return maketemp(n);
- dl = dirlen(name);
- bn = &dirtfname[n];
+ dl = basefilename(name) - name;
+ bn = &dirtpname[newRCSdirtp_index + isworkfile];
bufalloc(bn,
# if has_mktemp
dl + 9
@@ -1336,19 +1517,19 @@ makedirtemp(name, n)
np = tp = bn->string;
tp += dl;
*tp++ = '_';
- *tp++ = '0'+n;
+ *tp++ = '0'+isworkfile;
catchints();
# if has_mktemp
VOID strcpy(tp, "XXXXXX");
if (!mktemp(np) || !*np)
- faterror("can't make temporary file name `%.*s%c_%cXXXXXX'",
- (int)dl, name, SLASH, '0'+n
+ faterror("can't make temporary pathname `%.*s_%cXXXXXX'",
+ (int)dl, name, '0'+isworkfile
);
# else
/*
* Posix 1003.1-1990 has no reliable way
* to create a unique file in a named directory.
- * We fudge here. If the working file name is abcde,
+ * We fudge here. If the filename is abcde,
* the temp filename is _Ncde where N is a digit.
*/
name += dl;
@@ -1356,7 +1537,7 @@ makedirtemp(name, n)
if (*name) name++;
VOID strcpy(tp, name);
# endif
- dirtfmaker[n] = real;
+ dirtpmaker[newRCSdirtp_index + isworkfile] = real;
return np;
}
@@ -1368,84 +1549,127 @@ dirtempunlink()
enum maker m;
for (i = DIRTEMPNAMES; 0 <= --i; )
- if ((m = dirtfmaker[i]) != notmade) {
+ if ((m = dirtpmaker[i]) != notmade) {
if (m == effective)
seteid();
- VOID un_link(dirtfname[i].string);
+ VOID un_link(dirtpname[i].string);
if (m == effective)
setrid();
- dirtfmaker[i] = notmade;
+ dirtpmaker[i] = notmade;
}
}
int
#if has_prototypes
-chnamemod(FILE **fromp, char const *from, char const *to, mode_t mode)
+chnamemod(
+ FILE **fromp, char const *from, char const *to,
+ int set_mode, mode_t mode, time_t mtime
+)
/* The `#if has_prototypes' is needed because mode_t might promote to int. */
#else
- chnamemod(fromp,from,to,mode) FILE **fromp; char const *from,*to; mode_t mode;
+ chnamemod(fromp, from, to, set_mode, mode, mtime)
+ FILE **fromp; char const *from,*to;
+ int set_mode; mode_t mode; time_t mtime;
#endif
/*
- * Rename a file (with optional stream pointer *FROMP) from FROM to TO.
+ * Rename a file (with stream pointer *FROMP) from FROM to TO.
* FROM already exists.
- * Change its mode to MODE, before renaming if possible.
- * If FROMP, close and clear *FROMP before renaming it.
+ * If 0 < SET_MODE, change the mode to MODE, before renaming if possible.
+ * If MTIME is not -1, change its mtime to MTIME before renaming.
+ * Close and clear *FROMP before renaming it.
* Unlink TO if it already exists.
* Return -1 on error (setting errno), 0 otherwise.
*/
{
+ mode_t mode_while_renaming = mode;
+ int fchmod_set_mode = 0;
+
+# if bad_a_rename || bad_NFS_rename
+ struct stat st;
+ if (bad_NFS_rename || (bad_a_rename && set_mode <= 0)) {
+ if (fstat(fileno(*fromp), &st) != 0)
+ return -1;
+ if (bad_a_rename && set_mode <= 0)
+ mode = st.st_mode;
+ }
+# endif
+
# if bad_a_rename
/*
- * This host is brain damaged. A race condition is possible
- * while the lock file is temporarily writable.
- * There doesn't seem to be a workaround.
- */
- mode_t mode_while_renaming = mode|S_IWUSR;
-# else
-# define mode_while_renaming mode
+ * There's a short window of inconsistency
+ * during which the lock file is writable.
+ */
+ mode_while_renaming = mode|S_IWUSR;
+ if (mode != mode_while_renaming)
+ set_mode = 1;
# endif
- if (fromp) {
-# if has_fchmod
- if (fchmod(fileno(*fromp), mode_while_renaming) != 0)
- return -1;
-# endif
- Ozclose(fromp);
- }
+
# if has_fchmod
- else
+ if (0<set_mode && fchmod(fileno(*fromp),mode_while_renaming) == 0)
+ fchmod_set_mode = set_mode;
# endif
- if (chmod(from, mode_while_renaming) != 0)
+ /* If bad_chmod_close, we must close before chmod. */
+ Ozclose(fromp);
+ if (fchmod_set_mode<set_mode && chmod(from, mode_while_renaming) != 0)
+ return -1;
+
+ if (setmtime(from, mtime) != 0)
return -1;
# if !has_rename || bad_b_rename
- VOID un_link(to);
/*
- * We need not check the result;
- * link() or rename() will catch it.
- * No harm is done if TO does not exist.
- * However, there's a short window of inconsistency
- * during which TO does not exist.
- */
+ * There's a short window of inconsistency
+ * during which TO does not exist.
+ */
+ if (un_link(to) != 0 && errno != ENOENT)
+ return -1;
# endif
- return
-# if !has_rename
- do_link(from,to) != 0 ? -1 : un_link(from)
-# else
- rename(from, to) != 0
-# if has_NFS
- && errno != ENOENT
-# endif
- ? -1
-# if bad_a_rename
- : mode != mode_while_renaming ? chmod(to, mode)
-# endif
- : 0
-# endif
- ;
+# if has_rename
+ if (rename(from,to) != 0 && !(has_NFS && errno==ENOENT))
+ return -1;
+# else
+ if (do_link(from,to) != 0 || un_link(from) != 0)
+ return -1;
+# endif
-# undef mode_while_renaming
+# if bad_NFS_rename
+ {
+ /*
+ * Check whether the rename falsely reported success.
+ * A race condition can occur between the rename and the stat.
+ */
+ struct stat tostat;
+ if (stat(to, &tostat) != 0)
+ return -1;
+ if (! same_file(st, tostat, 0)) {
+ errno = EIO;
+ return -1;
+ }
+ }
+# endif
+
+# if bad_a_rename
+ if (0 < set_mode && chmod(to, mode) != 0)
+ return -1;
+# endif
+
+ return 0;
+}
+
+ int
+setmtime(file, mtime)
+ char const *file;
+ time_t mtime;
+/* Set FILE's last modified time to MTIME, but do nothing if MTIME is -1. */
+{
+ static struct utimbuf amtime; /* static so unused fields are zero */
+ if (mtime == -1)
+ return 0;
+ amtime.actime = now();
+ amtime.modtime = mtime;
+ return utime(file, &amtime);
}
@@ -1461,13 +1685,13 @@ findlock(delete, target)
* Return 0 for no locks, 1 for one, 2 for two or more.
*/
{
- register struct lock *next, **trail, **found;
+ register struct rcslock *next, **trail, **found;
found = 0;
for (trail = &Locks; (next = *trail); trail = &next->nextlock)
if (strcmp(getcaller(), next->login) == 0) {
if (found) {
- error("multiple revisions locked by %s; please specify one", getcaller());
+ rcserror("multiple revisions locked by %s; please specify one", getcaller());
return 2;
}
found = trail;
@@ -1477,36 +1701,37 @@ findlock(delete, target)
next = *found;
*target = next->delta;
if (delete) {
- next->delta->lockedby = nil;
+ next->delta->lockedby = 0;
*found = next->nextlock;
}
return 1;
}
int
-addlock(delta)
+addlock(delta, verbose)
struct hshentry * delta;
+ int verbose;
/*
* Add a lock held by caller to DELTA and yield 1 if successful.
- * Print an error message and yield -1 if no lock is added because
+ * Print an error message if verbose and yield -1 if no lock is added because
* DELTA is locked by somebody other than caller.
* Return 0 if the caller already holds the lock.
*/
{
- register struct lock *next;
+ register struct rcslock *next;
- next=Locks;
for (next = Locks; next; next = next->nextlock)
if (cmpnum(delta->num, next->delta->num) == 0)
if (strcmp(getcaller(), next->login) == 0)
return 0;
else {
- error("revision %s already locked by %s",
- delta->num, next->login
- );
+ if (verbose)
+ rcserror("Revision %s is already locked by %s.",
+ delta->num, next->login
+ );
return -1;
}
- next = ftalloc(struct lock);
+ next = ftalloc(struct rcslock);
delta->lockedby = next->login = getcaller();
next->delta = delta;
next->nextlock = Locks;
@@ -1523,28 +1748,30 @@ addsymbol(num, name, rebind)
* Associate with revision NUM the new symbolic NAME.
* If NAME already exists and REBIND is set, associate NAME with NUM;
* otherwise, print an error message and return false;
- * Return true if successful.
+ * Return -1 if unsuccessful, 0 if no change, 1 if change.
*/
{
register struct assoc *next;
for (next = Symbols; next; next = next->nextassoc)
if (strcmp(name, next->symbol) == 0)
- if (rebind || strcmp(next->num,num) == 0) {
+ if (strcmp(next->num,num) == 0)
+ return 0;
+ else if (rebind) {
next->num = num;
- return true;
+ return 1;
} else {
- error("symbolic name %s already bound to %s",
+ rcserror("symbolic name %s already bound to %s",
name, next->num
);
- return false;
+ return -1;
}
next = ftalloc(struct assoc);
next->symbol = name;
next->num = num;
next->nextassoc = Symbols;
Symbols = next;
- return true;
+ return 1;
}
@@ -1580,7 +1807,7 @@ checkaccesslist()
return true;
} while ((next = next->nextaccess));
- error("user %s not on the access list", getcaller());
+ rcserror("user %s not on the access list", getcaller());
return false;
}
@@ -1593,45 +1820,65 @@ dorewrite(lockflag, changed)
* Prepare to rewrite an RCS file if CHANGED is positive.
* Stop rewriting if CHANGED is zero, because there won't be any changes.
* Fail if CHANGED is negative.
- * Return true on success.
+ * Return 0 on success, -1 on failure.
*/
{
- int r, e;
+ int r = 0, e;
if (lockflag)
if (changed) {
if (changed < 0)
- return false;
- putadmin(frewrite);
+ return -1;
+ putadmin();
puttree(Head, frewrite);
aprintf(frewrite, "\n\n%s%c", Kdesc, nextc);
foutptr = frewrite;
} else {
- Ozclose(&frewrite);
+# if bad_creat0
+ int nr = !!frewrite, ne = 0;
+# endif
+ ORCSclose();
seteid();
ignoreints();
- r = un_link(newRCSfilename);
+# if bad_creat0
+ if (nr) {
+ nr = un_link(newRCSname);
+ ne = errno;
+ keepdirtemp(newRCSname);
+ }
+# endif
+ r = un_link(lockname);
e = errno;
- keepdirtemp(newRCSfilename);
+ keepdirtemp(lockname);
restoreints();
setrid();
- if (r != 0) {
- enerror(e, RCSfilename);
- return false;
- }
+ if (r != 0)
+ enerror(e, lockname);
+# if bad_creat0
+ if (nr != 0) {
+ enerror(ne, newRCSname);
+ r = -1;
+ }
+# endif
}
- return true;
+ return r;
}
int
-donerewrite(changed)
+donerewrite(changed, newRCStime)
int changed;
+ time_t newRCStime;
/*
* Finish rewriting an RCS file if CHANGED is nonzero.
- * Return true on success.
+ * Set its mode if CHANGED is positive.
+ * Set its modification time to NEWRCSTIME unless it is -1.
+ * Return 0 on success, -1 on failure.
*/
{
- int r, e;
+ int r = 0, e = 0;
+# if bad_creat0
+ int lr, le;
+# endif
if (changed && !nerror) {
if (finptr) {
@@ -1639,30 +1886,64 @@ donerewrite(changed)
Izclose(&finptr);
}
if (1 < RCSstat.st_nlink)
- warn("breaking hard link to %s", RCSfilename);
+ rcswarn("breaking hard link");
+ aflush(frewrite);
seteid();
ignoreints();
- r = chnamemod(&frewrite, newRCSfilename, RCSfilename,
- RCSstat.st_mode & ~(S_IWUSR|S_IWGRP|S_IWOTH)
+ r = chnamemod(
+ &frewrite, newRCSname, RCSname, changed,
+ RCSstat.st_mode & (mode_t)~(S_IWUSR|S_IWGRP|S_IWOTH),
+ newRCStime
);
e = errno;
- keepdirtemp(newRCSfilename);
+ keepdirtemp(newRCSname);
+# if bad_creat0
+ lr = un_link(lockname);
+ le = errno;
+ keepdirtemp(lockname);
+# endif
restoreints();
setrid();
if (r != 0) {
- enerror(e, RCSfilename);
- error("saved in %s", newRCSfilename);
- dirtempunlink();
- return false;
+ enerror(e, RCSname);
+ error("saved in %s", newRCSname);
}
+# if bad_creat0
+ if (lr != 0) {
+ enerror(le, lockname);
+ r = -1;
+ }
+# endif
}
- return true;
+ return r;
}
void
-aflush(f)
- FILE *f;
+ORCSclose()
+{
+ if (0 <= fdlock) {
+ if (close(fdlock) != 0)
+ efaterror(lockname);
+ fdlock = -1;
+ }
+ Ozclose(&frewrite);
+}
+
+ void
+ORCSerror()
+/*
+* Like ORCSclose, except we are cleaning up after an interrupt or fatal error.
+* Do not report errors, since this may loop. This is needed only because
+* some brain-damaged hosts (e.g. OS/2) cannot unlink files that are open, and
+* some nearly-Posix hosts (e.g. NFS) work better if the files are closed first.
+* This isn't a completely reliable away to work around brain-damaged hosts,
+* because of the gap between actual file opening and setting frewrite etc.,
+* but it's better than nothing.
+*/
{
- if (fflush(f) != 0)
- Oerror();
+ if (0 <= fdlock)
+ VOID close(fdlock);
+ if (frewrite)
+ /* Avoid fclose, since stdio may not be reentrant. */
+ VOID close(fileno(frewrite));
}
diff --git a/gnu/usr.bin/rcs/lib/rcsfcmp.c b/gnu/usr.bin/rcs/lib/rcsfcmp.c
index d8bb555..8b4b42b 100644
--- a/gnu/usr.bin/rcs/lib/rcsfcmp.c
+++ b/gnu/usr.bin/rcs/lib/rcsfcmp.c
@@ -1,14 +1,13 @@
-/*
- * RCS file comparison
- */
+/* Compare working files, ignoring RCS keyword strings. */
+
/*****************************************************************************
* rcsfcmp()
* Testprogram: define FCMPTEST
*****************************************************************************
*/
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -24,8 +23,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -37,9 +37,24 @@ Report problems and direct all questions to:
-/* $Log: rcsfcmp.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
- * Updated GNU utilities
+/*
+ * $Log: rcsfcmp.c,v $
+ * Revision 5.14 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.13 1995/06/01 16:23:43 eggert
+ * (rcsfcmp): Add -kb support.
+ *
+ * Revision 5.12 1994/03/17 14:05:48 eggert
+ * Normally calculate the $Log prefix from context, not from RCS file.
+ * Calculate line numbers correctly even if the $Log prefix contains newlines.
+ * Remove lint.
+ *
+ * Revision 5.11 1993/11/03 17:42:27 eggert
+ * Fix yet another off-by-one error when comparing Log string expansions.
+ *
+ * Revision 5.10 1992/07/28 16:12:44 eggert
+ * Statement macro names now end in _.
*
* Revision 5.9 1991/10/07 17:32:46 eggert
* Count log lines correctly.
@@ -104,8 +119,9 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(fcmpId, "$Id: rcsfcmp.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp $")
+libId(fcmpId, "$Id: rcsfcmp.c,v 5.14 1995/06/16 06:19:24 eggert Exp $")
+ static int discardkeyval P((int,RILE*));
static int
discardkeyval(c, f)
register int c;
@@ -117,24 +133,24 @@ discardkeyval(c, f)
case '\n':
return c;
default:
- Igeteof(f, c, return EOF;);
+ Igeteof_(f, c, return EOF;)
break;
}
}
int
-rcsfcmp(xfp, xstatp, ufname, delta)
+rcsfcmp(xfp, xstatp, uname, delta)
register RILE *xfp;
struct stat const *xstatp;
- char const *ufname;
+ char const *uname;
struct hshentry const *delta;
-/* Compare the files xfp and ufname. Return zero
- * if xfp has the same contents as ufname and neither has keywords,
+/* Compare the files xfp and uname. Return zero
+ * if xfp has the same contents as uname and neither has keywords,
* otherwise -1 if they are the same ignoring keyword values,
* and 1 if they differ even ignoring
* keyword values. For the LOG-keyword, rcsfcmp skips the log message
* given by the parameter delta in xfp. Thus, rcsfcmp returns nonpositive
- * if xfp contains the same as ufname, with the keywords expanded.
+ * if xfp contains the same as uname, with the keywords expanded.
* Implementation: character-by-character comparison until $ is found.
* If a $ is found, read in the marker keywords; if they are real keywords
* and identical, read in keyword value. If value is terminated properly,
@@ -148,23 +164,24 @@ rcsfcmp(xfp, xstatp, ufname, delta)
register int xeof, ueof;
register char * tp;
register char const *sp;
+ register size_t leaderlen;
int result;
enum markers match1;
struct stat ustat;
- if (!(ufp = Iopen(ufname, FOPEN_R_WORK, &ustat))) {
- efaterror(ufname);
+ if (!(ufp = Iopen(uname, FOPEN_R_WORK, &ustat))) {
+ efaterror(uname);
}
xeof = ueof = false;
- if (Expand==OLD_EXPAND) {
+ if (MIN_UNEXPAND <= Expand) {
if (!(result = xstatp->st_size!=ustat.st_size)) {
-# if has_mmap && large_memory
+# if large_memory && maps_memory
result = !!memcmp(xfp->base,ufp->base,(size_t)xstatp->st_size);
# else
for (;;) {
/* get the next characters */
- Igeteof(xfp, xc, xeof=true;);
- Igeteof(ufp, uc, ueof=true;);
+ Igeteof_(xfp, xc, xeof=true;)
+ Igeteof_(ufp, uc, ueof=true;)
if (xeof | ueof)
goto eof;
if (xc != uc)
@@ -175,21 +192,22 @@ rcsfcmp(xfp, xstatp, ufname, delta)
} else {
xc = 0;
uc = 0; /* Keep lint happy. */
+ leaderlen = 0;
result = 0;
for (;;) {
if (xc != KDELIM) {
/* get the next characters */
- Igeteof(xfp, xc, xeof=true;);
- Igeteof(ufp, uc, ueof=true;);
+ Igeteof_(xfp, xc, xeof=true;)
+ Igeteof_(ufp, uc, ueof=true;)
if (xeof | ueof)
goto eof;
} else {
/* try to get both keywords */
tp = xkeyword;
for (;;) {
- Igeteof(xfp, xc, xeof=true;);
- Igeteof(ufp, uc, ueof=true;);
+ Igeteof_(xfp, xc, xeof=true;)
+ Igeteof_(ufp, uc, ueof=true;)
if (xeof | ueof)
goto eof;
if (xc != uc)
@@ -224,8 +242,8 @@ rcsfcmp(xfp, xstatp, ufname, delta)
}
switch (xc) {
default:
- Igeteof(xfp, xc, xeof=true;);
- Igeteof(ufp, uc, ueof=true;);
+ Igeteof_(xfp, xc, xeof=true;)
+ Igeteof_(ufp, uc, ueof=true;)
if (xeof | ueof)
goto eof;
continue;
@@ -240,38 +258,47 @@ rcsfcmp(xfp, xstatp, ufname, delta)
goto return1;
if (xc==KDELIM) {
/* Skip closing KDELIM. */
- Igeteof(xfp, xc, xeof=true;);
- Igeteof(ufp, uc, ueof=true;);
+ Igeteof_(xfp, xc, xeof=true;)
+ Igeteof_(ufp, uc, ueof=true;)
if (xeof | ueof)
goto eof;
/* if the keyword is LOG, also skip the log message in xfp*/
if (match1==Log) {
/* first, compute the number of line feeds in log msg */
- unsigned lncnt;
+ int lncnt;
size_t ls, ccnt;
sp = delta->log.string;
ls = delta->log.size;
if (ls<sizeof(ciklog)-1 || memcmp(sp,ciklog,sizeof(ciklog)-1)) {
- /* This log message was inserted. */
- lncnt = 3;
- while (ls--) if (*sp++=='\n') lncnt++;
+ /*
+ * This log message was inserted. Skip its header.
+ * The number of newlines to skip is
+ * 1 + (C+1)*(1+L+1), where C is the number of newlines
+ * in the comment leader, and L is the number of
+ * newlines in the log string.
+ */
+ int c1 = 1;
+ for (ccnt=Comment.size; ccnt--; )
+ c1 += Comment.string[ccnt] == '\n';
+ lncnt = 2*c1 + 1;
+ while (ls--) if (*sp++=='\n') lncnt += c1;
for (;;) {
if (xc=='\n')
if(--lncnt==0) break;
- Igeteof(xfp, xc, goto returnresult;);
+ Igeteof_(xfp, xc, goto returnresult;)
}
/* skip last comment leader */
/* Can't just skip another line here, because there may be */
/* additional characters on the line (after the Log....$) */
- for (ccnt=Comment.size; ccnt--; ) {
- Igeteof(xfp, xc, goto returnresult;);
- if(xc=='\n') break;
+ ccnt = RCSversion<VERSION(5) ? Comment.size : leaderlen;
+ do {
+ Igeteof_(xfp, xc, goto returnresult;)
/*
* Read to the end of the comment leader or '\n',
- * whatever comes first. Some editors strip
- * trailing white space from a leader like " * ".
+ * whatever comes first, because the leader's
+ * trailing white space was probably stripped.
*/
- }
+ } while (ccnt-- && (xc!='\n' || --c1));
}
}
} else {
@@ -287,6 +314,10 @@ rcsfcmp(xfp, xstatp, ufname, delta)
}
if (xc != uc)
goto return1;
+ if (xc == '\n')
+ leaderlen = 0;
+ else
+ leaderlen++;
}
}
diff --git a/gnu/usr.bin/rcs/lib/rcsfnms.c b/gnu/usr.bin/rcs/lib/rcsfnms.c
index 93c96b9..5846b66 100644
--- a/gnu/usr.bin/rcs/lib/rcsfnms.c
+++ b/gnu/usr.bin/rcs/lib/rcsfnms.c
@@ -1,15 +1,14 @@
-/*
- * RCS file name handling
- */
+/* RCS filename and pathname handling */
+
/****************************************************************************
* creation and deletion of /tmp temporaries
- * pairing of RCS file names and working file names.
+ * pairing of RCS pathnames and working pathnames.
* Testprogram: define PAIRTEST
****************************************************************************
*/
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -25,8 +24,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -37,9 +37,44 @@ Report problems and direct all questions to:
-/* $Log: rcsfnms.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
- * Updated GNU utilities
+/*
+ * $Log: rcsfnms.c,v $
+ * Revision 5.16 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.15 1995/06/01 16:23:43 eggert
+ * (basefilename): Renamed from basename to avoid collisions.
+ * (dirlen): Remove (for similar reasons).
+ * (rcsreadopen): Open with FOPEN_RB.
+ * (SLASHSLASH_is_SLASH): Default is 0.
+ * (getcwd): Work around bad_wait_if_SIGCHLD_ignored bug.
+ *
+ * Revision 5.14 1994/03/17 14:05:48 eggert
+ * Strip trailing SLASHes from TMPDIR; some systems need this. Remove lint.
+ *
+ * Revision 5.13 1993/11/03 17:42:27 eggert
+ * Determine whether a file name is too long indirectly,
+ * by examining inode numbers, instead of trying to use operating system
+ * primitives like pathconf, which are not trustworthy in general.
+ * File names may now hold white space or $.
+ * Do not flatten ../X in pathnames; that may yield wrong answer for symlinks.
+ * Add getabsname hook. Improve quality of diagnostics.
+ *
+ * Revision 5.12 1992/07/28 16:12:44 eggert
+ * Add .sty. .pl now implies Perl, not Prolog. Fix fdlock initialization bug.
+ * Check that $PWD is really ".". Be consistent about pathnames vs filenames.
+ *
+ * Revision 5.11 1992/02/17 23:02:25 eggert
+ * `a/RCS/b/c' is now an RCS file with an empty extension, not just `a/b/RCS/c'.
+ *
+ * Revision 5.10 1992/01/24 18:44:19 eggert
+ * Fix bug: Expand and Ignored weren't reinitialized.
+ * Avoid `char const c=ch;' compiler bug.
+ * Add support for bad_creat0.
+ *
+ * Revision 5.9 1992/01/06 02:42:34 eggert
+ * Shorten long (>31 chars) name.
+ * while (E) ; -> while (E) continue;
*
* Revision 5.8 1991/09/24 00:28:40 eggert
* Don't export bindex().
@@ -69,8 +104,8 @@ Report problems and direct all questions to:
*
* Revision 5.0 1990/08/22 08:12:50 eggert
* Ignore signals when manipulating the semaphore file.
- * Modernize list of file name extensions.
- * Permit paths of arbitrary length. Beware file names beginning with "-".
+ * Modernize list of filename extensions.
+ * Permit paths of arbitrary length. Beware filenames beginning with "-".
* Remove compile-time limits; use malloc instead.
* Permit dates past 1999/12/31. Make lock and temp files faster and safer.
* Ansify and Posixate.
@@ -97,10 +132,10 @@ Report problems and direct all questions to:
* Comment leader '% ' for '*.tex' files added.
*
* Revision 4.3 83/12/15 12:26:48 wft
- * Added check for KDELIM in file names to pairfilenames().
+ * Added check for KDELIM in filenames to pairfilenames().
*
* Revision 4.2 83/12/02 22:47:45 wft
- * Added csh, red, and sl file name suffixes.
+ * Added csh, red, and sl filename suffixes.
*
* Revision 4.1 83/05/11 16:23:39 wft
* Added initialization of Dbranch to InitAdmin(). Canged pairfilenames():
@@ -109,7 +144,7 @@ Report problems and direct all questions to:
* 3. added ignoring of directories.
*
* Revision 3.7 83/05/11 15:01:58 wft
- * Added comtable[] which pairs file name suffixes with comment leaders;
+ * Added comtable[] which pairs filename suffixes with comment leaders;
* updated InitAdmin() accordingly.
*
* Revision 3.6 83/04/05 14:47:36 wft
@@ -124,7 +159,7 @@ Report problems and direct all questions to:
* removed unused variable.
*
* Revision 3.3 82/11/28 20:31:37 wft
- * Changed mktempfile() to store the generated file names.
+ * Changed mktempfile() to store the generated filenames.
* Changed getfullRCSname() to store the file and pathname, and to
* delete leading "../" and "./".
*
@@ -143,72 +178,87 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(fnmsId, "$Id: rcsfnms.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp $")
+libId(fnmsId, "$Id: rcsfnms.c,v 5.16 1995/06/16 06:19:24 eggert Exp $")
+
+static char const *bindex P((char const*,int));
+static int fin2open P((char const*, size_t, char const*, size_t, char const*, size_t, RILE*(*)P((struct buf*,struct stat*,int)), int));
+static int finopen P((RILE*(*)P((struct buf*,struct stat*,int)), int));
+static int suffix_matches P((char const*,char const*));
+static size_t dir_useful_len P((char const*));
+static size_t suffixlen P((char const*));
+static void InitAdmin P((void));
-char const *RCSfilename;
-char *workfilename;
+char const *RCSname;
+char *workname;
+int fdlock;
FILE *workstdout;
struct stat RCSstat;
char const *suffixes;
static char const rcsdir[] = "RCS";
-#define rcsdirlen (sizeof(rcsdir)-1)
+#define rcslen (sizeof(rcsdir)-1)
static struct buf RCSbuf, RCSb;
static int RCSerrno;
-/* Temp file names to be unlinked when done, if they are not nil. */
+/* Temp names to be unlinked when done, if they are not 0. */
#define TEMPNAMES 5 /* must be at least DIRTEMPNAMES (see rcsedit.c) */
-static char *volatile tfnames[TEMPNAMES];
+static char *volatile tpnames[TEMPNAMES];
struct compair {
char const *suffix, *comlead;
};
+/*
+* This table is present only for backwards compatibility.
+* Normally we ignore this table, and use the prefix of the `$Log' line instead.
+*/
static struct compair const comtable[] = {
-/* comtable pairs each filename suffix with a comment leader. The comment */
-/* leader is placed before each line generated by the $Log keyword. This */
-/* table is used to guess the proper comment leader from the working file's */
-/* suffix during initial ci (see InitAdmin()). Comment leaders are needed */
-/* for languages without multiline comments; for others they are optional. */
- "a", "-- ", /* Ada */
- "ada", "-- ",
- "asm", ";; ", /* assembler (MS-DOS) */
- "bat", ":: ", /* batch (MS-DOS) */
- "c", " * ", /* C */
- "c++", "// ", /* C++ in all its infinite guises */
- "cc", "// ",
- "cpp", "// ",
- "cxx", "// ",
- "cl", ";;; ", /* Common Lisp */
- "cmd", ":: ", /* command (OS/2) */
- "cmf", "c ", /* CM Fortran */
- "cs", " * ", /* C* */
- "el", "; ", /* Emacs Lisp */
- "f", "c ", /* Fortran */
- "for", "c ",
- "h", " * ", /* C-header */
- "hpp", "// ", /* C++ header */
- "hxx", "// ",
- "l", " * ", /* lex NOTE: conflict between lex and franzlisp */
- "lisp",";;; ", /* Lucid Lisp */
- "lsp", ";; ", /* Microsoft Lisp */
- "mac", ";; ", /* macro (DEC-10, MS-DOS, PDP-11, VMS, etc) */
- "me", ".\\\" ",/* me-macros t/nroff*/
- "ml", "; ", /* mocklisp */
- "mm", ".\\\" ",/* mm-macros t/nroff*/
- "ms", ".\\\" ",/* ms-macros t/nroff*/
- "p", " * ", /* Pascal */
- "pas", " * ",
- "pl", "% ", /* Prolog */
- "tex", "% ", /* TeX */
- "y", " * ", /* yacc */
- nil, "# " /* default for unknown suffix; must always be last */
+ { "a" , "-- " }, /* Ada */
+ { "ada" , "-- " },
+ { "adb" , "-- " },
+ { "ads" , "-- " },
+ { "asm" , ";; " }, /* assembler (MS-DOS) */
+ { "bat" , ":: " }, /* batch (MS-DOS) */
+ { "body", "-- " }, /* Ada */
+ { "c" , " * " }, /* C */
+ { "c++" , "// " }, /* C++ in all its infinite guises */
+ { "cc" , "// " },
+ { "cpp" , "// " },
+ { "cxx" , "// " },
+ { "cl" , ";;; "}, /* Common Lisp */
+ { "cmd" , ":: " }, /* command (OS/2) */
+ { "cmf" , "c " }, /* CM Fortran */
+ { "cs" , " * " }, /* C* */
+ { "el" , "; " }, /* Emacs Lisp */
+ { "f" , "c " }, /* Fortran */
+ { "for" , "c " },
+ { "h" , " * " }, /* C-header */
+ { "hpp" , "// " }, /* C++ header */
+ { "hxx" , "// " },
+ { "l" , " * " }, /* lex (NOTE: franzlisp disagrees) */
+ { "lisp", ";;; "}, /* Lucid Lisp */
+ { "lsp" , ";; " }, /* Microsoft Lisp */
+ { "m" , "// " }, /* Objective C */
+ { "mac" , ";; " }, /* macro (DEC-10, MS-DOS, PDP-11, VMS, etc) */
+ { "me" , ".\\\" "}, /* troff -me */
+ { "ml" , "; " }, /* mocklisp */
+ { "mm" , ".\\\" "}, /* troff -mm */
+ { "ms" , ".\\\" "}, /* troff -ms */
+ { "p" , " * " }, /* Pascal */
+ { "pas" , " * " },
+ { "ps" , "% " }, /* PostScript */
+ { "spec", "-- " }, /* Ada */
+ { "sty" , "% " }, /* LaTeX style */
+ { "tex" , "% " }, /* TeX */
+ { "y" , " * " }, /* yacc */
+ { 0 , "# " } /* default for unknown suffix; must be last */
};
#if has_mktemp
+ static char const *tmp P((void));
static char const *
tmp()
/* Yield the name of the tmp directory. */
@@ -227,14 +277,14 @@ tmp()
char const *
maketemp(n)
int n;
-/* Create a unique filename using n and the process id and store it
- * into the nth slot in tfnames.
- * Because of storage in tfnames, tempunlink() can unlink the file later.
- * Returns a pointer to the filename created.
+/* Create a unique pathname using n and the process id and store it
+ * into the nth slot in tpnames.
+ * Because of storage in tpnames, tempunlink() can unlink the file later.
+ * Return a pointer to the pathname created.
*/
{
char *p;
- char const *t = tfnames[n];
+ char const *t = tpnames[n];
if (t)
return t;
@@ -243,25 +293,26 @@ maketemp(n)
{
# if has_mktemp
char const *tp = tmp();
- p = testalloc(strlen(tp) + 10);
- VOID sprintf(p, "%s%cT%cXXXXXX", tp, SLASH, '0'+n);
+ size_t tplen = dir_useful_len(tp);
+ p = testalloc(tplen + 10);
+ VOID sprintf(p, "%.*s%cT%cXXXXXX", (int)tplen, tp, SLASH, '0'+n);
if (!mktemp(p) || !*p)
- faterror("can't make temporary file name `%s%cT%cXXXXXX'",
- tp, SLASH, '0'+n
+ faterror("can't make temporary pathname `%.*s%cT%cXXXXXX'",
+ (int)tplen, tp, SLASH, '0'+n
);
# else
- static char tfnamebuf[TEMPNAMES][L_tmpnam];
- p = tfnamebuf[n];
+ static char tpnamebuf[TEMPNAMES][L_tmpnam];
+ p = tpnamebuf[n];
if (!tmpnam(p) || !*p)
# ifdef P_tmpdir
- faterror("can't make temporary file name `%s...'",P_tmpdir);
+ faterror("can't make temporary pathname `%s...'",P_tmpdir);
# else
- faterror("can't make temporary file name");
+ faterror("can't make temporary pathname");
# endif
# endif
}
- tfnames[n] = p;
+ tpnames[n] = p;
return p;
}
@@ -274,28 +325,28 @@ tempunlink()
register char *p;
for (i = TEMPNAMES; 0 <= --i; )
- if ((p = tfnames[i])) {
+ if ((p = tpnames[i])) {
VOID unlink(p);
/*
* We would tfree(p) here,
* but this might dump core if we're handing a signal.
* We're about to exit anyway, so we won't bother.
*/
- tfnames[i] = 0;
+ tpnames[i] = 0;
}
}
static char const *
-bindex(sp,ch)
+bindex(sp, c)
register char const *sp;
- int ch;
+ register int c;
/* Function: Finds the last occurrence of character c in string sp
* and returns a pointer to the character just beyond it. If the
* character doesn't occur in the string, sp is returned.
*/
{
- register char const c=ch, *r;
+ register char const *r;
r = sp;
while (*sp) {
if (*sp++ == c) r=sp;
@@ -336,64 +387,22 @@ InitAdmin()
register char const *Suffix;
register int i;
- Head=nil; Dbranch=nil; AccessList=nil; Symbols=nil; Locks=nil;
+ Head=0; Dbranch=0; AccessList=0; Symbols=0; Locks=0;
StrictLocks=STRICT_LOCKING;
/* guess the comment leader from the suffix*/
- Suffix=bindex(workfilename, '.');
- if (Suffix==workfilename) Suffix= ""; /* empty suffix; will get default*/
+ Suffix = bindex(workname, '.');
+ if (Suffix==workname) Suffix= ""; /* empty suffix; will get default*/
for (i=0; !suffix_matches(Suffix,comtable[i].suffix); i++)
- ;
+ continue;
Comment.string = comtable[i].comlead;
Comment.size = strlen(comtable[i].comlead);
+ Expand = KEYVAL_EXPAND;
+ clear_buf(&Ignored);
Lexinit(); /* note: if !finptr, reads nothing; only initializes */
}
-/* 'cpp' does not like this line. It seems to be the leading '_' in the */
-/* second occurence of '_POSIX_NO_TRUNC'. It evaluates correctly with */
-/* just the first term so lets just do that for now. */
-/*#if defined(_POSIX_NO_TRUNC) && _POSIX_NO_TRUNC!=-1*/
-#if defined(_POSIX_NO_TRUNC)
-# define LONG_NAMES_MAY_BE_SILENTLY_TRUNCATED 0
-#else
-# define LONG_NAMES_MAY_BE_SILENTLY_TRUNCATED 1
-#endif
-
-#if LONG_NAMES_MAY_BE_SILENTLY_TRUNCATED
-#ifdef NAME_MAX
-# define filenametoolong(path) (NAME_MAX < strlen(basename(path)))
-#else
- static int
-filenametoolong(path)
- char *path;
-/* Yield true if the last file name in PATH is too long. */
-{
- static unsigned long dot_namemax;
-
- register size_t namelen;
- register char *base;
- register unsigned long namemax;
-
- base = path + dirlen(path);
- namelen = strlen(base);
- if (namelen <= _POSIX_NAME_MAX) /* fast check for shorties */
- return false;
- if (base != path) {
- *--base = 0;
- namemax = pathconf(path, _PC_NAME_MAX);
- *base = SLASH;
- } else {
- /* Cache the results for the working directory, for speed. */
- if (!dot_namemax)
- dot_namemax = pathconf(".", _PC_NAME_MAX);
- namemax = dot_namemax;
- }
- /* If pathconf() yielded -1, namemax is now ULONG_MAX. */
- return namemax<namelen;
-}
-#endif
-#endif
void
bufalloc(b, size)
@@ -425,7 +434,7 @@ bufrealloc(b, size)
bufalloc(b, size);
else {
while ((b->size <<= 1) < size)
- ;
+ continue;
b->string = trealloc(char, b->string, b->size);
}
}
@@ -498,7 +507,7 @@ bufscpy(b, s)
char const *
-basename(p)
+basefilename(p)
char const *p;
/* Yield the address of the base filename of the pathname P. */
{
@@ -510,19 +519,11 @@ basename(p)
}
}
- size_t
-dirlen(p)
- char const *p;
-/* Yield the length of P's directory, including its trailing SLASH. */
-{
- return basename(p) - p;
-}
-
static size_t
suffixlen(x)
char const *x;
-/* Yield the length of X, an RCS filename suffix. */
+/* Yield the length of X, an RCS pathname suffix. */
{
register char const *p;
@@ -541,10 +542,10 @@ suffixlen(x)
char const *
rcssuffix(name)
char const *name;
-/* Yield the suffix of NAME if it is an RCS filename, 0 otherwise. */
+/* Yield the suffix of NAME if it is an RCS pathname, 0 otherwise. */
{
char const *x, *p, *nz;
- size_t dl, nl, xl;
+ size_t nl, xl;
nl = strlen(name);
nz = name + nl;
@@ -553,30 +554,29 @@ rcssuffix(name)
if ((xl = suffixlen(x))) {
if (xl <= nl && memcmp(p = nz-xl, x, xl) == 0)
return p;
- } else {
- dl = dirlen(name);
- if (
- rcsdirlen < dl &&
- !memcmp(p = name+(dl-=rcsdirlen+1), rcsdir, rcsdirlen) &&
- (!dl || isSLASH(*--p))
- )
- return nz;
- }
+ } else
+ for (p = name; p < nz - rcslen; p++)
+ if (
+ isSLASH(p[rcslen])
+ && (p==name || isSLASH(p[-1]))
+ && memcmp(p, rcsdir, rcslen) == 0
+ )
+ return nz;
x += xl;
} while (*x++);
return 0;
}
/*ARGSUSED*/ RILE *
-rcsreadopen(RCSname, status, mustread)
- struct buf *RCSname;
+rcsreadopen(RCSpath, status, mustread)
+ struct buf *RCSpath;
struct stat *status;
int mustread;
-/* Open RCSNAME for reading and yield its FILE* descriptor.
+/* Open RCSPATH for reading and yield its FILE* descriptor.
* If successful, set *STATUS to its status.
- * Pass this routine to pairfilenames() for read-only access to the file. */
+ * Pass this routine to pairnames() for read-only access to the file. */
{
- return Iopen(RCSname->string, FOPEN_R, status);
+ return Iopen(RCSpath->string, FOPEN_RB, status);
}
static int
@@ -597,7 +597,7 @@ finopen(rcsopen, mustread)
* We prefer an old name to that of a nonexisting new RCS file,
* unless we tried locking the old name and failed.
*/
- preferold = RCSbuf.string[0] && (mustread||frewrite);
+ preferold = RCSbuf.string[0] && (mustread||0<=fdlock);
finptr = (*rcsopen)(&RCSb, &RCSstat, mustread);
interesting = finptr || errno!=ENOENT;
@@ -618,7 +618,7 @@ fin2open(d, dlen, base, baselen, x, xlen, rcsopen, mustread)
/*
* D is a directory name with length DLEN (including trailing slash).
* BASE is a filename with length BASELEN.
- * X is an RCS filename suffix with length XLEN.
+ * X is an RCS pathname suffix with length XLEN.
* Use RCSOPEN to open an RCS file; MUSTREAD is set if the file must be read.
* Yield true if successful.
* Try dRCS/basex first; if that fails and x is nonempty, try dbasex.
@@ -629,12 +629,12 @@ fin2open(d, dlen, base, baselen, x, xlen, rcsopen, mustread)
{
register char *p;
- bufalloc(&RCSb, dlen + rcsdirlen + 1 + baselen + xlen + 1);
+ bufalloc(&RCSb, dlen + rcslen + 1 + baselen + xlen + 1);
/* Try dRCS/basex. */
VOID memcpy(p = RCSb.string, d, dlen);
- VOID memcpy(p += dlen, rcsdir, rcsdirlen);
- p += rcsdirlen;
+ VOID memcpy(p += dlen, rcsdir, rcslen);
+ p += rcslen;
*p++ = SLASH;
VOID memcpy(p, base, baselen);
VOID memcpy(p += baselen, x, xlen);
@@ -654,16 +654,17 @@ fin2open(d, dlen, base, baselen, x, xlen, rcsopen, mustread)
}
int
-pairfilenames(argc, argv, rcsopen, mustread, quiet)
+pairnames(argc, argv, rcsopen, mustread, quiet)
int argc;
char **argv;
RILE *(*rcsopen)P((struct buf*,struct stat*,int));
int mustread, quiet;
-/* Function: Pairs the filenames pointed to by argv; argc indicates
+/*
+ * Pair the pathnames pointed to by argv; argc indicates
* how many there are.
- * Places a pointer to the RCS filename into RCSfilename,
- * and a pointer to the name of the working file into workfilename.
- * If both the workfilename and the RCS filename are given, and workstdout
+ * Place a pointer to the RCS pathname into RCSname,
+ * and a pointer to the pathname of the working file into workname.
+ * If both are given, and workstdout
* is set, a warning is printed.
*
* If the RCS file exists, places its status into RCSstat.
@@ -680,80 +681,62 @@ pairfilenames(argc, argv, rcsopen, mustread, quiet)
static struct buf tempbuf;
register char *p, *arg, *RCS1;
- char const *purefname, *pureRCSname, *x;
+ char const *base, *RCSbase, *x;
int paired;
size_t arglen, dlen, baselen, xlen;
- if (!(arg = *argv)) return 0; /* already paired filename */
+ fdlock = -1;
+
+ if (!(arg = *argv)) return 0; /* already paired pathname */
if (*arg == '-') {
- error("%s option is ignored after file names", arg);
+ error("%s option is ignored after pathnames", arg);
return 0;
}
- purefname = basename(arg);
-
- /* Allocate buffer temporary to hold the default paired file name. */
- p = arg;
- for (;;) {
- switch (*p++) {
- /* Beware characters that cause havoc with ci -k. */
- case KDELIM:
- error("RCS file name `%s' contains %c", arg, KDELIM);
- return 0;
- case ' ': case '\n': case '\t':
- error("RCS file name `%s' contains white space", arg);
- return 0;
- default:
- continue;
- case 0:
- break;
- }
- break;
- }
-
+ base = basefilename(arg);
paired = false;
/* first check suffix to see whether it is an RCS file or not */
if ((x = rcssuffix(arg)))
{
- /* RCS file name given*/
+ /* RCS pathname given */
RCS1 = arg;
- pureRCSname = purefname;
- baselen = x - purefname;
+ RCSbase = base;
+ baselen = x - base;
if (
1 < argc &&
- !rcssuffix(workfilename = p = argv[1]) &&
+ !rcssuffix(workname = p = argv[1]) &&
baselen <= (arglen = strlen(p)) &&
- ((p+=arglen-baselen) == workfilename || isSLASH(p[-1])) &&
- memcmp(purefname, p, baselen) == 0
+ ((p+=arglen-baselen) == workname || isSLASH(p[-1])) &&
+ memcmp(base, p, baselen) == 0
) {
argv[1] = 0;
paired = true;
} else {
- bufscpy(&tempbuf, purefname);
- workfilename = p = tempbuf.string;
+ bufscpy(&tempbuf, base);
+ workname = p = tempbuf.string;
p[baselen] = 0;
}
} else {
/* working file given; now try to find RCS file */
- workfilename = arg;
- baselen = p - purefname - 1;
- /* derive RCS file name*/
+ workname = arg;
+ baselen = strlen(base);
+ /* Derive RCS pathname. */
if (
1 < argc &&
(x = rcssuffix(RCS1 = argv[1])) &&
baselen <= x - RCS1 &&
- ((pureRCSname=x-baselen)==RCS1 || isSLASH(pureRCSname[-1])) &&
- memcmp(purefname, pureRCSname, baselen) == 0
+ ((RCSbase=x-baselen)==RCS1 || isSLASH(RCSbase[-1])) &&
+ memcmp(base, RCSbase, baselen) == 0
) {
argv[1] = 0;
paired = true;
} else
- pureRCSname = RCS1 = 0;
+ RCSbase = RCS1 = 0;
}
- /* now we have a (tentative) RCS filename in RCS1 and workfilename */
+ /* Now we have a (tentative) RCS pathname in RCS1 and workname. */
/* Second, try to find the right RCS file */
- if (pureRCSname!=RCS1) {
+ if (RCSbase!=RCS1) {
/* a path for RCSfile is given; single RCS file to look for */
bufscpy(&RCSbuf, RCS1);
finptr = (*rcsopen)(&RCSbuf, &RCSstat, mustread);
@@ -761,16 +744,16 @@ pairfilenames(argc, argv, rcsopen, mustread, quiet)
} else {
bufscpy(&RCSbuf, "");
if (RCS1)
- /* RCS file name was given without path. */
- VOID fin2open(arg, (size_t)0, pureRCSname, baselen,
+ /* RCS filename was given without path. */
+ VOID fin2open(arg, (size_t)0, RCSbase, baselen,
x, strlen(x), rcsopen, mustread
);
else {
- /* No RCS file name was given. */
+ /* No RCS pathname was given. */
/* Try each suffix in turn. */
- dlen = purefname-arg;
+ dlen = base-arg;
x = suffixes;
- while (! fin2open(arg, dlen, purefname, baselen,
+ while (! fin2open(arg, dlen, base, baselen,
x, xlen=suffixlen(x), rcsopen, mustread
)) {
x += xlen;
@@ -779,7 +762,7 @@ pairfilenames(argc, argv, rcsopen, mustread, quiet)
}
}
}
- RCSfilename = p = RCSbuf.string;
+ RCSname = p = RCSbuf.string;
if (finptr) {
if (!S_ISREG(RCSstat.st_mode)) {
error("%s isn't a regular file -- ignored", p);
@@ -787,7 +770,7 @@ pairfilenames(argc, argv, rcsopen, mustread, quiet)
}
Lexinit(); getadmin();
} else {
- if (RCSerrno!=ENOENT || mustread || !frewrite) {
+ if (RCSerrno!=ENOENT || mustread || fdlock<0) {
if (RCSerrno == EEXIST)
error("RCS file %s is in use", p);
else if (!quiet || RCSerrno!=ENOENT)
@@ -796,25 +779,9 @@ pairfilenames(argc, argv, rcsopen, mustread, quiet)
}
InitAdmin();
};
-# if LONG_NAMES_MAY_BE_SILENTLY_TRUNCATED
- if (filenametoolong(p)) {
- error("RCS file name %s is too long", p);
- return 0;
- }
-# ifndef NAME_MAX
- /*
- * Check workfilename too, even though it cannot be longer,
- * because it may reside on a different filesystem.
- */
- if (filenametoolong(workfilename)) {
- error("working file name %s is too long", workfilename);
- return 0;
- }
-# endif
-# endif
if (paired && workstdout)
- warn("Option -p is set; ignoring output file %s",workfilename);
+ workwarn("Working file ignored due to -p option");
prevkeys = false;
return finptr ? 1 : -1;
@@ -823,83 +790,106 @@ pairfilenames(argc, argv, rcsopen, mustread, quiet)
char const *
getfullRCSname()
-/* Function: returns a pointer to the full path name of the RCS file.
- * Gets the working directory's name at most once.
- * Removes leading "../" and "./".
+/*
+ * Return a pointer to the full pathname of the RCS file.
+ * Remove leading `./'.
*/
{
- static char const *wdptr;
- static struct buf rcsbuf, wdbuf;
- static size_t pathlength;
-
- register char const *realname;
- register size_t parentdirlength;
- register unsigned dotdotcounter;
- register char *d;
- register char const *wd;
-
- if (ROOTPATH(RCSfilename)) {
- return(RCSfilename);
- } else {
+ if (ROOTPATH(RCSname)) {
+ return RCSname;
+ } else {
+ static struct buf rcsbuf;
+# if needs_getabsname
+ bufalloc(&rcsbuf, SIZEABLE_PATH + 1);
+ while (getabsname(RCSname, rcsbuf.string, rcsbuf.size) != 0)
+ if (errno == ERANGE)
+ bufalloc(&rcsbuf, rcsbuf.size<<1);
+ else
+ efaterror("getabsname");
+# else
+ static char const *wdptr;
+ static struct buf wdbuf;
+ static size_t wdlen;
+
+ register char const *r;
+ register size_t dlen;
+ register char *d;
+ register char const *wd;
+
if (!(wd = wdptr)) {
/* Get working directory for the first time. */
- if (!(d = cgetenv("PWD"))) {
+ char *PWD = cgetenv("PWD");
+ struct stat PWDstat, dotstat;
+ if (! (
+ (d = PWD) &&
+ ROOTPATH(PWD) &&
+ stat(PWD, &PWDstat) == 0 &&
+ stat(".", &dotstat) == 0 &&
+ same_file(PWDstat, dotstat, 1)
+ )) {
bufalloc(&wdbuf, SIZEABLE_PATH + 1);
-# if !has_getcwd && has_getwd
- d = getwd(wdbuf.string);
+# if has_getcwd || !has_getwd
+ while (!(d = getcwd(wdbuf.string, wdbuf.size)))
+ if (errno == ERANGE)
+ bufalloc(&wdbuf, wdbuf.size<<1);
+ else if ((d = PWD))
+ break;
+ else
+ efaterror("getcwd");
# else
- while (
- !(d = getcwd(wdbuf.string, wdbuf.size))
- && errno==ERANGE
- )
- bufalloc(&wdbuf, wdbuf.size<<1);
+ d = getwd(wdbuf.string);
+ if (!d && !(d = PWD))
+ efaterror("getwd");
# endif
- if (!d)
- efaterror("working directory");
}
- parentdirlength = strlen(d);
- while (parentdirlength && isSLASH(d[parentdirlength-1])) {
- d[--parentdirlength] = 0;
- /* Check needed because some getwd implementations */
- /* generate "/" for the root. */
- }
+ wdlen = dir_useful_len(d);
+ d[wdlen] = 0;
wdptr = wd = d;
- pathlength = parentdirlength;
- }
- /*the following must be redone since RCSfilename may change*/
- /* Find how many `../'s to remove from RCSfilename. */
- dotdotcounter =0;
- realname = RCSfilename;
- while (realname[0]=='.') {
- if (isSLASH(realname[1])) {
- /* drop leading ./ */
- realname += 2;
- } else if (realname[1]=='.' && isSLASH(realname[2])) {
- /* drop leading ../ and remember */
- dotdotcounter++;
- realname += 3;
- } else
- break;
}
- /* Now remove dotdotcounter trailing directories from wd. */
- parentdirlength = pathlength;
- while (dotdotcounter && parentdirlength) {
- /* move pointer backwards over trailing directory */
- if (isSLASH(wd[--parentdirlength])) {
- dotdotcounter--;
- }
- }
- /* build full path name */
- bufalloc(&rcsbuf, parentdirlength+strlen(realname)+2);
+ /*
+ * Remove leading `./'s from RCSname.
+ * Do not try to handle `../', since removing it may yield
+ * the wrong answer in the presence of symbolic links.
+ */
+ for (r = RCSname; r[0]=='.' && isSLASH(r[1]); r += 2)
+ /* `.////' is equivalent to `./'. */
+ while (isSLASH(r[2]))
+ r++;
+ /* Build full pathname. */
+ dlen = wdlen;
+ bufalloc(&rcsbuf, dlen + strlen(r) + 2);
d = rcsbuf.string;
- VOID memcpy(d, wd, parentdirlength);
- d += parentdirlength;
+ VOID memcpy(d, wd, dlen);
+ d += dlen;
*d++ = SLASH;
- VOID strcpy(d, realname);
- return rcsbuf.string;
+ VOID strcpy(d, r);
+# endif
+ return rcsbuf.string;
}
}
+ static size_t
+dir_useful_len(d)
+ char const *d;
+/*
+* D names a directory; yield the number of characters of D's useful part.
+* To create a file in D, append a SLASH and a file name to D's useful part.
+* Ignore trailing slashes if possible; not only are they ugly,
+* but some non-Posix systems misbehave unless the slashes are omitted.
+*/
+{
+# ifndef SLASHSLASH_is_SLASH
+# define SLASHSLASH_is_SLASH 0
+# endif
+ size_t dlen = strlen(d);
+ if (!SLASHSLASH_is_SLASH && dlen==2 && isSLASH(d[0]) && isSLASH(d[1]))
+ --dlen;
+ else
+ while (dlen && isSLASH(d[dlen-1]))
+ --dlen;
+ return dlen;
+}
+
#ifndef isSLASH
int
isSLASH(c)
@@ -930,9 +920,6 @@ getcwd(path, size)
register char *p, *lim;
int closeerrno, closeerror, e, fd[2], readerror, toolong, wstatus;
pid_t child;
-# if !has_waitpid
- pid_t w;
-# endif
if (!size) {
errno = EINVAL;
@@ -940,6 +927,12 @@ getcwd(path, size)
}
if (pipe(fd) != 0)
return 0;
+# if bad_wait_if_SIGCHLD_ignored
+# ifndef SIGCHLD
+# define SIGCHLD SIGCLD
+# endif
+ VOID signal(SIGCHLD, SIG_DFL);
+# endif
if (!(child = vfork())) {
if (
close(fd[0]) == 0 &&
@@ -991,12 +984,15 @@ getcwd(path, size)
if (waitpid(child, &wstatus, 0) < 0)
wstatus = 1;
# else
- do {
- if ((w = wait(&wstatus)) < 0) {
- wstatus = 1;
- break;
- }
- } while (w != child);
+ {
+ pid_t w;
+ do {
+ if ((w = wait(&wstatus)) < 0) {
+ wstatus = 1;
+ break;
+ }
+ } while (w != child);
+ }
# endif
}
if (!fp) {
@@ -1029,7 +1025,7 @@ getcwd(path, size)
#ifdef PAIRTEST
-/* test program for pairfilenames() and getfullRCSname() */
+/* test program for pairnames() and getfullRCSname() */
char const cmdid[] = "pair";
@@ -1055,20 +1051,20 @@ int argc; char *argv[];
}
do {
- RCSfilename=workfilename=nil;
- result = pairfilenames(argc,argv,rcsreadopen,!initflag,quietflag);
+ RCSname = workname = 0;
+ result = pairnames(argc,argv,rcsreadopen,!initflag,quietflag);
if (result!=0) {
- diagnose("RCS file: %s; working file: %s\nFull RCS file name: %s\n",
- RCSfilename,workfilename,getfullRCSname()
+ diagnose("RCS pathname: %s; working pathname: %s\nFull RCS pathname: %s\n",
+ RCSname, workname, getfullRCSname()
);
}
switch (result) {
case 0: continue; /* already paired file */
case 1: if (initflag) {
- error("RCS file %s exists already",RCSfilename);
+ rcserror("already exists");
} else {
- diagnose("RCS file %s exists\n",RCSfilename);
+ diagnose("RCS file %s exists\n", RCSname);
}
Ifclose(finptr);
break;
@@ -1081,7 +1077,7 @@ int argc; char *argv[];
}
- exiting void
+ void
exiterr()
{
dirtempunlink();
diff --git a/gnu/usr.bin/rcs/lib/rcsgen.c b/gnu/usr.bin/rcs/lib/rcsgen.c
index dfb03c1..07b8b25 100644
--- a/gnu/usr.bin/rcs/lib/rcsgen.c
+++ b/gnu/usr.bin/rcs/lib/rcsgen.c
@@ -1,9 +1,7 @@
-/*
- * RCS revision generation
- */
+/* Generate RCS revisions. */
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -19,8 +17,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -28,11 +27,28 @@ Report problems and direct all questions to:
*/
-
-
-/* $Log: rcsgen.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:12 jkh
- * Updated GNU utilities
+/*
+ * $Log: rcsgen.c,v $
+ * Revision 5.16 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.15 1995/06/01 16:23:43 eggert
+ * (putadmin): Open RCS file with FOPEN_WB.
+ *
+ * Revision 5.14 1994/03/17 14:05:48 eggert
+ * Work around SVR4 stdio performance bug.
+ * Flush stderr after prompt. Remove lint.
+ *
+ * Revision 5.13 1993/11/03 17:42:27 eggert
+ * Don't discard ignored phrases. Improve quality of diagnostics.
+ *
+ * Revision 5.12 1992/07/28 16:12:44 eggert
+ * Statement macro names now end in _.
+ * Be consistent about pathnames vs filenames.
+ *
+ * Revision 5.11 1992/01/24 18:44:19 eggert
+ * Move put routines here from rcssyn.c.
+ * Add support for bad_creat0.
*
* Revision 5.10 1991/10/07 17:32:46 eggert
* Fix log bugs, e.g. ci -t/dev/null when has_mmap.
@@ -125,12 +141,14 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(genId, "$Id: rcsgen.c,v 1.1.1.1 1993/06/18 04:22:12 jkh Exp $")
+libId(genId, "$Id: rcsgen.c,v 5.16 1995/06/16 06:19:24 eggert Exp $")
int interactiveflag; /* Should we act as if stdin is a tty? */
struct buf curlogbuf; /* buffer for current log message */
enum stringwork { enter, copy, edit, expand, edit_expand };
+
+static void putdelta P((struct hshentry const*,FILE*));
static void scandeltatext P((struct hshentry*,enum stringwork,int));
@@ -148,11 +166,11 @@ buildrevision(deltas, target, outfile, expandflag)
* otherwise written into a temporary file.
* Temporary files are allocated by maketemp().
* if expandflag is set, keyword expansion is performed.
- * Return nil if outfile is set, the name of the temporary file otherwise.
+ * Return 0 if outfile is set, the name of the temporary file otherwise.
*
* Algorithm: Copy initial revision unchanged. Then edit all revisions but
- * the last one into it, alternating input and output files (resultfile and
- * editfile). The last revision is then edited in, performing simultaneous
+ * the last one into it, alternating input and output files (resultname and
+ * editname). The last revision is then edited in, performing simultaneous
* keyword substitution (this saves one extra pass).
* All this simplifies if only one revision needs to be generated,
* or no keyword expansion is necessary, or if output goes to stdout.
@@ -166,7 +184,7 @@ buildrevision(deltas, target, outfile, expandflag)
return 0;
else {
Ozclose(&fcopy);
- return(resultfile);
+ return resultname;
}
} else {
/* several revisions to generate */
@@ -178,17 +196,17 @@ buildrevision(deltas, target, outfile, expandflag)
}
if (expandflag || outfile) {
/* first, get to beginning of file*/
- finishedit((struct hshentry *)nil, outfile, false);
+ finishedit((struct hshentry*)0, outfile, false);
}
- scandeltatext(deltas->first, expandflag?edit_expand:edit, true);
+ scandeltatext(target, expandflag?edit_expand:edit, true);
finishedit(
- expandflag ? deltas->first : (struct hshentry*)nil,
+ expandflag ? target : (struct hshentry*)0,
outfile, true
);
if (outfile)
return 0;
Ozclose(&fcopy);
- return resultfile;
+ return resultname;
}
}
@@ -196,12 +214,13 @@ buildrevision(deltas, target, outfile, expandflag)
static void
scandeltatext(delta, func, needlog)
- struct hshentry * delta;
+ struct hshentry *delta;
enum stringwork func;
int needlog;
/* Function: Scans delta text nodes up to and including the one given
* by delta. For the one given by delta, the log message is saved into
* delta->log if needlog is set; func specifies how to handle the text.
+ * Similarly, if needlog, delta->igtext is set to the ignored phrases.
* Assumes the initial lexeme must be read in first.
* Does not advance nexttok after it is finished.
*/
@@ -220,11 +239,11 @@ scandeltatext(delta, func, needlog)
if (needlog && delta==nextdelta) {
cb = savestring(&curlogbuf);
delta->log = cleanlogmsg(curlogbuf.string, cb.size);
+ nextlex();
+ delta->igtext = getphrases(Ktext);
} else {readstring();
+ ignorephrases(Ktext);
}
- nextlex();
- while (nexttok==ID && strcmp(NextString,Ktext)!=0)
- ignorephrase();
getkeystring(Ktext);
if (delta==nextdelta)
@@ -236,7 +255,7 @@ scandeltatext(delta, func, needlog)
case enter: enterstring(); break;
case copy: copystring(); break;
case expand: xpandstring(delta); break;
- case edit: editstring((struct hshentry *)nil); break;
+ case edit: editstring((struct hshentry *)0); break;
case edit_expand: editstring(delta); break;
}
}
@@ -287,7 +306,7 @@ getcstdin()
if (feof(in) && ttystdin())
clearerr(in);
c = getc(in);
- if (c < 0) {
+ if (c == EOF) {
testIerror(in);
if (feof(in) && ttystdin())
afputc('\n',stderr);
@@ -330,9 +349,9 @@ putdesc(textflag, textfile)
char *textfile;
/* Function: puts the descriptive text into file frewrite.
* if finptr && !textflag, the text is copied from the old description.
- * Otherwise, if the textfile!=nil, the text is read from that
- * file, or from stdin, if textfile==nil.
- * A textfile with a leading '-' is treated as a string, not a file name.
+ * Otherwise, if textfile, the text is read from that
+ * file, or from stdin, if !textfile.
+ * A textfile with a leading '-' is treated as a string, not a pathname.
* If finptr, the old descriptive text is discarded.
* Always clears foutptr.
*/
@@ -372,13 +391,13 @@ putdesc(textflag, textfile)
p = textfile + 1;
s = strlen(p);
} else {
- if (!(txt = fopen(textfile, "r")))
+ if (!(txt = fopenSafer(textfile, "r")))
efaterror(textfile);
bufalloc(&desc, 1);
p = desc.string;
plim = p + desc.size;
for (;;) {
- if ((c=getc(txt)) < 0) {
+ if ((c=getc(txt)) == EOF) {
testIerror(txt);
if (feof(txt))
break;
@@ -395,7 +414,7 @@ putdesc(textflag, textfile)
desclean = cleanlogmsg(p, s);
}
putstring(frew, false, desclean, true);
- aputc('\n', frew);
+ aputc_('\n', frew)
}
}
@@ -409,13 +428,14 @@ getsstdin(option, name, note, buf)
register size_t i;
register int tty = ttystdin();
- if (tty)
+ if (tty) {
aprintf(stderr,
"enter %s, terminated with single '.' or end of file:\n%s>> ",
name, note
);
- else if (feof(stdin))
- faterror("can't reread redirected stdin for %s; use -%s<%s>",
+ eflush();
+ } else if (feof(stdin))
+ rcsfaterror("can't reread redirected stdin for %s; use -%s<%s>",
name, option, name
);
@@ -429,7 +449,234 @@ getsstdin(option, name, note, buf)
/* Remove trailing '.'. */
--i;
break;
- } else if (tty)
+ } else if (tty) {
aputs(">> ", stderr);
+ eflush();
+ }
return cleanlogmsg(p, i);
}
+
+
+ void
+putadmin()
+/* Output the admin node. */
+{
+ register FILE *fout;
+ struct assoc const *curassoc;
+ struct rcslock const *curlock;
+ struct access const *curaccess;
+
+ if (!(fout = frewrite)) {
+# if bad_creat0
+ ORCSclose();
+ fout = fopenSafer(makedirtemp(0), FOPEN_WB);
+# else
+ int fo = fdlock;
+ fdlock = -1;
+ fout = fdopen(fo, FOPEN_WB);
+# endif
+
+ if (!(frewrite = fout))
+ efaterror(RCSname);
+ }
+
+ /*
+ * Output the first character with putc, not printf.
+ * Otherwise, an SVR4 stdio bug buffers output inefficiently.
+ */
+ aputc_(*Khead, fout)
+ aprintf(fout, "%s\t%s;\n", Khead + 1, Head?Head->num:"");
+ if (Dbranch && VERSION(4)<=RCSversion)
+ aprintf(fout, "%s\t%s;\n", Kbranch, Dbranch);
+
+ aputs(Kaccess, fout);
+ curaccess = AccessList;
+ while (curaccess) {
+ aprintf(fout, "\n\t%s", curaccess->login);
+ curaccess = curaccess->nextaccess;
+ }
+ aprintf(fout, ";\n%s", Ksymbols);
+ curassoc = Symbols;
+ while (curassoc) {
+ aprintf(fout, "\n\t%s:%s", curassoc->symbol, curassoc->num);
+ curassoc = curassoc->nextassoc;
+ }
+ aprintf(fout, ";\n%s", Klocks);
+ curlock = Locks;
+ while (curlock) {
+ aprintf(fout, "\n\t%s:%s", curlock->login, curlock->delta->num);
+ curlock = curlock->nextlock;
+ }
+ if (StrictLocks) aprintf(fout, "; %s", Kstrict);
+ aprintf(fout, ";\n");
+ if (Comment.size) {
+ aprintf(fout, "%s\t", Kcomment);
+ putstring(fout, true, Comment, false);
+ aprintf(fout, ";\n");
+ }
+ if (Expand != KEYVAL_EXPAND)
+ aprintf(fout, "%s\t%c%s%c;\n",
+ Kexpand, SDELIM, expand_names[Expand], SDELIM
+ );
+ awrite(Ignored.string, Ignored.size, fout);
+ aputc_('\n', fout)
+}
+
+
+ static void
+putdelta(node, fout)
+ register struct hshentry const *node;
+ register FILE * fout;
+/* Output the delta NODE to FOUT. */
+{
+ struct branchhead const *nextbranch;
+
+ if (!node) return;
+
+ aprintf(fout, "\n%s\n%s\t%s;\t%s %s;\t%s %s;\nbranches",
+ node->num,
+ Kdate, node->date,
+ Kauthor, node->author,
+ Kstate, node->state?node->state:""
+ );
+ nextbranch = node->branches;
+ while (nextbranch) {
+ aprintf(fout, "\n\t%s", nextbranch->hsh->num);
+ nextbranch = nextbranch->nextbranch;
+ }
+
+ aprintf(fout, ";\n%s\t%s;\n", Knext, node->next?node->next->num:"");
+ awrite(node->ig.string, node->ig.size, fout);
+}
+
+
+ void
+puttree(root, fout)
+ struct hshentry const *root;
+ register FILE *fout;
+/* Output the delta tree with base ROOT in preorder to FOUT. */
+{
+ struct branchhead const *nextbranch;
+
+ if (!root) return;
+
+ if (root->selector)
+ putdelta(root, fout);
+
+ puttree(root->next, fout);
+
+ nextbranch = root->branches;
+ while (nextbranch) {
+ puttree(nextbranch->hsh, fout);
+ nextbranch = nextbranch->nextbranch;
+ }
+}
+
+
+ int
+putdtext(delta, srcname, fout, diffmt)
+ struct hshentry const *delta;
+ char const *srcname;
+ FILE *fout;
+ int diffmt;
+/*
+ * Output a deltatext node with delta number DELTA->num, log message DELTA->log,
+ * ignored phrases DELTA->igtext and text SRCNAME to FOUT.
+ * Double up all SDELIMs in both the log and the text.
+ * Make sure the log message ends in \n.
+ * Return false on error.
+ * If DIFFMT, also check that the text is valid diff -n output.
+ */
+{
+ RILE *fin;
+ if (!(fin = Iopen(srcname, "r", (struct stat*)0))) {
+ eerror(srcname);
+ return false;
+ }
+ putdftext(delta, fin, fout, diffmt);
+ Ifclose(fin);
+ return true;
+}
+
+ void
+putstring(out, delim, s, log)
+ register FILE *out;
+ struct cbuf s;
+ int delim, log;
+/*
+ * Output to OUT one SDELIM if DELIM, then the string S with SDELIMs doubled.
+ * If LOG is set then S is a log string; append a newline if S is nonempty.
+ */
+{
+ register char const *sp;
+ register size_t ss;
+
+ if (delim)
+ aputc_(SDELIM, out)
+ sp = s.string;
+ for (ss = s.size; ss; --ss) {
+ if (*sp == SDELIM)
+ aputc_(SDELIM, out)
+ aputc_(*sp++, out)
+ }
+ if (s.size && log)
+ aputc_('\n', out)
+ aputc_(SDELIM, out)
+}
+
+ void
+putdftext(delta, finfile, foutfile, diffmt)
+ struct hshentry const *delta;
+ RILE *finfile;
+ FILE *foutfile;
+ int diffmt;
+/* like putdtext(), except the source file is already open */
+{
+ declarecache;
+ register FILE *fout;
+ register int c;
+ register RILE *fin;
+ int ed;
+ struct diffcmd dc;
+
+ fout = foutfile;
+ aprintf(fout, DELNUMFORM, delta->num, Klog);
+
+ /* put log */
+ putstring(fout, true, delta->log, true);
+ aputc_('\n', fout)
+
+ /* put ignored phrases */
+ awrite(delta->igtext.string, delta->igtext.size, fout);
+
+ /* put text */
+ aprintf(fout, "%s\n%c", Ktext, SDELIM);
+
+ fin = finfile;
+ setupcache(fin);
+ if (!diffmt) {
+ /* Copy the file */
+ cache(fin);
+ for (;;) {
+ cachegeteof_(c, break;)
+ if (c==SDELIM) aputc_(SDELIM, fout) /*double up SDELIM*/
+ aputc_(c, fout)
+ }
+ } else {
+ initdiffcmd(&dc);
+ while (0 <= (ed = getdiffcmd(fin, false, fout, &dc)))
+ if (ed) {
+ cache(fin);
+ while (dc.nlines--)
+ do {
+ cachegeteof_(c, { if (!dc.nlines) goto OK_EOF; unexpected_EOF(); })
+ if (c == SDELIM)
+ aputc_(SDELIM, fout)
+ aputc_(c, fout)
+ } while (c != '\n');
+ uncache(fin);
+ }
+ }
+ OK_EOF:
+ aprintf(fout, "%c\n", SDELIM);
+}
diff --git a/gnu/usr.bin/rcs/lib/rcskeep.c b/gnu/usr.bin/rcs/lib/rcskeep.c
index 232a616..b73972d 100644
--- a/gnu/usr.bin/rcs/lib/rcskeep.c
+++ b/gnu/usr.bin/rcs/lib/rcskeep.c
@@ -1,14 +1,7 @@
-/*
- * RCS keyword extraction
- */
-/*****************************************************************************
- * main routine: getoldkeys()
- * Testprogram: define KEEPTEST
- *****************************************************************************
- */
+/* Extract RCS keyword string values from working files. */
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -24,8 +17,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -33,11 +27,25 @@ Report problems and direct all questions to:
*/
-
-
-/* $Log: rcskeep.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
- * Updated GNU utilities
+/*
+ * $Log: rcskeep.c,v $
+ * Revision 5.10 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.9 1995/06/01 16:23:43 eggert
+ * (getoldkeys): Don't panic if a Name: is empty.
+ *
+ * Revision 5.8 1994/03/17 14:05:48 eggert
+ * Remove lint.
+ *
+ * Revision 5.7 1993/11/09 17:40:15 eggert
+ * Use simpler timezone parsing strategy now that we're using ISO 8601 format.
+ *
+ * Revision 5.6 1993/11/03 17:42:27 eggert
+ * Scan for Name keyword. Improve quality of diagnostics.
+ *
+ * Revision 5.5 1992/07/28 16:12:44 eggert
+ * Statement macro names now end in _.
*
* Revision 5.4 1991/08/19 03:13:55 eggert
* Tune.
@@ -89,33 +97,29 @@ Report problems and direct all questions to:
*
*/
-/*
-#define KEEPTEST
-*/
-/* Testprogram; prints out the keyword values found. */
-
#include "rcsbase.h"
-libId(keepId, "$Id: rcskeep.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp $")
+libId(keepId, "$Id: rcskeep.c,v 5.10 1995/06/16 06:19:24 eggert Exp $")
-static int checknum P((char const*,int));
-static int getval P((RILE*,struct buf*,int));
+static int badly_terminated P((void));
+static int checknum P((char const*));
static int get0val P((int,RILE*,struct buf*,int));
+static int getval P((RILE*,struct buf*,int));
static int keepdate P((RILE*));
static int keepid P((int,RILE*,struct buf*));
static int keeprev P((RILE*));
int prevkeys;
-struct buf prevauthor, prevdate, prevrev, prevstate;
+struct buf prevauthor, prevdate, prevname, prevrev, prevstate;
int
getoldkeys(fp)
register RILE *fp;
/* Function: Tries to read keyword values for author, date,
* revision number, and state out of the file fp.
- * If FNAME is nonnull, it is opened and closed instead of using FP.
+ * If fp is null, workname is opened and closed instead of using fp.
* The results are placed into
- * prevauthor, prevdate, prevrev, prevstate.
+ * prevauthor, prevdate, prevname, prevrev, prevstate.
* Aborts immediately if it finds an error and returns false.
* If it returns true, it doesn't mean that any of the
* values were found; instead, check to see whether the corresponding arrays
@@ -126,14 +130,15 @@ getoldkeys(fp)
char keyword[keylength+1];
register char * tp;
int needs_closing;
+ int prevname_found;
if (prevkeys)
return true;
needs_closing = false;
if (!fp) {
- if (!(fp = Iopen(workfilename, FOPEN_R_WORK, (struct stat*)0))) {
- eerror(workfilename);
+ if (!(fp = Iopen(workname, FOPEN_R_WORK, (struct stat*)0))) {
+ eerror(workname);
return false;
}
needs_closing = true;
@@ -142,6 +147,7 @@ getoldkeys(fp)
/* initialize to empty */
bufscpy(&prevauthor, "");
bufscpy(&prevdate, "");
+ bufscpy(&prevname, ""); prevname_found = 0;
bufscpy(&prevrev, "");
bufscpy(&prevstate, "");
@@ -152,7 +158,7 @@ getoldkeys(fp)
/* try to get keyword */
tp = keyword;
for (;;) {
- Igeteof(fp, c, goto ok;);
+ Igeteof_(fp, c, goto ok;)
switch (c) {
default:
if (keyword+keylength <= tp)
@@ -168,7 +174,7 @@ getoldkeys(fp)
} while (c==KDELIM);
if (c!=VDELIM) continue;
*tp = c;
- Igeteof(fp, c, break;);
+ Igeteof_(fp, c, break;)
switch (c) {
case ' ': case '\t': break;
default: continue;
@@ -187,7 +193,7 @@ getoldkeys(fp)
case Header:
case Id:
if (!(
- getval(fp, (struct buf*)nil, false) &&
+ getval(fp, (struct buf*)0, false) &&
keeprev(fp) &&
(c = keepdate(fp)) &&
keepid(c, fp, &prevauthor) &&
@@ -195,8 +201,8 @@ getoldkeys(fp)
))
return false;
/* Skip either ``who'' (new form) or ``Locker: who'' (old). */
- if (getval(fp, (struct buf*)nil, true) &&
- getval(fp, (struct buf*)nil, true))
+ if (getval(fp, (struct buf*)0, true) &&
+ getval(fp, (struct buf*)0, true))
c = 0;
else if (nerror)
return false;
@@ -204,13 +210,24 @@ getoldkeys(fp)
c = KDELIM;
break;
case Locker:
+ (void) getval(fp, (struct buf*)0, false);
+ c = 0;
+ break;
case Log:
case RCSfile:
case Source:
- if (!getval(fp, (struct buf*)nil, false))
+ if (!getval(fp, (struct buf*)0, false))
return false;
c = 0;
break;
+ case Name:
+ if (getval(fp, &prevname, false)) {
+ if (*prevname.string)
+ checkssym(prevname.string);
+ prevname_found = 1;
+ }
+ c = 0;
+ break;
case Revision:
if (!keeprev(fp))
return false;
@@ -225,16 +242,18 @@ getoldkeys(fp)
continue;
}
if (!c)
- Igeteof(fp, c, c=0;);
+ Igeteof_(fp, c, c=0;)
if (c != KDELIM) {
- error("closing %c missing on keyword", KDELIM);
+ workerror("closing %c missing on keyword", KDELIM);
return false;
}
- if (*prevauthor.string && *prevdate.string && *prevrev.string && *prevstate.string) {
+ if (prevname_found &&
+ *prevauthor.string && *prevdate.string &&
+ *prevrev.string && *prevstate.string
+ )
break;
- }
}
- Igeteof(fp, c, break;);
+ Igeteof_(fp, c, break;)
}
ok:
@@ -249,7 +268,7 @@ getoldkeys(fp)
static int
badly_terminated()
{
- error("badly terminated keyword value");
+ workerror("badly terminated keyword value");
return false;
}
@@ -260,12 +279,12 @@ getval(fp, target, optional)
int optional;
/* Reads a keyword value from FP into TARGET.
* Returns true if one is found, false otherwise.
- * Does not modify target if it is nil.
+ * Does not modify target if it is 0.
* Do not report an error if OPTIONAL is set and KDELIM is found instead.
*/
{
int c;
- Igeteof(fp, c, return badly_terminated(););
+ Igeteof_(fp, c, return badly_terminated();)
return get0val(c, fp, target, optional);
}
@@ -308,8 +327,6 @@ get0val(c, fp, target, optional)
VOID printf("getval: %s\n", target);
# endif
}
- if (!got1)
- error("too much white space in keyword value");
return got1;
case KDELIM:
@@ -320,7 +337,7 @@ get0val(c, fp, target, optional)
case 0:
return badly_terminated();
}
- Igeteof(fp, c, return badly_terminated(););
+ Igeteof_(fp, c, return badly_terminated();)
}
}
@@ -332,8 +349,7 @@ keepdate(fp)
* Return 0 on error, lookahead character otherwise.
*/
{
- struct buf prevday, prevtime, prevzone;
- register char const *p;
+ struct buf prevday, prevtime;
register int c;
c = 0;
@@ -341,24 +357,18 @@ keepdate(fp)
if (getval(fp,&prevday,false)) {
bufautobegin(&prevtime);
if (getval(fp,&prevtime,false)) {
- bufautobegin(&prevzone);
- bufscpy(&prevzone, "");
- Igeteof(fp, c, c=0;);
- if (c=='-' || c=='+')
- if (!get0val(c,fp,&prevzone,false))
- c = 0;
- else
- Igeteof(fp, c, c=0;);
+ Igeteof_(fp, c, c=0;)
if (c) {
- p = prevday.string;
- bufalloc(&prevdate, strlen(p) + strlen(prevtime.string) + strlen(prevzone.string) + 5);
- VOID sprintf(prevdate.string, "%s%s %s %s",
+ register char const *d = prevday.string, *t = prevtime.string;
+ bufalloc(&prevdate, strlen(d) + strlen(t) + 9);
+ VOID sprintf(prevdate.string, "%s%s %s%s",
/* Parse dates put out by old versions of RCS. */
- isdigit(p[0]) && isdigit(p[1]) && p[2]=='/' ? "19" : "",
- p, prevtime.string, prevzone.string
+ isdigit(d[0]) && isdigit(d[1]) && !isdigit(d[2])
+ ? "19" : "",
+ d, t,
+ strchr(t,'-') || strchr(t,'+') ? "" : "+0000"
);
}
- bufautoend(&prevzone);
}
bufautoend(&prevtime);
}
@@ -374,11 +384,11 @@ keepid(c, fp, b)
/* Get previous identifier from C+FP into B. */
{
if (!c)
- Igeteof(fp, c, return false;);
+ Igeteof_(fp, c, return false;)
if (!get0val(c, fp, b, false))
return false;
checksid(b->string);
- return true;
+ return !nerror;
}
static int
@@ -386,28 +396,45 @@ keeprev(fp)
RILE *fp;
/* Get previous revision from FP into prevrev. */
{
- return getval(fp,&prevrev,false) && checknum(prevrev.string,-1);
+ return getval(fp,&prevrev,false) && checknum(prevrev.string);
}
static int
-checknum(sp,fields)
- register char const *sp;
- int fields;
-{ register int dotcount;
- dotcount=0;
- while(*sp) {
- if (*sp=='.') dotcount++;
- else if (!isdigit(*sp)) return false;
- sp++;
- }
- return fields<0 ? dotcount&1 : dotcount==fields;
+checknum(s)
+ char const *s;
+{
+ register char const *sp;
+ register int dotcount = 0;
+ for (sp=s; ; sp++) {
+ switch (*sp) {
+ case 0:
+ if (dotcount & 1)
+ return true;
+ else
+ break;
+
+ case '.':
+ dotcount++;
+ continue;
+
+ default:
+ if (isdigit(*sp))
+ continue;
+ break;
+ }
+ break;
+ }
+ workerror("%s is not a revision number", s);
+ return false;
}
#ifdef KEEPTEST
+/* Print the keyword values found. */
+
char const cmdid[] ="keeptest";
int
@@ -415,10 +442,10 @@ main(argc, argv)
int argc; char *argv[];
{
while (*(++argv)) {
- workfilename = *argv;
+ workname = *argv;
getoldkeys((RILE*)0);
- VOID printf("%s: revision: %s, date: %s, author: %s, state: %s\n",
- *argv, prevrev.string, prevdate.string, prevauthor.string, prevstate.string);
+ VOID printf("%s: revision: %s, date: %s, author: %s, name: %s, state: %s\n",
+ *argv, prevrev.string, prevdate.string, prevauthor.string, prevname.string, prevstate.string);
}
exitmain(EXIT_SUCCESS);
}
diff --git a/gnu/usr.bin/rcs/lib/rcskeys.c b/gnu/usr.bin/rcs/lib/rcskeys.c
index b45105c..9ef0adf 100644
--- a/gnu/usr.bin/rcs/lib/rcskeys.c
+++ b/gnu/usr.bin/rcs/lib/rcskeys.c
@@ -1,9 +1,7 @@
-/*
- * RCS keyword table and match operation
- */
+/* RCS keyword table and match operation */
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -19,8 +17,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -28,25 +27,13 @@ Report problems and direct all questions to:
*/
-
-
-/* $Log: rcskeys.c,v $
- * Revision 1.4 1994/06/22 00:51:42 rgrimes
- * Fix serious off by one error for FreeBSD keyword, this has been driving
- * me nuts as it was on by default and that is NOT what I wanted.
- *
- * Revision 1.3 1994/05/15 22:15:14 rgrimes
- * To truely have the OLD behavior of RCS by default make the expansion
- * of $FreeBSD$ false by default. This should keep them out
- * of the pre 2.x repository. (Or at least make them useless in it).
- *
- * Revision 1.2 1994/05/14 07:00:23 rgrimes
- * Add new option -K from David Dawes that allows you to turn on and off
- * specific keyword substitution during a rcs co command.
- * Add the new keyword FreeBSD that is IDENTICAL in operation to $Id: rcskeys.c,v 1.4 1994/06/22 00:51:42 rgrimes Exp $.
+/*
+ * $Log: rcskeys.c,v $
+ * Revision 5.4 1995/06/16 06:19:24 eggert
+ * Update FSF address.
*
- * Revision 1.1.1.1 1993/06/18 04:22:12 jkh
- * Updated GNU utilities
+ * Revision 5.3 1993/11/03 17:42:27 eggert
+ * Add Name keyword.
*
* Revision 5.2 1991/08/19 03:13:55 eggert
* Say `T const' instead of `const T'; it's less confusing for pointer types.
@@ -77,26 +64,17 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(keysId, "$Id: rcskeys.c,v 1.4 1994/06/22 00:51:42 rgrimes Exp $")
+libId(keysId, "$Id: rcskeys.c,v 5.4 1995/06/16 06:19:24 eggert Exp $")
char const *const Keyword[] = {
/* This must be in the same order as rcsbase.h's enum markers type. */
- nil,
+ 0,
AUTHOR, DATE, HEADER, IDH,
- LOCKER, LOG, RCSFILE, REVISION, SOURCE, STATE,
- FREEBSD
+ LOCKER, LOG, NAME, RCSFILE, REVISION, SOURCE, STATE
};
-/* Expand all keywords by default */
-
-static int ExpandKeyword[] = {
- nil,
- true, true, true, true,
- true, true, true, true, true, true,
- false
-};
enum markers
trymatch(string)
@@ -109,8 +87,6 @@ trymatch(string)
register int j;
register char const *p, *s;
for (j = sizeof(Keyword)/sizeof(*Keyword); (--j); ) {
- if (!ExpandKeyword[j])
- continue;
/* try next keyword */
p = Keyword[j];
s = string;
@@ -128,35 +104,3 @@ trymatch(string)
return(Nomatch);
}
-
-setIncExc(arg)
- char *arg;
-/* Sets up the ExpandKeyword table according to command-line flags */
-{
- char *key;
- int include = 0, j;
-
- arg += 2;
- switch (*arg++) {
- case 'e':
- include = false;
- break;
- case 'i':
- include = true;
- break;
- default:
- return(false);
- }
- if (include)
- for (j = sizeof(Keyword)/sizeof(*Keyword); (--j); )
- ExpandKeyword[j] = false;
- key = strtok(arg, ",");
- while (key) {
- for (j = sizeof(Keyword)/sizeof(*Keyword); (--j); )
- if (!strcmp(key, Keyword[j]))
- ExpandKeyword[j] = include;
- key = strtok(NULL, ",");
- }
- return(true);
-}
-
diff --git a/gnu/usr.bin/rcs/lib/rcslex.c b/gnu/usr.bin/rcs/lib/rcslex.c
index 621d492..09d41cb 100644
--- a/gnu/usr.bin/rcs/lib/rcslex.c
+++ b/gnu/usr.bin/rcs/lib/rcslex.c
@@ -1,17 +1,16 @@
-/*
- * RCS file input
- */
-/*********************************************************************************
+/* lexical analysis of RCS files */
+
+/******************************************************************************
* Lexical Analysis.
* hashtable, Lexinit, nextlex, getlex, getkey,
* getid, getnum, readstring, printstring, savestring,
* checkid, fatserror, error, faterror, warn, diagnose
* Testprogram: define LEXDB
- *********************************************************************************
+ ******************************************************************************
*/
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -27,8 +26,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -38,13 +38,43 @@ Report problems and direct all questions to:
-/* $Log: rcslex.c,v $
- * Revision 1.2 1993/06/28 19:13:10 nate
- * Added Chris Demetriou's FSYNC_ALL option which causes all writes to be
- * flushed immediately. (In case of a crash in the middle of CVS/RCS commits
+/*
+ * $Log: rcslex.c,v $
+ * Revision 5.19 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.18 1995/06/01 16:23:43 eggert
+ * (map_fd_deallocate,mmap_deallocate,read_deallocate,nothing_to_deallocate):
+ * New functions.
+ * (Iclose): If large_memory and maps_memory, use them to deallocate mapping.
+ * (fd2RILE): Use map_fd if available.
+ * If one mapping method fails, try the next instead of giving up;
+ * if they all fail, fall back on ordinary read.
+ * Work around bug: root mmap over NFS succeeds, but accessing dumps core.
+ * Use MAP_FAILED macro for mmap failure, and `char *' instead of caddr_t.
+ * (advise_access): Use madvise only if this instance used mmap.
+ * (Iopen): Use fdSafer to get safer file descriptor.
+ * (aflush): Moved here from rcsedit.c.
+ *
+ * Revision 5.17 1994/03/20 04:52:58 eggert
+ * Don't worry if madvise fails. Add Orewind. Remove lint.
+ *
+ * Revision 5.16 1993/11/09 17:55:29 eggert
+ * Fix `label: }' typo.
*
- * Revision 1.1.1.1 1993/06/18 04:22:12 jkh
- * Updated GNU utilities
+ * Revision 5.15 1993/11/03 17:42:27 eggert
+ * Improve quality of diagnostics by putting file names in them more often.
+ * Don't discard ignored phrases.
+ *
+ * Revision 5.14 1992/07/28 16:12:44 eggert
+ * Identifiers may now start with a digit and (unless they are symbolic names)
+ * may contain `.'. Avoid `unsigned'. Statement macro names now end in _.
+ *
+ * Revision 5.13 1992/02/17 23:02:27 eggert
+ * Work around NFS mmap SIGBUS problem.
+ *
+ * Revision 5.12 1992/01/06 02:42:34 eggert
+ * Use OPEN_O_BINARY if mode contains 'b'.
*
* Revision 5.11 1991/11/03 03:30:44 eggert
* Fix porting bug to ancient hosts lacking vfprintf.
@@ -139,7 +169,14 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(lexId, "$Id: rcslex.c,v 1.2 1993/06/28 19:13:10 nate Exp $")
+libId(lexId, "$Id: rcslex.c,v 5.19 1995/06/16 06:19:24 eggert Exp $")
+
+static char *checkidentifier P((char*,int,int));
+static void errsay P((char const*));
+static void fatsay P((char const*));
+static void lookup P((char const*));
+static void startsay P((const char*,const char*));
+static void warnsay P((char const*));
static struct hshentry *nexthsh; /*pointer to next hash entry, set by lookup*/
@@ -149,7 +186,7 @@ int hshenter; /*if true, next suitable lexeme will be entered */
/*into the symbol table. Handle with care. */
int nextc; /*next input character, initialized by Lexinit */
-unsigned long rcsline; /*current line-number of input */
+long rcsline; /*current line-number of input */
int nerror; /*counter for errors */
int quietflag; /*indicates quiet mode */
RILE * finptr; /*input file descriptor */
@@ -179,9 +216,9 @@ static int ignored_phrases; /* have we ignored phrases in this RCS file? */
void
warnignore()
{
- if (! (ignored_phrases|quietflag)) {
+ if (!ignored_phrases) {
ignored_phrases = true;
- warn("Unknown phrases like `%s ...;' are in the RCS file.", NextString);
+ rcswarn("Unknown phrases like `%s ...;' are present.", NextString);
}
}
@@ -212,7 +249,7 @@ lookup(str)
/* empty slot found */
*p = n = ftalloc(struct hshentry);
n->num = fstr_save(str);
- n->nexthsh = nil;
+ n->nexthsh = 0;
# ifdef LEXDB
VOID printf("\nEntered: %s at %u ", str, ihash);
# endif
@@ -238,7 +275,7 @@ Lexinit()
{ register int c;
for (c = hshsize; 0 <= --c; ) {
- hshtab[c] = nil;
+ hshtab[c] = 0;
}
nerror = 0;
@@ -248,7 +285,7 @@ Lexinit()
ignored_phrases = false;
rcsline = 1;
bufrealloc(&tokbuf, 2);
- Iget(finptr, nextc);
+ Iget_(finptr, nextc)
nextlex(); /*initial token*/
}
}
@@ -295,46 +332,48 @@ nextlex()
/* Note: falls into next case */
case SPACE:
- GETC(frew, c);
+ GETC_(frew, c)
continue;
- case DIGIT:
- sp = tokbuf.string;
- limit = sp + tokbuf.size;
- *sp++ = c;
- for (;;) {
- GETC(frew, c);
- if ((d=ctab[c])!=DIGIT && d!=PERIOD)
- break;
- *sp++ = c; /* 1.2. and 1.2 are different */
- if (limit <= sp)
- sp = bufenlarge(&tokbuf, &limit);
- }
- *sp = 0;
- if (hshenter)
- lookup(tokbuf.string);
- else
- NextString = fstr_save(tokbuf.string);
- d = NUM;
- break;
-
-
- case LETTER:
+ case IDCHAR:
+ case LETTER:
case Letter:
+ d = ID;
+ /* fall into */
+ case DIGIT:
+ case PERIOD:
sp = tokbuf.string;
limit = sp + tokbuf.size;
*sp++ = c;
for (;;) {
- GETC(frew, c);
- if ((d=ctab[c])!=LETTER && d!=Letter && d!=DIGIT && d!=IDCHAR)
+ GETC_(frew, c)
+ switch (ctab[c]) {
+ case IDCHAR:
+ case LETTER:
+ case Letter:
+ d = ID;
+ /* fall into */
+ case DIGIT:
+ case PERIOD:
+ *sp++ = c;
+ if (limit <= sp)
+ sp = bufenlarge(&tokbuf, &limit);
+ continue;
+
+ default:
break;
- *sp++ = c;
- if (limit <= sp)
- sp = bufenlarge(&tokbuf, &limit);
+ }
+ break;
}
*sp = 0;
+ if (d == DIGIT || d == PERIOD) {
+ d = NUM;
+ if (hshenter) {
+ lookup(tokbuf.string);
+ break;
+ }
+ }
NextString = fstr_save(tokbuf.string);
- d = ID; /* may be ID or keyword */
break;
case SBEGIN: /* long string */
@@ -345,7 +384,7 @@ nextlex()
case COLON:
case SEMI:
- GETC(frew, c);
+ GETC_(frew, c)
break;
} break; }
nextc = c;
@@ -381,11 +420,11 @@ eoflex()
++rcsline;
/* fall into */
case SPACE:
- cachegeteof(c, {uncache(fin);return true;});
+ cachegeteof_(c, {uncache(fin);return true;})
break;
}
if (fout)
- aputc(c, fout);
+ aputc_(c, fout)
}
}
@@ -449,7 +488,7 @@ getkeystring(key)
getid()
/* Function: Checks if nexttok is an identifier. If so,
* advances the input by calling nextlex and returns a pointer
- * to the identifier; otherwise returns nil.
+ * to the identifier; otherwise returns 0.
* Treats keywords as identifiers.
*/
{
@@ -458,14 +497,15 @@ getid()
name = NextString;
nextlex();
return name;
- } else return nil;
+ } else
+ return 0;
}
struct hshentry * getnum()
/* Function: Checks if nexttok is a number. If so,
* advances the input by calling nextlex and returns a pointer
- * to the hashtable entry. Otherwise returns nil.
+ * to the hashtable entry. Otherwise returns 0.
* Doesn't work if hshenter is false.
*/
{
@@ -474,46 +514,55 @@ struct hshentry * getnum()
num=nexthsh;
nextlex();
return num;
- } else return nil;
+ } else
+ return 0;
}
struct cbuf
getphrases(key)
char const *key;
-/* Get a series of phrases that do not start with KEY, yield resulting buffer.
- * Stop when the next phrase starts with a token that is not an identifier,
- * or is KEY.
- * Assume !foutptr.
- */
+/*
+* Get a series of phrases that do not start with KEY. Yield resulting buffer.
+* Stop when the next phrase starts with a token that is not an identifier,
+* or is KEY. Copy input to foutptr if it is set. Unlike ignorephrases(),
+* this routine assumes nextlex() has already been invoked before we start.
+*/
{
declarecache;
register int c;
- register char *p;
- char const *limit;
- register char const *ki, *kn;
+ register char const *kn;
struct cbuf r;
- struct buf b;
register RILE *fin;
+ register FILE *frew;
+# if large_memory
+# define savech_(c) ;
+# else
+ register char *p;
+ char const *limit;
+ struct buf b;
+# define savech_(c) {if (limit<=p)p=bufenlarge(&b,&limit); *p++ =(c);}
+# endif
- if (nexttok!=ID || strcmp(NextString,key) == 0) {
- r.string = 0;
- r.size = 0;
- return r;
- } else {
+ if (nexttok!=ID || strcmp(NextString,key) == 0)
+ clear_buf(&r);
+ else {
warnignore();
fin = finptr;
+ frew = foutptr;
setupcache(fin); cache(fin);
- bufautobegin(&b);
- bufscpy(&b, NextString);
+# if large_memory
+ r.string = (char const*)cacheptr() - strlen(NextString) - 1;
+# else
+ bufautobegin(&b);
+ bufscpy(&b, NextString);
+ p = b.string + strlen(b.string);
+ limit = b.string + b.size;
+# endif
ffree1(NextString);
- p = b.string + strlen(b.string);
- limit = b.string + b.size;
c = nextc;
for (;;) {
for (;;) {
- if (limit <= p)
- p = bufenlarge(&b, &limit);
- *p++ = c;
+ savech_(c)
switch (ctab[c]) {
default:
fatserror("unknown character `%c'", c);
@@ -523,15 +572,13 @@ getphrases(key)
/* fall into */
case COLON: case DIGIT: case LETTER: case Letter:
case PERIOD: case SPACE:
- cacheget(c);
+ GETC_(frew, c)
continue;
case SBEGIN: /* long string */
for (;;) {
for (;;) {
- if (limit <= p)
- p = bufenlarge(&b, &limit);
- cacheget(c);
- *p++ = c;
+ GETC_(frew, c)
+ savech_(c)
switch (c) {
case '\n':
++rcsline;
@@ -544,48 +591,50 @@ getphrases(key)
}
break;
}
- cacheget(c);
+ GETC_(frew, c)
if (c != SDELIM)
break;
- if (limit <= p)
- p = bufenlarge(&b, &limit);
- *p++ = c;
+ savech_(c)
}
continue;
case SEMI:
- cacheget(c);
+ cacheget_(c)
if (ctab[c] == NEWLN) {
+ if (frew)
+ aputc_(c, frew)
++rcsline;
- if (limit <= p)
- p = bufenlarge(&b, &limit);
- *p++ = c;
- cacheget(c);
+ savech_(c)
+ cacheget_(c)
}
+# if large_memory
+ r.size = (char const*)cacheptr() - 1 - r.string;
+# endif
for (;;) {
switch (ctab[c]) {
case NEWLN:
++rcsline;
/* fall into */
case SPACE:
- cacheget(c);
+ cacheget_(c)
continue;
default: break;
}
break;
}
+ if (frew)
+ aputc_(c, frew)
break;
}
break;
}
- switch (ctab[c]) {
- case LETTER:
- case Letter:
+ if (ctab[c] == Letter) {
for (kn = key; c && *kn==c; kn++)
- cacheget(c);
+ GETC_(frew, c)
if (!*kn)
switch (ctab[c]) {
case DIGIT: case LETTER: case Letter:
+ case IDCHAR: case PERIOD:
break;
default:
nextc = c;
@@ -594,23 +643,26 @@ getphrases(key)
uncache(fin);
goto returnit;
}
- for (ki=key; ki<kn; ) {
- if (limit <= p)
- p = bufenlarge(&b, &limit);
- *p++ = *ki++;
- }
- break;
-
- default:
+# if !large_memory
+ {
+ register char const *ki;
+ for (ki=key; ki<kn; )
+ savech_(*ki++)
+ }
+# endif
+ } else {
nextc = c;
uncache(fin);
nextlex();
- goto returnit;
+ break;
}
}
- returnit:
- return bufremember(&b, (size_t)(p - b.string));
+ returnit:;
+# if !large_memory
+ return bufremember(&b, (size_t)(p - b.string));
+# endif
}
+ return r;
}
@@ -626,14 +678,14 @@ readstring()
fin=finptr; frew=foutptr;
setupcache(fin); cache(fin);
for (;;) {
- GETC(frew, c);
+ GETC_(frew, c)
switch (c) {
case '\n':
++rcsline;
break;
case SDELIM:
- GETC(frew, c);
+ GETC_(frew, c)
if (c != SDELIM) {
/* end of string */
nextc = c;
@@ -660,13 +712,13 @@ printstring()
fout = stdout;
setupcache(fin); cache(fin);
for (;;) {
- cacheget(c);
+ cacheget_(c)
switch (c) {
case '\n':
++rcsline;
break;
case SDELIM:
- cacheget(c);
+ cacheget_(c)
if (c != SDELIM) {
nextc=c;
uncache(fin);
@@ -674,7 +726,7 @@ printstring()
}
break;
}
- aputc(c,fout);
+ aputc_(c,fout)
}
}
@@ -702,13 +754,13 @@ savestring(target)
setupcache(fin); cache(fin);
tp = target->string; limit = tp + target->size;
for (;;) {
- GETC(frew, c);
+ GETC_(frew, c)
switch (c) {
case '\n':
++rcsline;
break;
case SDELIM:
- GETC(frew, c);
+ GETC_(frew, c)
if (c != SDELIM) {
/* end of string */
nextc=c;
@@ -726,44 +778,76 @@ savestring(target)
}
- char *
-checkid(id, delimiter)
+ static char *
+checkidentifier(id, delimiter, dotok)
register char *id;
int delimiter;
+ register int dotok;
/* Function: check whether the string starting at id is an */
/* identifier and return a pointer to the delimiter*/
/* after the identifier. White space, delim and 0 */
/* are legal delimiters. Aborts the program if not*/
/* a legal identifier. Useful for checking commands*/
/* If !delim, the only delimiter is 0. */
+/* Allow '.' in identifier only if DOTOK is set. */
{
- register enum tokens d;
register char *temp;
- register char c,tc;
+ register char c;
register char delim = delimiter;
+ int isid = false;
temp = id;
- if ((d = ctab[(unsigned char)(c = *id)])==LETTER || d==Letter) {
- while ((d = ctab[(unsigned char)(c = *++id)])==LETTER
- || d==Letter || d==DIGIT || d==IDCHAR
- )
- ;
- if (c && (!delim || c!=delim && c!=' ' && c!='\t' && c!='\n')) {
+ for (;; id++) {
+ switch (ctab[(unsigned char)(c = *id)]) {
+ case IDCHAR:
+ case LETTER:
+ case Letter:
+ isid = true;
+ continue;
+
+ case DIGIT:
+ continue;
+
+ case PERIOD:
+ if (dotok)
+ continue;
+ break;
+
+ default:
+ break;
+ }
+ break;
+ }
+ if ( ! isid
+ || (c && (!delim || (c!=delim && c!=' ' && c!='\t' && c!='\n')))
+ ) {
/* append \0 to end of id before error message */
- tc = c;
- while( (c=(*++id))!=' ' && c!='\t' && c!='\n' && c!='\0' && c!=delim) ;
+ while ((c = *id) && c!=' ' && c!='\t' && c!='\n' && c!=delim)
+ id++;
*id = '\0';
- faterror("invalid character %c in identifier `%s'",tc,temp);
- }
- } else {
- /* append \0 to end of id before error message */
- while( (c=(*++id))!=' ' && c!='\t' && c!='\n' && c!='\0' && c!=delim) ;
- *id = '\0';
- faterror("identifier `%s' doesn't start with letter", temp);
- }
+ faterror("invalid %s `%s'",
+ dotok ? "identifier" : "symbol", temp
+ );
+ }
return id;
}
+ char *
+checkid(id, delimiter)
+ char *id;
+ int delimiter;
+{
+ return checkidentifier(id, delimiter, true);
+}
+
+ char *
+checksym(sym, delimiter)
+ char *sym;
+ int delimiter;
+{
+ return checkidentifier(sym, delimiter, false);
+}
+
void
checksid(id)
char *id;
@@ -772,16 +856,92 @@ checksid(id)
VOID checkid(id, 0);
}
+ void
+checkssym(sym)
+ char *sym;
+{
+ VOID checksym(sym, 0);
+}
+
+
+#if !large_memory
+# define Iclose(f) fclose(f)
+#else
+# if !maps_memory
+ static int Iclose P((RILE *));
+ static int
+ Iclose(f)
+ register RILE *f;
+ {
+ tfree(f->base);
+ f->base = 0;
+ return fclose(f->stream);
+ }
+# else
+ static int Iclose P((RILE *));
+ static int
+ Iclose(f)
+ register RILE *f;
+ {
+ (* f->deallocate) (f);
+ f->base = 0;
+ return close(f->fd);
+ }
+
+# if has_map_fd
+ static void map_fd_deallocate P((RILE *));
+ static void
+ map_fd_deallocate(f)
+ register RILE *f;
+ {
+ if (vm_deallocate(
+ task_self(),
+ (vm_address_t) f->base,
+ (vm_size_t) (f->lim - f->base)
+ ) != KERN_SUCCESS)
+ efaterror("vm_deallocate");
+ }
+# endif
+# if has_mmap
+ static void mmap_deallocate P((RILE *));
+ static void
+ mmap_deallocate(f)
+ register RILE *f;
+ {
+ if (munmap((char *) f->base, (size_t) (f->lim - f->base)) != 0)
+ efaterror("munmap");
+ }
+# endif
+ static void read_deallocate P((RILE *));
+ static void
+ read_deallocate(f)
+ RILE *f;
+ {
+ tfree(f->base);
+ }
+
+ static void nothing_to_deallocate P((RILE *));
+ static void
+ nothing_to_deallocate(f)
+ RILE *f;
+ {
+ }
+# endif
+#endif
+
+#if large_memory && maps_memory
+ static RILE *fd2_RILE P((int,char const*,struct stat*));
static RILE *
-#if has_mmap && large_memory
-fd2_RILE(fd, filename, status)
+fd2_RILE(fd, name, status)
#else
-fd2RILE(fd, filename, mode, status)
- char const *mode;
+ static RILE *fd2RILE P((int,char const*,char const*,struct stat*));
+ static RILE *
+fd2RILE(fd, name, type, status)
+ char const *type;
#endif
int fd;
- char const *filename;
+ char const *name;
register struct stat *status;
{
struct stat st;
@@ -789,67 +949,127 @@ fd2RILE(fd, filename, mode, status)
if (!status)
status = &st;
if (fstat(fd, status) != 0)
- efaterror(filename);
+ efaterror(name);
if (!S_ISREG(status->st_mode)) {
- error("`%s' is not a regular file", filename);
+ error("`%s' is not a regular file", name);
VOID close(fd);
errno = EINVAL;
return 0;
} else {
-# if ! (has_mmap && large_memory)
+# if !(large_memory && maps_memory)
FILE *stream;
- if (!(stream = fdopen(fd, mode)))
- efaterror(filename);
+ if (!(stream = fdopen(fd, type)))
+ efaterror(name);
# endif
# if !large_memory
return stream;
# else
# define RILES 3
- {
- static RILE rilebuf[RILES];
-
- register RILE *f;
- size_t s = status->st_size;
-
- if (s != status->st_size)
- faterror("`%s' is enormous", filename);
- for (f = rilebuf; f->base; f++)
- if (f == rilebuf+RILES)
- faterror("too many RILEs");
- if (!s) {
- static unsigned char dummy;
- f->base = &dummy;
- } else {
-# if has_mmap
- if (
- (f->base = (unsigned char *)mmap(
- (caddr_t)0, s, PROT_READ, MAP_SHARED,
- fd, (off_t)0
- )) == (unsigned char *)-1
- )
- efaterror("mmap");
-# else
- f->base = tnalloc(unsigned char, s);
+ {
+ static RILE rilebuf[RILES];
+
+ register RILE *f;
+ size_t s = status->st_size;
+
+ if (s != status->st_size)
+ faterror("%s: too large", name);
+ for (f = rilebuf; f->base; f++)
+ if (f == rilebuf+RILES)
+ faterror("too many RILEs");
+# if maps_memory
+ f->deallocate = nothing_to_deallocate;
+# endif
+ if (!s) {
+ static unsigned char nothing;
+ f->base = &nothing; /* Any nonzero address will do. */
+ } else {
+ f->base = 0;
+# if has_map_fd
+ map_fd(
+ fd, (vm_offset_t)0, (vm_address_t*) &f->base,
+ TRUE, (vm_size_t)s
+ );
+ f->deallocate = map_fd_deallocate;
+# endif
+# if has_mmap
+ if (!f->base) {
+ catchmmapints();
+ f->base = (unsigned char *) mmap(
+ (char *)0, s, PROT_READ, MAP_SHARED,
+ fd, (off_t)0
+ );
+# ifndef MAP_FAILED
+# define MAP_FAILED (-1)
# endif
+ if (f->base == (unsigned char *) MAP_FAILED)
+ f->base = 0;
+ else {
+# if has_NFS && mmap_signal
+ /*
+ * On many hosts, the superuser
+ * can mmap an NFS file it can't read.
+ * So access the first page now, and print
+ * a nice message if a bus error occurs.
+ */
+ readAccessFilenameBuffer(name, f->base);
+# endif
+ }
+ f->deallocate = mmap_deallocate;
+ }
+# endif
+ if (!f->base) {
+ f->base = tnalloc(unsigned char, s);
+# if maps_memory
+ {
+ /*
+ * We can't map the file into memory for some reason.
+ * Read it into main memory all at once; this is
+ * the simplest substitute for memory mapping.
+ */
+ char *bufptr = (char *) f->base;
+ size_t bufsiz = s;
+ do {
+ ssize_t r = read(fd, bufptr, bufsiz);
+ switch (r) {
+ case -1:
+ efaterror(name);
+
+ case 0:
+ /* The file must have shrunk! */
+ status->st_size = s -= bufsiz;
+ bufsiz = 0;
+ break;
+
+ default:
+ bufptr += r;
+ bufsiz -= r;
+ break;
+ }
+ } while (bufsiz);
+ if (lseek(fd, (off_t)0, SEEK_SET) == -1)
+ efaterror(name);
+ f->deallocate = read_deallocate;
}
- f->ptr = f->base;
- f->lim = f->base + s;
-# if has_mmap
- f->fd = fd;
-# else
- f->readlim = f->base;
- f->stream = stream;
# endif
- if_advise_access(s, f, MADV_SEQUENTIAL);
- return f;
+ }
}
+ f->ptr = f->base;
+ f->lim = f->base + s;
+ f->fd = fd;
+# if !maps_memory
+ f->readlim = f->base;
+ f->stream = stream;
+# endif
+ if_advise_access(s, f, MADV_SEQUENTIAL);
+ return f;
+ }
# endif
}
}
-#if !has_mmap && large_memory
+#if !maps_memory && large_memory
int
Igetmore(f)
register RILE *f;
@@ -875,59 +1095,42 @@ advise_access(f, advice)
register RILE *f;
int advice;
{
- if (madvise((caddr_t)f->base, (size_t)(f->lim - f->base), advice) != 0)
- efaterror("madvise");
+ if (f->deallocate == mmap_deallocate)
+ VOID madvise((char *)f->base, (size_t)(f->lim - f->base), advice);
+ /* Don't worry if madvise fails; it's only advisory. */
}
#endif
RILE *
-#if has_mmap && large_memory
-I_open(filename, status)
+#if large_memory && maps_memory
+I_open(name, status)
#else
-Iopen(filename, mode, status)
- char const *mode;
+Iopen(name, type, status)
+ char const *type;
#endif
- char const *filename;
+ char const *name;
struct stat *status;
-/* Open FILENAME for reading, yield its descriptor, and set *STATUS. */
+/* Open NAME for reading, yield its descriptor, and set *STATUS. */
{
- int fd;
+ int fd = fdSafer(open(name, O_RDONLY
+# if OPEN_O_BINARY
+ | (strchr(type,'b') ? OPEN_O_BINARY : 0)
+# endif
+ ));
- if ((fd = open(filename,O_RDONLY|O_BINARY)) < 0)
+ if (fd < 0)
return 0;
-# if has_mmap && large_memory
- return fd2_RILE(fd, filename, status);
+# if large_memory && maps_memory
+ return fd2_RILE(fd, name, status);
# else
- return fd2RILE(fd, filename, mode, status);
+ return fd2RILE(fd, name, type, status);
# endif
}
-#if !large_memory
-# define Iclose(f) fclose(f)
-#else
- static int
- Iclose(f)
- register RILE *f;
- {
-# if has_mmap
- size_t s = f->lim - f->base;
- if (s && munmap((caddr_t)f->base, s) != 0)
- return -1;
- f->base = 0;
- return close(f->fd);
-# else
- tfree(f->base);
- f->base = 0;
- return fclose(f->stream);
-# endif
- }
-#endif
-
-
static int Oerrloop;
- exiting void
+ void
Oerror()
{
if (Oerrloop)
@@ -936,19 +1139,13 @@ Oerror()
efaterror("output error");
}
-exiting void Ieof() { fatserror("unexpected end of file"); }
-exiting void Ierror() { efaterror("input error"); }
+void Ieof() { fatserror("unexpected end of file"); }
+void Ierror() { efaterror("input error"); }
void testIerror(f) FILE *f; { if (ferror(f)) Ierror(); }
void testOerror(o) FILE *o; { if (ferror(o)) Oerror(); }
void Ifclose(f) RILE *f; { if (f && Iclose(f)!=0) Ierror(); }
-#ifndef FSYNC_ALL
void Ofclose(f) FILE *f; { if (f && fclose(f)!=0) Oerror(); }
-#else
-void Ofclose(f) FILE *f; { if (f && (fflush(f)!=0 ||
- fsync(fileno(f))!=0 ||
- fclose(f)!=0)) Oerror(); }
-#endif
void Izclose(p) RILE **p; { Ifclose(*p); *p = 0; }
void Ozclose(p) FILE **p; { Ofclose(*p); *p = 0; }
@@ -964,19 +1161,17 @@ testIeof(f)
void Irewind(f) FILE *f; { if (fseek(f,0L,SEEK_SET) != 0) Ierror(); }
#endif
-void eflush()
-{
- if (fflush(stderr) != 0 && !Oerrloop)
- Oerror();
-}
+void Orewind(f) FILE *f; { if (fseek(f,0L,SEEK_SET) != 0) Oerror(); }
+void aflush(f) FILE *f; { if (fflush(f) != 0) Oerror(); }
+void eflush() { if (fflush(stderr)!=0 && !Oerrloop) Oerror(); }
void oflush()
{
if (fflush(workstdout ? workstdout : stdout) != 0 && !Oerrloop)
Oerror();
}
- static exiting void
+ void
fatcleanup(already_newline)
int already_newline;
{
@@ -984,8 +1179,38 @@ fatcleanup(already_newline)
exiterr();
}
-static void errsay() { oflush(); aprintf(stderr,"%s error: ",cmdid); nerror++; }
-static void fatsay() { oflush(); VOID fprintf(stderr,"%s error: ",cmdid); }
+ static void
+startsay(s, t)
+ const char *s, *t;
+{
+ oflush();
+ if (s)
+ aprintf(stderr, "%s: %s: %s", cmdid, s, t);
+ else
+ aprintf(stderr, "%s: %s", cmdid, t);
+}
+
+ static void
+fatsay(s)
+ char const *s;
+{
+ startsay(s, "");
+}
+
+ static void
+errsay(s)
+ char const *s;
+{
+ fatsay(s);
+ nerror++;
+}
+
+ static void
+warnsay(s)
+ char const *s;
+{
+ startsay(s, "warning: ");
+}
void eerror(s) char const *s; { enerror(errno,s); }
@@ -994,20 +1219,20 @@ enerror(e,s)
int e;
char const *s;
{
- errsay();
+ errsay((char const*)0);
errno = e;
perror(s);
eflush();
}
-exiting void efaterror(s) char const *s; { enfaterror(errno,s); }
+void efaterror(s) char const *s; { enfaterror(errno,s); }
- exiting void
+ void
enfaterror(e,s)
int e;
char const *s;
{
- fatsay();
+ fatsay((char const*)0);
errno = e;
perror(s);
fatcleanup(true);
@@ -1022,7 +1247,41 @@ error(char const *format,...)
/* non-fatal error */
{
va_list args;
- errsay();
+ errsay((char const*)0);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ afputc('\n',stderr);
+ eflush();
+}
+
+#if has_prototypes
+ void
+rcserror(char const *format,...)
+#else
+ /*VARARGS1*/ void rcserror(format, va_alist) char const *format; va_dcl
+#endif
+/* non-fatal RCS file error */
+{
+ va_list args;
+ errsay(RCSname);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ afputc('\n',stderr);
+ eflush();
+}
+
+#if has_prototypes
+ void
+workerror(char const *format,...)
+#else
+ /*VARARGS1*/ void workerror(format, va_alist) char const *format; va_dcl
+#endif
+/* non-fatal working file error */
+{
+ va_list args;
+ errsay(workname);
vararg_start(args, format);
fvfprintf(stderr, format, args);
va_end(args);
@@ -1031,17 +1290,17 @@ error(char const *format,...)
}
#if has_prototypes
- exiting void
+ void
fatserror(char const *format,...)
#else
- /*VARARGS1*/ exiting void
+ /*VARARGS1*/ void
fatserror(format, va_alist) char const *format; va_dcl
#endif
-/* fatal syntax error */
+/* fatal RCS file syntax error */
{
va_list args;
oflush();
- VOID fprintf(stderr, "%s: %s:%lu: ", cmdid, RCSfilename, rcsline);
+ VOID fprintf(stderr, "%s: %s:%ld: ", cmdid, RCSname, rcsline);
vararg_start(args, format);
fvfprintf(stderr, format, args);
va_end(args);
@@ -1049,16 +1308,16 @@ fatserror(char const *format,...)
}
#if has_prototypes
- exiting void
+ void
faterror(char const *format,...)
#else
- /*VARARGS1*/ exiting void faterror(format, va_alist)
+ /*VARARGS1*/ void faterror(format, va_alist)
char const *format; va_dcl
#endif
/* fatal error, terminates program after cleanup */
{
va_list args;
- fatsay();
+ fatsay((char const*)0);
vararg_start(args, format);
fvfprintf(stderr, format, args);
va_end(args);
@@ -1067,20 +1326,76 @@ faterror(char const *format,...)
#if has_prototypes
void
-warn(char const *format,...)
+rcsfaterror(char const *format,...)
#else
- /*VARARGS1*/ void warn(format, va_alist) char const *format; va_dcl
+ /*VARARGS1*/ void rcsfaterror(format, va_alist)
+ char const *format; va_dcl
#endif
-/* prints a warning message */
+/* fatal RCS file error, terminates program after cleanup */
{
va_list args;
- oflush();
- aprintf(stderr,"%s warning: ",cmdid);
+ fatsay(RCSname);
vararg_start(args, format);
fvfprintf(stderr, format, args);
va_end(args);
- afputc('\n',stderr);
- eflush();
+ fatcleanup(false);
+}
+
+#if has_prototypes
+ void
+warn(char const *format,...)
+#else
+ /*VARARGS1*/ void warn(format, va_alist) char const *format; va_dcl
+#endif
+/* warning */
+{
+ va_list args;
+ if (!quietflag) {
+ warnsay((char *)0);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ afputc('\n', stderr);
+ eflush();
+ }
+}
+
+#if has_prototypes
+ void
+rcswarn(char const *format,...)
+#else
+ /*VARARGS1*/ void rcswarn(format, va_alist) char const *format; va_dcl
+#endif
+/* RCS file warning */
+{
+ va_list args;
+ if (!quietflag) {
+ warnsay(RCSname);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ afputc('\n', stderr);
+ eflush();
+ }
+}
+
+#if has_prototypes
+ void
+workwarn(char const *format,...)
+#else
+ /*VARARGS1*/ void workwarn(format, va_alist) char const *format; va_dcl
+#endif
+/* working file warning */
+{
+ va_list args;
+ if (!quietflag) {
+ warnsay(workname);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ afputc('\n', stderr);
+ eflush();
+ }
}
void
@@ -1115,12 +1430,11 @@ diagnose(char const *format,...)
void
afputc(c, f)
-/* Function: afputc(c,f) acts like aputc(c,f), but is smaller and slower.
- */
+/* afputc(c,f); acts like aputc_(c,f) but is smaller and slower. */
int c;
register FILE *f;
{
- aputc(c,f);
+ aputc_(c,f)
}
@@ -1151,6 +1465,7 @@ fvfprintf(FILE *stream, char const *format, va_list args)
{
#if has_vfprintf
if (vfprintf(stream, format, args) < 0)
+ Oerror();
#else
# if has__doprintf
_doprintf(stream, format, args);
@@ -1166,8 +1481,8 @@ fvfprintf(FILE *stream, char const *format, va_list args)
# endif
# endif
if (ferror(stream))
-#endif
Oerror();
+#endif
}
#if has_prototypes
@@ -1248,7 +1563,7 @@ int argc; char * argv[];
exitmain(EXIT_SUCCESS);
}
-exiting void exiterr() { _exit(EXIT_FAILURE); }
+void exiterr() { _exit(EXIT_FAILURE); }
#endif
diff --git a/gnu/usr.bin/rcs/lib/rcsrev.c b/gnu/usr.bin/rcs/lib/rcsrev.c
index 96eb9e6..21e985b 100644
--- a/gnu/usr.bin/rcs/lib/rcsrev.c
+++ b/gnu/usr.bin/rcs/lib/rcsrev.c
@@ -1,9 +1,7 @@
-/*
- * RCS revision number handling
- */
+/* Handle RCS revision numbers. */
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -19,8 +17,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -28,12 +27,31 @@ Report problems and direct all questions to:
*/
-
-
-
-/* $Log: rcsrev.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
- * Updated GNU utilities
+/*
+ * $Log: rcsrev.c,v $
+ * Revision 5.10 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.9 1995/06/01 16:23:43 eggert
+ * (cmpdate, normalizeyear): New functions work around MKS RCS incompatibility.
+ * (cmpnum, compartial): s[d] -> *(s+d) to work around Cray compiler bug.
+ * (genrevs, genbranch): cmpnum -> cmpdate
+ *
+ * Revision 5.8 1994/03/17 14:05:48 eggert
+ * Remove lint.
+ *
+ * Revision 5.7 1993/11/09 17:40:15 eggert
+ * Fix format string typos.
+ *
+ * Revision 5.6 1993/11/03 17:42:27 eggert
+ * Revision number `.N' now stands for `D.N', where D is the default branch.
+ * Add -z. Improve quality of diagnostics. Add `namedrev' for Name support.
+ *
+ * Revision 5.5 1992/07/28 16:12:44 eggert
+ * Identifiers may now start with a digit. Avoid `unsigned'.
+ *
+ * Revision 5.4 1992/01/06 02:42:34 eggert
+ * while (E) ; -> while (E) continue;
*
* Revision 5.3 1991/08/19 03:13:55 eggert
* Add `-r$', `-rB.'. Remove botches like `<now>' from messages. Tune.
@@ -86,25 +104,21 @@ Report problems and direct all questions to:
* in that case.
*/
-
-
-/*
-#define REVTEST
-*/
-/* version REVTEST is for testing the routines that generate a sequence
- * of delta numbers needed to regenerate a given delta.
- */
-
#include "rcsbase.h"
-libId(revId, "$Id: rcsrev.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp $")
+libId(revId, "$Id: rcsrev.c,v 5.10 1995/06/16 06:19:24 eggert Exp $")
static char const *branchtip P((char const*));
-static struct hshentry *genbranch P((struct hshentry const*,char const*,unsigned,char const*,char const*,char const*,struct hshentries**));
+static char const *lookupsym P((char const*));
+static char const *normalizeyear P((char const*,char[5]));
+static struct hshentry *genbranch P((struct hshentry const*,char const*,int,char const*,char const*,char const*,struct hshentries**));
+static void absent P((char const*,int));
+static void cantfindbranch P((char const*,char const[datesize],char const*,char const*));
+static void store1 P((struct hshentries***,struct hshentry*));
- unsigned
+ int
countnumflds(s)
char const *s;
/* Given a pointer s to a dotted number (date or revision number),
@@ -112,9 +126,9 @@ countnumflds(s)
*/
{
register char const *sp;
- register unsigned count;
- if ((sp=s)==nil) return(0);
- if (*sp == '\0') return(0);
+ register int count;
+ if (!(sp=s) || !*sp)
+ return 0;
count = 1;
do {
if (*sp++ == '.') count++;
@@ -126,12 +140,12 @@ countnumflds(s)
getbranchno(revno,branchno)
char const *revno;
struct buf *branchno;
-/* Given a non-nil revision number revno, getbranchno copies the number of the branch
+/* Given a revision number revno, getbranchno copies the number of the branch
* on which revno is into branchno. If revno itself is a branch number,
* it is copied unchanged.
*/
{
- register unsigned numflds;
+ register int numflds;
register char *tp;
bufscpy(branchno, revno);
@@ -140,7 +154,7 @@ getbranchno(revno,branchno)
tp = branchno->string;
while (--numflds)
while (*tp++ != '.')
- ;
+ continue;
*(tp-1)='\0';
}
}
@@ -159,8 +173,8 @@ int cmpnum(num1, num2)
register size_t d1, d2;
register int r;
- s1=num1==nil?"":num1;
- s2=num2==nil?"":num2;
+ s1 = num1 ? num1 : "";
+ s2 = num2 ? num2 : "";
for (;;) {
/* Give precedence to shorter one. */
@@ -170,8 +184,10 @@ int cmpnum(num1, num2)
return -1;
/* Strip leading zeros, then find number of digits. */
- while (*s1=='0') ++s1; for (d1=0; isdigit(s1[d1]); d1++) ;
- while (*s2=='0') ++s2; for (d2=0; isdigit(s2[d2]); d2++) ;
+ while (*s1=='0') ++s1;
+ while (*s2=='0') ++s2;
+ for (d1=0; isdigit(*(s1+d1)); d1++) continue;
+ for (d2=0; isdigit(*(s2+d2)); d2++) continue;
/* Do not convert to integer; it might overflow! */
if (d1 != d2)
@@ -191,7 +207,7 @@ int cmpnum(num1, num2)
int cmpnumfld(num1, num2, fld)
char const *num1, *num2;
- unsigned fld;
+ int fld;
/* Compare the two dotted numbers at field fld.
* num1 and num2 must have at least fld fields.
* fld must be positive.
@@ -205,25 +221,63 @@ int cmpnumfld(num1, num2, fld)
/* skip fld-1 fields */
while (--fld) {
while (*s1++ != '.')
- ;
+ continue;
while (*s2++ != '.')
- ;
+ continue;
}
/* Now s1 and s2 point to the beginning of the respective fields */
- while (*s1=='0') ++s1; for (d1=0; isdigit(s1[d1]); d1++) ;
- while (*s2=='0') ++s2; for (d2=0; isdigit(s2[d2]); d2++) ;
+ while (*s1=='0') ++s1; for (d1=0; isdigit(*(s1+d1)); d1++) continue;
+ while (*s2=='0') ++s2; for (d2=0; isdigit(*(s2+d2)); d2++) continue;
return d1<d2 ? -1 : d1==d2 ? memcmp(s1,s2,d1) : 1;
}
+ int
+cmpdate(d1, d2)
+ char const *d1, *d2;
+/*
+* Compare the two dates. This is just like cmpnum,
+* except that for compatibility with old versions of RCS,
+* 1900 is added to dates with two-digit years.
+*/
+{
+ char year1[5], year2[5];
+ int r = cmpnumfld(normalizeyear(d1,year1), normalizeyear(d2,year2), 1);
+
+ if (r)
+ return r;
+ else {
+ while (isdigit(*d1)) d1++; d1 += *d1=='.';
+ while (isdigit(*d2)) d2++; d2 += *d2=='.';
+ return cmpnum(d1, d2);
+ }
+}
+
+ static char const *
+normalizeyear(date, year)
+ char const *date;
+ char year[5];
+{
+ if (isdigit(date[0]) && isdigit(date[1]) && !isdigit(date[2])) {
+ year[0] = '1';
+ year[1] = '9';
+ year[2] = date[0];
+ year[3] = date[1];
+ year[4] = 0;
+ return year;
+ } else
+ return date;
+}
+
+
static void
cantfindbranch(revno, date, author, state)
char const *revno, date[datesize], *author, *state;
{
- char datebuf[datesize];
+ char datebuf[datesize + zonelenmax];
- error("No revision on branch %s has%s%s%s%s%s%s.",
+ rcserror("No revision on branch %s has%s%s%s%s%s%s.",
revno,
date ? " a date before " : "",
date ? date2str(date,datebuf) : "",
@@ -237,11 +291,11 @@ cantfindbranch(revno, date, author, state)
static void
absent(revno, field)
char const *revno;
- unsigned field;
+ int field;
{
struct buf t;
bufautobegin(&t);
- error("%s %s absent", field&1?"revision":"branch",
+ rcserror("%s %s absent", field&1?"revision":"branch",
partialno(&t,revno,field)
);
bufautoend(&t);
@@ -251,7 +305,7 @@ absent(revno, field)
int
compartial(num1, num2, length)
char const *num1, *num2;
- unsigned length;
+ int length;
/* compare the first "length" fields of two dot numbers;
the omitted field is considered to be larger than any number */
@@ -270,20 +324,21 @@ compartial(num1, num2, length)
if (!*s1) return 1;
if (!*s2) return -1;
- while (*s1=='0') ++s1; for (d1=0; isdigit(s1[d1]); d1++) ;
- while (*s2=='0') ++s2; for (d2=0; isdigit(s2[d2]); d2++) ;
+ while (*s1=='0') ++s1; for (d1=0; isdigit(*(s1+d1)); d1++) continue;
+ while (*s2=='0') ++s2; for (d2=0; isdigit(*(s2+d2)); d2++) continue;
if (d1 != d2)
return d1<d2 ? -1 : 1;
if ((r = memcmp(s1, s2, d1)))
return r;
+ if (!--length)
+ return 0;
+
s1 += d1;
s2 += d1;
if (*s1 == '.') s1++;
if (*s2 == '.') s2++;
-
- if ( --length == 0 ) return 0;
}
}
@@ -291,7 +346,7 @@ compartial(num1, num2, length)
char * partialno(rev1,rev2,length)
struct buf *rev1;
char const *rev2;
- register unsigned length;
+ register int length;
/* Function: Copies length fields of revision number rev2 into rev1.
* Return rev1's string.
*/
@@ -338,20 +393,20 @@ struct hshentry * genrevs(revno,date,author,state,store)
* revision given by revno, date, author, and state, and stores pointers
* to these deltas into a list whose starting address is given by store.
* The last delta (target delta) is returned.
- * If the proper delta could not be found, nil is returned.
+ * If the proper delta could not be found, 0 is returned.
*/
{
- unsigned length;
+ int length;
register struct hshentry * next;
int result;
char const *branchnum;
struct buf t;
- char datebuf[datesize];
+ char datebuf[datesize + zonelenmax];
bufautobegin(&t);
if (!(next = Head)) {
- error("RCS file empty");
+ rcserror("RCS file empty");
goto norev;
}
@@ -363,7 +418,7 @@ struct hshentry * genrevs(revno,date,author,state,store)
store1(&store, next);
next = next->next;
if (!next) {
- error("branch number %s too low", partialno(&t,revno,1));
+ rcserror("branch number %s too low", partialno(&t,revno,1));
goto norev;
}
}
@@ -376,19 +431,19 @@ struct hshentry * genrevs(revno,date,author,state,store)
if (length<=1){
/* pick latest one on given branch */
branchnum = next->num; /* works even for empty revno*/
- while ((next!=nil) &&
- (cmpnumfld(branchnum,next->num,1)==0) &&
- !(
- (date==nil?1:(cmpnum(date,next->date)>=0)) &&
- (author==nil?1:(strcmp(author,next->author)==0)) &&
- (state ==nil?1:(strcmp(state, next->state) ==0))
- )
- )
+ while (next &&
+ cmpnumfld(branchnum,next->num,1) == 0 &&
+ (
+ (date && cmpdate(date,next->date) < 0) ||
+ (author && strcmp(author,next->author) != 0) ||
+ (state && strcmp(state,next->state) != 0)
+ )
+ )
{
store1(&store, next);
next=next->next;
}
- if ((next==nil) ||
+ if (!next ||
(cmpnumfld(branchnum,next->num,1)!=0))/*overshot*/ {
cantfindbranch(
length ? revno : partialno(&t,branchnum,1),
@@ -398,7 +453,7 @@ struct hshentry * genrevs(revno,date,author,state,store)
} else {
store1(&store, next);
}
- *store = nil;
+ *store = 0;
return next;
}
@@ -412,8 +467,8 @@ struct hshentry * genrevs(revno,date,author,state,store)
break;
}
- if ((next==nil) || (cmpnumfld(revno,next->num,1)!=0)) {
- error("revision number %s too low", partialno(&t,revno,2));
+ if (!next || cmpnumfld(revno,next->num,1) != 0) {
+ rcserror("revision number %s too low", partialno(&t,revno,2));
goto norev;
}
if ((length>2) && (result!=0)) {
@@ -427,29 +482,33 @@ struct hshentry * genrevs(revno,date,author,state,store)
if (length>2)
return genbranch(next,revno,length,date,author,state,store);
else { /* length == 2*/
- if ((date!=nil) && (cmpnum(date,next->date)<0)){
- error("Revision %s has date %s.",
+ if (date && cmpdate(date,next->date)<0) {
+ rcserror("Revision %s has date %s.",
next->num,
date2str(next->date, datebuf)
);
- return nil;
- }
- if ((author!=nil)&&(strcmp(author,next->author)!=0)) {
- error("Revision %s has author %s.",next->num,next->author);
- return nil;
+ return 0;
+ }
+ if (author && strcmp(author,next->author)!=0) {
+ rcserror("Revision %s has author %s.",
+ next->num, next->author
+ );
+ return 0;
}
- if ((state!=nil)&&(strcmp(state,next->state)!=0)) {
- error("Revision %s has state %s.",next->num,
- next->state==nil?"<empty>":next->state);
- return nil;
+ if (state && strcmp(state,next->state)!=0) {
+ rcserror("Revision %s has state %s.",
+ next->num,
+ next->state ? next->state : "<empty>"
+ );
+ return 0;
}
- *store=nil;
+ *store = 0;
return next;
}
norev:
bufautoend(&t);
- return nil;
+ return 0;
}
@@ -459,7 +518,7 @@ struct hshentry * genrevs(revno,date,author,state,store)
genbranch(bpoint, revno, length, date, author, state, store)
struct hshentry const *bpoint;
char const *revno;
- unsigned length;
+ int length;
char const *date, *author, *state;
struct hshentries **store;
/* Function: given a branchpoint, a revision number, date, author, and state,
@@ -467,15 +526,15 @@ genbranch(bpoint, revno, length, date, author, state, store)
* from the branch point on.
* Pointers to the found deltas are stored in a list beginning with store.
* revno must be on a side branch.
- * return nil on error
+ * Return 0 on error.
*/
{
- unsigned field;
+ int field;
register struct hshentry * next, * trail;
register struct branchhead const *bhead;
int result;
struct buf t;
- char datebuf[datesize];
+ char datebuf[datesize + zonelenmax];
field = 3;
bhead = bpoint->branches;
@@ -483,9 +542,11 @@ genbranch(bpoint, revno, length, date, author, state, store)
do {
if (!bhead) {
bufautobegin(&t);
- error("no side branches present for %s", partialno(&t,revno,field-1));
+ rcserror("no side branches present for %s",
+ partialno(&t,revno,field-1)
+ );
bufautoend(&t);
- return nil;
+ return 0;
}
/*find branch head*/
@@ -494,31 +555,33 @@ genbranch(bpoint, revno, length, date, author, state, store)
bhead = bhead->nextbranch;
if (!bhead) {
bufautobegin(&t);
- error("branch number %s too high",partialno(&t,revno,field));
+ rcserror("branch number %s too high",
+ partialno(&t,revno,field)
+ );
bufautoend(&t);
- return nil;
+ return 0;
}
}
if (result<0) {
absent(revno, field);
- return nil;
+ return 0;
}
next = bhead->hsh;
if (length==field) {
/* pick latest one on that branch */
- trail=nil;
- do { if ((date==nil?1:(cmpnum(date,next->date)>=0)) &&
- (author==nil?1:(strcmp(author,next->author)==0)) &&
- (state ==nil?1:(strcmp(state, next->state) ==0))
+ trail = 0;
+ do { if ((!date || cmpdate(date,next->date)>=0) &&
+ (!author || strcmp(author,next->author)==0) &&
+ (!state || strcmp(state,next->state)==0)
) trail = next;
next=next->next;
- } while (next!=nil);
+ } while (next);
- if (trail==nil) {
+ if (!trail) {
cantfindbranch(revno, date, author, state);
- return nil;
+ return 0;
} else { /* print up to last one suitable */
next = bhead->hsh;
while (next!=trail) {
@@ -527,7 +590,7 @@ genbranch(bpoint, revno, length, date, author, state, store)
}
store1(&store, next);
}
- *store = nil;
+ *store = 0;
return next;
}
@@ -536,44 +599,49 @@ genbranch(bpoint, revno, length, date, author, state, store)
/* check low */
if (cmpnumfld(revno,next->num,field+1)<0) {
bufautobegin(&t);
- error("revision number %s too low", partialno(&t,revno,field+1));
+ rcserror("revision number %s too low",
+ partialno(&t,revno,field+1)
+ );
bufautoend(&t);
- return(nil);
+ return 0;
}
do {
store1(&store, next);
trail = next;
next = next->next;
- } while ((next!=nil) &&
- (cmpnumfld(revno,next->num,field+1) >=0));
+ } while (next && cmpnumfld(revno,next->num,field+1)>=0);
if ((length>field+1) && /*need exact hit */
(cmpnumfld(revno,trail->num,field+1) !=0)){
absent(revno, field+1);
- return(nil);
+ return 0;
}
if (length == field+1) {
- if ((date!=nil) && (cmpnum(date,trail->date)<0)){
- error("Revision %s has date %s.",
+ if (date && cmpdate(date,trail->date)<0) {
+ rcserror("Revision %s has date %s.",
trail->num,
date2str(trail->date, datebuf)
);
- return nil;
+ return 0;
}
- if ((author!=nil)&&(strcmp(author,trail->author)!=0)) {
- error("Revision %s has author %s.",trail->num,trail->author);
- return nil;
+ if (author && strcmp(author,trail->author)!=0) {
+ rcserror("Revision %s has author %s.",
+ trail->num, trail->author
+ );
+ return 0;
}
- if ((state!=nil)&&(strcmp(state,trail->state)!=0)) {
- error("Revision %s has state %s.",trail->num,
- trail->state==nil?"<empty>":trail->state);
- return nil;
+ if (state && strcmp(state,trail->state)!=0) {
+ rcserror("Revision %s has state %s.",
+ trail->num,
+ trail->state ? trail->state : "<empty>"
+ );
+ return 0;
}
}
bhead = trail->branches;
} while ((field+=2) <= length);
- * store = nil;
+ *store = 0;
return trail;
}
@@ -583,17 +651,14 @@ lookupsym(id)
char const *id;
/* Function: looks up id in the list of symbolic names starting
* with pointer SYMBOLS, and returns a pointer to the corresponding
- * revision number. Returns nil if not present.
+ * revision number. Return 0 if not present.
*/
{
register struct assoc const *next;
- next = Symbols;
- while (next!=nil) {
+ for (next = Symbols; next; next = next->nextassoc)
if (strcmp(id, next->symbol)==0)
return next->num;
- else next=next->nextassoc;
- }
- return nil;
+ return 0;
}
int expandsym(source, target)
@@ -620,13 +685,12 @@ fexpandsym(source, target, fp)
register char const *sp, *bp;
register char *tp;
char const *tlim;
- register enum tokens d;
- unsigned dots;
+ int dots;
sp = source;
bufalloc(target, 1);
tp = target->string;
- if (!sp || !*sp) { /*accept nil pointer as a legal value*/
+ if (!sp || !*sp) { /* Accept 0 pointer as a legal value. */
*tp='\0';
return true;
}
@@ -634,7 +698,7 @@ fexpandsym(source, target, fp)
if (!getoldkeys(fp))
return false;
if (!*prevrev.string) {
- error("working file lacks revision number");
+ workerror("working file lacks revision number");
return false;
}
bufscpy(target, prevrev.string);
@@ -644,72 +708,122 @@ fexpandsym(source, target, fp)
dots = 0;
for (;;) {
- switch (ctab[(unsigned char)*sp]) {
- case DIGIT:
- while (*sp=='0' && isdigit(sp[1]))
- /* skip leading zeroes */
- sp++;
- do {
- if (tlim <= tp)
- tp = bufenlarge(target, &tlim);
- } while (isdigit(*tp++ = *sp++));
- --sp;
- tp[-1] = '\0';
- break;
+ register char *p = tp;
+ size_t s = tp - target->string;
+ int id = false;
+ for (;;) {
+ switch (ctab[(unsigned char)*sp]) {
+ case IDCHAR:
+ case LETTER:
+ case Letter:
+ id = true;
+ /* fall into */
+ case DIGIT:
+ if (tlim <= p)
+ p = bufenlarge(target, &tlim);
+ *p++ = *sp++;
+ continue;
+
+ default:
+ break;
+ }
+ break;
+ }
+ if (tlim <= p)
+ p = bufenlarge(target, &tlim);
+ *p = 0;
+ tp = target->string + s;
- case LETTER:
- case Letter:
- {
- register char *p = tp;
- register size_t s = tp - target->string;
- do {
- if (tlim <= p)
- p = bufenlarge(target, &tlim);
- *p++ = *sp++;
- } while ((d=ctab[(unsigned char)*sp])==LETTER ||
- d==Letter || d==DIGIT ||
- (d==IDCHAR));
- if (tlim <= p)
- p = bufenlarge(target, &tlim);
- *p = 0;
- tp = target->string + s;
- }
+ if (id) {
bp = lookupsym(tp);
- if (bp==nil) {
- error("Symbolic number %s is undefined.", tp);
+ if (!bp) {
+ rcserror("Symbolic name `%s' is undefined.",tp);
return false;
}
- do {
- if (tlim <= tp)
- tp = bufenlarge(target, &tlim);
- } while ((*tp++ = *bp++));
- break;
+ } else {
+ /* skip leading zeros */
+ for (bp = tp; *bp=='0' && isdigit(bp[1]); bp++)
+ continue;
+
+ if (!*bp)
+ if (s || *sp!='.')
+ break;
+ else {
+ /* Insert default branch before initial `.'. */
+ char const *b;
+ if (Dbranch)
+ b = Dbranch;
+ else if (Head)
+ b = Head->num;
+ else
+ break;
+ getbranchno(b, target);
+ bp = tp = target->string;
+ tlim = tp + target->size;
+ }
+ }
+
+ while ((*tp++ = *bp++))
+ if (tlim <= tp)
+ tp = bufenlarge(target, &tlim);
- default:
- goto improper;
- }
switch (*sp++) {
- case '\0': return true;
- case '.': break;
- default: goto improper;
- }
- if (!*sp) {
- if (dots & 1)
- goto improper;
- if (!(bp = branchtip(target->string)))
- return false;
- bufscpy(target, bp);
+ case '\0':
return true;
+
+ case '.':
+ if (!*sp) {
+ if (dots & 1)
+ break;
+ if (!(bp = branchtip(target->string)))
+ return false;
+ bufscpy(target, bp);
+ return true;
+ }
+ ++dots;
+ tp[-1] = '.';
+ continue;
}
- ++dots;
- tp[-1] = '.';
+ break;
}
- improper:
- error("improper revision number: %s", source);
+ rcserror("improper revision number: %s", source);
return false;
}
+ char const *
+namedrev(name, delta)
+ char const *name;
+ struct hshentry *delta;
+/* Yield NAME if it names DELTA, 0 otherwise. */
+{
+ if (name) {
+ char const *id = 0, *p, *val;
+ for (p = name; ; p++)
+ switch (ctab[(unsigned char)*p]) {
+ case IDCHAR:
+ case LETTER:
+ case Letter:
+ id = name;
+ break;
+
+ case DIGIT:
+ break;
+
+ case UNKN:
+ if (!*p && id &&
+ (val = lookupsym(id)) &&
+ strcmp(val, delta->num) == 0
+ )
+ return id;
+ /* fall into */
+ default:
+ return 0;
+ }
+ }
+ return 0;
+}
+
static char const *
branchtip(branch)
char const *branch;
@@ -731,6 +845,11 @@ tiprev()
#ifdef REVTEST
+/*
+* Test the routines that generate a sequence of delta numbers
+* needed to regenerate a given delta.
+*/
+
char const cmdid[] = "revtest";
int
@@ -775,9 +894,9 @@ int argc; char * argv[];
gets(author); aprintf(stderr,"%s; ",author);
aprintf(stderr,"State: ");
gets(state); aprintf(stderr, "%s;\n", state);
- target = genrevs(numricrevno.string, *date?date:(char *)nil, *author?author:(char *)nil,
- *state?state:(char*)nil, &gendeltas);
- if (target!=nil) {
+ target = genrevs(numricrevno.string, *date?date:(char *)0, *author?author:(char *)0,
+ *state?state:(char*)0, &gendeltas);
+ if (target) {
while (gendeltas) {
aprintf(stderr,"%s\n",gendeltas->first->num);
gendeltas = gendeltas->next;
@@ -788,6 +907,6 @@ int argc; char * argv[];
exitmain(EXIT_SUCCESS);
}
-exiting void exiterr() { _exit(EXIT_FAILURE); }
+void exiterr() { _exit(EXIT_FAILURE); }
#endif
diff --git a/gnu/usr.bin/rcs/lib/rcssyn.c b/gnu/usr.bin/rcs/lib/rcssyn.c
index 10b6147..0663208 100644
--- a/gnu/usr.bin/rcs/lib/rcssyn.c
+++ b/gnu/usr.bin/rcs/lib/rcssyn.c
@@ -1,16 +1,15 @@
-/*
- * RCS file input
- */
-/*********************************************************************************
+/* RCS file syntactic analysis */
+
+/******************************************************************************
* Syntax Analysis.
* Keyword table
* Testprogram: define SYNTEST
* Compatibility with Release 2: define COMPAT2=1
- *********************************************************************************
+ ******************************************************************************
*/
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -26,8 +25,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -35,10 +35,31 @@ Report problems and direct all questions to:
*/
-
-/* $Log: rcssyn.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:12 jkh
- * Updated GNU utilities
+/*
+ * $Log: rcssyn.c,v $
+ * Revision 5.15 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.14 1995/06/01 16:23:43 eggert
+ * (expand_names): Add "b" for -kb.
+ * (getdelta): Don't strip leading "19" from MKS RCS dates; see cmpdate.
+ *
+ * Revision 5.13 1994/03/20 04:52:58 eggert
+ * Remove lint.
+ *
+ * Revision 5.12 1993/11/03 17:42:27 eggert
+ * Parse MKS RCS dates; ignore \r in diff control lines.
+ * Don't discard ignored phrases. Improve quality of diagnostics.
+ *
+ * Revision 5.11 1992/07/28 16:12:44 eggert
+ * Avoid `unsigned'. Statement macro names now end in _.
+ *
+ * Revision 5.10 1992/01/24 18:44:19 eggert
+ * Move put routines to rcsgen.c.
+ *
+ * Revision 5.9 1992/01/06 02:42:34 eggert
+ * ULONG_MAX/10 -> ULONG_MAX_OVER_10
+ * while (E) ; -> while (E) continue;
*
* Revision 5.8 1991/08/19 03:13:55 eggert
* Tune.
@@ -130,54 +151,55 @@ Report problems and direct all questions to:
* generates files of release 3 format. Need not be defined if no
* old RCS files generated with release 2 exist.
*/
-/* version SYNTEST inputs a RCS file and then prints out its internal
- * data structures.
-*/
#include "rcsbase.h"
-libId(synId, "$Id: rcssyn.c,v 1.1.1.1 1993/06/18 04:22:12 jkh Exp $")
+libId(synId, "$Id: rcssyn.c,v 5.15 1995/06/16 06:19:24 eggert Exp $")
-/* forward */
static char const *getkeyval P((char const*,enum tokens,int));
+static int getdelta P((void));
static int strn2expmode P((char const*,size_t));
+static struct hshentry *getdnum P((void));
+static void badDiffOutput P((char const*)) exiting;
+static void diffLineNumberTooLarge P((char const*)) exiting;
+static void getsemi P((char const*));
/* keyword table */
char const
- Kdesc[] = "desc",
- Klog[] = "log",
- Ktext[] = "text";
-
-static char const
Kaccess[] = "access",
Kauthor[] = "author",
Kbranch[] = "branch",
- K_branches[]= "branches",
Kcomment[] = "comment",
Kdate[] = "date",
+ Kdesc[] = "desc",
Kexpand[] = "expand",
Khead[] = "head",
Klocks[] = "locks",
+ Klog[] = "log",
Knext[] = "next",
Kstate[] = "state",
Kstrict[] = "strict",
+ Ksymbols[] = "symbols",
+ Ktext[] = "text";
+
+static char const
#if COMPAT2
Ksuffix[] = "suffix",
#endif
- Ksymbols[] = "symbols";
+ K_branches[]= "branches";
static struct buf Commleader;
-static struct cbuf Ignored;
struct cbuf Comment;
+struct cbuf Ignored;
struct access * AccessList;
struct assoc * Symbols;
-struct lock * Locks;
+struct rcslock *Locks;
int Expand;
int StrictLocks;
struct hshentry * Head;
char const * Dbranch;
-unsigned TotalDeltas;
+int TotalDeltas;
static void
@@ -207,11 +229,11 @@ getadmin()
register char const *id;
struct access * newaccess;
struct assoc * newassoc;
- struct lock * newlock;
+ struct rcslock *newlock;
struct hshentry * delta;
struct access **LastAccess;
struct assoc **LastSymbol;
- struct lock **LastLock;
+ struct rcslock **LastLock;
struct buf b;
struct cbuf cb;
@@ -221,7 +243,7 @@ getadmin()
Head = getdnum();
getsemi(Khead);
- Dbranch = nil;
+ Dbranch = 0;
if (getkeyopt(Kbranch)) {
if ((delta = getnum()))
Dbranch = delta->num;
@@ -243,18 +265,18 @@ getadmin()
getkey(Kaccess);
LastAccess = &AccessList;
- while (id=getid()) {
+ while ((id = getid())) {
newaccess = ftalloc(struct access);
newaccess->login = id;
*LastAccess = newaccess;
LastAccess = &newaccess->nextaccess;
}
- *LastAccess = nil;
+ *LastAccess = 0;
getsemi(Kaccess);
getkey(Ksymbols);
LastSymbol = &Symbols;
- while (id = getid()) {
+ while ((id = getid())) {
if (!getlex(COLON))
fatserror("missing ':' in symbolic name definition");
if (!(delta=getnum())) {
@@ -267,31 +289,31 @@ getadmin()
LastSymbol = &newassoc->nextassoc;
}
}
- *LastSymbol = nil;
+ *LastSymbol = 0;
getsemi(Ksymbols);
getkey(Klocks);
LastLock = &Locks;
- while (id = getid()) {
+ while ((id = getid())) {
if (!getlex(COLON))
fatserror("missing ':' in lock");
if (!(delta=getdnum())) {
fatserror("missing number in lock");
} else { /*add new pair to lock list*/
- newlock = ftalloc(struct lock);
+ newlock = ftalloc(struct rcslock);
newlock->login=id;
newlock->delta=delta;
*LastLock = newlock;
LastLock = &newlock->nextlock;
}
}
- *LastLock = nil;
+ *LastLock = 0;
getsemi(Klocks);
if ((StrictLocks = getkeyopt(Kstrict)))
getsemi(Kstrict);
- Comment.size = 0;
+ clear_buf(&Comment);
if (getkeyopt(Kcomment)) {
if (nexttok==STRING) {
Comment = savestring(&Commleader);
@@ -319,7 +341,7 @@ getadmin()
char const *const expand_names[] = {
/* These must agree with *_EXPAND in rcsbase.h. */
- "kv","kvl","k","v","o",
+ "kv", "kvl", "k", "v", "o", "b",
0
};
@@ -346,20 +368,30 @@ strn2expmode(s, n)
void
-ignorephrase()
-/* Ignore a phrase introduced by a later version of RCS. */
+ignorephrases(key)
+ const char *key;
+/*
+* Ignore a series of phrases that do not start with KEY.
+* Stop when the next phrase starts with a token that is not an identifier,
+* or is KEY.
+*/
{
- warnignore();
- hshenter=false;
for (;;) {
- switch (nexttok) {
- case SEMI: hshenter=true; nextlex(); return;
- case ID:
- case NUM: ffree1(NextString); break;
- case STRING: readstring(); break;
- default: break;
- }
- nextlex();
+ nextlex();
+ if (nexttok != ID || strcmp(NextString,key) == 0)
+ break;
+ warnignore();
+ hshenter=false;
+ for (;; nextlex()) {
+ switch (nexttok) {
+ case SEMI: hshenter=true; break;
+ case ID:
+ case NUM: ffree1(NextString); continue;
+ case STRING: readstring(); continue;
+ default: continue;
+ }
+ break;
+ }
}
}
@@ -377,7 +409,7 @@ getdelta()
return false;
hshenter = false; /*Don't enter dates into hashtable*/
- Delta->date = getkeyval(Kdate, NUM, false);
+ Delta->date = getkeyval(Kdate, NUM, false);
hshenter=true; /*reset hshenter for revision numbers.*/
Delta->author = getkeyval(Kauthor, ID, false);
@@ -392,13 +424,13 @@ getdelta()
*LastBranch = NewBranch;
LastBranch = &NewBranch->nextbranch;
}
- *LastBranch = nil;
+ *LastBranch = 0;
getsemi(K_branches);
getkey(Knext);
Delta->next = num = getdnum();
getsemi(Knext);
- Delta->lockedby = nil;
+ Delta->lockedby = 0;
Delta->log.string = 0;
Delta->selector = true;
Delta->ig = getphrases(Kdesc);
@@ -413,9 +445,10 @@ gettree()
* updates the lockedby fields.
*/
{
- struct lock const *currlock;
+ struct rcslock const *currlock;
- while (getdelta());
+ while (getdelta())
+ continue;
currlock=Locks;
while (currlock) {
currlock->delta->lockedby = currlock->login;
@@ -456,7 +489,7 @@ getkeyval(keyword, token, optional)
* the actual character string of <id> or <num> is returned.
*/
{
- register char const *val = nil;
+ register char const *val = 0;
getkey(keyword);
if (nexttok==token) {
@@ -471,220 +504,10 @@ getkeyval(keyword, token, optional)
}
-
-
void
-putadmin(fout)
-register FILE * fout;
-/* Function: Print the <admin> node read with getadmin() to file fout.
- * Assumption: Variables AccessList, Symbols, Locks, StrictLocks,
- * and Head have been set.
- */
-{
- struct assoc const *curassoc;
- struct lock const *curlock;
- struct access const *curaccess;
-
- aprintf(fout, "%s\t%s;\n", Khead, Head?Head->num:"");
- if (Dbranch && VERSION(4)<=RCSversion)
- aprintf(fout, "%s\t%s;\n", Kbranch, Dbranch);
-
- aputs(Kaccess, fout);
- curaccess = AccessList;
- while (curaccess) {
- aprintf(fout, "\n\t%s", curaccess->login);
- curaccess = curaccess->nextaccess;
- }
- aprintf(fout, ";\n%s", Ksymbols);
- curassoc = Symbols;
- while (curassoc) {
- aprintf(fout, "\n\t%s:%s", curassoc->symbol, curassoc->num);
- curassoc = curassoc->nextassoc;
- }
- aprintf(fout, ";\n%s", Klocks);
- curlock = Locks;
- while (curlock) {
- aprintf(fout, "\n\t%s:%s", curlock->login, curlock->delta->num);
- curlock = curlock->nextlock;
- }
- if (StrictLocks) aprintf(fout, "; %s", Kstrict);
- aprintf(fout, ";\n");
- if (Comment.size) {
- aprintf(fout, "%s\t", Kcomment);
- putstring(fout, true, Comment, false);
- aprintf(fout, ";\n");
- }
- if (Expand != KEYVAL_EXPAND)
- aprintf(fout, "%s\t%c%s%c;\n",
- Kexpand, SDELIM, expand_names[Expand], SDELIM
- );
- awrite(Ignored.string, Ignored.size, fout);
- aputc('\n', fout);
-}
-
-
-
-
- static void
-putdelta(node,fout)
-register struct hshentry const *node;
-register FILE * fout;
-/* Function: prints a <delta> node to fout;
- */
-{
- struct branchhead const *nextbranch;
-
- if (node == nil) return;
-
- aprintf(fout, "\n%s\n%s\t%s;\t%s %s;\t%s %s;\nbranches",
- node->num,
- Kdate, node->date,
- Kauthor, node->author,
- Kstate, node->state?node->state:""
- );
- nextbranch = node->branches;
- while (nextbranch) {
- aprintf(fout, "\n\t%s", nextbranch->hsh->num);
- nextbranch = nextbranch->nextbranch;
- }
-
- aprintf(fout, ";\n%s\t%s;\n", Knext, node->next?node->next->num:"");
- awrite(node->ig.string, node->ig.size, fout);
-}
-
-
-
-
- void
-puttree(root,fout)
-struct hshentry const *root;
-register FILE * fout;
-/* Function: prints the delta tree in preorder to fout, starting with root.
- */
-{
- struct branchhead const *nextbranch;
-
- if (root==nil) return;
-
- if (root->selector)
- putdelta(root,fout);
-
- puttree(root->next,fout);
-
- nextbranch = root->branches;
- while (nextbranch) {
- puttree(nextbranch->hsh,fout);
- nextbranch = nextbranch->nextbranch;
- }
-}
-
-
- static exiting void
unexpected_EOF()
{
- faterror("unexpected EOF in diff output");
-}
-
-int putdtext(num,log,srcfilename,fout,diffmt)
- char const *num, *srcfilename;
- struct cbuf log;
- FILE *fout;
- int diffmt;
-/* Function: write a deltatext-node to fout.
- * num points to the deltanumber, log to the logmessage, and
- * sourcefile contains the text. Doubles up all SDELIMs in both the
- * log and the text; Makes sure the log message ends in \n.
- * returns false on error.
- * If diffmt is true, also checks that text is valid diff -n output.
- */
-{
- RILE *fin;
- int result;
- if (!(fin = Iopen(srcfilename, "r", (struct stat*)0))) {
- eerror(srcfilename);
- return false;
- }
- result = putdftext(num,log,fin,fout,diffmt);
- Ifclose(fin);
- return result;
-}
-
- void
-putstring(out, delim, s, log)
- register FILE *out;
- struct cbuf s;
- int delim, log;
-/*
- * Output to OUT one SDELIM if DELIM, then the string S with SDELIMs doubled.
- * If LOG is set then S is a log string; append a newline if S is nonempty.
- */
-{
- register char const *sp;
- register size_t ss;
-
- if (delim)
- aputc(SDELIM, out);
- sp = s.string;
- for (ss = s.size; ss; --ss) {
- if (*sp == SDELIM)
- aputc(SDELIM, out);
- aputc(*sp++, out);
- }
- if (s.size && log)
- aputc('\n', out);
- aputc(SDELIM, out);
-}
-
- int
-putdftext(num,log,finfile,foutfile,diffmt)
- char const *num;
- struct cbuf log;
- RILE *finfile;
- FILE *foutfile;
- int diffmt;
-/* like putdtext(), except the source file is already open */
-{
- declarecache;
- register FILE *fout;
- register int c;
- register RILE *fin;
- int ed;
- struct diffcmd dc;
-
- fout = foutfile;
- aprintf(fout,DELNUMFORM,num,Klog);
- /* put log */
- putstring(fout, true, log, true);
- /* put text */
- aprintf(fout, "\n%s\n%c", Ktext, SDELIM);
- fin = finfile;
- setupcache(fin);
- if (!diffmt) {
- /* Copy the file */
- cache(fin);
- for (;;) {
- cachegeteof(c, break;);
- if (c==SDELIM) aputc(SDELIM,fout); /*double up SDELIM*/
- aputc(c,fout);
- }
- } else {
- initdiffcmd(&dc);
- while (0 <= (ed = getdiffcmd(fin,false,fout,&dc)))
- if (ed) {
- cache(fin);
- while (dc.nlines--)
- do {
- cachegeteof(c, { if (!dc.nlines) goto OK_EOF; unexpected_EOF(); });
- if (c == SDELIM)
- aputc(SDELIM,fout);
- aputc(c,fout);
- } while (c != '\n');
- uncache(fin);
- }
- }
- OK_EOF:
- aprintf(fout, "%c\n", SDELIM);
- return true;
+ rcsfaterror("unexpected EOF in diff output");
}
void
@@ -696,18 +519,18 @@ initdiffcmd(dc)
dc->dafter = 0;
}
- static exiting void
+ static void
badDiffOutput(buf)
char const *buf;
{
- faterror("bad diff output line: %s", buf);
+ rcsfaterror("bad diff output line: %s", buf);
}
- static exiting void
+ static void
diffLineNumberTooLarge(buf)
char const *buf;
{
- faterror("diff line number too large: %s", buf);
+ rcsfaterror("diff line number too large: %s", buf);
}
int
@@ -729,16 +552,16 @@ getdiffcmd(finfile, delimiter, foutfile, dc)
register FILE *fout;
register char *p;
register RILE *fin;
- unsigned long line1, nlines, t;
+ long line1, nlines, t;
char buf[BUFSIZ];
fin = finfile;
fout = foutfile;
setupcache(fin); cache(fin);
- cachegeteof(c, { if (delimiter) unexpected_EOF(); return -1; } );
+ cachegeteof_(c, { if (delimiter) unexpected_EOF(); return -1; } )
if (delimiter) {
if (c==SDELIM) {
- cacheget(c);
+ cacheget_(c)
if (c==SDELIM) {
buf[0] = c;
buf[1] = 0;
@@ -754,23 +577,22 @@ getdiffcmd(finfile, delimiter, foutfile, dc)
p = buf;
do {
if (buf+BUFSIZ-2 <= p) {
- faterror("diff output command line too long");
+ rcsfaterror("diff output command line too long");
}
*p++ = c;
- cachegeteof(c, unexpected_EOF();) ;
+ cachegeteof_(c, unexpected_EOF();)
} while (c != '\n');
uncache(fin);
if (delimiter)
++rcsline;
*p = '\0';
for (p = buf+1; (c = *p++) == ' '; )
- ;
+ continue;
line1 = 0;
while (isdigit(c)) {
- t = line1 * 10;
if (
- ULONG_MAX/10 < line1 ||
- (line1 = t + (c - '0')) < t
+ LONG_MAX/10 < line1 ||
+ (t = line1 * 10, (line1 = t + (c - '0')) < t)
)
diffLineNumberTooLarge(buf);
c = *p++;
@@ -779,14 +601,15 @@ getdiffcmd(finfile, delimiter, foutfile, dc)
c = *p++;
nlines = 0;
while (isdigit(c)) {
- t = nlines * 10;
if (
- ULONG_MAX/10 < nlines ||
- (nlines = t + (c - '0')) < t
+ LONG_MAX/10 < nlines ||
+ (t = nlines * 10, (nlines = t + (c - '0')) < t)
)
diffLineNumberTooLarge(buf);
c = *p++;
}
+ if (c == '\r')
+ c = *p++;
if (c || !nlines) {
badDiffOutput(buf);
}
@@ -795,13 +618,13 @@ getdiffcmd(finfile, delimiter, foutfile, dc)
switch (buf[0]) {
case 'a':
if (line1 < dc->adprev) {
- faterror("backward insertion in diff output: %s", buf);
+ rcsfaterror("backward insertion in diff output: %s", buf);
}
dc->adprev = line1 + 1;
break;
case 'd':
if (line1 < dc->adprev || line1 < dc->dafter) {
- faterror("backward deletion in diff output: %s", buf);
+ rcsfaterror("backward deletion in diff output: %s", buf);
}
dc->adprev = line1;
dc->dafter = line1 + nlines;
@@ -821,6 +644,8 @@ getdiffcmd(finfile, delimiter, foutfile, dc)
#ifdef SYNTEST
+/* Input an RCS file and print its internal data structures. */
+
char const cmdid[] = "syntest";
int
@@ -837,10 +662,10 @@ int argc; char * argv[];
}
Lexinit();
getadmin();
- putadmin(stdout);
+ fdlock = STDOUT_FILENO;
+ putadmin();
gettree();
- puttree(Head,stdout);
getdesc(true);
@@ -852,9 +677,6 @@ int argc; char * argv[];
exitmain(EXIT_SUCCESS);
}
-
-exiting void exiterr() { _exit(EXIT_FAILURE); }
-
+void exiterr() { _exit(EXIT_FAILURE); }
#endif
-
diff --git a/gnu/usr.bin/rcs/lib/rcsutil.c b/gnu/usr.bin/rcs/lib/rcsutil.c
index 55140c2..1177592 100644
--- a/gnu/usr.bin/rcs/lib/rcsutil.c
+++ b/gnu/usr.bin/rcs/lib/rcsutil.c
@@ -1,9 +1,7 @@
-/*
- * RCS utilities
- */
+/* RCS utility functions */
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -19,8 +17,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -31,9 +30,58 @@ Report problems and direct all questions to:
-/* $Log: rcsutil.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
- * Updated GNU utilities
+/*
+ * $Log: rcsutil.c,v $
+ * Revision 5.20 1995/06/16 06:19:24 eggert
+ * (catchsig): Remove `return'.
+ * Update FSF address.
+ *
+ * Revision 5.19 1995/06/02 18:19:00 eggert
+ * (catchsigaction): New name for `catchsig', for sa_sigaction signature.
+ * Use nRCS even if !has_psiginfo, to remove unused variable warning.
+ * (setup_catchsig): Use sa_sigaction only if has_sa_sigaction.
+ * Use ENOTSUP only if defined.
+ *
+ * Revision 5.18 1995/06/01 16:23:43 eggert
+ * (catchsig, restoreints, setup_catchsig): Use SA_SIGINFO, not has_psiginfo,
+ * to determine whether to use SA_SIGINFO feature,
+ * but also check at runtime whether the feature works.
+ * (catchsig): If an mmap_signal occurs, report the affected file name.
+ * (unsupported_SA_SIGINFO, accessName): New variables.
+ * (setup_catchsig): If using SA_SIGINFO, use sa_sigaction, not sa_handler.
+ * If SA_SIGINFO fails, fall back on sa_handler method.
+ *
+ * (readAccessFilenameBuffer, dupSafer, fdSafer, fopenSafer): New functions.
+ * (concatenate): Remove.
+ *
+ * (runv): Work around bad_wait_if_SIGCHLD_ignored bug.
+ * Remove reference to OPEN_O_WORK.
+ *
+ * Revision 5.17 1994/03/20 04:52:58 eggert
+ * Specify subprocess input via file descriptor, not file name.
+ * Avoid messing with I/O buffers in the child process.
+ * Define dup in terms of F_DUPFD if it exists.
+ * Move setmtime to rcsedit.c. Remove lint.
+ *
+ * Revision 5.16 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits.
+ *
+ * Revision 5.15 1993/11/03 17:42:27 eggert
+ * Use psiginfo and setreuid if available. Move date2str to maketime.c.
+ *
+ * Revision 5.14 1992/07/28 16:12:44 eggert
+ * Add -V. has_sigaction overrides sig_zaps_handler. Fix -M bug.
+ * Add mmap_signal, which minimizes signal handling for non-mmap hosts.
+ *
+ * Revision 5.13 1992/02/17 23:02:28 eggert
+ * Work around NFS mmap SIGBUS problem. Add -T support.
+ *
+ * Revision 5.12 1992/01/24 18:44:19 eggert
+ * Work around NFS mmap bug that leads to SIGBUS core dumps. lint -> RCS_lint
+ *
+ * Revision 5.11 1992/01/06 02:42:34 eggert
+ * O_BINARY -> OPEN_O_WORK
+ * while (E) ; -> while (E) continue;
*
* Revision 5.10 1991/10/07 17:32:46 eggert
* Support piece tables even if !has_mmap.
@@ -139,7 +187,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(utilId, "$Id: rcsutil.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp $")
+libId(utilId, "$Id: rcsutil.c,v 5.20 1995/06/16 06:19:24 eggert Exp $")
#if !has_memcmp
int
@@ -173,7 +221,7 @@ memcpy(s1, s2, n)
}
#endif
-#if lint
+#if RCS_lint
malloc_type lintalloc;
#endif
@@ -190,6 +238,7 @@ struct alloclist {
static struct alloclist *alloced;
+ static malloc_type okalloc P((malloc_type));
static malloc_type
okalloc(p)
malloc_type p;
@@ -245,7 +294,7 @@ ffree()
tfree(p->alloc);
tfree(p);
}
- alloced = nil;
+ alloced = 0;
}
void
@@ -300,16 +349,18 @@ getusername(suspicious)
/* Prefer getenv() unless suspicious; it's much faster. */
# if getlogin_is_secure
(suspicious
- ||
- !(name = cgetenv("LOGNAME"))
- && !(name = cgetenv("USER")))
+ || (
+ !(name = cgetenv("LOGNAME"))
+ && !(name = cgetenv("USER"))
+ ))
&& !(name = getlogin())
# else
suspicious
- ||
+ || (
!(name = cgetenv("LOGNAME"))
&& !(name = cgetenv("USER"))
&& !(name = getlogin())
+ )
# endif
) {
#if has_getuid && has_getpwuid
@@ -323,7 +374,7 @@ getusername(suspicious)
#if has_setuid
faterror("setuid not supported");
#else
- faterror("Who are you? Please set LOGNAME.");
+ faterror("Who are you? Please setenv LOGNAME.");
#endif
#endif
}
@@ -346,65 +397,191 @@ getusername(suspicious)
*/
static sig_atomic_t volatile heldsignal, holdlevel;
+#ifdef SA_SIGINFO
+ static int unsupported_SA_SIGINFO;
+ static siginfo_t bufsiginfo;
+ static siginfo_t *volatile heldsiginfo;
+#endif
- static signal_type
-catchsig(s)
- int s;
-{
- char const *sname;
- char buf[BUFSIZ];
-#if sig_zaps_handler
- /* If a signal arrives before we reset the signal handler, we lose. */
- VOID signal(s, SIG_IGN);
-#endif
- if (holdlevel) {
- heldsignal = s;
- return;
- }
- ignoreints();
- setrid();
- if (!quietflag) {
- sname = nil;
-#if has_sys_siglist && defined(NSIG)
- if ((unsigned)s < NSIG) {
-# ifndef sys_siglist
- extern char const *sys_siglist[];
-# endif
- sname = sys_siglist[s];
- }
+#if has_NFS && has_mmap && large_memory && mmap_signal
+ static char const *accessName;
+
+ void
+ readAccessFilenameBuffer(filename, p)
+ char const *filename;
+ unsigned char const *p;
+ {
+ unsigned char volatile t;
+ accessName = filename;
+ t = *p;
+ accessName = 0;
+ }
#else
- switch (s) {
-#ifdef SIGHUP
- case SIGHUP: sname = "Hangup"; break;
+# define accessName ((char const *) 0)
#endif
-#ifdef SIGINT
+
+
+#if !has_psignal
+
+# define psignal my_psignal
+ static void my_psignal P((int,char const*));
+ static void
+my_psignal(sig, s)
+ int sig;
+ char const *s;
+{
+ char const *sname = "Unknown signal";
+# if has_sys_siglist && defined(NSIG)
+ if ((unsigned)sig < NSIG)
+ sname = sys_siglist[sig];
+# else
+ switch (sig) {
+# ifdef SIGHUP
+ case SIGHUP: sname = "Hangup"; break;
+# endif
+# ifdef SIGINT
case SIGINT: sname = "Interrupt"; break;
-#endif
-#ifdef SIGPIPE
+# endif
+# ifdef SIGPIPE
case SIGPIPE: sname = "Broken pipe"; break;
-#endif
-#ifdef SIGQUIT
+# endif
+# ifdef SIGQUIT
case SIGQUIT: sname = "Quit"; break;
-#endif
-#ifdef SIGTERM
+# endif
+# ifdef SIGTERM
case SIGTERM: sname = "Terminated"; break;
-#endif
-#ifdef SIGXCPU
+# endif
+# ifdef SIGXCPU
case SIGXCPU: sname = "Cputime limit exceeded"; break;
-#endif
-#ifdef SIGXFSZ
+# endif
+# ifdef SIGXFSZ
case SIGXFSZ: sname = "Filesize limit exceeded"; break;
-#endif
+# endif
+# if has_mmap && large_memory
+# if defined(SIGBUS) && mmap_signal==SIGBUS
+ case SIGBUS: sname = "Bus error"; break;
+# endif
+# if defined(SIGSEGV) && mmap_signal==SIGSEGV
+ case SIGSEGV: sname = "Segmentation fault"; break;
+# endif
+# endif
}
+# endif
+
+ /* Avoid calling sprintf etc., in case they're not reentrant. */
+ {
+ char const *p;
+ char buf[BUFSIZ], *b = buf;
+ for (p = s; *p; *b++ = *p++)
+ continue;
+ *b++ = ':';
+ *b++ = ' ';
+ for (p = sname; *p; *b++ = *p++)
+ continue;
+ *b++ = '\n';
+ VOID write(STDERR_FILENO, buf, b - buf);
+ }
+}
#endif
- if (sname)
- VOID sprintf(buf, "\nRCS: %s. Cleaning up.\n", sname);
- else
- VOID sprintf(buf, "\nRCS: Signal %d. Cleaning up.\n", s);
- VOID write(STDERR_FILENO, buf, strlen(buf));
+
+static signal_type catchsig P((int));
+#ifdef SA_SIGINFO
+ static signal_type catchsigaction P((int,siginfo_t*,void*));
+#endif
+
+ static signal_type
+catchsig(s)
+ int s;
+#ifdef SA_SIGINFO
+{
+ catchsigaction(s, (siginfo_t *)0, (void *)0);
+}
+ static signal_type
+catchsigaction(s, i, c)
+ int s;
+ siginfo_t *i;
+ void *c;
+#endif
+{
+# if sig_zaps_handler
+ /* If a signal arrives before we reset the handler, we lose. */
+ VOID signal(s, SIG_IGN);
+# endif
+
+# ifdef SA_SIGINFO
+ if (!unsupported_SA_SIGINFO)
+ i = 0;
+# endif
+
+ if (holdlevel) {
+ heldsignal = s;
+# ifdef SA_SIGINFO
+ if (i) {
+ bufsiginfo = *i;
+ heldsiginfo = &bufsiginfo;
+ }
+# endif
+ return;
+ }
+
+ ignoreints();
+ setrid();
+ if (!quietflag) {
+ /* Avoid calling sprintf etc., in case they're not reentrant. */
+ char const *p;
+ char buf[BUFSIZ], *b = buf;
+
+ if ( ! (
+# if has_mmap && large_memory && mmap_signal
+ /* Check whether this signal was planned. */
+ s == mmap_signal && accessName
+# else
+ 0
+# endif
+ )) {
+ char const *nRCS = "\nRCS";
+# if defined(SA_SIGINFO) && has_si_errno && has_mmap && large_memory && mmap_signal
+ if (s == mmap_signal && i && i->si_errno) {
+ errno = i->si_errno;
+ perror(nRCS++);
+ }
+# endif
+# if defined(SA_SIGINFO) && has_psiginfo
+ if (i)
+ psiginfo(i, nRCS);
+ else
+ psignal(s, nRCS);
+# else
+ psignal(s, nRCS);
+# endif
}
- exiterr();
+
+ for (p = "RCS: "; *p; *b++ = *p++)
+ continue;
+# if has_mmap && large_memory && mmap_signal
+ if (s == mmap_signal) {
+ p = accessName;
+ if (!p)
+ p = "Was a file changed by some other process? ";
+ else {
+ char const *p1;
+ for (p1 = p; *p1; p1++)
+ continue;
+ VOID write(STDERR_FILENO, buf, b - buf);
+ VOID write(STDERR_FILENO, p, p1 - p);
+ b = buf;
+ p = ": Permission denied. ";
+ }
+ while (*p)
+ *b++ = *p++;
+ }
+# endif
+ for (p = "Cleaning up.\n"; *p; *b++ = *p++)
+ continue;
+ VOID write(STDERR_FILENO, buf, b - buf);
+ }
+ exiterr();
}
void
@@ -417,62 +594,62 @@ ignoreints()
restoreints()
{
if (!--holdlevel && heldsignal)
+# ifdef SA_SIGINFO
+ VOID catchsigaction(heldsignal, heldsiginfo, (void *)0);
+# else
VOID catchsig(heldsignal);
+# endif
}
-static int const sig[] = {
-#ifdef SIGHUP
- SIGHUP,
-#endif
-#ifdef SIGINT
- SIGINT,
-#endif
-#ifdef SIGPIPE
- SIGPIPE,
-#endif
-#ifdef SIGQUIT
- SIGQUIT,
-#endif
-#ifdef SIGTERM
- SIGTERM,
-#endif
-#ifdef SIGXCPU
- SIGXCPU,
-#endif
-#ifdef SIGXFSZ
- SIGXFSZ,
-#endif
-};
-#define SIGS (sizeof(sig)/sizeof(*sig))
-
+static void setup_catchsig P((int const*,int));
#if has_sigaction
+ static void check_sig P((int));
static void
check_sig(r)
int r;
{
if (r != 0)
- efaterror("signal");
+ efaterror("signal handling");
}
static void
- setup_catchsig()
+ setup_catchsig(sig, sigs)
+ int const *sig;
+ int sigs;
{
- register int i;
- sigset_t blocked;
+ register int i, j;
struct sigaction act;
- check_sig(sigemptyset(&blocked));
- for (i=SIGS; 0<=--i; )
- check_sig(sigaddset(&blocked, sig[i]));
- for (i=SIGS; 0<=--i; ) {
- check_sig(sigaction(sig[i], (struct sigaction*)nil, &act));
+ for (i=sigs; 0<=--i; ) {
+ check_sig(sigaction(sig[i], (struct sigaction*)0, &act));
if (act.sa_handler != SIG_IGN) {
- act.sa_handler = catchsig;
- act.sa_mask = blocked;
- check_sig(sigaction(sig[i], &act, (struct sigaction*)nil));
+ act.sa_handler = catchsig;
+# ifdef SA_SIGINFO
+ if (!unsupported_SA_SIGINFO) {
+# if has_sa_sigaction
+ act.sa_sigaction = catchsigaction;
+# else
+ act.sa_handler = catchsigaction;
+# endif
+ act.sa_flags |= SA_SIGINFO;
+ }
+# endif
+ for (j=sigs; 0<=--j; )
+ check_sig(sigaddset(&act.sa_mask, sig[j]));
+ if (sigaction(sig[i], &act, (struct sigaction*)0) != 0) {
+# if defined(SA_SIGINFO) && defined(ENOTSUP)
+ if (errno == ENOTSUP && !unsupported_SA_SIGINFO) {
+ /* Turn off use of SA_SIGINFO and try again. */
+ unsupported_SA_SIGINFO = 1;
+ i++;
+ continue;
+ }
+# endif
+ check_sig(-1);
+ }
}
}
}
@@ -481,16 +658,18 @@ static int const sig[] = {
#if has_sigblock
static void
- setup_catchsig()
+ setup_catchsig(sig, sigs)
+ int const *sig;
+ int sigs;
{
register int i;
int mask;
mask = 0;
- for (i=SIGS; 0<=--i; )
+ for (i=sigs; 0<=--i; )
mask |= sigmask(sig[i]);
mask = sigblock(mask);
- for (i=SIGS; 0<=--i; )
+ for (i=sigs; 0<=--i; )
if (
signal(sig[i], catchsig) == SIG_IGN &&
signal(sig[i], SIG_IGN) != catchsig
@@ -502,11 +681,13 @@ static int const sig[] = {
#else
static void
- setup_catchsig()
+ setup_catchsig(sig, sigs)
+ int const *sig;
+ int sigs;
{
register i;
- for (i=SIGS; 0<=--i; )
+ for (i=sigs; 0<=--i; )
if (
signal(sig[i], SIG_IGN) != SIG_IGN &&
signal(sig[i], catchsig) != SIG_IGN
@@ -517,16 +698,68 @@ static int const sig[] = {
#endif
#endif
+
+static int const regsigs[] = {
+# ifdef SIGHUP
+ SIGHUP,
+# endif
+# ifdef SIGINT
+ SIGINT,
+# endif
+# ifdef SIGPIPE
+ SIGPIPE,
+# endif
+# ifdef SIGQUIT
+ SIGQUIT,
+# endif
+# ifdef SIGTERM
+ SIGTERM,
+# endif
+# ifdef SIGXCPU
+ SIGXCPU,
+# endif
+# ifdef SIGXFSZ
+ SIGXFSZ,
+# endif
+};
+
void
catchints()
{
static int catching_ints;
if (!catching_ints) {
- catching_ints = true;
- setup_catchsig();
+ catching_ints = true;
+ setup_catchsig(regsigs, (int) (sizeof(regsigs)/sizeof(*regsigs)));
}
}
+#if has_mmap && large_memory && mmap_signal
+
+ /*
+ * If you mmap an NFS file, and someone on another client removes the last
+ * link to that file, and you later reference an uncached part of that file,
+ * you'll get a SIGBUS or SIGSEGV (depending on the operating system).
+ * Catch the signal and report the problem to the user.
+ * Unfortunately, there's no portable way to differentiate between this
+ * problem and actual bugs in the program.
+ * This NFS problem is rare, thank goodness.
+ *
+ * This can also occur if someone truncates the file, even without NFS.
+ */
+
+ static int const mmapsigs[] = { mmap_signal };
+
+ void
+ catchmmapints()
+ {
+ static int catching_mmap_ints;
+ if (!catching_mmap_ints) {
+ catching_mmap_ints = true;
+ setup_catchsig(mmapsigs, (int)(sizeof(mmapsigs)/sizeof(*mmapsigs)));
+ }
+ }
+#endif
+
#endif /* has_signal */
@@ -538,7 +771,7 @@ fastcopy(inf,outf)
*/
{
#if large_memory
-# if has_mmap
+# if maps_memory
awrite((char const*)inf->ptr, (size_t)(inf->lim - inf->ptr), outf);
inf->ptr = inf->lim;
# else
@@ -589,10 +822,81 @@ awrite(buf, chars, f)
Oerror();
}
+/* dup a file descriptor; the result must not be stdin, stdout, or stderr. */
+ static int dupSafer P((int));
+ static int
+dupSafer(fd)
+ int fd;
+{
+# ifdef F_DUPFD
+ return fcntl(fd, F_DUPFD, STDERR_FILENO + 1);
+# else
+ int e, f, i, used = 0;
+ while (STDIN_FILENO <= (f = dup(fd)) && f <= STDERR_FILENO)
+ used |= 1<<f;
+ e = errno;
+ for (i = STDIN_FILENO; i <= STDERR_FILENO; i++)
+ if (used & (1<<i))
+ VOID close(i);
+ errno = e;
+ return f;
+# endif
+}
+/* Renumber a file descriptor so that it's not stdin, stdout, or stderr. */
+ int
+fdSafer(fd)
+ int fd;
+{
+ if (STDIN_FILENO <= fd && fd <= STDERR_FILENO) {
+ int f = dupSafer(fd);
+ int e = errno;
+ VOID close(fd);
+ errno = e;
+ fd = f;
+ }
+ return fd;
+}
+/* Like fopen, except the result is never stdin, stdout, or stderr. */
+ FILE *
+fopenSafer(filename, type)
+ char const *filename;
+ char const *type;
+{
+ FILE *stream = fopen(filename, type);
+ if (stream) {
+ int fd = fileno(stream);
+ if (STDIN_FILENO <= fd && fd <= STDERR_FILENO) {
+ int f = dupSafer(fd);
+ if (f < 0) {
+ int e = errno;
+ VOID fclose(stream);
+ errno = e;
+ return 0;
+ }
+ if (fclose(stream) != 0) {
+ int e = errno;
+ VOID close(f);
+ errno = e;
+ return 0;
+ }
+ stream = fdopen(f, type);
+ }
+ }
+ return stream;
+}
+#ifdef F_DUPFD
+# undef dup
+# define dup(fd) fcntl(fd, F_DUPFD, 0)
+#endif
+
+
+#if has_fork || has_spawn
+
+ static int movefd P((int,int));
static int
movefd(old, new)
int old, new;
@@ -607,6 +911,7 @@ movefd(old, new)
return close(old)==0 ? new : -1;
}
+ static int fdreopen P((int,char const*,int));
static int
fdreopen(fd, file, flags)
int fd;
@@ -623,38 +928,26 @@ fdreopen(fd, file, flags)
return movefd(newfd, fd);
}
-#if !has_spawn
- static void
-tryopen(fd,file,flags)
- int fd, flags;
- char const *file;
-{
- if (file && fdreopen(fd,file,flags) != fd)
- efaterror(file);
-}
-#else
- static int
-tryopen(fd,file,flags)
- int fd, flags;
- char const *file;
-{
- int newfd = -1;
- if (file && ((newfd=dup(fd)) < 0 || fdreopen(fd,file,flags) != fd))
- efaterror(file);
- return newfd;
-}
+#if has_spawn
+ static void redirect P((int,int));
static void
redirect(old, new)
int old, new;
+/*
+* Move file descriptor OLD to NEW.
+* If OLD is -1, do nothing.
+* If OLD is -2, just close NEW.
+*/
{
- if (0 <= old && (close(new) != 0 || movefd(old,new) < 0))
+ if ((old != -1 && close(new) != 0) || (0 <= old && movefd(old,new) < 0))
efaterror("spawn I/O redirection");
}
#endif
+#else /* !has_fork && !has_spawn */
-#if !has_fork && !has_spawn
+ static void bufargcat P((struct buf*,int,char const*));
static void
bufargcat(b, c, s)
register struct buf *b;
@@ -684,53 +977,145 @@ bufargcat(b, c, s)
*p++ = '\'';
*p = 0;
}
+
#endif
+#if !has_spawn && has_fork
/*
-* Run a command specified by the strings in 'inoutargs'.
-* inoutargs[0], if nonnil, is the name of the input file.
-* inoutargs[1], if nonnil, is the name of the output file.
-* inoutargs[2..] form the command to be run.
+* Output the string S to stderr, without touching any I/O buffers.
+* This is useful if you are a child process, whose buffers are usually wrong.
+* Exit immediately if the write does not completely succeed.
+*/
+static void write_stderr P((char const *));
+ static void
+write_stderr(s)
+ char const *s;
+{
+ size_t slen = strlen(s);
+ if (write(STDERR_FILENO, s, slen) != slen)
+ _exit(EXIT_TROUBLE);
+}
+#endif
+
+/*
+* Run a command.
+* infd, if not -1, is the input file descriptor.
+* outname, if nonzero, is the name of the output file.
+* args[1..] form the command to be run; args[0] might be modified.
*/
int
-runv(inoutargs)
- char const **inoutargs;
+runv(infd, outname, args)
+ int infd;
+ char const *outname, **args;
{
- register char const **p;
int wstatus;
+#if bad_wait_if_SIGCHLD_ignored
+ static int fixed_SIGCHLD;
+ if (!fixed_SIGCHLD) {
+ fixed_SIGCHLD = true;
+# ifndef SIGCHLD
+# define SIGCHLD SIGCLD
+# endif
+ VOID signal(SIGCHLD, SIG_DFL);
+ }
+#endif
+
oflush();
eflush();
{
#if has_spawn
int in, out;
- p = inoutargs;
- in = tryopen(STDIN_FILENO, *p++, O_BINARY|O_RDONLY);
- out = tryopen(STDOUT_FILENO, *p++, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY);
- wstatus = spawn_RCS(0, *p, (char*const*)p);
- if (wstatus == -1 && errno == ENOEXEC) {
- *--p = RCS_SHELL;
- wstatus = spawnv(0, *p, (char*const*)p);
+ char const *file;
+
+ in = -1;
+ if (infd != -1 && infd != STDIN_FILENO) {
+ if ((in = dup(STDIN_FILENO)) < 0) {
+ if (errno != EBADF)
+ efaterror("spawn input setup");
+ in = -2;
+ } else {
+# ifdef F_DUPFD
+ if (close(STDIN_FILENO) != 0)
+ efaterror("spawn input close");
+# endif
+ }
+ if (
+# ifdef F_DUPFD
+ fcntl(infd, F_DUPFD, STDIN_FILENO) != STDIN_FILENO
+# else
+ dup2(infd, STDIN_FILENO) != STDIN_FILENO
+# endif
+ )
+ efaterror("spawn input redirection");
}
+
+ out = -1;
+ if (outname) {
+ if ((out = dup(STDOUT_FILENO)) < 0) {
+ if (errno != EBADF)
+ efaterror("spawn output setup");
+ out = -2;
+ }
+ if (fdreopen(
+ STDOUT_FILENO, outname,
+ O_CREAT | O_TRUNC | O_WRONLY
+ ) < 0)
+ efaterror(outname);
+ }
+
+ wstatus = spawn_RCS(0, args[1], (char**)(args + 1));
+# ifdef RCS_SHELL
+ if (wstatus == -1 && errno == ENOEXEC) {
+ args[0] = RCS_SHELL;
+ wstatus = spawnv(0, args[0], (char**)args);
+ }
+# endif
redirect(in, STDIN_FILENO);
redirect(out, STDOUT_FILENO);
#else
#if has_fork
pid_t pid;
-# if !has_waitpid
- pid_t w;
-# endif
if (!(pid = vfork())) {
- p = inoutargs;
- tryopen(STDIN_FILENO, *p++, O_BINARY|O_RDONLY);
- tryopen(STDOUT_FILENO, *p++, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY);
- VOID exec_RCS(*p, (char*const*)p);
- if (errno == ENOEXEC) {
- *--p = RCS_SHELL;
- VOID execv(*p, (char*const*)p);
+ char const *notfound;
+ if (infd != -1 && infd != STDIN_FILENO && (
+# ifdef F_DUPFD
+ (VOID close(STDIN_FILENO),
+ fcntl(infd, F_DUPFD, STDIN_FILENO) != STDIN_FILENO)
+# else
+ dup2(infd, STDIN_FILENO) != STDIN_FILENO
+# endif
+ )) {
+ /* Avoid perror since it may misuse buffers. */
+ write_stderr(args[1]);
+ write_stderr(": I/O redirection failed\n");
+ _exit(EXIT_TROUBLE);
}
- VOID write(STDERR_FILENO, *p, strlen(*p));
- VOID write(STDERR_FILENO, ": not found\n", 12);
+
+ if (outname)
+ if (fdreopen(
+ STDOUT_FILENO, outname,
+ O_CREAT | O_TRUNC | O_WRONLY
+ ) < 0) {
+ /* Avoid perror since it may misuse buffers. */
+ write_stderr(args[1]);
+ write_stderr(": ");
+ write_stderr(outname);
+ write_stderr(": cannot create\n");
+ _exit(EXIT_TROUBLE);
+ }
+ VOID exec_RCS(args[1], (char**)(args + 1));
+ notfound = args[1];
+# ifdef RCS_SHELL
+ if (errno == ENOEXEC) {
+ args[0] = notfound = RCS_SHELL;
+ VOID execv(args[0], (char**)args);
+ }
+# endif
+
+ /* Avoid perror since it may misuse buffers. */
+ write_stderr(notfound);
+ write_stderr(": not found\n");
_exit(EXIT_TROUBLE);
}
if (pid < 0)
@@ -739,83 +1124,71 @@ runv(inoutargs)
if (waitpid(pid, &wstatus, 0) < 0)
efaterror("waitpid");
# else
- do {
- if ((w = wait(&wstatus)) < 0)
- efaterror("wait");
- } while (w != pid);
+ {
+ pid_t w;
+ do {
+ if ((w = wait(&wstatus)) < 0)
+ efaterror("wait");
+ } while (w != pid);
+ }
# endif
#else
static struct buf b;
+ char const *p;
/* Use system(). On many hosts system() discards signals. Yuck! */
- p = inoutargs+2;
+ p = args + 1;
bufscpy(&b, *p);
while (*++p)
bufargcat(&b, ' ', *p);
- if (inoutargs[0])
- bufargcat(&b, '<', inoutargs[0]);
- if (inoutargs[1])
- bufargcat(&b, '>', inoutargs[1]);
+ if (infd != -1 && infd != STDIN_FILENO) {
+ char redirection[32];
+ VOID sprintf(redirection, "<&%d", infd);
+ bufscat(&b, redirection);
+ }
+ if (outname)
+ bufargcat(&b, '>', outname);
wstatus = system(b.string);
#endif
#endif
}
- if (!WIFEXITED(wstatus))
- faterror("%s failed", inoutargs[2]);
+ if (!WIFEXITED(wstatus)) {
+ if (WIFSIGNALED(wstatus)) {
+ psignal(WTERMSIG(wstatus), args[1]);
+ fatcleanup(1);
+ }
+ faterror("%s failed for unknown reason", args[1]);
+ }
return WEXITSTATUS(wstatus);
}
#define CARGSMAX 20
/*
* Run a command.
-* The first two arguments are the input and output files (if nonnil);
-* the rest specify the command and its arguments.
+* infd, if not -1, is the input file descriptor.
+* outname, if nonzero, is the name of the output file.
+* The remaining arguments specify the command and its arguments.
*/
int
#if has_prototypes
-run(char const *infile, char const *outfile, ...)
+run(int infd, char const *outname, ...)
#else
/*VARARGS2*/
-run(infile, outfile, va_alist)
- char const *infile;
- char const *outfile;
+run(infd, outname, va_alist)
+ int infd;
+ char const *outname;
va_dcl
#endif
{
va_list ap;
char const *rgargs[CARGSMAX];
- register i = 0;
- rgargs[0] = infile;
- rgargs[1] = outfile;
- vararg_start(ap, outfile);
- for (i = 2; (rgargs[i++] = va_arg(ap, char const*)); )
+ register int i;
+ vararg_start(ap, outname);
+ for (i = 1; (rgargs[i++] = va_arg(ap, char const*)); )
if (CARGSMAX <= i)
faterror("too many command arguments");
va_end(ap);
- return runv(rgargs);
-}
-
-
- char const *
-date2str(date, datebuf)
- char const date[datesize];
- char datebuf[datesize];
-/*
-* Format a user-readable form of the RCS format DATE into the buffer DATEBUF.
-* Yield DATEBUF.
-*/
-{
- register char const *p = date;
-
- while (*p++ != '.')
- ;
- VOID sprintf(datebuf,
- "19%.*s/%.2s/%.2s %.2s:%.2s:%s" +
- (date[2]=='.' && VERSION(5)<=RCSversion ? 0 : 2),
- (int)(p-date-1), date,
- p, p+3, p+6, p+9, p+12
- );
- return datebuf;
+ return runv(infd, outname, rgargs);
}
@@ -828,23 +1201,28 @@ setRCSversion(str)
static int oldversion;
register char const *s = str + 2;
- int v = VERSION_DEFAULT;
-
- if (oldversion)
- redefined('V');
- oldversion = true;
if (*s) {
+ int v = VERSION_DEFAULT;
+
+ if (oldversion)
+ redefined('V');
+ oldversion = true;
v = 0;
while (isdigit(*s))
v = 10*v + *s++ - '0';
if (*s)
- faterror("%s isn't a number", str);
- if (v < VERSION_min || VERSION_max < v)
- faterror("%s out of range %d..%d", str, VERSION_min, VERSION_max);
+ error("%s isn't a number", str);
+ else if (v < VERSION_min || VERSION_max < v)
+ error("%s out of range %d..%d",
+ str, VERSION_min, VERSION_max
+ );
+
+ RCSversion = VERSION(v);
+ } else {
+ printf("RCS version %s\n", RCS_version_string);
+ exit(0);
}
-
- RCSversion = VERSION(v);
}
int
@@ -853,7 +1231,7 @@ getRCSINIT(argc, argv, newargv)
char **argv, ***newargv;
{
register char *p, *q, **pp;
- unsigned n;
+ size_t n;
if (!(q = cgetenv("RCSINIT")))
*newargv = argv;
@@ -922,7 +1300,7 @@ getRCSINIT(argc, argv, newargv)
}
copyrest:
while ((*pp++ = *argv++))
- ;
+ continue;
}
return argc;
}
@@ -950,8 +1328,11 @@ getRCSINIT(argc, argv, newargv)
*/
static void
-set_uid_to(u)
- uid_t u;
+#if has_prototypes
+set_uid_to(uid_t u)
+#else
+ set_uid_to(u) uid_t u;
+#endif
/* Become user u. */
{
static int looping;
@@ -959,8 +1340,13 @@ set_uid_to(u)
if (euid() == ruid())
return;
#if (has_fork||has_spawn) && DIFF_ABSOLUTE
- if (seteuid(u) != 0)
- efaterror("setuid");
+# if has_setreuid
+ if (setreuid(u==euid() ? ruid() : euid(), u) != 0)
+ efaterror("setuid");
+# else
+ if (seteuid(u) != 0)
+ efaterror("setuid");
+# endif
#endif
if (geteuid() != u) {
if (looping)
@@ -995,3 +1381,12 @@ setrid()
set_uid_to(ruid());
}
#endif
+
+ time_t
+now()
+{
+ static time_t t;
+ if (!t && time(&t) == -1)
+ efaterror("time");
+ return t;
+}
diff --git a/gnu/usr.bin/rcs/rcs/rcs.c b/gnu/usr.bin/rcs/rcs/rcs.c
index 6a83770..c1b9af0 100644
--- a/gnu/usr.bin/rcs/rcs/rcs.c
+++ b/gnu/usr.bin/rcs/rcs/rcs.c
@@ -1,8 +1,7 @@
-/*
- * RCS create/change operation
- */
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Change RCS file attributes. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -18,8 +17,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -27,12 +27,44 @@ Report problems and direct all questions to:
*/
-
-
-
-/* $Log: rcs.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:14 jkh
- * Updated GNU utilities
+/*
+ * $Log: rcs.c,v $
+ * Revision 5.21 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.20 1995/06/01 16:23:43 eggert
+ * (main): Warn if no options were given. Punctuate messages properly.
+ *
+ * (sendmail): Rewind mailmess before flushing it.
+ * Output another warning if mail should work but fails.
+ *
+ * (buildeltatext): Pass "--binary" if -kb and if --binary makes a difference.
+ *
+ * Revision 5.19 1994/03/17 14:05:48 eggert
+ * Use ORCSerror to clean up after a fatal error. Remove lint.
+ * Specify subprocess input via file descriptor, not file name. Remove lint.
+ * Flush stderr after prompt.
+ *
+ * Revision 5.18 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits. Don't print usage twice.
+ *
+ * Revision 5.17 1993/11/03 17:42:27 eggert
+ * Add -z. Don't lose track of -m or -t when there are no other changes.
+ * Don't discard ignored phrases. Improve quality of diagnostics.
+ *
+ * Revision 5.16 1992/07/28 16:12:44 eggert
+ * rcs -l now asks whether you want to break the lock.
+ * Add -V. Set RCS file's mode and time at right moment.
+ *
+ * Revision 5.15 1992/02/17 23:02:20 eggert
+ * Add -T.
+ *
+ * Revision 5.14 1992/01/27 16:42:53 eggert
+ * Add -M. Avoid invoking umask(); it's one less thing to configure.
+ * Add support for bad_creat0. lint -> RCS_lint
+ *
+ * Revision 5.13 1992/01/06 02:42:34 eggert
+ * Avoid changing RCS file in common cases where no change can occur.
*
* Revision 5.12 1991/11/20 17:58:08 eggert
* Don't read the delta tree from a nonexistent RCS file.
@@ -208,69 +240,80 @@ struct delrevpair {
int code;
};
+static int branchpoint P((struct hshentry*,struct hshentry*));
+static int breaklock P((struct hshentry const*));
static int buildeltatext P((struct hshentries const*));
+static int doaccess P((void));
+static int doassoc P((void));
+static int dolocks P((void));
+static int domessages P((void));
+static int rcs_setstate P((char const*,char const*));
static int removerevs P((void));
static int sendmail P((char const*,char const*));
-static struct Lockrev *rmnewlocklst P((struct Lockrev const*));
-static void breaklock P((struct hshentry const*));
+static int setlock P((char const*));
+static struct Lockrev **rmnewlocklst P((char const*));
+static struct hshentry *searchcutpt P((char const*,int,struct hshentries*));
static void buildtree P((void));
static void cleanup P((void));
-static void doaccess P((void));
-static void doassoc P((void));
-static void dolocks P((void));
-static void domessages P((void));
static void getaccessor P((char*,enum changeaccess));
static void getassoclst P((int,char*));
static void getchaccess P((char const*,enum changeaccess));
static void getdelrev P((char*));
static void getmessage P((char*));
static void getstates P((char*));
-static void rcs_setstate P((char const*,char const*));
static void scanlogtext P((struct hshentry*,int));
-static void setlock P((char const*));
static struct buf numrev;
static char const *headstate;
static int chgheadstate, exitstatus, lockhead, unlockcaller;
+static int suppress_mail;
static struct Lockrev *newlocklst, *rmvlocklst;
-static struct Message *messagelst, *lastmessage;
-static struct Status *statelst, *laststate;
-static struct Symrev *assoclst, *lastassoc;
+static struct Message *messagelst, **nextmessage;
+static struct Status *statelst, **nextstate;
+static struct Symrev *assoclst, **nextassoc;
static struct chaccess *chaccess, **nextchaccess;
static struct delrevpair delrev;
static struct hshentry *cuthead, *cuttail, *delstrt;
static struct hshentries *gendeltas;
-mainProg(rcsId, "rcs", "$Id: rcs.c,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp $")
+mainProg(rcsId, "rcs", "$Id: rcs.c,v 5.21 1995/06/16 06:19:24 eggert Exp $")
{
static char const cmdusage[] =
- "\nrcs usage: rcs -{ae}logins -Afile -{blu}[rev] -cstring -{iLU} -{nNs}name[:rev] -orange -t[file] -Vn file ...";
+ "\nrcs usage: rcs -{ae}logins -Afile -{blu}[rev] -cstring -{iILqTU} -ksubst -mrev:msg -{nN}name[:[rev]] -orange -sstate[:rev] -t[text] -Vn -xsuff -zzone file ...";
char *a, **newargv, *textfile;
char const *branchsym, *commsyml;
- int branchflag, expmode, initflag;
- int e, r, strictlock, strict_selected, textflag;
- mode_t defaultRCSmode; /* default mode for new RCS files */
- mode_t RCSmode;
+ int branchflag, changed, expmode, initflag;
+ int strictlock, strict_selected, textflag;
+ int keepRCStime, Ttimeflag;
+ size_t commsymlen;
struct buf branchnum;
- struct stat workstat;
- struct Lockrev *curlock, * rmvlock, *lockpt;
+ struct Lockrev *lockpt;
+ struct Lockrev **curlock, **rmvlock;
struct Status * curstate;
nosetid();
+ nextassoc = &assoclst;
nextchaccess = &chaccess;
- branchsym = commsyml = textfile = nil;
+ nextmessage = &messagelst;
+ nextstate = &statelst;
+ branchsym = commsyml = textfile = 0;
branchflag = strictlock = false;
bufautobegin(&branchnum);
- curlock = rmvlock = nil;
- defaultRCSmode = 0;
+ commsymlen = 0;
+ curlock = &newlocklst;
+ rmvlock = &rmvlocklst;
expmode = -1;
suffixes = X_DEFAULT;
initflag= textflag = false;
strict_selected = 0;
+ Ttimeflag = false;
/* preprocessing command options */
+ if (1 < argc && argv[1][0] != '-')
+ warn("No options were given; this usage is obsolescent.");
+
argc = getRCSINIT(argc, argv, &newargv);
argv = newargv;
while (a = *++argv, 0<--argc && *a++=='-') {
@@ -289,6 +332,7 @@ mainProg(rcsId, "rcs", "$Id: rcs.c,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp $")
case 'c': /* change comment symbol */
if (commsyml) redefined('c');
commsyml = a;
+ commsymlen = strlen(a);
break;
case 'a': /* add new accessor */
@@ -297,11 +341,11 @@ mainProg(rcsId, "rcs", "$Id: rcs.c,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp $")
case 'A': /* append access list according to accessfile */
if (!*a) {
- error("missing file name after -A");
+ error("missing pathname after -A");
break;
}
*argv = a;
- if (0 < pairfilenames(1,argv,rcsreadopen,true,false)) {
+ if (0 < pairnames(1,argv,rcsreadopen,true,false)) {
while (AccessList) {
getchaccess(str_save(AccessList->login),append);
AccessList = AccessList->nextaccess;
@@ -320,14 +364,10 @@ mainProg(rcsId, "rcs", "$Id: rcs.c,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp $")
lockhead = true;
break;
}
- lockpt = talloc(struct Lockrev);
+ *curlock = lockpt = talloc(struct Lockrev);
lockpt->revno = a;
- lockpt->nextrev = nil;
- if ( curlock )
- curlock->nextrev = lockpt;
- else
- newlocklst = lockpt;
- curlock = lockpt;
+ lockpt->nextrev = 0;
+ curlock = &lockpt->nextrev;
break;
case 'u': /* release lock of a locked revision */
@@ -335,33 +375,28 @@ mainProg(rcsId, "rcs", "$Id: rcs.c,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp $")
unlockcaller=true;
break;
}
- lockpt = talloc(struct Lockrev);
+ *rmvlock = lockpt = talloc(struct Lockrev);
lockpt->revno = a;
- lockpt->nextrev = nil;
- if (rmvlock)
- rmvlock->nextrev = lockpt;
- else
- rmvlocklst = lockpt;
- rmvlock = lockpt;
-
- curlock = rmnewlocklst(lockpt);
+ lockpt->nextrev = 0;
+ rmvlock = &lockpt->nextrev;
+ curlock = rmnewlocklst(lockpt->revno);
break;
case 'L': /* set strict locking */
- if (strict_selected++) { /* Already selected L or U? */
+ if (strict_selected) {
if (!strictlock) /* Already selected -U? */
- warn("-L overrides -U.");
+ warn("-U overridden by -L");
}
strictlock = true;
+ strict_selected = true;
break;
case 'U': /* release strict locking */
- if (strict_selected++) { /* Already selected L or U? */
+ if (strict_selected) {
if (strictlock) /* Already selected -L? */
- warn("-L overrides -U.");
+ warn("-L overridden by -U");
}
- else
- strictlock = false;
+ strict_selected = true;
break;
case 'n': /* add new association: error, if name exists */
@@ -384,6 +419,10 @@ mainProg(rcsId, "rcs", "$Id: rcs.c,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp $")
getmessage(a);
break;
+ case 'M': /* do not send mail */
+ suppress_mail = true;
+ break;
+
case 'o': /* delete revisions */
if (delrev.strt) redefined('o');
if (!*a) {
@@ -409,6 +448,12 @@ mainProg(rcsId, "rcs", "$Id: rcs.c,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp $")
}
break;
+ case 'T': /* do not update last-mod time for minor changes */
+ if (*a)
+ goto unknown;
+ Ttimeflag = true;
+ break;
+
case 'I':
interactiveflag = true;
break;
@@ -425,41 +470,38 @@ mainProg(rcsId, "rcs", "$Id: rcs.c,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp $")
setRCSversion(*argv);
break;
+ case 'z':
+ zone_set(a);
+ break;
+
case 'k': /* set keyword expand mode */
if (0 <= expmode) redefined('k');
if (0 <= (expmode = str2expmode(a)))
break;
/* fall into */
default:
- faterror("unknown option: %s%s", *argv, cmdusage);
+ unknown:
+ error("unknown option: %s%s", *argv, cmdusage);
};
} /* end processing of options */
- if (argc<1) faterror("no input file%s", cmdusage);
- if (nerror) {
- diagnose("%s aborted\n",cmdid);
- exitmain(EXIT_FAILURE);
- }
- if (initflag) {
- defaultRCSmode = umask((mode_t)0);
- VOID umask(defaultRCSmode);
- defaultRCSmode = (S_IRUSR|S_IRGRP|S_IROTH) & ~defaultRCSmode;
- }
+ /* Now handle all pathnames. */
+ if (nerror) cleanup();
+ else if (argc < 1) faterror("no input file%s", cmdusage);
+ else for (; 0 < argc; cleanup(), ++argv, --argc) {
- /* now handle all filenames */
- do {
ffree();
if ( initflag ) {
- switch (pairfilenames(argc, argv, rcswriteopen, false, false)) {
+ switch (pairnames(argc, argv, rcswriteopen, false, false)) {
case -1: break; /* not exist; ok */
case 0: continue; /* error */
- case 1: error("file %s exists already", RCSfilename);
+ case 1: rcserror("already exists");
continue;
}
}
else {
- switch (pairfilenames(argc, argv, rcswriteopen, true, false)) {
+ switch (pairnames(argc, argv, rcswriteopen, true, false)) {
case -1: continue; /* not exist */
case 0: continue; /* errors */
case 1: break; /* file exists; ok*/
@@ -467,115 +509,134 @@ mainProg(rcsId, "rcs", "$Id: rcs.c,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp $")
}
- /* now RCSfilename contains the name of the RCS file, and
- * workfilename contains the name of the working file.
+ /*
+ * RCSname contains the name of the RCS file, and
+ * workname contains the name of the working file.
* if !initflag, finptr contains the file descriptor for the
* RCS file. The admin node is initialized.
*/
- diagnose("RCS file: %s\n", RCSfilename);
+ diagnose("RCS file: %s\n", RCSname);
- RCSmode = defaultRCSmode;
- if (initflag) {
- if (stat(workfilename, &workstat) == 0)
- RCSmode = workstat.st_mode;
- } else {
+ changed = initflag | textflag;
+ keepRCStime = Ttimeflag;
+ if (!initflag) {
if (!checkaccesslist()) continue;
gettree(); /* Read the delta tree. */
- RCSmode = RCSstat.st_mode;
}
- RCSmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
/* update admin. node */
- if (strict_selected) StrictLocks = strictlock;
- if (commsyml) {
+ if (strict_selected) {
+ changed |= StrictLocks ^ strictlock;
+ StrictLocks = strictlock;
+ }
+ if (
+ commsyml &&
+ (
+ commsymlen != Comment.size ||
+ memcmp(commsyml, Comment.string, commsymlen) != 0
+ )
+ ) {
Comment.string = commsyml;
Comment.size = strlen(commsyml);
+ changed = true;
+ }
+ if (0 <= expmode && Expand != expmode) {
+ Expand = expmode;
+ changed = true;
}
- if (0 <= expmode) Expand = expmode;
/* update default branch */
if (branchflag && expandsym(branchsym, &branchnum)) {
if (countnumflds(branchnum.string)) {
- Dbranch = branchnum.string;
+ if (cmpnum(Dbranch, branchnum.string) != 0) {
+ Dbranch = branchnum.string;
+ changed = true;
+ }
} else
- Dbranch = nil;
- }
+ if (Dbranch) {
+ Dbranch = 0;
+ changed = true;
+ }
+ }
- doaccess(); /* Update access list. */
+ changed |= doaccess(); /* Update access list. */
- doassoc(); /* Update association list. */
+ changed |= doassoc(); /* Update association list. */
- dolocks(); /* Update locks. */
+ changed |= dolocks(); /* Update locks. */
- domessages(); /* Update log messages. */
+ changed |= domessages(); /* Update log messages. */
/* update state attribution */
if (chgheadstate) {
/* change state of default branch or head */
- if (Dbranch==nil) {
- if (Head==nil)
- warn("can't change states in an empty tree");
- else Head->state = headstate;
- } else {
- rcs_setstate(Dbranch,headstate); /* Can't set directly */
- }
- }
- curstate = statelst;
- while( curstate ) {
- rcs_setstate(curstate->revno,curstate->status);
- curstate = curstate->nextstatus;
+ if (!Dbranch) {
+ if (!Head)
+ rcswarn("can't change states in an empty tree");
+ else if (strcmp(Head->state, headstate) != 0) {
+ Head->state = headstate;
+ changed = true;
+ }
+ } else
+ changed |= rcs_setstate(Dbranch,headstate);
}
+ for (curstate = statelst; curstate; curstate = curstate->nextstatus)
+ changed |= rcs_setstate(curstate->revno,curstate->status);
- cuthead = cuttail = nil;
+ cuthead = cuttail = 0;
if (delrev.strt && removerevs()) {
/* rebuild delta tree if some deltas are deleted */
if ( cuttail )
- VOID genrevs(cuttail->num, (char *)nil,(char *)nil,
- (char *)nil, &gendeltas);
+ VOID genrevs(
+ cuttail->num, (char *)0, (char *)0, (char *)0,
+ &gendeltas
+ );
buildtree();
+ changed = true;
+ keepRCStime = false;
}
if (nerror)
continue;
- putadmin(frewrite);
+ putadmin();
if ( Head )
puttree(Head, frewrite);
putdesc(textflag,textfile);
if ( Head) {
- if (!delrev.strt && !messagelst) {
- /* No revision was deleted and no message was changed. */
- fastcopy(finptr, frewrite);
- } else {
+ if (delrev.strt || messagelst) {
if (!cuttail || buildeltatext(gendeltas)) {
advise_access(finptr, MADV_SEQUENTIAL);
- scanlogtext((struct hshentry *)nil, false);
+ scanlogtext((struct hshentry *)0, false);
/* copy rest of delta text nodes that are not deleted */
+ changed = true;
}
}
}
- Izclose(&finptr);
- if ( ! nerror ) { /* move temporary file to RCS file if no error */
- /* update mode */
- ignoreints();
- r = chnamemod(&frewrite, newRCSfilename, RCSfilename, RCSmode);
- e = errno;
- keepdirtemp(newRCSfilename);
- restoreints();
- if (r != 0) {
- enerror(e, RCSfilename);
- error("saved in %s", newRCSfilename);
- dirtempunlink();
- break;
- }
- diagnose("done\n");
- } else {
- diagnose("%s aborted; %s unchanged.\n",cmdid,RCSfilename);
- }
- } while (cleanup(),
- ++argv, --argc >=1);
+
+ if (initflag) {
+ /* Adjust things for donerewrite's sake. */
+ if (stat(workname, &RCSstat) != 0) {
+# if bad_creat0
+ mode_t m = umask(0);
+ (void) umask(m);
+ RCSstat.st_mode = (S_IRUSR|S_IRGRP|S_IROTH) & ~m;
+# else
+ changed = -1;
+# endif
+ }
+ RCSstat.st_nlink = 0;
+ keepRCStime = false;
+ }
+ if (donerewrite(changed,
+ keepRCStime ? RCSstat.st_mtime : (time_t)-1
+ ) != 0)
+ break;
+
+ diagnose("done\n");
+ }
tempunlink();
exitmain(exitstatus);
@@ -587,13 +648,14 @@ cleanup()
if (nerror) exitstatus = EXIT_FAILURE;
Izclose(&finptr);
Ozclose(&fcopy);
- Ozclose(&frewrite);
+ ORCSclose();
dirtempunlink();
}
- exiting void
+ void
exiterr()
{
+ ORCSerror();
dirtempunlink();
tempunlink();
_exit(EXIT_FAILURE);
@@ -612,9 +674,10 @@ char * sp;
char const *temp;
int c;
- while( (c=(*++sp)) == ' ' || c == '\t' || c =='\n') ;
+ while ((c = *++sp) == ' ' || c == '\t' || c =='\n')
+ continue;
temp = sp;
- sp = checkid(sp, ':'); /* check for invalid symbolic name */
+ sp = checksym(sp, ':'); /* check for invalid symbolic name */
c = *sp; *sp = '\0';
while( c == ' ' || c == '\t' || c == '\n') c = *++sp;
@@ -627,18 +690,15 @@ char * sp;
pt->ssymbol = temp;
pt->override = flag;
if (c == '\0') /* delete symbol */
- pt->revno = nil;
+ pt->revno = 0;
else {
- while( (c = *++sp) == ' ' || c == '\n' || c == '\t') ;
+ while ((c = *++sp) == ' ' || c == '\n' || c == '\t')
+ continue;
pt->revno = sp;
}
- pt->nextsym = nil;
- if (lastassoc)
- lastassoc->nextsym = pt;
- else
- assoclst = pt;
- lastassoc = pt;
- return;
+ pt->nextsym = 0;
+ *nextassoc = pt;
+ nextassoc = &pt->nextsym;
}
@@ -649,10 +709,11 @@ getchaccess(login, command)
{
register struct chaccess *pt;
- *nextchaccess = pt = talloc(struct chaccess);
+ pt = talloc(struct chaccess);
pt->login = login;
pt->command = command;
- pt->nextchaccess = nil;
+ pt->nextchaccess = 0;
+ *nextchaccess = pt;
nextchaccess = &pt->nextchaccess;
}
@@ -671,10 +732,11 @@ getaccessor(opt, command)
register char *sp;
sp = opt;
- while( ( c = *++sp) == ' ' || c == '\n' || c == '\t' || c == ',') ;
+ while ((c = *++sp) == ' ' || c == '\n' || c == '\t' || c == ',')
+ continue;
if ( c == '\0') {
if (command == erase && sp-opt == 1) {
- getchaccess((char const*)nil, command);
+ getchaccess((char*)0, command);
return;
}
error("missing login name after option -a or -e");
@@ -712,11 +774,8 @@ getmessage(option)
pt->revno = option;
pt->message = cb;
pt->nextmessage = 0;
- if (lastmessage)
- lastmessage->nextmessage = pt;
- else
- messagelst = pt;
- lastmessage = pt;
+ *nextmessage = pt;
+ nextmessage = &pt->nextmessage;
}
@@ -731,7 +790,8 @@ char *sp;
struct Status *pt;
register c;
- while( (c=(*++sp)) ==' ' || c == '\t' || c == '\n') ;
+ while ((c = *++sp) ==' ' || c == '\t' || c == '\n')
+ continue;
temp = sp;
sp = checkid(sp,':'); /* check for invalid state attribute */
c = *sp; *sp = '\0';
@@ -747,16 +807,14 @@ char *sp;
return;
}
- while( (c = *++sp) == ' ' || c == '\t' || c == '\n') ;
+ while ((c = *++sp) == ' ' || c == '\t' || c == '\n')
+ continue;
pt = talloc(struct Status);
pt->status = temp;
pt->revno = sp;
- pt->nextstatus = nil;
- if (laststate)
- laststate->nextstatus = pt;
- else
- statelst = pt;
- laststate = pt;
+ pt->nextstatus = 0;
+ *nextstate = pt;
+ nextstate = &pt->nextstatus;
}
@@ -772,7 +830,8 @@ char *sp;
int separator;
pt = &delrev;
- while((c = (*++sp)) == ' ' || c == '\n' || c == '\t') ;
+ while ((c = (*++sp)) == ' ' || c == '\n' || c == '\t')
+ continue;
/* Support old ambiguous '-' syntax; this will go away. */
if (strchr(sp,':'))
@@ -784,11 +843,12 @@ char *sp;
}
if (c == separator) { /* -o:rev */
- while( (c = (*++sp)) == ' ' || c == '\n' || c == '\t') ;
+ while ((c = (*++sp)) == ' ' || c == '\n' || c == '\t')
+ continue;
pt->strt = sp; pt->code = 1;
while( c != ' ' && c != '\n' && c != '\t' && c != '\0') c =(*++sp);
*sp = '\0';
- pt->end = nil;
+ pt->end = 0;
return;
}
else {
@@ -798,15 +858,18 @@ char *sp;
*sp = '\0';
while( c == ' ' || c == '\n' || c == '\t' ) c = *++sp;
if ( c == '\0' ) { /* -o rev or branch */
- pt->end = nil; pt->code = 0;
+ pt->code = 0;
+ pt->end = 0;
return;
}
if (c != separator) {
- faterror("invalid range %s %s after -o", pt->strt, sp);
+ error("invalid range %s %s after -o", pt->strt, sp);
}
- while( (c = *++sp) == ' ' || c == '\n' || c == '\t') ;
+ while ((c = *++sp) == ' ' || c == '\n' || c == '\t')
+ continue;
if (!c) { /* -orev: */
- pt->end = nil; pt->code = 2;
+ pt->code = 2;
+ pt->end = 0;
return;
}
}
@@ -824,11 +887,11 @@ scanlogtext(delta,edit)
struct hshentry *delta;
int edit;
/* Function: Scans delta text nodes up to and including the one given
- * by delta, or up to last one present, if delta==nil.
- * For the one given by delta (if delta!=nil), the log message is saved into
+ * by delta, or up to last one present, if !delta.
+ * For the one given by delta (if delta), the log message is saved into
* delta->log if delta==cuttail; the text is edited if EDIT is set, else copied.
* Assumes the initial lexeme must be read in first.
- * Does not advance nexttok after it is finished, except if delta==nil.
+ * Does not advance nexttok after it is finished, except if !delta.
*/
{
struct hshentry const *nextdelta;
@@ -838,12 +901,14 @@ scanlogtext(delta,edit)
foutptr = 0;
if (eoflex()) {
if(delta)
- faterror("can't find delta for revision %s", delta->num);
+ rcsfaterror("can't find delta for revision %s",
+ delta->num
+ );
return; /* no more delta text nodes */
}
nextlex();
if (!(nextdelta=getnum()))
- faterror("delta number corrupted");
+ fatserror("delta number corrupted");
if (nextdelta->selector) {
foutptr = frewrite;
aprintf(frewrite,DELNUMFORM,nextdelta->num,Klog);
@@ -853,17 +918,19 @@ scanlogtext(delta,edit)
cb = savestring(&curlogbuf);
if (!delta->log.string)
delta->log = cleanlogmsg(curlogbuf.string, cb.size);
- } else if (nextdelta->log.string && nextdelta->selector) {
- foutptr = 0;
- readstring();
- foutptr = frewrite;
- putstring(foutptr, false, nextdelta->log, true);
- afputc(nextc, foutptr);
- } else {readstring();
- }
- nextlex();
- while (nexttok==ID && strcmp(NextString,Ktext)!=0)
- ignorephrase();
+ nextlex();
+ delta->igtext = getphrases(Ktext);
+ } else {
+ if (nextdelta->log.string && nextdelta->selector) {
+ foutptr = 0;
+ readstring();
+ foutptr = frewrite;
+ putstring(foutptr, false, nextdelta->log, true);
+ afputc(nextc, foutptr);
+ } else
+ readstring();
+ ignorephrases(Ktext);
+ }
getkeystring(Ktext);
if (delta==nextdelta)
@@ -873,74 +940,70 @@ scanlogtext(delta,edit)
}
/* got the one we're looking for */
if (edit)
- editstring((struct hshentry *)nil);
+ editstring((struct hshentry*)0);
else
enterstring();
}
- static struct Lockrev *
+ static struct Lockrev **
rmnewlocklst(which)
- struct Lockrev const *which;
-/* Function: remove lock to revision which->revno from newlocklst */
-
+ char const *which;
+/* Remove lock to revision WHICH from newlocklst. */
{
- struct Lockrev * pt, *pre;
-
- while( newlocklst && (! strcmp(newlocklst->revno, which->revno))){
- struct Lockrev *pn = newlocklst->nextrev;
- tfree(newlocklst);
- newlocklst = pn;
- }
+ struct Lockrev *pt, **pre;
- pt = pre = newlocklst;
- while( pt ) {
- if ( ! strcmp(pt->revno, which->revno) ) {
- pre->nextrev = pt->nextrev;
+ pre = &newlocklst;
+ while ((pt = *pre))
+ if (strcmp(pt->revno, which) != 0)
+ pre = &pt->nextrev;
+ else {
+ *pre = pt->nextrev;
tfree(pt);
- pt = pre->nextrev;
- }
- else {
- pre = pt;
- pt = pt->nextrev;
- }
- }
+ }
return pre;
}
- static void
+ static int
doaccess()
{
register struct chaccess *ch;
register struct access **p, *t;
+ register int changed = false;
for (ch = chaccess; ch; ch = ch->nextchaccess) {
switch (ch->command) {
case erase:
- if (!ch->login)
- AccessList = nil;
- else
- for (p = &AccessList; (t = *p); )
- if (strcmp(ch->login, t->login) == 0)
+ if (!ch->login) {
+ if (AccessList) {
+ AccessList = 0;
+ changed = true;
+ }
+ } else
+ for (p = &AccessList; (t = *p); p = &t->nextaccess)
+ if (strcmp(ch->login, t->login) == 0) {
*p = t->nextaccess;
- else
- p = &t->nextaccess;
+ changed = true;
+ break;
+ }
break;
case append:
for (p = &AccessList; ; p = &t->nextaccess)
if (!(t = *p)) {
*p = t = ftalloc(struct access);
t->login = ch->login;
- t->nextaccess = nil;
+ t->nextaccess = 0;
+ changed = true;
break;
} else if (strcmp(ch->login, t->login) == 0)
break;
break;
}
}
+ return changed;
}
@@ -954,26 +1017,29 @@ sendmail(Delta, who)
{
#ifdef SENDMAIL
char const *messagefile;
- int old1, old2, c;
+ int old1, old2, c, status;
FILE * mailmess;
#endif
aprintf(stderr, "Revision %s is already locked by %s.\n", Delta, who);
+ if (suppress_mail)
+ return true;
if (!yesorno(false, "Do you want to break the lock? [ny](n): "))
return false;
/* go ahead with breaking */
#ifdef SENDMAIL
messagefile = maketemp(0);
- if (!(mailmess = fopen(messagefile, "w"))) {
+ if (!(mailmess = fopenSafer(messagefile, "w+"))) {
efaterror(messagefile);
}
aprintf(mailmess, "Subject: Broken lock on %s\n\nYour lock on revision %s of file %s\nhas been broken by %s for the following reason:\n",
- basename(RCSfilename), Delta, getfullRCSname(), getcaller()
+ basefilename(RCSname), Delta, getfullRCSname(), getcaller()
);
aputs("State the reason for breaking the lock:\n(terminate with single '.' or end of file)\n>> ", stderr);
+ eflush();
old1 = '\n'; old2 = ' ';
for (; ;) {
@@ -987,23 +1053,28 @@ sendmail(Delta, who)
else {
afputc(old1, mailmess);
old2 = old1; old1 = c;
- if (c=='\n') aputs(">> ", stderr);
+ if (c == '\n') {
+ aputs(">> ", stderr);
+ eflush();
+ }
}
}
+ Orewind(mailmess);
+ aflush(mailmess);
+ status = run(fileno(mailmess), (char*)0, SENDMAIL, who, (char*)0);
Ozclose(&mailmess);
-
- if (run(messagefile, (char*)nil, SENDMAIL, who, (char*)nil))
- warn("Mail may have failed."),
-#else
- warn("Mail notification of broken locks is not available."),
+ if (status == 0)
+ return true;
+ warn("Mail failed.");
#endif
- warn("Please tell `%s' why you broke the lock.", who);
+ warn("Mail notification of broken locks is not available.");
+ warn("Please tell `%s' why you broke the lock.", who);
return(true);
}
- static void
+ static int
breaklock(delta)
struct hshentry const *delta;
/* function: Finds the lock held by caller on delta,
@@ -1012,36 +1083,28 @@ breaklock(delta)
* Prints an error message if there is no such lock or error.
*/
{
- register struct lock * next, * trail;
+ register struct rcslock *next, **trail;
char const *num;
- struct lock dummy;
num=delta->num;
- dummy.nextlock=next=Locks;
- trail = &dummy;
- while (next!=nil) {
+ for (trail = &Locks; (next = *trail); trail = &next->nextlock)
if (strcmp(num, next->delta->num) == 0) {
if (
strcmp(getcaller(),next->login) != 0
&& !sendmail(num, next->login)
) {
- error("%s still locked by %s", num, next->login);
- return;
+ rcserror("revision %s still locked by %s",
+ num, next->login
+ );
+ return false;
}
- break; /* exact match */
+ diagnose("%s unlocked\n", next->delta->num);
+ *trail = next->nextlock;
+ next->delta->lockedby = 0;
+ return true;
}
- trail=next;
- next=next->nextlock;
- }
- if (next!=nil) {
- /*found one */
- diagnose("%s unlocked\n",next->delta->num);
- trail->nextlock=next->nextlock;
- next->delta->lockedby=nil;
- Locks=dummy.nextlock;
- } else {
- error("no lock set on revision %s", num);
- }
+ rcserror("no lock set on revision %s", num);
+ return false;
}
@@ -1049,14 +1112,14 @@ breaklock(delta)
static struct hshentry *
searchcutpt(object, length, store)
char const *object;
- unsigned length;
+ int length;
struct hshentries *store;
/* Function: Search store and return entry with number being object. */
-/* cuttail = nil, if the entry is Head; otherwise, cuttail */
+/* cuttail = 0, if the entry is Head; otherwise, cuttail */
/* is the entry point to the one with number being object */
{
- cuthead = nil;
+ cuthead = 0;
while (compartial(store->first->num, object, length)) {
cuthead = store->first;
store = store->rest;
@@ -1076,36 +1139,22 @@ struct hshentry *strt, *tail;
{
struct hshentry *pt;
- struct lock const *lockpt;
- int flag;
-
+ struct rcslock const *lockpt;
- pt = strt;
- flag = false;
- while( pt != tail) {
+ for (pt = strt; pt != tail; pt = pt->next) {
if ( pt->branches ){ /* a branch point */
- flag = true;
- error("can't remove branch point %s", pt->num);
- }
- lockpt = Locks;
- while(lockpt && lockpt->delta != pt)
- lockpt = lockpt->nextlock;
- if ( lockpt ) {
- flag = true;
- error("can't remove locked revision %s",pt->num);
- }
- pt = pt->next;
- }
-
- if ( ! flag ) {
- pt = strt;
- while( pt != tail ) {
- pt->selector = false;
- diagnose("deleting revision %s\n",pt->num);
- pt = pt->next;
+ rcserror("can't remove branch point %s", pt->num);
+ return true;
}
+ for (lockpt = Locks; lockpt; lockpt = lockpt->nextlock)
+ if (lockpt->delta == pt) {
+ rcserror("can't remove locked revision %s", pt->num);
+ return true;
+ }
+ pt->selector = false;
+ diagnose("deleting revision %s\n",pt->num);
}
- return flag;
+ return false;
}
@@ -1114,34 +1163,33 @@ struct hshentry *strt, *tail;
removerevs()
/* Function: get the revision range to be removed, and place the */
/* first revision removed in delstrt, the revision before */
-/* delstrt in cuthead( nil, if delstrt is head), and the */
-/* revision after the last removed revision in cuttail(nil */
+/* delstrt in cuthead (0, if delstrt is head), and the */
+/* revision after the last removed revision in cuttail (0 */
/* if the last is a leaf */
{
struct hshentry *target, *target2, *temp;
- unsigned length;
- int flag;
+ int length;
+ int cmp;
- flag = false;
if (!expandsym(delrev.strt, &numrev)) return 0;
- target = genrevs(numrev.string, (char*)nil, (char*)nil, (char*)nil, &gendeltas);
+ target = genrevs(numrev.string,(char*)0,(char*)0,(char*)0,&gendeltas);
if ( ! target ) return 0;
- if (cmpnum(target->num, numrev.string)) flag = true;
+ cmp = cmpnum(target->num, numrev.string);
length = countnumflds(numrev.string);
if (delrev.code == 0) { /* -o rev or -o branch */
if (length & 1)
temp=searchcutpt(target->num,length+1,gendeltas);
- else if (flag) {
- error("Revision %s doesn't exist.", numrev.string);
+ else if (cmp) {
+ rcserror("Revision %s doesn't exist.", numrev.string);
return 0;
}
else
temp = searchcutpt(numrev.string, length, gendeltas);
cuttail = target->next;
if ( branchpoint(temp, cuttail) ) {
- cuttail = nil;
+ cuttail = 0;
return 0;
}
delstrt = temp; /* first revision to be removed */
@@ -1149,7 +1197,7 @@ removerevs()
}
if (length & 1) { /* invalid branch after -o */
- error("invalid branch range %s after -o", numrev.string);
+ rcserror("invalid branch range %s after -o", numrev.string);
return 0;
}
@@ -1165,7 +1213,7 @@ removerevs()
cuttail = cuttail->next;
}
if ( branchpoint(temp, cuttail) ){
- cuttail = nil;
+ cuttail = 0;
return 0;
}
delstrt = temp;
@@ -1175,23 +1223,23 @@ removerevs()
if (delrev.code == 2) { /* -o rev- */
if ( length == 2 ) {
temp = searchcutpt(target->num, 1,gendeltas);
- if ( flag)
+ if (cmp)
cuttail = target;
else
cuttail = target->next;
}
else {
- if ( flag){
+ if (cmp) {
cuthead = target;
if ( !(temp = target->next) ) return 0;
}
else
temp = searchcutpt(target->num, length, gendeltas);
getbranchno(temp->num, &numrev); /* get branch number */
- target = genrevs(numrev.string, (char*)nil, (char*)nil, (char*)nil, &gendeltas);
+ VOID genrevs(numrev.string, (char*)0, (char*)0, (char*)0, &gendeltas);
}
if ( branchpoint( temp, cuttail ) ) {
- cuttail = nil;
+ cuttail = 0;
return 0;
}
delstrt = temp;
@@ -1202,28 +1250,29 @@ removerevs()
if (!expandsym(delrev.end, &numrev)) return 0;
if (
length != countnumflds(numrev.string)
- || length>2 && compartial(numrev.string, target->num, length-1)
+ || (length>2 && compartial(numrev.string, target->num, length-1))
) {
- error("invalid revision range %s-%s", target->num, numrev.string);
+ rcserror("invalid revision range %s-%s",
+ target->num, numrev.string
+ );
return 0;
}
- target2 = genrevs(numrev.string,(char*)nil,(char*)nil,(char*)nil,&gendeltas);
+ target2 = genrevs(numrev.string,(char*)0,(char*)0,(char*)0,&gendeltas);
if ( ! target2 ) return 0;
if ( length > 2) { /* delete revisions on branches */
if ( cmpnum(target->num, target2->num) > 0) {
- if (cmpnum(target2->num, numrev.string))
- flag = true;
- else
- flag = false;
+ cmp = cmpnum(target2->num, numrev.string);
temp = target;
target = target2;
target2 = temp;
}
- if ( flag ) {
+ if (cmp) {
if ( ! cmpnum(target->num, target2->num) ) {
- error("Revisions %s-%s don't exist.", delrev.strt,delrev.end);
+ rcserror("Revisions %s-%s don't exist.",
+ delrev.strt, delrev.end
+ );
return 0;
}
cuthead = target;
@@ -1240,13 +1289,12 @@ removerevs()
target2 = temp;
}
else
- if (cmpnum(target2->num, numrev.string))
- flag = true;
- else
- flag = false;
- if ( flag ) {
+ cmp = cmpnum(target2->num, numrev.string);
+ if (cmp) {
if ( ! cmpnum(target->num, target2->num) ) {
- error("Revisions %s-%s don't exist.", delrev.strt, delrev.end);
+ rcserror("Revisions %s-%s don't exist.",
+ delrev.strt, delrev.end
+ );
return 0;
}
cuttail = target2;
@@ -1256,7 +1304,7 @@ removerevs()
temp = searchcutpt(target->num, length, gendeltas);
}
if ( branchpoint(temp, cuttail) ) {
- cuttail = nil;
+ cuttail = 0;
return 0;
}
delstrt = temp;
@@ -1265,32 +1313,29 @@ removerevs()
- static void
+ static int
doassoc()
-/* Function: add or delete(if revno is nil) association */
-/* which is stored in assoclst */
-
+/* Add or delete (if !revno) association that is stored in assoclst. */
{
char const *p;
+ int changed = false;
struct Symrev const *curassoc;
- struct assoc * pre, * pt;
+ struct assoc **pre, *pt;
/* add new associations */
- curassoc = assoclst;
- while( curassoc ) {
- if ( curassoc->revno == nil ) { /* delete symbol */
- pre = pt = Symbols;
- while( pt && strcmp(pt->symbol,curassoc->ssymbol) ) {
- pre = pt;
- pt = pt->nextassoc;
- }
- if ( pt )
- if ( pre == pt )
- Symbols = pt->nextassoc;
- else
- pre->nextassoc = pt->nextassoc;
- else
- warn("can't delete nonexisting symbol %s",curassoc->ssymbol);
+ for (curassoc = assoclst; curassoc; curassoc = curassoc->nextsym) {
+ char const *ssymbol = curassoc->ssymbol;
+
+ if (!curassoc->revno) { /* delete symbol */
+ for (pre = &Symbols; ; pre = &pt->nextassoc)
+ if (!(pt = *pre)) {
+ rcswarn("can't delete nonexisting symbol %s", ssymbol);
+ break;
+ } else if (strcmp(pt->symbol, ssymbol) == 0) {
+ *pre = pt->nextassoc;
+ changed = true;
+ break;
+ }
}
else {
if (curassoc->revno[0]) {
@@ -1298,20 +1343,19 @@ doassoc()
if (expandsym(curassoc->revno, &numrev))
p = fstr_save(numrev.string);
} else if (!(p = tiprev()))
- error("no latest revision to associate with symbol %s",
- curassoc->ssymbol
+ rcserror("no latest revision to associate with symbol %s",
+ ssymbol
);
if (p)
- VOID addsymbol(p, curassoc->ssymbol, curassoc->override);
+ changed |= addsymbol(p, ssymbol, curassoc->override);
}
- curassoc = curassoc->nextsym;
}
-
+ return changed;
}
- static void
+ static int
dolocks()
/* Function: remove lock for caller or first lock if unlockcaller is set;
* remove locks which are stored in rmvlocklst,
@@ -1321,64 +1365,60 @@ dolocks()
{
struct Lockrev const *lockpt;
struct hshentry *target;
+ int changed = false;
if (unlockcaller) { /* find lock for caller */
if ( Head ) {
if (Locks) {
switch (findlock(true, &target)) {
case 0:
- breaklock(Locks->delta); /* remove most recent lock */
+ /* remove most recent lock */
+ changed |= breaklock(Locks->delta);
break;
case 1:
diagnose("%s unlocked\n",target->num);
+ changed = true;
break;
}
} else {
- warn("No locks are set.");
+ rcswarn("No locks are set.");
}
} else {
- warn("can't unlock an empty tree");
+ rcswarn("can't unlock an empty tree");
}
}
/* remove locks which are stored in rmvlocklst */
- lockpt = rmvlocklst;
- while( lockpt ) {
+ for (lockpt = rmvlocklst; lockpt; lockpt = lockpt->nextrev)
if (expandsym(lockpt->revno, &numrev)) {
- target = genrevs(numrev.string, (char *)nil, (char *)nil, (char *)nil, &gendeltas);
+ target = genrevs(numrev.string, (char *)0, (char *)0, (char *)0, &gendeltas);
if ( target )
if (!(countnumflds(numrev.string)&1) && cmpnum(target->num,numrev.string))
- error("can't unlock nonexisting revision %s",lockpt->revno);
+ rcserror("can't unlock nonexisting revision %s",
+ lockpt->revno
+ );
else
- breaklock(target);
+ changed |= breaklock(target);
/* breaklock does its own diagnose */
}
- lockpt = lockpt->nextrev;
- }
/* add new locks which stored in newlocklst */
- lockpt = newlocklst;
- while( lockpt ) {
- setlock(lockpt->revno);
- lockpt = lockpt->nextrev;
- }
-
- if (lockhead) { /* lock default branch or head */
- if (Dbranch) {
- setlock(Dbranch);
- } else if (Head) {
- if (0 <= addlock(Head))
- diagnose("%s locked\n",Head->num);
- } else {
- warn("can't lock an empty tree");
- }
- }
-
+ for (lockpt = newlocklst; lockpt; lockpt = lockpt->nextrev)
+ changed |= setlock(lockpt->revno);
+
+ if (lockhead) /* lock default branch or head */
+ if (Dbranch)
+ changed |= setlock(Dbranch);
+ else if (Head)
+ changed |= setlock(Head->num);
+ else
+ rcswarn("can't lock an empty tree");
+ return changed;
}
- static void
+ static int
setlock(rev)
char const *rev;
/* Function: Given a revision or branch number, finds the corresponding
@@ -1386,25 +1426,36 @@ setlock(rev)
*/
{
struct hshentry *target;
+ int r;
if (expandsym(rev, &numrev)) {
- target = genrevs(numrev.string, (char*)nil, (char*)nil,
- (char*)nil, &gendeltas);
+ target = genrevs(numrev.string, (char*)0, (char*)0,
+ (char*)0, &gendeltas);
if ( target )
if (!(countnumflds(numrev.string)&1) && cmpnum(target->num,numrev.string))
- error("can't lock nonexisting revision %s", numrev.string);
- else
- if (0 <= addlock(target))
- diagnose("%s locked\n", target->num);
- }
+ rcserror("can't lock nonexisting revision %s",
+ numrev.string
+ );
+ else {
+ if ((r = addlock(target, false)) < 0 && breaklock(target))
+ r = addlock(target, true);
+ if (0 <= r) {
+ if (r)
+ diagnose("%s locked\n", target->num);
+ return r;
+ }
+ }
+ }
+ return 0;
}
- static void
+ static int
domessages()
{
struct hshentry *target;
struct Message *p;
+ int changed = false;
for (p = messagelst; p; p = p->nextmessage)
if (
@@ -1412,12 +1463,19 @@ domessages()
(target = genrevs(
numrev.string, (char*)0, (char*)0, (char*)0, &gendeltas
))
- )
+ ) {
+ /*
+ * We can't check the old log -- it's much later in the file.
+ * We pessimistically assume that it changed.
+ */
target->log = p->message;
+ changed = true;
+ }
+ return changed;
}
- static void
+ static int
rcs_setstate(rev,status)
char const *rev, *status;
/* Function: Given a revision or branch number, finds the corresponding delta
@@ -1427,15 +1485,19 @@ rcs_setstate(rev,status)
struct hshentry *target;
if (expandsym(rev, &numrev)) {
- target = genrevs(numrev.string, (char*)nil, (char*)nil,
- (char*)nil, &gendeltas);
+ target = genrevs(numrev.string, (char*)0, (char*)0,
+ (char*)0, &gendeltas);
if ( target )
if (!(countnumflds(numrev.string)&1) && cmpnum(target->num,numrev.string))
- error("can't set state of nonexisting revision %s to %s",
- numrev.string, status);
- else
+ rcserror("can't set state of nonexisting revision %s",
+ numrev.string
+ );
+ else if (strcmp(target->state, status) != 0) {
target->state = status;
- }
+ return true;
+ }
+ }
+ return false;
}
@@ -1449,15 +1511,15 @@ buildeltatext(deltas)
/* change to delta text */
{
register FILE *fcut; /* temporary file to rebuild delta tree */
- char const *cutfilename, *diffilename;
+ char const *cutname;
- cutfilename = nil;
+ fcut = 0;
cuttail->selector = false;
scanlogtext(deltas->first, false);
if ( cuthead ) {
- cutfilename = maketemp(3);
- if (!(fcut = fopen(cutfilename, FOPEN_W_WORK))) {
- efaterror(cutfilename);
+ cutname = maketemp(3);
+ if (!(fcut = fopenSafer(cutname, FOPEN_WPLUS_WORK))) {
+ efaterror(cutname);
}
while (deltas->first != cuthead) {
@@ -1466,25 +1528,36 @@ buildeltatext(deltas)
}
snapshotedit(fcut);
- Ofclose(fcut);
+ Orewind(fcut);
+ aflush(fcut);
}
while (deltas->first != cuttail)
scanlogtext((deltas = deltas->rest)->first, true);
- finishedit((struct hshentry *)nil, (FILE*)0, true);
+ finishedit((struct hshentry*)0, (FILE*)0, true);
Ozclose(&fcopy);
- if ( cuthead ) {
- diffilename = maketemp(0);
- switch (run((char*)nil,diffilename,
- DIFF DIFF_FLAGS, cutfilename, resultfile, (char*)nil
- )) {
+ if (fcut) {
+ char const *diffname = maketemp(0);
+ char const *diffv[6 + !!OPEN_O_BINARY];
+ char const **diffp = diffv;
+ *++diffp = DIFF;
+ *++diffp = DIFFFLAGS;
+# if OPEN_O_BINARY
+ if (Expand == BINARY_EXPAND)
+ *++diffp == "--binary";
+# endif
+ *++diffp = "-";
+ *++diffp = resultname;
+ *++diffp = 0;
+ switch (runv(fileno(fcut), diffname, diffv)) {
case DIFF_FAILURE: case DIFF_SUCCESS: break;
- default: faterror ("diff failed");
+ default: rcsfaterror("diff failed");
}
- return putdtext(cuttail->num,cuttail->log,diffilename,frewrite,true);
+ Ofclose(fcut);
+ return putdtext(cuttail,diffname,frewrite,true);
} else
- return putdtext(cuttail->num,cuttail->log,resultfile,frewrite,false);
+ return putdtext(cuttail,resultname,frewrite,false);
}
@@ -1515,9 +1588,9 @@ buildtree()
pre->nextbranch = pt->nextbranch;
}
else {
- if ( cuttail == nil && !quietflag) {
+ if (!cuttail && !quietflag) {
if (!yesorno(false, "Do you really want to delete all revisions? [ny](n): ")) {
- error("No revision deleted");
+ rcserror("No revision deleted");
Delta = delstrt;
while( Delta) {
Delta->selector = true;
@@ -1531,7 +1604,7 @@ buildtree()
return;
}
-#if lint
+#if RCS_lint
/* This lets us lint everything all at once. */
char const cmdid[] = "";
diff --git a/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c b/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c
index 01d1942..d741f95 100644
--- a/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c
+++ b/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c
@@ -1,13 +1,7 @@
-/*
- * RCS rcsdiff operation
- */
-/*****************************************************************************
- * generate difference between RCS revisions
- *****************************************************************************
- */
+/* Compare RCS revisions. */
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -23,8 +17,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -32,12 +27,37 @@ Report problems and direct all questions to:
*/
-
-
-
-/* $Log: rcsdiff.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:16 jkh
- * Updated GNU utilities
+/*
+ * $Log: rcsdiff.c,v $
+ * Revision 5.19 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.18 1995/06/01 16:23:43 eggert
+ * (main): Pass "--binary" if -kb and if --binary makes a difference.
+ * Don't treat + options specially.
+ *
+ * Revision 5.17 1994/03/17 14:05:48 eggert
+ * Specify subprocess input via file descriptor, not file name. Remove lint.
+ *
+ * Revision 5.16 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits. Don't print usage twice.
+ *
+ * Revision 5.15 1993/11/03 17:42:27 eggert
+ * Add -z. Ignore -T. Pass -Vn to `co'. Add Name keyword.
+ * Put revision numbers in -c output. Improve quality of diagnostics.
+ *
+ * Revision 5.14 1992/07/28 16:12:44 eggert
+ * Add -V. Use co -M for better dates with traditional diff -c.
+ *
+ * Revision 5.13 1992/02/17 23:02:23 eggert
+ * Output more readable context diff headers.
+ * Suppress needless checkout and comparison of identical revisions.
+ *
+ * Revision 5.12 1992/01/24 18:44:19 eggert
+ * Add GNU diff 1.15.2's new options. lint -> RCS_lint
+ *
+ * Revision 5.11 1992/01/06 02:42:34 eggert
+ * Update usage string.
*
* Revision 5.10 1991/10/07 17:32:46 eggert
* Remove lint.
@@ -132,29 +152,30 @@ static int exitstatus;
static RILE *workptr;
static struct stat workstat;
-mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 1.1.1.1 1993/06/18 04:22:16 jkh Exp $")
+mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 5.19 1995/06/16 06:19:24 eggert Exp $")
{
static char const cmdusage[] =
- "\nrcsdiff usage: rcsdiff [-q] [-rrev1 [-rrev2]] [-Vn] [diff options] file ...";
+ "\nrcsdiff usage: rcsdiff -ksubst -q -rrev1 [-rrev2] -Vn -xsuff -zzone [diff options] file ...";
int revnums; /* counter for revision numbers given */
char const *rev1, *rev2; /* revision numbers from command line */
char const *xrev1, *xrev2; /* expanded revision numbers */
- char const *expandarg, *lexpandarg, *versionarg;
+ char const *expandarg, *lexpandarg, *suffixarg, *versionarg, *zonearg;
#if DIFF_L
static struct buf labelbuf[2];
int file_labels;
char const **diff_label1, **diff_label2;
char date2[datesize];
#endif
- char const *cov[9];
- char const **diffv, **diffp; /* argv for subsidiary diff */
+ char const *cov[10 + !DIFF_L];
+ char const **diffv, **diffp, **diffpend; /* argv for subsidiary diff */
char const **pp, *p, *diffvstr;
struct buf commarg;
struct buf numericrev; /* expanded revision number */
struct hshentries *gendeltas; /* deltas to be generated */
struct hshentry * target;
char *a, *dcp, **newargv;
+ int no_diff_means_no_output;
register c;
exitstatus = DIFF_SUCCESS;
@@ -162,38 +183,42 @@ mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 1.1.1.1 1993/06/18 04:22:16 jkh
bufautobegin(&commarg);
bufautobegin(&numericrev);
revnums = 0;
- rev1 = rev2 = xrev2 = nil;
+ rev1 = rev2 = xrev2 = 0;
#if DIFF_L
file_labels = 0;
#endif
- expandarg = versionarg = 0;
+ expandarg = suffixarg = versionarg = zonearg = 0;
+ no_diff_means_no_output = true;
suffixes = X_DEFAULT;
- /* Room for args + 2 i/o [+ 2 labels] + 1 file + 1 trailing null. */
- diffp = diffv = tnalloc(char const*, argc + 4 + 2*DIFF_L);
- *diffp++ = nil;
- *diffp++ = nil;
+ /*
+ * Room for runv extra + args [+ --binary] [+ 2 labels]
+ * + 1 file + 1 trailing null.
+ */
+ diffv = tnalloc(char const*, 1 + argc + !!OPEN_O_BINARY + 2*DIFF_L + 2);
+ diffp = diffv + 1;
*diffp++ = DIFF;
argc = getRCSINIT(argc, argv, &newargv);
argv = newargv;
while (a = *++argv, 0<--argc && *a++=='-') {
dcp = a;
- while (c = *a++) switch (c) {
+ while ((c = *a++)) switch (c) {
case 'r':
switch (++revnums) {
case 1: rev1=a; break;
case 2: rev2=a; break;
- default: faterror("too many revision numbers");
+ default: error("too many revision numbers");
}
goto option_handled;
+ case '-': case 'D':
+ no_diff_means_no_output = false;
+ /* fall into */
+ case 'C': case 'F': case 'I': case 'L': case 'W':
#if DIFF_L
- case 'L':
- if (++file_labels == 2)
+ if (c == 'L' && ++file_labels == 2)
faterror("too many -L options");
- /* fall into */
#endif
- case 'C': case 'D': case 'F': case 'I':
*dcp++ = c;
if (*a)
do *dcp++ = *a++;
@@ -206,7 +231,10 @@ mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 1.1.1.1 1993/06/18 04:22:16 jkh
*diffp++ = *argv++;
}
break;
- case 'B': case 'H': case 'T':
+ case 'y':
+ no_diff_means_no_output = false;
+ /* fall into */
+ case 'B': case 'H':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
@@ -218,8 +246,18 @@ mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 1.1.1.1 1993/06/18 04:22:16 jkh
quietflag=true;
break;
case 'x':
+ suffixarg = *argv;
suffixes = *argv + 2;
goto option_handled;
+ case 'z':
+ zonearg = *argv;
+ zone_set(*argv + 2);
+ goto option_handled;
+ case 'T':
+ /* Ignore -T, so that RCSINIT can contain -T. */
+ if (*a)
+ goto unknown;
+ break;
case 'V':
versionarg = *argv;
setRCSversion(versionarg);
@@ -230,7 +268,8 @@ mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 1.1.1.1 1993/06/18 04:22:16 jkh
goto option_handled;
/* fall into */
default:
- faterror("unknown option: %s%s", *argv, cmdusage);
+ unknown:
+ error("unknown option: %s%s", *argv, cmdusage);
};
option_handled:
if (dcp != *argv+1) {
@@ -239,12 +278,10 @@ mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 1.1.1.1 1993/06/18 04:22:16 jkh
}
} /* end of option processing */
- if (argc<1) faterror("no input file%s", cmdusage);
-
- for (pp = diffv+3, c = 0; pp<diffp; )
+ for (pp = diffv+2, c = 0; pp<diffp; )
c += strlen(*pp++) + 1;
diffvstr = a = tnalloc(char, c + 1);
- for (pp = diffv+3; pp<diffp; ) {
+ for (pp = diffv+2; pp<diffp; ) {
p = *pp++;
*a++ = ' ';
while ((*a = *p++))
@@ -253,30 +290,37 @@ mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 1.1.1.1 1993/06/18 04:22:16 jkh
*a = 0;
#if DIFF_L
- diff_label1 = diff_label2 = nil;
+ diff_label1 = diff_label2 = 0;
if (file_labels < 2) {
if (!file_labels)
diff_label1 = diffp++;
diff_label2 = diffp++;
}
#endif
- diffp[2] = nil;
-
- cov[0] = 0;
- cov[2] = CO;
- cov[3] = "-q";
-
- /* now handle all filenames */
- do {
+ diffpend = diffp;
+
+ cov[1] = CO;
+ cov[2] = "-q";
+# if !DIFF_L
+ cov[3] = "-M";
+# endif
+
+ /* Now handle all pathnames. */
+ if (nerror)
+ cleanup();
+ else if (argc < 1)
+ faterror("no input file%s", cmdusage);
+ else
+ for (; 0 < argc; cleanup(), ++argv, --argc) {
ffree();
- if (pairfilenames(argc, argv, rcsreadopen, true, false) <= 0)
+ if (pairnames(argc, argv, rcsreadopen, true, false) <= 0)
continue;
- diagnose("===================================================================\nRCS file: %s\n",RCSfilename);
+ diagnose("===================================================================\nRCS file: %s\n",RCSname);
if (!rev2) {
/* Make sure work file is readable, and get its status. */
- if (!(workptr = Iopen(workfilename,FOPEN_R_WORK,&workstat))) {
- eerror(workfilename);
+ if (!(workptr = Iopen(workname, FOPEN_R_WORK, &workstat))) {
+ eerror(workname);
continue;
}
}
@@ -284,15 +328,15 @@ mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 1.1.1.1 1993/06/18 04:22:16 jkh
gettree(); /* reads in the delta tree */
- if (Head==nil) {
- error("no revisions present");
+ if (!Head) {
+ rcserror("no revisions present");
continue;
}
if (revnums==0 || !*rev1)
rev1 = Dbranch ? Dbranch : Head->num;
if (!fexpandsym(rev1, &numericrev, workptr)) continue;
- if (!(target=genrevs(numericrev.string,(char *)nil,(char *)nil,(char *)nil,&gendeltas))) continue;
+ if (!(target=genrevs(numericrev.string,(char *)0,(char *)0,(char *)0,&gendeltas))) continue;
xrev1=target->num;
#if DIFF_L
if (diff_label1)
@@ -307,8 +351,10 @@ mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 1.1.1.1 1993/06/18 04:22:16 jkh
workptr
))
continue;
- if (!(target=genrevs(numericrev.string,(char *)nil,(char *)nil,(char *)nil,&gendeltas))) continue;
+ if (!(target=genrevs(numericrev.string,(char *)0,(char *)0,(char *)0,&gendeltas))) continue;
xrev2=target->num;
+ if (no_diff_means_no_output && xrev1 == xrev2)
+ continue;
} else if (
target->lockedby
&& !lexpandarg
@@ -323,55 +369,60 @@ mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 1.1.1.1 1993/06/18 04:22:16 jkh
*diff_label2 = setup_label(&labelbuf[1], target->num, target->date);
else {
time2date(workstat.st_mtime, date2);
- *diff_label2 = setup_label(&labelbuf[1], workfilename, date2);
+ *diff_label2 = setup_label(&labelbuf[1], (char*)0, date2);
}
#endif
diagnose("retrieving revision %s\n", xrev1);
bufscpy(&commarg, "-p");
- bufscat(&commarg, xrev1);
+ bufscat(&commarg, rev1); /* not xrev1, for $Name's sake */
- cov[1] = diffp[0] = maketemp(0);
- pp = &cov[4];
+ pp = &cov[3 + !DIFF_L];
*pp++ = commarg.string;
- if (lexpandarg)
- *pp++ = lexpandarg;
- if (versionarg)
- *pp++ = versionarg;
- *pp++ = RCSfilename;
+ if (lexpandarg) *pp++ = lexpandarg;
+ if (suffixarg) *pp++ = suffixarg;
+ if (versionarg) *pp++ = versionarg;
+ if (zonearg) *pp++ = zonearg;
+ *pp++ = RCSname;
*pp = 0;
- if (runv(cov)) {
- error("co failed");
+ diffp = diffpend;
+# if OPEN_O_BINARY
+ if (Expand == BINARY_EXPAND)
+ *diffp++ = "--binary";
+# endif
+ diffp[0] = maketemp(0);
+ if (runv(-1, diffp[0], cov)) {
+ rcserror("co failed");
continue;
}
if (!rev2) {
- diffp[1] = workfilename;
- if (workfilename[0] == '+') {
- /* Some diffs have options with leading '+'. */
- char *dp = ftnalloc(char, strlen(workfilename)+3);
+ diffp[1] = workname;
+ if (*workname == '-') {
+ char *dp = ftnalloc(char, strlen(workname)+3);
diffp[1] = dp;
*dp++ = '.';
*dp++ = SLASH;
- VOID strcpy(dp, workfilename);
+ VOID strcpy(dp, workname);
}
} else {
diagnose("retrieving revision %s\n",xrev2);
bufscpy(&commarg, "-p");
- bufscat(&commarg, xrev2);
- cov[1] = diffp[1] = maketemp(1);
- cov[4] = commarg.string;
- if (runv(cov)) {
- error("co failed");
+ bufscat(&commarg, rev2); /* not xrev2, for $Name's sake */
+ cov[3 + !DIFF_L] = commarg.string;
+ diffp[1] = maketemp(1);
+ if (runv(-1, diffp[1], cov)) {
+ rcserror("co failed");
continue;
}
}
if (!rev2)
- diagnose("diff%s -r%s %s\n", diffvstr, xrev1, workfilename);
+ diagnose("diff%s -r%s %s\n", diffvstr, xrev1, workname);
else
diagnose("diff%s -r%s -r%s\n", diffvstr, xrev1, xrev2);
- switch (runv(diffv)) {
+ diffp[2] = 0;
+ switch (runv(-1, (char*)0, diffv)) {
case DIFF_SUCCESS:
break;
case DIFF_FAILURE:
@@ -379,11 +430,9 @@ mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 1.1.1.1 1993/06/18 04:22:16 jkh
exitstatus = DIFF_FAILURE;
break;
default:
- error("diff failed");
+ workerror("diff failed");
}
- } while (cleanup(),
- ++argv, --argc >=1);
-
+ }
tempunlink();
exitmain(exitstatus);
@@ -397,10 +446,10 @@ cleanup()
Izclose(&workptr);
}
-#if lint
+#if RCS_lint
# define exiterr rdiffExit
#endif
- exiting void
+ void
exiterr()
{
tempunlink();
@@ -409,17 +458,24 @@ exiterr()
#if DIFF_L
static char const *
-setup_label(b, name, date)
+setup_label(b, num, date)
struct buf *b;
- char const *name;
+ char const *num;
char const date[datesize];
{
char *p;
- size_t l = strlen(name) + 3;
- bufalloc(b, l+datesize);
+ char datestr[datesize + zonelenmax];
+ VOID date2str(date, datestr);
+ bufalloc(b,
+ strlen(workname)
+ + sizeof datestr + 4
+ + (num ? strlen(num) : 0)
+ );
p = b->string;
- VOID sprintf(p, "-L%s\t", name);
- VOID date2str(date, p+l);
+ if (num)
+ VOID sprintf(p, "-L%s\t%s\t%s", workname, datestr, num);
+ else
+ VOID sprintf(p, "-L%s\t%s", workname, datestr);
return p;
}
#endif
diff --git a/gnu/usr.bin/rcs/rcsmerge/rcsmerge.c b/gnu/usr.bin/rcs/rcsmerge/rcsmerge.c
index f5c46a8..30f4a8b 100644
--- a/gnu/usr.bin/rcs/rcsmerge/rcsmerge.c
+++ b/gnu/usr.bin/rcs/rcsmerge/rcsmerge.c
@@ -1,13 +1,7 @@
-/*
- * rcsmerge operation
- */
-/*****************************************************************************
- * join 2 revisions with respect to a third
- *****************************************************************************
- */
+/* Merge RCS revisions. */
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -23,8 +17,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -32,11 +27,33 @@ Report problems and direct all questions to:
*/
-
-
-/* $Log: rcsmerge.c,v $
- * Revision 1.1.1.1 1993/06/18 04:22:16 jkh
- * Updated GNU utilities
+/*
+ * $Log: rcsmerge.c,v $
+ * Revision 5.15 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.14 1995/06/01 16:23:43 eggert
+ * (main): Report an error if -kb, so don't worry about binary stdout.
+ * Punctuate messages properly. Rewrite to avoid `goto end'.
+ *
+ * Revision 5.13 1994/03/17 14:05:48 eggert
+ * Specify subprocess input via file descriptor, not file name. Remove lint.
+ *
+ * Revision 5.12 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits. Don't print usage twice.
+ *
+ * Revision 5.11 1993/11/03 17:42:27 eggert
+ * Add -A, -E, -e, -z. Ignore -T. Allow up to three file labels.
+ * Pass -Vn to `co'. Pass unexpanded revision name to `co', so that Name works.
+ *
+ * Revision 5.10 1992/07/28 16:12:44 eggert
+ * Add -V.
+ *
+ * Revision 5.9 1992/01/24 18:44:19 eggert
+ * lint -> RCS_lint
+ *
+ * Revision 5.8 1992/01/06 02:42:34 eggert
+ * Update usage string.
*
* Revision 5.7 1991/11/20 17:58:09 eggert
* Don't Iopen(f, "r+"); it's not portable.
@@ -101,17 +118,17 @@ Report problems and direct all questions to:
static char const co[] = CO;
-mainProg(rcsmergeId, "rcsmerge", "$Id: rcsmerge.c,v 1.1.1.1 1993/06/18 04:22:16 jkh Exp $")
+mainProg(rcsmergeId, "rcsmerge", "$Id: rcsmerge.c,v 5.15 1995/06/16 06:19:24 eggert Exp $")
{
static char const cmdusage[] =
- "\nrcsmerge usage: rcsmerge -rrev1 [-rrev2] [-p] [-Vn] file";
+ "\nrcsmerge usage: rcsmerge -rrev1 [-rrev2] -ksubst -{pq}[rev] -Vn -xsuff -zzone file";
static char const quietarg[] = "-q";
register int i;
char *a, **newargv;
char const *arg[3];
- char const *rev[2]; /*revision numbers*/
- char const *expandarg, *versionarg;
+ char const *rev[3], *xrev[3]; /*revision numbers*/
+ char const *edarg, *expandarg, *suffixarg, *versionarg, *zonearg;
int tostdout;
int status;
RILE *workptr;
@@ -122,10 +139,10 @@ mainProg(rcsmergeId, "rcsmerge", "$Id: rcsmerge.c,v 1.1.1.1 1993/06/18 04:22:16
bufautobegin(&commarg);
bufautobegin(&numericrev);
- rev[0] = rev[1] = nil;
+ edarg = rev[1] = rev[2] = 0;
status = 0; /* Keep lint happy. */
tostdout = false;
- expandarg = versionarg = quietarg; /* i.e. a no-op */
+ expandarg = suffixarg = versionarg = zonearg = quietarg; /* no-op */
suffixes = X_DEFAULT;
argc = getRCSINIT(argc, argv, &newargv);
@@ -143,16 +160,33 @@ mainProg(rcsmergeId, "rcsmerge", "$Id: rcsmerge.c,v 1.1.1.1 1993/06/18 04:22:16
break;
/* falls into -r */
case 'r':
- if (!rev[0])
- rev[0] = a;
- else if (!rev[1])
+ if (!rev[1])
rev[1] = a;
+ else if (!rev[2])
+ rev[2] = a;
else
- faterror("too many revision numbers");
+ error("too many revision numbers");
break;
+
+ case 'A': case 'E': case 'e':
+ if (*a)
+ goto unknown;
+ edarg = *argv;
+ break;
+
case 'x':
+ suffixarg = *argv;
suffixes = a;
break;
+ case 'z':
+ zonearg = *argv;
+ zone_set(a);
+ break;
+ case 'T':
+ /* Ignore -T, so that RCSINIT can contain -T. */
+ if (*a)
+ goto unknown;
+ break;
case 'V':
versionarg = *argv;
setRCSversion(versionarg);
@@ -164,90 +198,88 @@ mainProg(rcsmergeId, "rcsmerge", "$Id: rcsmerge.c,v 1.1.1.1 1993/06/18 04:22:16
break;
/* fall into */
default:
- faterror("unknown option: %s%s", *argv, cmdusage);
+ unknown:
+ error("unknown option: %s%s", *argv, cmdusage);
};
} /* end of option processing */
- if (argc<1) faterror("no input file%s", cmdusage);
- if (!rev[0]) faterror("no base revision number given");
+ if (!rev[1]) faterror("no base revision number given");
- /* now handle all filenames */
+ /* Now handle all pathnames. */
- if (0 < pairfilenames(argc, argv, rcsreadopen, true, false)) {
+ if (!nerror) {
+ if (argc < 1)
+ faterror("no input file%s", cmdusage);
+ if (0 < pairnames(argc, argv, rcsreadopen, true, false)) {
- if (argc>2 || (argc==2&&argv[1]!=nil))
- warn("too many arguments");
- diagnose("RCS file: %s\n", RCSfilename);
- if (!(workptr = Iopen(workfilename,
- FOPEN_R_WORK,
- (struct stat*)0
- )))
- efaterror(workfilename);
+ if (argc>2 || (argc==2 && argv[1]))
+ warn("excess arguments ignored");
+ if (Expand == BINARY_EXPAND)
+ workerror("merging binary files");
+ diagnose("RCS file: %s\n", RCSname);
+ if (!(workptr = Iopen(workname, FOPEN_R_WORK, (struct stat*)0)))
+ efaterror(workname);
gettree(); /* reads in the delta tree */
- if (Head==nil) faterror("no revisions present");
+ if (!Head) rcsfaterror("no revisions present");
- if (!*rev[0])
- rev[0] = Dbranch ? Dbranch : Head->num;
- if (!fexpandsym(rev[0], &numericrev, workptr))
- goto end;
- if (!(target=genrevs(numericrev.string, (char *)nil, (char *)nil, (char *)nil,&gendeltas))) goto end;
- rev[0] = target->num;
- if (!rev[1] || !*rev[1])
+ if (!*rev[1])
rev[1] = Dbranch ? Dbranch : Head->num;
- if (!fexpandsym(rev[1], &numericrev, workptr))
- goto end;
- if (!(target=genrevs(numericrev.string, (char *)nil, (char *)nil, (char *)nil,&gendeltas))) goto end;
- rev[1] = target->num;
-
- if (strcmp(rev[0],rev[1]) == 0) {
- if (tostdout) {
- FILE *o;
-# if text_equals_binary_stdio || text_work_stdio
- o = stdout;
-# else
- if (!(o=fdopen(STDOUT_FILENO,FOPEN_W_WORK)))
- efaterror("stdout");
-# endif
- fastcopy(workptr,o);
- Ofclose(o);
- }
- goto end;
- }
- Izclose(&workptr);
+ if (fexpandsym(rev[1], &numericrev, workptr)
+ && (target=genrevs(numericrev.string, (char *)0, (char *)0, (char*)0, &gendeltas))
+ ) {
+ xrev[1] = target->num;
+ if (!rev[2] || !*rev[2])
+ rev[2] = Dbranch ? Dbranch : Head->num;
+ if (fexpandsym(rev[2], &numericrev, workptr)
+ && (target=genrevs(numericrev.string, (char *)0, (char *)0, (char *)0, &gendeltas))
+ ) {
+ xrev[2] = target->num;
+
+ if (strcmp(xrev[1],xrev[2]) == 0) {
+ if (tostdout) {
+ fastcopy(workptr, stdout);
+ Ofclose(stdout);
+ }
+ } else {
+ Izclose(&workptr);
- for (i=0; i<2; i++) {
- diagnose("retrieving revision %s\n", rev[i]);
+ for (i=1; i<=2; i++) {
+ diagnose("retrieving revision %s\n", xrev[i]);
bufscpy(&commarg, "-p");
- bufscat(&commarg, rev[i]);
+ bufscat(&commarg, rev[i]); /* not xrev[i], for $Name's sake */
if (run(
- (char*)0,
+ -1,
/* Do not collide with merger.c maketemp(). */
- arg[i+1] = maketemp(i+3),
- co, quietarg, commarg.string, expandarg,
- versionarg, RCSfilename, (char*)0
+ arg[i] = maketemp(i+2),
+ co, quietarg, commarg.string,
+ expandarg, suffixarg, versionarg, zonearg,
+ RCSname, (char*)0
))
- faterror("co failed");
+ rcsfaterror("co failed");
+ }
+ diagnose("Merging differences between %s and %s into %s%s\n",
+ xrev[1], xrev[2], workname,
+ tostdout?"; result to stdout":"");
+
+ arg[0] = xrev[0] = workname;
+ status = merge(tostdout, edarg, xrev, arg);
+ }
+ }
}
- diagnose("Merging differences between %s and %s into %s%s\n",
- rev[0], rev[1], workfilename,
- tostdout?"; result to stdout":"");
- arg[0] = rev[0] = workfilename;
- status = merge(tostdout, rev, arg);
+ Izclose(&workptr);
+ }
}
-
-end:
- Izclose(&workptr);
tempunlink();
exitmain(nerror ? DIFF_TROUBLE : status);
}
-#if lint
+#if RCS_lint
# define exiterr rmergeExit
#endif
- exiting void
+ void
exiterr()
{
tempunlink();
diff --git a/gnu/usr.bin/rcs/rlog/rlog.1 b/gnu/usr.bin/rcs/rlog/rlog.1
index e3deb68..cc4b45c9 100644
--- a/gnu/usr.bin/rcs/rlog/rlog.1
+++ b/gnu/usr.bin/rcs/rlog/rlog.1
@@ -2,9 +2,10 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: rlog.1,v 1.2 1994/05/11 22:39:43 phk Exp $
-.ds g \&\s-1UTC\s0
+.Id $Id: rlog.1,v 5.9 1995/06/16 06:19:24 eggert Exp $
+.ds i \&\s-1ISO\s0
.ds r \&\s-1RCS\s0
+.ds u \&\s-1UTC\s0
.if n .ds - \%--
.if t .ds - \(em
.TH RLOG 1 \*(Dt GNU
@@ -34,13 +35,17 @@ reverse chronological order for each branch. For each revision,
prints revision number, author, date/time, state, number of
lines added/deleted (with respect to the previous revision),
locker of the revision (if any), and log message.
-All times are displayed in Coordinated Universal Time (\*g).
+All times are displayed in Coordinated Universal Time (\*u) by default;
+this can be overridden with
+.BR \-z .
Without options,
.B rlog
prints complete information.
The options below restrict this output.
-.nr n \w'\f3\-V\fP\f2n\fP '+1n-1/1n
-.TP \nn
+.nr n \w'\f3\-V\fP\f2n\fP'+2n-1/1n
+.ds n \nn
+.if \n(.g .if r an-tag-sep .ds n \w'\f3\-V\fP\f2n\fP'u+\n[an-tag-sep]u
+.TP \*n
.B \-L
Ignore \*r files that have no locks set.
This is convenient in combination with
@@ -54,10 +59,6 @@ Print only the name of the \*r file.
This is convenient for translating a
working pathname into an \*r pathname.
.TP
-.BI \-v "[string]"
-Print only the working pathname and tip-revision.
-The optional string is prepended to the outputline.
-.TP
.B \-h
Print only the \*r pathname, working pathname, head,
default branch, access list, locks,
@@ -68,6 +69,9 @@ Print the same as
.BR \-h ,
plus the descriptive text.
.TP
+.B \-N
+Do not print the symbolic names.
+.TP
.B \-b
Print information about the revisions on the default branch, normally
the highest branch on the trunk.
@@ -84,23 +88,28 @@ selects the revisions that were deposited between
.I d1
and
.I d2
-inclusive.
+exclusive.
A range of the form
.BI < d
or
.IB d >
selects
-all revisions dated
-.I d
-or earlier.
+all revisions earlier than
+.IR d .
A range of the form
.IB d <
or
.BI > d
selects
-all revisions dated
-.I d
-or later.
+all revisions dated later than
+.IR d .
+If
+.B <
+or
+.B >
+is followed by
+.B =
+then the ranges are inclusive, not exclusive.
A range of the form
.I d
selects the single, latest revision dated
@@ -178,6 +187,13 @@ If
.I logins
is omitted, the user's login is assumed.
.TP
+.B \-T
+This option has no effect;
+it is present for compatibility with other \*r commands.
+.TP
+.BI \-V
+Print \*r's version number.
+.TP
.BI \-V n
Emulate \*r version
.I n
@@ -207,6 +223,40 @@ with the union of the revisions selected by
.B \-b
and
.BR \-r .
+.TP
+.BI \-z zone
+specifies the date output format,
+and specifies the default time zone for
+.I date
+in the
+.BI \-d dates
+option.
+The
+.I zone
+should be empty, a numeric \*u offset, or the special string
+.B LT
+for local time.
+The default is an empty
+.IR zone ,
+which uses the traditional \*r format of \*u without any time zone indication
+and with slashes separating the parts of the date;
+otherwise, times are output in \*i 8601 format with time zone indication.
+For example, if local time is January 11, 1990, 8pm Pacific Standard Time,
+eight hours west of \*u,
+then the time is output as follows:
+.RS
+.LP
+.RS
+.nf
+.ta \w'\f3\-z+05:30\fP 'u +\w'\f31990-01-11 09:30:00+05:30\fP 'u
+.ne 4
+\f2option\fP \f2time output\fP
+\f3\-z\fP \f31990/01/12 04:00:00\fP \f2(default)\fP
+\f3\-zLT\fP \f31990-01-11 20:00:00\-08\fP
+\f3\-z+05:30\fP \f31990-01-12 09:30:00+05:30\fP
+.ta 4n +4n +4n +4n
+.fi
+.RE
.SH EXAMPLES
.LP
.nf
@@ -233,11 +283,11 @@ The exit status is zero if and only if all operations were successful.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
-Revision Number: \*(Rv; Release Date: \*(Dt.
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
-Copyright \(co 1982, 1988, 1989 by Walter F. Tichy.
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
-Copyright \(co 1990, 1991 by Paul Eggert.
+Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
.SH "SEE ALSO"
ci(1), co(1), ident(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1),
rcsfile(5)
diff --git a/gnu/usr.bin/rcs/rlog/rlog.c b/gnu/usr.bin/rcs/rlog/rlog.c
index 80912bd..f387a1a 100644
--- a/gnu/usr.bin/rcs/rlog/rlog.c
+++ b/gnu/usr.bin/rcs/rlog/rlog.c
@@ -1,13 +1,7 @@
-/*
- * RLOG operation
- */
-/*****************************************************************************
- * print contents of RCS files
- *****************************************************************************
- */
+/* Print log messages and other information about RCS files. */
-/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Copyright 1990, 1991 by Paul Eggert
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
@@ -23,8 +17,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with RCS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
@@ -32,25 +27,41 @@ Report problems and direct all questions to:
*/
-
-
-
-/* $Log: rlog.c,v $
- * Revision 1.5 1994/05/12 00:42:59 phk
- * typo.
+/*
+ * $Log: rlog.c,v $
+ * Revision 5.18 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.17 1995/06/01 16:23:43 eggert
+ * (struct rcslockers): Renamed from `struct lockers'.
+ * (getnumericrev): Return error indication instead of ignoring errors.
+ * (main): Check it. Don't use dateform.
+ * (recentdate, extdate): cmpnum -> cmpdate
+ *
+ * Revision 5.16 1994/04/13 16:30:34 eggert
+ * Fix bug; `rlog -lxxx' inverted the sense of -l.
+ *
+ * Revision 5.15 1994/03/17 14:05:48 eggert
+ * -d'<DATE' now excludes DATE; the new syntax -d'<=DATE' includes it.
+ * Emulate -V4's white space generation more precisely.
+ * Work around SVR4 stdio performance bug. Remove lint.
*
- * Revision 1.4 1994/05/12 00:37:59 phk
- * made -v produce tip-revision, which was what I wanted in the first place...
+ * Revision 5.14 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits.
*
- * Revision 1.3 1994/05/11 22:39:44 phk
- * Added -v option to rlog. This gives a quick way to get a list of versions.
+ * Revision 5.13 1993/11/03 17:42:27 eggert
+ * Add -N, -z. Ignore -T.
*
- * Revision 1.2 1993/08/06 16:47:16 nate
- * Have rlog output be much easier to parse. (Added one line which is not
- * used by any CVS/RCS commands)
+ * Revision 5.12 1992/07/28 16:12:44 eggert
+ * Don't miss B.0 when handling branch B. Diagnose missing `,' in -r.
+ * Add -V. Avoid `unsigned'. Statement macro names now end in _.
*
- * Revision 1.1.1.1 1993/06/18 04:22:17 jkh
- * Updated GNU utilities
+ * Revision 5.11 1992/01/24 18:44:19 eggert
+ * Don't duplicate unexpected_EOF's function. lint -> RCS_lint
+ *
+ * Revision 5.10 1992/01/06 02:42:34 eggert
+ * Update usage string.
+ * while (E) ; -> while (E) continue;
*
* Revision 5.9 1991/09/17 19:07:40 eggert
* Getscript() didn't uncache partial lines.
@@ -147,9 +158,9 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-struct lockers { /* lockers in locker option; stored */
+struct rcslockers { /* lockers in locker option; stored */
char const * login; /* lockerlist */
- struct lockers * lockerlink;
+ struct rcslockers * lockerlink;
} ;
struct stateattri { /* states in state option; stored in */
@@ -163,28 +174,29 @@ struct authors { /* login names in author option; */
} ;
struct Revpairs{ /* revision or branch range in -r */
- unsigned numfld; /* option; stored in revlist */
+ int numfld; /* option; stored in revlist */
char const * strtrev;
char const * endrev;
struct Revpairs * rnext;
} ;
struct Datepairs{ /* date range in -d option; stored in */
+ struct Datepairs *dnext;
char strtdate[datesize]; /* duelst and datelist */
char enddate[datesize];
- struct Datepairs * dnext;
+ char ne_date; /* datelist only; distinguishes < from <= */
};
static char extractdelta P((struct hshentry const*));
static int checkrevpair P((char const*,char const*));
+static int extdate P((struct hshentry*));
+static int getnumericrev P((void));
static struct hshentry const *readdeltalog P((void));
-static unsigned extdate P((struct hshentry*));
static void cleanup P((void));
static void exttree P((struct hshentry*));
static void getauthor P((char*));
static void getdatepair P((char*));
static void getlocker P((char*));
-static void getnumericrev P((void));
static void getrevpairs P((char*));
static void getscript P((struct hshentry*));
static void getstate P((char*));
@@ -203,34 +215,33 @@ static int lockflag;
static struct Datepairs *datelist, *duelst;
static struct Revpairs *revlist, *Revlst;
static struct authors *authorlist;
-static struct lockers *lockerlist;
+static struct rcslockers *lockerlist;
static struct stateattri *statelist;
-mainProg(rlogId, "rlog", "$Id: rlog.c,v 1.5 1994/05/12 00:42:59 phk Exp $")
+mainProg(rlogId, "rlog", "$Id: rlog.c,v 5.18 1995/06/16 06:19:24 eggert Exp $")
{
static char const cmdusage[] =
- "\nrlog usage: rlog -{bhLRt} [-v[string]] -ddates -l[lockers] -rrevs -sstates -w[logins] -Vn file ...";
+ "\nrlog usage: rlog -{bhLNRt} -ddates -l[lockers] -r[revs] -sstates -Vn -w[logins] -xsuff -zzone file ...";
register FILE *out;
char *a, **newargv;
struct Datepairs *currdate;
- char const *accessListString, *accessFormat, *commentFormat;
+ char const *accessListString, *accessFormat;
char const *headFormat, *symbolFormat;
struct access const *curaccess;
struct assoc const *curassoc;
struct hshentry const *delta;
- struct lock const *currlock;
+ struct rcslock const *currlock;
int descflag, selectflag;
int onlylockflag; /* print only files with locks */
- int versionlist;
- char *vstring;
- int onlyRCSflag; /* print only RCS file name */
- unsigned revno;
-
- descflag = selectflag = true;
- versionlist = onlylockflag = onlyRCSflag = false;
- vstring=0;
+ int onlyRCSflag; /* print only RCS pathname */
+ int pre5;
+ int shownames;
+ int revno;
+
+ descflag = selectflag = shownames = true;
+ onlylockflag = onlyRCSflag = false;
out = stdout;
suffixes = X_DEFAULT;
@@ -243,6 +254,10 @@ mainProg(rlogId, "rlog", "$Id: rlog.c,v 1.5 1994/05/12 00:42:59 phk Exp $")
onlylockflag = true;
break;
+ case 'N':
+ shownames = false;
+ break;
+
case 'R':
onlyRCSflag =true;
break;
@@ -289,54 +304,63 @@ mainProg(rlogId, "rlog", "$Id: rlog.c,v 1.5 1994/05/12 00:42:59 phk Exp $")
suffixes = a;
break;
- case 'V':
- setRCSversion(*argv);
+ case 'z':
+ zone_set(a);
+ break;
+
+ case 'T':
+ /* Ignore -T, so that RCSINIT can contain -T. */
+ if (*a)
+ goto unknown;
break;
- case 'v':
- versionlist = true;
- vstring = a;
+ case 'V':
+ setRCSversion(*argv);
break;
default:
- faterror("unknown option: %s%s", *argv, cmdusage);
+ unknown:
+ error("unknown option: %s%s", *argv, cmdusage);
};
} /* end of option processing */
- if (argc<1) faterror("no input file%s", cmdusage);
-
if (! (descflag|selectflag)) {
warn("-t overrides -h.");
descflag = true;
}
- if (RCSversion < VERSION(5)) {
+ pre5 = RCSversion < VERSION(5);
+ if (pre5) {
accessListString = "\naccess list: ";
accessFormat = " %s";
- commentFormat = "\ncomment leader: \"";
- headFormat = "\nRCS file: %s; Working file: %s\nhead: %s%s\nbranch: %s%s\nlocks: ";
- insDelFormat = " lines added/del: %lu/%lu";
+ headFormat = "RCS file: %s; Working file: %s\nhead: %s%s\nbranch: %s%s\nlocks: ";
+ insDelFormat = " lines added/del: %ld/%ld";
symbolFormat = " %s: %s;";
} else {
accessListString = "\naccess list:";
accessFormat = "\n\t%s";
- commentFormat = "\ncomment leader: \"";
- headFormat = "\nRCS file: %s\nWorking file: %s\nhead:%s%s\nbranch:%s%s\nlocks:%s";
- insDelFormat = " lines: +%lu -%lu";
+ headFormat = "RCS file: %s\nWorking file: %s\nhead:%s%s\nbranch:%s%s\nlocks:%s";
+ insDelFormat = " lines: +%ld -%ld";
symbolFormat = "\n\t%s: %s";
}
- /* now handle all filenames */
- do {
+ /* Now handle all pathnames. */
+ if (nerror)
+ cleanup();
+ else if (argc < 1)
+ faterror("no input file%s", cmdusage);
+ else
+ for (; 0 < argc; cleanup(), ++argv, --argc) {
ffree();
- if (pairfilenames(argc, argv, rcsreadopen, true, false) <= 0)
+ if (pairnames(argc, argv, rcsreadopen, true, false) <= 0)
continue;
- /* now RCSfilename contains the name of the RCS file, and finptr
- * the file descriptor. Workfilename contains the name of the
- * working file.
+ /*
+ * RCSname contains the name of the RCS file,
+ * and finptr the file descriptor;
+ * workname contains the name of the working file.
*/
/* Keep only those locks given by -l. */
@@ -347,20 +371,26 @@ mainProg(rlogId, "rlog", "$Id: rlog.c,v 1.5 1994/05/12 00:42:59 phk Exp $")
if (onlylockflag && !Locks)
continue;
- if ( versionlist ) {
- gettree();
- aprintf(out, "%s%s %s\n", vstring, workfilename, tiprev());
+ if ( onlyRCSflag ) {
+ aprintf(out, "%s\n", RCSname);
continue;
}
- if ( onlyRCSflag ) {
- aprintf(out, "%s\n", RCSfilename);
+ gettree();
+
+ if (!getnumericrev())
continue;
- }
- /* print RCS filename , working filename and optional
+
+ /*
+ * Output the first character with putc, not printf.
+ * Otherwise, an SVR4 stdio bug buffers output inefficiently.
+ */
+ aputc_('\n', out)
+
+ /* print RCS pathname, working pathname and optional
administrative information */
/* could use getfullRCSname() here, but that is very slow */
- aprintf(out, headFormat, RCSfilename, workfilename,
+ aprintf(out, headFormat, RCSname, workname,
Head ? " " : "", Head ? Head->num : "",
Dbranch ? " " : "", Dbranch ? Dbranch : "",
StrictLocks ? " strict" : ""
@@ -371,8 +401,8 @@ mainProg(rlogId, "rlog", "$Id: rlog.c,v 1.5 1994/05/12 00:42:59 phk Exp $")
currlock->delta->num);
currlock = currlock->nextlock;
}
- if (StrictLocks && RCSversion<VERSION(5))
- aputs(" strict", out);
+ if (StrictLocks && pre5)
+ aputs(" ; strict" + (Locks?3:0), out);
aputs(accessListString, out); /* print access list */
curaccess = AccessList;
@@ -381,40 +411,40 @@ mainProg(rlogId, "rlog", "$Id: rlog.c,v 1.5 1994/05/12 00:42:59 phk Exp $")
curaccess = curaccess->nextaccess;
}
- aputs("\nsymbolic names:", out); /* print symbolic names */
- for (curassoc=Symbols; curassoc; curassoc=curassoc->nextassoc)
- aprintf(out, symbolFormat, curassoc->symbol, curassoc->num);
- aputs(commentFormat, out);
- awrite(Comment.string, Comment.size, out);
- aputs("\"\n", out);
- if (VERSION(5)<=RCSversion || Expand != KEYVAL_EXPAND)
- aprintf(out, "keyword substitution: %s\n",
+ if (shownames) {
+ aputs("\nsymbolic names:", out); /* print symbolic names */
+ for (curassoc=Symbols; curassoc; curassoc=curassoc->nextassoc)
+ aprintf(out, symbolFormat, curassoc->symbol, curassoc->num);
+ }
+ if (pre5) {
+ aputs("\ncomment leader: \"", out);
+ awrite(Comment.string, Comment.size, out);
+ afputc('\"', out);
+ }
+ if (!pre5 || Expand != KEYVAL_EXPAND)
+ aprintf(out, "\nkeyword substitution: %s",
expand_names[Expand]
);
- gettree();
-
- aprintf(out, "total revisions: %u", TotalDeltas);
+ aprintf(out, "\ntotal revisions: %d", TotalDeltas);
revno = 0;
if (Head && selectflag & descflag) {
- getnumericrev(); /* get numeric revision or branch names */
-
exttree(Head);
/* get most recently date of the dates pointed by duelst */
currdate = duelst;
while( currdate) {
- VOID sprintf(currdate->strtdate,DATEFORM,0,0,0,0,0,0);
+ VOID strcpy(currdate->strtdate, "0.0.0.0.0.0");
recentdate(Head, currdate);
currdate = currdate->dnext;
}
revno = extdate(Head);
- aprintf(out, ";\tselected revisions: %u", revno);
+ aprintf(out, ";\tselected revisions: %d", revno);
}
afputc('\n',out);
@@ -424,18 +454,16 @@ mainProg(rlogId, "rlog", "$Id: rlog.c,v 1.5 1994/05/12 00:42:59 phk Exp $")
}
if (revno) {
while (! (delta = readdeltalog())->selector || --revno)
- ;
+ continue;
if (delta->next && countnumflds(delta->num)==2)
/* Read through delta->next to get its insertlns. */
while (readdeltalog() != delta->next)
- ;
+ continue;
putrunk();
putree(Head);
}
- aputs("----------------------------\n", out);
aputs("=============================================================================\n",out);
- } while (cleanup(),
- ++argv, --argc >= 1);
+ }
Ofclose(out);
exitmain(exitstatus);
}
@@ -447,10 +475,10 @@ cleanup()
Izclose(&finptr);
}
-#if lint
+#if RCS_lint
# define exiterr rlogExit
#endif
- exiting void
+ void
exiterr()
{
_exit(EXIT_FAILURE);
@@ -478,7 +506,7 @@ putree(root)
order on each branch */
{
- if ( root == nil ) return;
+ if (!root) return;
putree(root->next);
@@ -493,8 +521,7 @@ putforest(branchroot)
struct branchhead const *branchroot;
/* function: print branches that has the same direct ancestor */
{
-
- if ( branchroot == nil ) return;
+ if (!branchroot) return;
putforest(branchroot->nextbranch);
@@ -511,8 +538,7 @@ putabranch(root)
/* function : print one branch */
{
-
- if ( root == nil) return;
+ if (!root) return;
putabranch(root->next);
@@ -538,17 +564,19 @@ putadelta(node,editscript,trunk)
size_t n;
struct branchhead const *newbranch;
struct buf branchnum;
- char datebuf[datesize];
+ char datebuf[datesize + zonelenmax];
+ int pre5 = RCSversion < VERSION(5);
if (!node->selector)
return;
out = stdout;
aprintf(out,
- "----------------------------\nrevision %s", node->num
+ "----------------------------\nrevision %s%s",
+ node->num, pre5 ? " " : ""
);
if ( node->lockedby )
- aprintf(out, "\tlocked by: %s;", node->lockedby);
+ aprintf(out, pre5+"\tlocked by: %s;", node->lockedby);
aprintf(out, "\ndate: %s; author: %s; state: %s;",
date2str(node->date, datebuf),
@@ -587,9 +615,6 @@ putadelta(node,editscript,trunk)
}
-
-
-
static struct hshentry const *
readdeltalog()
/* Function : get the log message and skip the text of a deltatext node.
@@ -614,9 +639,7 @@ readdeltalog()
cb = savestring(&logbuf);
Delta->log = bufremember(&logbuf, cb.size);
- nextlex();
- while (nexttok==ID && strcmp(NextString,Ktext)!=0)
- ignorephrase();
+ ignorephrases(Ktext);
getkeystring(Ktext);
Delta->insertlns = Delta->deletelns = 0;
if ( Delta != Head)
@@ -638,7 +661,7 @@ struct hshentry * Delta;
declarecache;
register RILE *fin;
register int c;
- register unsigned long i;
+ register long i;
struct diffcmd dc;
fin = finptr;
@@ -654,16 +677,16 @@ struct hshentry * Delta;
cache(fin);
do {
for (;;) {
- cacheget(c);
+ cacheget_(c)
switch (c) {
default:
continue;
case SDELIM:
- cacheget(c);
+ cacheget_(c)
if (c == SDELIM)
continue;
if (--i)
- fatserror("unexpected end to edit script");
+ unexpected_EOF();
nextc = c;
uncache(fin);
return;
@@ -692,10 +715,10 @@ struct hshentry *root;
{
struct branchhead const *newbranch;
- if (root == nil) return;
+ if (!root) return;
root->selector = extractdelta(root);
- root->log.string = nil;
+ root->log.string = 0;
exttree(root->next);
newbranch = root->branches;
@@ -716,26 +739,26 @@ char * argv;
{
register char c;
- struct lockers * newlocker;
+ struct rcslockers *newlocker;
argv--;
- while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
- c == '\n' || c == ';') ;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
if ( c == '\0') {
- lockerlist=nil;
+ lockerlist = 0;
return;
}
while( c != '\0' ) {
- newlocker = talloc(struct lockers);
+ newlocker = talloc(struct rcslockers);
newlocker->lockerlink = lockerlist;
newlocker->login = argv;
lockerlist = newlocker;
- while ( ( c = (*++argv)) != ',' && c != '\0' && c != ' '
- && c != '\t' && c != '\n' && c != ';') ;
+ while ((c = *++argv) && c!=',' && c!=' ' && c!='\t' && c!='\n' && c!=';')
+ continue;
*argv = '\0';
if ( c == '\0' ) return;
- while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
- c == '\n' || c == ';') ;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
}
}
@@ -752,12 +775,12 @@ char *argv;
struct authors * newauthor;
argv--;
- while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
- c == '\n' || c == ';') ;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
if ( c == '\0' ) {
authorlist = talloc(struct authors);
authorlist->login = getusername(false);
- authorlist->nextauthor = nil;
+ authorlist->nextauthor = 0;
return;
}
@@ -766,12 +789,12 @@ char *argv;
newauthor->nextauthor = authorlist;
newauthor->login = argv;
authorlist = newauthor;
- while( ( c = *++argv) != ',' && c != '\0' && c != ' '
- && c != '\t' && c != '\n' && c != ';') ;
+ while ((c = *++argv) && c!=',' && c!=' ' && c!='\t' && c!='\n' && c!=';')
+ continue;
* argv = '\0';
if ( c == '\0') return;
- while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
- c == '\n' || c == ';') ;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
}
}
@@ -789,10 +812,10 @@ char * argv;
struct stateattri *newstate;
argv--;
- while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
- c == '\n' || c == ';') ;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
if ( c == '\0'){
- warn("missing state attributes after -s options");
+ error("missing state attributes after -s options");
return;
}
@@ -801,12 +824,12 @@ char * argv;
newstate->nextstate = statelist;
newstate->status = argv;
statelist = newstate;
- while( (c = (*++argv)) != ',' && c != '\0' && c != ' '
- && c != '\t' && c != '\n' && c != ';') ;
+ while ((c = *++argv) && c!=',' && c!=' ' && c!='\t' && c!='\n' && c!=';')
+ continue;
*argv = '\0';
if ( c == '\0' ) return;
- while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
- c == '\n' || c == ';') ;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
}
}
@@ -818,25 +841,21 @@ trunclocks()
/* id's on lockerlist. Do not truncate if lockerlist empty. */
{
- struct lockers const *plocker;
- struct lock * plocked, * nextlocked;
+ struct rcslockers const *plocker;
+ struct rcslock *p, **pp;
- if ( (lockerlist == nil) || (Locks == nil)) return;
+ if (!lockerlist) return;
/* shorten Locks to those contained in lockerlist */
- plocked = Locks;
- Locks = nil;
- while( plocked != nil) {
- plocker = lockerlist;
- while((plocker != nil) && ( strcmp(plocker->login, plocked->login)!=0))
- plocker = plocker->lockerlink;
- nextlocked = plocked->nextlock;
- if ( plocker != nil) {
- plocked->nextlock = Locks;
- Locks = plocked;
- }
- plocked = nextlocked;
- }
+ for (pp = &Locks; (p = *pp); )
+ for (plocker = lockerlist; ; )
+ if (strcmp(plocker->login, p->login) == 0) {
+ pp = &p->nextlock;
+ break;
+ } else if (!(plocker = plocker->lockerlink)) {
+ *pp = p->nextlock;
+ break;
+ }
}
@@ -852,10 +871,10 @@ recentdate(root, pd)
{
struct branchhead const *newbranch;
- if ( root == nil) return;
+ if (!root) return;
if (root->selector) {
- if ( cmpnum(root->date, pd->strtdate) >= 0 &&
- cmpnum(root->date, pd->enddate) <= 0)
+ if ( cmpdate(root->date, pd->strtdate) >= 0 &&
+ cmpdate(root->date, pd->enddate) <= 0)
VOID strcpy(pd->strtdate, root->date);
}
@@ -872,7 +891,7 @@ recentdate(root, pd)
- static unsigned
+ static int
extdate(root)
struct hshentry * root;
/* function: select revisions which are in the date range specified */
@@ -881,7 +900,7 @@ struct hshentry * root;
{
struct branchhead const *newbranch;
struct Datepairs const *pdate;
- unsigned revno;
+ int revno, ne;
if (!root)
return 0;
@@ -889,20 +908,25 @@ struct hshentry * root;
if ( datelist || duelst) {
pdate = datelist;
while( pdate ) {
- if ( (pdate->strtdate)[0] == '\0' || cmpnum(root->date,pdate->strtdate) >= 0){
- if ((pdate->enddate)[0] == '\0' || cmpnum(pdate->enddate,root->date) >= 0)
+ ne = pdate->ne_date;
+ if (
+ (!pdate->strtdate[0]
+ || ne <= cmpdate(root->date, pdate->strtdate))
+ &&
+ (!pdate->enddate[0]
+ || ne <= cmpdate(pdate->enddate, root->date))
+ )
break;
- }
pdate = pdate->dnext;
}
- if ( pdate == nil) {
+ if (!pdate) {
pdate = duelst;
for (;;) {
if (!pdate) {
root->selector = false;
break;
}
- if ( cmpnum(root->date, pdate->strtdate) == 0)
+ if (cmpdate(root->date, pdate->strtdate) == 0)
break;
pdate = pdate->dnext;
}
@@ -927,11 +951,11 @@ extractdelta(pdelta)
/* statelist, revlist and yield true if pdelta is selected. */
{
- struct lock const *plock;
+ struct rcslock const *plock;
struct stateattri const *pstate;
struct authors const *pauthor;
struct Revpairs const *prevision;
- unsigned length;
+ int length;
if ((pauthor = authorlist)) /* only certain authors wanted */
while (strcmp(pauthor->login, pdelta->author) != 0)
@@ -977,10 +1001,10 @@ getdatepair(argv)
int switchflag;
argv--;
- while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
- c == '\n' || c == ';') ;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
if ( c == '\0' ) {
- warn("missing date/time after -d");
+ error("missing date/time after -d");
return;
}
@@ -989,9 +1013,13 @@ getdatepair(argv)
nextdate = talloc(struct Datepairs);
if ( c == '<' ) { /* case: -d <date */
c = *++argv;
+ if (!(nextdate->ne_date = c!='='))
+ c = *++argv;
(nextdate->strtdate)[0] = '\0';
} else if (c == '>') { /* case: -d'>date' */
c = *++argv;
+ if (!(nextdate->ne_date = c!='='))
+ c = *++argv;
(nextdate->enddate)[0] = '\0';
switchflag = true;
} else {
@@ -1009,7 +1037,11 @@ getdatepair(argv)
goto end;
} else {
/* case: -d date< or -d date>; see switchflag */
- while ( (c= *++argv) == ' ' || c=='\t' || c=='\n');
+ int eq = argv[1]=='=';
+ nextdate->ne_date = !eq;
+ argv += eq;
+ while ((c = *++argv) == ' ' || c=='\t' || c=='\n')
+ continue;
if ( c == ';' || c == '\0') {
/* second date missing */
if (switchflag)
@@ -1031,14 +1063,17 @@ getdatepair(argv)
nextdate->dnext = datelist;
datelist = nextdate;
end:
+ if (RCSversion < VERSION(5))
+ nextdate->ne_date = 0;
if ( c == '\0') return;
- while( (c = *++argv) == ';' || c == ' ' || c == '\t' || c =='\n');
+ while ((c = *++argv) == ';' || c == ' ' || c == '\t' || c =='\n')
+ continue;
}
}
- static void
+ static int
getnumericrev()
/* function: get the numeric name of revisions which stored in revlist */
/* and then stored the numeric names in Revlst */
@@ -1046,12 +1081,12 @@ getnumericrev()
{
struct Revpairs * ptr, *pt;
- unsigned n;
+ int n;
struct buf s, e;
char const *lrev;
struct buf const *rstart, *rend;
- Revlst = nil;
+ Revlst = 0;
ptr = revlist;
bufautobegin(&s);
bufautobegin(&e);
@@ -1062,48 +1097,48 @@ getnumericrev()
switch (ptr->numfld) {
- case 1: /* -r rev */
- if (expandsym(ptr->strtrev, &s)) {
- rend = &s;
- n = countnumflds(s.string);
- if (!n && (lrev = tiprev())) {
- bufscpy(&s, lrev);
- n = countnumflds(lrev);
- }
- }
+ case 1: /* -rREV */
+ if (!expandsym(ptr->strtrev, &s))
+ goto freebufs;
+ rend = &s;
+ n = countnumflds(s.string);
+ if (!n && (lrev = tiprev())) {
+ bufscpy(&s, lrev);
+ n = countnumflds(lrev);
+ }
break;
- case 2: /* -r rev- */
- if (expandsym(ptr->strtrev, &s)) {
- bufscpy(&e, s.string);
- n = countnumflds(s.string);
- (n<2 ? e.string : strrchr(e.string,'.'))[0] = 0;
- }
+ case 2: /* -rREV: */
+ if (!expandsym(ptr->strtrev, &s))
+ goto freebufs;
+ bufscpy(&e, s.string);
+ n = countnumflds(s.string);
+ (n<2 ? e.string : strrchr(e.string,'.'))[0] = 0;
break;
- case 3: /* -r -rev */
- if (expandsym(ptr->endrev, &e)) {
- if ((n = countnumflds(e.string)) < 2)
- bufscpy(&s, ".1");
- else {
- bufscpy(&s, e.string);
- VOID strcpy(strrchr(s.string,'.'), ".1");
- }
- }
+ case 3: /* -r:REV */
+ if (!expandsym(ptr->endrev, &e))
+ goto freebufs;
+ if ((n = countnumflds(e.string)) < 2)
+ bufscpy(&s, ".0");
+ else {
+ bufscpy(&s, e.string);
+ VOID strcpy(strrchr(s.string,'.'), ".0");
+ }
break;
- default: /* -r rev1-rev2 */
- if (
+ default: /* -rREV1:REV2 */
+ if (!(
expandsym(ptr->strtrev, &s)
&& expandsym(ptr->endrev, &e)
&& checkrevpair(s.string, e.string)
- ) {
- n = countnumflds(s.string);
- /* Swap if out of order. */
- if (compartial(s.string,e.string,n) > 0) {
- rstart = &e;
- rend = &s;
- }
+ ))
+ goto freebufs;
+ n = countnumflds(s.string);
+ /* Swap if out of order. */
+ if (compartial(s.string,e.string,n) > 0) {
+ rstart = &e;
+ rend = &s;
}
break;
}
@@ -1126,8 +1161,11 @@ getnumericrev()
pt->rnext=Revlst; Revlst=pt;
pt->numfld = countnumflds(pt->strtrev);
}
+
+ freebufs:
bufautoend(&s);
bufautoend(&e);
+ return !ptr;
}
@@ -1140,13 +1178,13 @@ checkrevpair(num1,num2)
fields( if length <= 2, may be different if first field) */
{
- unsigned length = countnumflds(num1);
+ int length = countnumflds(num1);
if (
countnumflds(num2) != length
- || 2 < length && compartial(num1, num2, length-1) != 0
+ || (2 < length && compartial(num1, num2, length-1) != 0)
) {
- error("invalid branch or revision pair %s : %s", num1, num2);
+ rcserror("invalid branch or revision pair %s : %s", num1, num2);
return false;
}
@@ -1203,7 +1241,8 @@ register char * argv;
while (c==' ' || c=='\t' || c=='\n')
c = *++argv;
if (c == separator) {
- while( (c =(*++argv)) == ' ' || c == '\t' || c =='\n') ;
+ while ((c = *++argv) == ' ' || c == '\t' || c =='\n')
+ continue;
nextrevpair->endrev = argv;
for (;; c = *++argv) {
switch (c) {
@@ -1214,8 +1253,8 @@ register char * argv;
break;
case ':': case '-':
if (c == separator)
- continue;
- break;
+ break;
+ continue;
}
break;
}
@@ -1223,13 +1262,15 @@ register char * argv;
while (c==' ' || c=='\t' || c =='\n')
c = *++argv;
nextrevpair->numfld =
- !nextrevpair->endrev[0] ? 2 /* -rrev- */ :
- !nextrevpair->strtrev[0] ? 3 /* -r-rev */ :
- 4 /* -rrev1-rev2 */;
+ !nextrevpair->endrev[0] ? 2 /* -rREV: */ :
+ !nextrevpair->strtrev[0] ? 3 /* -r:REV */ :
+ 4 /* -rREV1:REV2 */;
}
if (!c)
break;
- if (c!=',' && c!=';')
+ else if (c==',' || c==';')
+ c = *++argv;
+ else
error("missing `,' near `%c%s'", c, argv+1);
}
}
OpenPOWER on IntegriCloud