v24i006: RCS source control system, Part06/12

Rich Salz rsalz at uunet.uu.net
Fri Feb 22 06:59:06 AEST 1991


Submitted-by: Adam Hammer <hammer at cs.purdue.edu>
Posting-number: Volume 24, Issue 6
Archive-name: rcs/part06

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# Contents:  man/rlog.1 src/rcsbase.h src/rcsedit.c
# Wrapped by rsalz at litchi.bbn.com on Thu Feb 21 14:37:00 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 6 (of 12)."'
if test -f 'man/rlog.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'man/rlog.1'\"
else
  echo shar: Extracting \"'man/rlog.1'\" \(5105 characters\)
  sed "s/^X//" >'man/rlog.1' <<'END_OF_FILE'
X.de Id
X.ds Rv \\$3
X.ds Dt \\$4
X..
X.Id $Id: rlog.1,v 5.0 1990/08/22 09:11:00 eggert Exp $
X.ds g \s-1GMT\s0
X.ds r \s-1RCS\s0
X.if n .ds - \%--
X.if t .ds - \(em
X.TH RLOG 1 \*(Dt GNU
X.SH NAME
Xrlog \- print log messages and other information about RCS files
X.SH SYNOPSIS
X.B rlog
X.RI [ " options " ] " file " .\|.\|.
X.SH DESCRIPTION
X.B rlog
Xprints information about \*r files.
XFile names ending in
X.B ,v
Xdenote \*r files; all others denote working files.
XIf a working file is given,
X.B rlog
Xtries to find the corresponding
X\*r file first in an \*r subdirectory and then in the working file's directory,
Xas explained in
X.BR co (1).
X.PP
X.B rlog
Xprints the following information for each
X\*r file: \*r file name, working file name, head (i.e., the number
Xof the latest revision on the trunk), default branch, access list, locks,
Xsymbolic names, suffix, total number of revisions,
Xnumber of revisions selected for printing, and
Xdescriptive text.  This is followed by entries for the selected revisions in
Xreverse chronological order for each branch.  For each revision,
X.B rlog
Xprints revision number, author, date/time, state, number of
Xlines added/deleted (with respect to the previous revision),
Xlocker of the revision (if any), and log message.
XAll times are displayed in \*g.
XWithout options,
X.B rlog
Xprints complete information.
XThe options below restrict this output.
X.nr n \w'\f3\-V\fP\f2n\fP '+1n-1/1n
X.TP \nn
X.B \-L
XIgnore \*r files that have no locks set.
XThis is convenient in combination with
X.BR \-h ,
X.BR \-l ,
Xand
X.BR \-R .
X.TP
X.B \-R
XPrint only the name of the \*r file.
XThis is convenient for translating a
Xworking file name into an \*r file name.
X.TP
X.B \-h
XPrint only the \*r file name, working file name, head,
Xdefault branch, access list, locks,
Xsymbolic names, and suffix.
X.TP
X.B \-t
XPrint the same as
X.BR \-h ,
Xplus the descriptive text.
X.TP
X.B \-b
XPrint information about the revisions on the default branch, normally
Xthe highest branch on the trunk.
X.TP
X.BI \-d "dates"
XPrint information about revisions with a checkin date/time in the ranges given by
Xthe semicolon-separated list of
X.IR dates .
XA range of the form
X.IB d1 < d2
Xor
X.IB d2 > d1
Xselects the revisions that were deposited between
X.I d1
Xand
X.I d2
Xinclusive.
XA range of the form
X.BI < d
Xor
X.IB d >
Xselects
Xall revisions dated
X.I d
Xor earlier.
XA range of the form
X.IB d <
Xor
X.BI > d
Xselects
Xall revisions dated
X.I d
Xor later.
XA range of the form
X.I d
Xselects the single, latest revision dated
X.I d
Xor earlier.
XThe date/time strings
X.IR d ,
X.IR d1 ,
Xand
X.I d2
Xare in the free format explained in
X.BR co (1).
XQuoting is normally necessary, especially for
X.B <
Xand
X.BR > .
XNote that the separator is
Xa semicolon.
X.TP
X.BR \-l [\f2lockers\fP]
XPrint information about locked revisions only.
XIn addition, if the comma-separated list
X.I lockers
Xof login names is given,
Xignore all locks other than those held by the
X.IR lockers .
XFor example,
X.B "rlog\ \-L\ \-R\ \-lwft\ RCS/*,v"
Xprints the name of \*r files locked by the user
X.BR wft .
X.TP
X.BI \-r revisions
Xprints information about revisions given in the comma-separated list
X.I revisions
Xof revisions and ranges.  A range
X.IB rev1 \- rev2
Xmeans revisions
X.I rev1
Xto
X.I rev2
Xon the same branch,
X.BI \- rev
Xmeans revisions from the beginning of the branch up to and including
X.IR rev ,
Xand
X.IB rev \-
Xmeans revisions starting with
X.I rev
Xto the end of the branch containing
X.IR rev .
XAn argument that is a branch means all
Xrevisions on that branch.
XA range of branches means all revisions
Xon the branches in that range.
X.TP
X.BI \-s states
Xprints information about revisions whose state attributes match one of the
Xstates given in the comma-separated list
X.IR states .
X.TP
X.BR \-w [\f2logins\fP]
Xprints information about revisions checked in by users with
Xlogin names appearing in the comma-separated list
X.IR logins .
XIf
X.I logins
Xis omitted, the user's login is assumed.
X.TP
X.BI \-V n
XEmulate \*r version
X.I n
Xwhen generating logs.
XSee
X.BR co (1)
Xfor more.
X.PP
X.B rlog
Xprints the intersection of the revisions selected with
Xthe options
X.BR \-d ,
X.BR \-l ,
X.BR \-s ,
Xand
X.BR \-w ,
Xintersected
Xwith the union of the revisions selected by
X.B \-b
Xand
X.BR \-r .
X.SH EXAMPLES
X.LP
X.nf
X.B "    rlog  \-L  \-R  RCS/*,v"
X.B "    rlog  \-L  \-h  RCS/*,v"
X.B "    rlog  \-L  \-l  RCS/*,v"
X.B "    rlog  RCS/*,v"
X.fi
X.LP
XThe first command prints the names of all \*r files in the subdirectory
X.B RCS
Xthat have locks.  The second command prints the headers of those files,
Xand the third prints the headers plus the log messages of the locked revisions.
XThe last command prints complete information.
X.SH DIAGNOSTICS
XThe exit status is zero if and only if all operations were successful.
X.SH IDENTIFICATION
XAuthor: Walter F. Tichy.
X.br
XRevision Number: \*(Rv; Release Date: \*(Dt.
X.br
XCopyright \(co 1982, 1988, 1989 by Walter F. Tichy.
X.br
XCopyright \(co 1990 by Paul Eggert.
X.SH "SEE ALSO"
Xci(1), co(1), ident(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1),
Xrcsfile(5)
X.br
XWalter F. Tichy,
X\*r\*-A System for Version Control,
X.I "Software\*-Practice & Experience"
X.BR 15 ,
X7 (July 1985), 637-654.
END_OF_FILE
  if test 5105 -ne `wc -c <'man/rlog.1'`; then
    echo shar: \"'man/rlog.1'\" unpacked with wrong size!
  fi
  # end of 'man/rlog.1'
fi
if test -f 'src/rcsbase.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/rcsbase.h'\"
else
  echo shar: Extracting \"'src/rcsbase.h'\" \(23601 characters\)
  sed "s/^X//" >'src/rcsbase.h' <<'END_OF_FILE'
X
X/*
X *                     RCS common definitions and data structures
X */
X#define RCSBASE "$Id: rcsbase.h,v 5.5 1990/12/04 05:18:43 eggert Exp $"
X
X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X   Copyright 1990 by Paul Eggert
X   Distributed under license by the Free Software Foundation, Inc.
X
XThis file is part of RCS.
X
XRCS is free software; you can redistribute it and/or modify
Xit under the terms of the GNU General Public License as published by
Xthe Free Software Foundation; either version 1, or (at your option)
Xany later version.
X
XRCS is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
XGNU General Public License for more details.
X
XYou should have received a copy of the GNU General Public License
Xalong with RCS; see the file COPYING.  If not, write to
Xthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
X
XReport problems and direct all questions to:
X
X    rcs-bugs at cs.purdue.edu
X
X*/
X
X
X
X/*****************************************************************************
X * INSTRUCTIONS:
X * =============
X * See the Makefile for how to define C preprocessor symbols.
X * If you need to change the comment leaders, update the table comtable[]
X * in rcsfnms.c. (This can wait until you know what a comment leader is.)
X *****************************************************************************
X */
X
X
X/* $Log: rcsbase.h,v $
X * Revision 5.5  1990/12/04  05:18:43  eggert
X * Use -I for prompts and -q for diagnostics.
X *
X * Revision 5.4  1990/11/01  05:03:35  eggert
X * Don't assume that builtins are functions; they may be macros.
X * Permit arbitrary data in logs.
X *
X * Revision 5.3  1990/09/26  23:36:58  eggert
X * Port wait() to non-Posix ANSI C hosts.
X *
X * Revision 5.2  1990/09/04  08:02:20  eggert
X * Don't redefine NAME_MAX, PATH_MAX.
X * Improve incomplete line handling.  Standardize yes-or-no procedure.
X *
X * Revision 5.1  1990/08/29  07:13:53  eggert
X * Add -kkvl.  Fix type typos exposed by porting.  Clean old log messages too.
X *
X * Revision 5.0  1990/08/22  08:12:44  eggert
X * Adjust ANSI C / Posix support.  Add -k, -V, setuid.  Don't call access().
X * Remove compile-time limits; use malloc instead.
X * Ansify and Posixate.  Add support for ISO 8859.
X * Remove snoop and v2 support.
X *
X * Revision 4.9  89/05/01  15:17:14  narten
X * botched previous USG fix 
X * 
X * Revision 4.8  89/05/01  14:53:05  narten
X * changed #include <strings.h> -> string.h for USG systems.
X * 
X * Revision 4.7  88/11/08  15:58:45  narten
X * removed defs for functions loaded from libraries
X * 
X * Revision 4.6  88/08/09  19:12:36  eggert
X * Shrink stdio code size; remove lint; permit -Dhshsize=nn.
X * 
X * Revision 4.5  87/12/18  17:06:41  narten
X * made removed BSD ifdef, now uses V4_2BSD
X * 
X * Revision 4.4  87/10/18  10:29:49  narten
X * Updating version numbers
X * Changes relative to 1.1 are actually relative to 4.2
X * 
X * Revision 1.3  87/09/24  14:02:25  narten
X * changes for lint
X * 
X * Revision 1.2  87/03/27  14:22:02  jenkins
X * Port to suns
X * 
X * Revision 4.2  83/12/20  16:04:20  wft
X * merged 3.6.1.1 and 4.1 (SMALLOG, logsize).
X * moved setting of STRICT_LOCKING to Makefile.
X * changed DOLLAR to UNKN (conflict with KDELIM).
X * 
X * Revision 4.1  83/05/04  09:12:41  wft
X * Added markers Id and RCSfile.
X * Added Dbranch for default branches.
X * 
X * Revision 3.6.1.1  83/12/02  21:56:22  wft
X * Increased logsize, added macro SMALLOG.
X * 
X * Revision 3.6  83/01/15  16:43:28  wft
X * 4.2 prerelease
X * 
X * Revision 3.6  83/01/15  16:43:28  wft
X * Replaced dbm.h with BYTESIZ, fixed definition of rindex().
X * Added variants of NCPFN and NCPPN for bsd 4.2, selected by defining V4_2BSD.
X * Added macro DELNUMFORM to have uniform format for printing delta text nodes.
X * Added macro DELETE to mark deleted deltas.
X *
X * Revision 3.5  82/12/10  12:16:56  wft
X * Added two forms of DATEFORM, one using %02d, the other %.2d.
X *
X * Revision 3.4  82/12/04  20:01:25  wft
X * added LOCKER, Locker, and USG (redefinition of rindex).
X *
X * Revision 3.3  82/12/03  12:22:04  wft
X * Added dbm.h, stdio.h, RCSBASE, RCSSEP, RCSSUF, WORKMODE, TMPFILE3,
X * PRINTDATE, PRINTTIME, map, and ctab; removed Suffix. Redefined keyvallength
X * using NCPPN. Changed putc() to abort on write error.
X *
X * Revision 3.2  82/10/18  15:03:52  wft
X * added macro STRICT_LOCKING, removed RCSUMASK.
X * renamed JOINFILE[1,2] to JOINFIL[1,2].
X *
X * Revision 3.1  82/10/11  19:41:17  wft
X * removed NBPW, NBPC, NCPW.
X * added typdef int void to aid compiling
X */
X
X/* GCC */
X#if __GNUC__ && !__STRICT_ANSI__
X#	define exiting volatile
X#else
X#	define exiting
X#endif
X
X
X/* standard include files */
X
X#include "conf.h"
X
X#if !MAKEDEPEND
X
X#include <errno.h>
X#include <signal.h>
X#include <time.h>
X
X
X/* ANSI C library */
X/* These declarations are for the benefit of non-ANSI C hosts.  */
X
X	/* <errno.h> */
X#	ifndef errno
X		extern int errno;
X#	endif
X
X	/* <limits.h> */
X#	ifndef CHAR_BIT
X#		define CHAR_BIT 8
X#	endif
X#	ifndef ULONG_MAX
X#		define ULONG_MAX (-(unsigned long)1)
X#	endif
X
X	/* <signal.h> */
X#	ifndef signal
X		signal_type (*signal P((int,signal_type(*)P((int)))))P((int));
X#	endif
X
X	/* <stdio.h> */
X	/* conf.h declares the troublesome printf family.  */
X#	ifndef L_tmpnam
X#		define L_tmpnam 25 /* sizeof("/usr/tmp/xxxxxxxxxxxxxxx") */
X#	endif
X#	ifndef SEEK_SET
X#		define SEEK_SET 0
X#	endif
X#	ifndef fopen
X		FILE *fopen P((const char*,const char*));
X#	endif
X#	ifndef fread
X		fread_type fread P((void*,size_t,size_t,FILE*));
X#	endif
X#	ifndef fwrite
X		fread_type fwrite P((const void*,size_t,size_t,FILE*));
X#	endif
X#	ifndef fclose
X		int fclose P((FILE*));
X#	endif
X#	ifndef fflush
X		int fflush P((FILE*));
X#	endif
X#	ifndef fputs
X		int fputs P((const char*,FILE*));
X#	endif
X#	ifndef fseek
X		int fseek P((FILE*,long,int));
X#	endif
X#	ifndef perror
X		void perror P((const char*));
X#	endif
X#	ifndef clearerr
X		void clearerr P((FILE*));
X#	endif
X#	ifndef feof
X		int feof P((FILE*));
X#	endif
X#	ifndef ferror
X		int ferror P((FILE*));
X#	endif
X#	if has_rename && !defined(rename)
X		int rename P((const char*,const char*));
X#	endif
X#	if has_tmpnam && !defined(tmpnam)
X		char *tmpnam P((char*));
X#	endif
X
X	/* <stdlib.h> */
X#	ifndef EXIT_FAILURE
X#		define EXIT_FAILURE 1
X#	endif
X#	ifndef EXIT_SUCCESS
X#		define EXIT_SUCCESS 0
X#	endif
X#	ifndef getenv
X		char *getenv P((const char*));
X#	endif
X#	ifndef exit
X		exiting exit_type exit P((int));
X#	endif
X#	ifndef _exit
X		exiting underscore_exit_type _exit P((int));
X#	endif
X#	ifndef free
X		free_type free P((malloc_type));
X#	endif
X#	ifndef atoi
X		int atoi P((const char*));
X#	endif
X#	ifndef malloc
X		malloc_type malloc P((size_t));
X#	endif
X#	ifndef realloc
X		malloc_type realloc P((malloc_type,size_t));
X#	endif
X
X	/* <string.h> */
X#	ifndef strcat
X		char *strcat P((char*,const char*));
X#	endif
X#	ifndef strcpy
X		char *strcpy P((char*,const char*));
X#	endif
X#	ifndef strncpy
X		char *strncpy P((char*,const char*,int));
X#	endif
X#	ifndef strrchr
X		char *strrchr P((const char*,int));
X#	endif
X#	ifndef strcmp
X		int strcmp P((const char*,const char*));
X#	endif
X#	ifndef strncmp
X		int strncmp P((const char*,const char*,int));
X#	endif
X#	ifndef strlen
X		strlen_type strlen P((const char*));
X#	endif
X
X	/* <time.h> */
X#	ifndef time
X		time_t time P((time_t*));
X#	endif
X
X
X/* Posix 1003.1-1988 */
X/* These declarations are for the benefit of non-Posix hosts.  */
X
X	/* <limits.h> */
X#	if !defined(NAME_MAX) && !defined(_POSIX_NAME_MAX)
X#		if has_sys_dir_h
X#			include <sys/dir.h>
X#		endif
X#		ifndef NAME_MAX
X#			ifndef MAXNAMLEN
X#				define MAXNAMLEN 14
X#			endif
X#			define NAME_MAX MAXNAMLEN
X#		endif
X#	endif
X#	if !defined(PATH_MAX) && !defined(_POSIX_PATH_MAX)
X#		if has_sys_param_h
X#			include <sys/param.h>
X#		endif
X#		ifndef PATH_MAX
X#			ifndef MAXPATHLEN
X#				define MAXPATHLEN 256
X#			endif
X#			define PATH_MAX (MAXPATHLEN-1)
X#		endif
X#	endif
X
X	/* <sys/wait.h> */
X#	if has_sys_wait_h
X#		include <sys/wait.h>
X#	endif
X#	ifndef WEXITSTATUS
X#		define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
X#		undef WIFEXITED /* Avoid 4.3BSD incompatibility with Posix.  */
X#	endif
X#	ifndef WIFEXITED
X#		define WIFEXITED(stat_val) (!((stat_val) & 255))
X#	endif
X
X	/* <fcntl.h> */
X	/* conf.h declares fcntl() and open().  */
X#	ifdef F_DUPD
X#		undef dup2
X#		define dup2(a,b) fcntl(a,F_DUPFD,b)
X#	else
X#		ifndef dup2
X			int dup2 P((int,int));
X#		endif
X#	endif
X#	ifdef O_CREAT
X#		define open_can_creat 1
X#		undef creat
X#		define creat(path,mode) open(path,O_CREAT|O_TRUNC|O_WRONLY,mode)
X#	else
X#		define open_can_creat 0
X#		define O_RDONLY 0
X#		define O_WRONLY 1
X#		define O_CREAT 01000
X#		define O_TRUNC 02000
X#		ifndef creat
X			int creat P((const char*,mode_t));
X#		endif
X#	endif
X
X	/* <stdio.h> */
X#	ifndef fdopen
X		FILE *fdopen P((int,const char*));
X#	endif
X
X	/* <sys/stat.h> */
X	/* conf.h declares chmod() and umask().  */
X#	ifndef S_IRUSR
X#		define S_IRUSR 0400
X#		define S_IWUSR 0200
X#		define S_IRGRP 0040
X#		define S_IWGRP 0020
X#		define S_IROTH 0004
X#		define S_IWOTH 0002
X#	endif
X#	ifndef S_ISREG
X#		define S_ISREG(n) (((n) & S_IFMT) == S_IFREG)
X#	endif
X#	ifndef fstat
X		int fstat P((int,struct stat*));
X#	endif
X#	ifndef stat
X		int stat P((const char*,struct stat*));
X#	endif
X
X	/* <unistd.h> */
X#	ifndef STDIN_FILENO
X#		define STDIN_FILENO 0
X#		define STDOUT_FILENO 1
X#		define STDERR_FILENO 2
X#	endif
X#	ifndef getlogin
X		char *getlogin P((void));
X#	endif
X#	ifndef _exit
X		exiting void _exit P((int));
X#	endif
X#	ifndef close
X		int close P((int));
X#	endif
X#	ifndef execv
X		int execv P((const char*,const char*const*));
X#	endif
X#	ifndef execvp
X		int execvp P((const char*,const char*const*));
X#	endif
X#	ifndef isatty
X		int isatty P((int));
X#	endif
X#	ifndef read
X		int read P((int,char*,unsigned));
X#	endif
X#	ifndef write
X		int write P((int,const char*,unsigned));
X#	endif
X#	ifndef unlink
X		int unlink P((const char*));
X#	endif
X#	if has_getuid
X#		ifndef getgid
X			gid_t getgid P((void));
X#		endif
X#		ifndef getuid
X			uid_t getuid P((void));
X#		endif
X#	endif
X#	if has_seteuid
X#		ifndef setegid
X			int setegid P((gid_t));
X#		endif
X#		ifndef seteuid
X			int seteuid P((uid_t));
X#		endif
X#		ifndef getegid
X			gid_t getegid P((void));
X#		endif
X#		ifndef geteuid
X			uid_t geteuid P((void));
X#		endif
X#	endif
X#	if has_vfork
X#		ifndef vfork
X			pid_t vfork P((void));
X#		endif
X#	else
X#		define vfork fork
X#		ifndef fork
X			pid_t fork P((void));
X#		endif
X#	endif
X#	if has_getcwd && !defined(getcwd)
X		char *getcwd P((char*,size_t));
X#	endif
X
X
X/* traditional Unix library */
X#define EXIT_TROUBLE 2 /* code returned by diff(1) if trouble is found */
X#if !has_getcwd && !defined(getwd)
X	char *getwd P((char*));
X#endif
X#if !has_tmpnam && !defined(mktemp)
X	char *mktemp P((char*));
X#endif
X#if !has_sigaction & has_sigblock
X#	ifndef sigblock
X		int sigblock P((int));
X#	endif
X#	ifndef sigsetmask
X		int sigsetmask P((int));
X#	endif
X#endif
X#ifndef _filbuf
X	int _filbuf P((FILE*));
X#endif
X#ifndef _flsbuf
X	int _flsbuf P((int,FILE*));
X#endif
X
X
X#endif /* !MAKEDEPEND */
X
X
X/*
X * Parameters
X */
X
X/* backwards compatibility with old versions of RCS */
X#define VERSION_MIN 3		/* old output RCS format supported */
X#define VERSION_MAX 5		/* newest output RCS format supported */
X#ifndef VERSION_DEFAULT		/* default RCS output format */
X#	define VERSION_DEFAULT VERSION_MAX
X#endif
X#define VERSION(n) ((n) - VERSION_DEFAULT) /* internally, 0 is the default */
X
X#ifndef STRICT_LOCKING
X#define STRICT_LOCKING 1
X#endif
X			      /* 0 sets the default locking to non-strict;  */
X                              /* used in experimental environments.         */
X                              /* 1 sets the default locking to strict;      */
X                              /* used in production environments.           */
X
X#define yearlength	   16 /* (good through AD 9,999,999,999,999,999)    */
X#define datesize (yearlength+16) /* size of output of DATEFORM		    */
X#define joinlength         20 /* number of joined revisions permitted       */
X#define RCSSUF            'v' /* suffix for RCS files                       */
X#define KDELIM            '$' /* delimiter for keywords                     */
X#define VDELIM            ':' /* separates keywords from values             */
X#define DEFAULTSTATE    "Exp" /* default state of revisions                 */
X
X
X
X#define true     1
X#define false    0
X#define nil      0
X
X
X
X
X/* This version of putc prints a char, but aborts on write error            */
X#if lint
X#	define aputc(c,o) afputc(c,o)
X#	define GETC(i,o,c) afputc(c=getc(i), o)
X#else
X#	define aputc(c,o) do { if (putc(c,o)==EOF) IOerror(); } while(0)
X#	define GETC(i,o,c) do {c=getc(i); if (o) aputc(c,o); } while(0)
X#endif
X/* GETC writes a DEL-character (all ones) on end of file.		    */
X
X#define WORKMODE(RCSmode, writable) ((RCSmode)&~(S_IWUSR|S_IWGRP|S_IWOTH) | ((writable)?S_IWUSR:0))
X/* computes mode of working file: same as RCSmode, but write permission     */
X/* determined by writable */
X
X
X/* character classes and token codes */
Xenum tokens {
X/* classes */	DELIM,	DIGIT,	IDCHAR,	NEWLN,	LETTER,	Letter,
X		PERIOD,	SBEGIN,	SPACE,	UNKN,
X/* tokens */	COLON,	EOFILE,	ID,	NUM,	SEMI,	STRING
X};
X
X#define SDELIM  '@'     /* the actual character is needed for string handling*/
X/* SDELIM must be consistent with map[], so that ctab[SDELIM]==SBEGIN.
X * there should be no overlap among SDELIM, KDELIM, and VDELIM
X */
X
X#define isdigit(c) ((unsigned)((c)-'0') <= 9) /* faster than ctab[c]==DIGIT */
X
X
X
X
X
X/***************************************
X * Data structures for the symbol table
X ***************************************/
X
X/* Buffer of arbitrary data */
Xstruct buf {
X	char *string;
X	size_t size;
X};
Xstruct cbuf {
X	const char *string;
X	size_t size;
X};
X
X/* Hash table entry */
Xstruct hshentry {
X	const char	  * num;      /* pointer to revision number (ASCIZ) */
X	const char	  * date;     /* pointer to date of checkin	    */
X	const char	  * author;   /* login of person checking in        */
X	const char	  * lockedby; /* who locks the revision             */
X	const char	  * state;    /* state of revision (Exp by default) */
X	struct cbuf	    log;      /* log message requested at checkin   */
X        struct branchhead * branches; /* list of first revisions on branches*/
X	struct cbuf	    ig;	      /* ignored phrases of revision	    */
X        struct hshentry   * next;     /* next revision on same branch       */
X	struct hshentry   * nexthsh;  /* next revision with same hash value */
X	unsigned long	    insertlns;/* lines inserted (computed by rlog)  */
X	unsigned long	    deletelns;/* lines deleted  (computed by rlog)  */
X	char		    selector; /* true if selected, false if deleted */
X};
X
X/* list of hash entries */
Xstruct hshentries {
X	struct hshentries *rest;
X	struct hshentry *first;
X};
X
X/* list element for branch lists */
Xstruct branchhead {
X        struct hshentry   * hsh;
X        struct branchhead * nextbranch;
X};
X
X/* accesslist element */
Xstruct access {
X	const char	  * login;
X        struct access     * nextaccess;
X};
X
X/* list element for locks  */
Xstruct lock {
X	const char	  * login;
X        struct hshentry   * delta;
X        struct lock       * nextlock;
X};
X
X/* list element for symbolic names */
Xstruct assoc {
X	const char	  * symbol;
X	const char	  * num;
X        struct assoc      * nextassoc;
X};
X
X
X#define mainArgs (argc,argv) int argc; char **argv;
X
X#if lint
X#	define libId(name,rcsid)
X#	define mainProg(name,cmd,rcsid) int name mainArgs
X#else
X#	define libId(name,rcsid) const char name[] = rcsid;
X#	define mainProg(name,cmd,rcsid) const char copyright[] = "Copyright 1982,1988,1989 by Walter F. Tichy\nPurdue CS\nCopyright 1990 by Paul Eggert", rcsbaseId[] = RCSBASE, cmdid[] = cmd; libId(name,rcsid) int main mainArgs
X#endif
X
X/*
X * Markers for keyword expansion (used in co and ident)
X *	Every byte must have class LETTER or Letter.
X */
X#define AUTHOR          "Author"
X#define DATE            "Date"
X#define HEADER          "Header"
X#define IDH             "Id"
X#define LOCKER          "Locker"
X#define LOG             "Log"
X#define RCSFILE         "RCSfile"
X#define REVISION        "Revision"
X#define SOURCE          "Source"
X#define STATE           "State"
X#define keylength 8 /* max length of any of the above keywords */
X
Xenum markers { Nomatch, Author, Date, Header, Id,
X	       Locker, Log, RCSfile, Revision, Source, State };
X	/* This must be in the same order as rcskeys.c's Keyword[] array. */
X
X#define DELNUMFORM      "\n\n%s\n%s\n"
X/* used by putdtext and scanlogtext */
X
X/* main program */
Xextern const char cmdid[];
Xexiting void exiterr P((void));
X
X/* maketime */
Xvoid str2date P((const char*,char[datesize]));
Xvoid time2date P((time_t,char[datesize]));
X
X/* partime */
Xint partime P((const char*,struct tm*,int*));
X
X/* rcsedit */
X#define ciklogsize 23 /* sizeof("checked in with -k by ") */
Xextern FILE *fcopy;
Xextern const char *resultfile;
Xextern const char ciklog[ciklogsize];
Xextern int locker_expansion;
Xextern struct buf dirtfname[];
X#define newRCSfilename (dirtfname[0].string)
XFILE *initeditfiles P((const char*));
XFILE *rcswriteopen P((const char*));
Xconst char *makedirtemp P((const char*,int));
Xint expandline P((FILE*,FILE*,const struct hshentry*,int,FILE*));
Xvoid arewind P((FILE*));
Xvoid copystring P((void));
Xvoid dirtempunlink P((void));
Xvoid editstring P((const struct hshentry*));
Xvoid finishedit P((const struct hshentry*));
Xvoid inittmpeditfiles P((void));
Xvoid keepdirtemp P((const char*));
Xvoid swapeditfiles P((int));
Xvoid xpandstring P((const struct hshentry*));
X
X/* rcsfnms */
X#define bufautobegin(b) ((void) ((b)->size = 0)) /* for auto on block entry */
Xextern char *workfilename;
Xextern const char *RCSfilename;
Xextern int haveworkstat;
Xextern struct stat RCSstat;
Xextern struct stat workstat;
XFILE *rcsreadopen P((const char*));
Xchar *bufenlarge P((struct buf*,const char**));
Xchar *maketemp P((int));
Xconst char *bindex P((const char*,int));
Xconst char *getfullRCSname P((void));
Xconst char *tmp();
Xint getfworkstat P((int));
Xint getworkstat P((void));
Xint pairfilenames P((int,char**,FILE*(*)P((const char*)),int,int));
Xvoid bufalloc P((struct buf*,size_t));
Xvoid bufautoend P((struct buf*));
Xvoid bufrealloc P((struct buf*,size_t));
Xvoid bufscat P((struct buf*,const char*));
Xvoid bufscpy P((struct buf*,const char*));
Xvoid ffclose P((FILE*));
Xvoid tempunlink P((void));
X#if has_rename & !bad_rename
X#	define re_name(x,y) rename(x,y)
X#else
X	int re_name P((const char*,const char*));
X#endif
X
X/* rcsgen */
Xextern int interactiveflag;
Xextern struct cbuf curlogmsg;
Xextern struct buf curlogbuf;
Xconst char *buildrevision P((const struct hshentries*,struct hshentry*,int,int));
Xint getcstdin P((void));
Xint ttystdin P((void));
Xint yesorno P((int,const char*,...));
Xstruct cbuf cleanlogmsg P((char*,size_t));
Xvoid putdesc P((int,const char*));
X
X/* rcskeys */
Xextern const char *const Keyword[];
Xenum markers trymatch P((const char*));
X
X/* rcslex */
Xextern FILE *finptr;
Xextern FILE *foutptr;
Xextern FILE *frewrite;
Xextern const char *NextString;
Xextern enum tokens nexttok;
Xextern int hshenter;
Xextern int nerror;
Xextern int nextc;
Xextern int quietflag;
Xextern unsigned long rcsline;
Xconst char *getid P((void));
Xexiting void efaterror P((const char*));
Xexiting void faterror P((const char*,...));
Xexiting void fatserror P((const char*,...));
Xexiting void IOerror P((void));
Xexiting void unterminatedString P((void));
Xchar *checkid P((char*,int));
Xint getkeyopt P((const char*));
Xint getlex P((enum tokens));
Xstruct cbuf getphrases P((const char*));
Xstruct cbuf savestring P((struct buf*));
Xstruct hshentry *getnum P((void));
Xvoid Lexinit P((void));
Xvoid afputc P((int,FILE*));
Xvoid aprintf P((FILE*,const char*,...));
Xvoid aputs P((const char*,FILE*));
Xvoid checksid P((char*));
Xvoid diagnose P((const char*,...));
Xvoid eflush P((void));
Xvoid error P((const char*,...));
Xvoid eerror P((const char*));
Xvoid fvfprintf P((FILE*,const char*,va_list));
Xvoid getkey P((const char*));
Xvoid getkeystring P((const char*));
Xvoid nextlex P((void));
Xvoid oflush P((void));
Xvoid printstring P((void));
Xvoid readstring P((void));
Xvoid redefined P((int));
Xvoid warn P((const char*,...));
Xvoid warnignore P((void));
X
X/* rcsmap */
X#define ctab (&map[1])
Xextern const enum tokens map[];
X
X/* rcsrev */
Xchar *partialno P((struct buf*,const char*,unsigned));
Xint cmpnum P((const char*,const char*));
Xint cmpnumfld P((const char*,const char*,unsigned));
Xint compartial P((const char*,const char*,unsigned));
Xint expandsym P((const char*,struct buf*));
Xstruct hshentry *genrevs P((const char*,const char*,const char*,const char*,struct hshentries**));
Xunsigned countnumflds P((const char*));
Xvoid getbranchno P((const char*,struct buf*));
X
X/* rcssyn */
X/* These expand modes must agree with Expand_names[] in rcssyn.c.  */
X#define KEYVAL_EXPAND 0 /* -kkv `$Keyword: value $' */
X#define KEYVALLOCK_EXPAND 1 /* -kkvl `$Keyword: value locker $' */
X#define KEY_EXPAND 2 /* -kk `$Keyword$' */
X#define VAL_EXPAND 3 /* -kv `value' */
X#define OLD_EXPAND 4 /* -ko use old string, omitting expansion */
Xstruct diffcmd {
X	unsigned long
X		line1, /* number of first line */
X		nlines, /* number of lines affected */
X		adprev, /* previous 'a' line1+1 or 'd' line1 */
X		dafter; /* sum of previous 'd' line1 and previous 'd' nlines */
X};
Xextern const char      * Dbranch;
Xextern struct access   * AccessList;
Xextern struct assoc    * Symbols;
Xextern struct cbuf Comment;
Xextern struct lock     * Locks;
Xextern struct hshentry * Head;
Xextern int		 Expand;
Xextern int               StrictLocks;
Xextern int               TotalDeltas;
Xextern const char *const expand_names[];
Xextern const char Kdesc[];
Xextern const char Klog[];
Xextern const char Ktext[];
Xint getdiffcmd P((FILE*,int,FILE*,struct diffcmd*));
Xint putdftext P((const char*,struct cbuf,FILE*,FILE*,int));
Xint putdtext P((const char*,struct cbuf,const char*,FILE*,int));
Xint str2expmode P((const char*));
Xvoid getadmin P((void));
Xvoid getdesc P((int));
Xvoid gettree P((void));
Xvoid ignorephrase P((void));
Xvoid initdiffcmd P((struct diffcmd*));
Xvoid putadmin P((FILE*));
Xvoid puttree P((const struct hshentry*,FILE*));
X
X/* rcsutil */
Xextern int RCSversion;
Xchar *cgetenv P((const char*));
Xconst char *getcaller P((void));
Xconst char *fstrsave P((const char*));
Xconst char *strsave P((const char*));
Xint addlock P((struct hshentry*));
Xint addsymbol P((const char*,const char*,int));
Xint checkaccesslist P((void));
Xint findlock P((int,struct hshentry**));
Xint run P((const char*,const char*,...));
Xint runv P((const char**));
Xmalloc_type fremember P((malloc_type));
Xmalloc_type ftestalloc P((size_t));
Xmalloc_type testalloc P((size_t));
Xmalloc_type testrealloc P((malloc_type,size_t));
X#define ftalloc(T) ftnalloc(T,1)
X#define talloc(T) tnalloc(T,1)
X#if lint
X	extern malloc_type lintalloc;
X#	define ftnalloc(T,n) (lintalloc = ftestalloc(sizeof(T)*(n)), (T*)0)
X#	define tnalloc(T,n) (lintalloc = testalloc(sizeof(T)*(n)), (T*)0)
X#	define tfree(p)
X#else
X#	define ftnalloc(T,n) ((T*) ftestalloc(sizeof(T)*(n)))
X#	define tnalloc(T,n) ((T*) testalloc(sizeof(T)*(n)))
X#	define tfree(p) free((malloc_type)(p))
X#endif
Xvoid awrite P((const char*,fread_type,FILE*));
Xvoid catchints P((void));
Xvoid fastcopy P((FILE*,FILE*));
Xvoid ffree P((void));
Xvoid ffree1 P((const char*));
Xvoid initid P((void));
Xvoid ignoreints P((void));
Xvoid printdate P((FILE*,const char*,const char*));
Xvoid restoreints P((void));
Xvoid setRCSversion P((const char*));
X#define SETID (has_getuid & has_seteuid & DIFF_PATH_HARDWIRED)
X#if has_getuid
X	extern uid_t ruid;
X#	define myself(u) ((u) == ruid)
X#else
X#	define myself(u) true
X#endif
X#if SETID
X	void seteid P((void));
X	void setrid P((void));
X#else
X#	define seteid()
X#	define setrid()
X#endif
END_OF_FILE
  if test 23601 -ne `wc -c <'src/rcsbase.h'`; then
    echo shar: \"'src/rcsbase.h'\" unpacked with wrong size!
  fi
  # end of 'src/rcsbase.h'
fi
if test -f 'src/rcsedit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/rcsedit.c'\"
else
  echo shar: Extracting \"'src/rcsedit.c'\" \(22247 characters\)
  sed "s/^X//" >'src/rcsedit.c' <<'END_OF_FILE'
X/*
X *                     RCS stream editor
X */
X/**********************************************************************************
X *                       edits the input file according to a
X *                       script from stdin, generated by diff -n
X *                       performs keyword expansion
X **********************************************************************************
X */
X
X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X   Copyright 1990 by Paul Eggert
X   Distributed under license by the Free Software Foundation, Inc.
X
XThis file is part of RCS.
X
XRCS is free software; you can redistribute it and/or modify
Xit under the terms of the GNU General Public License as published by
Xthe Free Software Foundation; either version 1, or (at your option)
Xany later version.
X
XRCS is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
XGNU General Public License for more details.
X
XYou should have received a copy of the GNU General Public License
Xalong with RCS; see the file COPYING.  If not, write to
Xthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
X
XReport problems and direct all questions to:
X
X    rcs-bugs at cs.purdue.edu
X
X*/
X
X
X/* $Log: rcsedit.c,v $
X * Revision 5.5  1990/12/30  05:07:35  eggert
X * Fix report of busy RCS files when !defined(O_CREAT) | !defined(O_EXCL).
X *
X * Revision 5.4  1990/11/01  05:03:40  eggert
X * Permit arbitrary data in comment leaders.
X *
X * Revision 5.3  1990/09/11  02:41:13  eggert
X * Tune expandline().
X *
X * Revision 5.2  1990/09/04  08:02:21  eggert
X * Count RCS lines better.  Improve incomplete line handling.
X *
X * Revision 5.1  1990/08/29  07:13:56  eggert
X * Add -kkvl.
X * Fix bug when getting revisions to files ending in incomplete lines.
X * Fix bug in comment leader expansion.
X *
X * Revision 5.0  1990/08/22  08:12:47  eggert
X * Don't require final newline.
X * Don't append "checked in with -k by " to logs,
X * so that checking in a program with -k doesn't change it.
X * Don't generate trailing white space for empty comment leader.
X * Remove compile-time limits; use malloc instead.  Add -k, -V.
X * Permit dates past 1999/12/31.  Make lock and temp files faster and safer.
X * Ansify and Posixate.  Check diff's output.
X *
X * Revision 4.8  89/05/01  15:12:35  narten
X * changed copyright header to reflect current distribution rules
X * 
X * Revision 4.7  88/11/08  13:54:14  narten
X * misplaced semicolon caused infinite loop
X * 
X * Revision 4.6  88/08/09  19:12:45  eggert
X * Shrink stdio code size; allow cc -R.
X * 
X * Revision 4.5  87/12/18  11:38:46  narten
X * Changes from the 43. version. Don't know the significance of the
X * first change involving "rewind". Also, additional "lint" cleanup.
X * (Guy Harris)
X * 
X * Revision 4.4  87/10/18  10:32:21  narten
X * Updating version numbers. Changes relative to version 1.1 actually
X * relative to 4.1
X * 
X * Revision 1.4  87/09/24  13:59:29  narten
X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
X * warnings)
X * 
X * Revision 1.3  87/09/15  16:39:39  shepler
X * added an initializatin of the variables editline and linecorr
X * this will be done each time a file is processed.
X * (there was an obscure bug where if co was used to retrieve multiple files
X *  it would dump)
X * fix attributed to  Roy Morris @FileNet Corp ...!felix!roy
X * 
X * Revision 1.2  87/03/27  14:22:17  jenkins
X * Port to suns
X * 
X * Revision 4.1  83/05/12  13:10:30  wft
X * Added new markers Id and RCSfile; added locker to Header and Id.
X * Overhauled expandline completely() (problem with $01234567890123456789@).
X * Moved trymatch() and marker table to rcskeys.c.
X * 
X * Revision 3.7  83/05/12  13:04:39  wft
X * Added retry to expandline to resume after failed match which ended in $.
X * Fixed truncation problem for $19chars followed by@@.
X * Log no longer expands full path of RCS file.
X * 
X * Revision 3.6  83/05/11  16:06:30  wft
X * added retry to expandline to resume after failed match which ended in $.
X * Fixed truncation problem for $19chars followed by@@.
X * 
X * Revision 3.5  82/12/04  13:20:56  wft
X * Added expansion of keyword Locker.
X *
X * Revision 3.4  82/12/03  12:26:54  wft
X * Added line number correction in case editing does not start at the
X * beginning of the file.
X * Changed keyword expansion to always print a space before closing KDELIM;
X * Expansion for Header shortened.
X *
X * Revision 3.3  82/11/14  14:49:30  wft
X * removed Suffix from keyword expansion. Replaced fclose with ffclose.
X * keyreplace() gets log message from delta, not from curlogmsg.
X * fixed expression overflow in while(c=putc(GETC....
X * checked nil printing.
X *
X * Revision 3.2  82/10/18  21:13:39  wft
X * I added checks for write errors during the co process, and renamed
X * expandstring() to xpandstring().
X *
X * Revision 3.1  82/10/13  15:52:55  wft
X * changed type of result of getc() from char to int.
X * made keyword expansion loop in expandline() portable to machines
X * without sign-extension.
X */
X
X
X#include "rcsbase.h"
X
XlibId(editId, "$Id: rcsedit.c,v 5.5 1990/12/30 05:07:35 eggert Exp $")
X
Xstatic void keyreplace P((enum markers,const struct hshentry*,FILE*));
X
X
XFILE *fcopy;		 /* result file descriptor			    */
Xconst char *resultfile;  /* result file name				    */
Xint locker_expansion;	 /* should the locker name be appended to Id val?   */
Xstatic FILE *fedit;	 /* edit   file descriptor			    */
Xstatic const char *editfile;	 /* edit file				    */
Xstatic const char *editdir;  /* edit directory				    */
Xstatic unsigned long editline; /*fedit line counter; is always #lines+1     */
Xstatic long linecorr; /* #adds - #deletes in each edit run.		    */
X               /*used to correct editline in case file is not rewound after */
X               /* applying one delta                                        */
X
X#define DIRTEMPNAMES 3
Xenum maker {notmade, real, effective};
Xstruct buf dirtfname[DIRTEMPNAMES];		/* unlink these when done */
Xstatic volatile enum maker dirtfmaker[DIRTEMPNAMES];	/* if these are set */
X
X	FILE *
Xiniteditfiles(dir)
X	const char *dir;
X/* Function: Initializes resultfile and editfile with temporary filenames
X * in directory dir. Opens resultfile for reading and writing, with fcopy
X * as file descriptor. fedit is set to nil.
X */
X{
X	editline = 0;	/* make sure we start from the beginning*/
X	linecorr = 0;
X	editdir = dir;
X	resultfile = makedirtemp(dir,1);
X	editfile = nil;
X        fedit=nil;
X	errno = 0;
X	return fcopy = fopen(resultfile,"w+");
X}
X
X	void
Xinittmpeditfiles()
X{
X	if (!initeditfiles(tmp()))
X		efaterror(resultfile);
X}
X
X
X	void
Xarewind(f)
X	FILE *f;
X{
X	if (fseek(f, (long)0, SEEK_SET) == EOF)
X		IOerror();
X}
X
X	void
Xswapeditfiles(tostdout)
X	int tostdout;
X/* Function: swaps resultfile and editfile, assigns fedit=fcopy,
X * rewinds fedit for reading, and opens resultfile for reading and
X * writing, using fcopy. If tostdout, fcopy is set to stdout.
X */
X{
X	const char *tmpptr;
X        fedit=fcopy;
X	arewind(fedit);
X        editline = 1; linecorr=0;
X        tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
X        if (tostdout)
X                fcopy=stdout;
X	else {
X	    if (!resultfile)
X		resultfile = makedirtemp(editdir,2);
X	    errno = 0;
X	    if (!(fcopy = fopen(resultfile,"w+")))
X		efaterror(resultfile);
X        }
X}
X
X
X	void
Xfinishedit(delta)
X	const struct hshentry *delta;
X/* copy the rest of the edit file and close it (if it exists).
X * if delta!=nil, perform keyword substitution at the same time.
X */
X{
X	register FILE *fe, *fc;
X
X	fe = fedit;
X	if (fe) {
X		fc = fcopy;
X                if (delta!=nil) {
X			while (0 < expandline(fe,fc,delta,false,(FILE*)NULL))
X				;
X                } else {
X			fastcopy(fe,fc);
X                }
X		ffclose(fe);
X        }
X}
X
X
X
X	static exiting void
XeditEndsPrematurely()
X{
X	fatserror("edit script ends prematurely");
X}
X
X	static exiting void
XeditLineNumberOverflow()
X{
X	fatserror("edit script refers to line past end of file");
X}
X
X
X	static void
Xcopylines(upto,delta)
X	register unsigned long upto;
X	const struct hshentry *delta;
X/* Function: copies input lines editline..upto-1 from fedit to fcopy.
X * If delta != nil, keyword expansion is done simultaneously.
X * editline is updated. Rewinds a file only if necessary.
X */
X{
X	register int c;
X	register FILE *fe, *fc;
X
X	if (upto < editline) {
X                /* swap files */
X                finishedit((struct hshentry *)nil); swapeditfiles(false);
X                /* assumes edit only during last pass, from the beginning*/
X        }
X	fe = fedit;
X	fc = fcopy;
X	if (editline < upto)
X	    if (delta)
X		do {
X			if (expandline(fe,fc,delta,false,(FILE*)NULL) <= 0)
X				goto unexpected_EOF;
X		} while (++editline < upto);
X	    else
X		do {
X			do {
X				c = getc(fe);
X				if (c == EOF)
X					goto unexpected_EOF;
X				aputc(c, fc);
X			} while (c != '\n');
X		} while (++editline < upto);
X	return;
X
X    unexpected_EOF:
X	editLineNumberOverflow();
X}
X
X
X
X	void
Xxpandstring(delta)
X	const struct hshentry *delta;
X/* Function: Reads a string terminated by SDELIM from finptr and writes it
X * to fcopy. Double SDELIM is replaced with single SDELIM.
X * Keyword expansion is performed with data from delta.
X * If foutptr is nonnull, the string is also copied unchanged to foutptr.
X */
X{
X	while (0 < expandline(finptr,fcopy,delta,true,foutptr))
X		;
X}
X
X
X	void
Xcopystring()
X/* Function: copies a string terminated with a single SDELIM from finptr to
X * fcopy, replacing all double SDELIM with a single SDELIM.
X * If foutptr is nonnull, the string also copied unchanged to foutptr.
X * editline is set to (number of lines copied)+1.
X * Assumption: next character read is first string character.
X */
X{	register c;
X	register FILE *fin, *frew, *fcop;
X	register int amidline;
X
X	fin=finptr; frew=foutptr; fcop=fcopy;
X        editline=1;
X	amidline = false;
X	for (;;) {
X		GETC(fin,frew,c);
X		switch (c) {
X		    case EOF:
X			unterminatedString();
X			/*NOTREACHED*/
X		    case '\n':
X			++editline;
X			++rcsline;
X			amidline = false;
X			break;
X		    case SDELIM:
X			GETC(fin,frew,c);
X			if (c != SDELIM) {
X				/* end of string */
X				nextc = c;
X				editline += amidline;
X				return;
X			}
X			/* fall into */
X		    default:
X			amidline = true;
X			break;
X                }
X		aputc(c,fcop);
X        }
X}
X
X
X
X
X	void
Xeditstring(delta)
X	const struct hshentry *delta;
X/* Function: reads an edit script from finptr and applies it to
X * file fedit; the result is written to fcopy.
X * If delta!=nil, keyword expansion is performed simultaneously.
X * If foutptr is set, the edit script is also copied verbatim to foutptr.
X * Assumes that all these files are open.
X * If running out of lines in fedit, fedit and fcopy are swapped.
X * resultfile and editfile are the names of the files that go with fcopy
X * and fedit, respectively.
X * Assumes the next input character from finptr is the first character of
X * the edit script. Resets nextc on exit.
X */
X{
X        int ed; /* editor command */
X        register int c;
X	register FILE *fin, *frew, *f;
X	register unsigned long i;
X	unsigned long line_lim;
X	struct diffcmd dc;
X
X        editline += linecorr; linecorr=0; /*correct line number*/
X	frew = foutptr;
X	fin = finptr;
X	line_lim = ULONG_MAX;
X	initdiffcmd(&dc);
X	while (0  <=  (ed = getdiffcmd(fin,SDELIM,frew,&dc)))
X		if (line_lim <= dc.line1)
X			editLineNumberOverflow();
X		else if (!ed) {
X			copylines(dc.line1, delta);
X                        /* skip over unwanted lines */
X			i = dc.nlines;
X			linecorr -= i;
X			editline += i;
X			f = fedit;
X			do {
X                                /*skip next line*/
X				while ((c=getc(f))!='\n')
X					if (c==EOF) {
X					    if (i!=1)
X						editLineNumberOverflow();
X					    line_lim = dc.dafter;
X					    break;
X					}
X			} while (--i);
X		} else {
X			copylines(dc.line1+1, delta); /*copy only; no delete*/
X			i = dc.nlines;
X			linecorr += i;
X			f = fcopy;
X			do {
X                                /*copy next line from script*/
X                                if (delta!=nil)
X				    switch (expandline(fin,f,delta,true,frew)) {
X					case 0:
X					    if (i==1)
X						return;
X					    /* fall into */
X					case -1:
X					    editEndsPrematurely();
X				    }
X                                else {
X				       for (;;) {
X					    GETC(fin,frew,c);
X					    if (c == EOF)
X						editEndsPrematurely();
X					    aputc(c, f);
X					    if (c == '\n')
X						break;
X					    if (c==SDELIM) {
X						GETC(fin,frew,c);
X						if (c!=SDELIM) {
X						    if (--i)
X							editEndsPrematurely();
X						    nextc = c;
X						    return;
X						}
X					   }
X				       }
X				       ++rcsline;
X				}
X			} while (--i);
X                }
X	GETC(fin,frew,c);
X	nextc = c;
X}
X
X
X
X/* The rest is for keyword expansion */
X
X
X
X	int
Xexpandline(in, out, delta, delimstuffed, frew)
X	register FILE *in, *out;
X	const struct hshentry *delta;
X	int delimstuffed;
X	register FILE *frew;
X/* Function: Reads a line from in and writes it to out.
X * If DELIMSTUFFED is set, double SDELIM is replaced with single SDELIM.
X * Keyword expansion is performed with data from delta.
X * If FREW is set, the line is also copied unchanged to FREW.
X * DELIMSTUFFED must be set if FREW is set.
X * Yields -1 if no data is copied, 0 if an incomplete line is copied,
X * 1 if a complete line is copied.
X */
X{
X	register c;
X	register char * tp;
X	register int ds, r;
X	const char *tlim;
X	char keystring[keylength+2];
X	static struct buf keyval;
X        enum markers matchresult;
X
X	ds = delimstuffed;
X	r = -1;
X	GETC(in,frew,c);
X        for (;;) {
X		switch (c) {
X		    case EOF:
X                        if(ds) {
X				unterminatedString();
X                        }
X			return r;
X
X		    case SDELIM:
X			if (ds) {
X			    GETC(in,frew,c);
X			    if (c != SDELIM) {
X                                /* end of string */
X                                nextc=c;
X				return r;
X			    }
X			}
X			/* fall into */
X		    default:
X			r = 0;
X			aputc(c,out);
X			break;
X
X		    case '\n':
X			rcsline += ds;
X			aputc(c,out);
X			return 1;
X
X		    case KDELIM:
X			r = 0;
X                        /* check for keyword */
X                        /* first, copy a long enough string into keystring */
X			tp=keystring;
X			for (;;) {
X			    GETC(in,frew,c);
X			    if (tp < keystring+keylength)
X				switch (ctab[c]) {
X				    case LETTER: case Letter:
X					*tp++ = c;
X					continue;
X				    default:
X					break;
X				}
X			    break;
X                        }
X			*tp++ = c; *tp = '\0';
X			matchresult = trymatch(keystring);
X			if (matchresult==Nomatch) {
X				tp[-1] = 0;
X				aprintf(out, "%c%s", KDELIM, keystring);
X				continue;   /* last c handled properly */
X			}
X
X			/* Now we have a keyword terminated with a K/VDELIM */
X			if (c==VDELIM) {
X			      /* try to find closing KDELIM, and replace value */
X			      bufalloc(&keyval, 1);
X			      tp = keyval.string;
X			      tlim = tp + keyval.size;
X			      for (;;) {
X				      GETC(in,frew,c);
X				      if (c==EOF || c=='\n' || c==KDELIM)
X					break;
X				      *tp++ =c;
X				      if (tlim <= tp)
X					  tp = bufenlarge(&keyval, &tlim);
X				      if (c==SDELIM && ds) { /*skip next SDELIM */
X						GETC(in,frew,c);
X						if (c != SDELIM) {
X							/* end of string before closing KDELIM or newline */
X							*tp = 0;
X							aprintf(out, "%c%s%s", KDELIM, keystring, keyval.string);
X							nextc = c;
X							return 0;
X						}
X				      }
X			      }
X			      if (c!=KDELIM) {
X				    /* couldn't find closing KDELIM -- give up */
X				    *tp = 0;
X				    aprintf(out, "%c%s%s", KDELIM, keystring, keyval.string);
X				    continue;   /* last c handled properly */
X			      }
X			}
X			/* now put out the new keyword value */
X			keyreplace(matchresult,delta,out);
X                }
X		GETC(in,frew,c);
X        }
X}
X
X
Xconst char ciklog[ciklogsize] = "checked in with -k by ";
X
X	static void
Xkeyreplace(marker,delta,out)
X	enum markers marker;
X	register const struct hshentry *delta;
X	register FILE *out;
X/* function: outputs the keyword value(s) corresponding to marker.
X * Attributes are derived from delta.
X */
X{
X	register const char *sp, *cp, *date;
X	register char c;
X	register size_t cs, cw, ls;
X	int RCSv;
X
X	sp = Keyword[(int)marker];
X
X	if (Expand == KEY_EXPAND) {
X		aprintf(out, "%c%s%c", KDELIM, sp, KDELIM);
X		return;
X	}
X
X        date= delta->date;
X	RCSv = RCSversion;
X
X	if (Expand == KEYVAL_EXPAND  ||  Expand == KEYVALLOCK_EXPAND)
X		aprintf(out, "%c%s%c%c", KDELIM, sp, VDELIM,
X			marker==Log && RCSv<VERSION(5)  ?  '\t'  :  ' '
X		);
X
X        switch (marker) {
X        case Author:
X		aputs(delta->author, out);
X                break;
X        case Date:
X		printdate(out, date, " ");
X                break;
X        case Id:
X	case Header:
X		aprintf(out, "%s %s ",
X			  marker==Id || RCSv<VERSION(4)
X			? bindex(RCSfilename,SLASH)
X			: getfullRCSname(),
X			delta->num
X		);
X		printdate(out, date, " ");
X		aprintf(out, " %s %s",
X			delta->author,
X			  RCSv==VERSION(3) && delta->lockedby ? "Locked"
X			: delta->state
X		);
X		if (delta->lockedby!=nil)
X		    if (VERSION(5) <= RCSv) {
X			if (locker_expansion || Expand==KEYVALLOCK_EXPAND)
X			    aprintf(out, " %s", delta->lockedby);
X		    } else if (RCSv == VERSION(4))
X			aprintf(out, " Locker: %s", delta->lockedby);
X                break;
X        case Locker:
X		if (delta->lockedby)
X		    if (
X				locker_expansion
X			||	Expand == KEYVALLOCK_EXPAND
X			||	RCSv <= VERSION(4)
X		    )
X			aputs(delta->lockedby, out);
X                break;
X        case Log:
X        case RCSfile:
X		aputs(bindex(RCSfilename,SLASH), out);
X                break;
X        case Revision:
X		aputs(delta->num, out);
X                break;
X        case Source:
X		aputs(getfullRCSname(), out);
X                break;
X        case State:
X		aputs(delta->state, out);
X                break;
X	default:
X		break;
X        }
X	if (Expand == KEYVAL_EXPAND  ||  Expand == KEYVALLOCK_EXPAND) {
X		afputc(' ', out);
X		afputc(KDELIM, out);
X	}
X	if (marker == Log) {
X		sp = delta->log.string;
X		ls = delta->log.size;
X		if (sizeof(ciklog)-1<=ls && !strncmp(sp,ciklog,sizeof(ciklog)-1))
X			return;
X		afputc('\n', out);
X		cp = Comment.string;
X		cw = cs = Comment.size;
X		awrite(cp, cs, out);
X		aprintf(out, "Revision %s  ", delta->num);
X		printdate(out, date, "  ");
X		aprintf(out, "  %s", delta->author);
X		/* Do not include state: it may change and is not updated.  */
X		/* Comment is the comment leader.  */
X		if (VERSION(5) <= RCSv)
X		    for (;  cw && (cp[cw-1]==' ' || cp[cw-1]=='\t');  --cw)
X			;
X		for (;;) {
X		    afputc('\n', out);
X		    awrite(cp, cw, out);
X		    if (!ls)
X			break;
X		    --ls;
X		    c = *sp++;
X		    if (c != '\n') {
X			awrite(cp+cw, cs-cw, out);
X			do {
X			    afputc(c,out);
X			    if (!ls)
X				break;
X			    --ls;
X			    c = *sp++;
X			} while (c != '\n');
X		    }
X		}
X	}
X}
X
X
X	FILE *
Xrcswriteopen(RCSname)
X	const char *RCSname;
X/*
X * Create the lock file corresponding to RCSNAME.
X * Then try to open RCSNAME for reading and yield its FILE* descriptor.
X * If all goes well, discard any previously acquired locks,
X * and set frewrite to the FILE* descriptor of the lock file,
X * which will eventually turn into the new RCS file.
X */
X{
X	register char *tp;
X	register const char *sp, *lp;
X	FILE *f;
X	int fdesc, r;
X	struct buf *dirt;
X
X	sp = RCSname;
X	dirt = &dirtfname[frewrite != NULL];
X	bufalloc(dirt, strlen(sp)+1);
X	tp = dirt->string;
X	if ((lp = strrchr(sp,SLASH)))
X		while (sp<=lp)
X			*tp++ = *sp++;
X	*tp++ = RCSSEP ? RCSSEP : RCSSUF;
X#if RCSSEP
X	/* Insert `,' and append file name.  */
X	lp = strrchr(sp, RCSSEP);
X#else
X	/* The file system doesn't allow `,'; use `v' as a poor substitute.  */
X	lp = sp + strlen(sp) - 2;
X#endif
X	while (sp<=lp)
X		*tp++ = *sp++;
X	*tp = '\0'; /* same length as RCSname */
X	tp = dirt->string;
X
X	f = NULL;
X
X	seteid();
X	ignoreints();
X#	if !open_can_creat
X#		define create(f,m) creat(f, m)
X#	else
X#		define create(f,m) open(f, O_CREAT|O_WRONLY|o_excltrunc, m)
X#		ifdef O_EXCL
X#			define o_excltrunc O_EXCL
X#		else
X#			define o_excltrunc O_TRUNC
X#		endif
X#	endif
X	if (0 <= (fdesc = create(tp, S_IRUSR|S_IRGRP|S_IROTH))) {
X		dirtfmaker[0] = effective;
X		errno = 0;
X		f = fopen(RCSname,"r");
X		if (frewrite)
X		    /* We already have a lock somewhere else.  */
X		    if (f) {
X			/* Discard the first acquired lock.  */
X			ffclose(frewrite);  frewrite = NULL;
X			if (unlink(newRCSfilename) < 0) {
X			    setrid();
X			    efaterror(newRCSfilename);
X			}
X			bufscpy(&dirtfname[0], tp);
X		    } else {
X			/* Prefer the first acquired lock to this one.  */
X			r = close(fdesc)<0 || unlink(tp)<0;
X			restoreints();
X			setrid();
X			if (r)
X			    efaterror(tp);
X			return f;
X		    }
X		if (!(frewrite = fdopen(fdesc,"w"))) {
X		    setrid();
X		    efaterror(newRCSfilename);
X		}
X	}
X#if !open_can_creat | !defined(O_EXCL)
X	else if (errno != ENOENT) {
X		/* Set errno=EEXIST if the RCS file is busy.  */
X		struct stat statbuf;
X		int old_errno = errno;
X		errno  =  stat(tp,&statbuf)==0 ? EEXIST : old_errno;
X	}
X#endif
X
X	restoreints();
X	setrid();
X	return f;
X}
X
X	void
Xkeepdirtemp(name)
X	const char *name;
X/* Do not unlink name, either because it's not there any more,
X * or because it has already been unlinked.
X */
X{
X	register int i;
X	for (i=DIRTEMPNAMES; 0<=--i; )
X		if (dirtfname[i].string == name) {
X			dirtfmaker[i] = notmade;
X			return;
X		}
X	faterror("keepdirtemp");
X}
X
X	const char *
Xmakedirtemp(name, n)
X	register const char *name;
X	int n;
X/*
X * Have maketemp() do all the work if name==tmp.
X * Otherwise, create a unique filename in name's dir using n and name
X * and store it into the dirtfname[n].
X * Because of storage in tfnames, dirtempunlink() can unlink the file later.
X * Return a pointer to the filename created.
X */
X{
X	register char *tp;
X	register const char *lastslash, *np;
X
X	if (name == tmp())
X		return maketemp(n);
X	bufalloc(&dirtfname[n], strlen(name)+3);
X	np = tp = dirtfname[n].string;
X	if ((lastslash = strrchr(name,SLASH)))
X		while (name<=lastslash)
X			*tp++ = *name++;
X	*tp++ = RCSSEP ? RCSSEP : RCSSUF;
X	*tp++ = 'A'+n;
X	while ((*tp++ = *name++))
X	    ;
X	dirtfmaker[n] = real;
X	return np;
X}
X
X	void
Xdirtempunlink()
X/* Clean up makedirtemp() files.  May be invoked by signal handler. */
X{
X	register int i;
X	enum maker m;
X
X	for (i = DIRTEMPNAMES;  0 <= --i;  )
X	    if ((m = dirtfmaker[i]) != notmade) {
X		if (m == effective)
X		    seteid();
X		VOID unlink(dirtfname[i].string);
X		if (m == effective)
X		    setrid();
X		dirtfmaker[i] = notmade;
X	    }
X}
END_OF_FILE
  if test 22247 -ne `wc -c <'src/rcsedit.c'`; then
    echo shar: \"'src/rcsedit.c'\" unpacked with wrong size!
  fi
  # end of 'src/rcsedit.c'
fi
echo shar: End of archive 6 \(of 12\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 12 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.



More information about the Comp.sources.unix mailing list