home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume25 / rcs-5.6 / part02 < prev    next >
Text File  |  1991-12-19  |  90KB  |  3,203 lines

  1. Newsgroups: comp.sources.unix
  2. From: hammer@cs.purdue.edu (Adam Hammer)
  3. Subject: v25i078: rcs-5.6 - Revision Control System, V5.6, Part02/11
  4. Sender: sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: hammer@cs.purdue.edu (Adam Hammer)
  8. Posting-Number: Volume 25, Issue 78
  9. Archive-Name: rcs-5.6/part02
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 2 (of 11)."
  18. # Contents:  man/rcs.1 man/rcsintro.1 src/README src/maketime.c
  19. #   src/rcsdiff.c src/rcsfcmp.c src/rcskeep.c src/rcsmerge.c
  20. #   src/rcstest
  21. # Wrapped by vixie@cognition.pa.dec.com on Fri Dec 20 16:23:39 1991
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. if test -f 'man/rcs.1' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'man/rcs.1'\"
  25. else
  26. echo shar: Extracting \"'man/rcs.1'\" \(8642 characters\)
  27. sed "s/^X//" >'man/rcs.1' <<'END_OF_FILE'
  28. X.de Id
  29. X.ds Rv \\$3
  30. X.ds Dt \\$4
  31. X..
  32. X.Id $Id: rcs.1,v 5.6 1991/09/26 23:16:17 eggert Exp $
  33. X.ds r \&\s-1RCS\s0
  34. X.if n .ds - \%--
  35. X.if t .ds - \(em
  36. X.TH RCS 1 \*(Dt GNU
  37. X.SH NAME
  38. rcs \- change RCS file attributes
  39. X.SH SYNOPSIS
  40. X.B rcs
  41. X.RI [ " options " ] " file " .\|.\|.
  42. X.SH DESCRIPTION
  43. X.B rcs
  44. creates new \*r files or changes attributes of existing ones.
  45. An \*r file contains multiple revisions of text,
  46. an access list, a change log,
  47. descriptive text,
  48. and some control attributes.
  49. XFor
  50. X.B rcs
  51. to work, the caller's login name must be on the access list,
  52. except if the access list is empty, the caller is the owner of the file
  53. or the superuser, or
  54. the
  55. X.B \-i
  56. option is present.
  57. X.PP
  58. Pathnames matching an \*r suffix denote \*r files;
  59. all others denote working files.
  60. Names are paired as explained in
  61. X.BR ci (1).
  62. Revision numbers use the syntax described in
  63. X.BR ci (1).
  64. X.SH OPTIONS
  65. X.TP
  66. X.B \-i
  67. Create and initialize a new \*r file, but do not deposit any revision.
  68. If the \*r file has no path prefix, try to place it
  69. first into the subdirectory
  70. X.BR ./RCS ,
  71. and then into the current directory.
  72. If the \*r file
  73. already exists, print an error message.
  74. X.TP
  75. X.BI \-a "logins"
  76. Append the login names appearing in the comma-separated list
  77. X.I logins
  78. to the access list of the \*r file.
  79. X.TP
  80. X.BI \-A "oldfile"
  81. Append the access list of
  82. X.I oldfile
  83. to the access list of the \*r file.
  84. X.TP
  85. X.BR \-e [\f2logins\fP]
  86. XErase the login names appearing in the comma-separated list
  87. X.I logins
  88. from the access list of the \*r file.
  89. If
  90. X.I logins
  91. is omitted, erase the entire access list.
  92. X.TP
  93. X.BR \-b [\f2rev\fP]
  94. Set the default branch to
  95. X.IR rev .
  96. If
  97. X.I rev
  98. is omitted, the default
  99. branch is reset to the (dynamically) highest branch on the trunk.
  100. X.TP
  101. X.BI \-c string
  102. sets the comment leader to
  103. X.IR string .
  104. The comment leader
  105. is printed before every log message line generated by the keyword
  106. X.B $\&Log$
  107. during checkout (see
  108. X.BR co (1)).
  109. This is useful for programming
  110. languages without multi-line comments.
  111. An initial
  112. X.B ci ,
  113. or an
  114. X.B "rcs\ \-i"
  115. without
  116. X.BR \-c ,
  117. guesses the comment leader from the suffix of the working file.
  118. X.TP
  119. X.BI \-k subst
  120. Set the default keyword substitution to
  121. X.IR subst .
  122. The effect of keyword substitution is described in
  123. X.BR co (1).
  124. Giving an explicit
  125. X.B \-k
  126. option to
  127. X.BR co ,
  128. X.BR rcsdiff ,
  129. and
  130. X.B rcsmerge
  131. overrides this default.
  132. Beware
  133. X.BR "rcs\ \-kv",
  134. because
  135. X.B \-kv
  136. is incompatible with
  137. X.BR "co\ \-l".
  138. Use
  139. X.B "rcs\ \-kkv"
  140. to restore the normal default keyword substitution.
  141. X.TP
  142. X.BR \-l [\f2rev\fP]
  143. Lock the revision with number
  144. X.IR rev .
  145. If a branch is given, lock the latest revision on that branch.
  146. If
  147. X.I rev
  148. is omitted, lock the latest revision on the default branch.
  149. Locking prevents overlapping changes.
  150. A lock is removed with
  151. X.B ci
  152. or
  153. X.B "rcs\ \-u"
  154. X(see below).
  155. X.TP
  156. X.BR \-u [\f2rev\fP]
  157. Unlock the revision with number
  158. X.IR rev .
  159. If a branch is given, unlock the latest revision on that branch.
  160. If
  161. X.I rev
  162. is omitted, remove the latest lock held by the caller.
  163. Normally, only the locker of a revision may unlock it.
  164. Somebody else unlocking a revision breaks the lock.
  165. This causes a mail message to be sent to the original locker.
  166. The message contains a commentary solicited from the breaker.
  167. The commentary is terminated by end-of-file or by a line containing
  168. X.BR \&. "\ by"
  169. itself.
  170. X.TP
  171. X.B \-L
  172. Set locking to
  173. X.IR strict .
  174. Strict locking means that the owner
  175. of an \*r file is not exempt from locking for checkin.
  176. This option should be used for files that are shared.
  177. X.TP
  178. X.B \-U
  179. Set locking to non-strict.  Non-strict locking means that the owner of
  180. a file need not lock a revision for checkin.
  181. This option should
  182. X.I not
  183. be used for files that are shared.
  184. Whether default locking is strict is determined by your system administrator,
  185. but it is normally strict.
  186. X.TP
  187. X\f3\-m\fP\f2rev\fP\f3:\fP\f2msg\fP
  188. Replace revision
  189. X.IR rev 's
  190. log message with
  191. X.IR msg .
  192. X.TP
  193. X\f3\-n\fP\f2name\fP[\f3:\fP[\f2rev\fP]]
  194. Associate the symbolic name
  195. X.I name
  196. with the branch or
  197. revision
  198. X.IR rev .
  199. Delete the symbolic name if both
  200. X.B :
  201. and
  202. X.I rev
  203. are omitted; otherwise, print an error message if
  204. X.I name
  205. is already associated with
  206. another number.
  207. If
  208. X.I rev
  209. is symbolic, it is expanded before association.
  210. A
  211. X.I rev
  212. consisting of a branch number followed by a
  213. X.B .\&
  214. stands for the current latest revision in the branch.
  215. A
  216. X.B :
  217. with an empty
  218. X.I rev
  219. stands for the current latest revision on the default branch,
  220. normally the trunk.
  221. XFor example,
  222. X.BI "rcs\ \-n" name ":\ RCS/*"
  223. associates
  224. X.I name
  225. with the current latest revision of all the named \*r files;
  226. this contrasts with
  227. X.BI "rcs\ \-n" name ":$\ RCS/*"
  228. which associates
  229. X.I name
  230. with the revision numbers extracted from keyword strings
  231. in the corresponding working files.
  232. X.TP
  233. X\f3\-N\fP\f2name\fP[\f3:\fP[\f2rev\fP]]
  234. Act like
  235. X.BR \-n ,
  236. except override any previous assignment of
  237. X.IR name .
  238. X.TP
  239. X.BI \-o range
  240. deletes (\*(lqoutdates\*(rq) the revisions given by
  241. X.IR range .
  242. A range consisting of a single revision number means that revision.
  243. A range consisting of a branch number means the latest revision on that
  244. branch.
  245. A range of the form
  246. X.IB rev1 : rev2
  247. means
  248. revisions
  249. X.I rev1
  250. to
  251. X.I rev2
  252. on the same branch,
  253. X.BI : rev
  254. means from the beginning of the branch containing
  255. X.I rev
  256. up to and including
  257. X.IR rev ,
  258. and
  259. X.IB rev :
  260. means
  261. from revision
  262. X.I rev
  263. to the end of the branch containing
  264. X.IR rev .
  265. None of the outdated revisions may have branches or locks.
  266. X.TP
  267. X.B \-q
  268. Run quietly; do not print diagnostics.
  269. X.TP
  270. X.B \-I
  271. Run interactively, even if the standard input is not a terminal.
  272. X.TP
  273. X.B \-s\f2state\fP\f1[\fP:\f2rev\fP\f1]\fP
  274. Set the state attribute of the revision
  275. X.I rev
  276. to
  277. X.I state .
  278. If
  279. X.I rev
  280. is a branch number, assume the latest revision on that branch.
  281. If
  282. X.I rev
  283. is omitted, assume the latest revision on the default branch.
  284. Any identifier is acceptable for
  285. X.IR state .
  286. A useful set of states
  287. is
  288. X.B Exp
  289. X(for experimental),
  290. X.B Stab
  291. X(for stable), and
  292. X.B Rel
  293. X(for
  294. released).
  295. By default,
  296. X.BR ci (1)
  297. sets the state of a revision to
  298. X.BR Exp .
  299. X.TP
  300. X.BR \-t [\f2file\fP]
  301. Write descriptive text from the contents of the named
  302. X.I file
  303. into the \*r file, deleting the existing text.
  304. The
  305. X.IR file
  306. pathname may not begin with
  307. X.BR \- .
  308. If
  309. X.I file
  310. is omitted, obtain the text from standard input,
  311. terminated by end-of-file or by a line containing
  312. X.BR \&. "\ by"
  313. itself.
  314. Prompt for the text if interaction is possible; see
  315. X.BR \-I .
  316. With
  317. X.BR \-i ,
  318. descriptive text is obtained
  319. even if
  320. X.B \-t
  321. is not given.
  322. X.TP
  323. X.BI \-t\- string
  324. Write descriptive text from the
  325. X.I string
  326. into the \*r file, deleting the existing text.
  327. X.TP
  328. X.BI \-V n
  329. XEmulate \*r version
  330. X.IR n .
  331. See
  332. X.BR co (1)
  333. for details.
  334. X.TP
  335. X.BI \-x "suffixes"
  336. Use
  337. X.I suffixes
  338. to characterize \*r files.
  339. See
  340. X.BR ci (1)
  341. for details.
  342. X.SH COMPATIBILITY
  343. The
  344. X.BI \-b rev
  345. option generates an \*r file that cannot be parsed by \*r version 3 or earlier.
  346. X.PP
  347. The
  348. X.BI \-k subst
  349. options (except
  350. X.BR \-kkv )
  351. generate an \*r file that cannot be parsed by \*r version 4 or earlier.
  352. X.PP
  353. Use
  354. X.BI "rcs \-V" n
  355. to make an \*r file acceptable to \*r version
  356. X.I n
  357. by discarding information that would confuse version
  358. X.IR n .
  359. X.PP
  360. X\*r version 5.5 and earlier does not support the
  361. X.B \-x
  362. option, and requires a
  363. X.B ,v
  364. suffix on an \*r pathname.
  365. X.SH FILES
  366. X.B rcs
  367. accesses files much as
  368. X.BR ci (1)
  369. does,
  370. except that it uses the effective user for all accesses,
  371. it does not write the working file or its directory,
  372. and it does not even read the working file unless a revision number of
  373. X.B $
  374. is specified.
  375. X.SH ENVIRONMENT
  376. X.TP
  377. X.B \s-1RCSINIT\s0
  378. options prepended to the argument list, separated by spaces.
  379. See
  380. X.BR ci (1)
  381. for details.
  382. X.SH DIAGNOSTICS
  383. The \*r pathname and the revisions outdated are written to
  384. the diagnostic output.
  385. The exit status is zero if and only if all operations were successful.
  386. X.SH IDENTIFICATION
  387. Author: Walter F. Tichy.
  388. X.br
  389. Revision Number: \*(Rv; Release Date: \*(Dt.
  390. X.br
  391. Copyright \(co 1982, 1988, 1989 by Walter F. Tichy.
  392. X.br
  393. Copyright \(co 1990, 1991 by Paul Eggert.
  394. X.SH "SEE ALSO"
  395. co(1), ci(1), ident(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1),
  396. rcsfile(5)
  397. X.br
  398. Walter F. Tichy,
  399. X\*r\*-A System for Version Control,
  400. X.I "Software\*-Practice & Experience"
  401. X.BR 15 ,
  402. X7 (July 1985), 637-654.
  403. X.SH BUGS
  404. The separator for revision ranges in the
  405. X.B \-o
  406. option used to be
  407. X.B \-
  408. instead of
  409. X.BR : ,
  410. but this leads to confusion when symbolic names contain
  411. X.BR \- .
  412. XFor backwards compatibility
  413. X.B "rcs \-o"
  414. still supports the old
  415. X.B \-
  416. separator, but it warns about this obsolete use.
  417. X.PP
  418. Symbolic names need not refer to existing revisions or branches.
  419. XFor example, the
  420. X.B \-o
  421. option does not remove symbolic names for the outdated revisions; you must use
  422. X.B \-n
  423. to remove the names.
  424. X.br
  425. END_OF_FILE
  426. if test 8642 -ne `wc -c <'man/rcs.1'`; then
  427.     echo shar: \"'man/rcs.1'\" unpacked with wrong size!
  428. fi
  429. # end of 'man/rcs.1'
  430. fi
  431. if test -f 'man/rcsintro.1' -a "${1}" != "-c" ; then 
  432.   echo shar: Will not clobber existing file \"'man/rcsintro.1'\"
  433. else
  434. echo shar: Extracting \"'man/rcsintro.1'\" \(9299 characters\)
  435. sed "s/^X//" >'man/rcsintro.1' <<'END_OF_FILE'
  436. X.de Id
  437. X.ds Rv \\$3
  438. X.ds Dt \\$4
  439. X..
  440. X.Id $Id: rcsintro.1,v 5.1 1991/04/21 12:00:46 eggert Exp $
  441. X.ds r \&\s-1RCS\s0
  442. X.if n .ds - \%--
  443. X.if t .ds - \(em
  444. X.am SS
  445. X.LP
  446. X..
  447. X.TH RCSINTRO 1 \*(Dt GNU
  448. X.SH NAME
  449. rcsintro \- introduction to RCS commands
  450. X.SH DESCRIPTION
  451. The Revision Control System (\*r) manages multiple revisions of files.
  452. X\*r automates the storing, retrieval, logging, identification, and merging
  453. of revisions.  \*r is useful for text that is revised frequently, for example
  454. programs, documentation, graphics, papers, and form letters.
  455. X.PP
  456. The basic user interface is extremely simple.  The novice only needs
  457. to learn two commands:
  458. X.BR ci (1)
  459. and
  460. X.BR co (1).
  461. X.BR ci ,
  462. short for \*(lqcheck in\*(rq, deposits the contents of a
  463. file into an archival file called an \*r file.  An \*r file
  464. contains all revisions of a particular file.
  465. X.BR co ,
  466. short for \*(lqcheck out\*(rq, retrieves revisions from an \*r file.
  467. X.SS "Functions of \*r"
  468. X.IP \(bu
  469. Store and retrieve multiple revisions of text.  \*r saves all old
  470. revisions in a space efficient way.
  471. Changes no longer destroy the original, because the
  472. previous revisions remain accessible.  Revisions can be retrieved according to
  473. ranges of revision numbers, symbolic names, dates, authors, and
  474. states.
  475. X.IP \(bu
  476. Maintain a complete history of changes.
  477. X\*r logs all changes automatically.
  478. Besides the text of each revision, \*r stores the author, the date and time of
  479. check-in, and a log message summarizing the change.
  480. The logging makes it easy to find out
  481. what happened to a module, without having to compare
  482. source listings or having to track down colleagues.
  483. X.IP \(bu
  484. Resolve access conflicts.  When two or more programmers wish to
  485. modify the same revision, \*r alerts the programmers and prevents one
  486. modification from corrupting the other.
  487. X.IP \(bu
  488. Maintain a tree of revisions.  \*r can maintain separate lines of development
  489. for each module.  It stores a tree structure that represents the
  490. ancestral relationships among revisions.
  491. X.IP \(bu
  492. Merge revisions and resolve conflicts.
  493. Two separate lines of development of a module can be coalesced by merging.
  494. If the revisions to be merged affect the same sections of code, \*r alerts the
  495. user about the overlapping changes.
  496. X.IP \(bu
  497. Control releases and configurations.
  498. Revisions can be assigned symbolic names
  499. and marked as released, stable, experimental, etc.
  500. With these facilities, configurations of modules can be
  501. described simply and directly.
  502. X.IP \(bu
  503. Automatically identify each revision with name, revision number,
  504. creation time, author, etc.
  505. The identification is like a stamp that can be embedded at an appropriate place
  506. in the text of a revision.
  507. The identification makes it simple to determine which
  508. revisions of which modules make up a given configuration.
  509. X.IP \(bu
  510. Minimize secondary storage.  \*r needs little extra space for
  511. the revisions (only the differences).  If intermediate revisions are
  512. deleted, the corresponding deltas are compressed accordingly.
  513. X.SS "Getting Started with \*r"
  514. Suppose you have a file
  515. X.B f.c
  516. that you wish to put under control of \*r.
  517. If you have not already done so, make an \*r directory with the command
  518. X.IP
  519. X.B "mkdir  RCS"
  520. X.LP
  521. Then invoke the check-in command
  522. X.IP
  523. X.B "ci  f.c"
  524. X.LP
  525. This command creates an \*r file in the
  526. X.B RCS
  527. directory,
  528. stores
  529. X.B f.c
  530. into it as revision 1.1, and
  531. deletes
  532. X.BR f.c .
  533. It also asks you for a description.  The description
  534. should be a synopsis of the contents of the file.  All later check-in
  535. commands will ask you for a log entry, which should summarize the
  536. changes that you made.
  537. X.PP
  538. XFiles in the \*r directory are called \*r files;
  539. the others are called working files.
  540. To get back the working file
  541. X.B f.c
  542. in the previous example, use the check-out
  543. command
  544. X.IP
  545. X.B "co  f.c"
  546. X.LP
  547. This command extracts the latest revision from the \*r file
  548. and writes
  549. it into
  550. X.BR f.c .
  551. If you want to edit
  552. X.BR f.c ,
  553. you must lock it as you check it out with the command
  554. X.IP
  555. X.B "co  \-l  f.c"
  556. X.LP
  557. You can now edit
  558. X.BR f.c .
  559. X.PP
  560. Suppose after some editing you want to know what changes that you have made.
  561. The command
  562. X.IP
  563. X.B "rcsdiff  f.c"
  564. X.LP
  565. tells you the difference between the most recently checked-in version
  566. and the working file.
  567. You can check the file back in by invoking
  568. X.IP
  569. X.B "ci  f.c"
  570. X.LP
  571. This increments the revision number properly.
  572. X.PP
  573. If
  574. X.B ci
  575. complains with the message
  576. X.IP
  577. X.BI "ci error: no lock set by " "your name"
  578. X.LP
  579. then you have tried to check in a file even though you did not
  580. lock it when you checked it out.
  581. Of course, it is too late now to do the check-out with locking, because
  582. another check-out would
  583. overwrite your modifications.  Instead, invoke
  584. X.IP
  585. X.B "rcs  \-l  f.c"
  586. X.LP
  587. This command will lock the latest revision for you, unless somebody
  588. else got ahead of you already.  In this case, you'll have to negotiate with
  589. that person.
  590. X.PP
  591. Locking assures that you, and only you, can check in the next update, and
  592. avoids nasty problems if several people work on the same file.
  593. XEven if a revision is locked, it can still be checked out for
  594. reading, compiling, etc.  All that locking
  595. prevents is a
  596. X.I "check-in"
  597. by anybody but the locker.
  598. X.PP
  599. If your \*r file is private, i.e., if you are the only person who is going
  600. to deposit revisions into it, strict locking is not needed and you
  601. can turn it off.
  602. If strict locking is turned off,
  603. the owner of the \*r file need not have a lock for check-in; all others
  604. still do.  Turning strict locking off and on is done with the commands
  605. X.IP
  606. X.BR "rcs  \-U  f.c" "     and     " "rcs  \-L  f.c"
  607. X.LP
  608. If you don't want to clutter your working directory with \*r files, create
  609. a subdirectory called
  610. X.B RCS
  611. in your working directory, and move all your \*r
  612. files there.  \*r commands will look first into that directory to find
  613. needed files.  All the commands discussed above will still work, without any
  614. modification.
  615. X(Actually, pairs of \*r and working files can be specified in three ways:
  616. X(a) both are given, (b) only the working file is given, (c) only the
  617. X\*r file is given.  Both \*r and working files may have arbitrary path prefixes;
  618. X\*r commands pair them up intelligently.)
  619. X.PP
  620. To avoid the deletion of the working file during check-in (in case you want to
  621. continue editing or compiling), invoke
  622. X.IP
  623. X.BR "ci  \-l  f.c" "     or     " "ci  \-u  f.c"
  624. X.LP
  625. These commands check in
  626. X.B f.c
  627. as usual, but perform an implicit
  628. check-out.  The first form also locks the checked in revision, the second one
  629. doesn't.  Thus, these options save you one check-out operation.
  630. The first form is useful if you want to continue editing,
  631. the second one if you just want to read the file.
  632. Both update the identification markers in your working file (see below).
  633. X.PP
  634. You can give
  635. X.B ci
  636. the number you want assigned to a checked in
  637. revision.  Assume all your revisions were numbered 1.1, 1.2, 1.3, etc.,
  638. and you would like to start release 2.
  639. The command
  640. X.IP
  641. X.BR "ci  \-r2  f.c" "     or     " "ci  \-r2.1  f.c"
  642. X.LP
  643. assigns the number 2.1 to the new revision.
  644. XFrom then on,
  645. X.B ci
  646. will number the subsequent revisions
  647. with 2.2, 2.3, etc.  The corresponding
  648. X.B co
  649. commands
  650. X.IP
  651. X.BR "co  \-r2  f.c" "     and     " "co  \-r2.1  f.c"
  652. X.PP
  653. retrieve the latest revision numbered
  654. X.RI 2. x
  655. and the revision 2.1,
  656. respectively.
  657. X.B co
  658. without a revision number selects
  659. the latest revision on the
  660. X.IR trunk ,
  661. i.e. the highest
  662. revision with a number consisting of two fields.  Numbers with more than two
  663. fields are needed for branches.
  664. XFor example, to start a branch at revision 1.3, invoke
  665. X.IP
  666. X.B "ci  \-r1.3.1  f.c"
  667. X.LP
  668. This command starts a branch numbered 1 at revision 1.3, and assigns
  669. the number 1.3.1.1 to the new revision.  For more information about
  670. branches, see
  671. X.BR rcsfile (5).
  672. X.SS "Automatic Identification"
  673. X\*r can put special strings for identification into your source and object
  674. code.  To obtain such identification, place the marker
  675. X.IP
  676. X.B "$\&Id$"
  677. X.LP
  678. into your text, for instance inside a comment.
  679. X\*r will replace this marker with a string of the form
  680. X.IP
  681. X.BI $\&Id: "  filename  revision  date  time  author  state  " $
  682. X.LP
  683. With such a marker on the first page of each module, you can
  684. always see with which revision you are working.
  685. X\*r keeps the markers up to date automatically.
  686. To propagate the markers into your object code, simply put
  687. them into literal character strings.  In C, this is done as follows:
  688. X.IP
  689. X.ft 3
  690. static char rcsid[] = \&"$\&Id$\&";
  691. X.ft
  692. X.LP
  693. The command
  694. X.B ident
  695. extracts such markers from any file, even object code
  696. and dumps.
  697. Thus,
  698. X.B ident
  699. lets you find out
  700. which revisions of which modules were used in a given program.
  701. X.PP
  702. You may also find it useful to put the marker
  703. X.B $\&Log$
  704. into your text, inside a comment.  This marker accumulates
  705. the log messages that are requested during check-in.
  706. Thus, you can maintain the complete history of your file directly inside it.
  707. There are several additional identification markers; see
  708. X.BR co (1)
  709. for
  710. details.
  711. X.SH IDENTIFICATION
  712. Author: Walter F. Tichy.
  713. X.br
  714. Revision Number: \*(Rv; Release Date: \*(Dt.
  715. X.br
  716. Copyright \(co 1982, 1988, 1989 by Walter F. Tichy.
  717. X.br
  718. Copyright \(co 1990, 1991 by Paul Eggert.
  719. X.SH "SEE ALSO"
  720. ci(1), co(1), ident(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1)
  721. X.br
  722. Walter F. Tichy,
  723. X\*r\*-A System for Version Control,
  724. X.I "Software\*-Practice & Experience"
  725. X.BR 15 ,
  726. X7 (July 1985), 637-654.
  727. X.br
  728. END_OF_FILE
  729. if test 9299 -ne `wc -c <'man/rcsintro.1'`; then
  730.     echo shar: \"'man/rcsintro.1'\" unpacked with wrong size!
  731. fi
  732. # end of 'man/rcsintro.1'
  733. fi
  734. if test -f 'src/README' -a "${1}" != "-c" ; then 
  735.   echo shar: Will not clobber existing file \"'src/README'\"
  736. else
  737. echo shar: Extracting \"'src/README'\" \(9190 characters\)
  738. sed "s/^X//" >'src/README' <<'END_OF_FILE'
  739. RCS configuration instructions
  740. X
  741. X    $Id: README,v 1.5 1991/10/07 17:32:46 eggert Exp $
  742. X
  743. X    Copyright 1991 by Paul Eggert
  744. X    Distributed under license by the Free Software Foundation, Inc.
  745. X
  746. X    This file is part of RCS.
  747. X
  748. X    RCS is free software; you can redistribute it and/or modify it
  749. X    under the terms of the GNU General Public License as published
  750. X    by the Free Software Foundation; either version 2, or (at your
  751. X    option) any later version.
  752. X
  753. X    RCS is distributed in the hope that it will be useful, but
  754. X    WITHOUT ANY WARRANTY; without even the implied warranty of
  755. X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  756. X    GNU General Public License for more details.
  757. X
  758. X    You should have received a copy of the GNU General Public
  759. X    License along with RCS; see the file COPYING.  If not, write to
  760. X    the Free Software Foundation, 675 Mass Ave, Cambridge, MA
  761. X    02139, USA.
  762. X
  763. X    Report problems and direct all questions to:
  764. X
  765. X        rcs-bugs@cs.purdue.edu
  766. X
  767. X
  768. XFor Posix and near-Posix hosts, configure by editing Makefile,
  769. commenting out wrong lines and uncommenting right ones.
  770. See ``Makefile notes'' below for advice.
  771. X
  772. After configuring, make conf.h; if this fails,
  773. look in src/conf.error to see what went wrong in the conf.sh shell file.
  774. Check the resulting conf.h for plausibility; see ``conf.h notes'' below.
  775. If conf.h is wrong, and the mistake isn't listed in ``conf.h notes'',
  776. there is a bug in conf.sh; please report it.
  777. You can patch conf.h if you're in a hurry, but it's better to fix it;
  778. look at a.h and conf.error for ideas.
  779. If all else fails, copy conf.heg to conf.h and edit it by hand.
  780. After configuring, make `all'.
  781. X
  782. If all went well, make `install'.
  783. If installation succeeds, make `installtest';
  784. if this fails, make `installdebug' for detailed info.
  785. X
  786. If you want to test RCS before installing it,
  787. you must set RCSPREFIX to be empty, make RCS from scratch,
  788. prefix the src directory to your PATH, and run `sh src/rcstest'.
  789. Be sure to restore RCSPREFIX and rebuild RCS before installing it.
  790. X
  791. If you want to maintain RCS with itself,
  792. preserve the original revision numbers, dates, etc.
  793. by checking the files in with the -k option.
  794. X
  795. X
  796. X__________
  797. X
  798. Makefile notes
  799. X
  800. CC is the name of your C compiler.
  801. X
  802. CC_D is a list of extra options for the C preprocessor.
  803. It should include any extra -D and -I options needed on your system.
  804. X
  805. CC_O is the C compiler options that affect just compilation and assembly;
  806. not preprocessing, linking or linting.
  807. If your compiler has the BSD -R option, -R can improve performance by
  808. making all initialized data read-only (not just string literals);
  809. this is not worth worrying about if your compiler also supports `const'.
  810. X
  811. CC_W is the list of C compiler options to enable
  812. warnings about questionable constructs in the RCS source code.
  813. X
  814. COMPAT2 is 1 if you still have version 2 RCS files around.
  815. X(Version 2 became obsolete in 1982, so this isn't likely.)
  816. COMPAT2 assures that version 2 RCS files can still be read.
  817. When you have the new RCS installed, rename old version 2 RCS files as follows.
  818. Suppose the working file was `f.c';
  819. rename the RCS file `f.c.v' to `f.c,v', and the RCS file `f.v' to `f.c,v'.
  820. Thus suffixes are no longer dropped and RCS files end in `,v' rather than `.v'.
  821. After all version 2 RCS files have been updated with new versions of ci or rcs,
  822. you can remake RCS with COMPAT2 set to 0.
  823. X
  824. DIFF is the name of your diff program.
  825. If you override DIFF, make sure you rebuild conf.h afterwards;
  826. otherwise you may introduce a security hole.
  827. On some versions of Unix, the standard diff does not support RCS
  828. and you must use something like /usr/lib/rdiff instead;
  829. perhaps you should try GNU diff instead.
  830. X
  831. DIFFPREFIX act likes RCSPREFIX, except it applies to subsidiary diffs,
  832. not to subsidiary RCS commands.  It must be nonempty if setuid is to be used.
  833. X
  834. DIFF_FLAGS are diff's options for RCS format output, probably -n.
  835. If available, also include the -a option for comparing arbitrary files.
  836. X
  837. DIFF_L is 1 if diff understands the -L option for labeling context diff output.
  838. X
  839. DIFF_SUCCESS, DIFF_FAILURE, DIFF_TROUBLE are integer constants
  840. representing diff's exit status when it finds
  841. no differences, some differences, or trouble respectively.
  842. The first two should be EXIT_SUCCESS and EXIT_FAILURE,
  843. but on some hosts they are broken.
  844. X
  845. DIFF3 is the name of the diff3 program.
  846. With GNU diff, this is simply its user-visible diff3 program.
  847. With traditional diff3, this is not the user-visible diff3 program;
  848. instead, it this is the name of the undocumented diff3 auxiliary program,
  849. whose name is /usr/lib/diff3 or /usr/5lib/rdiff3prog or something similar.
  850. X
  851. DIFF3_BIN is 1 if DIFF3 is the user-visible GNU diff3 program (see DIFF3).
  852. Before setting this to 1, make sure your diff3 understands -a, -L, and and -m;
  853. e.g. the command `echo x | diff3 -m /dev/null /dev/null -' should output `x'.
  854. X
  855. XED is the name of the standard Unix line editor.
  856. It is needed only if DIFF3_BIN is 0.
  857. X
  858. XEXECUTABLE_PERMISSIONS are the options given to INSTALL for executable files
  859. on BSD Unix sites.  Watch out for `-g staff' if you don't have a staff group,
  860. or if your installation program doesn't have a -g option.
  861. X
  862. INSTALL is the command that installs commands.
  863. X
  864. LDFLAGS are the loader flags you need, e.g. -i, -n, -s, -x.
  865. X
  866. LDLIBS are the loader libraries you need, e.g. -lbsd, -lBSD, -ljobs, -lPW, -lx.
  867. X
  868. LINK is the command used to link together an executable.
  869. X
  870. LINT is the name and usual arguments of your lint program.
  871. X
  872. OTHER_OBJECT are any other object files you need to link.
  873. X
  874. RCSCOMMANDS is the list of commands to be installed by default.
  875. It doesn't include rcsclean$x, which is still a little experimental.
  876. X
  877. RCSDIR is where the RCS commands will be installed.
  878. X
  879. RCSPREFIX is the prefix for subsidiary RCS commands like ci.
  880. If empty, RCS will search the PATH for these commands;
  881. this lets you move RCS commands after building them, and permits
  882. multiple instances of setuid RCS commands on the same host for different users.
  883. If nonempty, it should be a path followed by /;
  884. this makes RCS look in just one place, and makes execution faster.
  885. X
  886. REMOVE is how to remove a file.
  887. X
  888. SENDMAIL is a comma-separated list of strings that are a command to send mail.
  889. The name of the addressee will be appended as a separate argument,
  890. and the standard input will be the message
  891. X(first line `Subject: xxxx', second line empty).
  892. If your host cannot send mail, leave SENDMAIL empty.
  893. X
  894. TESTPREFIX is the prefix for test commands.
  895. X
  896. o is the file name extension your host uses for object files.
  897. It includes the `.'.  It is typically `.o' on Unix hosts.
  898. X
  899. x is the file name extension your host uses for executables.
  900. It includes the `.'.  It is empty on Unix hosts,
  901. which traditionally lack extensions on executables.
  902. X
  903. X
  904. X__________
  905. X
  906. conf.h notes
  907. X
  908. See conf.sh for details about the definitions in conf.h.
  909. Comments below cover unusual situations that can require hand patches to conf.h.
  910. X
  911. has_NFS - Set this if the target host might use NFS.
  912. NFS's stateless server model has well-known problems with
  913. the non-idempotent operations link(), rename(), and unlink().
  914. XFor example, unlink() can run twice on the file server,
  915. causing the client to think that the unlink failed with errno==ENOENT.
  916. has_NFS enables code that works around these problems.
  917. X
  918. const - Some hosts support `const' but complain about it, perhaps because
  919. system headers are wrong.  `#define const /*empty*/' pacifies them.
  920. X
  921. has_rename - This should be 0 in SCO Unix V.3.2.  Its NFS rename() is broken,
  922. but if you run conf.sh in a non-NFS filesystem, conf.sh thinks rename() works.
  923. X
  924. has_seteuid - This should be 1 only if your seteuid lets you switch back and
  925. forth between any pair of users as specified in Posix 1003.1a Draft 5.
  926. One must be root to test this reliably, so conf.sh just guesses.
  927. X
  928. large_memory - This should be 1 if main memory is large enough to hold entire
  929. copies of RCS files, perhaps because virtual memory is available.
  930. X
  931. NAME_MAX - this should be #undef'ed in AT&T SVR4.0 V2.0, which defines NAME_MAX
  932. to be 14 even though longer names are permitted on some filesystems.
  933. If you run conf.sh in a short-name filesystem, conf.sh won't detect this bug.
  934. X
  935. X_POSIX_SOURCE must be #defined in a strict Standard C environment,
  936. because otherwise stdio.h cannot define useful names like fileno.
  937. Avoid defining _POSIX_SOURCE if possible,
  938. because it can disable useful non-Posix features in your host.
  939. Perhaps you can remove the need for _POSIX_SOURCE
  940. by supplying an option to your compiler to makes it less strict.
  941. X
  942. text_work_stdio - This option makes sense only on non-Posix hosts that
  943. distinguish between text and binary I/O, e.g. DOS.  Set this option if
  944. you want to use text I/O for working files, but binary I/O for RCS
  945. files.  If set, RCS does not support non-text working files, but RCS
  946. files are portable to other hosts across binary network file systems
  947. like NFS.  If not set, RCS supports non-text working files, but RCS
  948. files are not portable to Posix hosts.
  949. X
  950. TZ_must_be_set - set this to 1 on hosts where gmtime() yields bogus
  951. values unless the TZ environment variable is set.
  952. X
  953. volatile - See `const'.  E.g. `volatile sig_atomic_t' is conforming, but some
  954. buggy hosts complain.  Also, Ultrix 4.0 Mips CC 2.0 has buggy volatile support.
  955. END_OF_FILE
  956. if test 9190 -ne `wc -c <'src/README'`; then
  957.     echo shar: \"'src/README'\" unpacked with wrong size!
  958. fi
  959. # end of 'src/README'
  960. fi
  961. if test -f 'src/maketime.c' -a "${1}" != "-c" ; then 
  962.   echo shar: Will not clobber existing file \"'src/maketime.c'\"
  963. else
  964. echo shar: Extracting \"'src/maketime.c'\" \(9481 characters\)
  965. sed "s/^X//" >'src/maketime.c' <<'END_OF_FILE'
  966. X#
  967. X/*
  968. X * MAKETIME        derive 32-bit time value from TM structure.
  969. X *
  970. X * Usage:
  971. X *    int zone;    Minutes west of GMT, or
  972. X *            48*60 for localtime
  973. X *    time_t t;
  974. X *    struct tm *tp;    Pointer to TM structure from <time.h>
  975. X *    t = maketime(tp,zone);
  976. X *
  977. X * Returns:
  978. X *    -1 if failure; parameter out of range or nonsensical.
  979. X *    else time-value.
  980. X * Notes:
  981. X *    This code is quasi-public; it may be used freely in like software.
  982. X *    It is not to be sold, nor used in licensed software without
  983. X *    permission of the author.
  984. X *    For everyone's benefit, please report bugs and improvements!
  985. X *     Copyright 1981 by Ken Harrenstien, SRI International.
  986. X *    (ARPANET: KLH @ SRI)
  987. X */
  988. X/* $Log: maketime.c,v $
  989. X * Revision 5.3  1991/08/19  03:13:55  eggert
  990. X * Add setfiledate, str2time, TZ_must_be_set.
  991. X *
  992. X * Revision 5.2  1990/11/01  05:03:30  eggert
  993. X * Remove lint.
  994. X *
  995. X * Revision 5.1  1990/10/04  06:30:13  eggert
  996. X * Calculate the GMT offset of 'xxx LT' as of xxx, not as of now.
  997. X * Don't assume time_t is 32 bits.  Fix bugs near epoch and near end of time.
  998. X *
  999. X * Revision 5.0  1990/08/22  08:12:38  eggert
  1000. X * Switch to GMT and fix the bugs exposed thereby.
  1001. X * Permit dates past 1999/12/31.  Ansify and Posixate.
  1002. X *
  1003. X * Revision 1.8  88/11/08  13:54:53  narten
  1004. X * allow negative timezones (-24h <= x <= 24h)
  1005. X * 
  1006. X * Revision 1.7  88/08/28  14:47:52  eggert
  1007. X * Allow cc -R.  Remove unportable "#endif XXX"s.
  1008. X * 
  1009. X * Revision 1.6  87/12/18  17:05:58  narten
  1010. X * include rcsparam.h
  1011. X * 
  1012. X * Revision 1.5  87/12/18  11:35:51  narten
  1013. X * maketime.c: fixed USG code - you have tgo call "tzset" in order to have
  1014. X * "timezone" set. ("localtime" calls it, but it's probably better not to 
  1015. X * count on "localtime" having been called.)
  1016. X * 
  1017. X * Revision 1.4  87/10/18  10:26:57  narten
  1018. X * Updating version numbers. Changes relative to 1.0 are actually 
  1019. X * relative to 1.2
  1020. X * 
  1021. X * Revision 1.3  87/09/24  13:58:45  narten
  1022. X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  1023. X * warnings)
  1024. X * 
  1025. X * Revision 1.2  87/03/27  14:21:48  jenkins
  1026. X * Port to suns
  1027. X * 
  1028. X * Revision 1.2  83/12/05  10:12:56  wft
  1029. X * added cond. compilation for USG Unix; long timezone;
  1030. X * 
  1031. X * Revision 1.1  82/05/06  11:38:00  wft
  1032. X * Initial revision
  1033. X * 
  1034. X */
  1035. X
  1036. X
  1037. X#include "rcsbase.h"
  1038. X
  1039. libId(maketId, "$Id: maketime.c,v 5.3 1991/08/19 03:13:55 eggert Exp $")
  1040. X
  1041. static struct tm const *time2tm P((time_t));
  1042. X
  1043. X#define given(v) (0 <= (v)) /* Negative values are unspecified. */
  1044. X
  1045. static int const daytb[] = {
  1046. X    /* # days in year thus far, indexed by month (0-12!!) */
  1047. X    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
  1048. X};
  1049. X
  1050. X    static time_t
  1051. maketime(atm,zone)
  1052. X    struct tm const *atm;
  1053. X    int zone;
  1054. X{
  1055. X    register struct tm const *tp;
  1056. X    register int i;
  1057. X    int year, yday, mon, day, hour, min, sec, leap, localzone;
  1058. X    int attempts;
  1059. X    time_t t, tres;
  1060. X
  1061. X    attempts = 2;
  1062. X    localzone = zone==48*60;
  1063. X    tres = -1;
  1064. X    year = mon = day = 0;  /* Keep lint happy.  */
  1065. X
  1066. X    do {
  1067. X
  1068. X    if (localzone || !given(atm->tm_year)) {
  1069. X        if (tres == -1)
  1070. X            if ((tres = time((time_t*)0))  ==  -1)
  1071. X                return -1;
  1072. X        tp = time2tm(tres);
  1073. X        /* Get breakdowns of default time, adjusting to zone. */
  1074. X        year = tp->tm_year;        /* Use to set up defaults */
  1075. X        yday = tp->tm_yday;
  1076. X        mon = tp->tm_mon;
  1077. X        day = tp->tm_mday;
  1078. X        hour = tp->tm_hour;
  1079. X        min = tp->tm_min;
  1080. X        if (localzone) {
  1081. X            tp = localtime(&tres);
  1082. X            zone =
  1083. X            min - tp->tm_min + 60*(
  1084. X                hour - tp->tm_hour + 24*(
  1085. X                    /* If years differ, it's by one day. */
  1086. X                        year - tp->tm_year
  1087. X                    ?    year - tp->tm_year
  1088. X                    :    yday - tp->tm_yday));
  1089. X        }
  1090. X        /* Adjust the default day, month and year according to zone.  */
  1091. X        if ((min -= zone) < 0) {
  1092. X            if (hour-(59-min)/60 < 0  &&  --day <= 0) {
  1093. X            if (--mon < 0) {
  1094. X                --year;
  1095. X                mon = 11;
  1096. X            }
  1097. X            day  =  daytb[mon+1] - daytb[mon] + (mon==1&&!(year&3));
  1098. X            }
  1099. X        } else
  1100. X            if (
  1101. X              24 <= hour+min/60  &&
  1102. X              daytb[mon+1] - daytb[mon] + (mon==1&&!(year&3))  <  ++day
  1103. X            ) {
  1104. X                if (11 < ++mon) {
  1105. X                    ++year;
  1106. X                    mon = 0;
  1107. X                }
  1108. X                day = 1;
  1109. X            }
  1110. X    }
  1111. X    if (zone < -24*60  ||  24*60 < zone)
  1112. X        return -1;
  1113. X
  1114. X
  1115. X#ifdef DEBUG
  1116. printf("first YMD: %d %d %d\n",year,mon,day);
  1117. X#endif
  1118. X    tp = atm;
  1119. X
  1120. X    /* First must find date, using specified year, month, day.
  1121. X     * If one of these is unspecified, it defaults either to the
  1122. X     * current date (if no more global spec was given) or to the
  1123. X     * zero-value for that spec (i.e. a more global spec was seen).
  1124. X     * Reject times that do not fit in time_t,
  1125. X     * without assuming that time_t is 32 bits or is signed.
  1126. X     */
  1127. X    if (given(tp->tm_year))
  1128. X      {
  1129. X        year = tp->tm_year;
  1130. X        mon = 0;        /* Since year was given, default */
  1131. X        day = 1;        /* for remaining specs is zero */
  1132. X      }
  1133. X    if (year < 69)            /* 1969/12/31 OK in some timezones.  */
  1134. X        return -1;        /* ERR: year out of range */
  1135. X    leap   =   !(year&3)  &&  (year%100 || !((year+300)%400));
  1136. X    year -= 70;            /* UNIX time starts at 1970 */
  1137. X
  1138. X    /*
  1139. X     * Find day of year.
  1140. X     */
  1141. X    {
  1142. X        if (given(tp->tm_mon))
  1143. X          {    mon = tp->tm_mon;    /* Month was specified */
  1144. X            day = 1;        /* so set remaining default */
  1145. X          }
  1146. X        if (11 < (unsigned)mon)
  1147. X            return -1;        /* ERR: bad month */
  1148. X        if (given(tp->tm_mday)) day = tp->tm_mday;
  1149. X        if(day < 1
  1150. X         || (((daytb[mon+1]-daytb[mon]) < day)
  1151. X            && (day!=29 || mon!=1 || !leap) ))
  1152. X                return -1;    /* ERR: bad day */
  1153. X        yday = daytb[mon]    /* Add # of days in months so far */
  1154. X          + ((leap        /* Leap year, and past Feb?  If */
  1155. X              && mon>1)? 1:0)    /* so, add leap day for this year */
  1156. X          + day-1;        /* And finally add # days this mon */
  1157. X
  1158. X    }
  1159. X    if (leap+365 <= (unsigned)yday)
  1160. X        return -1;        /* ERR: bad YDAY */
  1161. X
  1162. X    if (year < 0) {
  1163. X        if (yday != 364)
  1164. X        return -1;        /* ERR: too early */
  1165. X        t = -1;
  1166. X    } else {
  1167. X        tres = year*365;        /* Get # days of years so far */
  1168. X        if (tres/365 != year)
  1169. X            return -1;        /* ERR: overflow */
  1170. X        t = tres
  1171. X        + ((year+1)>>2)        /* plus # of leap days since 1970 */
  1172. X        + yday;            /* and finally add # days this year */
  1173. X        if (t+4 < tres)
  1174. X            return -1;        /* ERR: overflow */
  1175. X    }
  1176. X    tres = t;
  1177. X
  1178. X    if (given(i = tp->tm_wday)) /* Check WDAY if present */
  1179. X        if (i != (tres+4)%7)    /* 1970/01/01 was Thu = 4 */
  1180. X            return -1;    /* ERR: bad WDAY */
  1181. X
  1182. X#ifdef DEBUG
  1183. printf("YMD: %d %d %d, T=%ld\n",year,mon,day,tres);
  1184. X#endif
  1185. X    /*
  1186. X     * Now determine time.  If not given, default to zeros
  1187. X     * (since time is always the least global spec)
  1188. X     */
  1189. X    tres *= 86400L;            /* Get # seconds (24*60*60) */
  1190. X    if (tres/86400L != t)
  1191. X        return -1;        /* ERR: overflow */
  1192. X    hour = min = sec = 0;
  1193. X    if (given(tp->tm_hour)) hour = tp->tm_hour;
  1194. X    if (given(tp->tm_min )) min  = tp->tm_min;
  1195. X    if (given(tp->tm_sec )) sec  = tp->tm_sec;
  1196. X    if (60 <= (unsigned)min  ||  60 < (unsigned)sec)
  1197. X        return -1;        /* ERR: MS out of range */
  1198. X    if (24 <= (unsigned)hour)
  1199. X        if(hour != 24 || (min+sec) !=0)    /* Allow 24:00 */
  1200. X            return -1;    /* ERR: H out of range */
  1201. X
  1202. X    t = tres;
  1203. X    tres += sec + 60L*(zone + min + 60*hour);
  1204. X
  1205. X#ifdef DEBUG
  1206. printf("HMS: %d %d %d T=%ld\n",hour,min,sec,tres);
  1207. X#endif
  1208. X
  1209. X    if (!localzone)            /* check for overflow */
  1210. X        return (year<0 ? (tres<0||86400L<=tres) : tres<t)  ?  -1  :  tres;
  1211. X
  1212. X    /* Check results; LT may have had a different GMT offset back then.  */
  1213. X    tp = localtime(&tres);
  1214. X    if (given(atm->tm_sec)  &&  atm->tm_sec != tp->tm_sec)
  1215. X        return -1; /* If seconds don't match, we're in trouble.  */
  1216. X    if (!(
  1217. X        given(atm->tm_min)  &&  atm->tm_min != tp->tm_min  ||
  1218. X        given(atm->tm_hour)  &&  atm->tm_hour != tp->tm_hour  ||
  1219. X        given(atm->tm_mday)  &&  atm->tm_mday != tp->tm_mday  ||
  1220. X        given(atm->tm_mon)  &&  atm->tm_mon != tp->tm_mon  ||
  1221. X        given(atm->tm_year)  &&  atm->tm_year != tp->tm_year
  1222. X    ))
  1223. X        return tres; /* Everything matches.  */
  1224. X
  1225. X    } while (--attempts);
  1226. X
  1227. X    return -1;
  1228. X}
  1229. X
  1230. X/*
  1231. X* Convert Unix time to struct tm format.
  1232. X* Use Coordinated Universal Time (UTC) if version 5 or newer;
  1233. X* use local time otherwise.
  1234. X*/
  1235. X    static struct tm const *
  1236. time2tm(unixtime)
  1237. X    time_t unixtime;
  1238. X{
  1239. X    struct tm const *tm;
  1240. X#    if TZ_must_be_set
  1241. X        static char const *TZ;
  1242. X        if (!TZ  &&  !(TZ = getenv("TZ")))
  1243. X            faterror("TZ is not set");
  1244. X#    endif
  1245. X    if (!(tm  =  (RCSversion<VERSION(5) ? localtime : gmtime)(&unixtime)))
  1246. X        faterror("UTC is not available; perhaps TZ is not set?");
  1247. X    return tm;
  1248. X}
  1249. X
  1250. X/*
  1251. X* Convert Unix time to RCS format.
  1252. X* For compatibility with older versions of RCS,
  1253. X* dates before AD 2000 are stored without the leading "19".
  1254. X*/
  1255. X    void
  1256. time2date(unixtime,date)
  1257. X    time_t unixtime;
  1258. X    char date[datesize];
  1259. X{
  1260. X    register struct tm const *tm = time2tm(unixtime);
  1261. X    VOID sprintf(date, DATEFORM,
  1262. X        tm->tm_year  +  (tm->tm_year<100 ? 0 : 1900),
  1263. X        tm->tm_mon+1, tm->tm_mday,
  1264. X        tm->tm_hour, tm->tm_min, tm->tm_sec
  1265. X    );
  1266. X}
  1267. X
  1268. X
  1269. X
  1270. X    static time_t
  1271. str2time(source)
  1272. X    char const *source;
  1273. X/* Parse a free-format date in SOURCE, yielding a Unix format time.  */
  1274. X{
  1275. X    int zone;
  1276. X    time_t unixtime;
  1277. X    struct tm parseddate;
  1278. X
  1279. X    if (!partime(source, &parseddate, &zone))
  1280. X        faterror("can't parse date/time: %s", source);
  1281. X    if ((unixtime = maketime(&parseddate, zone))  ==  -1)
  1282. X        faterror("bad date/time: %s", source);
  1283. X    return unixtime;
  1284. X}
  1285. X
  1286. X    void
  1287. str2date(source, target)
  1288. X    char const *source;
  1289. X    char target[datesize];
  1290. X/* Parse a free-format date in SOURCE, convert it
  1291. X * into RCS internal format, and store the result into TARGET.
  1292. X */
  1293. X{
  1294. X    time2date(str2time(source), target);
  1295. X}
  1296. X
  1297. X    int
  1298. setfiledate(file, date)
  1299. X    char const *file, date[datesize];
  1300. X/* Set the access and modification time of FILE to DATE.  */
  1301. X{
  1302. X    static struct utimbuf times; /* static so unused fields are zero */
  1303. X    char datebuf[datesize];
  1304. X
  1305. X    if (!date)
  1306. X        return 0;
  1307. X    times.actime = times.modtime = str2time(date2str(date, datebuf));
  1308. X    return utime(file, ×);
  1309. X}
  1310. END_OF_FILE
  1311. if test 9481 -ne `wc -c <'src/maketime.c'`; then
  1312.     echo shar: \"'src/maketime.c'\" unpacked with wrong size!
  1313. fi
  1314. # end of 'src/maketime.c'
  1315. fi
  1316. if test -f 'src/rcsdiff.c' -a "${1}" != "-c" ; then 
  1317.   echo shar: Will not clobber existing file \"'src/rcsdiff.c'\"
  1318. else
  1319. echo shar: Extracting \"'src/rcsdiff.c'\" \(11285 characters\)
  1320. sed "s/^X//" >'src/rcsdiff.c' <<'END_OF_FILE'
  1321. X/*
  1322. X *                     RCS rcsdiff operation
  1323. X */
  1324. X/*****************************************************************************
  1325. X *                       generate difference between RCS revisions
  1326. X *****************************************************************************
  1327. X */
  1328. X
  1329. X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
  1330. X   Copyright 1990, 1991 by Paul Eggert
  1331. X   Distributed under license by the Free Software Foundation, Inc.
  1332. X
  1333. This file is part of RCS.
  1334. X
  1335. RCS is free software; you can redistribute it and/or modify
  1336. it under the terms of the GNU General Public License as published by
  1337. the Free Software Foundation; either version 2, or (at your option)
  1338. any later version.
  1339. X
  1340. RCS is distributed in the hope that it will be useful,
  1341. but WITHOUT ANY WARRANTY; without even the implied warranty of
  1342. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1343. GNU General Public License for more details.
  1344. X
  1345. You should have received a copy of the GNU General Public License
  1346. along with RCS; see the file COPYING.  If not, write to
  1347. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  1348. X
  1349. Report problems and direct all questions to:
  1350. X
  1351. X    rcs-bugs@cs.purdue.edu
  1352. X
  1353. X*/
  1354. X
  1355. X
  1356. X
  1357. X
  1358. X/* $Log: rcsdiff.c,v $
  1359. X * Revision 5.10  1991/10/07  17:32:46  eggert
  1360. X * Remove lint.
  1361. X *
  1362. X * Revision 5.9  1991/08/19  03:13:55  eggert
  1363. X * Add RCSINIT, -r$.  Tune.
  1364. X *
  1365. X * Revision 5.8  1991/04/21  11:58:21  eggert
  1366. X * Add -x, RCSINIT, MS-DOS support.
  1367. X *
  1368. X * Revision 5.7  1990/12/13  06:54:07  eggert
  1369. X * GNU diff 1.15 has -u.
  1370. X *
  1371. X * Revision 5.6  1990/11/01  05:03:39  eggert
  1372. X * Remove unneeded setid check.
  1373. X *
  1374. X * Revision 5.5  1990/10/04  06:30:19  eggert
  1375. X * Accumulate exit status across files.
  1376. X *
  1377. X * Revision 5.4  1990/09/27  01:31:43  eggert
  1378. X * Yield 1, not EXIT_FAILURE, when diffs are found.
  1379. X *
  1380. X * Revision 5.3  1990/09/11  02:41:11  eggert
  1381. X * Simplify -kkvl test.
  1382. X *
  1383. X * Revision 5.2  1990/09/04  17:07:19  eggert
  1384. X * Diff's argv was too small by 1.
  1385. X *
  1386. X * Revision 5.1  1990/08/29  07:13:55  eggert
  1387. X * Add -kkvl.
  1388. X *
  1389. X * Revision 5.0  1990/08/22  08:12:46  eggert
  1390. X * Add -k, -V.  Don't use access().  Add setuid support.
  1391. X * Remove compile-time limits; use malloc instead.
  1392. X * Don't pass arguments with leading '+' to diff; GNU DIFF treats them as options.
  1393. X * Add GNU diff's flags.  Make lock and temp files faster and safer.
  1394. X * Ansify and Posixate.
  1395. X *
  1396. X * Revision 4.6  89/05/01  15:12:27  narten
  1397. X * changed copyright header to reflect current distribution rules
  1398. X * 
  1399. X * Revision 4.5  88/08/09  19:12:41  eggert
  1400. X * Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
  1401. X * 
  1402. X * Revision 4.4  87/12/18  11:37:46  narten
  1403. X * changes Jay Lepreau made in the 4.3 BSD version, to add support for
  1404. X * "-i", "-w", and "-t" flags and to permit flags to be bundled together,
  1405. X * merged in.
  1406. X * 
  1407. X * Revision 4.3  87/10/18  10:31:42  narten
  1408. X * Updating version numbers. Changes relative to 1.1 actually
  1409. X * relative to 4.1
  1410. X * 
  1411. X * Revision 1.3  87/09/24  13:59:21  narten
  1412. X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  1413. X * warnings)
  1414. X * 
  1415. X * Revision 1.2  87/03/27  14:22:15  jenkins
  1416. X * Port to suns
  1417. X * 
  1418. X * Revision 4.1  83/05/03  22:13:19  wft
  1419. X * Added default branch, option -q, exit status like diff.
  1420. X * Added fterror() to replace faterror().
  1421. X * 
  1422. X * Revision 3.6  83/01/15  17:52:40  wft
  1423. X * Expanded mainprogram to handle multiple RCS files.
  1424. X *
  1425. X * Revision 3.5  83/01/06  09:33:45  wft
  1426. X * Fixed passing of -c (context) option to diff.
  1427. X *
  1428. X * Revision 3.4  82/12/24  15:28:38  wft
  1429. X * Added call to catchsig().
  1430. X *
  1431. X * Revision 3.3  82/12/10  16:08:17  wft
  1432. X * Corrected checking of return code from diff; improved error msgs.
  1433. X *
  1434. X * Revision 3.2  82/12/04  13:20:09  wft
  1435. X * replaced getdelta() with gettree(). Changed diagnostics.
  1436. X *
  1437. X * Revision 3.1  82/11/28  19:25:04  wft
  1438. X * Initial revision.
  1439. X *
  1440. X */
  1441. X#include "rcsbase.h"
  1442. X
  1443. X#if DIFF_L
  1444. static char const *setup_label P((struct buf*,char const*,char const[datesize]));
  1445. X#endif
  1446. static void cleanup P((void));
  1447. X
  1448. static int exitstatus;
  1449. static RILE *workptr;
  1450. static struct stat workstat;
  1451. X
  1452. mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 5.10 1991/10/07 17:32:46 eggert Exp $")
  1453. X{
  1454. X    static char const cmdusage[] =
  1455. X        "\nrcsdiff usage: rcsdiff [-q] [-rrev1 [-rrev2]] [-Vn] [diff options] file ...";
  1456. X
  1457. X    int  revnums;                 /* counter for revision numbers given */
  1458. X    char const *rev1, *rev2;    /* revision numbers from command line */
  1459. X    char const *xrev1, *xrev2;    /* expanded revision numbers */
  1460. X    char const *expandarg, *lexpandarg, *versionarg;
  1461. X#if DIFF_L
  1462. X    static struct buf labelbuf[2];
  1463. X    int file_labels;
  1464. X    char const **diff_label1, **diff_label2;
  1465. X    char date2[datesize];
  1466. X#endif
  1467. X    char const *cov[9];
  1468. X    char const **diffv, **diffp;    /* argv for subsidiary diff */
  1469. X    char const **pp, *p, *diffvstr;
  1470. X    struct buf commarg;
  1471. X    struct buf numericrev;    /* expanded revision number */
  1472. X    struct hshentries *gendeltas;    /* deltas to be generated */
  1473. X    struct hshentry * target;
  1474. X    char *a, *dcp, **newargv;
  1475. X    register c;
  1476. X
  1477. X    exitstatus = DIFF_SUCCESS;
  1478. X
  1479. X    bufautobegin(&commarg);
  1480. X    bufautobegin(&numericrev);
  1481. X    revnums = 0;
  1482. X    rev1 = rev2 = xrev2 = nil;
  1483. X#if DIFF_L
  1484. X    file_labels = 0;
  1485. X#endif
  1486. X    expandarg = versionarg = 0;
  1487. X    suffixes = X_DEFAULT;
  1488. X
  1489. X    /* Room for args + 2 i/o [+ 2 labels] + 1 file + 1 trailing null.  */
  1490. X    diffp = diffv = tnalloc(char const*, argc + 4 + 2*DIFF_L);
  1491. X    *diffp++ = nil;
  1492. X    *diffp++ = nil;
  1493. X    *diffp++ = DIFF;
  1494. X
  1495. X    argc = getRCSINIT(argc, argv, &newargv);
  1496. X    argv = newargv;
  1497. X    while (a = *++argv,  0<--argc && *a++=='-') {
  1498. X    dcp = a;
  1499. X    while (c = *a++) switch (c) {
  1500. X        case 'r':
  1501. X            switch (++revnums) {
  1502. X            case 1: rev1=a; break;
  1503. X            case 2: rev2=a; break;
  1504. X            default: faterror("too many revision numbers");
  1505. X            }
  1506. X            goto option_handled;
  1507. X#if DIFF_L
  1508. X        case 'L':
  1509. X            if (++file_labels == 2)
  1510. X            faterror("too many -L options");
  1511. X            /* fall into */
  1512. X#endif
  1513. X        case 'C': case 'D': case 'F': case 'I':
  1514. X            *dcp++ = c;
  1515. X            if (*a)
  1516. X            do *dcp++ = *a++;
  1517. X            while (*a);
  1518. X            else {
  1519. X            if (!--argc)
  1520. X                faterror("-%c needs following argument%s",
  1521. X                    c, cmdusage
  1522. X                );
  1523. X            *diffp++ = *argv++;
  1524. X            }
  1525. X            break;
  1526. X        case 'B': case 'H': case 'T':
  1527. X        case '0': case '1': case '2': case '3': case '4':
  1528. X        case '5': case '6': case '7': case '8': case '9':
  1529. X        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  1530. X        case 'h': case 'i': case 'n': case 'p':
  1531. X        case 't': case 'u': case 'w':
  1532. X            *dcp++ = c;
  1533. X            break;
  1534. X        case 'q':
  1535. X            quietflag=true;
  1536. X            break;
  1537. X        case 'x':
  1538. X            suffixes = *argv + 2;
  1539. X            goto option_handled;
  1540. X        case 'V':
  1541. X            versionarg = *argv;
  1542. X            setRCSversion(versionarg);
  1543. X            goto option_handled;
  1544. X        case 'k':
  1545. X            expandarg = *argv;
  1546. X            if (0 <= str2expmode(expandarg+2))
  1547. X            goto option_handled;
  1548. X            /* fall into */
  1549. X        default:
  1550. X            faterror("unknown option: %s%s", *argv, cmdusage);
  1551. X        };
  1552. X      option_handled:
  1553. X    if (dcp != *argv+1) {
  1554. X        *dcp = 0;
  1555. X        *diffp++ = *argv;
  1556. X    }
  1557. X    } /* end of option processing */
  1558. X
  1559. X    if (argc<1) faterror("no input file%s", cmdusage);
  1560. X
  1561. X    for (pp = diffv+3, c = 0;  pp<diffp;  )
  1562. X        c += strlen(*pp++) + 1;
  1563. X    diffvstr = a = tnalloc(char, c + 1);
  1564. X    for (pp = diffv+3;  pp<diffp;  ) {
  1565. X        p = *pp++;
  1566. X        *a++ = ' ';
  1567. X        while ((*a = *p++))
  1568. X            a++;
  1569. X    }
  1570. X    *a = 0;
  1571. X
  1572. X#if DIFF_L
  1573. X    diff_label1 = diff_label2 = nil;
  1574. X    if (file_labels < 2) {
  1575. X        if (!file_labels)
  1576. X            diff_label1 = diffp++;
  1577. X        diff_label2 = diffp++;
  1578. X    }
  1579. X#endif
  1580. X    diffp[2] = nil;
  1581. X
  1582. X    cov[0] = 0;
  1583. X    cov[2] = CO;
  1584. X    cov[3] = "-q";
  1585. X
  1586. X    /* now handle all filenames */
  1587. X    do {
  1588. X        ffree();
  1589. X
  1590. X        if (pairfilenames(argc, argv, rcsreadopen, true, false)  <=  0)
  1591. X            continue;
  1592. X        diagnose("===================================================================\nRCS file: %s\n",RCSfilename);
  1593. X        if (!rev2) {
  1594. X        /* Make sure work file is readable, and get its status.  */
  1595. X        if (!(workptr = Iopen(workfilename,FOPEN_R_WORK,&workstat))) {
  1596. X            eerror(workfilename);
  1597. X            continue;
  1598. X        }
  1599. X        }
  1600. X
  1601. X
  1602. X        gettree(); /* reads in the delta tree */
  1603. X
  1604. X        if (Head==nil) {
  1605. X            error("no revisions present");
  1606. X            continue;
  1607. X        }
  1608. X        if (revnums==0  ||  !*rev1)
  1609. X            rev1  =  Dbranch ? Dbranch : Head->num;
  1610. X
  1611. X        if (!fexpandsym(rev1, &numericrev, workptr)) continue;
  1612. X        if (!(target=genrevs(numericrev.string,(char *)nil,(char *)nil,(char *)nil,&gendeltas))) continue;
  1613. X        xrev1=target->num;
  1614. X#if DIFF_L
  1615. X        if (diff_label1)
  1616. X        *diff_label1 = setup_label(&labelbuf[0], target->num, target->date);
  1617. X#endif
  1618. X
  1619. X        lexpandarg = expandarg;
  1620. X        if (revnums==2) {
  1621. X            if (!fexpandsym(
  1622. X                *rev2 ? rev2  : Dbranch ? Dbranch  : Head->num,
  1623. X                &numericrev,
  1624. X                workptr
  1625. X            ))
  1626. X            continue;
  1627. X            if (!(target=genrevs(numericrev.string,(char *)nil,(char *)nil,(char *)nil,&gendeltas))) continue;
  1628. X            xrev2=target->num;
  1629. X        } else if (
  1630. X            target->lockedby
  1631. X        &&    !lexpandarg
  1632. X        &&    Expand == KEYVAL_EXPAND
  1633. X        &&    WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
  1634. X        )
  1635. X            lexpandarg = "-kkvl";
  1636. X        Izclose(&workptr);
  1637. X#if DIFF_L
  1638. X        if (diff_label2)
  1639. X        if (revnums == 2)
  1640. X            *diff_label2 = setup_label(&labelbuf[1], target->num, target->date);
  1641. X        else {
  1642. X            time2date(workstat.st_mtime, date2);
  1643. X            *diff_label2 = setup_label(&labelbuf[1], workfilename, date2);
  1644. X        }
  1645. X#endif
  1646. X
  1647. X        diagnose("retrieving revision %s\n", xrev1);
  1648. X        bufscpy(&commarg, "-p");
  1649. X        bufscat(&commarg, xrev1);
  1650. X
  1651. X        cov[1] = diffp[0] = maketemp(0);
  1652. X        pp = &cov[4];
  1653. X        *pp++ = commarg.string;
  1654. X        if (lexpandarg)
  1655. X            *pp++ = lexpandarg;
  1656. X        if (versionarg)
  1657. X            *pp++ = versionarg;
  1658. X        *pp++ = RCSfilename;
  1659. X        *pp = 0;
  1660. X
  1661. X        if (runv(cov)) {
  1662. X            error("co failed");
  1663. X            continue;
  1664. X        }
  1665. X        if (!rev2) {
  1666. X            diffp[1] = workfilename;
  1667. X            if (workfilename[0] == '+') {
  1668. X            /* Some diffs have options with leading '+'.  */
  1669. X            char *dp = ftnalloc(char, strlen(workfilename)+3);
  1670. X            diffp[1] = dp;
  1671. X            *dp++ = '.';
  1672. X            *dp++ = SLASH;
  1673. X            VOID strcpy(dp, workfilename);
  1674. X            }
  1675. X        } else {
  1676. X            diagnose("retrieving revision %s\n",xrev2);
  1677. X            bufscpy(&commarg, "-p");
  1678. X            bufscat(&commarg, xrev2);
  1679. X            cov[1] = diffp[1] = maketemp(1);
  1680. X            cov[4] = commarg.string;
  1681. X            if (runv(cov)) {
  1682. X                error("co failed");
  1683. X                continue;
  1684. X            }
  1685. X        }
  1686. X        if (!rev2)
  1687. X            diagnose("diff%s -r%s %s\n", diffvstr, xrev1, workfilename);
  1688. X        else
  1689. X            diagnose("diff%s -r%s -r%s\n", diffvstr, xrev1, xrev2);
  1690. X
  1691. X        switch (runv(diffv)) {
  1692. X            case DIFF_SUCCESS:
  1693. X                break;
  1694. X            case DIFF_FAILURE:
  1695. X                if (exitstatus == DIFF_SUCCESS)
  1696. X                    exitstatus = DIFF_FAILURE;
  1697. X                break;
  1698. X            default:
  1699. X                error("diff failed");
  1700. X        }
  1701. X    } while (cleanup(),
  1702. X         ++argv, --argc >=1);
  1703. X
  1704. X
  1705. X    tempunlink();
  1706. X    exitmain(exitstatus);
  1707. X}
  1708. X
  1709. X    static void
  1710. cleanup()
  1711. X{
  1712. X    if (nerror) exitstatus = DIFF_TROUBLE;
  1713. X    Izclose(&finptr);
  1714. X    Izclose(&workptr);
  1715. X}
  1716. X
  1717. X#if lint
  1718. X#    define exiterr rdiffExit
  1719. X#endif
  1720. X    exiting void
  1721. exiterr()
  1722. X{
  1723. X    tempunlink();
  1724. X    _exit(DIFF_TROUBLE);
  1725. X}
  1726. X
  1727. X#if DIFF_L
  1728. X    static char const *
  1729. setup_label(b, name, date)
  1730. X    struct buf *b;
  1731. X    char const *name;
  1732. X    char const date[datesize];
  1733. X{
  1734. X    char *p;
  1735. X    size_t l = strlen(name) + 3;
  1736. X    bufalloc(b, l+datesize);
  1737. X    p = b->string;
  1738. X    VOID sprintf(p, "-L%s\t", name);
  1739. X    VOID date2str(date, p+l);
  1740. X    return p;
  1741. X}
  1742. X#endif
  1743. END_OF_FILE
  1744. if test 11285 -ne `wc -c <'src/rcsdiff.c'`; then
  1745.     echo shar: \"'src/rcsdiff.c'\" unpacked with wrong size!
  1746. fi
  1747. # end of 'src/rcsdiff.c'
  1748. fi
  1749. if test -f 'src/rcsfcmp.c' -a "${1}" != "-c" ; then 
  1750.   echo shar: Will not clobber existing file \"'src/rcsfcmp.c'\"
  1751. else
  1752. echo shar: Extracting \"'src/rcsfcmp.c'\" \(8406 characters\)
  1753. sed "s/^X//" >'src/rcsfcmp.c' <<'END_OF_FILE'
  1754. X/*
  1755. X *                     RCS file comparison
  1756. X */
  1757. X/*****************************************************************************
  1758. X *                       rcsfcmp()
  1759. X *                       Testprogram: define FCMPTEST
  1760. X *****************************************************************************
  1761. X */
  1762. X
  1763. X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
  1764. X   Copyright 1990, 1991 by Paul Eggert
  1765. X   Distributed under license by the Free Software Foundation, Inc.
  1766. X
  1767. This file is part of RCS.
  1768. X
  1769. RCS is free software; you can redistribute it and/or modify
  1770. it under the terms of the GNU General Public License as published by
  1771. the Free Software Foundation; either version 2, or (at your option)
  1772. any later version.
  1773. X
  1774. RCS is distributed in the hope that it will be useful,
  1775. but WITHOUT ANY WARRANTY; without even the implied warranty of
  1776. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1777. GNU General Public License for more details.
  1778. X
  1779. You should have received a copy of the GNU General Public License
  1780. along with RCS; see the file COPYING.  If not, write to
  1781. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  1782. X
  1783. Report problems and direct all questions to:
  1784. X
  1785. X    rcs-bugs@cs.purdue.edu
  1786. X
  1787. X*/
  1788. X
  1789. X
  1790. X
  1791. X
  1792. X
  1793. X/* $Log: rcsfcmp.c,v $
  1794. X * Revision 5.9  1991/10/07  17:32:46  eggert
  1795. X * Count log lines correctly.
  1796. X *
  1797. X * Revision 5.8  1991/08/19  03:13:55  eggert
  1798. X * Tune.
  1799. X *
  1800. X * Revision 5.7  1991/04/21  11:58:22  eggert
  1801. X * Fix errno bug.  Add MS-DOS support.
  1802. X *
  1803. X * Revision 5.6  1991/02/28  19:18:47  eggert
  1804. X * Open work file at most once.
  1805. X *
  1806. X * Revision 5.5  1990/11/27  09:26:05  eggert
  1807. X * Fix comment leader bug.
  1808. X *
  1809. X * Revision 5.4  1990/11/01  05:03:42  eggert
  1810. X * Permit arbitrary data in logs and comment leaders.
  1811. X *
  1812. X * Revision 5.3  1990/09/11  02:41:15  eggert
  1813. X * Don't ignore differences inside keyword strings if -ko is set.
  1814. X *
  1815. X * Revision 5.1  1990/08/29  07:13:58  eggert
  1816. X * Clean old log messages too.
  1817. X *
  1818. X * Revision 5.0  1990/08/22  08:12:49  eggert
  1819. X * Don't append "checked in with -k by " log to logs,
  1820. X * so that checking in a program with -k doesn't change it.
  1821. X * Ansify and Posixate.  Remove lint.
  1822. X *
  1823. X * Revision 4.5  89/05/01  15:12:42  narten
  1824. X * changed copyright header to reflect current distribution rules
  1825. X * 
  1826. X * Revision 4.4  88/08/09  19:12:50  eggert
  1827. X * Shrink stdio code size.
  1828. X * 
  1829. X * Revision 4.3  87/12/18  11:40:02  narten
  1830. X * lint cleanups (Guy Harris)
  1831. X * 
  1832. X * Revision 4.2  87/10/18  10:33:06  narten
  1833. X * updting version number. Changes relative to 1.1 actually relative to 
  1834. X * 4.1
  1835. X * 
  1836. X * Revision 1.2  87/03/27  14:22:19  jenkins
  1837. X * Port to suns
  1838. X * 
  1839. X * Revision 4.1  83/05/10  16:24:04  wft
  1840. X * Marker matching now uses trymatch(). Marker pattern is now
  1841. X * checked precisely.
  1842. X * 
  1843. X * Revision 3.1  82/12/04  13:21:40  wft
  1844. X * Initial revision.
  1845. X *
  1846. X */
  1847. X
  1848. X/*
  1849. X#define FCMPTEST
  1850. X*/
  1851. X/* Testprogram; prints out whether two files are identical,
  1852. X * except for keywords
  1853. X */
  1854. X
  1855. X#include  "rcsbase.h"
  1856. X
  1857. libId(fcmpId, "$Id: rcsfcmp.c,v 5.9 1991/10/07 17:32:46 eggert Exp $")
  1858. X
  1859. X    static int
  1860. discardkeyval(c, f)
  1861. X    register int c;
  1862. X    register RILE *f;
  1863. X{
  1864. X    for (;;)
  1865. X        switch (c) {
  1866. X            case KDELIM:
  1867. X            case '\n':
  1868. X                return c;
  1869. X            default:
  1870. X                Igeteof(f, c, return EOF;);
  1871. X                break;
  1872. X        }
  1873. X}
  1874. X
  1875. X    int
  1876. rcsfcmp(xfp, xstatp, ufname, delta)
  1877. X    register RILE *xfp;
  1878. X    struct stat const *xstatp;
  1879. X    char const *ufname;
  1880. X    struct hshentry const *delta;
  1881. X/* Compare the files xfp and ufname.  Return zero
  1882. X * if xfp has the same contents as ufname and neither has keywords,
  1883. X * otherwise -1 if they are the same ignoring keyword values,
  1884. X * and 1 if they differ even ignoring
  1885. X * keyword values. For the LOG-keyword, rcsfcmp skips the log message
  1886. X * given by the parameter delta in xfp.  Thus, rcsfcmp returns nonpositive
  1887. X * if xfp contains the same as ufname, with the keywords expanded.
  1888. X * Implementation: character-by-character comparison until $ is found.
  1889. X * If a $ is found, read in the marker keywords; if they are real keywords
  1890. X * and identical, read in keyword value. If value is terminated properly,
  1891. X * disregard it and optionally skip log message; otherwise, compare value.
  1892. X */
  1893. X{
  1894. X    register int xc, uc;
  1895. X    char xkeyword[keylength+2];
  1896. X    int eqkeyvals;
  1897. X    register RILE *ufp;
  1898. X    register int xeof, ueof;
  1899. X    register char * tp;
  1900. X    register char const *sp;
  1901. X    int result;
  1902. X    enum markers match1;
  1903. X    struct stat ustat;
  1904. X
  1905. X    if (!(ufp = Iopen(ufname, FOPEN_R_WORK, &ustat))) {
  1906. X       efaterror(ufname);
  1907. X    }
  1908. X    xeof = ueof = false;
  1909. X    if (Expand==OLD_EXPAND) {
  1910. X    if (!(result = xstatp->st_size!=ustat.st_size)) {
  1911. X#        if has_mmap && large_memory
  1912. X        result = !!memcmp(xfp->base,ufp->base,(size_t)xstatp->st_size);
  1913. X#        else
  1914. X        for (;;) {
  1915. X            /* get the next characters */
  1916. X            Igeteof(xfp, xc, xeof=true;);
  1917. X            Igeteof(ufp, uc, ueof=true;);
  1918. X            if (xeof | ueof)
  1919. X            goto eof;
  1920. X            if (xc != uc)
  1921. X            goto return1;
  1922. X        }
  1923. X#        endif
  1924. X    }
  1925. X    } else {
  1926. X    xc = 0;
  1927. X    uc = 0; /* Keep lint happy.  */
  1928. X    result = 0;
  1929. X
  1930. X    for (;;) {
  1931. X      if (xc != KDELIM) {
  1932. X        /* get the next characters */
  1933. X        Igeteof(xfp, xc, xeof=true;);
  1934. X        Igeteof(ufp, uc, ueof=true;);
  1935. X        if (xeof | ueof)
  1936. X        goto eof;
  1937. X      } else {
  1938. X        /* try to get both keywords */
  1939. X        tp = xkeyword;
  1940. X        for (;;) {
  1941. X        Igeteof(xfp, xc, xeof=true;);
  1942. X        Igeteof(ufp, uc, ueof=true;);
  1943. X        if (xeof | ueof)
  1944. X            goto eof;
  1945. X        if (xc != uc)
  1946. X            break;
  1947. X        switch (xc) {
  1948. X            default:
  1949. X            if (xkeyword+keylength <= tp)
  1950. X                break;
  1951. X            *tp++ = xc;
  1952. X            continue;
  1953. X            case '\n': case KDELIM: case VDELIM:
  1954. X            break;
  1955. X        }
  1956. X        break;
  1957. X        }
  1958. X        if (
  1959. X        (xc==KDELIM || xc==VDELIM)  &&  (uc==KDELIM || uc==VDELIM)  &&
  1960. X        (*tp = xc,  (match1 = trymatch(xkeyword)) != Nomatch)
  1961. X        ) {
  1962. X#ifdef FCMPTEST
  1963. X          VOID printf("found common keyword %s\n",xkeyword);
  1964. X#endif
  1965. X          result = -1;
  1966. X          for (;;) {
  1967. X          if (xc != uc) {
  1968. X              xc = discardkeyval(xc, xfp);
  1969. X              uc = discardkeyval(uc, ufp);
  1970. X              if ((xeof = xc==EOF)  |  (ueof = uc==EOF))
  1971. X              goto eof;
  1972. X              eqkeyvals = false;
  1973. X              break;
  1974. X          }
  1975. X          switch (xc) {
  1976. X              default:
  1977. X              Igeteof(xfp, xc, xeof=true;);
  1978. X              Igeteof(ufp, uc, ueof=true;);
  1979. X              if (xeof | ueof)
  1980. X                  goto eof;
  1981. X              continue;
  1982. X
  1983. X              case '\n': case KDELIM:
  1984. X              eqkeyvals = true;
  1985. X              break;
  1986. X          }
  1987. X          break;
  1988. X          }
  1989. X          if (xc != uc)
  1990. X          goto return1;
  1991. X          if (xc==KDELIM) {
  1992. X          /* Skip closing KDELIM.  */
  1993. X          Igeteof(xfp, xc, xeof=true;);
  1994. X          Igeteof(ufp, uc, ueof=true;);
  1995. X          if (xeof | ueof)
  1996. X              goto eof;
  1997. X          /* if the keyword is LOG, also skip the log message in xfp*/
  1998. X          if (match1==Log) {
  1999. X              /* first, compute the number of line feeds in log msg */
  2000. X              unsigned lncnt;
  2001. X              size_t ls, ccnt;
  2002. X              sp = delta->log.string;
  2003. X              ls = delta->log.size;
  2004. X              if (ls<sizeof(ciklog)-1 || memcmp(sp,ciklog,sizeof(ciklog)-1)) {
  2005. X            /* This log message was inserted.  */
  2006. X            lncnt = 3;
  2007. X            while (ls--) if (*sp++=='\n') lncnt++;
  2008. X            for (;;) {
  2009. X                if (xc=='\n')
  2010. X                if(--lncnt==0) break;
  2011. X                Igeteof(xfp, xc, goto returnresult;);
  2012. X            }
  2013. X            /* skip last comment leader */
  2014. X            /* Can't just skip another line here, because there may be */
  2015. X            /* additional characters on the line (after the Log....$)  */
  2016. X            for (ccnt=Comment.size; ccnt--; ) {
  2017. X                Igeteof(xfp, xc, goto returnresult;);
  2018. X                if(xc=='\n') break;
  2019. X                /*
  2020. X                 * Read to the end of the comment leader or '\n',
  2021. X                 * whatever comes first.  Some editors strip
  2022. X                 * trailing white space from a leader like " * ".
  2023. X                 */
  2024. X            }
  2025. X              }
  2026. X          }
  2027. X          } else {
  2028. X          /* both end in the same character, but not a KDELIM */
  2029. X          /* must compare string values.*/
  2030. X#ifdef FCMPTEST
  2031. X          VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
  2032. X#endif
  2033. X          if (!eqkeyvals)
  2034. X              goto return1;
  2035. X          }
  2036. X        }
  2037. X      }
  2038. X      if (xc != uc)
  2039. X          goto return1;
  2040. X    }
  2041. X    }
  2042. X
  2043. X  eof:
  2044. X    if (xeof==ueof)
  2045. X    goto returnresult;
  2046. X  return1:
  2047. X    result = 1;
  2048. X  returnresult:
  2049. X    Ifclose(ufp);
  2050. X    return result;
  2051. X}
  2052. X
  2053. X
  2054. X
  2055. X#ifdef FCMPTEST
  2056. X
  2057. char const cmdid[] = "rcsfcmp";
  2058. X
  2059. main(argc, argv)
  2060. int  argc; char  *argv[];
  2061. X/* first argument: comment leader; 2nd: log message, 3rd: expanded file,
  2062. X * 4th: unexpanded file
  2063. X */
  2064. X{       struct hshentry delta;
  2065. X
  2066. X    Comment.string = argv[1];
  2067. X    Comment.size = strlen(argv[1]);
  2068. X    delta.log.string = argv[2];
  2069. X    delta.log.size = strlen(argv[2]);
  2070. X    if (rcsfcmp(Iopen(argv[3], FOPEN_R_WORK, (struct stat*)0), argv[4], &delta))
  2071. X                VOID printf("files are the same\n");
  2072. X        else    VOID printf("files are different\n");
  2073. X}
  2074. X#endif
  2075. END_OF_FILE
  2076. if test 8406 -ne `wc -c <'src/rcsfcmp.c'`; then
  2077.     echo shar: \"'src/rcsfcmp.c'\" unpacked with wrong size!
  2078. fi
  2079. # end of 'src/rcsfcmp.c'
  2080. fi
  2081. if test -f 'src/rcskeep.c' -a "${1}" != "-c" ; then 
  2082.   echo shar: Will not clobber existing file \"'src/rcskeep.c'\"
  2083. else
  2084. echo shar: Extracting \"'src/rcskeep.c'\" \(10028 characters\)
  2085. sed "s/^X//" >'src/rcskeep.c' <<'END_OF_FILE'
  2086. X/*
  2087. X *                     RCS keyword extraction
  2088. X */
  2089. X/*****************************************************************************
  2090. X *                       main routine: getoldkeys()
  2091. X *                       Testprogram: define KEEPTEST
  2092. X *****************************************************************************
  2093. X */
  2094. X
  2095. X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
  2096. X   Copyright 1990, 1991 by Paul Eggert
  2097. X   Distributed under license by the Free Software Foundation, Inc.
  2098. X
  2099. This file is part of RCS.
  2100. X
  2101. RCS is free software; you can redistribute it and/or modify
  2102. it under the terms of the GNU General Public License as published by
  2103. the Free Software Foundation; either version 2, or (at your option)
  2104. any later version.
  2105. X
  2106. RCS is distributed in the hope that it will be useful,
  2107. but WITHOUT ANY WARRANTY; without even the implied warranty of
  2108. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2109. GNU General Public License for more details.
  2110. X
  2111. You should have received a copy of the GNU General Public License
  2112. along with RCS; see the file COPYING.  If not, write to
  2113. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  2114. X
  2115. Report problems and direct all questions to:
  2116. X
  2117. X    rcs-bugs@cs.purdue.edu
  2118. X
  2119. X*/
  2120. X
  2121. X
  2122. X
  2123. X/* $Log: rcskeep.c,v $
  2124. X * Revision 5.4  1991/08/19  03:13:55  eggert
  2125. X * Tune.
  2126. X *
  2127. X * Revision 5.3  1991/04/21  11:58:25  eggert
  2128. X * Shorten names to keep them distinct on shortname hosts.
  2129. X *
  2130. X * Revision 5.2  1990/10/04  06:30:20  eggert
  2131. X * Parse time zone offsets; future RCS versions may output them.
  2132. X *
  2133. X * Revision 5.1  1990/09/20  02:38:56  eggert
  2134. X * ci -k now checks dates more thoroughly.
  2135. X *
  2136. X * Revision 5.0  1990/08/22  08:12:53  eggert
  2137. X * Retrieve old log message if there is one.
  2138. X * Don't require final newline.
  2139. X * Remove compile-time limits; use malloc instead.  Tune.
  2140. X * Permit dates past 1999/12/31.  Ansify and Posixate.
  2141. X *
  2142. X * Revision 4.6  89/05/01  15:12:56  narten
  2143. X * changed copyright header to reflect current distribution rules
  2144. X * 
  2145. X * Revision 4.5  88/08/09  19:13:03  eggert
  2146. X * Remove lint and speed up by making FILE *fp local, not global.
  2147. X * 
  2148. X * Revision 4.4  87/12/18  11:44:21  narten
  2149. X * more lint cleanups (Guy Harris)
  2150. X * 
  2151. X * Revision 4.3  87/10/18  10:35:50  narten
  2152. X * Updating version numbers. Changes relative to 1.1 actually relative
  2153. X * to 4.1
  2154. X * 
  2155. X * Revision 1.3  87/09/24  14:00:00  narten
  2156. X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  2157. X * warnings)
  2158. X * 
  2159. X * Revision 1.2  87/03/27  14:22:29  jenkins
  2160. X * Port to suns
  2161. X * 
  2162. X * Revision 4.1  83/05/10  16:26:44  wft
  2163. X * Added new markers Id and RCSfile; extraction added.
  2164. X * Marker matching with trymatch().
  2165. X * 
  2166. X * Revision 3.2  82/12/24  12:08:26  wft
  2167. X * added missing #endif.
  2168. X *
  2169. X * Revision 3.1  82/12/04  13:22:41  wft
  2170. X * Initial revision.
  2171. X *
  2172. X */
  2173. X
  2174. X/*
  2175. X#define KEEPTEST
  2176. X*/
  2177. X/* Testprogram; prints out the keyword values found. */
  2178. X
  2179. X#include  "rcsbase.h"
  2180. X
  2181. libId(keepId, "$Id: rcskeep.c,v 5.4 1991/08/19 03:13:55 eggert Exp $")
  2182. X
  2183. static int checknum P((char const*,int));
  2184. static int getval P((RILE*,struct buf*,int));
  2185. static int get0val P((int,RILE*,struct buf*,int));
  2186. static int keepdate P((RILE*));
  2187. static int keepid P((int,RILE*,struct buf*));
  2188. static int keeprev P((RILE*));
  2189. X
  2190. int prevkeys;
  2191. struct buf prevauthor, prevdate, prevrev, prevstate;
  2192. X
  2193. X    int
  2194. getoldkeys(fp)
  2195. X    register RILE *fp;
  2196. X/* Function: Tries to read keyword values for author, date,
  2197. X * revision number, and state out of the file fp.
  2198. X * If FNAME is nonnull, it is opened and closed instead of using FP.
  2199. X * The results are placed into
  2200. X * prevauthor, prevdate, prevrev, prevstate.
  2201. X * Aborts immediately if it finds an error and returns false.
  2202. X * If it returns true, it doesn't mean that any of the
  2203. X * values were found; instead, check to see whether the corresponding arrays
  2204. X * contain the empty string.
  2205. X */
  2206. X{
  2207. X    register int c;
  2208. X    char keyword[keylength+1];
  2209. X    register char * tp;
  2210. X    int needs_closing;
  2211. X
  2212. X    if (prevkeys)
  2213. X    return true;
  2214. X
  2215. X    needs_closing = false;
  2216. X    if (!fp) {
  2217. X    if (!(fp = Iopen(workfilename, FOPEN_R_WORK, (struct stat*)0))) {
  2218. X        eerror(workfilename);
  2219. X        return false;
  2220. X    }
  2221. X    needs_closing = true;
  2222. X    }
  2223. X
  2224. X    /* initialize to empty */
  2225. X    bufscpy(&prevauthor, "");
  2226. X    bufscpy(&prevdate, "");
  2227. X    bufscpy(&prevrev, "");
  2228. X    bufscpy(&prevstate, "");
  2229. X
  2230. X    c = '\0'; /* anything but KDELIM */
  2231. X    for (;;) {
  2232. X        if ( c==KDELIM) {
  2233. X        do {
  2234. X        /* try to get keyword */
  2235. X        tp = keyword;
  2236. X        for (;;) {
  2237. X            Igeteof(fp, c, goto ok;);
  2238. X            switch (c) {
  2239. X            default:
  2240. X                if (keyword+keylength <= tp)
  2241. X                break;
  2242. X                *tp++ = c;
  2243. X                continue;
  2244. X
  2245. X            case '\n': case KDELIM: case VDELIM:
  2246. X                break;
  2247. X            }
  2248. X            break;
  2249. X        }
  2250. X        } while (c==KDELIM);
  2251. X            if (c!=VDELIM) continue;
  2252. X        *tp = c;
  2253. X        Igeteof(fp, c, break;);
  2254. X        switch (c) {
  2255. X        case ' ': case '\t': break;
  2256. X        default: continue;
  2257. X        }
  2258. X
  2259. X        switch (trymatch(keyword)) {
  2260. X            case Author:
  2261. X        if (!keepid(0, fp, &prevauthor))
  2262. X            return false;
  2263. X        c = 0;
  2264. X                break;
  2265. X            case Date:
  2266. X        if (!(c = keepdate(fp)))
  2267. X            return false;
  2268. X                break;
  2269. X            case Header:
  2270. X            case Id:
  2271. X        if (!(
  2272. X              getval(fp, (struct buf*)nil, false) &&
  2273. X              keeprev(fp) &&
  2274. X              (c = keepdate(fp)) &&
  2275. X              keepid(c, fp, &prevauthor) &&
  2276. X              keepid(0, fp, &prevstate)
  2277. X        ))
  2278. X            return false;
  2279. X        /* Skip either ``who'' (new form) or ``Locker: who'' (old).  */
  2280. X        if (getval(fp, (struct buf*)nil, true) &&
  2281. X            getval(fp, (struct buf*)nil, true))
  2282. X            c = 0;
  2283. X        else if (nerror)
  2284. X            return false;
  2285. X        else
  2286. X            c = KDELIM;
  2287. X        break;
  2288. X            case Locker:
  2289. X            case Log:
  2290. X            case RCSfile:
  2291. X            case Source:
  2292. X        if (!getval(fp, (struct buf*)nil, false))
  2293. X            return false;
  2294. X        c = 0;
  2295. X                break;
  2296. X            case Revision:
  2297. X        if (!keeprev(fp))
  2298. X            return false;
  2299. X        c = 0;
  2300. X                break;
  2301. X            case State:
  2302. X        if (!keepid(0, fp, &prevstate))
  2303. X            return false;
  2304. X        c = 0;
  2305. X                break;
  2306. X            default:
  2307. X               continue;
  2308. X            }
  2309. X        if (!c)
  2310. X        Igeteof(fp, c, c=0;);
  2311. X        if (c != KDELIM) {
  2312. X        error("closing %c missing on keyword", KDELIM);
  2313. X        return false;
  2314. X        }
  2315. X        if (*prevauthor.string && *prevdate.string && *prevrev.string && *prevstate.string) {
  2316. X                break;
  2317. X           }
  2318. X        }
  2319. X    Igeteof(fp, c, break;);
  2320. X    }
  2321. X
  2322. X ok:
  2323. X    if (needs_closing)
  2324. X    Ifclose(fp);
  2325. X    else
  2326. X    Irewind(fp);
  2327. X    prevkeys = true;
  2328. X    return true;
  2329. X}
  2330. X
  2331. X    static int
  2332. badly_terminated()
  2333. X{
  2334. X    error("badly terminated keyword value");
  2335. X    return false;
  2336. X}
  2337. X
  2338. X    static int
  2339. getval(fp, target, optional)
  2340. X    register RILE *fp;
  2341. X    struct buf *target;
  2342. X    int optional;
  2343. X/* Reads a keyword value from FP into TARGET.
  2344. X * Returns true if one is found, false otherwise.
  2345. X * Does not modify target if it is nil.
  2346. X * Do not report an error if OPTIONAL is set and KDELIM is found instead.
  2347. X */
  2348. X{
  2349. X    int c;
  2350. X    Igeteof(fp, c, return badly_terminated(););
  2351. X    return get0val(c, fp, target, optional);
  2352. X}
  2353. X
  2354. X    static int
  2355. get0val(c, fp, target, optional)
  2356. X    register int c;
  2357. X    register RILE *fp;
  2358. X    struct buf *target;
  2359. X    int optional;
  2360. X/* Reads a keyword value from C+FP into TARGET, perhaps OPTIONALly.
  2361. X * Same as getval, except C is the lookahead character.
  2362. X */
  2363. X{   register char * tp;
  2364. X    char const *tlim;
  2365. X    register int got1;
  2366. X
  2367. X    if (target) {
  2368. X    bufalloc(target, 1);
  2369. X    tp = target->string;
  2370. X    tlim = tp + target->size;
  2371. X    } else
  2372. X    tlim = tp = 0;
  2373. X    got1 = false;
  2374. X    for (;;) {
  2375. X    switch (c) {
  2376. X        default:
  2377. X        got1 = true;
  2378. X        if (tp) {
  2379. X            *tp++ = c;
  2380. X            if (tlim <= tp)
  2381. X            tp = bufenlarge(target, &tlim);
  2382. X        }
  2383. X        break;
  2384. X
  2385. X        case ' ':
  2386. X        case '\t':
  2387. X        if (tp) {
  2388. X            *tp = 0;
  2389. X#            ifdef KEEPTEST
  2390. X            VOID printf("getval: %s\n", target);
  2391. X#            endif
  2392. X        }
  2393. X        if (!got1)
  2394. X            error("too much white space in keyword value");
  2395. X        return got1;
  2396. X
  2397. X        case KDELIM:
  2398. X        if (!got1 && optional)
  2399. X            return false;
  2400. X        /* fall into */
  2401. X        case '\n':
  2402. X        case 0:
  2403. X        return badly_terminated();
  2404. X    }
  2405. X    Igeteof(fp, c, return badly_terminated(););
  2406. X    }
  2407. X}
  2408. X
  2409. X
  2410. X    static int
  2411. keepdate(fp)
  2412. X    RILE *fp;
  2413. X/* Function: reads a date prevdate; checks format
  2414. X * Return 0 on error, lookahead character otherwise.
  2415. X */
  2416. X{
  2417. X    struct buf prevday, prevtime, prevzone;
  2418. X    register char const *p;
  2419. X    register int c;
  2420. X
  2421. X    c = 0;
  2422. X    bufautobegin(&prevday);
  2423. X    if (getval(fp,&prevday,false)) {
  2424. X    bufautobegin(&prevtime);
  2425. X    if (getval(fp,&prevtime,false)) {
  2426. X        bufautobegin(&prevzone);
  2427. X        bufscpy(&prevzone, "");
  2428. X        Igeteof(fp, c, c=0;);
  2429. X        if (c=='-' || c=='+')
  2430. X        if (!get0val(c,fp,&prevzone,false))
  2431. X            c = 0;
  2432. X        else
  2433. X            Igeteof(fp, c, c=0;);
  2434. X        if (c) {
  2435. X        p = prevday.string;
  2436. X        bufalloc(&prevdate, strlen(p) + strlen(prevtime.string) + strlen(prevzone.string) + 5);
  2437. X        VOID sprintf(prevdate.string, "%s%s %s %s",
  2438. X            /* Parse dates put out by old versions of RCS.  */
  2439. X            isdigit(p[0]) && isdigit(p[1]) && p[2]=='/'  ?  "19"  :  "",
  2440. X            p, prevtime.string, prevzone.string
  2441. X        );
  2442. X        }
  2443. X        bufautoend(&prevzone);
  2444. X    }
  2445. X    bufautoend(&prevtime);
  2446. X    }
  2447. X    bufautoend(&prevday);
  2448. X    return c;
  2449. X}
  2450. X
  2451. X    static int
  2452. keepid(c, fp, b)
  2453. X    int c;
  2454. X    RILE *fp;
  2455. X    struct buf *b;
  2456. X/* Get previous identifier from C+FP into B.  */
  2457. X{
  2458. X    if (!c)
  2459. X        Igeteof(fp, c, return false;);
  2460. X    if (!get0val(c, fp, b, false))
  2461. X        return false;
  2462. X    checksid(b->string);
  2463. X    return true;
  2464. X}
  2465. X
  2466. X    static int
  2467. keeprev(fp)
  2468. X    RILE *fp;
  2469. X/* Get previous revision from FP into prevrev.  */
  2470. X{
  2471. X    return getval(fp,&prevrev,false) && checknum(prevrev.string,-1);
  2472. X}
  2473. X
  2474. X
  2475. X    static int
  2476. checknum(sp,fields)
  2477. X    register char const *sp;
  2478. X    int fields;
  2479. X{    register int dotcount;
  2480. X     dotcount=0;
  2481. X     while(*sp) {
  2482. X        if (*sp=='.') dotcount++;
  2483. X    else if (!isdigit(*sp)) return false;
  2484. X        sp++;
  2485. X     }
  2486. X     return fields<0 ? dotcount&1 : dotcount==fields;
  2487. X}
  2488. X
  2489. X
  2490. X
  2491. X#ifdef KEEPTEST
  2492. X
  2493. char const cmdid[] ="keeptest";
  2494. X
  2495. X    int
  2496. main(argc, argv)
  2497. int  argc; char  *argv[];
  2498. X{
  2499. X        while (*(++argv)) {
  2500. X        workfilename = *argv;
  2501. X        getoldkeys((RILE*)0);
  2502. X                VOID printf("%s:  revision: %s, date: %s, author: %s, state: %s\n",
  2503. X                *argv, prevrev.string, prevdate.string, prevauthor.string, prevstate.string);
  2504. X    }
  2505. X    exitmain(EXIT_SUCCESS);
  2506. X}
  2507. X#endif
  2508. END_OF_FILE
  2509. if test 10028 -ne `wc -c <'src/rcskeep.c'`; then
  2510.     echo shar: \"'src/rcskeep.c'\" unpacked with wrong size!
  2511. fi
  2512. # end of 'src/rcskeep.c'
  2513. fi
  2514. if test -f 'src/rcsmerge.c' -a "${1}" != "-c" ; then 
  2515.   echo shar: Will not clobber existing file \"'src/rcsmerge.c'\"
  2516. else
  2517. echo shar: Extracting \"'src/rcsmerge.c'\" \(6990 characters\)
  2518. sed "s/^X//" >'src/rcsmerge.c' <<'END_OF_FILE'
  2519. X/*
  2520. X *                       rcsmerge operation
  2521. X */
  2522. X/*****************************************************************************
  2523. X *                       join 2 revisions with respect to a third
  2524. X *****************************************************************************
  2525. X */
  2526. X
  2527. X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
  2528. X   Copyright 1990, 1991 by Paul Eggert
  2529. X   Distributed under license by the Free Software Foundation, Inc.
  2530. X
  2531. This file is part of RCS.
  2532. X
  2533. RCS is free software; you can redistribute it and/or modify
  2534. it under the terms of the GNU General Public License as published by
  2535. the Free Software Foundation; either version 2, or (at your option)
  2536. any later version.
  2537. X
  2538. RCS is distributed in the hope that it will be useful,
  2539. but WITHOUT ANY WARRANTY; without even the implied warranty of
  2540. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2541. GNU General Public License for more details.
  2542. X
  2543. You should have received a copy of the GNU General Public License
  2544. along with RCS; see the file COPYING.  If not, write to
  2545. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  2546. X
  2547. Report problems and direct all questions to:
  2548. X
  2549. X    rcs-bugs@cs.purdue.edu
  2550. X
  2551. X*/
  2552. X
  2553. X
  2554. X
  2555. X/* $Log: rcsmerge.c,v $
  2556. X * Revision 5.7  1991/11/20  17:58:09  eggert
  2557. X * Don't Iopen(f, "r+"); it's not portable.
  2558. X *
  2559. X * Revision 5.6  1991/08/19  03:13:55  eggert
  2560. X * Add -r$.  Tune.
  2561. X *
  2562. X * Revision 5.5  1991/04/21  11:58:27  eggert
  2563. X * Add -x, RCSINIT, MS-DOS support.
  2564. X *
  2565. X * Revision 5.4  1991/02/25  07:12:43  eggert
  2566. X * Merging a revision to itself is no longer an error.
  2567. X *
  2568. X * Revision 5.3  1990/11/01  05:03:50  eggert
  2569. X * Remove unneeded setid check.
  2570. X *
  2571. X * Revision 5.2  1990/09/04  08:02:28  eggert
  2572. X * Check for I/O error when reading working file.
  2573. X *
  2574. X * Revision 5.1  1990/08/29  07:14:04  eggert
  2575. X * Add -q.  Pass -L options to merge.
  2576. X *
  2577. X * Revision 5.0  1990/08/22  08:13:41  eggert
  2578. X * Propagate merge's exit status.
  2579. X * Remove compile-time limits; use malloc instead.
  2580. X * Make lock and temp files faster and safer.  Ansify and Posixate.  Add -V.
  2581. X * Don't use access().  Tune.
  2582. X *
  2583. X * Revision 4.5  89/05/01  15:13:16  narten
  2584. X * changed copyright header to reflect current distribution rules
  2585. X * 
  2586. X * Revision 4.4  88/08/09  19:13:13  eggert
  2587. X * Beware merging into a readonly file.
  2588. X * Beware merging a revision to itself (no change).
  2589. X * Use execv(), not system(); yield exit status like diff(1)'s.
  2590. X * 
  2591. X * Revision 4.3  87/10/18  10:38:02  narten
  2592. X * Updating version numbers. Changes relative to version 1.1 
  2593. X * actually relative to 4.1
  2594. X * 
  2595. X * Revision 1.3  87/09/24  14:00:31  narten
  2596. X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  2597. X * warnings)
  2598. X * 
  2599. X * Revision 1.2  87/03/27  14:22:36  jenkins
  2600. X * Port to suns
  2601. X * 
  2602. X * Revision 4.1  83/03/28  11:14:57  wft
  2603. X * Added handling of default branch.
  2604. X * 
  2605. X * Revision 3.3  82/12/24  15:29:00  wft
  2606. X * Added call to catchsig().
  2607. X *
  2608. X * Revision 3.2  82/12/10  21:32:02  wft
  2609. X * Replaced getdelta() with gettree(); improved error messages.
  2610. X *
  2611. X * Revision 3.1  82/11/28  19:27:44  wft
  2612. X * Initial revision.
  2613. X *
  2614. X */
  2615. X#include "rcsbase.h"
  2616. X
  2617. static char const co[] = CO;
  2618. X
  2619. mainProg(rcsmergeId, "rcsmerge", "$Id: rcsmerge.c,v 5.7 1991/11/20 17:58:09 eggert Exp $")
  2620. X{
  2621. X    static char const cmdusage[] =
  2622. X        "\nrcsmerge usage: rcsmerge -rrev1 [-rrev2] [-p] [-Vn] file";
  2623. X    static char const quietarg[] = "-q";
  2624. X
  2625. X    register int i;
  2626. X    char *a, **newargv;
  2627. X    char const *arg[3];
  2628. X    char const *rev[2]; /*revision numbers*/
  2629. X    char const *expandarg, *versionarg;
  2630. X        int tostdout;
  2631. X    int status;
  2632. X    RILE *workptr;
  2633. X    struct buf commarg;
  2634. X    struct buf numericrev; /* holds expanded revision number */
  2635. X    struct hshentries *gendeltas; /* deltas to be generated */
  2636. X        struct hshentry * target;
  2637. X
  2638. X    bufautobegin(&commarg);
  2639. X    bufautobegin(&numericrev);
  2640. X    rev[0] = rev[1] = nil;
  2641. X    status = 0; /* Keep lint happy.  */
  2642. X    tostdout = false;
  2643. X    expandarg = versionarg = quietarg; /* i.e. a no-op */
  2644. X    suffixes = X_DEFAULT;
  2645. X
  2646. X    argc = getRCSINIT(argc, argv, &newargv);
  2647. X    argv = newargv;
  2648. X    while (a = *++argv,  0<--argc && *a++=='-') {
  2649. X        switch (*a++) {
  2650. X                case 'p':
  2651. X                        tostdout=true;
  2652. X            goto revno;
  2653. X
  2654. X        case 'q':
  2655. X            quietflag = true;
  2656. X        revno:
  2657. X            if (!*a)
  2658. X                break;
  2659. X                        /* falls into -r */
  2660. X                case 'r':
  2661. X            if (!rev[0])
  2662. X                rev[0] = a;
  2663. X            else if (!rev[1])
  2664. X                rev[1] = a;
  2665. X            else
  2666. X                faterror("too many revision numbers");
  2667. X                        break;
  2668. X        case 'x':
  2669. X            suffixes = a;
  2670. X            break;
  2671. X        case 'V':
  2672. X            versionarg = *argv;
  2673. X            setRCSversion(versionarg);
  2674. X            break;
  2675. X
  2676. X        case 'k':
  2677. X            expandarg = *argv;
  2678. X            if (0 <= str2expmode(expandarg+2))
  2679. X                break;
  2680. X            /* fall into */
  2681. X                default:
  2682. X            faterror("unknown option: %s%s", *argv, cmdusage);
  2683. X                };
  2684. X        } /* end of option processing */
  2685. X
  2686. X    if (argc<1) faterror("no input file%s", cmdusage);
  2687. X    if (!rev[0]) faterror("no base revision number given");
  2688. X
  2689. X        /* now handle all filenames */
  2690. X
  2691. X    if (0  <  pairfilenames(argc, argv, rcsreadopen, true, false)) {
  2692. X
  2693. X                if (argc>2 || (argc==2&&argv[1]!=nil))
  2694. X                        warn("too many arguments");
  2695. X        diagnose("RCS file: %s\n", RCSfilename);
  2696. X        if (!(workptr = Iopen(workfilename,
  2697. X            FOPEN_R_WORK,
  2698. X            (struct stat*)0
  2699. X        )))
  2700. X            efaterror(workfilename);
  2701. X
  2702. X                gettree();  /* reads in the delta tree */
  2703. X
  2704. X                if (Head==nil) faterror("no revisions present");
  2705. X
  2706. X        if (!*rev[0])
  2707. X            rev[0]  =  Dbranch ? Dbranch : Head->num;
  2708. X        if (!fexpandsym(rev[0], &numericrev, workptr))
  2709. X            goto end;
  2710. X        if (!(target=genrevs(numericrev.string, (char *)nil, (char *)nil, (char *)nil,&gendeltas))) goto end;
  2711. X        rev[0] = target->num;
  2712. X        if (!rev[1] || !*rev[1])
  2713. X            rev[1]  =  Dbranch ? Dbranch : Head->num;
  2714. X        if (!fexpandsym(rev[1], &numericrev, workptr))
  2715. X            goto end;
  2716. X        if (!(target=genrevs(numericrev.string, (char *)nil, (char *)nil, (char *)nil,&gendeltas))) goto end;
  2717. X        rev[1] = target->num;
  2718. X
  2719. X        if (strcmp(rev[0],rev[1]) == 0) {
  2720. X            if (tostdout) {
  2721. X                FILE *o;
  2722. X#                if text_equals_binary_stdio || text_work_stdio
  2723. X                    o = stdout;
  2724. X#                else
  2725. X                    if (!(o=fdopen(STDOUT_FILENO,FOPEN_W_WORK)))
  2726. X                    efaterror("stdout");
  2727. X#                endif
  2728. X                fastcopy(workptr,o);
  2729. X                Ofclose(o);
  2730. X            }
  2731. X            goto end;
  2732. X        }
  2733. X        Izclose(&workptr);
  2734. X
  2735. X        for (i=0; i<2; i++) {
  2736. X            diagnose("retrieving revision %s\n", rev[i]);
  2737. X            bufscpy(&commarg, "-p");
  2738. X            bufscat(&commarg, rev[i]);
  2739. X            if (run(
  2740. X                (char*)0,
  2741. X                /* Do not collide with merger.c maketemp().  */
  2742. X                arg[i+1] = maketemp(i+3),
  2743. X                co, quietarg, commarg.string, expandarg,
  2744. X                versionarg, RCSfilename, (char*)0
  2745. X            ))
  2746. X                faterror("co failed");
  2747. X        }
  2748. X        diagnose("Merging differences between %s and %s into %s%s\n",
  2749. X             rev[0], rev[1], workfilename,
  2750. X                         tostdout?"; result to stdout":"");
  2751. X
  2752. X        arg[0] = rev[0] = workfilename;
  2753. X        status = merge(tostdout, rev, arg);
  2754. X        }
  2755. X
  2756. end:
  2757. X    Izclose(&workptr);
  2758. X    tempunlink();
  2759. X    exitmain(nerror ? DIFF_TROUBLE : status);
  2760. X}
  2761. X
  2762. X#if lint
  2763. X#    define exiterr rmergeExit
  2764. X#endif
  2765. X    exiting void
  2766. exiterr()
  2767. X{
  2768. X    tempunlink();
  2769. X    _exit(DIFF_TROUBLE);
  2770. X}
  2771. END_OF_FILE
  2772. if test 6990 -ne `wc -c <'src/rcsmerge.c'`; then
  2773.     echo shar: \"'src/rcsmerge.c'\" unpacked with wrong size!
  2774. fi
  2775. # end of 'src/rcsmerge.c'
  2776. fi
  2777. if test -f 'src/rcstest' -a "${1}" != "-c" ; then 
  2778.   echo shar: Will not clobber existing file \"'src/rcstest'\"
  2779. else
  2780. echo shar: Extracting \"'src/rcstest'\" \(9809 characters\)
  2781. sed "s/^X//" >'src/rcstest' <<'END_OF_FILE'
  2782. X#!/bin/sh
  2783. X
  2784. X# Test RCS's functions.
  2785. X# The RCS commands are searched for in the PATH as usual;
  2786. X# to test the working directory's commands, prepend . to your PATH.
  2787. X
  2788. X# Test RCS by creating files RCS/a.* and RCS/a.c.
  2789. X# If all goes well, output nothing, and remove the temporary files.
  2790. X# Otherwise, send a message to standard output.
  2791. X# Exit status is 0 if OK, 1 if an RCS bug is found, and 2 if scaffolding fails.
  2792. X# With the -v option, output more debugging info.
  2793. X
  2794. X# If diff outputs `No differences encountered' when comparing identical files,
  2795. X# then rcstest may also output these noise lines; ignore them.
  2796. X
  2797. X# The current directory and ./RCS must be readable, writable, and searchable.
  2798. X
  2799. X#    $Id: rcstest,v 5.8 1991/11/20 17:58:10 eggert Exp $
  2800. X
  2801. X
  2802. X#    Copyright 1990, 1991 by Paul Eggert
  2803. X#    Distributed under license by the Free Software Foundation, Inc.
  2804. X#
  2805. X# This file is part of RCS.
  2806. X#
  2807. X# RCS is free software; you can redistribute it and/or modify
  2808. X# it under the terms of the GNU General Public License as published by
  2809. X# the Free Software Foundation; either version 2, or (at your option)
  2810. X# any later version.
  2811. X#
  2812. X# RCS is distributed in the hope that it will be useful,
  2813. X# but WITHOUT ANY WARRANTY; without even the implied warranty of
  2814. X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2815. X# GNU General Public License for more details.
  2816. X#
  2817. X# You should have received a copy of the GNU General Public License
  2818. X# along with RCS; see the file COPYING.  If not, write to
  2819. X# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  2820. X#
  2821. X# Report problems and direct all questions to:
  2822. X#
  2823. X#     rcs-bugs@cs.purdue.edu
  2824. X
  2825. RCSINIT=-x
  2826. export RCSINIT
  2827. X
  2828. SLASH=/
  2829. RCSfile=RCS${SLASH}a.c
  2830. RCS_alt=RCS${SLASH}a.d
  2831. lockfile=RCS${SLASH}a._
  2832. X
  2833. case $1 in
  2834. X-v) q=; set -x;;
  2835. X'') q=-q;;
  2836. X*) echo >&2 "$0: usage: $0 [-v]"; exit 2
  2837. esac
  2838. X
  2839. test -d RCS || {
  2840. X    echo >&2 "$0: RCS: not a directory; please \`mkdir RCS' first."
  2841. X    exit 1
  2842. X}
  2843. X
  2844. rm -f a.* $RCSfile $RCS_alt $lockfile &&
  2845. echo 1.1 >a.11 &&
  2846. echo 1.1.1.1 >a.3x1 &&
  2847. echo 1.2 >a.12 || { echo "#initialization failed"; exit 2; }
  2848. X
  2849. case `diff -c a.11 a.3x1` in
  2850. X*'! 1.1.1.1')
  2851. X    diff='diff -c';;
  2852. X*)
  2853. X    echo "#warning: diff -c does not work, so diagnostics may be cryptic"
  2854. X    diff=diff
  2855. esac
  2856. X
  2857. rcs -i -L -ta.11 $q a.c &&
  2858. X<$RCSfile || {
  2859. X    echo "#rcs -i -L failed; perhaps RCS is not properly installed."
  2860. X    exit 1
  2861. X}
  2862. X
  2863. rlog a.c >/dev/null || { echo "#rlog failed on empty RCS file"; exit 1; }
  2864. rm -f $RCSfile || exit 2
  2865. X
  2866. cp a.11 a.c &&
  2867. ci -ta.11 -mm $q a.c &&
  2868. X<$RCSfile &&
  2869. rcs -L $q a.c || { echo "#ci+rcs -L failed"; exit 1; }
  2870. test ! -f a.c || { echo "#ci did not remove working file"; exit 1; }
  2871. for l in '' '-l'
  2872. do
  2873. X    co $l $q a.c &&
  2874. X    test -f a.c || { echo '#co' $l did not create working file; exit 1; }
  2875. X    $diff a.11 a.c || { echo '#ci' followed by co $l is not a no-op; exit 1; }
  2876. done
  2877. X
  2878. cp a.12 a.c &&
  2879. ci -mm $q a.c &&
  2880. co $q a.c &&
  2881. X$diff a.12 a.c || { echo "#ci+co failed"; exit 1; }
  2882. X
  2883. co -r1.1 $q a.c &&
  2884. X$diff a.11 a.c || { echo "#can't retrieve first revision"; exit 1; }
  2885. X
  2886. rm -f a.c &&
  2887. cp a.3x1 a.c &&
  2888. ci -r1.1.1 -mm $q a.c &&
  2889. co -r1.1.1.1 $q a.c &&
  2890. X$diff a.3x1 a.c || { echo "#branches failed"; exit 1; }
  2891. X
  2892. co -l $q a.c &&
  2893. ci -f -mm $q a.c &&
  2894. co -r1.3 $q a.c &&
  2895. X$diff a.12 a.c || { echo "#(co -l; ci -f) failed"; exit 1; }
  2896. X
  2897. co -l $q a.c &&
  2898. echo 1.4 >a.c &&
  2899. ci -l -mm $q a.c &&
  2900. echo error >a.c &&
  2901. ci -mm $q a.c || { echo "#ci -l failed"; exit 1; }
  2902. X
  2903. co -l $q a.c &&
  2904. echo 1.5 >a.c &&
  2905. ci -u -mm $q a.c &&
  2906. X<a.c || { echo "#ci -u didn't create a working file"; exit 1; }
  2907. rm -f a.c &&
  2908. echo error >a.c || exit 2
  2909. ci -mm $q a.c 2>/dev/null && { echo "#ci -u didn't unlock the file"; exit 1; }
  2910. X
  2911. rm -f a.c &&
  2912. rcs -l $q a.c &&
  2913. co -u $q a.c || { echo "#rcs -l + co -u failed"; exit 1; }
  2914. rm -f a.c &&
  2915. echo error >a.c || exit 2
  2916. ci -mm $q a.c 2>/dev/null && { echo "#co -u didn't unlock the file"; exit 1; }
  2917. X
  2918. rm -f a.c &&
  2919. cp a.11 a.c &&
  2920. co -f $q a.c || { echo "#co -f failed"; exit 1; }
  2921. X$diff a.11 a.c >/dev/null && { echo "#co -f had no effect"; exit 1; }
  2922. X
  2923. co -p1.1 $q a.c >a.t &&
  2924. X$diff a.11 a.t || { echo "#co -p failed"; exit 1; }
  2925. X
  2926. for n in n N
  2927. do
  2928. X    rm -f a.c &&
  2929. X    co -l $q a.c &&
  2930. X    echo $n >a.$n &&
  2931. X    cp a.$n a.c &&
  2932. X    ci -${n}n -mm $q a.c &&
  2933. X    co -rn $q a.c &&
  2934. X    $diff a.$n a.c || { echo "#ci -$n failed"; exit 1; }
  2935. done
  2936. X
  2937. case $LOGNAME in
  2938. X?*) me=$LOGNAME;;
  2939. X*)
  2940. X    case $USER in
  2941. X    ?*) me=$USER;;
  2942. X    *)
  2943. X        me=`who am i` || exit 2
  2944. X        me=`echo "$me" | sed -e 's/ .*//' -e 's/.*!//'`
  2945. X        case $me in
  2946. X        '') echo >&2 "$0: cannot deduce user name"; exit 2
  2947. X        esac
  2948. X    esac
  2949. esac
  2950. date=`date -u 2>/dev/null` ||
  2951. date=`TZ=GMT0 date 2>/dev/null` ||
  2952. date=`TZ= date` || exit 2
  2953. set $date
  2954. case $2 in
  2955. Jan) m=01;; Feb) m=02;; Mar) m=03;; Apr) m=04;; May) m=05;; Jun) m=06;;
  2956. Jul) m=07;; Aug) m=08;; Sep) m=09;; Oct) m=10;; Nov) m=11;; Dec) m=12;;
  2957. X*) echo >&2 "$0: $2: unknown month name"; exit 2
  2958. esac
  2959. case $3 in
  2960. X?) d=0$3;;
  2961. X*) d=$3
  2962. esac
  2963. case $6 in
  2964. X[0-9][0-9][0-9][0-9]*) D=$6/$m/$d;;
  2965. X*)
  2966. X    case $5 in
  2967. X    [0-9][0-9][0-9][0-9]*) D=$5/$m/$d;;
  2968. X    *) echo >&2 "$0: bad date format: $date"; exit 2
  2969. X    esac
  2970. esac
  2971. T=$4
  2972. case $PWD in
  2973. X'') PWD=`pwd`
  2974. esac &&
  2975. co -l $q a.c &&
  2976. sed 's/@/$/g' >a.kv <<EOF
  2977. X@Author: w @
  2978. X@Date: $D $T @
  2979. X@Header: $PWD$SLASH$RCSfile 2.1 $D $T w s @
  2980. X@Id: a.c 2.1 $D $T w s @
  2981. X@Locker:  @
  2982. X@Log: a.c @
  2983. X * Revision 2.1  $D  $T  w
  2984. X * m
  2985. X *
  2986. X@RCSfile: a.c @
  2987. X@Revision: 2.1 @
  2988. X@Source: $PWD$SLASH$RCSfile @
  2989. X@State: s @
  2990. XEOF
  2991. test $? = 0 &&
  2992. sed 's/:.*\$/$/' a.kv >a.k &&
  2993. sed -e 's/w s [$]/w s '"$me"' $/' -e 's/[$]Locker: /&'"$me/" a.kv >a.kvl &&
  2994. sed -e '/^\$/!d' -e 's/\$$/: old $/' a.k >a.o &&
  2995. sed -e 's/\$[^ ]*: //' -e 's/ \$//' a.kv >a.v &&
  2996. cp a.o a.c &&
  2997. ci -d"$date" -ss -ww -u2.1 -mm $q a.c &&
  2998. X$diff a.kv a.c || { echo "#keyword expansion failed"; exit 1; }
  2999. co -p -ko $q a.c >a.oo &&
  3000. X$diff a.o a.oo || { echo "#co -p -ko failed"; exit 1; }
  3001. cp a.kv a.o || exit 2
  3002. rcs -o2.1 $q a.c &&
  3003. rcs -l $q a.c &&
  3004. ci -k -u $q a.c &&
  3005. X$diff a.kv a.c || { echo "#ci -k failed"; exit 1; }
  3006. sed '/^[^$]/d' a.kv >a.i &&
  3007. ident a.c >a.i1 &&
  3008. sed -e 1d -e 's/^[     ]*//' a.i1 >a.i2 &&
  3009. X$diff a.i a.i2 || { echo "#ident failed"; exit 1; }
  3010. X
  3011. rcs -i $q a.c 2>/dev/null && { echo "#rcs -i permitted existing file"; exit 1; }
  3012. X
  3013. co -l $q a.c &&
  3014. echo 2.2 >a.c &&
  3015. ci -mm $q a.c &&
  3016. echo 1.1.1.2 >a.c &&
  3017. rcs -l1.1.1 $q a.c &&
  3018. ci -r1.1.1.2 -mm $q a.c &&
  3019. rcs -b1.1.1 $q a.c &&
  3020. test " `co -p $q a.c`" = ' 1.1.1.2' || { echo "#rcs -b1.1.1 failed"; exit 1; }
  3021. rcs -b $q a.c &&
  3022. test " `co -p $q a.c`" = ' 2.2' || { echo "#rcs -b failed"; exit 1; }
  3023. X
  3024. echo 2.3 >a.c || exit 2
  3025. rcs -U $q a.c || { echo "#rcs -U failed"; exit 1; }
  3026. ci -mm $q a.c || { echo "#rcs -U didn't unset strict locking"; exit 1; }
  3027. rcs -L $q a.c || { echo "#rcs -L failed"; exit 1; }
  3028. echo error >a.c || exit 2
  3029. ci -mm $q a.c 2>/dev/null && { echo "#ci retest failed"; exit 1; }
  3030. X
  3031. rm -f a.c &&
  3032. log0=`rlog -h a.c` &&
  3033. co -l $q a.c &&
  3034. ci -mm $q a.c &&
  3035. log1=`rlog -h a.c` &&
  3036. test " $log0" = " $log1" || { echo "#unchanged ci didn't revert"; exit 1; }
  3037. X
  3038. rm -f a.c &&
  3039. rcs -nN:1.1 $q a.c &&
  3040. co -rN $q a.c &&
  3041. X$diff a.11 a.c || { echo "#rcs -n failed"; exit 1; }
  3042. X
  3043. rcs -NN:2.1 $q a.c &&
  3044. co -rN $q a.c &&
  3045. X$diff a.kv a.c || { echo "#rcs -N failed"; exit 1; }
  3046. X
  3047. co -l $q a.c &&
  3048. rcs -c':::' $q a.c &&
  3049. echo '$''Log$' >a.c &&
  3050. ci -u -mm $q a.c &&
  3051. test " `sed '$!d' a.c`" = ' :::' || { echo "#rcs -c failed"; exit 1; }
  3052. X
  3053. rcs -o2.2: $q a.c &&
  3054. co $q a.c &&
  3055. X$diff a.kv a.c || { echo "#rcs -o failed"; exit 1; }
  3056. X
  3057. rcsdiff -r1.1 -r2.1 $q a.c >a.0
  3058. case $? in
  3059. X1) ;;
  3060. X*) echo "#rcsdiff bad status"; exit 1
  3061. esac
  3062. diff a.11 a.kv >a.1
  3063. X$diff a.0 a.1 || { echo "#rcsdiff failed"; exit 1; }
  3064. X
  3065. rcs -l2.1 $q a.c || { echo "#rcs -l2.1 failed"; exit 1; }
  3066. for i in k kv kvl o v
  3067. do
  3068. X    rm -f a.c &&
  3069. X    cp a.$i a.c &&
  3070. X    rcsdiff -k$i $q a.c || { echo "#rcsdiff -k$i failed"; exit 1; }
  3071. done
  3072. co -p1.1 -ko $q a.c >a.t &&
  3073. X$diff a.11 a.t || { echo "#co -p1.1 -ko failed"; exit 1; }
  3074. rcs -u2.1 $q a.c || { echo "#rcs -u2.1 failed"; exit 1; }
  3075. X
  3076. rm -f a.c &&
  3077. co -l $q a.c &&
  3078. cat >a.c <<'EOF'
  3079. X2.2
  3080. a
  3081. b
  3082. c
  3083. d
  3084. XEOF
  3085. test $? = 0 &&
  3086. ci -l -mm $q a.c &&
  3087. co -p2.2 $q a.c | sed -e s/2.2/2.3/ -e s/b/b1/ >a.c &&
  3088. ci -l -mm $q a.c &&
  3089. co -p2.2 $q a.c | sed -e s/2.2/new/ -e s/d/d1/ >a.c || exit 2
  3090. cat >a.0 <<'EOF'
  3091. X2.3
  3092. a
  3093. b1
  3094. c
  3095. d1
  3096. XEOF
  3097. cat >a.1 <<'EOF'
  3098. X<<<<<<< a.c
  3099. new
  3100. X=======
  3101. X2.3
  3102. X>>>>>>> 2.3
  3103. a
  3104. b1
  3105. c
  3106. d1
  3107. XEOF
  3108. rcsmerge -r2.2 -r2.3 $q a.c
  3109. case $? in
  3110. X0)
  3111. X    if $diff a.0 a.c >/dev/null
  3112. X    then echo "#warning: diff3 -E does not work, " \
  3113. X        "so merge and rcsmerge ignore overlaps and suppress overlap lines."
  3114. X    else
  3115. X        $diff a.1 a.c || { echo "#rcsmerge failed (status 0)"; exit 1; }
  3116. X        echo "#warning: The diff3 lib program exit status ignores overlaps," \
  3117. X            "so rcsmerge does not warn about overlap lines that it generates."
  3118. X    fi
  3119. X    ;;
  3120. X1)
  3121. X    $diff a.1 a.c || { echo "#rcsmerge failed (status 1)"; exit 1; }
  3122. X    ;;
  3123. X*)
  3124. X    echo "#rcsmerge bad status"; exit 1
  3125. esac
  3126. X
  3127. nl='
  3128. X'
  3129. X{
  3130. X    co -p $q a.c | tr "$nl" '\200' >a.24 &&
  3131. X    cp a.24 a.c &&
  3132. X    ciOut=`(ci -l -mm $q a.c 2>&1)` &&
  3133. X    case $ciOut in
  3134. X    ?*) echo >&2 "$ciOut"
  3135. X    esac &&
  3136. X    co -p $q a.c | tr '\200' "$nl" >a.c &&
  3137. X    rcsdiff -r2.3 $q a.c >/dev/null &&
  3138. X
  3139. X    echo 2.5 >a.c &&
  3140. X    ci -l -mm $q a.c &&
  3141. X    cp a.24 a.c &&
  3142. X    rcsdiff -r2.4 $q a.c >/dev/null
  3143. X} || echo "#warning: Traditional diff is used, so RCS is limited to text files."
  3144. X
  3145. rcs -u -o2.4: $q a.c || { echo "#rcs -u -o failed"; exit 1; }
  3146. X
  3147. rcs -i -Aa.c -t- $q a.d || { echo "#rcs -i -A failed"; exit 1; }
  3148. X
  3149. rlog -r2.1 a.c >a.t &&
  3150. grep '^checked in with -k' a.t >/dev/null &&
  3151. sed '/^checked in with -k/d' a.t >a.u &&
  3152. X$diff - a.u <<EOF
  3153. X
  3154. RCS file: $RCSfile
  3155. Working file: a.c
  3156. head: 2.3
  3157. branch:
  3158. locks: strict
  3159. access list:
  3160. symbolic names:
  3161. X    N: 2.1
  3162. X    n: 1.8
  3163. comment leader: ":::"
  3164. keyword substitution: kv
  3165. total revisions: 13;    selected revisions: 1
  3166. description:
  3167. X1.1
  3168. X----------------------------
  3169. revision 2.1
  3170. date: $D $T;  author: w;  state: s;  lines: +13 -1
  3171. X=============================================================================
  3172. XEOF
  3173. test $? = 0 || { echo "#rlog failed"; exit 1; }
  3174. X
  3175. X
  3176. test ! -f $lockfile || { echo "#lock file not removed"; exit 1; }
  3177. X
  3178. exec rm -f a.* $RCSfile $RCS_alt
  3179. END_OF_FILE
  3180. if test 9809 -ne `wc -c <'src/rcstest'`; then
  3181.     echo shar: \"'src/rcstest'\" unpacked with wrong size!
  3182. fi
  3183. chmod +x 'src/rcstest'
  3184. # end of 'src/rcstest'
  3185. fi
  3186. echo shar: End of archive 2 \(of 11\).
  3187. cp /dev/null ark2isdone
  3188. MISSING=""
  3189. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  3190.     if test ! -f ark${I}isdone ; then
  3191.     MISSING="${MISSING} ${I}"
  3192.     fi
  3193. done
  3194. if test "${MISSING}" = "" ; then
  3195.     echo You have unpacked all 11 archives.
  3196.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  3197. else
  3198.     echo You still need to unpack the following archives:
  3199.     echo "        " ${MISSING}
  3200. fi
  3201. ##  End of shell archive.
  3202. exit 0
  3203.