RCS: delete from tree.

Moved to a package. Not added to the image as we keep this only for
POSIX compatibility.

Fixes #11662.

Signed-off-by: Adrien Destugues <[email protected]>
This commit is contained in:
Augustin Cavalier
2015-01-05 17:40:07 +01:00
committed by Adrien Destugues
parent 71c761d99b
commit 45e1214ac1
35 changed files with 0 additions and 19568 deletions
-3
View File
@@ -293,9 +293,6 @@ SubInclude HAIKU_TOP src bin screenmode ;
SubInclude HAIKU_TOP src bin writembr ;
SubInclude HAIKU_TOP src bin zic ;
# RCS commands
SubInclude HAIKU_TOP src bin rcs ;
# debugging tools
SubInclude HAIKU_TOP src bin debug ;
-89
View File
@@ -1,89 +0,0 @@
SubDir HAIKU_TOP src bin rcs ;
SubDirCcFlags -w ;
local rcs_rsrc = [ FGristFiles rcs.rsrc ] ;
ResComp $(rcs_rsrc) : [ FGristFiles rcs.rdef ] ;
StaticLibrary librcs.a :
rcsutil.c
rcsfnms.c
rcsmap.c
rcsrev.c
rcssyn.c
rcslex.c
maketime.c
partime.c
rcstime.c
rcskeep.c
rcskeys.c
version.c
;
BinCommand ci :
ci.c
rcsgen.c
rcsedit.c
rcsfcmp.c
: librcs.a be
: $(rcs_rsrc)
;
BinCommand co :
co.c
rcsgen.c
rcsedit.c
: librcs.a be
: $(rcs_rsrc)
;
BinCommand ident :
ident.c
rcsmap.c
version.c
: be
: $(rcs_rsrc)
;
BinCommand merge :
merge.c
merger.c
: librcs.a be
: $(rcs_rsrc)
;
BinCommand rlog :
rlog.c
: librcs.a be
: $(rcs_rsrc)
;
BinCommand rcs :
rcs.c
rcsgen.c
rcsedit.c
: librcs.a be
: $(rcs_rsrc)
;
BinCommand rcsclean :
rcsclean.c
rcsedit.c
rcsfcmp.c
rcsgen.c
: librcs.a be
: $(rcs_rsrc)
;
BinCommand rcsdiff :
rcsdiff.c
: librcs.a be
: $(rcs_rsrc)
;
BinCommand rcsmerge :
rcsmerge.c
merger.c
: librcs.a be
: $(rcs_rsrc)
;
-1322
View File
File diff suppressed because it is too large Load Diff
-830
View File
@@ -1,830 +0,0 @@
/* 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.
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:
[email protected]
*/
/*
* $Log: co.c,v $
* Revision 1.1 2003/06/11 15:56:09 darkwyrm
* Added rcs, gzip, sed, and associated utilities.
*
* 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 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
* -k affects just working file, not RCS file.
*
* Revision 5.8 1991/08/19 03:13:55 eggert
* Warn before removing somebody else's file.
* Add -M. Fix co -j bugs. Tune.
*
* Revision 5.7 1991/04/21 11:58:15 eggert
* Ensure that working file is newer than RCS file after co -[lu].
* Add -x, RCSINIT, MS-DOS support.
*
* Revision 5.6 1990/12/04 05:18:38 eggert
* Don't checkaccesslist() unless necessary.
* Use -I for prompts and -q for diagnostics.
*
* Revision 5.5 1990/11/01 05:03:26 eggert
* Fix -j. Add -I.
*
* Revision 5.4 1990/10/04 06:30:11 eggert
* Accumulate exit status across files.
*
* Revision 5.3 1990/09/11 02:41:09 eggert
* co -kv yields a readonly working file.
*
* Revision 5.2 1990/09/04 08:02:13 eggert
* Standardize yes-or-no procedure.
*
* Revision 5.0 1990/08/22 08:10:02 eggert
* Permit multiple locks by same user. Add setuid support.
* Remove compile-time limits; use malloc instead.
* Permit dates past 1999/12/31. Switch to GMT.
* Make lock and temp files faster and safer.
* Ansify and Posixate. Add -k, -V. Remove snooping. Tune.
*
* Revision 4.7 89/05/01 15:11:41 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.6 88/08/09 19:12:15 eggert
* Fix "co -d" core dump; rawdate wasn't always initialized.
* Use execv(), not system(); fix putchar('\0') and diagnose() botches; remove lint
*
* Revision 4.5 87/12/18 11:35:40 narten
* lint cleanups (from Guy Harris)
*
* Revision 4.4 87/10/18 10:20:53 narten
* Updating version numbers changes relative to 1.1, are actually
* relative to 4.2
*
* Revision 1.3 87/09/24 13:58:30 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:21:38 jenkins
* Port to suns
*
* Revision 4.2 83/12/05 13:39:48 wft
* made rewriteflag external.
*
* Revision 4.1 83/05/10 16:52:55 wft
* Added option -u and -f.
* Added handling of default branch.
* Replaced getpwuid() with getcaller().
* Removed calls to stat(); now done by pairfilenames().
* Changed and renamed rmoldfile() to rmworkfile().
* Replaced catchints() calls with restoreints(), unlink()--link() with rename();
*
* Revision 3.7 83/02/15 15:27:07 wft
* Added call to fastcopy() to copy remainder of RCS file.
*
* Revision 3.6 83/01/15 14:37:50 wft
* Added ignoring of interrupts while RCS file is renamed; this avoids
* deletion of RCS files during the unlink/link window.
*
* Revision 3.5 82/12/08 21:40:11 wft
* changed processing of -d to use DATEFORM; removed actual from
* call to preparejoin; re-fixed printing of done at the end.
*
* Revision 3.4 82/12/04 18:40:00 wft
* Replaced getdelta() with gettree(), SNOOPDIR with SNOOPFILE.
* Fixed printing of "done".
*
* Revision 3.3 82/11/28 22:23:11 wft
* Replaced getlogin() with getpwuid(), flcose() with ffclose(),
* %02d with %.2d, mode generation for working file with WORKMODE.
* Fixed nil printing. Fixed -j combined with -l and -p, and exit
* for non-existing revisions in preparejoin().
*
* Revision 3.2 82/10/18 20:47:21 wft
* Mode of working file is now maintained even for co -l, but write permission
* is removed.
* The working file inherits its mode from the RCS file, plus write permission
* for the owner. The write permission is not given if locking is strict and
* co does not lock.
* An existing working file without write permission is deleted automatically.
* Otherwise, co asks (empty answer: abort co).
* Call to getfullRCSname() added, check for write error added, call
* for getlogin() fixed.
*
* Revision 3.1 82/10/13 16:01:30 wft
* fixed type of variables receiving from getc() (char -> int).
* removed unused variables.
*/
#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((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, *suffixarg, *versionarg, *zonearg;
static char const **joinlist; /* revisions to be joined */
static int joinlength;
static FILE *neworkptr;
static int exitstatus;
static int forceflag;
static int lastjoin; /* index of last element in joinlist */
static int lockflag; /* -1 -> unlock, 0 -> do nothing, 1 -> lock */
static int mtimeflag;
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 3476 2003-06-11 15:56:10Z darkwyrm $")
{
static char const cmdusage[] =
"\nco usage: co -{fIlMpqru}[rev] -ddate -jjoins -ksubst -sstate -T -w[who] -Vn -xsuff -zzone file ...";
char *a, *joinflag, **newargv;
char const *author, *date, *rev, *state;
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 = 0;
joinflag = 0;
bufautobegin(&numericrev);
expmode = -1;
suffixes = X_DEFAULT;
tostdout = false;
Ttimeflag = false;
argc = getRCSINIT(argc, argv, &newargv);
argv = newargv;
while (a = *++argv, 0<--argc && *a++=='-') {
switch (*a++) {
case 'r':
revno:
if (*a) {
if (rev) warn("redefinition of revision number");
rev = a;
}
break;
case 'f':
forceflag=true;
goto revno;
case 'l':
if (lockflag < 0) {
warn("-u overridden by -l.");
}
lockflag = 1;
goto revno;
case 'u':
if (0 < lockflag) {
warn("-l overridden by -u.");
}
lockflag = -1;
goto revno;
case 'p':
tostdout = true;
goto revno;
case 'I':
interactiveflag = true;
goto revno;
case 'q':
quietflag=true;
goto revno;
case 'd':
if (date)
redefined('d');
str2date(a, finaldate);
date=finaldate;
break;
case 'j':
if (*a) {
if (joinflag) redefined('j');
joinflag = a;
}
break;
case 'M':
mtimeflag = true;
goto revno;
case 's':
if (*a) {
if (state) redefined('s');
state = a;
}
break;
case 'T':
if (*a)
goto unknown;
Ttimeflag = true;
break;
case 'w':
if (author) redefined('w');
if (*a)
author = a;
else
author = getcaller();
break;
case 'x':
suffixarg = *argv;
suffixes = a;
break;
case 'V':
versionarg = *argv;
setRCSversion(versionarg);
break;
case 'z':
zonearg = *argv;
zone_set(a);
break;
case 'k': /* set keyword expand mode */
expandarg = *argv;
if (0 <= expmode) redefined('k');
if (0 <= (expmode = str2expmode(a)))
break;
/* fall into */
default:
unknown:
error("unknown option: %s%s", *argv, cmdusage);
};
} /* end of option processing */
/* 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 (pairnames(argc, argv, lockflag?rcswriteopen:rcsreadopen, true, false) <= 0)
continue;
/*
* 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", RCSname, tostdout?"standard output":workname);
workstatstat = -1;
if (tostdout) {
# 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(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)
workerror("permission denied on parent directory");
else
eerror(neworkname);
continue;
}
}
gettree(); /* reads in the delta tree */
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;
} else {
int locks = lockflag ? findlock(false, &targetdelta) : 0;
if (rev) {
/* expand symbolic revision number */
if (!expandsym(rev, &numericrev))
continue;
} else {
switch (locks) {
default:
continue;
case 0:
bufscpy(&numericrev, Dbranch?Dbranch:"");
break;
case 1:
bufscpy(&numericrev, targetdelta->num);
break;
}
}
/* get numbers of deltas to be generated */
if (!(targetdelta=genrevs(numericrev.string,date,author,state,&gendeltas)))
continue;
/* check reservations */
changelock =
lockflag < 0 ?
rmlock(targetdelta)
: lockflag == 0 ?
0
:
addlock(targetdelta, true);
if (
changelock < 0
|| (changelock && !checkaccesslist())
|| dorewrite(lockflag, changelock) != 0
)
continue;
if (0 <= expmode)
Expand = expmode;
if (0 < lockflag && Expand == VAL_EXPAND) {
rcserror("cannot combine -kv and -l");
continue;
}
if (joinflag && !preparejoin(joinflag))
continue;
diagnose("revision %s%s\n",targetdelta->num,
0<lockflag ? " (locked)" :
lockflag<0 ? " (unlocked)" : "");
/* Prepare to remove old working file if necessary. */
if (workstatstat == 0)
if (!rmworkfile()) continue;
/* skip description */
getdesc(false); /* don't echo*/
locker_expansion = 0 < lockflag;
targetdelta->name = namedrev(rev, targetdelta);
joinname = buildrevision(
gendeltas, targetdelta,
joinflag&&tostdout ? (FILE*)0 : neworkptr,
Expand < MIN_UNEXPAND
);
# if !large_memory
if (fcopy == neworkptr)
fcopy = 0; /* Don't close it twice. */
# endif
if_advise_access(changelock && gendeltas->first!=targetdelta,
finptr, MADV_SEQUENTIAL
);
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 (joinflag) {
newdate = 0;
if (!joinname) {
aflush(neworkptr);
joinname = neworkname;
}
if (Expand == BINARY_EXPAND)
workerror("merging binary files");
if (!buildjoin(joinname))
continue;
}
}
if (!tostdout) {
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(workname);
error("see %s", neworkname);
continue;
}
diagnose("done\n");
}
}
tempunlink();
Ofclose(workstdout);
exitmain(exitstatus);
} /* end of main (co) */
static void
cleanup()
{
if (nerror) exitstatus = EXIT_FAILURE;
Izclose(&finptr);
ORCSclose();
# if !large_memory
if (fcopy!=workstdout) Ozclose(&fcopy);
# endif
if (neworkptr!=workstdout) Ozclose(&neworkptr);
dirtempunlink();
}
#if RCS_lint
# define exiterr coExit
#endif
void
exiterr()
{
ORCSerror();
dirtempunlink();
tempunlink();
_exit(EXIT_FAILURE);
}
/*****************************************************************
* The following routines are auxiliary routines
*****************************************************************/
static int
rmworkfile()
/*
* 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);
* otherwise failure.
* Returns true if permission is gotten.
*/
{
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): ",
workname,
myself(workstat.st_uid) ? "" : ", and you do not own it"
)) {
error(!quietflag && ttystdin()
? "checkout aborted"
: "writable %s exists; checkout aborted", workname);
return false;
}
}
/* Actual unlink is done later by caller. */
return true;
}
static int
rmlock(delta)
struct hshentry const *delta;
/* Function: removes the lock held by caller on delta.
* Returns -1 if someone else holds the lock,
* 0 if there is no lock on delta,
* and 1 if a lock was found and removed.
*/
{ register struct rcslock * next, * trail;
char const *num;
struct rcslock dummy;
int whomatch, nummatch;
num=delta->num;
dummy.nextlock=next=Locks;
trail = &dummy;
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)) {
rcserror("revision %s locked by %s; use co -r or rcs -u",
num, next->login
);
return -1;
}
trail=next;
next=next->nextlock;
}
if (next) {
/*found one; delete it */
trail->nextlock=next->nextlock;
Locks=dummy.nextlock;
next->delta->lockedby = 0;
return 1; /*success*/
} else return 0; /*no lock on delta*/
}
/*****************************************************************
* The rest of the routines are for handling joins
*****************************************************************/
static char *
addjoin(joinrev)
char *joinrev;
/* Add joinrev's number to joinlist, yielding address of char past joinrev,
* or 0 if no such revision exists.
*/
{
register char *j;
register struct hshentry *d;
char terminator;
struct buf numrev;
struct hshentries *joindeltas;
j = joinrev;
for (;;) {
switch (*j++) {
default:
continue;
case 0:
case ' ': case '\t': case '\n':
case ':': case ',': case ';':
break;
}
break;
}
terminator = *--j;
*j = 0;
bufautobegin(&numrev);
d = 0;
if (expandsym(joinrev, &numrev))
d = genrevs(numrev.string,(char*)0,(char*)0,(char*)0,&joindeltas);
bufautoend(&numrev);
*j = terminator;
if (d) {
joinlist[++lastjoin] = d->num;
return j;
}
return 0;
}
static int
preparejoin(j)
register char *j;
/* Parse join list J and place pointers to the
* revision numbers into joinlist.
*/
{
lastjoin= -1;
for (;;) {
while ((*j==' ')||(*j=='\t')||(*j==',')) j++;
if (*j=='\0') break;
if (lastjoin>=joinlength-2) {
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++;
if (*j == ':') {
j++;
while((*j==' ') || (*j=='\t')) j++;
if (*j!='\0') {
if (!(j = addjoin(j))) return false;
} else {
rcsfaterror("join pair incomplete");
}
} else {
if (lastjoin==0) { /* first pair */
/* common ancestor missing */
joinlist[1]=joinlist[0];
lastjoin=1;
/*derive common ancestor*/
if (!(joinlist[0] = getancestor(targetdelta->num,joinlist[1])))
return false;
} else {
rcsfaterror("join pair incomplete");
}
}
}
if (lastjoin < 1)
rcsfaterror("empty join");
return true;
}
static char const *
getancestor(r1, r2)
char const *r1, *r2;
/* 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;
int l1, l2, l3;
char const *r;
l1 = countnumflds(r1);
l2 = countnumflds(r2);
if ((2<l1 || 2<l2) && cmpnum(r1,r2)!=0) {
/* not on main trunk or identical */
l3 = 0;
while (cmpnumfld(r1, r2, l3+1)==0 && cmpnumfld(r1, r2, l3+2)==0)
l3 += 2;
/* 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 ? 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);
}
rcserror("common ancestor of %s and %s undefined", r1, r2);
return 0;
}
static int
buildjoin(initialfile)
char const *initialfile;
/* Function: merge pairs of elements in joinlist into initialfile
* If workstdout is set, copy result to stdout.
* All unlinking of initialfile, rev2, and rev3 should be done by tempunlink().
*/
{
struct buf commarg;
struct buf subs;
char const *rev2, *rev3;
int i;
char const *cov[10], *mergev[11];
char const **p;
bufautobegin(&commarg);
bufautobegin(&subs);
rev2 = maketemp(0);
rev3 = maketemp(3); /* buildrevision() may use 1 and 2 */
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++ = RCSname;
*p = 0;
mergev[1] = MERGE;
mergev[2] = mergev[4] = "-L";
/* rest of mergev setup below */
i=0;
while (i<lastjoin) {
/*prepare marker for merge*/
if (i==0)
bufscpy(&subs, targetdelta->num);
else {
bufscat(&subs, ",");
bufscat(&subs, joinlist[i-2]);
bufscat(&subs, ":");
bufscat(&subs, joinlist[i-1]);
}
diagnose("revision %s\n",joinlist[i]);
bufscpy(&commarg, "-p");
bufscat(&commarg, joinlist[i]);
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[2] = commarg.string;
if (runv(-1, rev3, cov))
goto badmerge;
diagnose("merging...\n");
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 = 0;
switch (runv(-1, (char*)0, mergev)) {
case DIFF_FAILURE: case DIFF_SUCCESS:
break;
default:
goto badmerge;
}
i=i+2;
}
bufautoend(&commarg);
bufautoend(&subs);
return true;
badmerge:
nerror++;
bufautoend(&commarg);
bufautoend(&subs);
return false;
}
-399
View File
@@ -1,399 +0,0 @@
/* RCS compile-time configuration */
/* $Id: conf.h 28305 2008-10-23 21:46:26Z bonefish $ */
/*
* This file is generated automatically.
* If you edit it by hand your changes may be lost.
* Instead, please try to fix conf.sh,
* and send your fixes to [email protected].
*/
#define exitmain(n) return n /* how to exit from main() */
/* #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>
#include <time.h>
/* Comment out #include lines below that do not work. */
#include <sys/types.h>
#include <sys/stat.h>
#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 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 */
#if has_readlink && !defined(MAXSYMLINKS)
# if has_sys_param_h
# include <sys/param.h>
# endif
# ifndef MAXSYMLINKS
# define MAXSYMLINKS 20 /* BSD; not standard yet */
# endif
#endif
/* 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; */
/* typedef int ssize_t; */
/* typedef long time_t; */
/* typedef int uid_t; */
/* 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 ? */ /* Does <varargs.h> work? */
#define va_start_args 2 /* How many args does va_start() take? */
#if defined(O_BINARY) && !(defined(__BEOS__) || defined(__HAIKU__))
/* 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
# define P(params) ()
#endif
#if has_stdarg
# include <stdarg.h>
#else
# if has_varargs
# include <varargs.h>
# else
typedef char *va_list;
# define va_dcl int va_alist;
# define va_start(ap) ((ap) = (va_list)&va_alist)
# define va_arg(ap,t) (((t*) ((ap)+=sizeof(t))) [-1])
# define va_end(ap)
# endif
#endif
#if va_start_args == 2
# define vararg_start va_start
#else
# define vararg_start(ap,p) va_start(ap)
#endif
#define bad_chmod_close 0 /* Can chmod() close file descriptors? */
#define bad_creat0 1 /* 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 exiting
#endif
#define has_dirent 1 /* Do opendir(), readdir(), closedir() work? */
#define void_closedir 0 /* Does closedir() yield void? */
#define has_fchmod 0 /* Does fchmod() work? */
#define has_fflush_input 1 /* 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_memcmp 1 /* Does memcmp() work? */
#define has_memcpy 1 /* Does memcpy() work? */
#define has_memmove 1 /* Does memmove() work? */
#define has_map_fd 0 /* Does map_fd() work? */
#define has_mmap 0 /* Does mmap() work on regular files? */
#define has_madvise 0 /* Does madvise() work? */
/* #define mmap_signal ? */ /* 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 ../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_type void /* type returned by signal handlers */
#define sig_zaps_handler 0 /* Must a signal handler reinvoke signal()? */
/* #define has_sigblock ? */ /* Does sigblock() work? */
/* #define sigmask(s) (1 << ((s)-1)) */ /* Yield mask for signal number. */
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 0 /* Does psignal() work? */
/* #define has_si_errno ? */ /* Does siginfo_t have si_errno? */
#define has_sys_siglist 1 /* 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 0 /* Does vfork() work? */
#define has_fork 0 /* Does fork() work? */
#define has_spawn 0 /* Does spawn*() 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? */
#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 DIFF "/bin/diff" /* name of 'diff' program */
#define DIFF3 "/bin/diff3" /* name of 'diff3' program */
#define DIFF3_BIN 1 /* Is diff3 user-visible (not the /usr/lib auxiliary)? */
#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 "ed" /* name of 'ed' program (used only if !DIFF3_BIN) */
#define MERGE "/usr/local/bin/merge" /* name of 'merge' program */
#define TMPDIR "/tmp" /* default directory for temporary files */
#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 0 /* Do all subprograms satisfy ROOTPATH? */
#define DIFF_ABSOLUTE 1 /* Is ROOTPATH(DIFF) true? */
#define SENDMAIL "/bin/mail" /* how to send mail */
#define TZ_must_be_set 0 /* Must TZ be set for gmtime() to work? */
/* Adjust the following declarations as needed. */
/* 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. */
/* traditional BSD */
#if has_sys_siglist && !defined(sys_siglist) && !(defined(__BEOS__) || defined(__HAIKU__))
extern char const * const sys_siglist[];
#endif
/* Posix (ISO/IEC 9945-1: 1990 / IEEE Std 1003.1-1990) */
/* <fcntl.h> */
#ifdef O_CREAT
# define open_can_creat 1
#else
# define open_can_creat 0
# define O_RDONLY 0
# define O_WRONLY 1
# define O_RDWR 2
# define O_CREAT 01000
# define O_TRUNC 02000
#endif
#ifndef O_EXCL
#define O_EXCL 0
#endif
/* <sys/stat.h> */
#ifndef S_IRUSR
# ifdef S_IREAD
# define S_IRUSR S_IREAD
# else
# define S_IRUSR 0400
# endif
# ifdef S_IWRITE
# define S_IWUSR S_IWRITE
# else
# define S_IWUSR (S_IRUSR/2)
# endif
#endif
#ifndef S_IRGRP
# if has_getuid
# define S_IRGRP (S_IRUSR / 0010)
# define S_IWGRP (S_IWUSR / 0010)
# define S_IROTH (S_IRUSR / 0100)
# define S_IWOTH (S_IWUSR / 0100)
# else
/* single user OS -- not Posix or Unix */
# define S_IRGRP 0
# define S_IWGRP 0
# define S_IROTH 0
# define S_IWOTH 0
# endif
#endif
#ifndef S_ISREG
#define S_ISREG(n) (((n) & S_IFMT) == S_IFREG)
#endif
/* <sys/wait.h> */
#ifndef WEXITSTATUS
#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) & 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));
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
# define STDOUT_FILENO 1
# define STDERR_FILENO 2
#endif
#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_setuid && !has_seteuid
# undef seteuid
# define seteuid setuid
#endif
#if has_spawn
# if ALL_ABSOLUTE
# define spawn_RCS spawnv
# else
# define spawn_RCS spawnvp
# endif
#else
# if ALL_ABSOLUTE
# define exec_RCS execv
# else
# define exec_RCS execvp
# endif
#endif
/* utime.h */
#if !has_utimbuf
struct utimbuf { time_t actime, modtime; };
#endif
/* Standard C library */
/* <stdio.h> */
#ifndef L_tmpnam
#define L_tmpnam 32 /* power of 2 > sizeof("/usr/tmp/xxxxxxxxxxxxxxx") */
#endif
#ifndef SEEK_SET
#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
/* <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));
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#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));
void *memcpy P((void*,void const*,size_t));
#if has_memmove
void *memmove P((void*,void const*,size_t));
#endif
/* <time.h> */
time_t time P((time_t*));
-399
View File
@@ -1,399 +0,0 @@
/* example RCS compile-time configuration */
/* $Id: conf.heg 28305 2008-10-23 21:46:26Z bonefish $ */
/*
* This example RCS compile-time configuration describes a host that conforms
* to Standard C (1990) and to Posix 1003.1b-1993 with Memory Mapped Files,
* and has GNU diffutils 2.7 or later. If you can't get conf.sh to work,
* copy this file to conf.h and edit conf.h by hand; see ../INSTALL.RCS.
*/
#define exitmain(n) return n /* how to exit from main() */
/* #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>
#include <time.h>
/* Comment out #include lines below that do not work. */
#include <sys/types.h>
#include <sys/stat.h>
#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 boolean symbols to be 0 (false, the default), or 1 (true). */
#define has_sys_param_h 0 /* Does #include <sys/param.h> work? */
/* extern int errno; */ /* Uncomment if <errno.h> doesn't declare errno. */
#define has_readlink 0 /* Does readlink() work? */
#define readlink_isreg_errno EINVAL /* errno after readlink on regular file */
#if has_readlink && !defined(MAXSYMLINKS)
# if has_sys_param_h
# include <sys/param.h>
# endif
# ifndef MAXSYMLINKS
# define MAXSYMLINKS 20 /* BSD; not standard yet */
# endif
#endif
/* 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; */
/* typedef int ssize_t; */
/* typedef long time_t; */
/* typedef int uid_t; */
/* 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 ? */ /* Does <varargs.h> work? */
#define va_start_args 2 /* How many args does va_start() take? */
#if defined (O_BINARY) && !(defined(__BEOS__) || defined(__HAIKU__))
/* 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
# define P(params) ()
#endif
#if has_stdarg
# include <stdarg.h>
#else
# if has_varargs
# include <varargs.h>
# else
typedef char *va_list;
# define va_dcl int va_alist;
# define va_start(ap) ((ap) = (va_list)&va_alist)
# define va_arg(ap,t) (((t*) ((ap)+=sizeof(t))) [-1])
# define va_end(ap)
# endif
#endif
#if va_start_args == 2
# define vararg_start va_start
#else
# define vararg_start(ap,p) va_start(ap)
#endif
#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 0 /* Does __attribute__((noreturn)) work? */
#if has_attribute_noreturn
# define exiting __attribute__((noreturn))
#else
# define exiting
#endif
#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_fflush_input 1 /* 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_memcmp 1 /* Does memcmp() work? */
#define has_memcpy 1 /* Does memcpy() work? */
#define has_memmove 1 /* Does memmove() 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 ../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 1 /* Does struct sigaction have sa_sigaction? */
#define has_signal 1 /* Does signal() work? */
#define signal_type void /* type returned by signal handlers */
#define sig_zaps_handler 0 /* Must a signal handler reinvoke signal()? */
/* #define has_sigblock ? */ /* Does sigblock() work? */
/* #define sigmask(s) (1 << ((s)-1)) */ /* Yield mask for signal number. */
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 0 /* Does mktemp() work? */
#define has_NFS 0 /* Might NFS be used? */
#define has_psiginfo 0 /* Does psiginfo() work? */
#define has_psignal 0 /* Does psignal() work? */
#define has_si_errno 0 /* Does siginfo_t have si_errno? */
#define has_sys_siglist 0 /* 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 0 /* Does vfork() work? */
#define has_fork 1 /* Does fork() work? */
#define has_spawn 0 /* Does spawn*() work? */
#define has_waitpid 1 /* Does waitpid() work? */
#define bad_wait_if_SIGCHLD_ignored 1 /* 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 0 /* 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? */
#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 DIFF "/usr/local/bin/diff" /* name of 'diff' program */
#define DIFF3 "/usr/local/bin/diff3" /* name of 'diff3' program */
#define DIFF3_BIN 1 /* Is diff3 user-visible (not the /usr/lib auxiliary)? */
#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/local/bin/merge" /* name of 'merge' program */
#define TMPDIR "/tmp" /* default directory for temporary files */
#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 0 /* Are // and / the same directory? */
#define ALL_ABSOLUTE 1 /* Do all subprograms satisfy ROOTPATH? */
#define DIFF_ABSOLUTE 1 /* Is ROOTPATH(DIFF) true? */
#define SENDMAIL "/bin/mail" /* how to send mail */
#define TZ_must_be_set 0 /* Must TZ be set for gmtime() to work? */
/* Adjust the following declarations as needed. */
/* 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. */
/* 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) */
/* <fcntl.h> */
#ifdef O_CREAT
# define open_can_creat 1
#else
# define open_can_creat 0
# define O_RDONLY 0
# define O_WRONLY 1
# define O_RDWR 2
# define O_CREAT 01000
# define O_TRUNC 02000
#endif
#ifndef O_EXCL
#define O_EXCL 0
#endif
/* <sys/stat.h> */
#ifndef S_IRUSR
# ifdef S_IREAD
# define S_IRUSR S_IREAD
# else
# define S_IRUSR 0400
# endif
# ifdef S_IWRITE
# define S_IWUSR S_IWRITE
# else
# define S_IWUSR (S_IRUSR/2)
# endif
#endif
#ifndef S_IRGRP
# if has_getuid
# define S_IRGRP (S_IRUSR / 0010)
# define S_IWGRP (S_IWUSR / 0010)
# define S_IROTH (S_IRUSR / 0100)
# define S_IWOTH (S_IWUSR / 0100)
# else
/* single user OS -- not Posix or Unix */
# define S_IRGRP 0
# define S_IWGRP 0
# define S_IROTH 0
# define S_IWOTH 0
# endif
#endif
#ifndef S_ISREG
#define S_ISREG(n) (((n) & S_IFMT) == S_IFREG)
#endif
/* <sys/wait.h> */
#ifndef WEXITSTATUS
#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) & 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));
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
# define STDOUT_FILENO 1
# define STDERR_FILENO 2
#endif
#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_setuid && !has_seteuid
# undef seteuid
# define seteuid setuid
#endif
#if has_spawn
# if ALL_ABSOLUTE
# define spawn_RCS spawnv
# else
# define spawn_RCS spawnvp
# endif
#else
# if ALL_ABSOLUTE
# define exec_RCS execv
# else
# define exec_RCS execvp
# endif
#endif
/* utime.h */
#if !has_utimbuf
struct utimbuf { time_t actime, modtime; };
#endif
/* Standard C library */
/* <stdio.h> */
#ifndef L_tmpnam
#define L_tmpnam 32 /* power of 2 > sizeof("/usr/tmp/xxxxxxxxxxxxxxx") */
#endif
#ifndef SEEK_SET
#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
/* <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));
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#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));
void *memcpy P((void*,void const*,size_t));
#if has_memmove
void *memmove P((void*,void const*,size_t));
#endif
/* <time.h> */
time_t time P((time_t*));
-274
View File
@@ -1,274 +0,0 @@
/* 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.
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:
[email protected]
*/
/*
* $Log: ident.c,v $
* Revision 1.1 2003/06/11 15:56:09 darkwyrm
* Added rcs, gzip, sed, and associated utilities.
*
* 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,
* because they might be executables, not working files.
*
* Revision 5.2 1991/08/19 03:13:55 eggert
* Report read errors immediately.
*
* Revision 5.1 1991/02/25 07:12:37 eggert
* Don't report empty keywords. Check for I/O errors.
*
* Revision 5.0 1990/08/22 08:12:37 eggert
* Don't limit output to known keywords.
* Remove arbitrary limits and lint. Ansify and Posixate.
*
* Revision 4.5 89/05/01 15:11:54 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.4 87/10/23 17:09:57 narten
* added exit(0) so exit return code would be non random
*
* Revision 4.3 87/10/18 10:23:55 narten
* Updating version numbers. Changes relative to 1.1 are actually relative
* to 4.1
*
* Revision 1.3 87/07/09 09:20:52 trinkle
* Added check to make sure there is at least one arg before comparing argv[1]
* with "-q". This necessary on machines that don't allow dereferncing null
* pointers (i.e. Suns).
*
* Revision 1.2 87/03/27 14:21:47 jenkins
* Port to suns
*
* Revision 4.1 83/05/10 16:31:02 wft
* Added option -q and input from reading stdin.
* Marker matching is now done with trymatch() (independent of keywords).
*
* Revision 3.4 83/02/18 17:37:49 wft
* removed printing of new line after last file.
*
* Revision 3.3 82/12/04 12:48:55 wft
* Added LOCKER.
*
* Revision 3.2 82/11/28 18:24:17 wft
* removed Suffix; added ungetc to avoid skipping over trailing KDELIM.
*
* Revision 3.1 82/10/13 15:58:51 wft
* fixed type of variables receiving from getc() (char-->int).
*/
#include "rcsbase.h"
static int match P((FILE*));
static int scanfile P((FILE*,char const*,int));
static void reportError P((char const*));
mainProg(identId, "ident", "$Id: ident.c 3476 2003-06-11 15:56:10Z darkwyrm $")
/* Ident searches the named files for all occurrences
* of the pattern $@: text $ where @ is a keyword.
*/
{
FILE *fp;
int quiet = 0;
int status = EXIT_SUCCESS;
char const *a;
while ((a = *++argv) && *a=='-')
while (*++a)
switch (*a) {
case 'q':
quiet = 1;
break;
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));
if (ferror(stdout) || fclose(stdout)!=0) {
reportError("standard output");
status = EXIT_FAILURE;
}
exitmain(status);
}
#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 -1 if there's a write error; exit immediately on a read error.
*/
{
register int c;
if (name) {
VOID printf("%s:\n", name);
if (ferror(stdout))
return -1;
} else
name = "standard input";
c = 0;
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);
return 0;
}
static int
match(fp) /* group substring between two KDELIM's; then do pattern match */
register FILE *fp;
{
char line[BUFSIZ];
register int c;
register char * tp;
tp = line;
while ((c = getc(fp)) != VDELIM) {
if (c == EOF && feof(fp) | ferror(fp))
return c;
switch (ctab[c]) {
case LETTER: case Letter:
*tp++ = c;
if (tp < line+sizeof(line)-4)
break;
/* fall into */
default:
return c ? c : '\n'/* anything but 0 or KDELIM or EOF */;
}
}
if (tp == line)
return c;
*tp++ = c;
if ((c = getc(fp)) != ' ')
return c ? c : '\n';
*tp++ = c;
while( (c = getc(fp)) != KDELIM ) {
if (c == EOF && feof(fp) | ferror(fp))
return c;
switch (ctab[c]) {
default:
*tp++ = c;
if (tp < line+sizeof(line)-2)
break;
/* fall into */
case NEWLN: case UNKN:
return c ? c : '\n';
}
}
if (tp[-1] != ' ')
return c;
*tp++ = c; /*append trailing KDELIM*/
*tp = '\0';
VOID printf(" %c%s\n", KDELIM, line);
return 0;
}
-344
View File
@@ -1,344 +0,0 @@
/* Convert struct partime into time_t. */
/* Copyright 1992, 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:
[email protected]
*/
#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
#include "partime.h"
#include "maketime.h"
char const maketId[]
= "$Id: maketime.c 3476 2003-06-11 15:56:10Z darkwyrm $";
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 UNIXTIME to struct tm form.
* Use gmtime if available and if !LOCALZONE, localtime otherwise.
*/
struct tm *
time2tm(unixtime, localzone)
time_t unixtime;
int localzone;
{
struct tm *tm;
# if TZ_must_be_set
static char const *TZ;
if (!TZ && !(TZ = getenv("TZ")))
faterror("The TZ environment variable is not set; please set it to your timezone");
# endif
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);
}
/*
* 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
adjzone(t, seconds)
register struct tm *t;
long seconds;
{
/*
* 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
maketime(pt, default_time)
struct partime const *pt;
time_t default_time;
{
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 (!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;
}
/* Parse a free-format date in SOURCE, yielding a Unix format time. */
time_t
str2time(source, default_time, default_zone)
char const *source;
time_t default_time;
long default_zone;
{
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
main(argc, argv) int argc; char **argv;
{
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
-39
View File
@@ -1,39 +0,0 @@
/* Yield time_t from struct partime yielded by partime. */
/* 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:
[email protected]
*/
#if defined(__STDC__) || has_prototypes
# define __MAKETIME_P(x) x
#else
# define __MAKETIME_P(x) ()
#endif
struct tm *time2tm __MAKETIME_P((time_t,int));
time_t difftm __MAKETIME_P((struct tm const *, struct tm const *));
time_t str2time __MAKETIME_P((char const *, time_t, long));
time_t tm2time __MAKETIME_P((struct tm *, int));
void adjzone __MAKETIME_P((struct tm *, long));
-113
View File
@@ -1,113 +0,0 @@
/* merge - three-way file merge */
/* Copyright 1991, 1992, 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:
[email protected]
*/
#include "rcsbase.h"
static void badoption P((char const*));
static char const usage[] =
"\nmerge: usage: merge [-AeEpqxX3] [-L lab [-L lab [-L lab]]] file1 file2 file3";
static void
badoption(a)
char const *a;
{
error("unknown option: %s%s", a, usage);
}
mainProg(mergeId, "merge", "$Id: merge.c 3476 2003-06-11 15:56:10Z darkwyrm $")
{
register char const *a;
char const *arg[3], *label[3], *edarg = 0;
int labels, tostdout;
labels = 0;
tostdout = false;
for (; (a = *++argv) && *a++ == '-'; --argc) {
switch (*a++) {
case 'A': case 'E': case 'e':
if (edarg && edarg[1] != (*argv)[1])
error("%s and %s are incompatible",
edarg, *argv
);
edarg = *argv;
break;
case 'p': tostdout = true; break;
case 'q': quietflag = true; break;
case 'L':
if (3 <= labels)
faterror("too many -L options");
if (!(label[labels++] = *++argv))
faterror("-L needs following argument");
--argc;
break;
case 'V':
printf("RCS version %s\n", RCS_version_string);
exitmain(0);
default:
badoption(a - 2);
continue;
}
if (*a)
badoption(a - 2);
}
if (argc != 4)
faterror("%s arguments%s",
argc<4 ? "not enough" : "too many", usage
);
/* This copy keeps us `const'-clean. */
arg[0] = argv[0];
arg[1] = argv[1];
arg[2] = argv[2];
for (; labels < 3; labels++)
label[labels] = arg[labels];
if (nerror)
exiterr();
exitmain(merge(tostdout, edarg, label, arg));
}
#if RCS_lint
# define exiterr mergeExit
#endif
void
exiterr()
{
tempunlink();
_exit(DIFF_TROUBLE);
}
-148
View File
@@ -1,148 +0,0 @@
/* three-way file merge internals */
/* Copyright 1991, 1992, 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:
[email protected]
*/
#include "rcsbase.h"
libId(mergerId, "$Id: merger.c 3476 2003-06-11 15:56:10Z darkwyrm $")
static char const *normalize_arg P((char const*,char**));
static char const *
normalize_arg(s, b)
char const *s;
char **b;
/*
* If S looks like an option, prepend ./ to it. Yield the result.
* Set *B to the address of any storage that was allocated.
*/
{
char *t;
if (*s == '-') {
*b = t = testalloc(strlen(s) + 3);
VOID sprintf(t, ".%c%s", SLASH, s);
return t;
} else {
*b = 0;
return s;
}
}
int
merge(tostdout, edarg, label, argv)
int tostdout;
char const *edarg;
char const *const label[3];
char const *const argv[3];
/*
* Do `merge [-p] EDARG -L l0 -L l1 -L l2 a0 a1 a2',
* where TOSTDOUT specifies whether -p is present,
* EDARG gives the editing type (e.g. "-A", or null for the default),
* LABEL gives l0, l1 and l2, and ARGV gives a0, a1 and a2.
* Yield DIFF_SUCCESS or DIFF_FAILURE.
*/
{
register int i;
FILE *f;
RILE *rt;
char const *a[3], *t;
char *b[3];
int s;
#if !DIFF3_BIN
char const *d[2];
#endif
for (i=3; 0<=--i; )
a[i] = normalize_arg(argv[i], &b[i]);
if (!edarg)
edarg = "-E";
#if DIFF3_BIN
t = 0;
if (!tostdout)
t = maketemp(0);
s = run(
-1, t,
DIFF3, edarg, "-am",
"-L", label[0],
"-L", label[1],
"-L", label[2],
a[0], a[1], a[2], (char*)0
);
switch (s) {
case DIFF_SUCCESS:
break;
case DIFF_FAILURE:
warn("conflicts during merge");
break;
default:
exiterr();
}
if (t) {
if (!(f = fopenSafer(argv[0], "w")))
efaterror(argv[0]);
if (!(rt = Iopen(t, "r", (struct stat*)0)))
efaterror(t);
fastcopy(rt, f);
Ifclose(rt);
Ofclose(f);
}
#else
for (i=0; i<2; i++)
switch (run(
-1, d[i]=maketemp(i),
DIFF, a[i], a[2], (char*)0
)) {
case DIFF_FAILURE: case DIFF_SUCCESS: break;
default: faterror("diff failed");
}
t = maketemp(2);
s = run(
-1, t,
DIFF3, edarg, d[0], d[1], a[0], a[1], a[2],
label[0], label[2], (char*)0
);
if (s != DIFF_SUCCESS) {
s = DIFF_FAILURE;
warn("overlaps or other problems during merge");
}
if (!(f = fopenSafer(t, "a+")))
efaterror(t);
aputs(tostdout ? "1,$p\n" : "w\n", f);
Orewind(f);
aflush(f);
if (run(fileno(f), (char*)0, ED, "-", a[0], (char*)0))
exiterr();
Ofclose(f);
#endif
tempunlink();
for (i=3; 0<=--i; )
if (b[i])
tfree(b[i]);
return s;
}
-701
View File
@@ -1,701 +0,0 @@
/* Parse a string, yielding a struct partime that describes it. */
/* 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:
[email protected]
*/
#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
#include <ctype.h>
#undef isdigit
#define isdigit(c) (((unsigned)(c)-'0') <= 9) /* faster than stock */
#include "partime.h"
char const partimeId[]
= "$Id: partime.c 3476 2003-06-11 15:56:10Z darkwyrm $";
/* Lookup tables for names of months, weekdays, time zones. */
#define NAME_LENGTH_MAXIMUM 4
struct name_val {
char name[NAME_LENGTH_MAXIMUM];
int val;
};
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 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
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. */
{
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;
}
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.
*/
{
int n = 0;
char const *lim = s + digits;
while (s < lim) {
unsigned d = *s++ - '0';
if (9 < d)
return 0;
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;
default:
minutesEastOfUTC = lookup (s, zone_names);
if (minutesEastOfUTC == -1)
return 0;
/* 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 (
(s[0]=='D' || s[0]=='d') &&
(s[1]=='S' || s[1]=='s') &&
(s[2]=='T' || s[2]=='t')
) {
s += 3;
trailing_dst:
*zone = z + 60*60;
return (char *) s;
}
switch (*s) {
case '-': case '+': break;
default: return (char *) s;
}
}
sign = *s++;
if (!(s = parse_ranged (s, 2, 0, 23, &hh)))
return 0;
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;
}
}
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;
}
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.
*/
{
switch (c) {
case '$': /* The next character must be a non-digit. */
if (isdigit ((unsigned char) *s))
return 0;
break;
case '-': case '/': case ':':
/* These characters stand for themselves. */
if (*s++ != c)
return 0;
break;
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;
}
break;
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;
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;
}
static int
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.
*/
{
# 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;
}
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.
*/
{
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;
}
-71
View File
@@ -1,71 +0,0 @@
/* Parse a string, yielding a struct partime that describes it. */
/* 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:
[email protected]
*/
#define TM_UNDEFINED (-1)
#define TM_DEFINED(x) (0 <= (x))
#define TM_UNDEFINED_ZONE ((long) -24 * 60 * 60)
#define TM_LOCAL_ZONE (TM_UNDEFINED_ZONE - 1)
struct partime {
/*
* This structure describes the parsed time.
* Only the following tm_* values in it are used:
* sec, min, hour, mday, mon, year, wday, yday.
* If TM_UNDEFINED(value), the parser never found the value.
* The tm_year field is the actual year, not the year - 1900;
* but see ymodulus below.
*/
struct tm tm;
/*
* If !TM_UNDEFINED(ymodulus),
* then tm.tm_year is actually modulo ymodulus.
*/
int ymodulus;
/*
* Week of year, ISO 8601 style.
* If TM_UNDEFINED(yweek), the parser never found yweek.
* Weeks start on Mondays.
* Week 1 includes Jan 4.
*/
int yweek;
/* Seconds east of UTC; or TM_LOCAL_ZONE or TM_UNDEFINED_ZONE. */
long zone;
};
#if defined(__STDC__) || has_prototypes
# define __PARTIME_P(x) x
#else
# define __PARTIME_P(x) ()
#endif
char *partime __PARTIME_P((char const *, struct partime *));
char *parzone __PARTIME_P((char const *, long *));
-1633
View File
File diff suppressed because it is too large Load Diff
-11
View File
@@ -1,11 +0,0 @@
resource app_version
{
major = 5,
middle = 7,
minor = 0,
variety = 5,
internal = 0,
short_info = "5.7",
long_info = "5.7 ©1995 The Free Software Foundation"
};
-760
View File
@@ -1,760 +0,0 @@
/* RCS common definitions and data structures */
#define RCSBASE "$Id: rcsbase.h 3476 2003-06-11 15:56:10Z darkwyrm $"
/* 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.
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:
[email protected]
*/
/*
* $Log: rcsbase.h,v $
* Revision 1.1 2003/06/11 15:56:09 darkwyrm
* Added rcs, gzip, sed, and associated utilities.
*
* Revision 5.20 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* 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.
*
* Revision 5.10 1991/09/24 00:28:39 eggert
* Remove unexported functions.
*
* Revision 5.9 1991/08/19 03:13:55 eggert
* Add piece tables and other tuneups, and NFS workarounds.
*
* Revision 5.8 1991/04/21 11:58:20 eggert
* Add -x, RCSINIT, MS-DOS support.
*
* Revision 5.7 1991/02/28 19:18:50 eggert
* Try setuid() if seteuid() doesn't work.
*
* Revision 5.6 1991/02/26 17:48:37 eggert
* Support new link behavior. Move ANSI C / Posix declarations into conf.sh.
*
* Revision 5.5 1990/12/04 05:18:43 eggert
* Use -I for prompts and -q for diagnostics.
*
* Revision 5.4 1990/11/01 05:03:35 eggert
* Don't assume that builtins are functions; they may be macros.
* Permit arbitrary data in logs.
*
* Revision 5.3 1990/09/26 23:36:58 eggert
* Port wait() to non-Posix ANSI C hosts.
*
* Revision 5.2 1990/09/04 08:02:20 eggert
* Don't redefine NAME_MAX, PATH_MAX.
* Improve incomplete line handling. Standardize yes-or-no procedure.
*
* Revision 5.1 1990/08/29 07:13:53 eggert
* Add -kkvl. Fix type typos exposed by porting. Clean old log messages too.
*
* Revision 5.0 1990/08/22 08:12:44 eggert
* Adjust ANSI C / Posix support. Add -k, -V, setuid. Don't call access().
* Remove compile-time limits; use malloc instead.
* Ansify and Posixate. Add support for ISO 8859.
* Remove snoop and v2 support.
*
* Revision 4.9 89/05/01 15:17:14 narten
* botched previous USG fix
*
* Revision 4.8 89/05/01 14:53:05 narten
* changed #include <strings.h> -> string.h for USG systems.
*
* Revision 4.7 88/11/08 15:58:45 narten
* removed defs for functions loaded from libraries
*
* Revision 4.6 88/08/09 19:12:36 eggert
* Shrink stdio code size; remove lint; permit -Dhshsize=nn.
*
* Revision 4.5 87/12/18 17:06:41 narten
* made removed BSD ifdef, now uses V4_2BSD
*
* Revision 4.4 87/10/18 10:29:49 narten
* Updating version numbers
* Changes relative to 1.1 are actually relative to 4.2
*
* Revision 1.3 87/09/24 14:02:25 narten
* changes for lint
*
* Revision 1.2 87/03/27 14:22:02 jenkins
* Port to suns
*
* Revision 4.2 83/12/20 16:04:20 wft
* merged 3.6.1.1 and 4.1 (SMALLOG, logsize).
* moved setting of STRICT_LOCKING to Makefile.
* changed DOLLAR to UNKN (conflict with KDELIM).
*
* Revision 4.1 83/05/04 09:12:41 wft
* Added markers Id and RCSfile.
* Added Dbranch for default branches.
*
* Revision 3.6.1.1 83/12/02 21:56:22 wft
* Increased logsize, added macro SMALLOG.
*
* Revision 3.6 83/01/15 16:43:28 wft
* 4.2 prerelease
*
* Revision 3.6 83/01/15 16:43:28 wft
* Replaced dbm.h with BYTESIZ, fixed definition of rindex().
* Added variants of NCPFN and NCPPN for bsd 4.2, selected by defining V4_2BSD.
* Added macro DELNUMFORM to have uniform format for printing delta text nodes.
* Added macro DELETE to mark deleted deltas.
*
* Revision 3.5 82/12/10 12:16:56 wft
* Added two forms of DATEFORM, one using %02d, the other %.2d.
*
* Revision 3.4 82/12/04 20:01:25 wft
* added LOCKER, Locker, and USG (redefinition of rindex).
*
* Revision 3.3 82/12/03 12:22:04 wft
* Added dbm.h, stdio.h, RCSBASE, RCSSEP, RCSSUF, WORKMODE, TMPFILE3,
* PRINTDATE, PRINTTIME, map, and ctab; removed Suffix. Redefined keyvallength
* using NCPPN. Changed putc() to abort on write error.
*
* Revision 3.2 82/10/18 15:03:52 wft
* added macro STRICT_LOCKING, removed RCSUMASK.
* renamed JOINFILE[1,2] to JOINFIL[1,2].
*
* Revision 3.1 82/10/11 19:41:17 wft
* removed NBPW, NBPC, NCPW.
* added typdef int void to aid compiling
*/
#include "conf.h"
#define EXIT_TROUBLE DIFF_TROUBLE
#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 */
#define Fread(p,s,n,f) fread(p, (freadarg_type)(s), (freadarg_type)(n), f)
#define Fwrite(p,s,n,f) fwrite(p, (freadarg_type)(s), (freadarg_type)(n), f)
/*
* Parameters
*/
/* backwards compatibility with old versions of RCS */
#define VERSION_min 3 /* old output RCS format supported */
#define VERSION_max 5 /* newest output RCS format supported */
#ifndef VERSION_DEFAULT /* default RCS output format */
# define VERSION_DEFAULT VERSION_max
#endif
#define VERSION(n) ((n) - VERSION_DEFAULT) /* internally, 0 is the default */
#ifndef STRICT_LOCKING
#define STRICT_LOCKING 1
#endif
/* 0 sets the default locking to non-strict; */
/* used in experimental environments. */
/* 1 sets the default locking to strict; */
/* used in production environments. */
#define yearlength 16 /* (good through AD 9,999,999,999,999,999) */
#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 */
#define DEFAULTSTATE "Exp" /* default state of revisions */
#define true 1
#define false 0
/*
* RILE - readonly file
* declarecache; - declares local cache for RILE variable(s)
* 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
* 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 RILE {
Iptr_type ptr, lim;
unsigned char *base; /* not Iptr_type for lint's sake */
unsigned char *readlim;
int fd;
# if maps_memory
void (*deallocate) P((struct RILE *));
# else
FILE *stream;
# endif
} RILE;
# 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++;
# 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++;
# 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 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))==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)==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 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 */
/* character classes and token codes */
enum tokens {
/* classes */ DELIM, DIGIT, IDCHAR, NEWLN, LETTER, Letter,
PERIOD, SBEGIN, SPACE, UNKN,
/* tokens */ COLON, ID, NUM, SEMI, STRING
};
#define SDELIM '@' /* the actual character is needed for string handling*/
/* SDELIM must be consistent with ctab[], so that ctab[SDELIM]==SBEGIN.
* there should be no overlap among SDELIM, KDELIM, and VDELIM
*/
#define isdigit(c) (((unsigned)(c)-'0') <= 9) /* faster than ctab[c]==DIGIT */
/***************************************
* Data structures for the symbol table
***************************************/
/* Buffer of arbitrary data */
struct buf {
char *string;
size_t size;
};
struct cbuf {
char const *string;
size_t size;
};
/* Hash table entry */
struct hshentry {
char const * num; /* pointer to revision number (ASCIZ) */
char const * date; /* pointer to date of checkin */
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 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 */
long insertlns;/* lines inserted (computed by rlog) */
long deletelns;/* lines deleted (computed by rlog) */
char selector; /* true if selected, false if deleted */
};
/* list of hash entries */
struct hshentries {
struct hshentries *rest;
struct hshentry *first;
};
/* list element for branch lists */
struct branchhead {
struct hshentry * hsh;
struct branchhead * nextbranch;
};
/* accesslist element */
struct access {
char const * login;
struct access * nextaccess;
};
/* list element for locks */
struct rcslock {
char const * login;
struct hshentry * delta;
struct rcslock * nextlock;
};
/* list element for symbolic names */
struct assoc {
char const * symbol;
char const * num;
struct assoc * nextassoc;
};
#define mainArgs (argc,argv) int argc; char **argv;
#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(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
/*
* Markers for keyword expansion (used in co and ident)
* Every byte must have class LETTER or Letter.
*/
#define AUTHOR "Author"
#define DATE "Date"
#define HEADER "Header"
#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 keylength 8 /* max length of any of the above keywords */
enum markers { Nomatch, Author, Date, Header, Id,
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"
/* used by putdtext and scanlogtext */
#define EMPTYLOG "*** empty log message ***" /* used by ci and rlog */
/* main program */
extern char const cmdid[];
void exiterr P((void)) exiting;
/* merge */
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 *resultname;
extern char const ciklog[ciklogsize];
extern int locker_expansion;
RILE *rcswriteopen P((struct buf*,struct stat*,int));
char const *makedirtemp P((int));
char const *getcaller P((void));
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*,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));
int findlock P((int,struct hshentry**));
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));
void finishedit P((struct hshentry const*,FILE*,int));
void keepdirtemp P((char const*));
void openfcopy P((FILE*));
void snapshotedit P((FILE*));
void xpandstring P((struct hshentry const*));
#if has_NFS || bad_unlink
int un_link P((char const*));
#else
# define un_link(s) unlink(s)
#endif
#if large_memory
void edit_string P((void));
# define editstring(delta) edit_string()
#else
void editstring P((struct hshentry const*));
#endif
/* rcsfcmp */
int rcsfcmp P((RILE*,struct stat const*,char const*,struct hshentry const*));
/* rcsfnms */
#define bufautobegin(b) clear_buf(b)
#define clear_buf(b) (VOID ((b)->string = 0, (b)->size = 0))
extern FILE *workstdout;
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 *basefilename P((char const*));
char const *getfullRCSname P((void));
char const *maketemp P((int));
char const *rcssuffix 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*));
void bufrealloc P((struct buf*,size_t));
void bufscat P((struct buf*,char const*));
void bufscpy P((struct buf*,char const*));
void tempunlink P((void));
/* rcsgen */
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*,...)) 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, prevname, prevrev, prevstate;
int getoldkeys P((RILE*));
/* rcskeys */
extern char const *const Keyword[];
enum markers trymatch P((char const*));
/* rcslex */
extern FILE *foutptr;
extern FILE *frewrite;
extern RILE *finptr;
extern char const *NextString;
extern enum tokens nexttok;
extern int hshenter;
extern int nerror;
extern int nextc;
extern int quietflag;
extern long rcsline;
char const *getid 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));
struct cbuf getphrases P((char const*));
struct cbuf savestring P((struct buf*));
struct hshentry *getnum P((void));
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*,...)) printf_string(2,3);
void aputs P((char const*,FILE*));
void checksid P((char*));
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*,...)) printf_string(1,2);
void fvfprintf P((FILE*,char const*,va_list));
void getkey P((char const*));
void getkeystring P((char const*));
void nextlex P((void));
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*,...)) 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)
#else
# define advise_access(f,advice)
# define if_advise_access(p,f,advice)
#endif
#if large_memory && maps_memory
RILE *I_open P((char const*,struct stat*));
# define Iopen(f,m,s) I_open(f,s)
#else
RILE *Iopen P((char const*,char const*,struct stat*));
#endif
#if !large_memory
void testIeof P((FILE*));
void Irewind P((RILE*));
#endif
/* rcsmap */
extern enum tokens const ctab[];
/* rcsrev */
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*,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**));
int countnumflds P((char const*));
void getbranchno P((char const*,struct buf*));
/* rcssyn */
/* These expand modes must agree with Expand_names[] in rcssyn.c. */
#define KEYVAL_EXPAND 0 /* -kkv `$Keyword: value $' */
#define KEYVALLOCK_EXPAND 1 /* -kkvl `$Keyword: value locker $' */
#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 {
long
line1, /* number of first line */
nlines, /* number of lines affected */
adprev, /* previous 'a' line1+1 or 'd' line1 */
dafter; /* sum of previous 'd' line1 and previous 'd' nlines */
};
extern char const * Dbranch;
extern struct access * AccessList;
extern struct assoc * Symbols;
extern struct cbuf Comment;
extern struct cbuf Ignored;
extern struct rcslock *Locks;
extern struct hshentry * Head;
extern int Expand;
extern int StrictLocks;
extern int TotalDeltas;
extern char const *const expand_names[];
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 str2expmode P((char const*));
void getadmin P((void));
void getdesc P((int));
void gettree P((void));
void ignorephrases P((char const*));
void initdiffcmd P((struct diffcmd*));
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 *getusername P((int));
int fdSafer P((int));
int getRCSINIT P((int,char**,char***));
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 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)
# define trealloc(T,p,n) (lintalloc = testrealloc((malloc_type)0, sizeof(T)*(n)), p)
# define tfree(p)
#else
# define ftnalloc(T,n) ((T*) ftestalloc(sizeof(T)*(n)))
# define tnalloc(T,n) ((T*) testalloc(sizeof(T)*(n)))
# 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));
void ffree1 P((char const*));
void setRCSversion P((char const*));
#if has_signal
void catchints P((void));
void ignoreints P((void));
void restoreints P((void));
#else
# define catchints()
# 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())
#else
# define myself(u) true
#endif
#if has_setuid
uid_t euid P((void));
void nosetid P((void));
void seteid P((void));
void setrid P((void));
#else
# define nosetid()
# define seteid()
# define setrid()
#endif
/* version */
extern char const RCS_version_string[];
-333
View File
@@ -1,333 +0,0 @@
/* Clean up working files. */
/* Copyright 1991, 1992, 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:
[email protected]
*/
#include "rcsbase.h"
#if has_dirent
static int get_directory P((char const*,char***));
#endif
static int unlock P((struct hshentry *));
static void cleanup P((void));
static RILE *workptr;
static int exitstatus;
mainProg(rcscleanId, "rcsclean", "$Id: rcsclean.c 3476 2003-06-11 15:56:10Z darkwyrm $")
{
static char const usage[] =
"\nrcsclean: usage: rcsclean -ksubst -{nqru}[rev] -T -Vn -xsuff -zzone file ...";
static struct buf revision;
char *a, **newargv;
char const *rev, *p;
int dounlock, expmode, perform, unlocked, unlockflag, waslocked;
int Ttimeflag;
struct hshentries *deltas;
struct hshentry *delta;
struct stat workstat;
setrid();
expmode = -1;
rev = 0;
suffixes = X_DEFAULT;
perform = true;
unlockflag = false;
Ttimeflag = false;
argc = getRCSINIT(argc, argv, &newargv);
argv = newargv;
for (;;) {
if (--argc < 1) {
# if has_dirent
argc = get_directory(".", &newargv);
argv = newargv;
break;
# else
faterror("no pathnames specified");
# endif
}
a = *++argv;
if (!*a || *a++ != '-')
break;
switch (*a++) {
case 'k':
if (0 <= expmode)
redefined('k');
if ((expmode = str2expmode(a)) < 0)
goto unknown;
break;
case 'n':
perform = false;
goto handle_revision;
case 'q':
quietflag = true;
/* fall into */
case 'r':
handle_revision:
if (*a) {
if (rev)
warn("redefinition of revision number");
rev = a;
}
break;
case 'T':
if (*a)
goto unknown;
Ttimeflag = true;
break;
case 'u':
unlockflag = true;
goto handle_revision;
case 'V':
setRCSversion(*argv);
break;
case 'x':
suffixes = a;
break;
case 'z':
zone_set(a);
break;
default:
unknown:
error("unknown option: %s%s", *argv, usage);
}
}
dounlock = perform & unlockflag;
if (nerror)
cleanup();
else
for (; 0 < argc; cleanup(), ++argv, --argc) {
ffree();
if (!(
0 < pairnames(
argc, argv,
dounlock ? rcswriteopen : rcsreadopen,
true, true
) &&
(workptr = Iopen(workname, FOPEN_R_WORK, &workstat))
))
continue;
if (same_file(RCSstat, workstat, 0)) {
rcserror("RCS file is the same as working file %s.",
workname
);
continue;
}
gettree();
p = 0;
if (rev) {
if (!fexpandsym(rev, &revision, workptr))
continue;
p = revision.string;
} else if (Head)
switch (unlockflag ? findlock(false,&delta) : 0) {
default:
continue;
case 0:
p = Dbranch ? Dbranch : "";
break;
case 1:
p = delta->num;
break;
}
delta = 0;
deltas = 0; /* Keep lint happy. */
if (p && !(delta = genrevs(p,(char*)0,(char*)0,(char*)0,&deltas)))
continue;
waslocked = delta && delta->lockedby;
locker_expansion = unlock(delta);
unlocked = locker_expansion & unlockflag;
if (unlocked<waslocked && workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH))
continue;
if (unlocked && !checkaccesslist())
continue;
if (dorewrite(dounlock, unlocked) != 0)
continue;
if (0 <= expmode)
Expand = expmode;
else if (
waslocked &&
Expand == KEYVAL_EXPAND &&
WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
)
Expand = KEYVALLOCK_EXPAND;
getdesc(false);
if (
!delta ? workstat.st_size!=0 :
0 < rcsfcmp(
workptr, &workstat,
buildrevision(deltas, delta, (FILE*)0, false),
delta
)
)
continue;
if (quietflag < unlocked)
aprintf(stdout, "rcs -u%s %s\n", delta->num, RCSname);
if (perform & unlocked) {
if_advise_access(deltas->first != delta, finptr, MADV_SEQUENTIAL);
if (donerewrite(true,
Ttimeflag ? RCSstat.st_mtime : (time_t)-1
) != 0)
continue;
}
if (!quietflag)
aprintf(stdout, "rm -f %s\n", workname);
Izclose(&workptr);
if (perform && un_link(workname) != 0)
eerror(workname);
}
tempunlink();
if (!quietflag)
Ofclose(stdout);
exitmain(exitstatus);
}
static void
cleanup()
{
if (nerror) exitstatus = EXIT_FAILURE;
Izclose(&finptr);
Izclose(&workptr);
Ozclose(&fcopy);
ORCSclose();
dirtempunlink();
}
#if RCS_lint
# define exiterr rcscleanExit
#endif
void
exiterr()
{
ORCSerror();
dirtempunlink();
tempunlink();
_exit(EXIT_FAILURE);
}
static int
unlock(delta)
struct hshentry *delta;
{
register struct rcslock **al, *l;
if (delta && delta->lockedby && strcmp(getcaller(),delta->lockedby)==0)
for (al = &Locks; (l = *al); al = &l->nextlock)
if (l->delta == delta) {
*al = l->nextlock;
delta->lockedby = 0;
return true;
}
return false;
}
#if has_dirent
static int
get_directory(dirname, aargv)
char const *dirname;
char ***aargv;
/*
* Put a vector of all DIRNAME's directory entries names into *AARGV.
* Ignore names of RCS files.
* Yield the number of entries found. Terminate the vector with 0.
* Allocate the storage for the vector and entry names.
* Do not sort the names. Do not include '.' and '..'.
*/
{
int i, entries = 0, entries_max = 64;
size_t chars = 0, chars_max = 1024;
size_t *offset = tnalloc(size_t, entries_max);
char *a = tnalloc(char, chars_max), **p;
DIR *d;
struct dirent *e;
if (!(d = opendir(dirname)))
efaterror(dirname);
while ((errno = 0, e = readdir(d))) {
char const *en = e->d_name;
size_t s = strlen(en) + 1;
if (en[0]=='.' && (!en[1] || (en[1]=='.' && !en[2])))
continue;
if (rcssuffix(en))
continue;
while (chars_max < s + chars)
a = trealloc(char, a, chars_max<<=1);
if (entries == entries_max)
offset = trealloc(size_t, offset, entries_max<<=1);
offset[entries++] = chars;
VOID strcpy(a+chars, en);
chars += s;
}
# if void_closedir
# define close_directory(d) (closedir(d), 0)
# else
# define close_directory(d) closedir(d)
# endif
if (errno || close_directory(d) != 0)
efaterror(dirname);
if (chars)
a = trealloc(char, a, chars);
else
tfree(a);
*aargv = p = tnalloc(char*, entries+1);
for (i=0; i<entries; i++)
*p++ = a + offset[i];
*p = 0;
tfree(offset);
return entries;
}
#endif
-484
View File
@@ -1,484 +0,0 @@
/* Compare RCS revisions. */
/* 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.
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:
[email protected]
*/
/*
* $Log: rcsdiff.c,v $
* Revision 1.1 2003/06/11 15:56:09 darkwyrm
* Added rcs, gzip, sed, and associated utilities.
*
* 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.
*
* Revision 5.9 1991/08/19 03:13:55 eggert
* Add RCSINIT, -r$. Tune.
*
* Revision 5.8 1991/04/21 11:58:21 eggert
* Add -x, RCSINIT, MS-DOS support.
*
* Revision 5.7 1990/12/13 06:54:07 eggert
* GNU diff 1.15 has -u.
*
* Revision 5.6 1990/11/01 05:03:39 eggert
* Remove unneeded setid check.
*
* Revision 5.5 1990/10/04 06:30:19 eggert
* Accumulate exit status across files.
*
* Revision 5.4 1990/09/27 01:31:43 eggert
* Yield 1, not EXIT_FAILURE, when diffs are found.
*
* Revision 5.3 1990/09/11 02:41:11 eggert
* Simplify -kkvl test.
*
* Revision 5.2 1990/09/04 17:07:19 eggert
* Diff's argv was too small by 1.
*
* Revision 5.1 1990/08/29 07:13:55 eggert
* Add -kkvl.
*
* Revision 5.0 1990/08/22 08:12:46 eggert
* Add -k, -V. Don't use access(). Add setuid support.
* Remove compile-time limits; use malloc instead.
* Don't pass arguments with leading '+' to diff; GNU DIFF treats them as options.
* Add GNU diff's flags. Make lock and temp files faster and safer.
* Ansify and Posixate.
*
* Revision 4.6 89/05/01 15:12:27 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.5 88/08/09 19:12:41 eggert
* Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
*
* Revision 4.4 87/12/18 11:37:46 narten
* changes Jay Lepreau made in the 4.3 BSD version, to add support for
* "-i", "-w", and "-t" flags and to permit flags to be bundled together,
* merged in.
*
* Revision 4.3 87/10/18 10:31:42 narten
* Updating version numbers. Changes relative to 1.1 actually
* relative to 4.1
*
* Revision 1.3 87/09/24 13:59:21 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:22:15 jenkins
* Port to suns
*
* Revision 4.1 83/05/03 22:13:19 wft
* Added default branch, option -q, exit status like diff.
* Added fterror() to replace faterror().
*
* Revision 3.6 83/01/15 17:52:40 wft
* Expanded mainprogram to handle multiple RCS files.
*
* Revision 3.5 83/01/06 09:33:45 wft
* Fixed passing of -c (context) option to diff.
*
* Revision 3.4 82/12/24 15:28:38 wft
* Added call to catchsig().
*
* Revision 3.3 82/12/10 16:08:17 wft
* Corrected checking of return code from diff; improved error msgs.
*
* Revision 3.2 82/12/04 13:20:09 wft
* replaced getdelta() with gettree(). Changed diagnostics.
*
* Revision 3.1 82/11/28 19:25:04 wft
* Initial revision.
*
*/
#include "rcsbase.h"
#if DIFF_L
static char const *setup_label P((struct buf*,char const*,char const[datesize]));
#endif
static void cleanup P((void));
static int exitstatus;
static RILE *workptr;
static struct stat workstat;
mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c 3476 2003-06-11 15:56:10Z darkwyrm $")
{
static char const cmdusage[] =
"\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, *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[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;
bufautobegin(&commarg);
bufautobegin(&numericrev);
revnums = 0;
rev1 = rev2 = xrev2 = 0;
#if DIFF_L
file_labels = 0;
#endif
expandarg = suffixarg = versionarg = zonearg = 0;
no_diff_means_no_output = true;
suffixes = X_DEFAULT;
/*
* 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) {
case 'r':
switch (++revnums) {
case 1: rev1=a; break;
case 2: rev2=a; break;
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
if (c == 'L' && ++file_labels == 2)
faterror("too many -L options");
#endif
*dcp++ = c;
if (*a)
do *dcp++ = *a++;
while (*a);
else {
if (!--argc)
faterror("-%c needs following argument%s",
c, cmdusage
);
*diffp++ = *argv++;
}
break;
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':
case 'h': case 'i': case 'n': case 'p':
case 't': case 'u': case 'w':
*dcp++ = c;
break;
case 'q':
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);
goto option_handled;
case 'k':
expandarg = *argv;
if (0 <= str2expmode(expandarg+2))
goto option_handled;
/* fall into */
default:
unknown:
error("unknown option: %s%s", *argv, cmdusage);
};
option_handled:
if (dcp != *argv+1) {
*dcp = 0;
*diffp++ = *argv;
}
} /* end of option processing */
for (pp = diffv+2, c = 0; pp<diffp; )
c += strlen(*pp++) + 1;
diffvstr = a = tnalloc(char, c + 1);
for (pp = diffv+2; pp<diffp; ) {
p = *pp++;
*a++ = ' ';
while ((*a = *p++))
a++;
}
*a = 0;
#if DIFF_L
diff_label1 = diff_label2 = 0;
if (file_labels < 2) {
if (!file_labels)
diff_label1 = diffp++;
diff_label2 = diffp++;
}
#endif
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 (pairnames(argc, argv, rcsreadopen, true, false) <= 0)
continue;
diagnose("===================================================================\nRCS file: %s\n",RCSname);
if (!rev2) {
/* Make sure work file is readable, and get its status. */
if (!(workptr = Iopen(workname, FOPEN_R_WORK, &workstat))) {
eerror(workname);
continue;
}
}
gettree(); /* reads in the delta tree */
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 *)0,(char *)0,(char *)0,&gendeltas))) continue;
xrev1=target->num;
#if DIFF_L
if (diff_label1)
*diff_label1 = setup_label(&labelbuf[0], target->num, target->date);
#endif
lexpandarg = expandarg;
if (revnums==2) {
if (!fexpandsym(
*rev2 ? rev2 : Dbranch ? Dbranch : Head->num,
&numericrev,
workptr
))
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
&& Expand == KEYVAL_EXPAND
&& WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
)
lexpandarg = "-kkvl";
Izclose(&workptr);
#if DIFF_L
if (diff_label2)
if (revnums == 2)
*diff_label2 = setup_label(&labelbuf[1], target->num, target->date);
else {
time2date(workstat.st_mtime, date2);
*diff_label2 = setup_label(&labelbuf[1], (char*)0, date2);
}
#endif
diagnose("retrieving revision %s\n", xrev1);
bufscpy(&commarg, "-p");
bufscat(&commarg, rev1); /* not xrev1, for $Name's sake */
pp = &cov[3 + !DIFF_L];
*pp++ = commarg.string;
if (lexpandarg) *pp++ = lexpandarg;
if (suffixarg) *pp++ = suffixarg;
if (versionarg) *pp++ = versionarg;
if (zonearg) *pp++ = zonearg;
*pp++ = RCSname;
*pp = 0;
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] = workname;
if (*workname == '-') {
char *dp = ftnalloc(char, strlen(workname)+3);
diffp[1] = dp;
*dp++ = '.';
*dp++ = SLASH;
VOID strcpy(dp, workname);
}
} else {
diagnose("retrieving revision %s\n",xrev2);
bufscpy(&commarg, "-p");
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, workname);
else
diagnose("diff%s -r%s -r%s\n", diffvstr, xrev1, xrev2);
diffp[2] = 0;
switch (runv(-1, (char*)0, diffv)) {
case DIFF_SUCCESS:
break;
case DIFF_FAILURE:
if (exitstatus == DIFF_SUCCESS)
exitstatus = DIFF_FAILURE;
break;
default:
workerror("diff failed");
}
}
tempunlink();
exitmain(exitstatus);
}
static void
cleanup()
{
if (nerror) exitstatus = DIFF_TROUBLE;
Izclose(&finptr);
Izclose(&workptr);
}
#if RCS_lint
# define exiterr rdiffExit
#endif
void
exiterr()
{
tempunlink();
_exit(DIFF_TROUBLE);
}
#if DIFF_L
static char const *
setup_label(b, num, date)
struct buf *b;
char const *num;
char const date[datesize];
{
char *p;
char datestr[datesize + zonelenmax];
VOID date2str(date, datestr);
bufalloc(b,
strlen(workname)
+ sizeof datestr + 4
+ (num ? strlen(num) : 0)
);
p = b->string;
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
File diff suppressed because it is too large Load Diff
-358
View File
@@ -1,358 +0,0 @@
/* Compare working files, ignoring RCS keyword strings. */
/*****************************************************************************
* rcsfcmp()
* Testprogram: define FCMPTEST
*****************************************************************************
*/
/* 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.
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:
[email protected]
*/
/*
* $Log: rcsfcmp.c,v $
* Revision 1.1 2003/06/11 15:56:09 darkwyrm
* Added rcs, gzip, sed, and associated utilities.
*
* 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.
*
* Revision 5.8 1991/08/19 03:13:55 eggert
* Tune.
*
* Revision 5.7 1991/04/21 11:58:22 eggert
* Fix errno bug. Add MS-DOS support.
*
* Revision 5.6 1991/02/28 19:18:47 eggert
* Open work file at most once.
*
* Revision 5.5 1990/11/27 09:26:05 eggert
* Fix comment leader bug.
*
* Revision 5.4 1990/11/01 05:03:42 eggert
* Permit arbitrary data in logs and comment leaders.
*
* Revision 5.3 1990/09/11 02:41:15 eggert
* Don't ignore differences inside keyword strings if -ko is set.
*
* Revision 5.1 1990/08/29 07:13:58 eggert
* Clean old log messages too.
*
* Revision 5.0 1990/08/22 08:12:49 eggert
* Don't append "checked in with -k by " log to logs,
* so that checking in a program with -k doesn't change it.
* Ansify and Posixate. Remove lint.
*
* Revision 4.5 89/05/01 15:12:42 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.4 88/08/09 19:12:50 eggert
* Shrink stdio code size.
*
* Revision 4.3 87/12/18 11:40:02 narten
* lint cleanups (Guy Harris)
*
* Revision 4.2 87/10/18 10:33:06 narten
* updting version number. Changes relative to 1.1 actually relative to
* 4.1
*
* Revision 1.2 87/03/27 14:22:19 jenkins
* Port to suns
*
* Revision 4.1 83/05/10 16:24:04 wft
* Marker matching now uses trymatch(). Marker pattern is now
* checked precisely.
*
* Revision 3.1 82/12/04 13:21:40 wft
* Initial revision.
*
*/
/*
#define FCMPTEST
*/
/* Testprogram; prints out whether two files are identical,
* except for keywords
*/
#include "rcsbase.h"
libId(fcmpId, "$Id: rcsfcmp.c 3476 2003-06-11 15:56:10Z darkwyrm $")
static int discardkeyval P((int,RILE*));
static int
discardkeyval(c, f)
register int c;
register RILE *f;
{
for (;;)
switch (c) {
case KDELIM:
case '\n':
return c;
default:
Igeteof_(f, c, return EOF;)
break;
}
}
int
rcsfcmp(xfp, xstatp, uname, delta)
register RILE *xfp;
struct stat const *xstatp;
char const *uname;
struct hshentry const *delta;
/* 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 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,
* disregard it and optionally skip log message; otherwise, compare value.
*/
{
register int xc, uc;
char xkeyword[keylength+2];
int eqkeyvals;
register RILE *ufp;
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(uname, FOPEN_R_WORK, &ustat))) {
efaterror(uname);
}
xeof = ueof = false;
if (MIN_UNEXPAND <= Expand) {
if (!(result = xstatp->st_size!=ustat.st_size)) {
# 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;)
if (xeof | ueof)
goto eof;
if (xc != uc)
goto return1;
}
# endif
}
} 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;)
if (xeof | ueof)
goto eof;
} else {
/* try to get both keywords */
tp = xkeyword;
for (;;) {
Igeteof_(xfp, xc, xeof=true;)
Igeteof_(ufp, uc, ueof=true;)
if (xeof | ueof)
goto eof;
if (xc != uc)
break;
switch (xc) {
default:
if (xkeyword+keylength <= tp)
break;
*tp++ = xc;
continue;
case '\n': case KDELIM: case VDELIM:
break;
}
break;
}
if (
(xc==KDELIM || xc==VDELIM) && (uc==KDELIM || uc==VDELIM) &&
(*tp = xc, (match1 = trymatch(xkeyword)) != Nomatch)
) {
#ifdef FCMPTEST
VOID printf("found common keyword %s\n",xkeyword);
#endif
result = -1;
for (;;) {
if (xc != uc) {
xc = discardkeyval(xc, xfp);
uc = discardkeyval(uc, ufp);
if ((xeof = xc==EOF) | (ueof = uc==EOF))
goto eof;
eqkeyvals = false;
break;
}
switch (xc) {
default:
Igeteof_(xfp, xc, xeof=true;)
Igeteof_(ufp, uc, ueof=true;)
if (xeof | ueof)
goto eof;
continue;
case '\n': case KDELIM:
eqkeyvals = true;
break;
}
break;
}
if (xc != uc)
goto return1;
if (xc==KDELIM) {
/* Skip closing KDELIM. */
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 */
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. 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;)
}
/* skip last comment leader */
/* Can't just skip another line here, because there may be */
/* additional characters on the line (after the Log....$) */
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, because the leader's
* trailing white space was probably stripped.
*/
} while (ccnt-- && (xc!='\n' || --c1));
}
}
} else {
/* both end in the same character, but not a KDELIM */
/* must compare string values.*/
#ifdef FCMPTEST
VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
#endif
if (!eqkeyvals)
goto return1;
}
}
}
if (xc != uc)
goto return1;
if (xc == '\n')
leaderlen = 0;
else
leaderlen++;
}
}
eof:
if (xeof==ueof)
goto returnresult;
return1:
result = 1;
returnresult:
Ifclose(ufp);
return result;
}
#ifdef FCMPTEST
char const cmdid[] = "rcsfcmp";
main(argc, argv)
int argc; char *argv[];
/* first argument: comment leader; 2nd: log message, 3rd: expanded file,
* 4th: unexpanded file
*/
{ struct hshentry delta;
Comment.string = argv[1];
Comment.size = strlen(argv[1]);
delta.log.string = argv[2];
delta.log.size = strlen(argv[2]);
if (rcsfcmp(Iopen(argv[3], FOPEN_R_WORK, (struct stat*)0), argv[4], &delta))
VOID printf("files are the same\n");
else VOID printf("files are different\n");
}
#endif
File diff suppressed because it is too large Load Diff
-99
View File
@@ -1,99 +0,0 @@
#! /bin/sh
# rcsfreeze - assign a symbolic revision number to a configuration of RCS files
# $Id: rcsfreeze.sh 3476 2003-06-11 15:56:10Z darkwyrm $
# The idea is to run rcsfreeze each time a new version is checked
# in. A unique symbolic revision number (C_[number], where number
# is increased each time rcsfreeze is run) is then assigned to the most
# recent revision of each RCS file of the main trunk.
#
# If the command is invoked with an argument, then this
# argument is used as the symbolic name to freeze a configuration.
# The unique identifier is still generated
# and is listed in the log file but it will not appear as
# part of the symbolic revision name in the actual RCS file.
#
# A log message is requested from the user which is saved for future
# references.
#
# The shell script works only on all RCS files at one time.
# It is important that all changed files are checked in (there are
# no precautions against any error in this respect).
# file names:
# {RCS/}.rcsfreeze.ver version number
# {RCS/}.rscfreeze.log log messages, most recent first
PATH=/usr/local/bin:/bin:/usr/bin:/usr/ucb:$PATH
export PATH
DATE=`date` || exit
# Check whether we have an RCS subdirectory, so we can have the right
# prefix for our paths.
if test -d RCS
then RCSDIR=RCS/ EXT=
else RCSDIR= EXT=,v
fi
# Version number stuff, log message file
VERSIONFILE=${RCSDIR}.rcsfreeze.ver
LOGFILE=${RCSDIR}.rcsfreeze.log
# Initialize, rcsfreeze never run before in the current directory
test -r $VERSIONFILE || { echo 0 >$VERSIONFILE && >>$LOGFILE; } || exit
# Get Version number, increase it, write back to file.
VERSIONNUMBER=`cat $VERSIONFILE` &&
VERSIONNUMBER=`expr $VERSIONNUMBER + 1` &&
echo $VERSIONNUMBER >$VERSIONFILE || exit
# Symbolic Revision Number
SYMREV=C_$VERSIONNUMBER
# Allow the user to give a meaningful symbolic name to the revision.
SYMREVNAME=${1-$SYMREV}
echo >&2 "rcsfreeze: symbolic revision number computed: \"${SYMREV}\"
rcsfreeze: symbolic revision number used: \"${SYMREVNAME}\"
rcsfreeze: the two differ only when rcsfreeze invoked with argument
rcsfreeze: give log message, summarizing changes (end with EOF or single '.')" \
|| exit
# Stamp the logfile. Because we order the logfile the most recent
# first we will have to save everything right now in a temporary file.
TMPLOG=/tmp/rcsfrz$$
trap 'rm -f $TMPLOG; exit 1' 1 2 13 15
# Now ask for a log message, continously add to the log file
(
echo "Version: $SYMREVNAME($SYMREV), Date: $DATE
-----------" || exit
while read MESS
do
case $MESS in
.) break
esac
echo " $MESS" || exit
done
echo "-----------
" &&
cat $LOGFILE
) >$TMPLOG &&
# combine old and new logfiles
cp $TMPLOG $LOGFILE &&
rm -f $TMPLOG &&
# Now the real work begins by assigning a symbolic revision number
# to each rcs file. Take the most recent version on the default branch.
# If there are any .*,v files, throw them in too.
# But ignore RCS/.* files that do not end in ,v.
DOTFILES=
for DOTFILE in ${RCSDIR}.*,v
do
if test -f "$DOTFILE"
then
DOTFILES="${RCSDIR}.*,v"
break
fi
done
exec rcs -q -n$SYMREVNAME: ${RCSDIR}*$EXT $DOTFILES
-685
View File
@@ -1,685 +0,0 @@
/* Generate RCS revisions. */
/* 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.
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
*/
/*
* $Log: rcsgen.c,v $
* Revision 1.1 2003/06/11 15:56:09 darkwyrm
* Added rcs, gzip, sed, and associated utilities.
*
* 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.
*
* Revision 5.9 1991/09/10 22:15:46 eggert
* Fix test for redirected stdin.
*
* Revision 5.8 1991/08/19 03:13:55 eggert
* Add piece tables. Tune.
*
* Revision 5.7 1991/04/21 11:58:24 eggert
* Add MS-DOS support.
*
* Revision 5.6 1990/12/27 19:54:26 eggert
* Fix bug: rcs -t inserted \n, making RCS file grow.
*
* Revision 5.5 1990/12/04 05:18:45 eggert
* Use -I for prompts and -q for diagnostics.
*
* Revision 5.4 1990/11/01 05:03:47 eggert
* Add -I and new -t behavior. Permit arbitrary data in logs.
*
* Revision 5.3 1990/09/21 06:12:43 hammer
* made putdesc() treat stdin the same whether or not it was from a terminal
* by making it recognize that a single '.' was then end of the
* description always
*
* Revision 5.2 1990/09/04 08:02:25 eggert
* Fix `co -p1.1 -ko' bug. Standardize yes-or-no procedure.
*
* Revision 5.1 1990/08/29 07:14:01 eggert
* Clean old log messages too.
*
* Revision 5.0 1990/08/22 08:12:52 eggert
* Remove compile-time limits; use malloc instead.
* Ansify and Posixate.
*
* Revision 4.7 89/05/01 15:12:49 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.6 88/08/28 14:59:10 eggert
* Shrink stdio code size; allow cc -R; remove lint; isatty() -> ttystdin()
*
* Revision 4.5 87/12/18 11:43:25 narten
* additional lint cleanups, and a bug fix from the 4.3BSD version that
* keeps "ci" from sticking a '\377' into the description if you run it
* with a zero-length file as the description. (Guy Harris)
*
* Revision 4.4 87/10/18 10:35:10 narten
* Updating version numbers. Changes relative to 1.1 actually relative to
* 4.2
*
* Revision 1.3 87/09/24 13:59:51 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:22:27 jenkins
* Port to suns
*
* Revision 4.2 83/12/02 23:01:39 wft
* merged 4.1 and 3.3.1.1 (clearerr(stdin)).
*
* Revision 4.1 83/05/10 16:03:33 wft
* Changed putamin() to abort if trying to reread redirected stdin.
* Fixed getdesc() to output a prompt on initial newline.
*
* Revision 3.3.1.1 83/10/19 04:21:51 lepreau
* Added clearerr(stdin) for re-reading description from stdin.
*
* Revision 3.3 82/11/28 21:36:49 wft
* 4.2 prerelease
*
* Revision 3.3 82/11/28 21:36:49 wft
* Replaced ferror() followed by fclose() with ffclose().
* Putdesc() now suppresses the prompts if stdin
* is not a terminal. A pointer to the current log message is now
* inserted into the corresponding delta, rather than leaving it in a
* global variable.
*
* Revision 3.2 82/10/18 21:11:26 wft
* I added checks for write errors during editing, and improved
* the prompt on putdesc().
*
* Revision 3.1 82/10/13 15:55:09 wft
* corrected type of variables assigned to by getc (char --> int)
*/
#include "rcsbase.h"
libId(genId, "$Id: rcsgen.c 3476 2003-06-11 15:56:10Z darkwyrm $")
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));
char const *
buildrevision(deltas, target, outfile, expandflag)
struct hshentries const *deltas;
struct hshentry *target;
FILE *outfile;
int expandflag;
/* Function: Generates the revision given by target
* by retrieving all deltas given by parameter deltas and combining them.
* If outfile is set, the revision is output to it,
* otherwise written into a temporary file.
* Temporary files are allocated by maketemp().
* if expandflag is set, keyword expansion is performed.
* 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 (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.
*/
{
if (deltas->first == target) {
/* only latest revision to generate */
openfcopy(outfile);
scandeltatext(target, expandflag?expand:copy, true);
if (outfile)
return 0;
else {
Ozclose(&fcopy);
return resultname;
}
} else {
/* several revisions to generate */
/* Get initial revision without keyword expansion. */
scandeltatext(deltas->first, enter, false);
while ((deltas=deltas->rest)->rest) {
/* do all deltas except last one */
scandeltatext(deltas->first, edit, false);
}
if (expandflag || outfile) {
/* first, get to beginning of file*/
finishedit((struct hshentry*)0, outfile, false);
}
scandeltatext(target, expandflag?edit_expand:edit, true);
finishedit(
expandflag ? target : (struct hshentry*)0,
outfile, true
);
if (outfile)
return 0;
Ozclose(&fcopy);
return resultname;
}
}
static void
scandeltatext(delta, func, needlog)
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.
*/
{
struct hshentry const *nextdelta;
struct cbuf cb;
for (;;) {
if (eoflex())
fatserror("can't find delta for revision %s", delta->num);
nextlex();
if (!(nextdelta=getnum())) {
fatserror("delta number corrupted");
}
getkeystring(Klog);
if (needlog && delta==nextdelta) {
cb = savestring(&curlogbuf);
delta->log = cleanlogmsg(curlogbuf.string, cb.size);
nextlex();
delta->igtext = getphrases(Ktext);
} else {readstring();
ignorephrases(Ktext);
}
getkeystring(Ktext);
if (delta==nextdelta)
break;
readstring(); /* skip over it */
}
switch (func) {
case enter: enterstring(); break;
case copy: copystring(); break;
case expand: xpandstring(delta); break;
case edit: editstring((struct hshentry *)0); break;
case edit_expand: editstring(delta); break;
}
}
struct cbuf
cleanlogmsg(m, s)
char *m;
size_t s;
{
register char *t = m;
register char const *f = t;
struct cbuf r;
while (s) {
--s;
if ((*t++ = *f++) == '\n')
while (m < --t)
if (t[-1]!=' ' && t[-1]!='\t') {
*t++ = '\n';
break;
}
}
while (m < t && (t[-1]==' ' || t[-1]=='\t' || t[-1]=='\n'))
--t;
r.string = m;
r.size = t - m;
return r;
}
int ttystdin()
{
static int initialized;
if (!initialized) {
if (!interactiveflag)
interactiveflag = isatty(STDIN_FILENO);
initialized = true;
}
return interactiveflag;
}
int
getcstdin()
{
register FILE *in;
register int c;
in = stdin;
if (feof(in) && ttystdin())
clearerr(in);
c = getc(in);
if (c == EOF) {
testIerror(in);
if (feof(in) && ttystdin())
afputc('\n',stderr);
}
return c;
}
#if has_prototypes
int
yesorno(int default_answer, char const *question, ...)
#else
/*VARARGS2*/ int
yesorno(default_answer, question, va_alist)
int default_answer; char const *question; va_dcl
#endif
{
va_list args;
register int c, r;
if (!quietflag && ttystdin()) {
oflush();
vararg_start(args, question);
fvfprintf(stderr, question, args);
va_end(args);
eflush();
r = c = getcstdin();
while (c!='\n' && !feof(stdin))
c = getcstdin();
if (r=='y' || r=='Y')
return true;
if (r=='n' || r=='N')
return false;
}
return default_answer;
}
void
putdesc(textflag, textfile)
int textflag;
char *textfile;
/* Function: puts the descriptive text into file frewrite.
* if finptr && !textflag, the text is copied from the old description.
* 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.
*/
{
static struct buf desc;
static struct cbuf desclean;
register FILE *txt;
register int c;
register FILE * frew;
register char *p;
register size_t s;
char const *plim;
frew = frewrite;
if (finptr && !textflag) {
/* copy old description */
aprintf(frew, "\n\n%s%c", Kdesc, nextc);
foutptr = frewrite;
getdesc(false);
foutptr = 0;
} else {
foutptr = 0;
/* get new description */
if (finptr) {
/*skip old description*/
getdesc(false);
}
aprintf(frew,"\n\n%s\n%c",Kdesc,SDELIM);
if (!textfile)
desclean = getsstdin(
"t-", "description",
"NOTE: This is NOT the log message!\n", &desc
);
else if (!desclean.string) {
if (*textfile == '-') {
p = textfile + 1;
s = strlen(p);
} else {
if (!(txt = fopenSafer(textfile, "r")))
efaterror(textfile);
bufalloc(&desc, 1);
p = desc.string;
plim = p + desc.size;
for (;;) {
if ((c=getc(txt)) == EOF) {
testIerror(txt);
if (feof(txt))
break;
}
if (plim <= p)
p = bufenlarge(&desc, &plim);
*p++ = c;
}
if (fclose(txt) != 0)
Ierror();
s = p - desc.string;
p = desc.string;
}
desclean = cleanlogmsg(p, s);
}
putstring(frew, false, desclean, true);
aputc_('\n', frew)
}
}
struct cbuf
getsstdin(option, name, note, buf)
char const *option, *name, *note;
struct buf *buf;
{
register int c;
register char *p;
register size_t i;
register int tty = ttystdin();
if (tty) {
aprintf(stderr,
"enter %s, terminated with single '.' or end of file:\n%s>> ",
name, note
);
eflush();
} else if (feof(stdin))
rcsfaterror("can't reread redirected stdin for %s; use -%s<%s>",
name, option, name
);
for (
i = 0, p = 0;
c = getcstdin(), !feof(stdin);
bufrealloc(buf, i+1), p = buf->string, p[i++] = c
)
if (c == '\n')
if (i && p[i-1]=='.' && (i==1 || p[i-2]=='\n')) {
/* Remove trailing '.'. */
--i;
break;
} 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);
}
-455
View File
@@ -1,455 +0,0 @@
/* Extract RCS keyword string values 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.
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
*/
/*
* $Log: rcskeep.c,v $
* Revision 1.1 2003/06/11 15:56:10 darkwyrm
* Added rcs, gzip, sed, and associated utilities.
*
* 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.
*
* Revision 5.3 1991/04/21 11:58:25 eggert
* Shorten names to keep them distinct on shortname hosts.
*
* Revision 5.2 1990/10/04 06:30:20 eggert
* Parse time zone offsets; future RCS versions may output them.
*
* Revision 5.1 1990/09/20 02:38:56 eggert
* ci -k now checks dates more thoroughly.
*
* Revision 5.0 1990/08/22 08:12:53 eggert
* Retrieve old log message if there is one.
* Don't require final newline.
* Remove compile-time limits; use malloc instead. Tune.
* Permit dates past 1999/12/31. Ansify and Posixate.
*
* Revision 4.6 89/05/01 15:12:56 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.5 88/08/09 19:13:03 eggert
* Remove lint and speed up by making FILE *fp local, not global.
*
* Revision 4.4 87/12/18 11:44:21 narten
* more lint cleanups (Guy Harris)
*
* Revision 4.3 87/10/18 10:35:50 narten
* Updating version numbers. Changes relative to 1.1 actually relative
* to 4.1
*
* Revision 1.3 87/09/24 14:00:00 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:22:29 jenkins
* Port to suns
*
* Revision 4.1 83/05/10 16:26:44 wft
* Added new markers Id and RCSfile; extraction added.
* Marker matching with trymatch().
*
* Revision 3.2 82/12/24 12:08:26 wft
* added missing #endif.
*
* Revision 3.1 82/12/04 13:22:41 wft
* Initial revision.
*
*/
#include "rcsbase.h"
libId(keepId, "$Id: rcskeep.c 3476 2003-06-11 15:56:10Z darkwyrm $")
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, 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 fp is null, workname is opened and closed instead of using fp.
* The results are placed into
* 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
* contain the empty string.
*/
{
register int c;
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(workname, FOPEN_R_WORK, (struct stat*)0))) {
eerror(workname);
return false;
}
needs_closing = true;
}
/* initialize to empty */
bufscpy(&prevauthor, "");
bufscpy(&prevdate, "");
bufscpy(&prevname, ""); prevname_found = 0;
bufscpy(&prevrev, "");
bufscpy(&prevstate, "");
c = '\0'; /* anything but KDELIM */
for (;;) {
if ( c==KDELIM) {
do {
/* try to get keyword */
tp = keyword;
for (;;) {
Igeteof_(fp, c, goto ok;)
switch (c) {
default:
if (keyword+keylength <= tp)
break;
*tp++ = c;
continue;
case '\n': case KDELIM: case VDELIM:
break;
}
break;
}
} while (c==KDELIM);
if (c!=VDELIM) continue;
*tp = c;
Igeteof_(fp, c, break;)
switch (c) {
case ' ': case '\t': break;
default: continue;
}
switch (trymatch(keyword)) {
case Author:
if (!keepid(0, fp, &prevauthor))
return false;
c = 0;
break;
case Date:
if (!(c = keepdate(fp)))
return false;
break;
case Header:
case Id:
if (!(
getval(fp, (struct buf*)0, false) &&
keeprev(fp) &&
(c = keepdate(fp)) &&
keepid(c, fp, &prevauthor) &&
keepid(0, fp, &prevstate)
))
return false;
/* Skip either ``who'' (new form) or ``Locker: who'' (old). */
if (getval(fp, (struct buf*)0, true) &&
getval(fp, (struct buf*)0, true))
c = 0;
else if (nerror)
return false;
else
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*)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;
c = 0;
break;
case State:
if (!keepid(0, fp, &prevstate))
return false;
c = 0;
break;
default:
continue;
}
if (!c)
Igeteof_(fp, c, c=0;)
if (c != KDELIM) {
workerror("closing %c missing on keyword", KDELIM);
return false;
}
if (prevname_found &&
*prevauthor.string && *prevdate.string &&
*prevrev.string && *prevstate.string
)
break;
}
Igeteof_(fp, c, break;)
}
ok:
if (needs_closing)
Ifclose(fp);
else
Irewind(fp);
prevkeys = true;
return true;
}
static int
badly_terminated()
{
workerror("badly terminated keyword value");
return false;
}
static int
getval(fp, target, optional)
register RILE *fp;
struct buf *target;
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 0.
* Do not report an error if OPTIONAL is set and KDELIM is found instead.
*/
{
int c;
Igeteof_(fp, c, return badly_terminated();)
return get0val(c, fp, target, optional);
}
static int
get0val(c, fp, target, optional)
register int c;
register RILE *fp;
struct buf *target;
int optional;
/* Reads a keyword value from C+FP into TARGET, perhaps OPTIONALly.
* Same as getval, except C is the lookahead character.
*/
{ register char * tp;
char const *tlim;
register int got1;
if (target) {
bufalloc(target, 1);
tp = target->string;
tlim = tp + target->size;
} else
tlim = tp = 0;
got1 = false;
for (;;) {
switch (c) {
default:
got1 = true;
if (tp) {
*tp++ = c;
if (tlim <= tp)
tp = bufenlarge(target, &tlim);
}
break;
case ' ':
case '\t':
if (tp) {
*tp = 0;
# ifdef KEEPTEST
VOID printf("getval: %s\n", target);
# endif
}
return got1;
case KDELIM:
if (!got1 && optional)
return false;
/* fall into */
case '\n':
case 0:
return badly_terminated();
}
Igeteof_(fp, c, return badly_terminated();)
}
}
static int
keepdate(fp)
RILE *fp;
/* Function: reads a date prevdate; checks format
* Return 0 on error, lookahead character otherwise.
*/
{
struct buf prevday, prevtime;
register int c;
c = 0;
bufautobegin(&prevday);
if (getval(fp,&prevday,false)) {
bufautobegin(&prevtime);
if (getval(fp,&prevtime,false)) {
Igeteof_(fp, c, c=0;)
if (c) {
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(d[0]) && isdigit(d[1]) && !isdigit(d[2])
? "19" : "",
d, t,
strchr(t,'-') || strchr(t,'+') ? "" : "+0000"
);
}
}
bufautoend(&prevtime);
}
bufautoend(&prevday);
return c;
}
static int
keepid(c, fp, b)
int c;
RILE *fp;
struct buf *b;
/* Get previous identifier from C+FP into B. */
{
if (!c)
Igeteof_(fp, c, return false;)
if (!get0val(c, fp, b, false))
return false;
checksid(b->string);
return !nerror;
}
static int
keeprev(fp)
RILE *fp;
/* Get previous revision from FP into prevrev. */
{
return getval(fp,&prevrev,false) && checknum(prevrev.string);
}
static int
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
main(argc, argv)
int argc; char *argv[];
{
while (*(++argv)) {
workname = *argv;
getoldkeys((RILE*)0);
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);
}
#endif
-109
View File
@@ -1,109 +0,0 @@
/* RCS keyword table and match operation */
/* 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.
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
*/
/*
* $Log: rcskeys.c,v $
* Revision 1.1 2003/06/11 15:56:10 darkwyrm
* Added rcs, gzip, sed, and associated utilities.
*
* Revision 5.4 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* 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.
* (This change was made in other source files too.)
*
* Revision 5.1 1991/04/21 11:58:25 eggert
* Don't put , just before } in initializer.
*
* Revision 5.0 1990/08/22 08:12:54 eggert
* Add -k. Ansify and Posixate.
*
* Revision 4.3 89/05/01 15:13:02 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.2 87/10/18 10:36:33 narten
* Updating version numbers. Changes relative to 1.1 actuallyt
* relative to 4.1
*
* Revision 1.2 87/09/24 14:00:10 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 4.1 83/05/04 10:06:53 wft
* Initial revision.
*
*/
#include "rcsbase.h"
libId(keysId, "$Id: rcskeys.c 3476 2003-06-11 15:56:10Z darkwyrm $")
char const *const Keyword[] = {
/* This must be in the same order as rcsbase.h's enum markers type. */
0,
AUTHOR, DATE, HEADER, IDH,
LOCKER, LOG, NAME, RCSFILE, REVISION, SOURCE, STATE
};
enum markers
trymatch(string)
char const *string;
/* function: Checks whether string starts with a keyword followed
* by a KDELIM or a VDELIM.
* If successful, returns the appropriate marker, otherwise Nomatch.
*/
{
register int j;
register char const *p, *s;
for (j = sizeof(Keyword)/sizeof(*Keyword); (--j); ) {
/* try next keyword */
p = Keyword[j];
s = string;
while (*p++ == *s++) {
if (!*p)
switch (*s) {
case KDELIM:
case VDELIM:
return (enum markers)j;
default:
return Nomatch;
}
}
}
return(Nomatch);
}
-1576
View File
File diff suppressed because it is too large Load Diff
-69
View File
@@ -1,69 +0,0 @@
/* RCS map of character types */
/* Copyright (C) 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1995 by 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
*/
#include "rcsbase.h"
libId(mapId, "$Id: rcsmap.c 3476 2003-06-11 15:56:10Z darkwyrm $")
/* map of character types */
/* ISO 8859/1 (Latin-1) */
enum tokens const ctab[] = {
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
SPACE, SPACE, NEWLN, SPACE, SPACE, SPACE, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
SPACE, IDCHAR, IDCHAR, IDCHAR, DELIM, IDCHAR, IDCHAR, IDCHAR,
IDCHAR, IDCHAR, IDCHAR, IDCHAR, DELIM, IDCHAR, PERIOD, IDCHAR,
DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
DIGIT, DIGIT, COLON, SEMI, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
SBEGIN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
IDCHAR, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
Letter, Letter, Letter, IDCHAR, IDCHAR, IDCHAR, IDCHAR, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, IDCHAR,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, Letter,
Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
Letter, Letter, Letter, Letter, Letter, Letter, Letter, IDCHAR,
Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter
};
-290
View File
@@ -1,290 +0,0 @@
/* Merge RCS revisions. */
/* 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.
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
*/
/*
* $Log: rcsmerge.c,v $
* Revision 1.1 2003/06/11 15:56:10 darkwyrm
* Added rcs, gzip, sed, and associated utilities.
*
* 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.
*
* Revision 5.6 1991/08/19 03:13:55 eggert
* Add -r$. Tune.
*
* Revision 5.5 1991/04/21 11:58:27 eggert
* Add -x, RCSINIT, MS-DOS support.
*
* Revision 5.4 1991/02/25 07:12:43 eggert
* Merging a revision to itself is no longer an error.
*
* Revision 5.3 1990/11/01 05:03:50 eggert
* Remove unneeded setid check.
*
* Revision 5.2 1990/09/04 08:02:28 eggert
* Check for I/O error when reading working file.
*
* Revision 5.1 1990/08/29 07:14:04 eggert
* Add -q. Pass -L options to merge.
*
* Revision 5.0 1990/08/22 08:13:41 eggert
* Propagate merge's exit status.
* Remove compile-time limits; use malloc instead.
* Make lock and temp files faster and safer. Ansify and Posixate. Add -V.
* Don't use access(). Tune.
*
* Revision 4.5 89/05/01 15:13:16 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.4 88/08/09 19:13:13 eggert
* Beware merging into a readonly file.
* Beware merging a revision to itself (no change).
* Use execv(), not system(); yield exit status like diff(1)'s.
*
* Revision 4.3 87/10/18 10:38:02 narten
* Updating version numbers. Changes relative to version 1.1
* actually relative to 4.1
*
* Revision 1.3 87/09/24 14:00:31 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:22:36 jenkins
* Port to suns
*
* Revision 4.1 83/03/28 11:14:57 wft
* Added handling of default branch.
*
* Revision 3.3 82/12/24 15:29:00 wft
* Added call to catchsig().
*
* Revision 3.2 82/12/10 21:32:02 wft
* Replaced getdelta() with gettree(); improved error messages.
*
* Revision 3.1 82/11/28 19:27:44 wft
* Initial revision.
*
*/
#include "rcsbase.h"
static char const co[] = CO;
mainProg(rcsmergeId, "rcsmerge", "$Id: rcsmerge.c 3476 2003-06-11 15:56:10Z darkwyrm $")
{
static char const cmdusage[] =
"\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[3], *xrev[3]; /*revision numbers*/
char const *edarg, *expandarg, *suffixarg, *versionarg, *zonearg;
int tostdout;
int status;
RILE *workptr;
struct buf commarg;
struct buf numericrev; /* holds expanded revision number */
struct hshentries *gendeltas; /* deltas to be generated */
struct hshentry * target;
bufautobegin(&commarg);
bufautobegin(&numericrev);
edarg = rev[1] = rev[2] = 0;
status = 0; /* Keep lint happy. */
tostdout = false;
expandarg = suffixarg = versionarg = zonearg = quietarg; /* no-op */
suffixes = X_DEFAULT;
argc = getRCSINIT(argc, argv, &newargv);
argv = newargv;
while (a = *++argv, 0<--argc && *a++=='-') {
switch (*a++) {
case 'p':
tostdout=true;
goto revno;
case 'q':
quietflag = true;
revno:
if (!*a)
break;
/* falls into -r */
case 'r':
if (!rev[1])
rev[1] = a;
else if (!rev[2])
rev[2] = a;
else
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);
break;
case 'k':
expandarg = *argv;
if (0 <= str2expmode(expandarg+2))
break;
/* fall into */
default:
unknown:
error("unknown option: %s%s", *argv, cmdusage);
};
} /* end of option processing */
if (!rev[1]) faterror("no base revision number given");
/* Now handle all pathnames. */
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]))
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) rcsfaterror("no revisions present");
if (!*rev[1])
rev[1] = Dbranch ? Dbranch : Head->num;
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=1; i<=2; i++) {
diagnose("retrieving revision %s\n", xrev[i]);
bufscpy(&commarg, "-p");
bufscat(&commarg, rev[i]); /* not xrev[i], for $Name's sake */
if (run(
-1,
/* Do not collide with merger.c maketemp(). */
arg[i] = maketemp(i+2),
co, quietarg, commarg.string,
expandarg, suffixarg, versionarg, zonearg,
RCSname, (char*)0
))
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);
}
}
}
Izclose(&workptr);
}
}
tempunlink();
exitmain(nerror ? DIFF_TROUBLE : status);
}
#if RCS_lint
# define exiterr rmergeExit
#endif
void
exiterr()
{
tempunlink();
_exit(DIFF_TROUBLE);
}
-915
View File
@@ -1,915 +0,0 @@
/* Handle RCS revision numbers. */
/* 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.
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
*/
/*
* $Log: rcsrev.c,v $
* Revision 1.1 2003/06/11 15:56:10 darkwyrm
* Added rcs, gzip, sed, and associated utilities.
*
* 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.
*
* Revision 5.2 1991/04/21 11:58:28 eggert
* Add tiprev().
*
* Revision 5.1 1991/02/25 07:12:43 eggert
* Avoid overflow when comparing revision numbers.
*
* Revision 5.0 1990/08/22 08:13:43 eggert
* Remove compile-time limits; use malloc instead.
* Ansify and Posixate. Tune.
* Remove possibility of an internal error. Remove lint.
*
* Revision 4.5 89/05/01 15:13:22 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.4 87/12/18 11:45:22 narten
* more lint cleanups. Also, the NOTREACHED comment is no longer necessary,
* since there's now a return value there with a value. (Guy Harris)
*
* Revision 4.3 87/10/18 10:38:42 narten
* Updating version numbers. Changes relative to version 1.1 actually
* relative to 4.1
*
* Revision 1.3 87/09/24 14:00:37 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:22:37 jenkins
* Port to suns
*
* Revision 4.1 83/03/25 21:10:45 wft
* Only changed $Header to $Id.
*
* Revision 3.4 82/12/04 13:24:08 wft
* Replaced getdelta() with gettree().
*
* Revision 3.3 82/11/28 21:33:15 wft
* fixed compartial() and compnum() for nil-parameters; fixed nils
* in error messages. Testprogram output shortenend.
*
* Revision 3.2 82/10/18 21:19:47 wft
* renamed compnum->cmpnum, compnumfld->cmpnumfld,
* numericrevno->numricrevno.
*
* Revision 3.1 82/10/11 19:46:09 wft
* changed expandsym() to check for source==nil; returns zero length string
* in that case.
*/
#include "rcsbase.h"
libId(revId, "$Id: rcsrev.c 3476 2003-06-11 15:56:10Z darkwyrm $")
static char const *branchtip P((char const*));
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*));
int
countnumflds(s)
char const *s;
/* Given a pointer s to a dotted number (date or revision number),
* countnumflds returns the number of digitfields in s.
*/
{
register char const *sp;
register int count;
if (!(sp=s) || !*sp)
return 0;
count = 1;
do {
if (*sp++ == '.') count++;
} while (*sp);
return(count);
}
void
getbranchno(revno,branchno)
char const *revno;
struct buf *branchno;
/* 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 int numflds;
register char *tp;
bufscpy(branchno, revno);
numflds=countnumflds(revno);
if (!(numflds & 1)) {
tp = branchno->string;
while (--numflds)
while (*tp++ != '.')
continue;
*(tp-1)='\0';
}
}
int cmpnum(num1, num2)
char const *num1, *num2;
/* compares the two dotted numbers num1 and num2 lexicographically
* by field. Individual fields are compared numerically.
* returns <0, 0, >0 if num1<num2, num1==num2, and num1>num2, resp.
* omitted fields are assumed to be higher than the existing ones.
*/
{
register char const *s1, *s2;
register size_t d1, d2;
register int r;
s1 = num1 ? num1 : "";
s2 = num2 ? num2 : "";
for (;;) {
/* Give precedence to shorter one. */
if (!*s1)
return (unsigned char)*s2;
if (!*s2)
return -1;
/* Strip leading zeros, then find number of digits. */
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)
return d1<d2 ? -1 : 1;
if ((r = memcmp(s1, s2, d1)))
return r;
s1 += d1;
s2 += d1;
/* skip '.' */
if (*s1) s1++;
if (*s2) s2++;
}
}
int cmpnumfld(num1, num2, fld)
char const *num1, *num2;
int fld;
/* Compare the two dotted numbers at field fld.
* num1 and num2 must have at least fld fields.
* fld must be positive.
*/
{
register char const *s1, *s2;
register size_t d1, d2;
s1 = num1;
s2 = num2;
/* 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++) 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 + zonelenmax];
rcserror("No revision on branch %s has%s%s%s%s%s%s.",
revno,
date ? " a date before " : "",
date ? date2str(date,datebuf) : "",
author ? " and author "+(date?0:4) : "",
author ? author : "",
state ? " and state "+(date||author?0:4) : "",
state ? state : ""
);
}
static void
absent(revno, field)
char const *revno;
int field;
{
struct buf t;
bufautobegin(&t);
rcserror("%s %s absent", field&1?"revision":"branch",
partialno(&t,revno,field)
);
bufautoend(&t);
}
int
compartial(num1, num2, length)
char const *num1, *num2;
int length;
/* compare the first "length" fields of two dot numbers;
the omitted field is considered to be larger than any number */
/* restriction: at least one number has length or more fields */
{
register char const *s1, *s2;
register size_t d1, d2;
register int r;
s1 = num1; s2 = num2;
if (!s1) return 1;
if (!s2) return -1;
for (;;) {
if (!*s1) return 1;
if (!*s2) return -1;
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++;
}
}
char * partialno(rev1,rev2,length)
struct buf *rev1;
char const *rev2;
register int length;
/* Function: Copies length fields of revision number rev2 into rev1.
* Return rev1's string.
*/
{
register char *r1;
bufscpy(rev1, rev2);
r1 = rev1->string;
while (length) {
while (*r1!='.' && *r1)
++r1;
++r1;
length--;
}
/* eliminate last '.'*/
*(r1-1)='\0';
return rev1->string;
}
static void
store1(store, next)
struct hshentries ***store;
struct hshentry *next;
/*
* Allocate a new list node that addresses NEXT.
* Append it to the list that **STORE is the end pointer of.
*/
{
register struct hshentries *p;
p = ftalloc(struct hshentries);
p->first = next;
**store = p;
*store = &p->rest;
}
struct hshentry * genrevs(revno,date,author,state,store)
char const *revno, *date, *author, *state;
struct hshentries **store;
/* Function: finds the deltas needed for reconstructing the
* 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, 0 is returned.
*/
{
int length;
register struct hshentry * next;
int result;
char const *branchnum;
struct buf t;
char datebuf[datesize + zonelenmax];
bufautobegin(&t);
if (!(next = Head)) {
rcserror("RCS file empty");
goto norev;
}
length = countnumflds(revno);
if (length >= 1) {
/* at least one field; find branch exactly */
while ((result=cmpnumfld(revno,next->num,1)) < 0) {
store1(&store, next);
next = next->next;
if (!next) {
rcserror("branch number %s too low", partialno(&t,revno,1));
goto norev;
}
}
if (result>0) {
absent(revno, 1);
goto norev;
}
}
if (length<=1){
/* pick latest one on given branch */
branchnum = next->num; /* works even for empty revno*/
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 ||
(cmpnumfld(branchnum,next->num,1)!=0))/*overshot*/ {
cantfindbranch(
length ? revno : partialno(&t,branchnum,1),
date, author, state
);
goto norev;
} else {
store1(&store, next);
}
*store = 0;
return next;
}
/* length >=2 */
/* find revision; may go low if length==2*/
while ((result=cmpnumfld(revno,next->num,2)) < 0 &&
(cmpnumfld(revno,next->num,1)==0) ) {
store1(&store, next);
next = next->next;
if (!next)
break;
}
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)) {
absent(revno, 2);
goto norev;
}
/* print last one */
store1(&store, next);
if (length>2)
return genbranch(next,revno,length,date,author,state,store);
else { /* length == 2*/
if (date && cmpdate(date,next->date)<0) {
rcserror("Revision %s has date %s.",
next->num,
date2str(next->date, datebuf)
);
return 0;
}
if (author && strcmp(author,next->author)!=0) {
rcserror("Revision %s has author %s.",
next->num, next->author
);
return 0;
}
if (state && strcmp(state,next->state)!=0) {
rcserror("Revision %s has state %s.",
next->num,
next->state ? next->state : "<empty>"
);
return 0;
}
*store = 0;
return next;
}
norev:
bufautoend(&t);
return 0;
}
static struct hshentry *
genbranch(bpoint, revno, length, date, author, state, store)
struct hshentry const *bpoint;
char const *revno;
int length;
char const *date, *author, *state;
struct hshentries **store;
/* Function: given a branchpoint, a revision number, date, author, and state,
* genbranch finds the deltas necessary to reconstruct the given revision
* 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 0 on error.
*/
{
int field;
register struct hshentry * next, * trail;
register struct branchhead const *bhead;
int result;
struct buf t;
char datebuf[datesize + zonelenmax];
field = 3;
bhead = bpoint->branches;
do {
if (!bhead) {
bufautobegin(&t);
rcserror("no side branches present for %s",
partialno(&t,revno,field-1)
);
bufautoend(&t);
return 0;
}
/*find branch head*/
/*branches are arranged in increasing order*/
while (0 < (result=cmpnumfld(revno,bhead->hsh->num,field))) {
bhead = bhead->nextbranch;
if (!bhead) {
bufautobegin(&t);
rcserror("branch number %s too high",
partialno(&t,revno,field)
);
bufautoend(&t);
return 0;
}
}
if (result<0) {
absent(revno, field);
return 0;
}
next = bhead->hsh;
if (length==field) {
/* pick latest one on that branch */
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);
if (!trail) {
cantfindbranch(revno, date, author, state);
return 0;
} else { /* print up to last one suitable */
next = bhead->hsh;
while (next!=trail) {
store1(&store, next);
next=next->next;
}
store1(&store, next);
}
*store = 0;
return next;
}
/* length > field */
/* find revision */
/* check low */
if (cmpnumfld(revno,next->num,field+1)<0) {
bufautobegin(&t);
rcserror("revision number %s too low",
partialno(&t,revno,field+1)
);
bufautoend(&t);
return 0;
}
do {
store1(&store, next);
trail = next;
next = next->next;
} 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 0;
}
if (length == field+1) {
if (date && cmpdate(date,trail->date)<0) {
rcserror("Revision %s has date %s.",
trail->num,
date2str(trail->date, datebuf)
);
return 0;
}
if (author && strcmp(author,trail->author)!=0) {
rcserror("Revision %s has author %s.",
trail->num, trail->author
);
return 0;
}
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 = 0;
return trail;
}
static char const *
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. Return 0 if not present.
*/
{
register struct assoc const *next;
for (next = Symbols; next; next = next->nextassoc)
if (strcmp(id, next->symbol)==0)
return next->num;
return 0;
}
int expandsym(source, target)
char const *source;
struct buf *target;
/* Function: Source points to a revision number. Expandsym copies
* the number to target, but replaces all symbolic fields in the
* source number with their numeric values.
* Expand a branch followed by `.' to the latest revision on that branch.
* Ignore `.' after a revision. Remove leading zeros.
* returns false on error;
*/
{
return fexpandsym(source, target, (RILE*)0);
}
int
fexpandsym(source, target, fp)
char const *source;
struct buf *target;
RILE *fp;
/* Same as expandsym, except if FP is nonzero, it is used to expand KDELIM. */
{
register char const *sp, *bp;
register char *tp;
char const *tlim;
int dots;
sp = source;
bufalloc(target, 1);
tp = target->string;
if (!sp || !*sp) { /* Accept 0 pointer as a legal value. */
*tp='\0';
return true;
}
if (sp[0] == KDELIM && !sp[1]) {
if (!getoldkeys(fp))
return false;
if (!*prevrev.string) {
workerror("working file lacks revision number");
return false;
}
bufscpy(target, prevrev.string);
return true;
}
tlim = tp + target->size;
dots = 0;
for (;;) {
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;
if (id) {
bp = lookupsym(tp);
if (!bp) {
rcserror("Symbolic name `%s' is undefined.",tp);
return false;
}
} 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);
switch (*sp++) {
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;
}
break;
}
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;
{
struct hshentry *h;
struct hshentries *hs;
h = genrevs(branch, (char*)0, (char*)0, (char*)0, &hs);
return h ? h->num : (char const*)0;
}
char const *
tiprev()
{
return Dbranch ? branchtip(Dbranch) : Head ? Head->num : (char const*)0;
}
#ifdef REVTEST
/*
* Test the routines that generate a sequence of delta numbers
* needed to regenerate a given delta.
*/
char const cmdid[] = "revtest";
int
main(argc,argv)
int argc; char * argv[];
{
static struct buf numricrevno;
char symrevno[100]; /* used for input of revision numbers */
char author[20];
char state[20];
char date[20];
struct hshentries *gendeltas;
struct hshentry * target;
int i;
if (argc<2) {
aputs("No input file\n",stderr);
exitmain(EXIT_FAILURE);
}
if (!(finptr=Iopen(argv[1], FOPEN_R, (struct stat*)0))) {
faterror("can't open input file %s", argv[1]);
}
Lexinit();
getadmin();
gettree();
getdesc(false);
do {
/* all output goes to stderr, to have diagnostics and */
/* errors in sequence. */
aputs("\nEnter revision number or <return> or '.': ",stderr);
if (!gets(symrevno)) break;
if (*symrevno == '.') break;
aprintf(stderr,"%s;\n",symrevno);
expandsym(symrevno,&numricrevno);
aprintf(stderr,"expanded number: %s; ",numricrevno.string);
aprintf(stderr,"Date: ");
gets(date); aprintf(stderr,"%s; ",date);
aprintf(stderr,"Author: ");
gets(author); aprintf(stderr,"%s; ",author);
aprintf(stderr,"State: ");
gets(state); aprintf(stderr, "%s;\n", state);
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;
}
}
} while (true);
aprintf(stderr,"done\n");
exitmain(EXIT_SUCCESS);
}
void exiterr() { _exit(EXIT_FAILURE); }
#endif
-685
View File
@@ -1,685 +0,0 @@
/* RCS file syntactic analysis */
/******************************************************************************
* Syntax Analysis.
* Keyword table
* Testprogram: define SYNTEST
* Compatibility with Release 2: define COMPAT2=1
******************************************************************************
*/
/* 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.
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
*/
/*
* $Log: rcssyn.c,v $
* Revision 1.1 2003/06/11 15:56:10 darkwyrm
* Added rcs, gzip, sed, and associated utilities.
*
* 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.
*
* Revision 5.7 1991/04/21 11:58:29 eggert
* Disambiguate names on shortname hosts.
* Fix errno bug. Add MS-DOS support.
*
* Revision 5.6 1991/02/28 19:18:51 eggert
* Fix null termination bug in reporting keyword expansion.
*
* Revision 5.5 1991/02/25 07:12:44 eggert
* Check diff output more carefully; avoid overflow.
*
* Revision 5.4 1990/11/01 05:28:48 eggert
* When ignoring unknown phrases, copy them to the output RCS file.
* Permit arbitrary data in logs and comment leaders.
* Don't check for nontext on initial checkin.
*
* Revision 5.3 1990/09/20 07:58:32 eggert
* Remove the test for non-text bytes; it caused more pain than it cured.
*
* Revision 5.2 1990/09/04 08:02:30 eggert
* Parse RCS files with no revisions.
* Don't strip leading white space from diff commands. Count RCS lines better.
*
* Revision 5.1 1990/08/29 07:14:06 eggert
* Add -kkvl. Clean old log messages too.
*
* Revision 5.0 1990/08/22 08:13:44 eggert
* Try to parse future RCS formats without barfing.
* Add -k. Don't require final newline.
* Remove compile-time limits; use malloc instead.
* Don't output branch keyword if there's no default branch,
* because RCS version 3 doesn't understand it.
* Tune. Remove lint.
* Add support for ISO 8859. Ansify and Posixate.
* Check that a newly checked-in file is acceptable as input to 'diff'.
* Check diff's output.
*
* Revision 4.6 89/05/01 15:13:32 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.5 88/08/09 19:13:21 eggert
* Allow cc -R; remove lint.
*
* Revision 4.4 87/12/18 11:46:16 narten
* more lint cleanups (Guy Harris)
*
* Revision 4.3 87/10/18 10:39:36 narten
* Updating version numbers. Changes relative to 1.1 actually relative to
* 4.1
*
* Revision 1.3 87/09/24 14:00:49 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:22:40 jenkins
* Port to suns
*
* Revision 4.1 83/03/28 11:38:49 wft
* Added parsing and printing of default branch.
*
* Revision 3.6 83/01/15 17:46:50 wft
* Changed readdelta() to initialize selector and log-pointer.
* Changed puttree to check for selector==DELETE; putdtext() uses DELNUMFORM.
*
* Revision 3.5 82/12/08 21:58:58 wft
* renamed Commentleader to Commleader.
*
* Revision 3.4 82/12/04 13:24:40 wft
* Added routine gettree(), which updates keeplock after reading the
* delta tree.
*
* Revision 3.3 82/11/28 21:30:11 wft
* Reading and printing of Suffix removed; version COMPAT2 skips the
* Suffix for files of release 2 format. Fixed problems with printing nil.
*
* Revision 3.2 82/10/18 21:18:25 wft
* renamed putdeltatext to putdtext.
*
* Revision 3.1 82/10/11 19:45:11 wft
* made sure getc() returns into an integer.
*/
/* version COMPAT2 reads files of the format of release 2 and 3, but
* generates files of release 3 format. Need not be defined if no
* old RCS files generated with release 2 exist.
*/
#include "rcsbase.h"
libId(synId, "$Id: rcssyn.c 3476 2003-06-11 15:56:10Z darkwyrm $")
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
Kaccess[] = "access",
Kauthor[] = "author",
Kbranch[] = "branch",
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
K_branches[]= "branches";
static struct buf Commleader;
struct cbuf Comment;
struct cbuf Ignored;
struct access * AccessList;
struct assoc * Symbols;
struct rcslock *Locks;
int Expand;
int StrictLocks;
struct hshentry * Head;
char const * Dbranch;
int TotalDeltas;
static void
getsemi(key)
char const *key;
/* Get a semicolon to finish off a phrase started by KEY. */
{
if (!getlex(SEMI))
fatserror("missing ';' after '%s'", key);
}
static struct hshentry *
getdnum()
/* Get a delta number. */
{
register struct hshentry *delta = getnum();
if (delta && countnumflds(delta->num)&1)
fatserror("%s isn't a delta number", delta->num);
return delta;
}
void
getadmin()
/* Read an <admin> and initialize the appropriate global variables. */
{
register char const *id;
struct access * newaccess;
struct assoc * newassoc;
struct rcslock *newlock;
struct hshentry * delta;
struct access **LastAccess;
struct assoc **LastSymbol;
struct rcslock **LastLock;
struct buf b;
struct cbuf cb;
TotalDeltas=0;
getkey(Khead);
Head = getdnum();
getsemi(Khead);
Dbranch = 0;
if (getkeyopt(Kbranch)) {
if ((delta = getnum()))
Dbranch = delta->num;
getsemi(Kbranch);
}
#if COMPAT2
/* read suffix. Only in release 2 format */
if (getkeyopt(Ksuffix)) {
if (nexttok==STRING) {
readstring(); nextlex(); /* Throw away the suffix. */
} else if (nexttok==ID) {
nextlex();
}
getsemi(Ksuffix);
}
#endif
getkey(Kaccess);
LastAccess = &AccessList;
while ((id = getid())) {
newaccess = ftalloc(struct access);
newaccess->login = id;
*LastAccess = newaccess;
LastAccess = &newaccess->nextaccess;
}
*LastAccess = 0;
getsemi(Kaccess);
getkey(Ksymbols);
LastSymbol = &Symbols;
while ((id = getid())) {
if (!getlex(COLON))
fatserror("missing ':' in symbolic name definition");
if (!(delta=getnum())) {
fatserror("missing number in symbolic name definition");
} else { /*add new pair to association list*/
newassoc = ftalloc(struct assoc);
newassoc->symbol=id;
newassoc->num = delta->num;
*LastSymbol = newassoc;
LastSymbol = &newassoc->nextassoc;
}
}
*LastSymbol = 0;
getsemi(Ksymbols);
getkey(Klocks);
LastLock = &Locks;
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 rcslock);
newlock->login=id;
newlock->delta=delta;
*LastLock = newlock;
LastLock = &newlock->nextlock;
}
}
*LastLock = 0;
getsemi(Klocks);
if ((StrictLocks = getkeyopt(Kstrict)))
getsemi(Kstrict);
clear_buf(&Comment);
if (getkeyopt(Kcomment)) {
if (nexttok==STRING) {
Comment = savestring(&Commleader);
nextlex();
}
getsemi(Kcomment);
}
Expand = KEYVAL_EXPAND;
if (getkeyopt(Kexpand)) {
if (nexttok==STRING) {
bufautobegin(&b);
cb = savestring(&b);
if ((Expand = strn2expmode(cb.string,cb.size)) < 0)
fatserror("unknown expand mode %.*s",
(int)cb.size, cb.string
);
bufautoend(&b);
nextlex();
}
getsemi(Kexpand);
}
Ignored = getphrases(Kdesc);
}
char const *const expand_names[] = {
/* These must agree with *_EXPAND in rcsbase.h. */
"kv", "kvl", "k", "v", "o", "b",
0
};
int
str2expmode(s)
char const *s;
/* Yield expand mode corresponding to S, or -1 if bad. */
{
return strn2expmode(s, strlen(s));
}
static int
strn2expmode(s, n)
char const *s;
size_t n;
{
char const *const *p;
for (p = expand_names; *p; ++p)
if (memcmp(*p,s,n) == 0 && !(*p)[n])
return p - expand_names;
return -1;
}
void
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.
*/
{
for (;;) {
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;
}
}
}
static int
getdelta()
/* Function: reads a delta block.
* returns false if the current block does not start with a number.
*/
{
register struct hshentry * Delta, * num;
struct branchhead **LastBranch, *NewBranch;
if (!(Delta = getdnum()))
return false;
hshenter = false; /*Don't enter dates into hashtable*/
Delta->date = getkeyval(Kdate, NUM, false);
hshenter=true; /*reset hshenter for revision numbers.*/
Delta->author = getkeyval(Kauthor, ID, false);
Delta->state = getkeyval(Kstate, ID, true);
getkey(K_branches);
LastBranch = &Delta->branches;
while ((num = getdnum())) {
NewBranch = ftalloc(struct branchhead);
NewBranch->hsh = num;
*LastBranch = NewBranch;
LastBranch = &NewBranch->nextbranch;
}
*LastBranch = 0;
getsemi(K_branches);
getkey(Knext);
Delta->next = num = getdnum();
getsemi(Knext);
Delta->lockedby = 0;
Delta->log.string = 0;
Delta->selector = true;
Delta->ig = getphrases(Kdesc);
TotalDeltas++;
return (true);
}
void
gettree()
/* Function: Reads in the delta tree with getdelta(), then
* updates the lockedby fields.
*/
{
struct rcslock const *currlock;
while (getdelta())
continue;
currlock=Locks;
while (currlock) {
currlock->delta->lockedby = currlock->login;
currlock = currlock->nextlock;
}
}
void
getdesc(prdesc)
int prdesc;
/* Function: read in descriptive text
* nexttok is not advanced afterwards.
* If prdesc is set, the text is printed to stdout.
*/
{
getkeystring(Kdesc);
if (prdesc)
printstring(); /*echo string*/
else readstring(); /*skip string*/
}
static char const *
getkeyval(keyword, token, optional)
char const *keyword;
enum tokens token;
int optional;
/* reads a pair of the form
* <keyword> <token> ;
* where token is one of <id> or <num>. optional indicates whether
* <token> is optional. A pointer to
* the actual character string of <id> or <num> is returned.
*/
{
register char const *val = 0;
getkey(keyword);
if (nexttok==token) {
val = NextString;
nextlex();
} else {
if (!optional)
fatserror("missing %s", keyword);
}
getsemi(keyword);
return(val);
}
void
unexpected_EOF()
{
rcsfaterror("unexpected EOF in diff output");
}
void
initdiffcmd(dc)
register struct diffcmd *dc;
/* Initialize *dc suitably for getdiffcmd(). */
{
dc->adprev = 0;
dc->dafter = 0;
}
static void
badDiffOutput(buf)
char const *buf;
{
rcsfaterror("bad diff output line: %s", buf);
}
static void
diffLineNumberTooLarge(buf)
char const *buf;
{
rcsfaterror("diff line number too large: %s", buf);
}
int
getdiffcmd(finfile, delimiter, foutfile, dc)
RILE *finfile;
FILE *foutfile;
int delimiter;
struct diffcmd *dc;
/* Get a editing command output by 'diff -n' from fin.
* The input is delimited by SDELIM if delimiter is set, EOF otherwise.
* Copy a clean version of the command to fout (if nonnull).
* Yield 0 for 'd', 1 for 'a', and -1 for EOF.
* Store the command's line number and length into dc->line1 and dc->nlines.
* Keep dc->adprev and dc->dafter up to date.
*/
{
register int c;
declarecache;
register FILE *fout;
register char *p;
register RILE *fin;
long line1, nlines, t;
char buf[BUFSIZ];
fin = finfile;
fout = foutfile;
setupcache(fin); cache(fin);
cachegeteof_(c, { if (delimiter) unexpected_EOF(); return -1; } )
if (delimiter) {
if (c==SDELIM) {
cacheget_(c)
if (c==SDELIM) {
buf[0] = c;
buf[1] = 0;
badDiffOutput(buf);
}
uncache(fin);
nextc = c;
if (fout)
aprintf(fout, "%c%c", SDELIM, c);
return -1;
}
}
p = buf;
do {
if (buf+BUFSIZ-2 <= p) {
rcsfaterror("diff output command line too long");
}
*p++ = c;
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)) {
if (
LONG_MAX/10 < line1 ||
(t = line1 * 10, (line1 = t + (c - '0')) < t)
)
diffLineNumberTooLarge(buf);
c = *p++;
}
while (c == ' ')
c = *p++;
nlines = 0;
while (isdigit(c)) {
if (
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);
}
if (line1+nlines < line1)
diffLineNumberTooLarge(buf);
switch (buf[0]) {
case 'a':
if (line1 < dc->adprev) {
rcsfaterror("backward insertion in diff output: %s", buf);
}
dc->adprev = line1 + 1;
break;
case 'd':
if (line1 < dc->adprev || line1 < dc->dafter) {
rcsfaterror("backward deletion in diff output: %s", buf);
}
dc->adprev = line1;
dc->dafter = line1 + nlines;
break;
default:
badDiffOutput(buf);
}
if (fout) {
aprintf(fout, "%s\n", buf);
}
dc->line1 = line1;
dc->nlines = nlines;
return buf[0] == 'a';
}
#ifdef SYNTEST
/* Input an RCS file and print its internal data structures. */
char const cmdid[] = "syntest";
int
main(argc,argv)
int argc; char * argv[];
{
if (argc<2) {
aputs("No input file\n",stderr);
exitmain(EXIT_FAILURE);
}
if (!(finptr = Iopen(argv[1], FOPEN_R, (struct stat*)0))) {
faterror("can't open input file %s", argv[1]);
}
Lexinit();
getadmin();
fdlock = STDOUT_FILENO;
putadmin();
gettree();
getdesc(true);
nextlex();
if (!eoflex()) {
fatserror("expecting EOF");
}
exitmain(EXIT_SUCCESS);
}
void exiterr() { _exit(EXIT_FAILURE); }
#endif
-454
View File
@@ -1,454 +0,0 @@
#! /bin/sh
# Test RCS's functions.
# The RCS commands are searched for in the PATH as usual;
# to test the working directory's commands, prepend . to your PATH.
# Test RCS by creating files RCS/a.* and RCS/a.c.
# If all goes well, output nothing, and remove the temporary files.
# Otherwise, send a message to standard output.
# Exit status is 0 if OK, 1 if an RCS bug is found, and 2 if scaffolding fails.
# With the -v option, output more debugging info.
# If diff outputs `No differences encountered' when comparing identical files,
# then rcstest may also output these noise lines; ignore them.
# The current directory and ./RCS must be readable, writable, and searchable.
# $Id: rcstest 3476 2003-06-11 15:56:10Z darkwyrm $
# Copyright 1990, 1991, 1992, 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:
#
# [email protected]
# The Makefile overrides the following defaults.
: ${ALL_CFLAGS=-Dhas_conf_h}
: ${CC=cc}
: ${DIFF=diff}
# : ${LDFLAGS=} ${LIBS=} tickles old shell bug
CL="$CC $ALL_CFLAGS $LDFLAGS -o a.out"
L=$LIBS
RCSINIT=-x
export RCSINIT
SLASH=/
RCSfile=RCS${SLASH}a.c
RCS_alt=RCS${SLASH}a.d
lockfile=RCS${SLASH}a._
case $1 in
-v) q=; set -x;;
'') q=-q;;
*) echo >&2 "$0: usage: $0 [-v]"; exit 2
esac
if test -d RCS
then rmdir=:
else rmdir=rmdir; mkdir RCS || exit
fi
rm -f a.* $RCSfile $RCS_alt $lockfile &&
echo 1.1 >a.11 &&
echo 1.1.1.1 >a.3x1 &&
echo 1.2 >a.12 || { echo "#initialization failed"; exit 2; }
case "`$DIFF -c a.11 a.3x1`" in
*!\ 1.1.1.1)
diff="$DIFF -c";;
*)
echo "#warning: $DIFF -c does not work, so diagnostics may be cryptic"
diff=$DIFF
esac
rcs -i -L -ta.11 $q a.c &&
test -r $RCSfile || {
echo "#rcs -i -L failed; perhaps RCS is not properly installed."
exit 1
}
rlog a.c >/dev/null || { echo "#rlog failed on empty RCS file"; exit 1; }
rm -f $RCSfile || exit 2
cp a.11 a.c &&
ci -ta.11 -mm $q a.c &&
test -r $RCSfile &&
rcs -L $q a.c || { echo "#ci+rcs -L failed"; exit 1; }
test ! -f a.c || { echo "#ci did not remove working file"; exit 1; }
for l in '' '-l'
do
co $l $q a.c &&
test -f a.c || { echo '#co' $l did not create working file; exit 1; }
$diff a.11 a.c || { echo '#ci' followed by co $l is not a no-op; exit 1; }
done
cp a.12 a.c &&
ci -mm $q a.c &&
co $q a.c &&
$diff a.12 a.c || { echo "#ci+co failed"; exit 1; }
rm -f a.c &&
co -r1.1 $q a.c &&
$diff a.11 a.c || { echo "#can't retrieve first revision"; exit 1; }
rm -f a.c &&
cp a.3x1 a.c &&
ci -r1.1.1 -mm $q a.c &&
co -r1.1.1.1 $q a.c &&
$diff a.3x1 a.c || { echo "#branches failed"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
ci -f -mm $q a.c &&
co -r1.3 $q a.c &&
$diff a.12 a.c || { echo "#(co -l; ci -f) failed"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
echo 1.4 >a.c &&
ci -l -mm $q a.c &&
echo error >a.c &&
ci -mm $q a.c || { echo "#ci -l failed"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
echo 1.5 >a.c &&
ci -u -mm $q a.c &&
test -r a.c || { echo "#ci -u didn't create a working file"; exit 1; }
rm -f a.c &&
echo error >a.c || exit 2
ci -mm $q a.c 2>/dev/null && { echo "#ci -u didn't unlock the file"; exit 1; }
rm -f a.c &&
rcs -l $q a.c &&
co -u $q a.c || { echo "#rcs -l + co -u failed"; exit 1; }
rm -f a.c &&
echo error >a.c || exit 2
ci -mm $q a.c 2>/dev/null && { echo "#co -u didn't unlock the file"; exit 1; }
rm -f a.c &&
cp a.11 a.c &&
co -f $q a.c || { echo "#co -f failed"; exit 1; }
$diff a.11 a.c >/dev/null && { echo "#co -f had no effect"; exit 1; }
co -p1.1 $q a.c >a.t &&
$diff a.11 a.t || { echo "#co -p failed"; exit 1; }
for n in n N
do
rm -f a.c &&
co -l $q a.c &&
echo $n >a.$n &&
cp a.$n a.c &&
ci -${n}n -mm $q a.c &&
co -rn $q a.c &&
$diff a.$n a.c || { echo "#ci -$n failed"; exit 1; }
done
case $LOGNAME in
?*) me=$LOGNAME;;
*)
case $USER in
?*) me=$USER;;
*)
me=`who am i` || exit 2
me=`echo "$me" | sed -e 's/ .*//' -e 's/.*!//'`
case $me in
'') echo >&2 "$0: cannot deduce user name"; exit 2
esac
esac
esac
# Get the date of the previous revision in UTC.
date=`rlog -r a.c | sed -n '/^date: /{ s///; s/;.*//; p; q; }'` || exit
case $date in
[0-9][0-9][0-9]*[0-9]/[0-1][0-9]/[0-3][0-9]\ [0-2][0-9]:[0-5][0-9]:[0-6][0-9]);;
*) echo >&2 "$0: $date: bad rlog date output"; exit 1
esac
PWD=`pwd` && export PWD &&
rm -f a.c &&
co -l $q a.c &&
sed 's/@/$/g' >a.kv <<EOF
@Author: w @
@Date: $date @
@Header: $PWD$SLASH$RCSfile 2.1 $date w s @
@Id: a.c 2.1 $date w s @
@Locker: @
* @Log: a.c @
* Revision 2.1 $date w
* m
*
@Name: Oz @
@RCSfile: a.c @
@Revision: 2.1 @
@Source: $PWD$SLASH$RCSfile @
@State: s @
EOF
test $? = 0 &&
sed 's/:.*\$/$/' a.kv >a.k &&
sed -e 's/w s [$]/w s '"$me"' $/' -e 's/[$]Locker: /&'"$me/" a.kv >a.kvl &&
sed s/Oz//g a.kv >a.e &&
sed s/Oz/N/g a.kv >a.N &&
sed -e '/\$/!d' -e 's/\$$/: old $/' a.k >a.o &&
sed -e 's/\$[^ ]*: //' -e 's/ \$//' a.kv >a.v &&
cp a.o a.c &&
ci -d"$date" -nOz -ss -ww -u2.1 -mm $q a.c &&
$diff a.kv a.c || { echo "#keyword expansion failed"; exit 1; }
co -pOz -ko $q a.c >a.oo &&
$diff a.o a.oo || { echo "#co -p -ko failed"; exit 1; }
cp a.kv a.o && cp a.o a.b || exit 2
rcs -oOz $q a.c &&
rcs -l $q a.c &&
ci -k -u $q a.c &&
$diff a.kv a.c || { echo "#ci -k failed"; exit 1; }
sed -n 's/^[^$]*\$/$/p' a.kv >a.i &&
ident a.c >a.i1 &&
sed -e 1d -e 's/^[ ]*//' a.i1 >a.i2 &&
$diff a.i a.i2 || { echo "#ident failed"; exit 1; }
rcs -i $q a.c 2>/dev/null && { echo "#rcs -i permitted existing file"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
echo 2.2 >a.c &&
ci -mm $q a.c &&
echo 1.1.1.2 >a.c &&
rcs -l1.1.1 $q a.c &&
ci -r1.1.1.2 -mm $q a.c &&
rcs -b1.1.1 $q a.c &&
test " `co -p $q a.c`" = ' 1.1.1.2' || { echo "#rcs -b1.1.1 failed"; exit 1; }
rcs -b $q a.c &&
test " `co -p $q a.c`" = ' 2.2' || { echo "#rcs -b failed"; exit 1; }
echo 2.3 >a.c || exit 2
rcs -U $q a.c || { echo "#rcs -U failed"; exit 1; }
ci -mm $q a.c || { echo "#rcs -U didn't unset strict locking"; exit 1; }
rcs -L $q a.c || { echo "#rcs -L failed"; exit 1; }
echo error >a.c || exit 2
ci -mm $q a.c 2>/dev/null && { echo "#ci retest failed"; exit 1; }
rm -f a.c &&
log0=`rlog -h a.c` &&
co -l $q a.c &&
ci -mm $q a.c &&
log1=`rlog -h a.c` &&
test " $log0" = " $log1" || { echo "#unchanged ci didn't revert"; exit 1; }
rm -f a.c &&
rcs -nN:1.1 $q a.c &&
co -rN $q a.c &&
$diff a.11 a.c || { echo "#rcs -n failed"; exit 1; }
rm -f a.c &&
rcs -NN:2.1 $q a.c &&
co -rN $q a.c &&
$diff a.N a.c || { echo "#rcs -N failed"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
echo ':::$''Log$' >a.c &&
ci -u -mm $q a.c &&
test " `sed '$!d' a.c`" = ' :::' || { echo "#comment leader failed"; exit 1; }
rm -f a.c &&
rcs -o2.2: $q a.c &&
co $q a.c &&
$diff a.e a.c || { echo "#rcs -o failed"; exit 1; }
rcsdiff -r1.1 -rOz $q a.c >a.0
case $? in
1) ;;
*) echo "#rcsdiff bad status"; exit 1
esac
$DIFF a.11 a.kv >a.1
$diff a.0 a.1 || { echo "#rcsdiff failed"; exit 1; }
rcs -l2.1 $q a.c || { echo "#rcs -l2.1 failed"; exit 1; }
for i in b k kv kvl o v
do
rm -f a.c &&
cp a.$i a.c &&
rcsdiff -k$i -rOz $q a.c || { echo "#rcsdiff -k$i failed"; exit 1; }
done
co -p1.1 -ko $q a.c >a.t &&
$diff a.11 a.t || { echo "#co -p1.1 -ko failed"; exit 1; }
rcs -u2.1 $q a.c || { echo "#rcs -u2.1 failed"; exit 1; }
rm -f a.c &&
rcsclean $q a.c &&
rcsclean -u $q a.c || { echo "#rcsclean botched a nonexistent file"; exit 1; }
rm -f a.c &&
co $q a.c &&
rcsclean -n $q a.c &&
rcsclean -n -u $q a.c &&
test -f a.c || { echo "#rcsclean -n removed a file"; exit 1; }
rm -f a.c &&
co $q a.c &&
rcsclean $q a.c &&
test ! -f a.c || { echo "#rcsclean missed an unlocked file"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
rcsclean $q a.c &&
test -f a.c || { echo "#rcsclean removed a locked file"; exit 1; }
rcsclean -u $q a.c &&
test ! -f a.c || {
echo "#rcsclean -u missed an unchanged locked file"; exit 1;
}
rm -f a.c &&
co -l $q a.c &&
echo change >>a.c &&
rcsclean $q a.c &&
rcsclean $q -u a.c &&
test -f a.c || { echo "#rcsclean removed a changed file"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
cat >a.c <<'EOF'
2.2
a
b
c
d
EOF
test $? = 0 &&
ci -l -mm $q a.c &&
co -p2.2 $q a.c | sed -e s/2.2/2.3/ -e s/b/b1/ >a.c &&
ci -l -mm $q a.c &&
co -p2.2 $q a.c | sed -e s/2.2/new/ -e s/d/d1/ >a.c || exit 2
cat >a.0 <<'EOF'
2.3
a
b1
c
d1
EOF
cat >a.1 <<'EOF'
<<<<<<< a.c
new
=======
2.3
>>>>>>> 2.3
a
b1
c
d1
EOF
rcsmerge -E -r2.2 -r2.3 $q a.c
case $? in
0)
if $diff a.0 a.c >/dev/null
then echo "#warning: diff3 -E does not work, " \
"so merge and rcsmerge ignore overlaps and suppress overlap lines."
else
$diff a.1 a.c || { echo "#rcsmerge failed (status 0)"; exit 1; }
echo "#warning: The diff3 lib program exit status ignores overlaps," \
"so rcsmerge does not warn about overlap lines that it generates."
fi
;;
1)
$diff a.1 a.c || { echo "#rcsmerge failed (status 1)"; exit 1; }
;;
*)
echo "#rcsmerge bad status"; exit 1
esac
# Avoid `tr' if possible; it's not portable, and it can't handle null bytes.
# Our substitute exclusive-ORs with '\n';
# this ensures null bytes on output, which is even better than `tr',
# since some diffs think a file is binary only if it contains null bytes.
cat >a.c <<'EOF'
#include <stdio.h>
int main() {
int c;
while ((c=getchar()) != EOF)
putchar(c ^ '\n');
return 0;
}
EOF
tr=tr
if (rm -f a.exe a.out && $CL a.c $L >&2) >/dev/null 2>&1
then
if test -s a.out
then tr=./a.out
elif test -s a.exe
then tr=./a.exe
fi
fi
{
co -p $q a.c | $tr '\012' '\200' >a.24 &&
cp a.24 a.c &&
ciOut=`(ci -l -mm $q a.c 2>&1)` &&
case $ciOut in
?*) echo >&2 "$ciOut"
esac &&
co -p $q a.c | $tr '\200' '\012' >a.c &&
rcsdiff -r2.3 $q a.c >/dev/null &&
echo 2.5 >a.c &&
ci -l -mm $q a.c &&
cp a.24 a.c &&
rcsdiff -r2.4 $q a.c >/dev/null
} || echo "#warning: Traditional diff is used, so RCS is limited to text files."
rcs -u -o2.4: $q a.c || { echo "#rcs -u -o failed"; exit 1; }
rcs -i -Aa.c -t- $q a.d || { echo "#rcs -i -A failed"; exit 1; }
rlog -r2.1 a.c >a.t &&
grep '^checked in with -k' a.t >/dev/null &&
sed '/^checked in with -k/d' a.t >a.u &&
$diff - a.u <<EOF
RCS file: $RCSfile
Working file: a.c
head: 2.3
branch:
locks: strict
access list:
symbolic names:
N: 2.1
Oz: 2.1
n: 1.8
keyword substitution: kv
total revisions: 13; selected revisions: 1
description:
1.1
----------------------------
revision 2.1
date: $date; author: w; state: s; lines: +14 -1
=============================================================================
EOF
test $? = 0 || { echo "#rlog failed"; exit 1; }
test ! -f $lockfile || { echo "#lock file not removed"; exit 1; }
rm -f a.* $RCSfile $RCS_alt
$rmdir RCS
-191
View File
@@ -1,191 +0,0 @@
/* Convert between RCS time format and Posix and/or C formats. */
/* Copyright 1992, 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
*/
#include "rcsbase.h"
#include "partime.h"
#include "maketime.h"
libId(rcstimeId, "$Id: rcstime.c 3476 2003-06-11 15:56:10Z darkwyrm $")
static long zone_offset; /* seconds east of UTC, or TM_LOCAL_ZONE */
static int use_zone_offset; /* if zero, use UTC without zone indication */
/*
* Convert Unix time to RCS format.
* For compatibility with older versions of RCS,
* dates from 1900 through 1999 are stored without the leading "19".
*/
void
time2date(unixtime,date)
time_t unixtime;
char date[datesize];
{
register struct tm const *tm = time2tm(unixtime, RCSversion<VERSION(5));
VOID sprintf(date,
# if has_printf_dot
"%.2d.%.2d.%.2d.%.2d.%.2d.%.2d",
# else
"%02d.%02d.%02d.%02d.%02d.%02d",
# endif
tm->tm_year + ((unsigned)tm->tm_year < 100 ? 0 : 1900),
tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec
);
}
/* Like str2time, except die if an error was found. */
static time_t str2time_checked P((char const*,time_t,long));
static time_t
str2time_checked(source, default_time, default_zone)
char const *source;
time_t default_time;
long default_zone;
{
time_t t = str2time(source, default_time, default_zone);
if (t == -1)
faterror("unknown date/time: %s", source);
return t;
}
/*
* Parse a free-format date in SOURCE, convert it
* into RCS internal format, and store the result into TARGET.
*/
void
str2date(source, target)
char const *source;
char target[datesize];
{
time2date(
str2time_checked(source, now(),
use_zone_offset ? zone_offset
: RCSversion<VERSION(5) ? TM_LOCAL_ZONE
: 0
),
target
);
}
/* Convert an RCS internal format date to time_t. */
time_t
date2time(source)
char const source[datesize];
{
char s[datesize + zonelenmax];
return str2time_checked(date2str(source, s), (time_t)0, 0);
}
/* Set the time zone for date2str output. */
void
zone_set(s)
char const *s;
{
if ((use_zone_offset = *s)) {
long zone;
char const *zonetail = parzone(s, &zone);
if (!zonetail || *zonetail)
error("%s: not a known time zone", s);
else
zone_offset = zone;
}
}
/*
* Format a user-readable form of the RCS format DATE into the buffer DATEBUF.
* Yield DATEBUF.
*/
char const *
date2str(date, datebuf)
char const date[datesize];
char datebuf[datesize + zonelenmax];
{
register char const *p = date;
while (*p++ != '.')
continue;
if (!use_zone_offset)
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
);
else {
struct tm t;
struct tm const *z;
int non_hour;
long zone;
char c;
t.tm_year = atoi(date) - (date[2]=='.' ? 0 : 1900);
t.tm_mon = atoi(p) - 1;
t.tm_mday = atoi(p+3);
t.tm_hour = atoi(p+6);
t.tm_min = atoi(p+9);
t.tm_sec = atoi(p+12);
t.tm_wday = -1;
zone = zone_offset;
if (zone == TM_LOCAL_ZONE) {
time_t u = tm2time(&t, 0), d;
z = localtime(&u);
d = difftm(z, &t);
zone = (time_t)-1 < 0 || d < -d ? d : -(long)-d;
} else {
adjzone(&t, zone);
z = &t;
}
c = '+';
if (zone < 0) {
zone = -zone;
c = '-';
}
VOID sprintf(datebuf,
# if has_printf_dot
"%.2d-%.2d-%.2d %.2d:%.2d:%.2d%c%.2d",
# else
"%02d-%02d-%02d %02d:%02d:%02d%c%02d",
# endif
z->tm_year + 1900,
z->tm_mon + 1, z->tm_mday, z->tm_hour, z->tm_min, z->tm_sec,
c, (int) (zone / (60*60))
);
if ((non_hour = zone % (60*60))) {
# if has_printf_dot
static char const fmt[] = ":%.2d";
# else
static char const fmt[] = ":%02d";
# endif
VOID sprintf(datebuf + strlen(datebuf), fmt, non_hour / 60);
if ((non_hour %= 60))
VOID sprintf(datebuf + strlen(datebuf), fmt, non_hour);
}
}
return datebuf;
}
File diff suppressed because it is too large Load Diff
-1279
View File
File diff suppressed because it is too large Load Diff
-2
View File
@@ -1,2 +0,0 @@
#include "rcsbase.h"
char const RCS_version_string[] = "5.7";