Newsgroups: comp.sources.unix From: hammer@cs.purdue.edu (Adam Hammer) Subject: v25i078: rcs-5.6 - Revision Control System, V5.6, Part02/11 Sender: sources-moderator@pa.dec.com Approved: vixie@pa.dec.com Submitted-By: hammer@cs.purdue.edu (Adam Hammer) Posting-Number: Volume 25, Issue 78 Archive-Name: rcs-5.6/part02 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'man/rcs.1' <<'END_OF_FILE' X.de Id X.ds Rv \\$3 X.ds Dt \\$4 X.. X.Id $Id: rcs.1,v 5.6 1991/09/26 23:16:17 eggert Exp $ X.ds r \&\s-1RCS\s0 X.if n .ds - \%-- X.if t .ds - \(em X.TH RCS 1 \*(Dt GNU X.SH NAME rcs \- change RCS file attributes X.SH SYNOPSIS X.B rcs X.RI [ " options " ] " file " .\|.\|. X.SH DESCRIPTION X.B rcs creates new \*r files or changes attributes of existing ones. An \*r file contains multiple revisions of text, an access list, a change log, descriptive text, and some control attributes. XFor X.B rcs to work, the caller's login name must be on the access list, except if the access list is empty, the caller is the owner of the file or the superuser, or the X.B \-i option is present. X.PP Pathnames matching an \*r suffix denote \*r files; all others denote working files. Names are paired as explained in X.BR ci (1). Revision numbers use the syntax described in X.BR ci (1). X.SH OPTIONS X.TP X.B \-i Create and initialize a new \*r file, but do not deposit any revision. If the \*r file has no path prefix, try to place it first into the subdirectory X.BR ./RCS , and then into the current directory. If the \*r file already exists, print an error message. X.TP X.BI \-a "logins" Append the login names appearing in the comma-separated list X.I logins to the access list of the \*r file. X.TP X.BI \-A "oldfile" Append the access list of X.I oldfile to the access list of the \*r file. X.TP X.BR \-e [\f2logins\fP] XErase the login names appearing in the comma-separated list X.I logins from the access list of the \*r file. If X.I logins is omitted, erase the entire access list. X.TP X.BR \-b [\f2rev\fP] Set the default branch to X.IR rev . If X.I rev is omitted, the default branch is reset to the (dynamically) highest branch on the trunk. X.TP X.BI \-c string sets the comment leader to X.IR string . The comment leader is printed before every log message line generated by the keyword X.B $\&Log$ during checkout (see X.BR co (1)). This is useful for programming languages without multi-line comments. An initial X.B ci , or an X.B "rcs\ \-i" without X.BR \-c , guesses the comment leader from the suffix of the working file. X.TP X.BI \-k subst Set the default keyword substitution to X.IR subst . The effect of keyword substitution is described in X.BR co (1). Giving an explicit X.B \-k option to X.BR co , X.BR rcsdiff , and X.B rcsmerge overrides this default. Beware X.BR "rcs\ \-kv", because X.B \-kv is incompatible with X.BR "co\ \-l". Use X.B "rcs\ \-kkv" to restore the normal default keyword substitution. X.TP X.BR \-l [\f2rev\fP] Lock the revision with number X.IR rev . If a branch is given, lock the latest revision on that branch. If X.I rev is omitted, lock the latest revision on the default branch. Locking prevents overlapping changes. A lock is removed with X.B ci or X.B "rcs\ \-u" X(see below). X.TP X.BR \-u [\f2rev\fP] Unlock the revision with number X.IR rev . If a branch is given, unlock the latest revision on that branch. If X.I rev is omitted, remove the latest lock held by the caller. Normally, only the locker of a revision may unlock it. Somebody else unlocking a revision breaks the lock. This causes a mail message to be sent to the original locker. The message contains a commentary solicited from the breaker. The commentary is terminated by end-of-file or by a line containing X.BR \&. "\ by" itself. X.TP X.B \-L Set locking to X.IR strict . Strict locking means that the owner of an \*r file is not exempt from locking for checkin. This option should be used for files that are shared. X.TP X.B \-U Set locking to non-strict. Non-strict locking means that the owner of a file need not lock a revision for checkin. This option should X.I not be used for files that are shared. Whether default locking is strict is determined by your system administrator, but it is normally strict. X.TP X\f3\-m\fP\f2rev\fP\f3:\fP\f2msg\fP Replace revision X.IR rev 's log message with X.IR msg . X.TP X\f3\-n\fP\f2name\fP[\f3:\fP[\f2rev\fP]] Associate the symbolic name X.I name with the branch or revision X.IR rev . Delete the symbolic name if both X.B : and X.I rev are omitted; otherwise, print an error message if X.I name is already associated with another number. If X.I rev is symbolic, it is expanded before association. A X.I rev consisting of a branch number followed by a X.B .\& stands for the current latest revision in the branch. A X.B : with an empty X.I rev stands for the current latest revision on the default branch, normally the trunk. XFor example, X.BI "rcs\ \-n" name ":\ RCS/*" associates X.I name with the current latest revision of all the named \*r files; this contrasts with X.BI "rcs\ \-n" name ":$\ RCS/*" which associates X.I name with the revision numbers extracted from keyword strings in the corresponding working files. X.TP X\f3\-N\fP\f2name\fP[\f3:\fP[\f2rev\fP]] Act like X.BR \-n , except override any previous assignment of X.IR name . X.TP X.BI \-o range deletes (\*(lqoutdates\*(rq) the revisions given by X.IR range . A range consisting of a single revision number means that revision. A range consisting of a branch number means the latest revision on that branch. A range of the form X.IB rev1 : rev2 means revisions X.I rev1 to X.I rev2 on the same branch, X.BI : rev means from the beginning of the branch containing X.I rev up to and including X.IR rev , and X.IB rev : means from revision X.I rev to the end of the branch containing X.IR rev . None of the outdated revisions may have branches or locks. X.TP X.B \-q Run quietly; do not print diagnostics. X.TP X.B \-I Run interactively, even if the standard input is not a terminal. X.TP X.B \-s\f2state\fP\f1[\fP:\f2rev\fP\f1]\fP Set the state attribute of the revision X.I rev to X.I state . If X.I rev is a branch number, assume the latest revision on that branch. If X.I rev is omitted, assume the latest revision on the default branch. Any identifier is acceptable for X.IR state . A useful set of states is X.B Exp X(for experimental), X.B Stab X(for stable), and X.B Rel X(for released). By default, X.BR ci (1) sets the state of a revision to X.BR Exp . X.TP X.BR \-t [\f2file\fP] Write descriptive text from the contents of the named X.I file into the \*r file, deleting the existing text. The X.IR file pathname may not begin with X.BR \- . If X.I file is omitted, obtain the text from standard input, terminated by end-of-file or by a line containing X.BR \&. "\ by" itself. Prompt for the text if interaction is possible; see X.BR \-I . With X.BR \-i , descriptive text is obtained even if X.B \-t is not given. X.TP X.BI \-t\- string Write descriptive text from the X.I string into the \*r file, deleting the existing text. X.TP X.BI \-V n XEmulate \*r version X.IR n . See X.BR co (1) for details. X.TP X.BI \-x "suffixes" Use X.I suffixes to characterize \*r files. See X.BR ci (1) for details. X.SH COMPATIBILITY The X.BI \-b rev option generates an \*r file that cannot be parsed by \*r version 3 or earlier. X.PP The X.BI \-k subst options (except X.BR \-kkv ) generate an \*r file that cannot be parsed by \*r version 4 or earlier. X.PP Use X.BI "rcs \-V" n to make an \*r file acceptable to \*r version X.I n by discarding information that would confuse version X.IR n . X.PP X\*r version 5.5 and earlier does not support the X.B \-x option, and requires a X.B ,v suffix on an \*r pathname. X.SH FILES X.B rcs accesses files much as X.BR ci (1) does, except that it uses the effective user for all accesses, it does not write the working file or its directory, and it does not even read the working file unless a revision number of X.B $ is specified. X.SH ENVIRONMENT X.TP X.B \s-1RCSINIT\s0 options prepended to the argument list, separated by spaces. See X.BR ci (1) for details. X.SH DIAGNOSTICS The \*r pathname and the revisions outdated are written to the diagnostic output. The exit status is zero if and only if all operations were successful. X.SH IDENTIFICATION Author: Walter F. Tichy. X.br Revision Number: \*(Rv; Release Date: \*(Dt. X.br Copyright \(co 1982, 1988, 1989 by Walter F. Tichy. X.br Copyright \(co 1990, 1991 by Paul Eggert. X.SH "SEE ALSO" co(1), ci(1), ident(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1), rcsfile(5) X.br Walter F. Tichy, X\*r\*-A System for Version Control, X.I "Software\*-Practice & Experience" X.BR 15 , X7 (July 1985), 637-654. X.SH BUGS The separator for revision ranges in the X.B \-o option used to be X.B \- instead of X.BR : , but this leads to confusion when symbolic names contain X.BR \- . XFor backwards compatibility X.B "rcs \-o" still supports the old X.B \- separator, but it warns about this obsolete use. X.PP Symbolic names need not refer to existing revisions or branches. XFor example, the X.B \-o option does not remove symbolic names for the outdated revisions; you must use X.B \-n to remove the names. X.br END_OF_FILE if test 8642 -ne `wc -c <'man/rcs.1'`; then echo shar: \"'man/rcs.1'\" unpacked with wrong size! fi # end of 'man/rcs.1' fi if test -f 'man/rcsintro.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'man/rcsintro.1'\" else echo shar: Extracting \"'man/rcsintro.1'\" \(9299 characters\) sed "s/^X//" >'man/rcsintro.1' <<'END_OF_FILE' X.de Id X.ds Rv \\$3 X.ds Dt \\$4 X.. X.Id $Id: rcsintro.1,v 5.1 1991/04/21 12:00:46 eggert Exp $ X.ds r \&\s-1RCS\s0 X.if n .ds - \%-- X.if t .ds - \(em X.am SS X.LP X.. X.TH RCSINTRO 1 \*(Dt GNU X.SH NAME rcsintro \- introduction to RCS commands X.SH DESCRIPTION The Revision Control System (\*r) manages multiple revisions of files. X\*r automates the storing, retrieval, logging, identification, and merging of revisions. \*r is useful for text that is revised frequently, for example programs, documentation, graphics, papers, and form letters. X.PP The basic user interface is extremely simple. The novice only needs to learn two commands: X.BR ci (1) and X.BR co (1). X.BR ci , short for \*(lqcheck in\*(rq, deposits the contents of a file into an archival file called an \*r file. An \*r file contains all revisions of a particular file. X.BR co , short for \*(lqcheck out\*(rq, retrieves revisions from an \*r file. X.SS "Functions of \*r" X.IP \(bu Store and retrieve multiple revisions of text. \*r saves all old revisions in a space efficient way. Changes no longer destroy the original, because the previous revisions remain accessible. Revisions can be retrieved according to ranges of revision numbers, symbolic names, dates, authors, and states. X.IP \(bu Maintain a complete history of changes. X\*r logs all changes automatically. Besides the text of each revision, \*r stores the author, the date and time of check-in, and a log message summarizing the change. The logging makes it easy to find out what happened to a module, without having to compare source listings or having to track down colleagues. X.IP \(bu Resolve access conflicts. When two or more programmers wish to modify the same revision, \*r alerts the programmers and prevents one modification from corrupting the other. X.IP \(bu Maintain a tree of revisions. \*r can maintain separate lines of development for each module. It stores a tree structure that represents the ancestral relationships among revisions. X.IP \(bu Merge revisions and resolve conflicts. Two separate lines of development of a module can be coalesced by merging. If the revisions to be merged affect the same sections of code, \*r alerts the user about the overlapping changes. X.IP \(bu Control releases and configurations. Revisions can be assigned symbolic names and marked as released, stable, experimental, etc. With these facilities, configurations of modules can be described simply and directly. X.IP \(bu Automatically identify each revision with name, revision number, creation time, author, etc. The identification is like a stamp that can be embedded at an appropriate place in the text of a revision. The identification makes it simple to determine which revisions of which modules make up a given configuration. X.IP \(bu Minimize secondary storage. \*r needs little extra space for the revisions (only the differences). If intermediate revisions are deleted, the corresponding deltas are compressed accordingly. X.SS "Getting Started with \*r" Suppose you have a file X.B f.c that you wish to put under control of \*r. If you have not already done so, make an \*r directory with the command X.IP X.B "mkdir RCS" X.LP Then invoke the check-in command X.IP X.B "ci f.c" X.LP This command creates an \*r file in the X.B RCS directory, stores X.B f.c into it as revision 1.1, and deletes X.BR f.c . It also asks you for a description. The description should be a synopsis of the contents of the file. All later check-in commands will ask you for a log entry, which should summarize the changes that you made. X.PP XFiles in the \*r directory are called \*r files; the others are called working files. To get back the working file X.B f.c in the previous example, use the check-out command X.IP X.B "co f.c" X.LP This command extracts the latest revision from the \*r file and writes it into X.BR f.c . If you want to edit X.BR f.c , you must lock it as you check it out with the command X.IP X.B "co \-l f.c" X.LP You can now edit X.BR f.c . X.PP Suppose after some editing you want to know what changes that you have made. The command X.IP X.B "rcsdiff f.c" X.LP tells you the difference between the most recently checked-in version and the working file. You can check the file back in by invoking X.IP X.B "ci f.c" X.LP This increments the revision number properly. X.PP If X.B ci complains with the message X.IP X.BI "ci error: no lock set by " "your name" X.LP then you have tried to check in a file even though you did not lock it when you checked it out. Of course, it is too late now to do the check-out with locking, because another check-out would overwrite your modifications. Instead, invoke X.IP X.B "rcs \-l f.c" X.LP This command will lock the latest revision for you, unless somebody else got ahead of you already. In this case, you'll have to negotiate with that person. X.PP Locking assures that you, and only you, can check in the next update, and avoids nasty problems if several people work on the same file. XEven if a revision is locked, it can still be checked out for reading, compiling, etc. All that locking prevents is a X.I "check-in" by anybody but the locker. X.PP If your \*r file is private, i.e., if you are the only person who is going to deposit revisions into it, strict locking is not needed and you can turn it off. If strict locking is turned off, the owner of the \*r file need not have a lock for check-in; all others still do. Turning strict locking off and on is done with the commands X.IP X.BR "rcs \-U f.c" " and " "rcs \-L f.c" X.LP If you don't want to clutter your working directory with \*r files, create a subdirectory called X.B RCS in your working directory, and move all your \*r files there. \*r commands will look first into that directory to find needed files. All the commands discussed above will still work, without any modification. X(Actually, pairs of \*r and working files can be specified in three ways: X(a) both are given, (b) only the working file is given, (c) only the X\*r file is given. Both \*r and working files may have arbitrary path prefixes; X\*r commands pair them up intelligently.) X.PP To avoid the deletion of the working file during check-in (in case you want to continue editing or compiling), invoke X.IP X.BR "ci \-l f.c" " or " "ci \-u f.c" X.LP These commands check in X.B f.c as usual, but perform an implicit check-out. The first form also locks the checked in revision, the second one doesn't. Thus, these options save you one check-out operation. The first form is useful if you want to continue editing, the second one if you just want to read the file. Both update the identification markers in your working file (see below). X.PP You can give X.B ci the number you want assigned to a checked in revision. Assume all your revisions were numbered 1.1, 1.2, 1.3, etc., and you would like to start release 2. The command X.IP X.BR "ci \-r2 f.c" " or " "ci \-r2.1 f.c" X.LP assigns the number 2.1 to the new revision. XFrom then on, X.B ci will number the subsequent revisions with 2.2, 2.3, etc. The corresponding X.B co commands X.IP X.BR "co \-r2 f.c" " and " "co \-r2.1 f.c" X.PP retrieve the latest revision numbered X.RI 2. x and the revision 2.1, respectively. X.B co without a revision number selects the latest revision on the X.IR trunk , i.e. the highest revision with a number consisting of two fields. Numbers with more than two fields are needed for branches. XFor example, to start a branch at revision 1.3, invoke X.IP X.B "ci \-r1.3.1 f.c" X.LP This command starts a branch numbered 1 at revision 1.3, and assigns the number 1.3.1.1 to the new revision. For more information about branches, see X.BR rcsfile (5). X.SS "Automatic Identification" X\*r can put special strings for identification into your source and object code. To obtain such identification, place the marker X.IP X.B "$\&Id$" X.LP into your text, for instance inside a comment. X\*r will replace this marker with a string of the form X.IP X.BI $\&Id: " filename revision date time author state " $ X.LP With such a marker on the first page of each module, you can always see with which revision you are working. X\*r keeps the markers up to date automatically. To propagate the markers into your object code, simply put them into literal character strings. In C, this is done as follows: X.IP X.ft 3 static char rcsid[] = \&"$\&Id$\&"; X.ft X.LP The command X.B ident extracts such markers from any file, even object code and dumps. Thus, X.B ident lets you find out which revisions of which modules were used in a given program. X.PP You may also find it useful to put the marker X.B $\&Log$ into your text, inside a comment. This marker accumulates the log messages that are requested during check-in. Thus, you can maintain the complete history of your file directly inside it. There are several additional identification markers; see X.BR co (1) for details. X.SH IDENTIFICATION Author: Walter F. Tichy. X.br Revision Number: \*(Rv; Release Date: \*(Dt. X.br Copyright \(co 1982, 1988, 1989 by Walter F. Tichy. X.br Copyright \(co 1990, 1991 by Paul Eggert. X.SH "SEE ALSO" ci(1), co(1), ident(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1) X.br Walter F. Tichy, X\*r\*-A System for Version Control, X.I "Software\*-Practice & Experience" X.BR 15 , X7 (July 1985), 637-654. X.br END_OF_FILE if test 9299 -ne `wc -c <'man/rcsintro.1'`; then echo shar: \"'man/rcsintro.1'\" unpacked with wrong size! fi # end of 'man/rcsintro.1' fi if test -f 'src/README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/README'\" else echo shar: Extracting \"'src/README'\" \(9190 characters\) sed "s/^X//" >'src/README' <<'END_OF_FILE' RCS configuration instructions X X $Id: README,v 1.5 1991/10/07 17:32:46 eggert Exp $ X X Copyright 1991 by Paul Eggert X Distributed under license by the Free Software Foundation, Inc. X X This file is part of RCS. X X RCS is free software; you can redistribute it and/or modify it X under the terms of the GNU General Public License as published X by the Free Software Foundation; either version 2, or (at your X option) any later version. X X RCS is distributed in the hope that it will be useful, but X WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public X License along with RCS; see the file COPYING. If not, write to X the Free Software Foundation, 675 Mass Ave, Cambridge, MA X 02139, USA. X X Report problems and direct all questions to: X X rcs-bugs@cs.purdue.edu X X XFor Posix and near-Posix hosts, configure by editing Makefile, commenting out wrong lines and uncommenting right ones. See ``Makefile notes'' below for advice. X After configuring, make conf.h; if this fails, look in src/conf.error to see what went wrong in the conf.sh shell file. Check the resulting conf.h for plausibility; see ``conf.h notes'' below. If conf.h is wrong, and the mistake isn't listed in ``conf.h notes'', there is a bug in conf.sh; please report it. You can patch conf.h if you're in a hurry, but it's better to fix it; look at a.h and conf.error for ideas. If all else fails, copy conf.heg to conf.h and edit it by hand. After configuring, make `all'. X If all went well, make `install'. If installation succeeds, make `installtest'; if this fails, make `installdebug' for detailed info. X If you want to test RCS before installing it, you must set RCSPREFIX to be empty, make RCS from scratch, prefix the src directory to your PATH, and run `sh src/rcstest'. Be sure to restore RCSPREFIX and rebuild RCS before installing it. X If you want to maintain RCS with itself, preserve the original revision numbers, dates, etc. by checking the files in with the -k option. X X X__________ X Makefile notes X CC is the name of your C compiler. X CC_D is a list of extra options for the C preprocessor. It should include any extra -D and -I options needed on your system. X CC_O is the C compiler options that affect just compilation and assembly; not preprocessing, linking or linting. If your compiler has the BSD -R option, -R can improve performance by making all initialized data read-only (not just string literals); this is not worth worrying about if your compiler also supports `const'. X CC_W is the list of C compiler options to enable warnings about questionable constructs in the RCS source code. X COMPAT2 is 1 if you still have version 2 RCS files around. X(Version 2 became obsolete in 1982, so this isn't likely.) COMPAT2 assures that version 2 RCS files can still be read. When you have the new RCS installed, rename old version 2 RCS files as follows. Suppose the working file was `f.c'; rename the RCS file `f.c.v' to `f.c,v', and the RCS file `f.v' to `f.c,v'. Thus suffixes are no longer dropped and RCS files end in `,v' rather than `.v'. After all version 2 RCS files have been updated with new versions of ci or rcs, you can remake RCS with COMPAT2 set to 0. X DIFF is the name of your diff program. If you override DIFF, make sure you rebuild conf.h afterwards; otherwise you may introduce a security hole. On some versions of Unix, the standard diff does not support RCS and you must use something like /usr/lib/rdiff instead; perhaps you should try GNU diff instead. X DIFFPREFIX act likes RCSPREFIX, except it applies to subsidiary diffs, not to subsidiary RCS commands. It must be nonempty if setuid is to be used. X DIFF_FLAGS are diff's options for RCS format output, probably -n. If available, also include the -a option for comparing arbitrary files. X DIFF_L is 1 if diff understands the -L option for labeling context diff output. X DIFF_SUCCESS, DIFF_FAILURE, DIFF_TROUBLE are integer constants representing diff's exit status when it finds no differences, some differences, or trouble respectively. The first two should be EXIT_SUCCESS and EXIT_FAILURE, but on some hosts they are broken. X DIFF3 is the name of the diff3 program. With GNU diff, this is simply its user-visible diff3 program. With traditional diff3, this is not the user-visible diff3 program; instead, it this is the name of the undocumented diff3 auxiliary program, whose name is /usr/lib/diff3 or /usr/5lib/rdiff3prog or something similar. X DIFF3_BIN is 1 if DIFF3 is the user-visible GNU diff3 program (see DIFF3). Before setting this to 1, make sure your diff3 understands -a, -L, and and -m; e.g. the command `echo x | diff3 -m /dev/null /dev/null -' should output `x'. X XED is the name of the standard Unix line editor. It is needed only if DIFF3_BIN is 0. X XEXECUTABLE_PERMISSIONS are the options given to INSTALL for executable files on BSD Unix sites. Watch out for `-g staff' if you don't have a staff group, or if your installation program doesn't have a -g option. X INSTALL is the command that installs commands. X LDFLAGS are the loader flags you need, e.g. -i, -n, -s, -x. X LDLIBS are the loader libraries you need, e.g. -lbsd, -lBSD, -ljobs, -lPW, -lx. X LINK is the command used to link together an executable. X LINT is the name and usual arguments of your lint program. X OTHER_OBJECT are any other object files you need to link. X RCSCOMMANDS is the list of commands to be installed by default. It doesn't include rcsclean$x, which is still a little experimental. X RCSDIR is where the RCS commands will be installed. X RCSPREFIX is the prefix for subsidiary RCS commands like ci. If empty, RCS will search the PATH for these commands; this lets you move RCS commands after building them, and permits multiple instances of setuid RCS commands on the same host for different users. If nonempty, it should be a path followed by /; this makes RCS look in just one place, and makes execution faster. X REMOVE is how to remove a file. X SENDMAIL is a comma-separated list of strings that are a command to send mail. The name of the addressee will be appended as a separate argument, and the standard input will be the message X(first line `Subject: xxxx', second line empty). If your host cannot send mail, leave SENDMAIL empty. X TESTPREFIX is the prefix for test commands. X o is the file name extension your host uses for object files. It includes the `.'. It is typically `.o' on Unix hosts. X x is the file name extension your host uses for executables. It includes the `.'. It is empty on Unix hosts, which traditionally lack extensions on executables. X X X__________ X conf.h notes X See conf.sh for details about the definitions in conf.h. Comments below cover unusual situations that can require hand patches to conf.h. X has_NFS - Set this if the target host might use NFS. NFS's stateless server model has well-known problems with the non-idempotent operations link(), rename(), and unlink(). XFor example, unlink() can run twice on the file server, causing the client to think that the unlink failed with errno==ENOENT. has_NFS enables code that works around these problems. X const - Some hosts support `const' but complain about it, perhaps because system headers are wrong. `#define const /*empty*/' pacifies them. X has_rename - This should be 0 in SCO Unix V.3.2. Its NFS rename() is broken, but if you run conf.sh in a non-NFS filesystem, conf.sh thinks rename() works. X has_seteuid - This should be 1 only if your seteuid lets you switch back and forth between any pair of users as specified in Posix 1003.1a Draft 5. One must be root to test this reliably, so conf.sh just guesses. X large_memory - This should be 1 if main memory is large enough to hold entire copies of RCS files, perhaps because virtual memory is available. X NAME_MAX - this should be #undef'ed in AT&T SVR4.0 V2.0, which defines NAME_MAX to be 14 even though longer names are permitted on some filesystems. If you run conf.sh in a short-name filesystem, conf.sh won't detect this bug. X X_POSIX_SOURCE must be #defined in a strict Standard C environment, because otherwise stdio.h cannot define useful names like fileno. Avoid defining _POSIX_SOURCE if possible, because it can disable useful non-Posix features in your host. Perhaps you can remove the need for _POSIX_SOURCE by supplying an option to your compiler to makes it less strict. X text_work_stdio - This option makes sense only on non-Posix hosts that distinguish between text and binary I/O, e.g. DOS. Set this option if you want to use text I/O for working files, but binary I/O for RCS files. If set, RCS does not support non-text working files, but RCS files are portable to other hosts across binary network file systems like NFS. If not set, RCS supports non-text working files, but RCS files are not portable to Posix hosts. X TZ_must_be_set - set this to 1 on hosts where gmtime() yields bogus values unless the TZ environment variable is set. X volatile - See `const'. E.g. `volatile sig_atomic_t' is conforming, but some buggy hosts complain. Also, Ultrix 4.0 Mips CC 2.0 has buggy volatile support. END_OF_FILE if test 9190 -ne `wc -c <'src/README'`; then echo shar: \"'src/README'\" unpacked with wrong size! fi # end of 'src/README' fi if test -f 'src/maketime.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/maketime.c'\" else echo shar: Extracting \"'src/maketime.c'\" \(9481 characters\) sed "s/^X//" >'src/maketime.c' <<'END_OF_FILE' X# X/* X * MAKETIME derive 32-bit time value from TM structure. X * X * Usage: X * int zone; Minutes west of GMT, or X * 48*60 for localtime X * time_t t; X * struct tm *tp; Pointer to TM structure from X * t = maketime(tp,zone); X * X * Returns: X * -1 if failure; parameter out of range or nonsensical. X * else time-value. X * Notes: X * This code is quasi-public; it may be used freely in like software. X * It is not to be sold, nor used in licensed software without X * permission of the author. X * For everyone's benefit, please report bugs and improvements! X * Copyright 1981 by Ken Harrenstien, SRI International. X * (ARPANET: KLH @ SRI) X */ X/* $Log: maketime.c,v $ X * Revision 5.3 1991/08/19 03:13:55 eggert X * Add setfiledate, str2time, TZ_must_be_set. X * X * Revision 5.2 1990/11/01 05:03:30 eggert X * Remove lint. X * X * Revision 5.1 1990/10/04 06:30:13 eggert X * Calculate the GMT offset of 'xxx LT' as of xxx, not as of now. X * Don't assume time_t is 32 bits. Fix bugs near epoch and near end of time. X * X * Revision 5.0 1990/08/22 08:12:38 eggert X * Switch to GMT and fix the bugs exposed thereby. X * Permit dates past 1999/12/31. Ansify and Posixate. X * X * Revision 1.8 88/11/08 13:54:53 narten X * allow negative timezones (-24h <= x <= 24h) X * X * Revision 1.7 88/08/28 14:47:52 eggert X * Allow cc -R. Remove unportable "#endif XXX"s. X * X * Revision 1.6 87/12/18 17:05:58 narten X * include rcsparam.h X * X * Revision 1.5 87/12/18 11:35:51 narten X * maketime.c: fixed USG code - you have tgo call "tzset" in order to have X * "timezone" set. ("localtime" calls it, but it's probably better not to X * count on "localtime" having been called.) X * X * Revision 1.4 87/10/18 10:26:57 narten X * Updating version numbers. Changes relative to 1.0 are actually X * relative to 1.2 X * X * Revision 1.3 87/09/24 13:58:45 narten X * Sources now pass through lint (if you ignore printf/sprintf/fprintf X * warnings) X * X * Revision 1.2 87/03/27 14:21:48 jenkins X * Port to suns X * X * Revision 1.2 83/12/05 10:12:56 wft X * added cond. compilation for USG Unix; long timezone; X * X * Revision 1.1 82/05/06 11:38:00 wft X * Initial revision X * X */ X X X#include "rcsbase.h" X libId(maketId, "$Id: maketime.c,v 5.3 1991/08/19 03:13:55 eggert Exp $") X static struct tm const *time2tm P((time_t)); X X#define given(v) (0 <= (v)) /* Negative values are unspecified. */ X static int const daytb[] = { X /* # days in year thus far, indexed by month (0-12!!) */ X 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 X}; X X static time_t maketime(atm,zone) X struct tm const *atm; X int zone; X{ X register struct tm const *tp; X register int i; X int year, yday, mon, day, hour, min, sec, leap, localzone; X int attempts; X time_t t, tres; X X attempts = 2; X localzone = zone==48*60; X tres = -1; X year = mon = day = 0; /* Keep lint happy. */ X X do { X X if (localzone || !given(atm->tm_year)) { X if (tres == -1) X if ((tres = time((time_t*)0)) == -1) X return -1; X tp = time2tm(tres); X /* Get breakdowns of default time, adjusting to zone. */ X year = tp->tm_year; /* Use to set up defaults */ X yday = tp->tm_yday; X mon = tp->tm_mon; X day = tp->tm_mday; X hour = tp->tm_hour; X min = tp->tm_min; X if (localzone) { X tp = localtime(&tres); X zone = X min - tp->tm_min + 60*( X hour - tp->tm_hour + 24*( X /* If years differ, it's by one day. */ X year - tp->tm_year X ? year - tp->tm_year X : yday - tp->tm_yday)); X } X /* Adjust the default day, month and year according to zone. */ X if ((min -= zone) < 0) { X if (hour-(59-min)/60 < 0 && --day <= 0) { X if (--mon < 0) { X --year; X mon = 11; X } X day = daytb[mon+1] - daytb[mon] + (mon==1&&!(year&3)); X } X } else X if ( X 24 <= hour+min/60 && X daytb[mon+1] - daytb[mon] + (mon==1&&!(year&3)) < ++day X ) { X if (11 < ++mon) { X ++year; X mon = 0; X } X day = 1; X } X } X if (zone < -24*60 || 24*60 < zone) X return -1; X X X#ifdef DEBUG printf("first YMD: %d %d %d\n",year,mon,day); X#endif X tp = atm; X X /* First must find date, using specified year, month, day. X * If one of these is unspecified, it defaults either to the X * current date (if no more global spec was given) or to the X * zero-value for that spec (i.e. a more global spec was seen). X * Reject times that do not fit in time_t, X * without assuming that time_t is 32 bits or is signed. X */ X if (given(tp->tm_year)) X { X year = tp->tm_year; X mon = 0; /* Since year was given, default */ X day = 1; /* for remaining specs is zero */ X } X if (year < 69) /* 1969/12/31 OK in some timezones. */ X return -1; /* ERR: year out of range */ X leap = !(year&3) && (year%100 || !((year+300)%400)); X year -= 70; /* UNIX time starts at 1970 */ X X /* X * Find day of year. X */ X { X if (given(tp->tm_mon)) X { mon = tp->tm_mon; /* Month was specified */ X day = 1; /* so set remaining default */ X } X if (11 < (unsigned)mon) X return -1; /* ERR: bad month */ X if (given(tp->tm_mday)) day = tp->tm_mday; X if(day < 1 X || (((daytb[mon+1]-daytb[mon]) < day) X && (day!=29 || mon!=1 || !leap) )) X return -1; /* ERR: bad day */ X yday = daytb[mon] /* Add # of days in months so far */ X + ((leap /* Leap year, and past Feb? If */ X && mon>1)? 1:0) /* so, add leap day for this year */ X + day-1; /* And finally add # days this mon */ X X } X if (leap+365 <= (unsigned)yday) X return -1; /* ERR: bad YDAY */ X X if (year < 0) { X if (yday != 364) X return -1; /* ERR: too early */ X t = -1; X } else { X tres = year*365; /* Get # days of years so far */ X if (tres/365 != year) X return -1; /* ERR: overflow */ X t = tres X + ((year+1)>>2) /* plus # of leap days since 1970 */ X + yday; /* and finally add # days this year */ X if (t+4 < tres) X return -1; /* ERR: overflow */ X } X tres = t; X X if (given(i = tp->tm_wday)) /* Check WDAY if present */ X if (i != (tres+4)%7) /* 1970/01/01 was Thu = 4 */ X return -1; /* ERR: bad WDAY */ X X#ifdef DEBUG printf("YMD: %d %d %d, T=%ld\n",year,mon,day,tres); X#endif X /* X * Now determine time. If not given, default to zeros X * (since time is always the least global spec) X */ X tres *= 86400L; /* Get # seconds (24*60*60) */ X if (tres/86400L != t) X return -1; /* ERR: overflow */ X hour = min = sec = 0; X if (given(tp->tm_hour)) hour = tp->tm_hour; X if (given(tp->tm_min )) min = tp->tm_min; X if (given(tp->tm_sec )) sec = tp->tm_sec; X if (60 <= (unsigned)min || 60 < (unsigned)sec) X return -1; /* ERR: MS out of range */ X if (24 <= (unsigned)hour) X if(hour != 24 || (min+sec) !=0) /* Allow 24:00 */ X return -1; /* ERR: H out of range */ X X t = tres; X tres += sec + 60L*(zone + min + 60*hour); X X#ifdef DEBUG printf("HMS: %d %d %d T=%ld\n",hour,min,sec,tres); X#endif X X if (!localzone) /* check for overflow */ X return (year<0 ? (tres<0||86400L<=tres) : trestm_sec) && atm->tm_sec != tp->tm_sec) X return -1; /* If seconds don't match, we're in trouble. */ X if (!( X given(atm->tm_min) && atm->tm_min != tp->tm_min || X given(atm->tm_hour) && atm->tm_hour != tp->tm_hour || X given(atm->tm_mday) && atm->tm_mday != tp->tm_mday || X given(atm->tm_mon) && atm->tm_mon != tp->tm_mon || X given(atm->tm_year) && atm->tm_year != tp->tm_year X )) X return tres; /* Everything matches. */ X X } while (--attempts); X X return -1; X} X X/* X* Convert Unix time to struct tm format. X* Use Coordinated Universal Time (UTC) if version 5 or newer; X* use local time otherwise. X*/ X static struct tm const * time2tm(unixtime) X time_t unixtime; X{ X struct tm const *tm; X# if TZ_must_be_set X static char const *TZ; X if (!TZ && !(TZ = getenv("TZ"))) X faterror("TZ is not set"); X# endif X if (!(tm = (RCSversiontm_year + (tm->tm_year<100 ? 0 : 1900), X tm->tm_mon+1, tm->tm_mday, X tm->tm_hour, tm->tm_min, tm->tm_sec X ); X} X X X X static time_t str2time(source) X char const *source; X/* Parse a free-format date in SOURCE, yielding a Unix format time. */ X{ X int zone; X time_t unixtime; X struct tm parseddate; X X if (!partime(source, &parseddate, &zone)) X faterror("can't parse date/time: %s", source); X if ((unixtime = maketime(&parseddate, zone)) == -1) X faterror("bad date/time: %s", source); X return unixtime; X} X X void str2date(source, target) X char const *source; X char target[datesize]; X/* Parse a free-format date in SOURCE, convert it X * into RCS internal format, and store the result into TARGET. X */ X{ X time2date(str2time(source), target); X} X X int setfiledate(file, date) X char const *file, date[datesize]; X/* Set the access and modification time of FILE to DATE. */ X{ X static struct utimbuf times; /* static so unused fields are zero */ X char datebuf[datesize]; X X if (!date) X return 0; X times.actime = times.modtime = str2time(date2str(date, datebuf)); X return utime(file, ×); X} END_OF_FILE if test 9481 -ne `wc -c <'src/maketime.c'`; then echo shar: \"'src/maketime.c'\" unpacked with wrong size! fi # end of 'src/maketime.c' fi if test -f 'src/rcsdiff.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/rcsdiff.c'\" else echo shar: Extracting \"'src/rcsdiff.c'\" \(11285 characters\) sed "s/^X//" >'src/rcsdiff.c' <<'END_OF_FILE' X/* X * RCS rcsdiff operation X */ X/***************************************************************************** X * generate difference between RCS revisions X ***************************************************************************** X */ X X/* Copyright (C) 1982, 1988, 1989 Walter Tichy X Copyright 1990, 1991 by Paul Eggert X Distributed under license by the Free Software Foundation, Inc. X This file is part of RCS. X 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. X 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. X You should have received a copy of the GNU General Public License along with RCS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. X Report problems and direct all questions to: X X rcs-bugs@cs.purdue.edu X X*/ X X X X X/* $Log: rcsdiff.c,v $ X * Revision 5.10 1991/10/07 17:32:46 eggert X * Remove lint. X * X * Revision 5.9 1991/08/19 03:13:55 eggert X * Add RCSINIT, -r$. Tune. X * X * Revision 5.8 1991/04/21 11:58:21 eggert X * Add -x, RCSINIT, MS-DOS support. X * X * Revision 5.7 1990/12/13 06:54:07 eggert X * GNU diff 1.15 has -u. X * X * Revision 5.6 1990/11/01 05:03:39 eggert X * Remove unneeded setid check. X * X * Revision 5.5 1990/10/04 06:30:19 eggert X * Accumulate exit status across files. X * X * Revision 5.4 1990/09/27 01:31:43 eggert X * Yield 1, not EXIT_FAILURE, when diffs are found. X * X * Revision 5.3 1990/09/11 02:41:11 eggert X * Simplify -kkvl test. X * X * Revision 5.2 1990/09/04 17:07:19 eggert X * Diff's argv was too small by 1. X * X * Revision 5.1 1990/08/29 07:13:55 eggert X * Add -kkvl. X * X * Revision 5.0 1990/08/22 08:12:46 eggert X * Add -k, -V. Don't use access(). Add setuid support. X * Remove compile-time limits; use malloc instead. X * Don't pass arguments with leading '+' to diff; GNU DIFF treats them as options. X * Add GNU diff's flags. Make lock and temp files faster and safer. X * Ansify and Posixate. X * X * Revision 4.6 89/05/01 15:12:27 narten X * changed copyright header to reflect current distribution rules X * X * Revision 4.5 88/08/09 19:12:41 eggert X * Use execv(), not system(); yield exit status like diff(1)s; allow cc -R. X * X * Revision 4.4 87/12/18 11:37:46 narten X * changes Jay Lepreau made in the 4.3 BSD version, to add support for X * "-i", "-w", and "-t" flags and to permit flags to be bundled together, X * merged in. X * X * Revision 4.3 87/10/18 10:31:42 narten X * Updating version numbers. Changes relative to 1.1 actually X * relative to 4.1 X * X * Revision 1.3 87/09/24 13:59:21 narten X * Sources now pass through lint (if you ignore printf/sprintf/fprintf X * warnings) X * X * Revision 1.2 87/03/27 14:22:15 jenkins X * Port to suns X * X * Revision 4.1 83/05/03 22:13:19 wft X * Added default branch, option -q, exit status like diff. X * Added fterror() to replace faterror(). X * X * Revision 3.6 83/01/15 17:52:40 wft X * Expanded mainprogram to handle multiple RCS files. X * X * Revision 3.5 83/01/06 09:33:45 wft X * Fixed passing of -c (context) option to diff. X * X * Revision 3.4 82/12/24 15:28:38 wft X * Added call to catchsig(). X * X * Revision 3.3 82/12/10 16:08:17 wft X * Corrected checking of return code from diff; improved error msgs. X * X * Revision 3.2 82/12/04 13:20:09 wft X * replaced getdelta() with gettree(). Changed diagnostics. X * X * Revision 3.1 82/11/28 19:25:04 wft X * Initial revision. X * X */ X#include "rcsbase.h" X X#if DIFF_L static char const *setup_label P((struct buf*,char const*,char const[datesize])); X#endif static void cleanup P((void)); X static int exitstatus; static RILE *workptr; static struct stat workstat; X mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 5.10 1991/10/07 17:32:46 eggert Exp $") X{ X static char const cmdusage[] = X "\nrcsdiff usage: rcsdiff [-q] [-rrev1 [-rrev2]] [-Vn] [diff options] file ..."; X X int revnums; /* counter for revision numbers given */ X char const *rev1, *rev2; /* revision numbers from command line */ X char const *xrev1, *xrev2; /* expanded revision numbers */ X char const *expandarg, *lexpandarg, *versionarg; X#if DIFF_L X static struct buf labelbuf[2]; X int file_labels; X char const **diff_label1, **diff_label2; X char date2[datesize]; X#endif X char const *cov[9]; X char const **diffv, **diffp; /* argv for subsidiary diff */ X char const **pp, *p, *diffvstr; X struct buf commarg; X struct buf numericrev; /* expanded revision number */ X struct hshentries *gendeltas; /* deltas to be generated */ X struct hshentry * target; X char *a, *dcp, **newargv; X register c; X X exitstatus = DIFF_SUCCESS; X X bufautobegin(&commarg); X bufautobegin(&numericrev); X revnums = 0; X rev1 = rev2 = xrev2 = nil; X#if DIFF_L X file_labels = 0; X#endif X expandarg = versionarg = 0; X suffixes = X_DEFAULT; X X /* Room for args + 2 i/o [+ 2 labels] + 1 file + 1 trailing null. */ X diffp = diffv = tnalloc(char const*, argc + 4 + 2*DIFF_L); X *diffp++ = nil; X *diffp++ = nil; X *diffp++ = DIFF; X X argc = getRCSINIT(argc, argv, &newargv); X argv = newargv; X while (a = *++argv, 0<--argc && *a++=='-') { X dcp = a; X while (c = *a++) switch (c) { X case 'r': X switch (++revnums) { X case 1: rev1=a; break; X case 2: rev2=a; break; X default: faterror("too many revision numbers"); X } X goto option_handled; X#if DIFF_L X case 'L': X if (++file_labels == 2) X faterror("too many -L options"); X /* fall into */ X#endif X case 'C': case 'D': case 'F': case 'I': X *dcp++ = c; X if (*a) X do *dcp++ = *a++; X while (*a); X else { X if (!--argc) X faterror("-%c needs following argument%s", X c, cmdusage X ); X *diffp++ = *argv++; X } X break; X case 'B': case 'H': case 'T': X case '0': case '1': case '2': case '3': case '4': X case '5': case '6': case '7': case '8': case '9': X case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': X case 'h': case 'i': case 'n': case 'p': X case 't': case 'u': case 'w': X *dcp++ = c; X break; X case 'q': X quietflag=true; X break; X case 'x': X suffixes = *argv + 2; X goto option_handled; X case 'V': X versionarg = *argv; X setRCSversion(versionarg); X goto option_handled; X case 'k': X expandarg = *argv; X if (0 <= str2expmode(expandarg+2)) X goto option_handled; X /* fall into */ X default: X faterror("unknown option: %s%s", *argv, cmdusage); X }; X option_handled: X if (dcp != *argv+1) { X *dcp = 0; X *diffp++ = *argv; X } X } /* end of option processing */ X X if (argc<1) faterror("no input file%s", cmdusage); X X for (pp = diffv+3, c = 0; ppnum; X X if (!fexpandsym(rev1, &numericrev, workptr)) continue; X if (!(target=genrevs(numericrev.string,(char *)nil,(char *)nil,(char *)nil,&gendeltas))) continue; X xrev1=target->num; X#if DIFF_L X if (diff_label1) X *diff_label1 = setup_label(&labelbuf[0], target->num, target->date); X#endif X X lexpandarg = expandarg; X if (revnums==2) { X if (!fexpandsym( X *rev2 ? rev2 : Dbranch ? Dbranch : Head->num, X &numericrev, X workptr X )) X continue; X if (!(target=genrevs(numericrev.string,(char *)nil,(char *)nil,(char *)nil,&gendeltas))) continue; X xrev2=target->num; X } else if ( X target->lockedby X && !lexpandarg X && Expand == KEYVAL_EXPAND X && WORKMODE(RCSstat.st_mode,true) == workstat.st_mode X ) X lexpandarg = "-kkvl"; X Izclose(&workptr); X#if DIFF_L X if (diff_label2) X if (revnums == 2) X *diff_label2 = setup_label(&labelbuf[1], target->num, target->date); X else { X time2date(workstat.st_mtime, date2); X *diff_label2 = setup_label(&labelbuf[1], workfilename, date2); X } X#endif X X diagnose("retrieving revision %s\n", xrev1); X bufscpy(&commarg, "-p"); X bufscat(&commarg, xrev1); X X cov[1] = diffp[0] = maketemp(0); X pp = &cov[4]; X *pp++ = commarg.string; X if (lexpandarg) X *pp++ = lexpandarg; X if (versionarg) X *pp++ = versionarg; X *pp++ = RCSfilename; X *pp = 0; X X if (runv(cov)) { X error("co failed"); X continue; X } X if (!rev2) { X diffp[1] = workfilename; X if (workfilename[0] == '+') { X /* Some diffs have options with leading '+'. */ X char *dp = ftnalloc(char, strlen(workfilename)+3); X diffp[1] = dp; X *dp++ = '.'; X *dp++ = SLASH; X VOID strcpy(dp, workfilename); X } X } else { X diagnose("retrieving revision %s\n",xrev2); X bufscpy(&commarg, "-p"); X bufscat(&commarg, xrev2); X cov[1] = diffp[1] = maketemp(1); X cov[4] = commarg.string; X if (runv(cov)) { X error("co failed"); X continue; X } X } X if (!rev2) X diagnose("diff%s -r%s %s\n", diffvstr, xrev1, workfilename); X else X diagnose("diff%s -r%s -r%s\n", diffvstr, xrev1, xrev2); X X switch (runv(diffv)) { X case DIFF_SUCCESS: X break; X case DIFF_FAILURE: X if (exitstatus == DIFF_SUCCESS) X exitstatus = DIFF_FAILURE; X break; X default: X error("diff failed"); X } X } while (cleanup(), X ++argv, --argc >=1); X X X tempunlink(); X exitmain(exitstatus); X} X X static void cleanup() X{ X if (nerror) exitstatus = DIFF_TROUBLE; X Izclose(&finptr); X Izclose(&workptr); X} X X#if lint X# define exiterr rdiffExit X#endif X exiting void exiterr() X{ X tempunlink(); X _exit(DIFF_TROUBLE); X} X X#if DIFF_L X static char const * setup_label(b, name, date) X struct buf *b; X char const *name; X char const date[datesize]; X{ X char *p; X size_t l = strlen(name) + 3; X bufalloc(b, l+datesize); X p = b->string; X VOID sprintf(p, "-L%s\t", name); X VOID date2str(date, p+l); X return p; X} X#endif END_OF_FILE if test 11285 -ne `wc -c <'src/rcsdiff.c'`; then echo shar: \"'src/rcsdiff.c'\" unpacked with wrong size! fi # end of 'src/rcsdiff.c' fi if test -f 'src/rcsfcmp.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/rcsfcmp.c'\" else echo shar: Extracting \"'src/rcsfcmp.c'\" \(8406 characters\) sed "s/^X//" >'src/rcsfcmp.c' <<'END_OF_FILE' X/* X * RCS file comparison X */ X/***************************************************************************** X * rcsfcmp() X * Testprogram: define FCMPTEST X ***************************************************************************** X */ X X/* Copyright (C) 1982, 1988, 1989 Walter Tichy X Copyright 1990, 1991 by Paul Eggert X Distributed under license by the Free Software Foundation, Inc. X This file is part of RCS. X 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. X 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. X You should have received a copy of the GNU General Public License along with RCS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. X Report problems and direct all questions to: X X rcs-bugs@cs.purdue.edu X X*/ X X X X X X/* $Log: rcsfcmp.c,v $ X * Revision 5.9 1991/10/07 17:32:46 eggert X * Count log lines correctly. X * X * Revision 5.8 1991/08/19 03:13:55 eggert X * Tune. X * X * Revision 5.7 1991/04/21 11:58:22 eggert X * Fix errno bug. Add MS-DOS support. X * X * Revision 5.6 1991/02/28 19:18:47 eggert X * Open work file at most once. X * X * Revision 5.5 1990/11/27 09:26:05 eggert X * Fix comment leader bug. X * X * Revision 5.4 1990/11/01 05:03:42 eggert X * Permit arbitrary data in logs and comment leaders. X * X * Revision 5.3 1990/09/11 02:41:15 eggert X * Don't ignore differences inside keyword strings if -ko is set. X * X * Revision 5.1 1990/08/29 07:13:58 eggert X * Clean old log messages too. X * X * Revision 5.0 1990/08/22 08:12:49 eggert X * Don't append "checked in with -k by " log to logs, X * so that checking in a program with -k doesn't change it. X * Ansify and Posixate. Remove lint. X * X * Revision 4.5 89/05/01 15:12:42 narten X * changed copyright header to reflect current distribution rules X * X * Revision 4.4 88/08/09 19:12:50 eggert X * Shrink stdio code size. X * X * Revision 4.3 87/12/18 11:40:02 narten X * lint cleanups (Guy Harris) X * X * Revision 4.2 87/10/18 10:33:06 narten X * updting version number. Changes relative to 1.1 actually relative to X * 4.1 X * X * Revision 1.2 87/03/27 14:22:19 jenkins X * Port to suns X * X * Revision 4.1 83/05/10 16:24:04 wft X * Marker matching now uses trymatch(). Marker pattern is now X * checked precisely. X * X * Revision 3.1 82/12/04 13:21:40 wft X * Initial revision. X * X */ X X/* X#define FCMPTEST X*/ X/* Testprogram; prints out whether two files are identical, X * except for keywords X */ X X#include "rcsbase.h" X libId(fcmpId, "$Id: rcsfcmp.c,v 5.9 1991/10/07 17:32:46 eggert Exp $") X X static int discardkeyval(c, f) X register int c; X register RILE *f; X{ X for (;;) X switch (c) { X case KDELIM: X case '\n': X return c; X default: X Igeteof(f, c, return EOF;); X break; X } X} X X int rcsfcmp(xfp, xstatp, ufname, delta) X register RILE *xfp; X struct stat const *xstatp; X char const *ufname; X struct hshentry const *delta; X/* Compare the files xfp and ufname. Return zero X * if xfp has the same contents as ufname and neither has keywords, X * otherwise -1 if they are the same ignoring keyword values, X * and 1 if they differ even ignoring X * keyword values. For the LOG-keyword, rcsfcmp skips the log message X * given by the parameter delta in xfp. Thus, rcsfcmp returns nonpositive X * if xfp contains the same as ufname, with the keywords expanded. X * Implementation: character-by-character comparison until $ is found. X * If a $ is found, read in the marker keywords; if they are real keywords X * and identical, read in keyword value. If value is terminated properly, X * disregard it and optionally skip log message; otherwise, compare value. X */ X{ X register int xc, uc; X char xkeyword[keylength+2]; X int eqkeyvals; X register RILE *ufp; X register int xeof, ueof; X register char * tp; X register char const *sp; X int result; X enum markers match1; X struct stat ustat; X X if (!(ufp = Iopen(ufname, FOPEN_R_WORK, &ustat))) { X efaterror(ufname); X } X xeof = ueof = false; X if (Expand==OLD_EXPAND) { X if (!(result = xstatp->st_size!=ustat.st_size)) { X# if has_mmap && large_memory X result = !!memcmp(xfp->base,ufp->base,(size_t)xstatp->st_size); X# else X for (;;) { X /* get the next characters */ X Igeteof(xfp, xc, xeof=true;); X Igeteof(ufp, uc, ueof=true;); X if (xeof | ueof) X goto eof; X if (xc != uc) X goto return1; X } X# endif X } X } else { X xc = 0; X uc = 0; /* Keep lint happy. */ X result = 0; X X for (;;) { X if (xc != KDELIM) { X /* get the next characters */ X Igeteof(xfp, xc, xeof=true;); X Igeteof(ufp, uc, ueof=true;); X if (xeof | ueof) X goto eof; X } else { X /* try to get both keywords */ X tp = xkeyword; X for (;;) { X Igeteof(xfp, xc, xeof=true;); X Igeteof(ufp, uc, ueof=true;); X if (xeof | ueof) X goto eof; X if (xc != uc) X break; X switch (xc) { X default: X if (xkeyword+keylength <= tp) X break; X *tp++ = xc; X continue; X case '\n': case KDELIM: case VDELIM: X break; X } X break; X } X if ( X (xc==KDELIM || xc==VDELIM) && (uc==KDELIM || uc==VDELIM) && X (*tp = xc, (match1 = trymatch(xkeyword)) != Nomatch) X ) { X#ifdef FCMPTEST X VOID printf("found common keyword %s\n",xkeyword); X#endif X result = -1; X for (;;) { X if (xc != uc) { X xc = discardkeyval(xc, xfp); X uc = discardkeyval(uc, ufp); X if ((xeof = xc==EOF) | (ueof = uc==EOF)) X goto eof; X eqkeyvals = false; X break; X } X switch (xc) { X default: X Igeteof(xfp, xc, xeof=true;); X Igeteof(ufp, uc, ueof=true;); X if (xeof | ueof) X goto eof; X continue; X X case '\n': case KDELIM: X eqkeyvals = true; X break; X } X break; X } X if (xc != uc) X goto return1; X if (xc==KDELIM) { X /* Skip closing KDELIM. */ X Igeteof(xfp, xc, xeof=true;); X Igeteof(ufp, uc, ueof=true;); X if (xeof | ueof) X goto eof; X /* if the keyword is LOG, also skip the log message in xfp*/ X if (match1==Log) { X /* first, compute the number of line feeds in log msg */ X unsigned lncnt; X size_t ls, ccnt; X sp = delta->log.string; X ls = delta->log.size; X if (ls'src/rcskeep.c' <<'END_OF_FILE' X/* X * RCS keyword extraction X */ X/***************************************************************************** X * main routine: getoldkeys() X * Testprogram: define KEEPTEST X ***************************************************************************** X */ X X/* Copyright (C) 1982, 1988, 1989 Walter Tichy X Copyright 1990, 1991 by Paul Eggert X Distributed under license by the Free Software Foundation, Inc. X This file is part of RCS. X 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. X 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. X You should have received a copy of the GNU General Public License along with RCS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. X Report problems and direct all questions to: X X rcs-bugs@cs.purdue.edu X X*/ X X X X/* $Log: rcskeep.c,v $ X * Revision 5.4 1991/08/19 03:13:55 eggert X * Tune. X * X * Revision 5.3 1991/04/21 11:58:25 eggert X * Shorten names to keep them distinct on shortname hosts. X * X * Revision 5.2 1990/10/04 06:30:20 eggert X * Parse time zone offsets; future RCS versions may output them. X * X * Revision 5.1 1990/09/20 02:38:56 eggert X * ci -k now checks dates more thoroughly. X * X * Revision 5.0 1990/08/22 08:12:53 eggert X * Retrieve old log message if there is one. X * Don't require final newline. X * Remove compile-time limits; use malloc instead. Tune. X * Permit dates past 1999/12/31. Ansify and Posixate. X * X * Revision 4.6 89/05/01 15:12:56 narten X * changed copyright header to reflect current distribution rules X * X * Revision 4.5 88/08/09 19:13:03 eggert X * Remove lint and speed up by making FILE *fp local, not global. X * X * Revision 4.4 87/12/18 11:44:21 narten X * more lint cleanups (Guy Harris) X * X * Revision 4.3 87/10/18 10:35:50 narten X * Updating version numbers. Changes relative to 1.1 actually relative X * to 4.1 X * X * Revision 1.3 87/09/24 14:00:00 narten X * Sources now pass through lint (if you ignore printf/sprintf/fprintf X * warnings) X * X * Revision 1.2 87/03/27 14:22:29 jenkins X * Port to suns X * X * Revision 4.1 83/05/10 16:26:44 wft X * Added new markers Id and RCSfile; extraction added. X * Marker matching with trymatch(). X * X * Revision 3.2 82/12/24 12:08:26 wft X * added missing #endif. X * X * Revision 3.1 82/12/04 13:22:41 wft X * Initial revision. X * X */ X X/* X#define KEEPTEST X*/ X/* Testprogram; prints out the keyword values found. */ X X#include "rcsbase.h" X libId(keepId, "$Id: rcskeep.c,v 5.4 1991/08/19 03:13:55 eggert Exp $") X static int checknum P((char const*,int)); static int getval P((RILE*,struct buf*,int)); static int get0val P((int,RILE*,struct buf*,int)); static int keepdate P((RILE*)); static int keepid P((int,RILE*,struct buf*)); static int keeprev P((RILE*)); X int prevkeys; struct buf prevauthor, prevdate, prevrev, prevstate; X X int getoldkeys(fp) X register RILE *fp; X/* Function: Tries to read keyword values for author, date, X * revision number, and state out of the file fp. X * If FNAME is nonnull, it is opened and closed instead of using FP. X * The results are placed into X * prevauthor, prevdate, prevrev, prevstate. X * Aborts immediately if it finds an error and returns false. X * If it returns true, it doesn't mean that any of the X * values were found; instead, check to see whether the corresponding arrays X * contain the empty string. X */ X{ X register int c; X char keyword[keylength+1]; X register char * tp; X int needs_closing; X X if (prevkeys) X return true; X X needs_closing = false; X if (!fp) { X if (!(fp = Iopen(workfilename, FOPEN_R_WORK, (struct stat*)0))) { X eerror(workfilename); X return false; X } X needs_closing = true; X } X X /* initialize to empty */ X bufscpy(&prevauthor, ""); X bufscpy(&prevdate, ""); X bufscpy(&prevrev, ""); X bufscpy(&prevstate, ""); X X c = '\0'; /* anything but KDELIM */ X for (;;) { X if ( c==KDELIM) { X do { X /* try to get keyword */ X tp = keyword; X for (;;) { X Igeteof(fp, c, goto ok;); X switch (c) { X default: X if (keyword+keylength <= tp) X break; X *tp++ = c; X continue; X X case '\n': case KDELIM: case VDELIM: X break; X } X break; X } X } while (c==KDELIM); X if (c!=VDELIM) continue; X *tp = c; X Igeteof(fp, c, break;); X switch (c) { X case ' ': case '\t': break; X default: continue; X } X X switch (trymatch(keyword)) { X case Author: X if (!keepid(0, fp, &prevauthor)) X return false; X c = 0; X break; X case Date: X if (!(c = keepdate(fp))) X return false; X break; X case Header: X case Id: X if (!( X getval(fp, (struct buf*)nil, false) && X keeprev(fp) && X (c = keepdate(fp)) && X keepid(c, fp, &prevauthor) && X keepid(0, fp, &prevstate) X )) X return false; X /* Skip either ``who'' (new form) or ``Locker: who'' (old). */ X if (getval(fp, (struct buf*)nil, true) && X getval(fp, (struct buf*)nil, true)) X c = 0; X else if (nerror) X return false; X else X c = KDELIM; X break; X case Locker: X case Log: X case RCSfile: X case Source: X if (!getval(fp, (struct buf*)nil, false)) X return false; X c = 0; X break; X case Revision: X if (!keeprev(fp)) X return false; X c = 0; X break; X case State: X if (!keepid(0, fp, &prevstate)) X return false; X c = 0; X break; X default: X continue; X } X if (!c) X Igeteof(fp, c, c=0;); X if (c != KDELIM) { X error("closing %c missing on keyword", KDELIM); X return false; X } X if (*prevauthor.string && *prevdate.string && *prevrev.string && *prevstate.string) { X break; X } X } X Igeteof(fp, c, break;); X } X X ok: X if (needs_closing) X Ifclose(fp); X else X Irewind(fp); X prevkeys = true; X return true; X} X X static int badly_terminated() X{ X error("badly terminated keyword value"); X return false; X} X X static int getval(fp, target, optional) X register RILE *fp; X struct buf *target; X int optional; X/* Reads a keyword value from FP into TARGET. X * Returns true if one is found, false otherwise. X * Does not modify target if it is nil. X * Do not report an error if OPTIONAL is set and KDELIM is found instead. X */ X{ X int c; X Igeteof(fp, c, return badly_terminated();); X return get0val(c, fp, target, optional); X} X X static int get0val(c, fp, target, optional) X register int c; X register RILE *fp; X struct buf *target; X int optional; X/* Reads a keyword value from C+FP into TARGET, perhaps OPTIONALly. X * Same as getval, except C is the lookahead character. X */ X{ register char * tp; X char const *tlim; X register int got1; X X if (target) { X bufalloc(target, 1); X tp = target->string; X tlim = tp + target->size; X } else X tlim = tp = 0; X got1 = false; X for (;;) { X switch (c) { X default: X got1 = true; X if (tp) { X *tp++ = c; X if (tlim <= tp) X tp = bufenlarge(target, &tlim); X } X break; X X case ' ': X case '\t': X if (tp) { X *tp = 0; X# ifdef KEEPTEST X VOID printf("getval: %s\n", target); X# endif X } X if (!got1) X error("too much white space in keyword value"); X return got1; X X case KDELIM: X if (!got1 && optional) X return false; X /* fall into */ X case '\n': X case 0: X return badly_terminated(); X } X Igeteof(fp, c, return badly_terminated();); X } X} X X X static int keepdate(fp) X RILE *fp; X/* Function: reads a date prevdate; checks format X * Return 0 on error, lookahead character otherwise. X */ X{ X struct buf prevday, prevtime, prevzone; X register char const *p; X register int c; X X c = 0; X bufautobegin(&prevday); X if (getval(fp,&prevday,false)) { X bufautobegin(&prevtime); X if (getval(fp,&prevtime,false)) { X bufautobegin(&prevzone); X bufscpy(&prevzone, ""); X Igeteof(fp, c, c=0;); X if (c=='-' || c=='+') X if (!get0val(c,fp,&prevzone,false)) X c = 0; X else X Igeteof(fp, c, c=0;); X if (c) { X p = prevday.string; X bufalloc(&prevdate, strlen(p) + strlen(prevtime.string) + strlen(prevzone.string) + 5); X VOID sprintf(prevdate.string, "%s%s %s %s", X /* Parse dates put out by old versions of RCS. */ X isdigit(p[0]) && isdigit(p[1]) && p[2]=='/' ? "19" : "", X p, prevtime.string, prevzone.string X ); X } X bufautoend(&prevzone); X } X bufautoend(&prevtime); X } X bufautoend(&prevday); X return c; X} X X static int keepid(c, fp, b) X int c; X RILE *fp; X struct buf *b; X/* Get previous identifier from C+FP into B. */ X{ X if (!c) X Igeteof(fp, c, return false;); X if (!get0val(c, fp, b, false)) X return false; X checksid(b->string); X return true; X} X X static int keeprev(fp) X RILE *fp; X/* Get previous revision from FP into prevrev. */ X{ X return getval(fp,&prevrev,false) && checknum(prevrev.string,-1); X} X X X static int checknum(sp,fields) X register char const *sp; X int fields; X{ register int dotcount; X dotcount=0; X while(*sp) { X if (*sp=='.') dotcount++; X else if (!isdigit(*sp)) return false; X sp++; X } X return fields<0 ? dotcount&1 : dotcount==fields; X} X X X X#ifdef KEEPTEST X char const cmdid[] ="keeptest"; X X int main(argc, argv) int argc; char *argv[]; X{ X while (*(++argv)) { X workfilename = *argv; X getoldkeys((RILE*)0); X VOID printf("%s: revision: %s, date: %s, author: %s, state: %s\n", X *argv, prevrev.string, prevdate.string, prevauthor.string, prevstate.string); X } X exitmain(EXIT_SUCCESS); X} X#endif END_OF_FILE if test 10028 -ne `wc -c <'src/rcskeep.c'`; then echo shar: \"'src/rcskeep.c'\" unpacked with wrong size! fi # end of 'src/rcskeep.c' fi if test -f 'src/rcsmerge.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/rcsmerge.c'\" else echo shar: Extracting \"'src/rcsmerge.c'\" \(6990 characters\) sed "s/^X//" >'src/rcsmerge.c' <<'END_OF_FILE' X/* X * rcsmerge operation X */ X/***************************************************************************** X * join 2 revisions with respect to a third X ***************************************************************************** X */ X X/* Copyright (C) 1982, 1988, 1989 Walter Tichy X Copyright 1990, 1991 by Paul Eggert X Distributed under license by the Free Software Foundation, Inc. X This file is part of RCS. X 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. X 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. X You should have received a copy of the GNU General Public License along with RCS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. X Report problems and direct all questions to: X X rcs-bugs@cs.purdue.edu X X*/ X X X X/* $Log: rcsmerge.c,v $ X * Revision 5.7 1991/11/20 17:58:09 eggert X * Don't Iopen(f, "r+"); it's not portable. X * X * Revision 5.6 1991/08/19 03:13:55 eggert X * Add -r$. Tune. X * X * Revision 5.5 1991/04/21 11:58:27 eggert X * Add -x, RCSINIT, MS-DOS support. X * X * Revision 5.4 1991/02/25 07:12:43 eggert X * Merging a revision to itself is no longer an error. X * X * Revision 5.3 1990/11/01 05:03:50 eggert X * Remove unneeded setid check. X * X * Revision 5.2 1990/09/04 08:02:28 eggert X * Check for I/O error when reading working file. X * X * Revision 5.1 1990/08/29 07:14:04 eggert X * Add -q. Pass -L options to merge. X * X * Revision 5.0 1990/08/22 08:13:41 eggert X * Propagate merge's exit status. X * Remove compile-time limits; use malloc instead. X * Make lock and temp files faster and safer. Ansify and Posixate. Add -V. X * Don't use access(). Tune. X * X * Revision 4.5 89/05/01 15:13:16 narten X * changed copyright header to reflect current distribution rules X * X * Revision 4.4 88/08/09 19:13:13 eggert X * Beware merging into a readonly file. X * Beware merging a revision to itself (no change). X * Use execv(), not system(); yield exit status like diff(1)'s. X * X * Revision 4.3 87/10/18 10:38:02 narten X * Updating version numbers. Changes relative to version 1.1 X * actually relative to 4.1 X * X * Revision 1.3 87/09/24 14:00:31 narten X * Sources now pass through lint (if you ignore printf/sprintf/fprintf X * warnings) X * X * Revision 1.2 87/03/27 14:22:36 jenkins X * Port to suns X * X * Revision 4.1 83/03/28 11:14:57 wft X * Added handling of default branch. X * X * Revision 3.3 82/12/24 15:29:00 wft X * Added call to catchsig(). X * X * Revision 3.2 82/12/10 21:32:02 wft X * Replaced getdelta() with gettree(); improved error messages. X * X * Revision 3.1 82/11/28 19:27:44 wft X * Initial revision. X * X */ X#include "rcsbase.h" X static char const co[] = CO; X mainProg(rcsmergeId, "rcsmerge", "$Id: rcsmerge.c,v 5.7 1991/11/20 17:58:09 eggert Exp $") X{ X static char const cmdusage[] = X "\nrcsmerge usage: rcsmerge -rrev1 [-rrev2] [-p] [-Vn] file"; X static char const quietarg[] = "-q"; X X register int i; X char *a, **newargv; X char const *arg[3]; X char const *rev[2]; /*revision numbers*/ X char const *expandarg, *versionarg; X int tostdout; X int status; X RILE *workptr; X struct buf commarg; X struct buf numericrev; /* holds expanded revision number */ X struct hshentries *gendeltas; /* deltas to be generated */ X struct hshentry * target; X X bufautobegin(&commarg); X bufautobegin(&numericrev); X rev[0] = rev[1] = nil; X status = 0; /* Keep lint happy. */ X tostdout = false; X expandarg = versionarg = quietarg; /* i.e. a no-op */ X suffixes = X_DEFAULT; X X argc = getRCSINIT(argc, argv, &newargv); X argv = newargv; X while (a = *++argv, 0<--argc && *a++=='-') { X switch (*a++) { X case 'p': X tostdout=true; X goto revno; X X case 'q': X quietflag = true; X revno: X if (!*a) X break; X /* falls into -r */ X case 'r': X if (!rev[0]) X rev[0] = a; X else if (!rev[1]) X rev[1] = a; X else X faterror("too many revision numbers"); X break; X case 'x': X suffixes = a; X break; X case 'V': X versionarg = *argv; X setRCSversion(versionarg); X break; X X case 'k': X expandarg = *argv; X if (0 <= str2expmode(expandarg+2)) X break; X /* fall into */ X default: X faterror("unknown option: %s%s", *argv, cmdusage); X }; X } /* end of option processing */ X X if (argc<1) faterror("no input file%s", cmdusage); X if (!rev[0]) faterror("no base revision number given"); X X /* now handle all filenames */ X X if (0 < pairfilenames(argc, argv, rcsreadopen, true, false)) { X X if (argc>2 || (argc==2&&argv[1]!=nil)) X warn("too many arguments"); X diagnose("RCS file: %s\n", RCSfilename); X if (!(workptr = Iopen(workfilename, X FOPEN_R_WORK, X (struct stat*)0 X ))) X efaterror(workfilename); X X gettree(); /* reads in the delta tree */ X X if (Head==nil) faterror("no revisions present"); X X if (!*rev[0]) X rev[0] = Dbranch ? Dbranch : Head->num; X if (!fexpandsym(rev[0], &numericrev, workptr)) X goto end; X if (!(target=genrevs(numericrev.string, (char *)nil, (char *)nil, (char *)nil,&gendeltas))) goto end; X rev[0] = target->num; X if (!rev[1] || !*rev[1]) X rev[1] = Dbranch ? Dbranch : Head->num; X if (!fexpandsym(rev[1], &numericrev, workptr)) X goto end; X if (!(target=genrevs(numericrev.string, (char *)nil, (char *)nil, (char *)nil,&gendeltas))) goto end; X rev[1] = target->num; X X if (strcmp(rev[0],rev[1]) == 0) { X if (tostdout) { X FILE *o; X# if text_equals_binary_stdio || text_work_stdio X o = stdout; X# else X if (!(o=fdopen(STDOUT_FILENO,FOPEN_W_WORK))) X efaterror("stdout"); X# endif X fastcopy(workptr,o); X Ofclose(o); X } X goto end; X } X Izclose(&workptr); X X for (i=0; i<2; i++) { X diagnose("retrieving revision %s\n", rev[i]); X bufscpy(&commarg, "-p"); X bufscat(&commarg, rev[i]); X if (run( X (char*)0, X /* Do not collide with merger.c maketemp(). */ X arg[i+1] = maketemp(i+3), X co, quietarg, commarg.string, expandarg, X versionarg, RCSfilename, (char*)0 X )) X faterror("co failed"); X } X diagnose("Merging differences between %s and %s into %s%s\n", X rev[0], rev[1], workfilename, X tostdout?"; result to stdout":""); X X arg[0] = rev[0] = workfilename; X status = merge(tostdout, rev, arg); X } X end: X Izclose(&workptr); X tempunlink(); X exitmain(nerror ? DIFF_TROUBLE : status); X} X X#if lint X# define exiterr rmergeExit X#endif X exiting void exiterr() X{ X tempunlink(); X _exit(DIFF_TROUBLE); X} END_OF_FILE if test 6990 -ne `wc -c <'src/rcsmerge.c'`; then echo shar: \"'src/rcsmerge.c'\" unpacked with wrong size! fi # end of 'src/rcsmerge.c' fi if test -f 'src/rcstest' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/rcstest'\" else echo shar: Extracting \"'src/rcstest'\" \(9809 characters\) sed "s/^X//" >'src/rcstest' <<'END_OF_FILE' X#!/bin/sh X X# Test RCS's functions. X# The RCS commands are searched for in the PATH as usual; X# to test the working directory's commands, prepend . to your PATH. X X# Test RCS by creating files RCS/a.* and RCS/a.c. X# If all goes well, output nothing, and remove the temporary files. X# Otherwise, send a message to standard output. X# Exit status is 0 if OK, 1 if an RCS bug is found, and 2 if scaffolding fails. X# With the -v option, output more debugging info. X X# If diff outputs `No differences encountered' when comparing identical files, X# then rcstest may also output these noise lines; ignore them. X X# The current directory and ./RCS must be readable, writable, and searchable. X X# $Id: rcstest,v 5.8 1991/11/20 17:58:10 eggert Exp $ X X X# Copyright 1990, 1991 by Paul Eggert X# Distributed under license by the Free Software Foundation, Inc. X# X# This file is part of RCS. X# X# RCS is free software; you can redistribute it and/or modify X# it under the terms of the GNU General Public License as published by X# the Free Software Foundation; either version 2, or (at your option) X# any later version. X# X# RCS is distributed in the hope that it will be useful, X# but WITHOUT ANY WARRANTY; without even the implied warranty of X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X# GNU General Public License for more details. X# X# You should have received a copy of the GNU General Public License X# along with RCS; see the file COPYING. If not, write to X# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. X# X# Report problems and direct all questions to: X# X# rcs-bugs@cs.purdue.edu X RCSINIT=-x export RCSINIT X SLASH=/ RCSfile=RCS${SLASH}a.c RCS_alt=RCS${SLASH}a.d lockfile=RCS${SLASH}a._ X case $1 in X-v) q=; set -x;; X'') q=-q;; X*) echo >&2 "$0: usage: $0 [-v]"; exit 2 esac X test -d RCS || { X echo >&2 "$0: RCS: not a directory; please \`mkdir RCS' first." X exit 1 X} X 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; } X case `diff -c a.11 a.3x1` in X*'! 1.1.1.1') X diff='diff -c';; X*) X echo "#warning: diff -c does not work, so diagnostics may be cryptic" X diff=diff esac X rcs -i -L -ta.11 $q a.c && X<$RCSfile || { X echo "#rcs -i -L failed; perhaps RCS is not properly installed." X exit 1 X} X rlog a.c >/dev/null || { echo "#rlog failed on empty RCS file"; exit 1; } rm -f $RCSfile || exit 2 X cp a.11 a.c && ci -ta.11 -mm $q a.c && X<$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 X co $l $q a.c && X test -f a.c || { echo '#co' $l did not create working file; exit 1; } X $diff a.11 a.c || { echo '#ci' followed by co $l is not a no-op; exit 1; } done X cp a.12 a.c && ci -mm $q a.c && co $q a.c && X$diff a.12 a.c || { echo "#ci+co failed"; exit 1; } X co -r1.1 $q a.c && X$diff a.11 a.c || { echo "#can't retrieve first revision"; exit 1; } X 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 && X$diff a.3x1 a.c || { echo "#branches failed"; exit 1; } X co -l $q a.c && ci -f -mm $q a.c && co -r1.3 $q a.c && X$diff a.12 a.c || { echo "#(co -l; ci -f) failed"; exit 1; } X 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; } X co -l $q a.c && echo 1.5 >a.c && ci -u -mm $q a.c && Xa.c || exit 2 ci -mm $q a.c 2>/dev/null && { echo "#ci -u didn't unlock the file"; exit 1; } X 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; } X rm -f a.c && cp a.11 a.c && co -f $q a.c || { echo "#co -f failed"; exit 1; } X$diff a.11 a.c >/dev/null && { echo "#co -f had no effect"; exit 1; } X co -p1.1 $q a.c >a.t && X$diff a.11 a.t || { echo "#co -p failed"; exit 1; } X for n in n N do X rm -f a.c && X co -l $q a.c && X echo $n >a.$n && X cp a.$n a.c && X ci -${n}n -mm $q a.c && X co -rn $q a.c && X $diff a.$n a.c || { echo "#ci -$n failed"; exit 1; } done X case $LOGNAME in X?*) me=$LOGNAME;; X*) X case $USER in X ?*) me=$USER;; X *) X me=`who am i` || exit 2 X me=`echo "$me" | sed -e 's/ .*//' -e 's/.*!//'` X case $me in X '') echo >&2 "$0: cannot deduce user name"; exit 2 X esac X esac esac date=`date -u 2>/dev/null` || date=`TZ=GMT0 date 2>/dev/null` || date=`TZ= date` || exit 2 set $date case $2 in Jan) m=01;; Feb) m=02;; Mar) m=03;; Apr) m=04;; May) m=05;; Jun) m=06;; Jul) m=07;; Aug) m=08;; Sep) m=09;; Oct) m=10;; Nov) m=11;; Dec) m=12;; X*) echo >&2 "$0: $2: unknown month name"; exit 2 esac case $3 in X?) d=0$3;; X*) d=$3 esac case $6 in X[0-9][0-9][0-9][0-9]*) D=$6/$m/$d;; X*) X case $5 in X [0-9][0-9][0-9][0-9]*) D=$5/$m/$d;; X *) echo >&2 "$0: bad date format: $date"; exit 2 X esac esac T=$4 case $PWD in X'') PWD=`pwd` esac && co -l $q a.c && sed 's/@/$/g' >a.kv <a.k && sed -e 's/w s [$]/w s '"$me"' $/' -e 's/[$]Locker: /&'"$me/" a.kv >a.kvl && 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" -ss -ww -u2.1 -mm $q a.c && X$diff a.kv a.c || { echo "#keyword expansion failed"; exit 1; } co -p -ko $q a.c >a.oo && X$diff a.o a.oo || { echo "#co -p -ko failed"; exit 1; } cp a.kv a.o || exit 2 rcs -o2.1 $q a.c && rcs -l $q a.c && ci -k -u $q a.c && X$diff a.kv a.c || { echo "#ci -k failed"; exit 1; } sed '/^[^$]/d' a.kv >a.i && ident a.c >a.i1 && sed -e 1d -e 's/^[ ]*//' a.i1 >a.i2 && X$diff a.i a.i2 || { echo "#ident failed"; exit 1; } X rcs -i $q a.c 2>/dev/null && { echo "#rcs -i permitted existing file"; exit 1; } X 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; } X 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; } X 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; } X rm -f a.c && rcs -nN:1.1 $q a.c && co -rN $q a.c && X$diff a.11 a.c || { echo "#rcs -n failed"; exit 1; } X rcs -NN:2.1 $q a.c && co -rN $q a.c && X$diff a.kv a.c || { echo "#rcs -N failed"; exit 1; } X co -l $q a.c && rcs -c':::' $q a.c && echo '$''Log$' >a.c && ci -u -mm $q a.c && test " `sed '$!d' a.c`" = ' :::' || { echo "#rcs -c failed"; exit 1; } X rcs -o2.2: $q a.c && co $q a.c && X$diff a.kv a.c || { echo "#rcs -o failed"; exit 1; } X rcsdiff -r1.1 -r2.1 $q a.c >a.0 case $? in X1) ;; X*) echo "#rcsdiff bad status"; exit 1 esac diff a.11 a.kv >a.1 X$diff a.0 a.1 || { echo "#rcsdiff failed"; exit 1; } X rcs -l2.1 $q a.c || { echo "#rcs -l2.1 failed"; exit 1; } for i in k kv kvl o v do X rm -f a.c && X cp a.$i a.c && X rcsdiff -k$i $q a.c || { echo "#rcsdiff -k$i failed"; exit 1; } done co -p1.1 -ko $q a.c >a.t && X$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; } X rm -f a.c && co -l $q a.c && cat >a.c <<'EOF' X2.2 a b c d XEOF 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' X2.3 a b1 c d1 XEOF cat >a.1 <<'EOF' X<<<<<<< a.c new X======= X2.3 X>>>>>>> 2.3 a b1 c d1 XEOF rcsmerge -r2.2 -r2.3 $q a.c case $? in X0) X if $diff a.0 a.c >/dev/null X then echo "#warning: diff3 -E does not work, " \ X "so merge and rcsmerge ignore overlaps and suppress overlap lines." X else X $diff a.1 a.c || { echo "#rcsmerge failed (status 0)"; exit 1; } X echo "#warning: The diff3 lib program exit status ignores overlaps," \ X "so rcsmerge does not warn about overlap lines that it generates." X fi X ;; X1) X $diff a.1 a.c || { echo "#rcsmerge failed (status 1)"; exit 1; } X ;; X*) X echo "#rcsmerge bad status"; exit 1 esac X nl=' X' X{ X co -p $q a.c | tr "$nl" '\200' >a.24 && X cp a.24 a.c && X ciOut=`(ci -l -mm $q a.c 2>&1)` && X case $ciOut in X ?*) echo >&2 "$ciOut" X esac && X co -p $q a.c | tr '\200' "$nl" >a.c && X rcsdiff -r2.3 $q a.c >/dev/null && X X echo 2.5 >a.c && X ci -l -mm $q a.c && X cp a.24 a.c && X rcsdiff -r2.4 $q a.c >/dev/null X} || echo "#warning: Traditional diff is used, so RCS is limited to text files." X rcs -u -o2.4: $q a.c || { echo "#rcs -u -o failed"; exit 1; } X rcs -i -Aa.c -t- $q a.d || { echo "#rcs -i -A failed"; exit 1; } X 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 && X$diff - a.u <