page%swap@Sun.COM (Bob Page) (11/19/89)
Submitted-by: rsbx@cbmvax.commodore.com (Raymond S. Brand) Posting-number: Volume 89, Issue 221 Archive-name: unix/rcs.06 # This is a shell archive. # Remove anything above and including the cut line. # Then run the rest of the file through 'sh'. # Unpacked files will be owned by you and have default permissions. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: SHell ARchive # Run the following text through 'sh' to create: # doc/rcs.1l # doc/rcsclean.1l # doc/rcsdiff.1l # doc/rcsfile.5l # doc/rcsfreeze.1l # doc/rcsintro.1l # doc/rcsmerge.1l # doc/rlog.1l # ked/ked.c,v # rcs/readme # rcs/rcs.rcsfiles/maketime.c,v # This is archive 6 of a 14-part kit. # This archive created: Sun Nov 19 01:12:07 1989 if `test ! -d doc` then mkdir doc echo "mkdir doc" fi echo "extracting doc/rcs.1l" sed 's/^X//' << \SHAR_EOF > doc/rcs.1l X.TH RCS 1L "" "Purdue University" X.SH NAME Xrcs \- change RCS file attributes X.SH SYNOPSIS X.B rcs X[ options ] Xfile ... X.SH DESCRIPTION X.I Rcs Xcreates new RCS files or changes attributes of existing ones. XAn RCS file contains multiple revisions of text, Xan access list, a change log, Xdescriptive text, Xand some control attributes. XFor \fIrcs\fR to work, the caller's login name must be on the access list, Xexcept if the access list is empty, the caller is the owner of the file Xor the superuser, or Xthe \fB\-i\fR option is present. X.PP XFiles ending in `,v' are RCS files, all others are working files. If Xa working file is given, \fIrcs\fR tries to find the corresponding XRCS file first in directory ./RCS and then in the current directory, Xas explained in X.IR co (1L). X.TP 11 X.B \-i Xcreates and initializes a new RCS file, but does not deposit any revision. XIf the RCS file has no path prefix, \fIrcs\fR tries to place it Xfirst into the subdirectory ./RCS, and then into the current directory. XIf the RCS file Xalready exists, an error message is printed. X.TP X.BI \-a "logins" Xappends the login names appearing in the comma-separated list \fIlogins\fR Xto the access list of the RCS file. X.TP X.BI \-A "oldfile" Xappends the access list of \fIoldfile\fR to the access list of the RCS file. X.TP X.BR \-e [\fIlogins\fR] Xerases the login names appearing in the comma-separated list \fIlogins\fR Xfrom the access list of the RCS file. XIf \fIlogins\fR is omitted, the entire access list is erased. X.TP X.BR \-b [\fIrev\fR] Xsets the default branch to \fIrev\fR. If \fIrev\fR is omitted, the default Xbranch is reset to the (dynamically) highest branch on the trunk. X.TP X.BI \-c "string" Xsets the comment leader to \fIstring\fR. The comment leader Xis printed before every log message line generated by the keyword X$\&Log$ during checkout (see X.IR co (1L)). XThis is useful for programming Xlanguages without multi-line comments. During \fBrcs -i\fR or initial X\fBci\fR, the comment leader is guessed from the suffix of the working file. X.TP X.BR \-l [\fIrev\fR] Xlocks the revision with number \fIrev\fR. XIf a branch is given, the latest revision on that branch is locked. XIf \fIrev\fR is omitted, the latest revision on the default branch is locked. XLocking prevents overlapping changes. XA lock is removed with \fBci\fR or \fBrcs -u\fR (see below). X.TP X.BR \-u [\fIrev\fR] Xunlocks the revision with number \fIrev\fR. XIf a branch is given, the latest revision on that branch is unlocked. XIf \fIrev\fR is omitted, the latest lock held by the caller is removed. XNormally, only the locker of a revision may unlock it. XSomebody else unlocking a revision breaks the lock. XThis causes a mail message to be sent to the original locker. XThe message contains a commentary solicited from the breaker. XThe commentary is terminated with a line containing a single `.' or Xcontrol-D. X.TP X.B \-L Xsets locking to \fIstrict\fR. Strict locking means that the owner Xof an RCS file is not exempt from locking for checkin. XThis option should be used for files that are shared. X.TP X.B \-U Xsets locking to non-strict. Non-strict locking means that the owner of Xa file need not lock a revision for checkin. XThis option should NOT be used for files that are shared. XThe default (\fB\-L\fR or \fB\-U\fR) is determined by your system administrator. X.TP X.B \-n\fIname\fR[:\fIrev\fR] Xassociates the symbolic name \fIname\fR with the branch or Xrevision \fIrev\fR. X\fIRcs\fR prints an error message if \fIname\fR is already associated with Xanother number. XIf \fIrev\fR is omitted, the symbolic name is deleted. X.TP X.B \-N\fIname\fR[:\fIrev\fR] Xsame as \fB\-n\fR, except that it overrides a previous assignment of X\fIname\fR. X.TP X.BI \-o "range" Xdeletes ("outdates") the revisions given by \fIrange\fR. XA range consisting of a single revision number means that revision. XA range consisting of a branch number means the latest revision on that Xbranch. XA range of the form \fIrev1-rev2\fR means Xrevisions \fIrev1\fR to \fIrev2\fR on the same branch, X\fI-rev\fR means from the beginning of the branch containing X\fIrev\fR up to and including \fIrev\fR, and \fIrev-\fR means Xfrom revision \fIrev\fR to the end of the branch containing \fIrev\fR. XNone of the outdated revisions may have branches or locks. X.TP X.B \-q Xquiet mode; diagnostics are not printed. X.TP X.B \-s\fIstate\fR[:\fIrev\fR] Xsets the state attribute of the revision \fIrev\fR to \fIstate\fR. XIf \fIrev\fR is a branch number, the latest revision on that branch is Xassumed. XIf \fIrev\fR is omitted, the latest revision on the default branch is assumed. XAny identifier is acceptable for \fIstate\fR. XA useful set of states Xis \fIExp\fR (for experimental), \fIStab\fR (for stable), and \fIRel\fR (for Xreleased). XBy default, X.IR ci (1L) Xsets the state of a revision to \fIExp\fR. X.TP X.BR \-t [\fItxtfile\fR] Xwrites descriptive text into the RCS file (deletes the existing text). XIf \fItxtfile\fR is omitted, X\fIrcs\fR prompts the user for text supplied from the standard input, Xterminated with a line containing a single `.' or control-D. XOtherwise, the descriptive text is copied from the file \fItxtfile\fR. XIf the \fB\-i\fR option is present, descriptive text is requested Xeven if \fB\-t\fR is not given. XThe prompt is suppressed if the standard input is not a terminal. X.SH DIAGNOSTICS XThe RCS file name and the revisions outdated are written to Xthe diagnostic output. XThe exit status always refers to the last RCS file operated upon, Xand is 0 if the operation was successful, 1 otherwise. X.SH FILES XThe caller of the command Xmust have read/write permission for the directory containing Xthe RCS file and read permission for the RCS file itself. X.I Rcs Xcreates a semaphore file in the same directory as the RCS Xfile to prevent simultaneous update. XFor changes, \fIrcs\fR always creates a new file. On successful completion, X\fIrcs\fR deletes the old one and renames the new one. XThis strategy makes links to RCS files useless. X.SH IDENTIFICATION X.de VL X\\$2 X.. XAuthor: Walter F. Tichy, XPurdue University, West Lafayette, IN, 47907. X.sp 0 XRevision Number: X.VL $Revision: 1.3 $ X; Release Date: X.VL $Date: 89/05/02 11:14:37 $ X\&. X.sp 0 XCopyright \(co 1982, 1988, 1989 by Walter F. Tichy. X.SH SEE ALSO Xco(1L), ci(1L), ident(1L), rcsdiff(1L), rcsintro(1L), rcsmerge(1L), rlog(1L), Xrcsfile(5L) X.sp 0 XWalter F. Tichy, "Design, Implementation, and Evaluation of a Revision Control XSystem," in \fIProceedings of the 6th International Conference on Software XEngineering\fR, IEEE, Tokyo, Sept. 1982. SHAR_EOF echo "extracting doc/rcsclean.1l" sed 's/^X//' << \SHAR_EOF > doc/rcsclean.1l X.TH RCSCLEAN 1L "" "Purdue University" X.SH NAME Xrcsclean \- clean up working files X.SH SYNOPSIS X\fBrcsclean\fR [ \fB-r\fIrev\fR ] [ \fB-q\fIrev\fR ] file... X.SH DESCRIPTION X.I Rcsclean Xremoves working files that were checked out and never modified. XFor each file given, \fIrcsclean\fR Xcompares the working file and a revision in the corresponding XRCS file. If it finds no difference, it removes the working file, and, Xif the revision was locked by the caller, unlocks the revision. X.PP XA file name ending in ',v' is an RCS file name, otherwise a Xworking file name. \fIRcsclean\fR derives the working file name from the RCS Xfile name and vice versa, as explained in X.IR co (1L). XPairs consisting Xof both an RCS and a working file name may also be specified. X.PP X\fIRev\fR specifies with which revision the working file is compared. XIf \fIrev\fR is omitted, \fIrcsclean\fR compares the working file with Xthe latest revision Xon the default branch (normally the highest branch on the trunk). XThe option \fB-q\fR suppresses diagnostics. X.PP X\fIRcsclean\fR is useful for "clean" targets in Makefiles. XNote that X.IR rcsdiff (1L) Xprints out the differences. XAlso, X.IR ci (1L) Xnormally asks whether to check in a file Xif it was not changed. X.SH EXAMPLES X.nf XThe command X X rcsclean *.c *.h X X.fi Xremoves all working files ending in ".c" or ".h" that were not changed Xsince their checkout. X.SH DIAGNOSTICS XThe exit status is 0 if there were no differences Xduring the last comparison or if the last working file did not exist, X1 if there were differences, and 2 if there were errors. X.SH IDENTIFICATION X.de VL X\\$2 X.. XAuthor: Walter F. Tichy, XPurdue University, West Lafayette, IN, 47907. X.sp 0 XRevision Number: X.VL $Revision: 1.2 $ X; Release Date: X.VL $Date: 89/05/02 11:15:26 $ X\&. X.sp 0 XCopyright \(co 1982, 1988, 1989 by Walter F. Tichy. X.SH SEE ALSO Xco(1L), ci(1L), ident(1L), rcs(1L), rcsdiff(1L), rcsintro(1L), rcsmerge(1L), Xrlog(1L), rcsfile(5L). SHAR_EOF echo "extracting doc/rcsdiff.1l" sed 's/^X//' << \SHAR_EOF > doc/rcsdiff.1l X.TH RCSDIFF 1L "" "Purdue University" X.SH NAME Xrcsdiff \- compare RCS revisions X.SH SYNOPSIS X\fBrcsdiff\fR [ \fB\-biwt\fR ] [ \fB\-cefhn\fR ] [ \fB\-q\fR ] [ \fB\-r\fIrev1\fR ] [ \fB\-r\fIrev2\fR ] file ... X.SH DESCRIPTION X.I Rcsdiff Xruns X.IR diff (1) Xto compare two revisions of each RCS file given. XA file name ending in ',v' is an RCS file name, otherwise a Xworking file name. \fIRcsdiff\fR derives the working file name from the RCS Xfile name and vice versa, as explained in X.IR co (1L). XPairs consisting Xof both an RCS and a working file name may also be specified. X.PP XThe options \fB\-b\fR, \fB\-i\fR, \fB\-w\fR, \fB\-t\fR, X\fB\-c\fR, \fB\-e\fR, \fB\-f\fR, and \fB\-h\fR, Xhave the same effect as described in X.IR diff (1); Xoption X\fB\-n\fR generates an edit script of the format used by RCS. XThe option \fB\-q\fR suppresses diagnostic output. X.PP XIf both \fIrev1\fR and \fIrev2\fR Xare omitted, \fIrcsdiff\fR compares the latest revision on the Xdefault branch (normally the highest branch on the trunk) Xwith the contents of the corresponding working file. This is useful Xfor determining what you changed since the last checkin. X.PP XIf \fIrev1\fR is given, but \fIrev2\fR is omitted, X\fIrcsdiff\fR compares revision \fIrev1\fR of the RCS file with Xthe contents of the corresponding working file. X.PP XIf both \fIrev1\fR and \fIrev2\fR are given, X\fIrcsdiff\fR compares revisions \fIrev1\fR and \fIrev2\fR of the RCS file. X.PP XBoth \fIrev1\fR and \fIrev2\fR may be given numerically or symbolically, Xand may actually be attached to any of the options. X.SH EXAMPLES X.nf XThe command X X.B " rcsdiff f.c X X.fi Xruns \fIdiff\fR on the latest revision on the default branch of RCS file f.c,v Xand the contents of working file f.c. X.SH DIAGNOSTICS XThe exit status is 0 if there were no differences during the last comparison, X1 if there were differences, and 2 if there were errors. X.SH IDENTIFICATION X.de VL X\\$2 X.. XAuthor: Walter F. Tichy, XPurdue University, West Lafayette, IN, 47907. X.sp 0 XRevision Number: X.VL $Revision: 1.3 $ X; Release Date: X.VL $Date: 89/05/02 11:16:01 $ X\&. X.sp 0 XCopyright \(co 1982, 1988, 1989 by Walter F. Tichy. X.SH SEE ALSO Xci(1L), co(1L), diff(1), ident(1L), rcs(1L), rcsintro(1L), rcsmerge(1L), rlog(1L) X.br XWalter F. Tichy, "Design, Implementation, and Evaluation of a Revision Control XSystem," in \fIProceedings of the 6th International Conference on Software XEngineering\fR, IEEE, Tokyo, Sept. 1982. SHAR_EOF echo "extracting doc/rcsfile.5l" sed 's/^X//' << \SHAR_EOF > doc/rcsfile.5l X.TH RCSFILE 5L "" "Purdue University" X.SH NAME Xrcsfile \- format of RCS file X.SH DESCRIPTION XAn RCS file is an ASCII file. Its contents are described by the grammar Xbelow. The text is free format, i.e., spaces, tabs and new lines have Xno significance except in strings. Strings are enclosed by `@'. XIf a string contains a `@', it must be doubled. X.PP XThe meta syntax uses the following conventions: `|' (bar) separates Xalternatives; `{' and `}' enclose optional phrases; `{' and `}*' enclose Xphrases that may be repeated zero or more times; X`{' and '}+' enclose phrases that must appear at least once and may be Xrepeated; X`<' and `>' enclose nonterminals. X.PP X.ta 1.5i 2.0i 3i X.fc ~ X.nf X X X<rcstext> ~~::=~~<admin> {<delta>}* <desc> {<deltatext>}* X X<admin> ~~::=~~\fBhead\fR ~~{<num>}; X ~~ ~~\fBbranch\fR ~~{<num>}; X ~~ ~~\fBaccess\fR ~~{<id>}*; X ~~ ~~\fBsymbols\fR ~~{<id> : <num>}*; X ~~ ~~\fBlocks\fR ~~{<id> : <num>}*; X ~~ ~~\fBcomment\fR ~~{<string>}; X X<delta> ~~::=~~<num> X ~~ ~~\fBdate\fR ~~<num>; X ~~ ~~\fBauthor\fR ~~<id>; X ~~ ~~\fBstate\fR ~~{<id>}; X ~~ ~~\fBbranches\fR ~~{<num>}*; X ~~ ~~\fBnext\fR ~~{<num>}; X X<desc> ~~::=~~\fBdesc\fR ~~<string> X X<deltatext>~~::=~~<num> X ~~ ~~\fBlog\fR ~~<string> X ~~ ~~\fBtext\fR ~~<string> X X X<num> ~~::=~~{<digit>{.}}+ X X<digit> ~~::=~~0 | 1 | ... | 9 X X<id> ~~::=~~<letter>{<idchar>}* X X<letter> ~~::=~~A | B | ... | Z | a | b | ... | z X X<idchar> ~~::=~~Any printing ASCII character except space, X ~~ ~~tab, carriage return, new line, and <special>. X X<special> ~~::=~~; | : | , | @ X X<string> ~~::=~~@{any ASCII character, with `@' doubled}*@ X X.fi X.PP XIdentifiers are case sensitive. Keywords are in lower case only. XThe sets of keywords and identifiers may overlap. X.PP XThe <delta> nodes form a tree. All nodes whose numbers Xconsist of a single pair X(e.g., 2.3, 2.1, 1.3, etc.) Xare on the "trunk", and are linked through the \fBnext\fR Xfield in order of decreasing numbers. The \fBhead\fR field in the X<admin> node points to the head of that sequence (i.e., contains Xthe highest pair). XThe \fBbranch\fR node in the admin node indicates the default Xbranch (or revision) for most RCS operations. If empty, the default Xbranch is the highest branch on the trunk. X.PP XAll <delta> nodes whose numbers consist of 2n fields (n\(>=2) X(e.g., 3.1.1.1, 2.1.2.2, etc.) Xare linked as follows. All nodes whose first (2n)-1 number fields are identical Xare linked through the \fBnext\fR field in order of increasing numbers. XFor each such sequence, Xthe <delta> node whose number is identical to the first X2(n-1) number fields of the deltas on that sequence is called the branchpoint. XThe \fBbranches\fR field of a node contains a list of the Xnumbers of the first nodes of all sequences for which it is a branchpoint. XThis list is ordered in increasing numbers. X.sp 1 X.ne 38 XExample: X.eo X.nf X.vs 12pts X.cs 1 20 X.if t .in +0.5i X Head X | X | X v X --------- X / \ / \ | | / \ / \ X / \ / \ | 2.1 | / \ / \ X / \ / \ | | / \ / \ X/1.2.1.3\ /1.3.1.1\ | | /1.2.2.2\ /1.2.2.1.1.1\ X--------- --------- --------- --------- ------------- X ^ ^ | ^ ^ X | | | | | X | | v | | X / \ | --------- / \ | X / \ | \ 1.3 / / \ | X / \ ---------\ / / \----------- X/1.2.1.1\ \ / /1.2.2.1\ X--------- \ / --------- X ^ | ^ X | | | X | v | X | --------- | X | \ 1.2 / | X ----------------------\ /--------- X \ / X \ / X | X | X v X --------- X \ 1.1 / X \ / X \ / X \ / X X X.if t .in -0.5i X.cs 1 X.ec X.ce XFig. 1: A revision tree X.fi X.PP X.SH IDENTIFICATION X.de VL X\\$2 X.. XAuthor: Walter F. Tichy, XPurdue University, West Lafayette, IN, 47907. X.sp 0 XRevision Number: X.VL $Revision: 1.2 $ X; Release Date: X.VL $Date: 89/05/02 11:16:56 $ X\&. X.sp 0 XCopyright \(co 1982, 1988, 1989 by Walter F. Tichy. X.SH SEE ALSO Xci(1L), co(1L), ident(1L), rcs(1L), rcsdiff(1L), rcsmerge(1L), rlog(1L), X.br XWalter F. Tichy, "Design, Implementation, and Evaluation of a Revision Control XSystem," in \fIProceedings of the 6th International Conference on Software XEngineering\fR, IEEE, Tokyo, Sept. 1982. SHAR_EOF echo "extracting doc/rcsfreeze.1l" sed 's/^X//' << \SHAR_EOF > doc/rcsfreeze.1l X.TH RCSFREEZE 1L "" "Purdue University" X.SH NAME Xrcsfreeze \- freeze a configuration of sources checked in under RCS X.SH SYNOPSIS X.B rcsfreeze X[symbolic revision name] X.SH DESCRIPTION XThe X.I rcsfreeze Xcommand has the purpose of assigning a symbolic revision Xnumber to a set of RCS files, which form a valid configuration. X.PP XThe idea is to run X.I rcsfreeze Xeach time a new version is checked Xin. A unique symbolic revision number (\c X.BI C_ number, Xwhere X.I number Xis increased each time rcsfreeze is run) is then assigned to the most Xrecent revision of each RCS file of the main trunk. X.PP XIf the command is invoked with an argument, then this Xargument is used as the symbolic name to freeze a configuration. XThe unique identifier is still generated Xand is listed in the log file but it will not appear as Xpart of the symbolic revision name in the actual RCS files. X.PP XA log message is requested from the user which is saved for future Xreferences. X.PP XThe shell script works only on all RCS files at one time. XIt is important that all changed files are checked in (there are Xno precautions against any error in this respect). Run X.IR rcsclean (1L) Xfirst and see whether any sources remain in the current directory. X.SH FILES X.TP 2.5i X[RCS/]rcsfreeze.version Xfor the version number X.TP X[RCS/]rscfreeze.log Xfor the log messages, most recent log message first. X.SH AUTHOR XStephan v. Bechtolsheim X.SH "SEE ALSO" Xrcs(1L), rlog(1L), rcsclean(1L) X.SH BUGS XThe program does not check whether there are any sources checked out Xand modified. SHAR_EOF echo "extracting doc/rcsintro.1l" sed 's/^X//' << \SHAR_EOF > doc/rcsintro.1l X.TH RCSINTRO 1L "May 11, 1983" "Purdue University" X.SH NAME Xrcsintro - introduction to RCS commands X.SH DESCRIPTION XThe Revision Control System (RCS) manages multiple revisions of text files. XRCS automates the storing, retrieval, logging, identification, and merging Xof revisions. RCS is useful for text that is revised frequently, for example Xprograms, documentation, graphics, papers, form letters, etc. X.PP XThe basic user interface is extremely simple. The novice only needs Xto learn two commands: X.IR ci (1L) Xand X.IR co (1L). X\fICi\fR, short for "check in", deposits the contents of a Xtext file into an archival file called an RCS file. An RCS file Xcontains all revisions of a particular text file. X\fICo\fR, short for "check out", retrieves revisions from an RCS file. X.PP X.B "Functions of RCS" X.PP X.IP \(bu XStorage and retrieval of multiple revisions of text. RCS saves all old Xrevisions in a space efficient way. XChanges no longer destroy the original, because the Xprevious revisions remain accessible. Revisions can be retrieved according to Xranges of revision numbers, symbolic names, dates, authors, and Xstates. X.IP \(bu XMaintenance of a complete history of changes. RCS logs all changes automatically. XBesides the text of each revision, RCS stores the author, the date and time of Xcheck-in, and a log message summarizing the change. XThe logging makes it easy to find out Xwhat happened to a module, without having to compare Xsource listings or having to track down colleagues. X.IP \(bu XResolution of access conflicts. When two or more programmers wish to Xmodify the same revision, RCS alerts the programmers and prevents one Xmodification from corrupting the other. X.IP \(bu XMaintenance of a tree of Revisions. RCS can maintain separate lines of development Xfor each module. It stores a tree structure that represents the Xancestral relationships among revisions. X.IP \(bu XMerging of revisions and resolution of conflicts. XTwo separate lines of development of a module can be coalesced by merging. XIf the revisions to be merged affect the same sections of code, RCS alerts the Xuser about the overlapping changes. X.IP \(bu XRelease and configuration control. Revisions can be assigned symbolic names Xand marked as released, stable, experimental, etc. XWith these facilities, configurations of modules can be Xdescribed simply and directly. X.IP \(bu XAutomatic identification of each revision with name, revision number, Xcreation time, author, etc. XThe identification is like a stamp that can be embedded at an appropriate place Xin the text of a revision. XThe identification makes it simple to determine which Xrevisions of which modules make up a given configuration. X.IP \(bu XMinimization of secondary storage. RCS needs little extra space for Xthe revisions (only the differences). If intermediate revisions are Xdeleted, the corresponding deltas are compressed accordingly. X.sp X.PP X.B "Getting Started with RCS" X.PP XSuppose you have a file f.c that you wish to put under control of RCS. XInvoke the check-in command X.PP X.ti 1.5i X.B "ci f.c X.PP XThis command creates the RCS file f.c,v, stores f.c into it as revision 1.1, and Xdeletes f.c. It also asks you for a description. The description Xshould be a synopsis of the contents of the file. All later check-in Xcommands will ask you for a log entry, which should summarize the Xchanges that you made. X.PP XFiles ending in ,v are called RCS files (`v' stands for `versions'), Xthe others are called working files. XTo get back the working file f.c in the previous example, use the check-out Xcommand X.PP X.ti 1.5i X.B "co f.c X.PP XThis command extracts the latest revision from f.c,v and writes Xit into f.c. You can now edit f.c and check it back in by invoking X.PP X.ti 1.5i X.B "ci f.c X.PP X\fICi\fR increments the revision number properly. XIf \fIci\fR complains with the message X.PP X ci error: no lock set by <your login> X.PP Xthen your system administrator has decided to create all RCS files Xwith the locking attribute set to `strict'. In this case, you should Xhave locked the revision during the previous check-out. Your last check-out Xshould have been X.PP X.ti 1.5i X.B "co \-l f.c X.PP XOf course, it is too late now to do the check-out with locking, because you Xprobably modified f.c already, and a second check-out would Xoverwrite your modifications. Instead, invoke X.PP X.ti 1.5i X.B "rcs \-l f.c X.PP XThis command will lock the latest revision for you, unless somebody Xelse got ahead of you already. In this case, you'll have to negotiate with Xthat person. X.PP XLocking assures that you, and only you, can check in the next update, and Xavoids nasty problems if several people work on the same file. XEven if a revision is locked, it can still be checked out for Xreading, compiling, etc. All that locking Xprevents is a CHECK-IN by anybody but the locker. X.PP XIf your RCS file is private, i.e., if you are the only person who is going Xto deposit revisions into it, strict locking is not needed and you Xcan turn it off. XIf strict locking is turned off, Xthe owner of the RCS file need not have a lock for check-in; all others Xstill do. Turning strict locking off and on is done with the commands X.PP X.ti 1.5i X.BR "rcs \-U f.c" " and " "rcs \-L f.c" X.PP XIf you don't want to clutter your working directory with RCS files, create Xa subdirectory called RCS in your working directory, and move all your RCS Xfiles there. RCS commands will look first into that directory to find Xneeded files. All the commands discussed above will still work, without any Xmodification. X(Actually, pairs of RCS and working files can be specified in 3 ways: X(a) both are given, (b) only the working file is given, (c) only the XRCS file is given. Both RCS and working files may have arbitrary path prefixes; XRCS commands pair them up intelligently). X.PP XTo avoid the deletion of the working file during check-in (in case you want to Xcontinue editing), invoke X.PP X.ti 1.5i X.BR "ci \-l f.c" " or " "ci \-u f.c" X.PP XThese commands check in f.c as usual, but perform an implicit Xcheck-out. The first form also locks the checked in revision, the second one Xdoesn't. Thus, these options save you one check-out operation. XThe first form is useful if locking is strict, the second one if not strict. XBoth update the identification markers in your working file (see below). X.PP XYou can give \fIci\fR the number you want assigned to a checked in Xrevision. Assume all your revisions were numbered 1.1, 1.2, 1.3, etc., Xand you would like to start release 2. XThe command X.PP X.ti 1.5i X.BR "ci \-r2 f.c" " or " "ci \-r2.1 f.c" X.PP Xassigns the number 2.1 to the new revision. XFrom then on, \fIci\fR will number the subsequent revisions Xwith 2.2, 2.3, etc. The corresponding \fIco\fR commands X.PP X.ti 1.5i X.BR "co \-r2 f.c" " and " "co \-r2.1 f.c" X.PP Xretrieve the latest revision numbered 2.x and the revision 2.1, Xrespectively. \fICo\fR without a revision number selects Xthe latest revision on the "trunk", i.e., the highest Xrevision with a number consisting of 2 fields. Numbers with more than 2 Xfields are needed for branches. XFor example, to start a branch at revision 1.3, invoke X.PP X.ti 1.5i X.B "ci \-r1.3.1 f.c X.PP XThis command starts a branch numbered 1 at revision 1.3, and assigns Xthe number 1.3.1.1 to the new revision. For more information about Xbranches, see \fIrcsfile\fR(5L). X.sp X.PP X.B "Automatic Identification" X.PP XRCS can put special strings for identification into your source and object Xcode. To obtain such identification, place the marker X.PP X.ti 1.5i X$\&Header$ X.PP Xinto your text, for instance inside a comment. XRCS will replace this marker with a string of the form X.PP X.ti 1.5i X$\&Header: filename revision_number date time author state $ X.PP XWith such a marker on the first page of each module, you can Xalways see with which revision you are working. XRCS keeps the markers up to date automatically. XTo propagate the markers into your object code, simply put Xthem into literal character strings. In C, this is done as follows: X.PP X.ti 1.5i Xstatic char rcsid[] = "$\&Header$"; X.PP XThe command \fIident\fR extracts such markers from any file, even object code Xand dumps. XThus, \fIident\fR lets you find out Xwhich revisions of which modules were used in a given program. X.PP XYou may also find it useful to put the marker $\&Log$ Xinto your text, inside a comment. This marker accumulates Xthe log messages that are requested during check-in. XThus, you can maintain the complete history of your file directly inside it. XThere are several additional identification markers; see \fIco\fR(1L) for Xdetails. X.SH IDENTIFICATION X.de VL X\\$2 X.. XAuthor: Walter F. Tichy, XPurdue University, West Lafayette, IN, 47907. X.br XRevision Number: X.VL $Revision: 1.2 $ X; Release Date: X.VL $Date: 89/05/02 11:17:54 $ X\&. X.br XCopyright \(co 1982, 1988, 1989 by Walter F. Tichy. X.SH SEE ALSO Xci(1L), co(1L), ident(1L), merge(1L), rcs(1L), rcsdiff(1L), rcsmerge(1L), rlog(1L), Xrcsfile(5L), X.br XWalter F. Tichy, "Design, Implementation, and Evaluation of a Revision Control XSystem," in \fIProceedings of the 6th International Conference on Software XEngineering\fR, IEEE, Tokyo, Sept. 1982. SHAR_EOF echo "extracting doc/rcsmerge.1l" sed 's/^X//' << \SHAR_EOF > doc/rcsmerge.1l X.TH RCSMERGE 1L "" "Purdue University" X.SH NAME Xrcsmerge \- merge RCS revisions X.SH SYNOPSIS X\fBrcsmerge\fR \fB\-r\fIrev1\fR [ \fB\-r\fIrev2\fR ] [ \fB\-p\fR ] file X.SH DESCRIPTION X.I Rcsmerge Xincorporates the changes between \fIrev1\fR and \fIrev2\fR of an XRCS file into the corresponding working file. If \fB\-p\fR is given, the result Xis printed on the standard output, otherwise the result overwrites the Xworking file. X.PP XA file name ending in ',v' is an RCS file name, otherwise a Xworking file name. \fIMerge\fR derives the working file name from the RCS Xfile name and vice versa, as explained in X.IR co (1L). XA pair consisting Xof both an RCS and a working file name may also be specified. X.PP X\fIRev1\fR may not be omitted. If \fIrev2\fR is omitted, the latest Xrevision on the default branch (normally the highest branch on the trunk) Xis assumed. XBoth \fIrev1\fR and \fIrev2\fR may be given numerically or symbolically. X.PP X\fIRcsmerge\fR prints a warning if there are overlaps, and delimits Xthe overlapping regions as explained in \fIco \-j\fR. XThe command is useful for incorporating changes into a checked-out revision. X.SH EXAMPLES XSuppose you have released revision 2.8 of f.c. Assume Xfurthermore that you just completed revision 3.4, when you receive Xupdates to release 2.8 from someone else. XTo combine the updates to 2.8 and your changes between 2.8 and 3.4, Xput the updates to 2.8 into file f.c and execute X.sp X.B " rcsmerge \-p \-r2.8 \-r3.4 f.c >f.merged.c X.sp XThen examine f.merged.c. XAlternatively, if you want to save the updates to 2.8 in the RCS file, Xcheck them in as revision 2.8.1.1 and execute \fIco \-j\fR: X.sp X.B " ci \-r2.8.1.1 f.c X.br X.B " co \-r3.4 \-j2.8:2.8.1.1 f.c X.sp XAs another example, the following command undoes the changes Xbetween revision 2.4 and 2.8 in your currently checked out revision Xin f.c. X.sp X.B " rcsmerge \-r2.8 \-r2.4 f.c X.sp XNote the order of the arguments, and that f.c will be Xoverwritten. X.SH IDENTIFICATION X.de VL X\\$2 X.. XAuthor: Walter F. Tichy, XPurdue University, West Lafayette, IN, 47907. X.sp 0 XRevision Number: X.VL $Revision: 1.2 $ X; Release Date: X.VL $Date: 89/05/02 11:18:34 $ X\&. X.sp 0 XCopyright \(co 1982, 1988, 1989 by Walter F. Tichy. X.SH SEE ALSO Xci(1L), co(1L), merge(1L), ident(1L), rcs(1L), rcsdiff(1L), rlog(1L), rcsfile(5L), X.br XWalter F. Tichy, "Design, Implementation, and Evaluation of a Revision Control XSystem," in \fIProceedings of the 6th International Conference on Software XEngineering\fR, IEEE, Tokyo, Sept. 1982. X.SH BUGS X\fIRcsmerge\fR does not work on Xfiles that contain lines with a single `.'. SHAR_EOF echo "extracting doc/rlog.1l" sed 's/^X//' << \SHAR_EOF > doc/rlog.1l X.TH RLOG 1L "" "Purdue University" X.SH NAME Xrlog \- print log messages and other information about RCS files X.SH SYNOPSIS X.B rlog X[ options ] Xfile ... X.SH DESCRIPTION X.I Rlog Xprints information about RCS files. XFiles ending in `,v' are RCS files, all others are working files. If Xa working file is given, \fIrlog\fR tries to find the corresponding XRCS file first in directory ./RCS and then in the current directory, Xas explained in X.IR co (1L). X.PP X\fIRlog\fR prints the following information for each XRCS file: RCS file name, working file name, head (i.e., the number Xof the latest revision on the trunk), default branch, access list, locks, Xsymbolic names, suffix, total number of revisions, Xnumber of revisions selected for printing, and Xdescriptive text. This is followed by entries for the selected revisions in Xreverse chronological order for each branch. For each revision, X\fIrlog\fR prints revision number, author, date/time, state, number of Xlines added/deleted (with respect to the previous revision), Xlocker of the revision (if any), and log message. XWithout options, \fIrlog\fR prints complete information. XThe options below restrict this output. X.TP 10 X.B \-L Xignores RCS files that have no locks set; convenient in combination with X\fB\-R\fR, \fB\-h\fR, or \fB\-l\fR. X.TP 10 X.B \-R Xonly prints the name of the RCS file; convenient for translating a Xworking file name into an RCS file name. X.TP 10 X.B \-h Xprints only RCS file name, working file name, head, Xdefault branch, access list, locks, Xsymbolic names, and suffix. X.TP 10 X.B \-t Xprints the same as \fB\-h\fR, plus the descriptive text. X.TP 10 X.B \-b Xprints information about the revisions on the default branch (normally Xthe highest branch on the trunk). X.TP 10 X.BI \-d "dates" Xprints information about revisions with a checkin date/time in the ranges given by Xthe semicolon-separated list of \fIdates\fR. XA range of the form \fId1<d2\fR or \fId2>d1\fR Xselects the revisions that were deposited between X\fId1\fR and \fId2\fR, (inclusive). XA range of the form \fI<d\fR or \fId>\fR selects Xall revisions dated X\fId\fR or earlier. XA range of the form \fId<\fR or \fI>d\fR selects Xall revisions dated \fId\fR or later. XA range of the form \fId\fR selects the single, latest revision dated \fId\fR or Xearlier. XThe date/time strings \fId, d1, \fRand \fId2\fR Xare in the free format explained in X.IR co (1L). XQuoting is normally necessary, especially for \fI<\fR and \fI>\fR. Note that the separator is Xa semicolon. X.TP 10 X.B \-l\fR[\fIlockers\fR] Xprints information about locked revisions. XIf the comma-separated list \fIlockers\fR of login names is given, Xonly the revisions locked by the given login names are printed. XIf the list is omitted, all locked revisions are printed. X.TP 10 X.BI \-r "revisions" Xprints information about revisions given in the comma-separated list X\fIrevisions\fR of revisions and ranges. A range \fIrev1-rev2\fR means revisions X\fIrev1\fR to \fIrev2\fR on the same branch, \fI-rev\fR means revisions Xfrom the beginning of the branch up to and including \fIrev\fR, Xand \fIrev-\fR means revisions starting with \fIrev\fR to the end of the Xbranch containing \fIrev\fR. An argument that is a branch means all Xrevisions on that branch. A range of branches means all revisions Xon the branches in that range. X.TP 10 X.BI \-s "states" Xprints information about revisions whose state attributes match one of the Xstates given in the comma-separated list \fIstates\fR. X.TP 10 X.B \-w\fR[\fIlogins\fR] Xprints information about revisions checked in by users with Xlogin names appearing in the comma-separated list \fIlogins\fR. XIf \fIlogins\fR is omitted, the user's login is assumed. X.PP X\fIRlog\fR prints the intersection of the revisions selected with Xthe options \fB\-d\fR, \fB\-l\fR, \fB\-s\fR, \fB\-w\fR, intersected Xwith the union of the revisions selected by \fB\-b\fR and \fB\-r\fR. X.SH EXAMPLES X.nf X.sp X rlog \-L \-R RCS/*,v X rlog \-L \-h RCS/*,v X rlog \-L \-l RCS/*,v X rlog RCS/*,v X.sp X.fi XThe first command prints the names of all RCS files in the subdirectory `RCS' Xwhich have locks. The second command prints the headers of those files, Xand the third prints the headers plus the log messages of the locked revisions. XThe last command prints complete information. X.SH DIAGNOSTICS XThe exit status always refers to the last RCS file operated upon, Xand is 0 if the operation was successful, 1 otherwise. X.SH IDENTIFICATION X.de VL X\\$2 X.. XAuthor: Walter F. Tichy, XPurdue University, West Lafayette, IN, 47907. X.sp 0 XRevision Number: X.VL $Revision: 1.3 $ X; Release Date: X.VL $Date: 89/05/02 11:19:20 $ X\&. X.sp 0 XCopyright \(co 1982, 1988, 1989 by Walter F. Tichy. X.SH SEE ALSO Xci(1L), co(1L), ident(1L), rcs(1L), rcsdiff(1L), rcsintro(1L), rcsmerge(1L), Xrcsfile(5L) X.br XWalter F. Tichy, "Design, Implementation, and Evaluation of a Revision Control XSystem," in \fIProceedings of the 6th International Conference on Software XEngineering\fR, IEEE, Tokyo, Sept. 1982. SHAR_EOF if `test ! -d ked` then mkdir ked echo "mkdir ked" fi echo "extracting ked/ked.c,v" sed 's/^X//' << \SHAR_EOF > ked/ked.c,v Xhead 1.5; Xbranch ; Xaccess ; Xsymbols ; Xlocks ; strict; Xcomment @ * @; X X X1.5 Xdate 89.09.17.10.58.39; author rick; state Exp; Xbranches ; Xnext 1.4; X X1.4 Xdate 89.09.04.18.52.56; author rick; state Exp; Xbranches ; Xnext 1.3; X X1.3 Xdate 89.09.01.11.02.22; author rick; state Exp; Xbranches ; Xnext 1.2; X X1.2 Xdate 89.08.27.19.01.04; author rick; state Exp; Xbranches ; Xnext 1.1; X X1.1 Xdate 89.08.27.17.44.11; author rick; state Exp; Xbranches ; Xnext ; X X Xdesc X@Initial checkin X@ X X X1.5 Xlog X@Cleanup so no errors when compiled with Lattice C X@ Xtext X@/* ed - standard editor Authors: Brian Beattie, Kees Bot, and others */ X X/* Modifications for Amiga made by Rick Schaeffer */ X X/* X * Copyright 1987 Brian Beattie Rights Reserved. X * X * Permission to copy and/or distribute granted under the X * following conditions: X * X * 1). No charge may be made other than reasonable charges X * for reproduction. X * X * 2). This notice must remain intact. X * X * 3). No further restrictions may be added. X * X */ X X/* This program used to be in many little pieces, with this makefile: X.SUFFIXES: .c .s X XCFLAGS = -F X XOBJS = append.s catsub.s ckglob.s deflt.s del.s docmd.s doglob.s\ X doprnt.s doread.s dowrite.s ed.s egets.s find.s getfn.s getlst.s\ X getnum.s getone.s getptr.s getrhs.s gettxt.s ins.s join.s maksub.s\ X move.s optpat.s set.s setbuf.s subst.s getpat.s matchs.s amatch.s\ X unmkpat.s omatch.s makepat.s bitmap.s dodash.s esc.s system.s X Xed: $(OBJS) X cc -T. -i -o ed $(OBJS) X*/ X X#include <stdio.h> X#include <ios1.h> X/****************************/ X X/* tools.h */ Xstatic char tools_h[] = X"$Header: Rodime:ricks/rcs2/src/ked/ked.c,v 1.4 89/09/04 18:52:56 rick Exp Locker: rick $"; X/* X * #defines for non-printing ASCII characters X */ X X#define NUL 0x00 /* ^@@ */ X#define EOS 0x00 /* end of string */ X#define SOH 0x01 /* ^A */ X#define STX 0x02 /* ^B */ X#define ETX 0x03 /* ^C */ X#define EOT 0x04 /* ^D */ X#define ENQ 0x05 /* ^E */ X#define ACK 0x06 /* ^F */ X#define BEL 0x07 /* ^G */ X#define BS 0x08 /* ^H */ X#define HT 0x09 /* ^I */ X#define LF 0x0a /* ^J */ X#define NL '\n' X#define VT 0x0b /* ^K */ X#define FF 0x0c /* ^L */ X#define CR 0x0d /* ^M */ X#define SO 0x0e /* ^N */ X#define SI 0x0f /* ^O */ X#define DLE 0x10 /* ^P */ X#define DC1 0x11 /* ^Q */ X#define DC2 0x12 /* ^R */ X#define DC3 0x13 /* ^S */ X#define DC4 0x14 /* ^T */ X#define NAK 0x15 /* ^U */ X#define SYN 0x16 /* ^V */ X#define ETB 0x17 /* ^W */ X#define CAN 0x18 /* ^X */ X#define EM 0x19 /* ^Y */ X#define SUB 0x1a /* ^Z */ X#define ESC 0x1b /* ^[ */ X#define FS 0x1c /* ^\ */ X#define GS 0x1d /* ^] */ X#define RS 0x1e /* ^^ */ X#define US 0x1f /* ^_ */ X#define SP 0x20 /* space */ X#define DEL 0x7f /* DEL*/ X X X#define TRUE 1 X#define FALSE 0 X#define ERR -2 X X X/* Definitions of meta-characters used in pattern matching X * routines. LITCHAR & NCCL are only used as token identifiers; X * all the others are also both token identifier and actual symbol X * used in the regular expression. X */ X X X#define BOL '^' X#define EOL '$' X#define ANY '.' X#define LITCHAR 'L' X#define ESCAPE '\\' X#define CCL '[' /* Character class: [...] */ X#define CCLEND ']' X#define NEGATE '~' X#define NCCL '!' /* Negative character class [^...] */ X#define CLOSURE '*' X#define OR_SYM '|' X#define DITTO '&' X#define OPEN '(' X#define CLOSE ')' X X/* Largest permitted size for an expanded character class. (i.e. the class X * [a-z] will expand into 26 symbols; [a-z0-9] will expand into 36.) X */ X#define CLS_SIZE 128 X X/* X * Tokens are used to hold pattern templates. (see makepat()) X */ Xtypedef char BITMAP; X Xtypedef struct token { X char tok; X char lchar; X BITMAP *bitmap; X struct token *next; X} TOKEN; X X#define TOKSIZE sizeof (TOKEN) X X/* X * An absolute maximun for strings. X */ X X#define MAXSTR 132 /* Maximum numbers of characters in a line */ X X Xextern char *matchs(); Xextern char *amatch(); Xextern char *in_string(); Xextern TOKEN *getpat(); Xextern int esc(); Xextern char *dodash(); Xextern TOKEN *makepat(); Xextern void unmakepat(); Xextern int insert(); Xextern int delete(); Xextern int isalphanum(); Xextern char *stoupper(); Xextern int pr_tok(); Xextern int pr_line(); Xextern BITMAP *makebitmap(); X X/* macros */ X#define toupper(c) (c>='a'&&c<='z'?c-32:c) X X/* ed.h */ X#define FATAL (ERR-1) Xstruct line { X int l_stat; /* empty, mark */ X struct line *l_prev; X struct line *l_next; X char l_buff[1]; X}; X Xtypedef struct line LINE; X X#define LINFREE 1 /* entry not in use */ X#define LGLOB 2 /* line marked global */ X X#define MAXLINE 256 /* max number of chars per line */ X#define MAXPAT 256 /* max number of chars per replacement pattern */ X#define MAXFNAME 256 /* max file name size */ X Xextern LINE line0; Xextern int curln, lastln, line1, line2, nlines; Xextern int nflg; /* print line number flag */ Xextern int lflg; /* print line in verbose mode */ Xextern int pflg; /* print current line after each command */ Xextern char *inptr; /* tty input buffer */ Xextern char linbuf[], *linptr; /* current line */ Xextern int truncflg; /* truncate long line flag */ Xextern int eightbit; /* save eighth bit */ Xextern int nonascii; /* count of non-ascii chars read */ Xextern int nullchar; /* count of null chars read */ Xextern int truncated; /* count of lines truncated */ Xextern int fchanged; /* file changed */ X X#define nextln(l) ((l)+1 > lastln ? 0 : (l)+1) X#define prevln(l) ((l)-1 < 0 ? lastln : (l)-1) X Xextern char *getfn(); Xextern LINE *getptr(); Xextern char *gettxt(); Xextern char *maksub(); Xextern TOKEN *optpat(); X Xextern char *catsub(); X Xextern char *strcpy(); Xextern int *malloc(); Xextern void putcntl(),prntln(),relink(),clrbuf(),edsetbuf(); X X/* amatch.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X X/* Scans throught the pattern template looking for a match X * with lin. Each element of lin is compared with the template X * until either a mis-match is found or the end of the template X * is reached. In the former case a 0 is returned; in the latter, X * a pointer into lin (pointing to the character following the X * matched pattern) is returned. X * X * "lin" is a pointer to the line being searched. X * "pat" is a pointer to a template made by makepat(). X * "boln" is a pointer into "lin" which points at the X * character at the beginning of the line. X */ X Xchar *paropen[9], *parclose[9]; Xint between, parnum; Xstatic char *match(); X Xchar * Xamatch(lin, pat, boln) Xchar *lin; XTOKEN *pat; Xchar *boln; X{ X X between=0; X parnum=0; X X lin=match(lin, pat, boln); X X if (between) return 0; X X while (parnum<9) { X paropen[parnum] = parclose[parnum] = ""; X parnum++; X } X return lin; X} X Xstatic char * Xmatch(lin, pat, boln) Xchar *lin; XTOKEN *pat; Xchar *boln; X{ X register char *bocl, *rval, *strstart; X X if(pat == 0) X return 0; X X strstart = lin; X X while(pat) X { X if(pat->tok == CLOSURE && pat->next) X { X /* Process a closure: X * first skip over the closure token to the X * object to be repeated. This object can be X * a character class. X */ X X pat = pat->next; X X /* Now match as many occurrences of the X * closure pattern as possible. X */ X bocl = lin; X X while( *lin && omatch(&lin, pat)) X ; X X /* 'Lin' now points to the character that made X * made us fail. Now go on to process the X * rest of the string. A problem here is X * a character following the closure which X * could have been in the closure. X * For example, in the pattern "[a-z]*t" (which X * matches any lower-case word ending in a t), X * the final 't' will be sucked up in the while X * loop. So, if the match fails, we back up a X * notch and try to match the rest of the X * string again, repeating this process X * recursively until we get back to the X * beginning of the closure. The recursion X * goes, at most two levels deep. X */ X X if(pat = pat->next) X { X int savbtwn=between; X int savprnm=parnum; X X while(bocl <= lin) X { X if(rval = match(lin, pat, boln)) X { X /* success */ X return(rval); X } else { X --lin; X between=savbtwn; X parnum=savprnm; X } X } X return (0); /* match failed */ X } X } else X if (pat->tok == OPEN) X { X if (between || parnum>=9) return 0; X paropen[parnum] = lin; X between=1; X pat = pat->next; X } else X if (pat->tok == CLOSE) X { X if (!between) return 0; X parclose[parnum++] = lin; X between=0; X pat = pat->next; X } else X if (omatch(&lin, pat, boln)) X { X pat = pat->next; X } else { X return (0); X } X } X /* Note that omatch() advances lin to point at the next X * character to be matched. Consequently, when we reach X * the end of the template, lin will be pointing at the X * character following the last character matched. The X * exceptions are templates containing only a BOLN or EOLN X * token. In these cases omatch doesn't advance. X * X * A philosophical point should be mentioned here. Is $ X * a position or a character? (i.e. does $ mean the EOL X * character itself or does it mean the character at the end X * of the line.) I decided here to make it mean the former, X * in order to make the behavior of match() consistent. If X * you give match the pattern ^$ (match all lines consisting X * only of an end of line) then, since something has to be X * returned, a pointer to the end of line character itself is X * returned. X */ X X return ((char *)max(strstart , lin)); X} X X/* append.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xappend(line, glob) Xint line, glob; X{ X int stat; X char lin[MAXLINE]; X X if(glob) X return(ERR); X curln = line; X while(1) X { X if(nflg) X printf("%d\t",curln+1); X X if(fgets(lin, MAXLINE, stdin) == NULL) X return( EOF ); X if(lin[0] == '.' && lin[1] == '\n') X return(0); X stat = ins(lin); X if(stat < 0) X return( ERR ); X X } X} X X/* bitmap.c */ X/* X * BITMAP.C - makebitmap, setbit, testbit X * bit-map manipulation routines. X * X * Copyright (c) Allen I. Holub, all rights reserved. This program may X * for copied for personal, non-profit use only. X * X */ X X#ifdef DEBUG X/* #include <stdio.h> */ X#endif X X/* #include "tools.h" */ X X XBITMAP *makebitmap( size ) Xunsigned size; X{ X /* Make a bit map with "size" bits. The first entry in X * the map is an "unsigned int" representing the maximum X * bit. The map itself is concatenated to this integer. X * Return a pointer to a map on success, 0 if there's X * not enough memory. X */ X X unsigned *map, numbytes; X X numbytes = (size >> 3) + ((size & 0x07) ? 1 : 0 ); X X#ifdef DEBUG X printf("Making a %d bit map (%d bytes required)\n", size, numbytes); X#endif X X if( map = (unsigned *) malloc( numbytes + sizeof(unsigned) )) X *map = size; X X return ((BITMAP *)map); X} X Xsetbit( c, map, val ) Xunsigned c, val; Xchar *map; X{ X /* Set bit c in the map to val. X * If c > map-size, 0 is returned, else 1 is returned. X */ X X if( c >= *(unsigned *)map ) /* if c >= map size */ X return 0; X X map += sizeof(unsigned); /* skip past size */ X X if( val ) X map[c >> 3] |= 1 << (c & 0x07); X else X map[c >> 3] &= ~(1 << (c & 0x07)); X X return( 1 ); X} X Xtestbit( c, map ) Xunsigned c; Xchar *map; X{ X /* Return 1 if the bit corresponding to c in map is set. X * 0 if it is not. X */ X X if( c >= *(unsigned *)map ) X return 0; X X map += sizeof(unsigned); X X return(map[ c >> 3 ] & (1 << (c & 0x07))); X} X X/* catsub.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xextern char *paropen[9], *parclose[9]; X Xchar * Xcatsub(from, to, sub, new, newend) Xchar *from, *to, *sub, *new, *newend; X{ X char *cp, *cp2; X X for(cp = new; *sub != EOS && cp < newend;) X { X if(*sub == DITTO) X for(cp2 = from; cp2 < to;) X { X *cp++ = *cp2++; X if(cp >= newend) X break; X } X else X if (*sub == ESCAPE) { X sub++; X if ('1' <= *sub && *sub <= '9') { X char *parcl = parclose[*sub - '1']; X X for (cp2 = paropen[*sub - '1']; cp2 < parcl;) X { X *cp++ = *cp2++; X if (cp >= newend) break; X } X } else X *cp++ = *sub; X } else X *cp++ = *sub; X X sub++; X } X X return(cp); X} X X/* ckglob.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xckglob() X{ X TOKEN *glbpat; X char c, delim, *lin; X int num; X LINE *ptr; X X c = *inptr; X X if(c != 'g' && c != 'v') X return(0); X X if (deflt(1, lastln) < 0) X return(ERR); X X delim = *++inptr; X if(delim <= ' ') X return(ERR); X X glbpat = optpat(); X X if(*inptr == delim) X inptr++; X X for (num=1; num<=lastln; num++) X { X ptr = getptr(num); X ptr->l_stat &= ~LGLOB; X if (line1 <= num && num <= line2) { X lin = gettxt(num); X if(matchs(lin, glbpat, 0)) { X if (c=='g') ptr->l_stat |= LGLOB; X } else { X if (c=='v') ptr->l_stat |= LGLOB; X } X } X } X return(1); X} X X/* deflt.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xdeflt(def1, def2) Xint def1, def2; X{ X if(nlines == 0) X { X line1 = def1; X line2 = def2; X } X if(line1 > line2 || line1 <= 0) X return (ERR); X} X X/* del.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xdel(from, to) Xint from, to; X{ X LINE *first, *last, *next, *tmp; X X if(from < 1) X from = 1; X first = getptr(prevln(from)); X last = getptr(nextln(to)); X next = first->l_next; X while(next != last && next != &line0) X { X tmp = next->l_next; X free(next); X next = tmp; X } X relink(first, last, first, last); X lastln -= (to - from)+1; X curln = prevln(from); X return(1); X} X X/* docmd.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xchar fname[MAXFNAME]; Xint fchanged; Xextern int nofname; Xextern int prompt; Xextern int mark[]; X Xdocmd(glob) Xint glob; X{ X static char rhs[MAXPAT]; X TOKEN *subpat; X int c, err, line3; X int apflg, pflag, gflag; X int nchng; X char *fptr; X X pflag = FALSE; X while(*inptr == SP && *inptr == HT) X inptr++; X X c = *inptr++; X X switch(c) X { X case NL: /* print next line */ X if(nlines == 0) X { X if ((line2 = nextln(curln))==0) X return(ERR); X } X curln = line2; X return (1); X break; X X case '=': /* print current line number */ X printf("%d\n",line2); X break; X X case 'a': /* append lines */ X if(*inptr != NL || nlines > 1) X return(ERR); X X if(append(line1, glob) < 0) X return(ERR);; X fchanged = TRUE; X break; X X case 'c': /* changed lines */ X if(*inptr != NL) X return(ERR); X X if(deflt(curln, curln) < 0) X return(ERR); X X if(del(line1, line2) < 0) X return(ERR); X if(append(curln, glob) < 0) X return(ERR); X fchanged = TRUE; X break; X X case 'd': /* delete lines */ X if(*inptr != NL) X return(ERR); X X if(deflt(curln, curln) < 0) X return(ERR); X X if(del(line1, line2) < 0) X return(ERR); X if(nextln(curln) != 0) X curln = nextln(curln); X fchanged = TRUE; X break; X X case 'e': /* edit new file with change check */ X if(nlines > 0) X return(ERR); X if(fchanged) { X fchanged = FALSE; X return(ERR); X } X /*FALL THROUGH*/ X case 'E': /* edit new file no check */ X if(nlines > 0) X return(ERR); X X if(*inptr != ' ' && *inptr != HT && *inptr != NL) X return(ERR); X X if((fptr = getfn()) == NULL) X return(ERR); X X clrbuf(); X if((err = doread(0, fptr)) < 0) X return(err); X X strcpy(fname, fptr); X fchanged = FALSE; X break; X X case 'f': /* set or display current file name */ X if(nlines > 0) X return(ERR); X X if(*inptr != ' ' && *inptr != HT && *inptr != NL) X return(ERR); X X if((fptr = getfn()) == NULL) X return(ERR); X X if (nofname) X printf("%s\n", fname); X else X strcpy(fname, fptr); X break; X X case 'H': X case 'h': /* print last error */ X return(ERR); X break; X X case 'i': /* insert lines */ X if(*inptr != NL || nlines > 1) X return(ERR); X X if(append(prevln(line1), glob) < 0) X return(ERR); X fchanged = TRUE; X break; X X case 'j': /* join lines */ X if (*inptr != NL || deflt(curln, curln+1)<0) X return(ERR); X X if (join(line1, line2) < 0) X return(ERR); X break; X X case 'k': /* mark line address */ X while (*inptr == ' ' || *inptr == HT) inptr++; X X if (*inptr < 'a' || *inptr > 'z') X return ERR; X c= *inptr++; X X if(*inptr != ' ' && *inptr != HT && *inptr != NL) X return(ERR); X X mark[c-'a'] = line1; X break; X X case 'L': /* toggle verbose print */ X lflg = ~lflg; X break; X X case 'l': /* print lines verbose */ X if(*inptr != NL) X return(ERR); X if(deflt(curln,curln) < 0) X return(ERR); X if (dolst(line1,line2) < 0) X return(ERR); X break; X X case 'm': /* move lines */ X if((line3 = getone()) < 0) X return(ERR); X if(deflt(curln,curln) < 0) X return(ERR); X if(move(line3) < 0) X return(ERR); X fchanged = TRUE; X break; X X case 'N': /* toggle print line numbers */ X nflg = ~nflg; X break; X X case 'n': /* print lines with numbers */ X if(*inptr != NL) X return(ERR); X if(deflt(curln,curln) < 0) X return(ERR); X if (donum(line1,line2) < 0) X return(ERR); X break; X X case 'P': /* toggle prompt */ X prompt = ~prompt; X break; X X case 'p': /* print lines */ X if(*inptr != NL) X return(ERR); X if(deflt(curln,curln) < 0) X return(ERR); X if(doprnt(line1,line2) < 0) X return(ERR); X break; X X case 'q': /* quit, check changed */ X if(fchanged) { X fchanged = FALSE; X return(ERR); X } X /*FALL THROUGH*/ X case 'Q': /* quit, no check for change */ X if(*inptr == NL && nlines == 0 && !glob) X return(EOF); X else X return(ERR); X X case 'r': /* read in file */ X if(nlines > 1) X return(ERR); X X if(nlines == 0) X line2 = lastln; X X if(*inptr != ' ' && *inptr != HT && *inptr != NL) X return(ERR); X X if((fptr = getfn()) == NULL) X return(ERR); X X if((err = doread(line2, fptr)) < 0) X return(err); X fchanged = TRUE; X break; X X case 's': /* substitute, set */ X if(*inptr == 'e') X return(set()); X while(*inptr == SP || *inptr == HT) X inptr++; X if((subpat = optpat()) == NULL) X return(ERR); X if((gflag = getrhs(rhs)) < 0) X return(ERR); X if(*inptr == 'p') X pflag++; X if(deflt(curln, curln) < 0) X return(ERR); X if((nchng = subst(subpat, rhs, gflag, pflag)) < 0) X return(ERR); X if(nchng) X fchanged = TRUE; X break; X X case 't': /* copy lines */ X if((line3 = getone()) < 0) X return(ERR); X if(deflt(curln,curln) < 0) X return(ERR); X if(transfer(line3) < 0) X return(ERR); X fchanged = TRUE; X break; X X case 'u': /* undo last command */ X return(ERR); X break; X X case 'W': /* write append */ X case 'w': /* write */ X apflg = (c=='W'); X X if(*inptr != ' ' && *inptr != HT && *inptr != NL) X return(ERR); X X if((fptr = getfn()) == NULL) X return(ERR); X X if(deflt(1, lastln) < 0) X return(ERR); X if(dowrite(line1, line2, fptr, apflg) < 0) X return(ERR); X fchanged = FALSE; X break; X X case 'x': /* write then quit */ X if(*inptr == NL && nlines == 0 && !glob) X { X if((fptr = getfn()) == NULL) X return(ERR); X if(dowrite(1, lastln, fptr, 0) >= 0) X return(EOF); X } X return(ERR); X X case 'z': /* print +21, -21, -11.+10 lines */ X if(deflt(curln,curln) < 0) X return(ERR); X X switch(*inptr) X { X case '-': X if(doprnt(line1-21,line1) < 0) X return(ERR); X break; X X case '.': X if(doprnt(line1-11,line1+10) < 0) X return(ERR); X break; X X case '+': X case '\n': X if(doprnt(line1,line1+21) < 0) X return(ERR); X break; X } X break; X X default: X return(ERR); X } X return (0); X} X Xint dolst(line1, line2) int line1, line2; X{ X int oldlflg=lflg, p; X X lflg=1; X p=doprnt(line1, line2); X lflg=oldlflg; X X return p; X} X Xint donum(line1, line2) int line1, line2; X{ X int oldnflg=nflg, p; X X nflg=1; X p=doprnt(line1, line2); X nflg=oldnflg; X X return p; X} X X/* dodash.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X X/* Expand the set pointed to by *src into dest. X * Stop at delim. Return 0 on error or size of X * character class on success. Update *src to X * point at delim. A set can have one element X * {x} or several elements ( {abcdefghijklmnopqrstuvwxyz} X * and {a-z} are equivalent ). Note that the dash X * notation is expanded as sequential numbers. X * This means (since we are using the ASCII character X * set) that a-Z will contain the entire alphabet X * plus the symbols: [\]^_`. The maximum number of X * characters in a character class is defined by maxccl. X */ Xchar * Xdodash(delim, src, map) X Xint delim; Xchar *src, *map; X{ X X register int first, last; X char *start; X X start = src; X X while( *src && *src != delim ) X { X if( *src != '-') X setbit( esc( &src ), map, 1 ); X X else if( src == start || *(src + 1) == delim ) X setbit( '-', map, 1 ); X else { X src++; X X if( *src < *(src - 2)) X { X first = *src; X last = *(src - 2); X } else { X first = *(src - 2); X last = *src; X } X X while( ++first <= last ) X setbit( first, map, 1); X X } X src++; X } X return( src ); X} X X/* doglob.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xdoglob() X{ X int lin, stat; X char *cmd; X LINE *ptr; X X cmd = inptr; X X while(1) X { X for (lin=1; lin<=lastln; lin++) { X ptr = getptr(lin); X if (ptr->l_stat & LGLOB) break; X } X if (lin>lastln) break; X X ptr->l_stat &= ~LGLOB; X curln = lin; X inptr = cmd; X if((stat = getlst()) < 0) X return(stat); X if((stat = docmd(1)) < 0) X return(stat); X } X return(0); X} X X/* doprnt.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xdoprnt(from, to) Xint from, to; X{ X int i; X X from = from < 1 ? 1 : from; X to = to > lastln ? lastln : to; X X if(to != 0) X { X for(i = from; i <= to; i++) X prntln(gettxt(i), lflg, (nflg ? i : 0)); X curln = to; X } X X return(0); X} X Xvoid prntln(str, vflg, lin) Xchar *str; Xint vflg, lin; X{ X if(lin) X printf("%d\t",lin); X while(*str && *str != NL) X { X if(*str < ' ' || *str >= 0x7f) X { X switch(*str) X { X case '\t': X if(vflg) X putcntl(*str, stdout); X else X putc(*str, stdout); X break; X X case DEL: X putc('^', stdout); X putc('?', stdout); X break; X X default: X putcntl(*str, stdout); X break; X } X } else X putc(*str, stdout); X str++; X } X if(vflg) X putc('$',stdout); X putc('\n', stdout); X} X Xvoid putcntl(c, stream) Xchar c; XFILE *stream; X{ X putc('^', stream); X putc((c&31)|'@@', stream); X} X X/* doread.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xextern int diag; X Xdoread(lin, fname) Xint lin; Xchar *fname; X{ X extern FILE *fopen(); X FILE *fp; X int err; X long bytes; X int lines; X static char str[MAXLINE]; X X err = 0; X nonascii = nullchar = truncated = 0; X X if (diag) printf("\"%s\" ",fname); X if((fp = fopen(fname, "r")) == NULL) X { X printf("file open err\n"); X return( ERR ); X } X curln = lin; X for(lines = 0, bytes = 0;(err = egets(str,MAXLINE,fp)) > 0;) X { X bytes += strlen(str); X if(ins(str) < 0) X { X printf("file insert error\n"); X err++; X break; X } X lines++; X } X fclose(fp); X if(err < 0) X return(err); X if (diag) { X printf("%d lines %d bytes",lines,bytes); X if(nonascii) X printf(" [%d non-ascii]",nonascii); X if(nullchar) X printf(" [%d nul]",nullchar); X if(truncated) X printf(" [%d lines truncated]",truncated); X printf("\n"); X } X return( err ); X} X X/* dowrite.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xdowrite(from, to, fname, apflg) Xint from, to; Xchar *fname; Xint apflg; X{ X extern FILE *fopen(); X FILE *fp; X int lin, err; X int lines, bytes; X char *str; X X err = 0; X X lines = bytes = 0; X if (diag) X printf("\"%s\" ",fname); X X if((fp = fopen(fname,(apflg?"a":"w"))) == NULL) X { X printf("file open error\n"); X return( ERR ); X } X for(lin = from; lin <= to; lin++) X { X str = gettxt(lin); X lines++; X bytes += strlen(str); X if(fputs(str, fp) == EOF) X { X printf("file write error\n"); X err++; X break; X } X } X if (diag) X printf("%d lines %d bytes\n",lines,bytes); X X fclose(fp); X return( err ); X} X X/* ed.c */ X/* X * Copyright 1987 Brian Beattie Rights Reserved. X * X * Permission to copy and/or distribute granted under the X * following conditions: X * X * 1). No charge may be made other than resonable charges X * for reproduction. X * X * 2). This notice must remain intact. X * X * 3). No further restrictions may be added. X * X */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X#include <setjmp.h> Xjmp_buf env; X XLINE line0; Xint curln = 0; Xint lastln = 0; Xchar *inptr; Xstatic char inlin[MAXLINE]; Xint nflg, lflg, pflg, pflag, prompt; Xint line1, line2, nlines; Xextern char fname[]; Xint version = 103; Xint diag=1; X Xvoid intr() X{ X printf("?\n"); X longjmp(env, 1); X} X Xvoid main(argc,argv) Xint argc; Xchar **argv; X{ X int stat, i, doflush; X X edsetbuf(); X doflush=isatty(1); X X if (argc>1 && argv[1][0]=='-' && argv[1][1]==0) { X diag=0; X argc--; X argv++; X } X if(argc > 1) X { X for(i = 1; i < argc; i++) X { X if(doread(0,argv[i])==0) { X curln = 1; X strcpy(fname, argv[i]); X break; X } X } X } X while(1) X { X setjmp(env); X signal(2, intr); X X if (prompt) X { X if (nflg) printf("%d",curln); X printf("*"); X } X X if (doflush) fflush(stdout); X X if (fgets(inlin, sizeof(inlin),stdin) == NULL) X { X break; X } X/* X if(*inlin == '!') X { X for(inptr = inlin; *inptr != NL; inptr++) X ; X *inptr = EOS; X system(inlin+1); X continue; X } X*/ X inptr = inlin; X if(getlst() >= 0) X if((stat = ckglob()) != 0) X { X if(stat >= 0 && (stat = doglob()) >= 0) X { X curln = stat; X continue; X } X } else { X if((stat = docmd(0)) >= 0) X { X if(stat == 1) X doprnt(curln, curln); X continue; X } X } X if(stat == EOF) X { X exit(0); X } X if(stat == FATAL) X { X fputs("FATAL ERROR\n",stderr); X exit(1); X } X printf("?\n"); X } X} X X/* egets.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xint truncflg = 1; /* truncate long line flag */ Xint eightbit = 1; /* save eight bit */ Xint nonascii, nullchar, truncated; Xegets(str,size,stream) Xchar *str; Xint size; XFILE *stream; X{ X int c, count; X char *cp; X X for(count = 0, cp = str; size > count;) X { X c = getc(stream); X if(c == EOF) X { X *cp++ = '\n'; X *cp = EOS; X if(count) X { X printf("[Incomplete last line]\n"); X } X return(count); X } X if(c == NL) X { X *cp++ = c; X *cp = EOS; X return(++count); X } X if(c > 127) X { X if(!eightbit) /* if not saving eighth bit */ X c = c&127; /* strip eigth bit */ X nonascii++; /* count it */ X } X if(c) X { X *cp++ = c; /* not null, keep it */ X count++; X } else X nullchar++; /* count nulls */ X } X str[count-1] = EOS; X if(c != NL) X { X printf("truncating line\n"); X truncated++; X while((c = getc(stream)) != EOF) X if(c == NL) X break; X } X return(count); X} X X/* esc.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X X/* Map escape sequences into their equivalent symbols. Returns the X * correct ASCII character. If no escape prefix is present then s X * is untouched and *s is returned, otherwise **s is advanced to point X * at the escaped character and the translated character is returned. X */ Xesc(s) Xchar **s; X{ X register int rval; X X X if (**s != ESCAPE) X { X rval = **s; X } else { X (*s)++; X X switch(toupper(**s)) X { X case '\000': X rval = ESCAPE; break; X case 'S': X rval = ' '; break; X case 'N': X rval = '\n'; break; X case 'T': X rval = '\t'; break; X case 'B': X rval = '\b'; break; X case 'R': X rval = '\r'; break; X default: X rval = **s; break; X } X } X X return (rval); X} X X/* find.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xfind(pat, dir) XTOKEN *pat; Xint dir; X{ X int i, num; X char *lin; X X num=curln; X for(i=0; i<lastln; i++) X { X lin = gettxt(num); X if(matchs(lin, pat, 0)) X { X return(num); X } X num = (dir ? nextln(num) : prevln(num)); X } X return ( ERR ); X} X X/* getfn.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xextern char fname[MAXFNAME]; Xint nofname; X Xchar * Xgetfn() X{ X static char file[256]; X char *cp; X X if(*inptr == NL) X { X nofname=TRUE; X strcpy(file, fname); X } else { X nofname=FALSE; X while(*inptr == SP || *inptr == HT) X inptr++; X X cp = file; X while(*inptr && *inptr != NL && *inptr != SP && *inptr != HT) X { X *cp++ = *inptr++; X } X *cp = '\0'; X X if(strlen(file) == 0) X { X printf("bad file name\n"); X return( NULL ); X } X } X X if(strlen(file) == 0) X { X printf("no file name\n"); X return(NULL); X } X return( file ); X} X X/* getlst.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xgetlst() X{ X int num; X X line2 = 0; X for(nlines = 0; (num = getone()) >= 0;) X { X line1 = line2; X line2 = num; X nlines++; X if(*inptr != ',' && *inptr != ';') X break; X if(*inptr == ';') X curln = num; X inptr++; X } X nlines = min(nlines, 2); X if(nlines == 0) X line2 = curln; X if(nlines <= 1) X line1 = line2; X X if(num == ERR) X return(num); X else X return(nlines); X} X X/* getnum.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xint mark['z'-'a'+1]; X Xgetnum(first) int first; X{ X TOKEN *srchpat; X int num; X char c; X X while(*inptr == SP || *inptr == HT) X inptr++; X X if(*inptr >= '0' && *inptr <= '9') /* line number */ X { X for(num = 0; *inptr >= '0' && *inptr <= '9';) X { X num = (num * 10) + *inptr - '0'; X inptr++; X } X return num; X } X X switch(c = *inptr) X { X case '.': X inptr++; X return (curln); X X case '$': X inptr++; X return (lastln); X X case '/': X case '?': X srchpat = optpat(); X if(*inptr == c) X inptr++; X return(find(srchpat,c == '/'?1:0)); X X case '-': X case '+': X return(first ? curln : 1); X X case '\'': X inptr++; X if (*inptr < 'a' || *inptr > 'z') X return(EOF); X X return mark[ *inptr++ - 'a' ]; X X default: X return ( first ? EOF : 1 ); /* unknown address */ X } X} X X/* getone.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X X#define FIRST 1 X#define NOTFIRST 0 X Xgetone() X{ X int c, i, num; X X if((num = getnum(FIRST)) >= 0) X { X while(1) X { X while(*inptr == SP || *inptr == HT) X inptr++; X X if(*inptr != '+' && *inptr != '-') X break; X c = *inptr++; X X if((i = getnum(NOTFIRST)) < 0) X return ( i ); X X if(c == '+') X { X num += i; X } else { X num -= i; X } X } X } X return ( num>lastln ? ERR : num ); X} X X/* getpat.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X X/* Translate arg into a TOKEN string */ XTOKEN * Xgetpat (arg) Xchar *arg; X{ X X return (makepat(arg, '\000')); X} X X/* getptr.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X XLINE * Xgetptr(num) Xint num; X{ X LINE *ptr; X int j; X X if (2*num>lastln && num<=lastln) { /* high line numbers */ X ptr = line0.l_prev; X for (j = lastln; j>num; j--) X ptr = ptr->l_prev; X } else { /* low line numbers */ X ptr = &line0; X for(j = 0; j < num; j++) X ptr = ptr->l_next; X } X return(ptr); X} X X/* getrhs.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xgetrhs(sub) Xchar *sub; X{ X if(inptr[0] == NL || inptr[1] == NL) /* check for eol */ X return( ERR ); X X if(maksub(sub, MAXPAT) == NULL) X return( ERR ); X X inptr++; /* skip over delimter */ X while(*inptr == SP || *inptr == HT) X inptr++; X if(*inptr == 'g') X { X inptr++; X return( 1 ); X } X return( 0 ); X} X X/* gettxt.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xchar * Xgettxt(num) Xint num; X{ X LINE *lin; X static char txtbuf[MAXLINE]; X X lin = getptr(num); X strcpy(txtbuf,lin->l_buff); X strcat(txtbuf,"\n"); X return(txtbuf); X} X X/* ins.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xins(str) Xchar *str; X{ X char buf[MAXLINE], *cp; X LINE *new, *cur, *nxt; X X cp = buf; X while(1) X { X if((*cp = *str++) == NL) X *cp = EOS; X if(*cp) X { X cp++; X continue; X } X if((new = (LINE *)malloc(sizeof(LINE)+strlen(buf))) == NULL) X return( ERR ); /* no memory */ X X new->l_stat=0; X strcpy(new->l_buff,buf); /* build new line */ X cur = getptr(curln); /* get current line */ X nxt = getptr(nextln(curln)); /* get next line */ X relink(cur, new, new, nxt); /* add to linked list */ X relink(new, nxt, cur, new); X lastln++; X curln++; X X if(*str == EOS) /* end of line ? */ X return( 1 ); X X cp = buf; X } X} X X/* join.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xextern int fchanged; X Xjoin(first, last) Xint first, last; X{ X char buf[MAXLINE]; X char *cp=buf, *str; X int num; X X if (first<=0 || first>last || last>lastln) X return(ERR); X if (first==last) { X curln=first; X return 0; X } X for (num=first; num<=last; num++) { X str=gettxt(num); X X while (*str!=NL && cp<buf+MAXLINE-1) *cp++ = *str++; X X if (cp==buf+MAXLINE-1) { X printf("line too long\n"); X return(ERR); X } X } X *cp++ = NL; X *cp = EOS; X del(first, last); X curln=first-1; X ins(buf); X fchanged = TRUE; X return 0; X} X X/* makepat.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X X/* X * Make a pattern template from the strinng pointed to by arg. Stop X * when delim or '\000' or '\n' is found in arg. Return a pointer to X * the pattern template. X * X * The pattern template used here are somewhat different than those X * used in the "Software Tools" book; each token is a structure of X * the form TOKEN (see tools.h). A token consists of an identifier, X * a pointer to a string, a literal character and a pointer to another X * token. This last is 0 if there is no subsequent token. X * X * The one strangeness here is caused (again) by CLOSURE which has X * to be put in front of the previous token. To make this insertion a X * little easier, the 'next' field of the last to point at the chain X * (the one pointed to by 'tail) is made to point at the previous node. X * When we are finished, tail->next is set to 0. X */ XTOKEN * Xmakepat(arg, delim) Xchar *arg; Xint delim; X{ X TOKEN *head, *tail, *ntok; X int error; X X /* X * Check for characters that aren't legal at the beginning of X * a template. X */ X X if (*arg=='\0' || *arg==delim || *arg=='\n' || *arg==CLOSURE) X return(0); X X error = 0; X tail = head = NULL; X X while (*arg && *arg != delim && *arg != '\n' && !error) X { X ntok = (TOKEN *)malloc(TOKSIZE); X ntok->lchar = '\000'; X ntok->next = 0; X X switch(*arg) X { X case ANY: X ntok->tok = ANY; X break; X X case BOL: X if (head == 0) /* then this is the first symbol */ X ntok->tok = BOL; X else X ntok->tok = LITCHAR; X ntok->lchar = BOL; X break; X X case EOL: X if(*(arg+1) == delim || *(arg+1) == '\000' || X *(arg+1) == '\n') X { X ntok->tok = EOL; X } else { X ntok->tok = LITCHAR; X ntok->lchar = EOL; X } X break; X X case CLOSURE: X if (head != 0) X { X switch (tail->tok) X { X case BOL: X case EOL: X case CLOSURE: X return (0); X X default: X ntok->tok = CLOSURE; X } X } X break; X X case CCL: X X if(*(arg + 1) == NEGATE) X { X ntok->tok = NCCL; X arg += 2; X } else { X ntok->tok = CCL; X arg++; X } X X if( ntok->bitmap = makebitmap(CLS_SIZE) ) X arg = dodash(CCLEND, arg, ntok->bitmap ); X else { X fprintf(stderr,"Not enough memory for pat\n"); X error = 1; X } X break; X X default: X if (*arg == ESCAPE && *(arg+1) == OPEN) { X ntok->tok = OPEN; X arg++; X } else X if (*arg == ESCAPE && *(arg+1) == CLOSE) { X ntok->tok = CLOSE; X arg++; X } else { X ntok->tok = LITCHAR; X ntok->lchar = esc(&arg); X } X } X X if (error || ntok == 0) X { X unmakepat(head); X return (0); X } else if (head == 0) X { X /* This is the first node in the chain. */ X X ntok->next = 0; X head = tail = ntok; X } else if (ntok->tok != CLOSURE) X { X /* Insert at end of list (after tail) */ X X tail->next = ntok; X ntok->next = tail; X tail = ntok; X } else if (head != tail) X { X /* X * More than one node in the chain. Insert the X * CLOSURE node immediately in front of tail. X */ X X (tail->next)->next = ntok; X ntok->next = tail; X } else { X /* X * Only one node in the chain, Insert the CLOSURE X * node at the head of the linked list. X */ X X ntok->next = head; X tail->next = ntok; X head = ntok; X } X arg++; X } X X tail->next = 0; X return (head); X} X X/* maksub.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xchar * Xmaksub(sub, subsz) Xchar *sub; Xint subsz; X{ X int size; X char delim, *cp; X X size = 0; X cp = sub; X X delim = *inptr++; X for(size = 0; *inptr != delim && *inptr != NL && size < subsz; size++) X { X if(*inptr == '&') X { X *cp++ = DITTO; X inptr++; X } else X if((*cp++ = *inptr++) == ESCAPE) X { X if (size>=subsz) return(NULL); X X switch(toupper(*inptr)) X { X case NL: X *cp++ = ESCAPE; X break; X case 'S': X *cp++ = SP; X inptr++; X break; X case 'N': X *cp++ = NL; X inptr++; X break; X case 'T': X *cp++ = HT; X inptr++; X break; X case 'B': X *cp++ = BS; X inptr++; X break; X case 'R': X *cp++ = CR; X inptr++; X break; X case '0': { X int i=3; X *cp = 0; X do { X if (*++inptr<'0' || *inptr >'7') X break; X X *cp = (*cp<<3) | (*inptr-'0'); X } while (--i!=0); X cp++; X } break; X default: X *cp++ = *inptr++; X break; X } X } X } X if(size >= subsz) X return( NULL ); X X *cp = EOS; X return( sub ); X} X X/* matchs.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X X/* X * Compares line and pattern. Line is a character string while pat X * is a pattern template made by getpat(). X * Returns: X * 1. A zero if no match was found. X * X * 2. A pointer to the last character satisfing the match X * if ret_endp is non-zero. X * X * 3. A pointer to the beginning of the matched string if X * ret_endp is zero. X * X * e.g.: X * X * matchs ("1234567890", getpat("4[0-9]*7), 0); X * will return a pointer to the '4', while: X * X * matchs ("1234567890", getpat("4[0-9]*7), 1); X * will return a pointer to the '7'. X */ Xchar * Xmatchs(line, pat, ret_endp) Xchar *line; XTOKEN *pat; Xint ret_endp; X{ X X char *rval, *bptr; X X bptr = line; X X while(*line) X { X if ((rval = amatch(line, pat, bptr)) == 0) X { X line++; X } else { X if(rval > bptr && rval > line) X rval--; /* point to last char matched */ X rval = ret_endp ? rval : line; X break; X } X } X return (rval); X} X X/* move.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xmove(num) Xint num; X{ X LINE *k0, *k1, *k2, *k3; X X if(line1 <= 0 || line2 < line1 || line1 <= num && num <= line2) X return( ERR ); X k0 = getptr(prevln(line1)); X k1 = getptr(line1); X k2 = getptr(line2); X k3 = getptr(nextln(line2)); X lastln -= line2-line1+1; X X relink(k0, k3, k0, k3); X X if (num > line1) X num -= line2-line1+1; X X curln = num + (line2 - line1 + 1); X X k0 = getptr(num); X k3 = getptr(nextln(num)); X lastln += line2-line1+1; X X relink(k0, k1, k2, k3); X relink(k2, k3, k0, k1); X X return( 1 ); X} X Xint transfer(num) Xint num; X{ X int mid, lin, ntrans; X X if (line1<=0 || line1>line2) X return(ERR); X X mid= num<line2 ? num : line2; X X curln=num; X ntrans=0; X X for (lin=line1; lin<=mid; lin++) { X ins(gettxt(lin)); X ntrans++; X } X lin+=ntrans; X line2+=ntrans; X X for ( ; lin<=line2; lin+=2) { X ins(gettxt(lin)); X line2++; X } X return(1); X} X X/* omatch.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X X/* X * Match one pattern element, pointed at by pat, with the character at X * **linp. Return non-zero on match. Otherwise, return 0. *Linp is X * advanced to skip over the matched character; it is not advanced on X * failure. The amount of advance is 0 for patterns that match null X * strings, 1 otherwise. "boln" should point at the position that will X * match a BOL token. X */ Xomatch(linp, pat, boln) Xchar **linp; XTOKEN *pat; Xchar *boln; X{ X X register int advance; X X advance = -1; X X if (**linp) X { X switch (pat->tok) X { X case LITCHAR: X if (**linp == pat->lchar) X advance = 1; X break; X X case BOL: X if (*linp = boln) X advance = 0; X break; X X case ANY: X if (**linp != '\n') X advance = 1; X break; X X case EOL: X if (**linp == '\n') X advance = 0; X break; X X case CCL: X if( testbit( **linp, pat->bitmap)) X advance = 1; X break; X X case NCCL: X if (!testbit (**linp, pat->bitmap)) X advance = 1; X break; X } X } X if (advance >= 0) X *linp += advance; X X return (++advance); X} X X/* optpat.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X XTOKEN *oldpat; X XTOKEN * Xoptpat() X{ X char delim, str[MAXPAT], *cp; X X delim = *inptr++; X cp = str; X while(*inptr != delim && *inptr != NL) X { X if(*inptr == ESCAPE && inptr[1] != NL) X *cp++ = *inptr++; X *cp++ = *inptr++; X } X X *cp = EOS; X if(*str == EOS) X return(oldpat); X if(oldpat) X unmakepat(oldpat); X oldpat=getpat(str); X return(oldpat); X} X X/* set.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xstruct tbl { X char *t_str; X int *t_ptr; X int t_val; X} *t, tbl[] = { X "number", &nflg, TRUE, X "nonumber", &nflg, FALSE, X "list", &lflg, TRUE, X "nolist", &lflg, FALSE, X "eightbit", &eightbit, TRUE, X "noeightbit", &eightbit, FALSE, X "prompt", &prompt, TRUE, X "noprompt", &prompt, FALSE, X 0 X}; X Xset() X{ X char word[16]; X int i; X X inptr++; X if(*inptr != 't') X { X if(*inptr != SP && *inptr != HT && *inptr != NL) X return(ERR); X } else X inptr++; X X if(*inptr == NL) X return(show("all")); X /* skip white space */ X while(*inptr == SP || *inptr == HT) X inptr++; X X for(i = 0; *inptr != SP && *inptr != HT && *inptr != NL;) X word[i++] = *inptr++; X word[i] = EOS; X for(t = tbl; t->t_str; t++) X { X if(strcmp(word,t->t_str) == 0) X { X *t->t_ptr = t->t_val; X return(0); X } X } X} X Xshow() X{ X extern int version; X X printf("ed version %d.%d\n",version/100,version%100); X printf("number %s, ",nflg?"ON":"OFF"); X printf("list %s, ",lflg?"ON":"OFF"); X printf("prompt %s,\n",prompt?"ON":"OFF"); X return(0); X} X X/* setbuf.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xvoid relink(a, x, y, b) XLINE *a, *x, *y, *b; X{ X x->l_prev = a; X y->l_next = b; X} X Xvoid clrbuf() X{ X del(1, lastln); X} X Xvoid edsetbuf() X{ X relink(&line0, &line0, &line0, &line0); X curln = lastln = 0; X} X X/* subst.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X/* #include "ed.h" */ X Xsubst(pat, sub, gflg, pflag) XTOKEN *pat; Xchar *sub; Xint gflg, pflag; X{ X int lin, chngd, nchngd; X char *txtptr, *txt; X char *lastm, *m, *new, buf[MAXLINE]; X X if(line1 <= 0) X return( ERR ); X nchngd = 0; /* reset count of lines changed */ X for(lin = line1; lin <= line2; lin++) X { X txt = txtptr = gettxt(lin); X new = buf; X chngd = 0; X lastm = NULL; X while(*txtptr) X { X if(gflg || !chngd) X m = amatch(txtptr, pat, txt); X else X m = NULL; X if(m != NULL && lastm != m) X { X chngd++; X new = catsub(txtptr, m, sub, new, X buf+MAXLINE); X lastm = m; X } X if(m == NULL || m == txtptr) X { X *new++ = *txtptr++; X } else { X txtptr = m; X } X } X if(chngd) X { X if(new >= buf+MAXLINE) X return( ERR ); X *new++ = EOS; X del(lin,lin); X ins(buf); X nchngd++; X if(pflag) X doprnt(curln, curln); X } X } X if(nchngd == 0 && !gflg) X { X return(ERR); X } X return( nchngd ); X} X X#if 0 X/* system.c */ X#define SHELL "/bin/sh" X Xsystem(c) Xchar *c; { X int pid, status; X X switch (pid = fork()) { X case -1: X return -1; X case 0: X execl(SHELL, "sh", "-c", c, (char *) 0); X exit(-1); X default: X while (wait(&status) != pid) X ; X } X return status; X} X#endif X X/* unmkpat.c */ X/* #include <stdio.h> */ X/* #include "tools.h" */ X X/* Free up the memory usde for token string */ Xvoid unmakepat(head) XTOKEN *head; X{ X X register TOKEN *old_head; X X while (head) X { X switch (head->tok) X { X case CCL: X case NCCL: X free(head->bitmap); X /* fall through to default */ X X default: X old_head = head; X head = head->next; X free (old_head); X break; X } X } X} X Xisatty(fd) Xint fd; X{ X long IsInteractive(); X struct UFB *ufb; X X ufb = chkufb(fd); X if (ufb == NULL) X return(-1); X return(IsInteractive(ufb->ufbfh) != 0); X} X@ X X X1.4 Xlog X@More amiga changes X@ Xtext X@d3 2 Xd36 1 Xd41 1 Xa41 1 X"$Header: Rodime:ricks/ked2/ked2.c,v 1.3 89/09/01 11:02:22 rick Exp Locker: rick $"; Xd144 1 Xa144 1 Xextern int unmakepat(); Xa153 2 X#define max(a,b) ((a>b)?a:b) X#define min(a,b) ((a<b)?a:b) Xd201 1 Xa229 1 X register i; Xd594 1 Xd614 1 Xa614 1 X int i, apflg, pflag, gflag; Xd1056 1 Xa1056 1 Xprntln(str, vflg, lin) Xd1093 1 Xa1093 1 Xputcntl(c, stream) Xd1234 1 Xa1234 1 Xintr() Xd1240 1 Xa1240 1 Xmain(argc,argv) Xd1244 1 Xa1244 1 X int stat, i, j, doflush; Xd1246 1 Xa1246 1 X setbuf(); Xa1809 1 X char buf[CLS_SIZE]; Xd2297 1 Xa2297 1 Xrelink(a, x, y, b) Xd2304 1 Xa2304 1 Xclrbuf() Xd2309 1 Xa2309 1 Xint setbuf() Xd2404 1 Xa2404 1 Xunmakepat(head) Xd2428 5 Xd2434 5 X@ X X X1.3 Xlog X@Amiga changes X@ Xtext X@d38 1 Xa38 1 X"$Header: Quantum:ricks/ked2/ed.c,v 1.1 89/08/27 17:44:11 rick Exp Locker: rick $"; Xd1309 1 Xa1309 1 X _cleanup(); exit(0); Xd1314 1 Xa1314 1 X _cleanup(); exit(1); X@ X X X1.2 Xlog X@No changes X@ Xtext X@d1280 1 Xd1289 1 Xd2308 1 Xa2308 1 Xvoid setbuf() Xd2376 1 Xd2396 1 X@ X X X1.1 Xlog X@Initial revision X@ Xtext X@d38 1 Xa38 1 X"$Header: ed.c,v 1.6 88/05/23 16:47:56 dnix Exp $"; X@ SHAR_EOF if `test ! -d rcs` then mkdir rcs echo "mkdir rcs" fi echo "extracting rcs/readme" sed 's/^X//' << \SHAR_EOF > rcs/readme XThe source code for RCS is distrubuted as RCSfiles. This is so that you will Xhave the original sources and the current Amiga sources (and intermediate Xversions). It also provides a collection of RCSfiles that newcommers to RCS Xcan play with to learn what RCS does. X X X Ray SHAR_EOF if `test ! -d rcs/rcs.rcsfiles` then mkdir rcs/rcs.rcsfiles echo "mkdir rcs/rcs.rcsfiles" fi echo "extracting rcs/rcs.rcsfiles/maketime.c,v" sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/maketime.c,v Xhead 1.8; Xbranch 1.8.2; Xaccess ; Xsymbols amiga_rcs:1.8.2 cbmvax_source:1.8.1 uunet_june89_dist:1.8; Xlocks ; strict; Xcomment @ * @; X X X1.8 Xdate 88.11.08.13.54.53; author narten; state Exp; Xbranches 1.8.1.1 1.8.2.1; Xnext ; X X1.8.1.1 Xdate 89.08.11.01.41.52; author rsbx; state Exp; Xbranches ; Xnext ; X X1.8.2.1 Xdate 89.10.13.19.17.37; author rsbx; state Exp; Xbranches ; Xnext 1.8.2.2; X X1.8.2.2 Xdate 89.10.15.15.43.22; author rsbx; state Exp; Xbranches ; Xnext ; X X Xdesc X@derive 32-bit time value from TM structure. X@ X X X X1.8 Xlog X@checked in with -k by rsbx at 89.08.10.16.02.32. X@ Xtext X@# X/* X * MAKETIME derive 32-bit time value from TM structure. X * X * Usage: X * long t,maketime(); X * struct tm *tp; Pointer to TM structure from <time.h> X * NOTE: this must be extended version!!! X * t = maketime(tp); X * X * Returns: X * 0 if failure; parameter out of range or nonsensical. X * else long 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#ifndef lint Xstatic char rcsid[]= "$Id: maketime.c,v 1.8 88/11/08 13:54:53 narten Exp $"; X#endif X/* $Log: maketime.c,v $ X * Revision 1.8 88/11/08 13:54:53 narten X * allow negative timezones (-24h <= x <= 24h) X * X * Revision 1.7 88/11/08 12:02:24 narten X * changes from eggert@@sm.unisys.com (Paul Eggert) 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.1 84/01/23 14:50:04 kcs X * Initial revision 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#include "time.h" X Xint daytb[] = { /* # 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 Xstruct tm *localtime(); Xlong time(); X Xlong maketime(atm) Xstruct tm *atm; X{ register struct tm *tp; X register int i; X int year, yday, mon, day, hour, min, sec, zone, dst, leap; X long tres, curtim; X X VOID time(&curtim); X tp = localtime(&curtim); /* Get breakdowns of current time */ X year = tp->tm_year; /* Use to set up defaults */ X mon = tp->tm_mon; X day = tp->tm_mday; X X X#ifdef DEBUG Xprintf("first YMD: %d %d %d, T=%ld\n",year,mon,day,tres); 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 * Start with year... note 32 bits can only handle 135 years. X */ X if(tp->tm_year != TMNULL) X { if((year = tp->tm_year) >= 1900) /* Allow full yr # */ X year -= 1900; /* by making kosher */ X mon = 0; /* Since year was given, default */ X day = 1; /* for remaining specs is zero */ X } X if(year < 70 || 70+134 < year ) /* Check range */ X return(0); /* ERR: year out of range */ X leap = year&03 ? 0 : 1; /* See if leap year */ X year -= 70; /* UNIX time starts at 1970 */ X X /* X * Find day of year. X * YDAY is used only if it exists and either the month or day-of-month X * is missing. X */ X if (tp->tm_yday != TMNULL X && (tp->tm_mon == TMNULL || tp->tm_mday == TMNULL)) X yday = tp->tm_yday; X else X { if(tp->tm_mon != TMNULL) X { mon = tp->tm_mon; /* Month was specified */ X day = 1; /* so set remaining default */ X } X if(mon < 0 || 11 < mon) return(0); /* ERR: bad month */ X if(tp->tm_mday != TMNULL) day = tp->tm_mday; X if(day < 1 X || (((daytb[mon+1]-daytb[mon]) < day) X && (day!=29 || mon!=1 || !leap) )) X return(0); /* 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 if (tp->tm_yday != TMNULL /* Confirm that YDAY correct */ X && tp->tm_yday != yday) return(0); /* ERR: conflict */ X } X if(yday < 0 || (leap?366:365) <= yday) X return(0); /* ERR: bad YDAY or maketime bug */ X X tres = year*365 /* Get # days of years so far */ X + ((year+1)>>2) /* plus # of leap days since 1970 */ X + yday; /* and finally add # days this year */ X X if((i = tp->tm_wday) != TMNULL) /* Check WDAY if present */ X if(i < 0 || 6 < i /* Ensure within range */ X || i != (tres+4)%7) /* Matches? Jan 1,1970 was Thu = 4 */ X return(0); /* ERR: bad WDAY */ X X#ifdef DEBUG Xprintf("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 hour = min = sec = 0; X if(tp->tm_hour != TMNULL) hour = tp->tm_hour; X if(tp->tm_min != TMNULL) min = tp->tm_min; X if(tp->tm_sec != TMNULL) sec = tp->tm_sec; X if( min < 0 || 60 <= min X || sec < 0 || 60 <= sec) return(0); /* ERR: MS out of range */ X if(hour < 0 || 24 <= hour) X if(hour != 24 || (min+sec) !=0) /* Allow 24:00 */ X return(0); /* ERR: H out of range */ X X /* confirm AM/PM if there */ X switch(tp->tm_ampm) X { case 0: case TMNULL: /* Ignore these values */ X break; X case 1: /* AM */ X case 2: /* PM */ X if(hour > 12) return(0); /* ERR: hrs 13-23 bad */ X if(hour ==12) hour = 0; /* Modulo 12 */ X if(tp->tm_ampm == 2) /* If PM, then */ X hour += 12; /* get 24-hour time */ X break; X default: return(0); /* ERR: illegal TM_AMPM value */ X } X X tres += sec + 60L*(min + 60L*hour); /* Add in # secs of time */ X X#ifdef DEBUG Xprintf("HMS: %d %d %d T=%ld\n",hour,min,sec,tres); X#endif X /* X * We now have the GMT date/time and must make final X * adjustment for the specified time zone. If none is specified, X * the local time-zone is assumed. X */ X if((zone = tp->tm_zon) == TMNULL /* If unspecified */ X || (zone == 1)) /* or local-zone requested */ X zone = localzone(); /* then set to local zone */ X if(zone < -24*60 || 24*60 <= zone) X return(0); /* ERR: zone out of range */ X X /* See if must apply Daylight Saving Time shift. X * Note that if DST is specified, validity is not checked. X */ X if((dst = tp->tm_isdst) == TMNULL) /* Must we figure it out? */ X { curtim = tres +localzone()*60L; /* Yuck. Get equiv local */ X dst = localtime(&curtim)->tm_isdst; /* time, and ask. */ X } X tres += zone*60L -(dst?3600:0); /* Add in # seconds of zone adj */ X X return(tres); X} X X X/* LOCALZONE return local timezone in # mins west of GMT X * X */ X X#if defined(V6) || defined(USG) Xextern long timezone; X#else X#include <sys/types.h> X#include <sys/timeb.h> X#endif X Xstatic int lclzon; Xlocalzone() X{ X if (!lclzon) { X#if defined(V6) || defined(USG) X#ifdef USG X tzset(); X#endif X lclzon = timezone/60 + 1; X#else X struct timeb tb; X X ftime(&tb); X lclzon = tb.timezone + 1; X X#endif X } X return lclzon - 1; X} X@ X X X1.8.2.1 Xlog X@Start of Amiga RCS port branch. X@ Xtext X@d23 1 Xa23 5 X<<<<<<< maketime.c Xstatic char rcsid[]= "$Id: maketime.c,v 1.8.1.1 89/08/11 01:41:52 rsbx Exp Locker: rsbx $"; X======= Xstatic char rcsid[]= "$Id: maketime.c,v 1.2 89/09/17 13:34:45 rick Exp $"; X>>>>>>> 1.2 Xa25 11 X<<<<<<< maketime.c X * Revision 1.8.1.1 89/08/11 01:41:52 rsbx X * Start of cbmvax RCS source branch. X======= X * Revision 1.2 89/09/17 13:34:45 rick X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com) X * All changes done with conditional compile (#ifdef AMIGA). This version X * compiles correctly with Lattice C version 5.02 or later. X>>>>>>> 1.2 X * X<<<<<<< maketime.c Xa26 3 X * checked in with -k by rsbx at 89.08.10.16.02.32. X * X * Revision 1.8 88/11/08 13:54:53 narten Xa34 8 X======= X * Revision 1.3 89/09/16 09:42:31 rick X * Modified AMIGA changes to work with Lattice C X * X * Revision 1.2 88/09/03 15:08:05 rick X * Port to AmigaDos. All done with conditional compiles X * X>>>>>>> 1.2 Xd89 2 Xa90 1 X#ifdef MYDEBUG Xa91 1 X<<<<<<< maketime.c Xa92 3 X======= X#endif MYDEBUG X>>>>>>> 1.2 Xa106 3 X#ifdef AMIGA X if(year < 78 || 78+134 < year ) /* Check range */ X#else Xa107 1 X#endif Xa109 3 X#ifdef AMIGA X year -= 78; /* AMIGA time starts at 1978 */ X#else Xa110 1 X#endif Xa116 1 X Xa135 1 X#ifndef AMIGA /* Manx's localtime messes up yday */ Xa137 1 X#endif Xd143 1 Xa143 1 X + ((year+1)>>2) /* plus # of leap days since 1970 (1980)*/ Xa147 3 X#ifdef AMIGA X || i != (tres+0)%7) /* Matches? Jan 1,1978 was Sun = 0 */ X#else Xa148 1 X#endif Xd151 1 Xa151 1 X#ifdef MYDEBUG Xa152 1 X<<<<<<< maketime.c Xa153 3 X======= X#endif MYDEBUG X>>>>>>> 1.2 Xd163 4 Xa166 4 X if( (min < 0) || (60 <= min) X || (sec < 0) || (60 <= sec) ) return(0); /* ERR: MS out of range */ X if((hour < 0) || (24 <= hour)) X if((hour != 24) || ((min+sec) !=0)) /* Allow 24:00 */ Xa169 1 X#ifndef AMIGA Xa181 1 X#endif Xd185 1 Xa185 1 X#ifdef MYDEBUG Xa186 1 X<<<<<<< maketime.c Xa187 3 X======= X#endif MYDEBUG X>>>>>>> 1.2 Xa192 1 X#ifndef AMIGA Xd207 1 Xa207 1 X#endif Xa214 1 X<<<<<<< maketime.c Xa216 4 X======= X#ifndef AMIGA X#ifdef V6 X>>>>>>> 1.2 Xa241 1 X#endif AMIGA X@ X X X1.8.2.2 Xlog X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS Xsources I have here (and are later than the ones Rick used). X@ Xtext X@d1 1 Xd23 5 Xa27 1 Xstatic char rcsid[]= "$Id: maketime.c,v 1.8.2.1 89/10/13 19:17:37 rsbx Exp Locker: rsbx $"; Xd30 1 Xa30 3 X * Revision 1.8.2.1 89/10/13 19:17:37 rsbx X * Start of Amiga RCS port branch. X * Xd33 6 Xd40 1 Xd53 8 Xd106 1 Xa106 4 X int year, yday, mon, day, hour, min, sec, leap; X#ifndef AMIGA X int zone, dst; X#endif Xd117 1 Xd119 3 Xd197 1 Xd199 3 Xd237 1 Xd239 3 Xd270 4 Xd275 2 Xa276 1 X#if defined(V6) || defined(USG) X@ X X X1.8.1.1 Xlog X@Start of cbmvax RCS source branch. X@ Xtext X@a26 3 X * checked in with -k by rsbx at 89.08.10.16.02.32. X * X * Revision 1.8 88/11/08 13:54:53 narten X@ SHAR_EOF echo "End of archive 6 (of 14)" # if you want to concatenate archives, remove anything after this line exit