111894Speter/* RCS common definitions and data structures */
29Sjkh
350472Speter#define RCSBASE "$FreeBSD$"
49Sjkh
511894Speter/* Copyright 1982, 1988, 1989 Walter Tichy
611894Speter   Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
79Sjkh   Distributed under license by the Free Software Foundation, Inc.
89Sjkh
99SjkhThis file is part of RCS.
109Sjkh
119SjkhRCS is free software; you can redistribute it and/or modify
129Sjkhit under the terms of the GNU General Public License as published by
139Sjkhthe Free Software Foundation; either version 2, or (at your option)
149Sjkhany later version.
159Sjkh
169SjkhRCS is distributed in the hope that it will be useful,
179Sjkhbut WITHOUT ANY WARRANTY; without even the implied warranty of
189SjkhMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
199SjkhGNU General Public License for more details.
209Sjkh
219SjkhYou should have received a copy of the GNU General Public License
2211894Speteralong with RCS; see the file COPYING.
2311894SpeterIf not, write to the Free Software Foundation,
2411894Speter59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
259Sjkh
269SjkhReport problems and direct all questions to:
279Sjkh
289Sjkh    rcs-bugs@cs.purdue.edu
299Sjkh
309Sjkh*/
319Sjkh
3211894Speter/*
3311894Speter * Revision 5.20  1995/06/16 06:19:24  eggert
3411894Speter * Update FSF address.
358858Srgrimes *
3611894Speter * Revision 5.19  1995/06/01 16:23:43  eggert
3711894Speter * (SIZEABLE_PATH): Don't depend on PATH_MAX: it's not worth configuring.
3811894Speter * (Ioffset_type,BINARY_EXPAND,MIN_UNEXPAND,MIN_UNCHANGED_EXPAND): New macros.
3911894Speter * (maps_memory): New macro; replaces many instances of `has_mmap'.
4011894Speter * (cacheptr): Renamed from cachetell.
4111894Speter * (struct RILE): New alternate name for RILE; the type is now recursive.
4211894Speter * (deallocate): New member for RILE, used for generic buffer deallocation.
4311894Speter * (cacheunget_): No longer take a failure arg; just call Ierror on failure.
4411894Speter * (struct rcslock): Renamed from struct lock, to avoid collisions with
4511894Speter * system headers on some hosts.  All users changed.
4611894Speter * (basefilename): Renamed from basename, likewise.
4711894Speter * (dirtpname): Remove; no longer external.
4811894Speter * (dirlen, dateform): Remove; no longer used.
4911894Speter * (cmpdate, fopenSafer, fdSafer, readAccessFilenameBuffer): New functions.
5011894Speter * (zonelenmax): Increase to 9 for full ISO 8601 format.
5111894Speter * (catchmmapints): Depend on has_NFS.
521494Srgrimes *
5311894Speter * Revision 5.18  1994/03/17 14:05:48  eggert
5411894Speter * Add primitives for reading backwards from a RILE;
5511894Speter * this is needed to go back and find the $Log prefix.
5611894Speter * Specify subprocess input via file descriptor, not file name.  Remove lint.
5711894Speter *
5811894Speter * Revision 5.17  1993/11/09 17:40:15  eggert
5911894Speter * Move RCS-specific time handling into rcstime.c.
6011894Speter * printf_string now takes two arguments, alas.
6111894Speter *
6211894Speter * Revision 5.16  1993/11/03 17:42:27  eggert
6311894Speter * Don't arbitrarily limit the number of joins.  Remove `nil'.
6411894Speter * Add Name keyword.  Don't discard ignored phrases.
6511894Speter * Add support for merge -A vs -E, and allow up to three labels.
6611894Speter * Improve quality of diagnostics and prototypes.
6711894Speter *
6811894Speter * Revision 5.15  1992/07/28  16:12:44  eggert
6911894Speter * Statement macro names now end in _.
7011894Speter *
7111894Speter * Revision 5.14  1992/02/17  23:02:22  eggert
7211894Speter * Add -T support.  Work around NFS mmap SIGBUS problem.
7311894Speter *
7411894Speter * Revision 5.13  1992/01/24  18:44:19  eggert
7511894Speter * Add support for bad_creat0.  lint -> RCS_lint
7611894Speter *
7711894Speter * Revision 5.12  1992/01/06  02:42:34  eggert
7811894Speter * while (E) ; -> while (E) continue;
7911894Speter *
809Sjkh * Revision 5.11  1991/10/07  17:32:46  eggert
819Sjkh * Support piece tables even if !has_mmap.
829Sjkh *
839Sjkh * Revision 5.10  1991/09/24  00:28:39  eggert
849Sjkh * Remove unexported functions.
859Sjkh *
869Sjkh * Revision 5.9  1991/08/19  03:13:55  eggert
879Sjkh * Add piece tables and other tuneups, and NFS workarounds.
889Sjkh *
899Sjkh * Revision 5.8  1991/04/21  11:58:20  eggert
909Sjkh * Add -x, RCSINIT, MS-DOS support.
919Sjkh *
929Sjkh * Revision 5.7  1991/02/28  19:18:50  eggert
939Sjkh * Try setuid() if seteuid() doesn't work.
949Sjkh *
959Sjkh * Revision 5.6  1991/02/26  17:48:37  eggert
969Sjkh * Support new link behavior.  Move ANSI C / Posix declarations into conf.sh.
979Sjkh *
989Sjkh * Revision 5.5  1990/12/04  05:18:43  eggert
999Sjkh * Use -I for prompts and -q for diagnostics.
1009Sjkh *
1019Sjkh * Revision 5.4  1990/11/01  05:03:35  eggert
1029Sjkh * Don't assume that builtins are functions; they may be macros.
1039Sjkh * Permit arbitrary data in logs.
1049Sjkh *
1059Sjkh * Revision 5.3  1990/09/26  23:36:58  eggert
1069Sjkh * Port wait() to non-Posix ANSI C hosts.
1079Sjkh *
1089Sjkh * Revision 5.2  1990/09/04  08:02:20  eggert
1099Sjkh * Don't redefine NAME_MAX, PATH_MAX.
1109Sjkh * Improve incomplete line handling.  Standardize yes-or-no procedure.
1119Sjkh *
1129Sjkh * Revision 5.1  1990/08/29  07:13:53  eggert
1139Sjkh * Add -kkvl.  Fix type typos exposed by porting.  Clean old log messages too.
1149Sjkh *
1159Sjkh * Revision 5.0  1990/08/22  08:12:44  eggert
1169Sjkh * Adjust ANSI C / Posix support.  Add -k, -V, setuid.  Don't call access().
1179Sjkh * Remove compile-time limits; use malloc instead.
1189Sjkh * Ansify and Posixate.  Add support for ISO 8859.
1199Sjkh * Remove snoop and v2 support.
1209Sjkh *
1219Sjkh * Revision 4.9  89/05/01  15:17:14  narten
1228858Srgrimes * botched previous USG fix
1238858Srgrimes *
1249Sjkh * Revision 4.8  89/05/01  14:53:05  narten
1259Sjkh * changed #include <strings.h> -> string.h for USG systems.
1268858Srgrimes *
1279Sjkh * Revision 4.7  88/11/08  15:58:45  narten
1289Sjkh * removed defs for functions loaded from libraries
1298858Srgrimes *
1309Sjkh * Revision 4.6  88/08/09  19:12:36  eggert
1319Sjkh * Shrink stdio code size; remove lint; permit -Dhshsize=nn.
1328858Srgrimes *
1339Sjkh * Revision 4.5  87/12/18  17:06:41  narten
1349Sjkh * made removed BSD ifdef, now uses V4_2BSD
1358858Srgrimes *
1369Sjkh * Revision 4.4  87/10/18  10:29:49  narten
1379Sjkh * Updating version numbers
1389Sjkh * Changes relative to 1.1 are actually relative to 4.2
1398858Srgrimes *
1409Sjkh * Revision 1.3  87/09/24  14:02:25  narten
1419Sjkh * changes for lint
1428858Srgrimes *
1439Sjkh * Revision 1.2  87/03/27  14:22:02  jenkins
1449Sjkh * Port to suns
1458858Srgrimes *
1469Sjkh * Revision 4.2  83/12/20  16:04:20  wft
1479Sjkh * merged 3.6.1.1 and 4.1 (SMALLOG, logsize).
1489Sjkh * moved setting of STRICT_LOCKING to Makefile.
1499Sjkh * changed DOLLAR to UNKN (conflict with KDELIM).
1508858Srgrimes *
1519Sjkh * Revision 4.1  83/05/04  09:12:41  wft
1529Sjkh * Added markers Id and RCSfile.
1539Sjkh * Added Dbranch for default branches.
1548858Srgrimes *
1559Sjkh * Revision 3.6.1.1  83/12/02  21:56:22  wft
1569Sjkh * Increased logsize, added macro SMALLOG.
1578858Srgrimes *
1589Sjkh * Revision 3.6  83/01/15  16:43:28  wft
1599Sjkh * 4.2 prerelease
1608858Srgrimes *
1619Sjkh * Revision 3.6  83/01/15  16:43:28  wft
1629Sjkh * Replaced dbm.h with BYTESIZ, fixed definition of rindex().
1639Sjkh * Added variants of NCPFN and NCPPN for bsd 4.2, selected by defining V4_2BSD.
1649Sjkh * Added macro DELNUMFORM to have uniform format for printing delta text nodes.
1659Sjkh * Added macro DELETE to mark deleted deltas.
1669Sjkh *
1679Sjkh * Revision 3.5  82/12/10  12:16:56  wft
1689Sjkh * Added two forms of DATEFORM, one using %02d, the other %.2d.
1699Sjkh *
1709Sjkh * Revision 3.4  82/12/04  20:01:25  wft
1719Sjkh * added LOCKER, Locker, and USG (redefinition of rindex).
1729Sjkh *
1739Sjkh * Revision 3.3  82/12/03  12:22:04  wft
1749Sjkh * Added dbm.h, stdio.h, RCSBASE, RCSSEP, RCSSUF, WORKMODE, TMPFILE3,
1759Sjkh * PRINTDATE, PRINTTIME, map, and ctab; removed Suffix. Redefined keyvallength
1769Sjkh * using NCPPN. Changed putc() to abort on write error.
1779Sjkh *
1789Sjkh * Revision 3.2  82/10/18  15:03:52  wft
1799Sjkh * added macro STRICT_LOCKING, removed RCSUMASK.
1809Sjkh * renamed JOINFILE[1,2] to JOINFIL[1,2].
1819Sjkh *
1829Sjkh * Revision 3.1  82/10/11  19:41:17  wft
1839Sjkh * removed NBPW, NBPC, NCPW.
1849Sjkh * added typdef int void to aid compiling
1859Sjkh */
1869Sjkh
1879Sjkh
1889Sjkh#include "conf.h"
1899Sjkh
1909Sjkh
1919Sjkh#define EXIT_TROUBLE DIFF_TROUBLE
1929Sjkh
19311894Speter#ifdef _POSIX_PATH_MAX
19411894Speter#	define SIZEABLE_PATH _POSIX_PATH_MAX
1959Sjkh#else
19611894Speter#	define SIZEABLE_PATH 255 /* size of a large path; not a hard limit */
1979Sjkh#endif
1989Sjkh
1999Sjkh/* for traditional C hosts with unusual size arguments */
2009Sjkh#define Fread(p,s,n,f)  fread(p, (freadarg_type)(s), (freadarg_type)(n), f)
2019Sjkh#define Fwrite(p,s,n,f)  fwrite(p, (freadarg_type)(s), (freadarg_type)(n), f)
2029Sjkh
2039Sjkh
2049Sjkh/*
2059Sjkh * Parameters
2069Sjkh */
2079Sjkh
2089Sjkh/* backwards compatibility with old versions of RCS */
2099Sjkh#define VERSION_min 3		/* old output RCS format supported */
2109Sjkh#define VERSION_max 5		/* newest output RCS format supported */
2119Sjkh#ifndef VERSION_DEFAULT		/* default RCS output format */
2129Sjkh#	define VERSION_DEFAULT VERSION_max
2139Sjkh#endif
2149Sjkh#define VERSION(n) ((n) - VERSION_DEFAULT) /* internally, 0 is the default */
2159Sjkh
2169Sjkh#ifndef STRICT_LOCKING
2179Sjkh#define STRICT_LOCKING 1
2189Sjkh#endif
2199Sjkh			      /* 0 sets the default locking to non-strict;  */
2209Sjkh                              /* used in experimental environments.         */
2219Sjkh                              /* 1 sets the default locking to strict;      */
2229Sjkh                              /* used in production environments.           */
2239Sjkh
2249Sjkh#define yearlength	   16 /* (good through AD 9,999,999,999,999,999)    */
22511894Speter#define datesize (yearlength+16)	/* size of output of time2date */
2269Sjkh#define RCSTMPPREFIX '_' /* prefix for temp files in working dir  */
2279Sjkh#define KDELIM            '$' /* delimiter for keywords                     */
2289Sjkh#define VDELIM            ':' /* separates keywords from values             */
2299Sjkh#define DEFAULTSTATE    "Exp" /* default state of revisions                 */
2309Sjkh
2319Sjkh
2329Sjkh
2339Sjkh#define true     1
2349Sjkh#define false    0
2359Sjkh
2369Sjkh
2379Sjkh/*
2389Sjkh * RILE - readonly file
2399Sjkh * declarecache; - declares local cache for RILE variable(s)
2409Sjkh * setupcache - sets up the local RILE cache, but does not initialize it
2419Sjkh * cache, uncache - caches and uncaches the local RILE;
2429Sjkh *	(uncache,cache) is needed around functions that advance the RILE pointer
24311894Speter * Igeteof_(f,c,s) - get a char c from f, executing statement s at EOF
24411894Speter * cachegeteof_(c,s) - Igeteof_ applied to the local RILE
24511894Speter * Iget_(f,c) - like Igeteof_, except EOF is an error
24611894Speter * cacheget_(c) - Iget_ applied to the local RILE
24711894Speter * cacheunget_(f,c,s) - read c backwards from cached f, executing s at BOF
24811894Speter * Ifileno, Ioffset_type, Irewind, Itell - analogs to stdio routines
24911894Speter *
25011894Speter * By conventions, macros whose names end in _ are statements, not expressions.
25111894Speter * Following such macros with `; else' results in a syntax error.
2529Sjkh */
2539Sjkh
25411894Speter#define maps_memory (has_map_fd || has_mmap)
25511894Speter
2569Sjkh#if large_memory
2579Sjkh	typedef unsigned char const *Iptr_type;
25811894Speter	typedef struct RILE {
2599Sjkh		Iptr_type ptr, lim;
26011894Speter		unsigned char *base; /* not Iptr_type for lint's sake */
26111894Speter		unsigned char *readlim;
26211894Speter		int fd;
26311894Speter#		if maps_memory
26411894Speter			void (*deallocate) P((struct RILE *));
2659Sjkh#		else
2669Sjkh			FILE *stream;
2679Sjkh#		endif
2689Sjkh	} RILE;
26911894Speter#	if maps_memory
2709Sjkh#		define declarecache register Iptr_type ptr, lim
2719Sjkh#		define setupcache(f) (lim = (f)->lim)
27211894Speter#		define Igeteof_(f,c,s) if ((f)->ptr==(f)->lim) s else (c)= *(f)->ptr++;
27311894Speter#		define cachegeteof_(c,s) if (ptr==lim) s else (c)= *ptr++;
2749Sjkh#	else
27511894Speter		int Igetmore P((RILE*));
2769Sjkh#		define declarecache register Iptr_type ptr; register RILE *rRILE
2779Sjkh#		define setupcache(f) (rRILE = (f))
27811894Speter#		define Igeteof_(f,c,s) if ((f)->ptr==(f)->readlim && !Igetmore(f)) s else (c)= *(f)->ptr++;
27911894Speter#		define cachegeteof_(c,s) if (ptr==rRILE->readlim && !Igetmore(rRILE)) s else (c)= *ptr++;
2809Sjkh#	endif
2819Sjkh#	define uncache(f) ((f)->ptr = ptr)
2829Sjkh#	define cache(f) (ptr = (f)->ptr)
28311894Speter#	define Iget_(f,c) Igeteof_(f,c,Ieof();)
28411894Speter#	define cacheget_(c) cachegeteof_(c,Ieof();)
28511894Speter#	define cacheunget_(f,c) (c)=(--ptr)[-1];
28611894Speter#	define Ioffset_type size_t
28711894Speter#	define Itell(f) ((f)->ptr - (f)->base)
28811894Speter#	define Irewind(f) ((f)->ptr = (f)->base)
28911894Speter#	define cacheptr() ptr
29011894Speter#	define Ifileno(f) ((f)->fd)
2919Sjkh#else
2929Sjkh#	define RILE FILE
2939Sjkh#	define declarecache register FILE *ptr
2949Sjkh#	define setupcache(f) (ptr = (f))
2959Sjkh#	define uncache(f)
2969Sjkh#	define cache(f)
29711894Speter#	define Igeteof_(f,c,s) {if(((c)=getc(f))==EOF){testIerror(f);if(feof(f))s}}
29811894Speter#	define cachegeteof_(c,s) Igeteof_(ptr,c,s)
29911894Speter#	define Iget_(f,c) { if (((c)=getc(f))==EOF) testIeof(f); }
30011894Speter#	define cacheget_(c) Iget_(ptr,c)
30111894Speter#	define cacheunget_(f,c) if(fseek(ptr,-2L,SEEK_CUR))Ierror();else cacheget_(c)
30211894Speter#	define Ioffset_type long
30311894Speter#	define Itell(f) ftell(f)
3049Sjkh#	define Ifileno(f) fileno(f)
3059Sjkh#endif
3069Sjkh
3079Sjkh/* Print a char, but abort on write error.  */
30811894Speter#define aputc_(c,o) { if (putc(c,o)==EOF) testOerror(o); }
3099Sjkh
3109Sjkh/* Get a character from an RCS file, perhaps copying to a new RCS file.  */
31111894Speter#define GETCeof_(o,c,s) { cachegeteof_(c,s) if (o) aputc_(c,o) }
31211894Speter#define GETC_(o,c) { cacheget_(c) if (o) aputc_(c,o) }
3139Sjkh
3149Sjkh
31511894Speter#define WORKMODE(RCSmode, writable) (((RCSmode)&(mode_t)~(S_IWUSR|S_IWGRP|S_IWOTH)) | ((writable)?S_IWUSR:0))
3169Sjkh/* computes mode of working file: same as RCSmode, but write permission     */
3179Sjkh/* determined by writable */
3189Sjkh
3199Sjkh
3209Sjkh/* character classes and token codes */
3219Sjkhenum tokens {
3229Sjkh/* classes */	DELIM,	DIGIT,	IDCHAR,	NEWLN,	LETTER,	Letter,
3239Sjkh		PERIOD,	SBEGIN,	SPACE,	UNKN,
3249Sjkh/* tokens */	COLON,	ID,	NUM,	SEMI,	STRING
3259Sjkh};
3269Sjkh
3279Sjkh#define SDELIM  '@'     /* the actual character is needed for string handling*/
3289Sjkh/* SDELIM must be consistent with ctab[], so that ctab[SDELIM]==SBEGIN.
3299Sjkh * there should be no overlap among SDELIM, KDELIM, and VDELIM
3309Sjkh */
3319Sjkh
33211894Speter#define isdigit(c) (((unsigned)(c)-'0') <= 9) /* faster than ctab[c]==DIGIT */
3339Sjkh
3349Sjkh
3359Sjkh
3369Sjkh
3379Sjkh
3389Sjkh/***************************************
3399Sjkh * Data structures for the symbol table
3409Sjkh ***************************************/
3419Sjkh
3429Sjkh/* Buffer of arbitrary data */
3439Sjkhstruct buf {
3449Sjkh	char *string;
3459Sjkh	size_t size;
3469Sjkh};
3479Sjkhstruct cbuf {
3489Sjkh	char const *string;
3499Sjkh	size_t size;
3509Sjkh};
3519Sjkh
3529Sjkh/* Hash table entry */
3539Sjkhstruct hshentry {
3549Sjkh	char const	  * num;      /* pointer to revision number (ASCIZ) */
3559Sjkh	char const	  * date;     /* pointer to date of checkin	    */
3569Sjkh	char const	  * author;   /* login of person checking in	    */
3579Sjkh	char const	  * lockedby; /* who locks the revision		    */
3589Sjkh	char const	  * state;    /* state of revision (Exp by default) */
35911894Speter	char const	  * name;     /* name (if any) by which retrieved   */
3609Sjkh	struct cbuf	    log;      /* log message requested at checkin   */
3619Sjkh        struct branchhead * branches; /* list of first revisions on branches*/
36211894Speter	struct cbuf	    ig;	      /* ignored phrases in admin part	    */
36311894Speter	struct cbuf	    igtext;   /* ignored phrases in deltatext part  */
3649Sjkh        struct hshentry   * next;     /* next revision on same branch       */
3659Sjkh	struct hshentry   * nexthsh;  /* next revision with same hash value */
36611894Speter	long		    insertlns;/* lines inserted (computed by rlog)  */
36711894Speter	long		    deletelns;/* lines deleted  (computed by rlog)  */
3689Sjkh	char		    selector; /* true if selected, false if deleted */
3699Sjkh};
3709Sjkh
3719Sjkh/* list of hash entries */
3729Sjkhstruct hshentries {
3739Sjkh	struct hshentries *rest;
3749Sjkh	struct hshentry *first;
3759Sjkh};
3769Sjkh
3779Sjkh/* list element for branch lists */
3789Sjkhstruct branchhead {
3799Sjkh        struct hshentry   * hsh;
3809Sjkh        struct branchhead * nextbranch;
3819Sjkh};
3829Sjkh
3839Sjkh/* accesslist element */
3849Sjkhstruct access {
3859Sjkh	char const	  * login;
3869Sjkh        struct access     * nextaccess;
3879Sjkh};
3889Sjkh
3899Sjkh/* list element for locks  */
39011894Speterstruct rcslock {
3919Sjkh	char const	  * login;
3929Sjkh        struct hshentry   * delta;
39311894Speter	struct rcslock    * nextlock;
3949Sjkh};
3959Sjkh
3969Sjkh/* list element for symbolic names */
3979Sjkhstruct assoc {
3989Sjkh	char const	  * symbol;
3999Sjkh	char const	  * num;
4009Sjkh        struct assoc      * nextassoc;
4019Sjkh};
4029Sjkh
4039Sjkh
4049Sjkh#define mainArgs (argc,argv) int argc; char **argv;
4059Sjkh
40611894Speter#if RCS_lint
4079Sjkh#	define libId(name,rcsid)
4089Sjkh#	define mainProg(name,cmd,rcsid) int name mainArgs
4099Sjkh#else
4109Sjkh#	define libId(name,rcsid) char const name[] = rcsid;
41111894Speter#	define mainProg(n,c,i) char const Copyright[] = "Copyright 1982,1988,1989 Walter F. Tichy, Purdue CS\nCopyright 1990,1991,1992,1993,1994,1995 Paul Eggert", baseid[] = RCSBASE, cmdid[] = c; libId(n,i) int main P((int,char**)); int main mainArgs
4129Sjkh#endif
4139Sjkh
4149Sjkh/*
4159Sjkh * Markers for keyword expansion (used in co and ident)
4169Sjkh *	Every byte must have class LETTER or Letter.
4179Sjkh */
4189Sjkh#define AUTHOR          "Author"
4199Sjkh#define DATE            "Date"
4209Sjkh#define HEADER          "Header"
4219Sjkh#define IDH             "Id"
4229Sjkh#define LOCKER          "Locker"
4239Sjkh#define LOG             "Log"
42411894Speter#define NAME		"Name"
4259Sjkh#define RCSFILE         "RCSfile"
4269Sjkh#define REVISION        "Revision"
4279Sjkh#define SOURCE          "Source"
4289Sjkh#define STATE           "State"
42925699Speter#define CVSHEADER       "CVSHeader"
43025699Speter#define keylength 9 /* max length of any of the above keywords */
4319Sjkh
4329Sjkhenum markers { Nomatch, Author, Date, Header, Id,
43325699Speter	       Locker, Log, Name, RCSfile, Revision, Source, State, CVSHeader,
43425699Speter	       LocalId };
4359Sjkh	/* This must be in the same order as rcskeys.c's Keyword[] array. */
4369Sjkh
4379Sjkh#define DELNUMFORM      "\n\n%s\n%s\n"
4389Sjkh/* used by putdtext and scanlogtext */
4399Sjkh
4409Sjkh#define EMPTYLOG "*** empty log message ***" /* used by ci and rlog */
4419Sjkh
4429Sjkh/* main program */
4439Sjkhextern char const cmdid[];
44411894Spetervoid exiterr P((void)) exiting;
4459Sjkh
4469Sjkh/* merge */
44711894Speterint merge P((int,char const*,char const*const[3],char const*const[3]));
4489Sjkh
4499Sjkh/* rcsedit */
4509Sjkh#define ciklogsize 23 /* sizeof("checked in with -k by ") */
4519Sjkhextern FILE *fcopy;
45211894Speterextern char const *resultname;
4539Sjkhextern char const ciklog[ciklogsize];
4549Sjkhextern int locker_expansion;
4559SjkhRILE *rcswriteopen P((struct buf*,struct stat*,int));
45611894Speterchar const *makedirtemp P((int));
4579Sjkhchar const *getcaller P((void));
45811894Speterint addlock P((struct hshentry*,int));
4599Sjkhint addsymbol P((char const*,char const*,int));
4609Sjkhint checkaccesslist P((void));
46111894Speterint chnamemod P((FILE**,char const*,char const*,int,mode_t,time_t));
46211894Speterint donerewrite P((int,time_t));
4639Sjkhint dorewrite P((int,int));
46411894Speterint expandline P((RILE*,FILE*,struct hshentry const*,int,FILE*,int));
4659Sjkhint findlock P((int,struct hshentry**));
46611894Speterint setmtime P((char const*,time_t));
46711894Spetervoid ORCSclose P((void));
46811894Spetervoid ORCSerror P((void));
4699Sjkhvoid copystring P((void));
4709Sjkhvoid dirtempunlink P((void));
4719Sjkhvoid enterstring P((void));
4729Sjkhvoid finishedit P((struct hshentry const*,FILE*,int));
4739Sjkhvoid keepdirtemp P((char const*));
4749Sjkhvoid openfcopy P((FILE*));
4759Sjkhvoid snapshotedit P((FILE*));
4769Sjkhvoid xpandstring P((struct hshentry const*));
4779Sjkh#if has_NFS || bad_unlink
4789Sjkh	int un_link P((char const*));
4799Sjkh#else
4809Sjkh#	define un_link(s) unlink(s)
4819Sjkh#endif
4829Sjkh#if large_memory
4839Sjkh	void edit_string P((void));
4849Sjkh#	define editstring(delta) edit_string()
4859Sjkh#else
4869Sjkh	void editstring P((struct hshentry const*));
4879Sjkh#endif
4889Sjkh
4899Sjkh/* rcsfcmp */
4909Sjkhint rcsfcmp P((RILE*,struct stat const*,char const*,struct hshentry const*));
4919Sjkh
4929Sjkh/* rcsfnms */
49311894Speter#define bufautobegin(b) clear_buf(b)
49411894Speter#define clear_buf(b) (VOID ((b)->string = 0, (b)->size = 0))
4959Sjkhextern FILE *workstdout;
49611894Speterextern char *workname;
49711894Speterextern char const *RCSname;
4989Sjkhextern char const *suffixes;
49911894Speterextern int fdlock;
5009Sjkhextern struct stat RCSstat;
5019SjkhRILE *rcsreadopen P((struct buf*,struct stat*,int));
5029Sjkhchar *bufenlarge P((struct buf*,char const**));
50311894Speterchar const *basefilename P((char const*));
5049Sjkhchar const *getfullRCSname P((void));
50525699Speterchar const *getfullCVSname P((void));
5069Sjkhchar const *maketemp P((int));
5079Sjkhchar const *rcssuffix P((char const*));
50811894Speterint pairnames P((int,char**,RILE*(*)P((struct buf*,struct stat*,int)),int,int));
5099Sjkhstruct cbuf bufremember P((struct buf*,size_t));
5109Sjkhvoid bufalloc P((struct buf*,size_t));
5119Sjkhvoid bufautoend P((struct buf*));
5129Sjkhvoid bufrealloc P((struct buf*,size_t));
5139Sjkhvoid bufscat P((struct buf*,char const*));
5149Sjkhvoid bufscpy P((struct buf*,char const*));
5159Sjkhvoid tempunlink P((void));
5169Sjkh
5179Sjkh/* rcsgen */
5189Sjkhextern int interactiveflag;
5199Sjkhextern struct buf curlogbuf;
5209Sjkhchar const *buildrevision P((struct hshentries const*,struct hshentry*,FILE*,int));
5219Sjkhint getcstdin P((void));
52211894Speterint putdtext P((struct hshentry const*,char const*,FILE*,int));
5239Sjkhint ttystdin P((void));
52411894Speterint yesorno P((int,char const*,...)) printf_string(2,3);
5259Sjkhstruct cbuf cleanlogmsg P((char*,size_t));
5269Sjkhstruct cbuf getsstdin P((char const*,char const*,char const*,struct buf*));
5279Sjkhvoid putdesc P((int,char*));
52811894Spetervoid putdftext P((struct hshentry const*,RILE*,FILE*,int));
5299Sjkh
5309Sjkh/* rcskeep */
5319Sjkhextern int prevkeys;
53211894Speterextern struct buf prevauthor, prevdate, prevname, prevrev, prevstate;
5339Sjkhint getoldkeys P((RILE*));
5349Sjkh
5359Sjkh/* rcskeys */
53625699Speterextern char const *Keyword[];
53725699Speterextern enum markers LocalIdMode;
5389Sjkhenum markers trymatch P((char const*));
53925699Spetervoid setRCSLocalId(char const *);
54025699Spetervoid setIncExc(char const *);
5419Sjkh
5429Sjkh/* rcslex */
5439Sjkhextern FILE *foutptr;
5449Sjkhextern FILE *frewrite;
5459Sjkhextern RILE *finptr;
5469Sjkhextern char const *NextString;
5479Sjkhextern enum tokens nexttok;
5489Sjkhextern int hshenter;
5499Sjkhextern int nerror;
5509Sjkhextern int nextc;
5519Sjkhextern int quietflag;
55211894Speterextern long rcsline;
5539Sjkhchar const *getid P((void));
55411894Spetervoid efaterror P((char const*)) exiting;
55511894Spetervoid enfaterror P((int,char const*)) exiting;
55611894Spetervoid fatcleanup P((int)) exiting;
55711894Spetervoid faterror P((char const*,...)) printf_string_exiting(1,2);
55811894Spetervoid fatserror P((char const*,...)) printf_string_exiting(1,2);
55911894Spetervoid rcsfaterror P((char const*,...)) printf_string_exiting(1,2);
56011894Spetervoid Ieof P((void)) exiting;
56111894Spetervoid Ierror P((void)) exiting;
56211894Spetervoid Oerror P((void)) exiting;
5639Sjkhchar *checkid P((char*,int));
56411894Speterchar *checksym P((char*,int));
5659Sjkhint eoflex P((void));
5669Sjkhint getkeyopt P((char const*));
5679Sjkhint getlex P((enum tokens));
5689Sjkhstruct cbuf getphrases P((char const*));
5699Sjkhstruct cbuf savestring P((struct buf*));
5709Sjkhstruct hshentry *getnum P((void));
5719Sjkhvoid Ifclose P((RILE*));
5729Sjkhvoid Izclose P((RILE**));
5739Sjkhvoid Lexinit P((void));
5749Sjkhvoid Ofclose P((FILE*));
57511894Spetervoid Orewind P((FILE*));
5769Sjkhvoid Ozclose P((FILE**));
57711894Spetervoid aflush P((FILE*));
5789Sjkhvoid afputc P((int,FILE*));
57911894Spetervoid aprintf P((FILE*,char const*,...)) printf_string(2,3);
5809Sjkhvoid aputs P((char const*,FILE*));
5819Sjkhvoid checksid P((char*));
58211894Spetervoid checkssym P((char*));
58311894Spetervoid diagnose P((char const*,...)) printf_string(1,2);
5849Sjkhvoid eerror P((char const*));
5859Sjkhvoid eflush P((void));
5869Sjkhvoid enerror P((int,char const*));
58711894Spetervoid error P((char const*,...)) printf_string(1,2);
5889Sjkhvoid fvfprintf P((FILE*,char const*,va_list));
5899Sjkhvoid getkey P((char const*));
5909Sjkhvoid getkeystring P((char const*));
5919Sjkhvoid nextlex P((void));
5929Sjkhvoid oflush P((void));
5939Sjkhvoid printstring P((void));
5949Sjkhvoid readstring P((void));
5959Sjkhvoid redefined P((int));
59611894Spetervoid rcserror P((char const*,...)) printf_string(1,2);
59711894Spetervoid rcswarn P((char const*,...)) printf_string(1,2);
5989Sjkhvoid testIerror P((FILE*));
5999Sjkhvoid testOerror P((FILE*));
60011894Spetervoid warn P((char const*,...)) printf_string(1,2);
6019Sjkhvoid warnignore P((void));
60211894Spetervoid workerror P((char const*,...)) printf_string(1,2);
60311894Spetervoid workwarn P((char const*,...)) printf_string(1,2);
6049Sjkh#if has_madvise && has_mmap && large_memory
6059Sjkh	void advise_access P((RILE*,int));
6069Sjkh#	define if_advise_access(p,f,advice) if (p) advise_access(f,advice)
6079Sjkh#else
6089Sjkh#	define advise_access(f,advice)
6099Sjkh#	define if_advise_access(p,f,advice)
6109Sjkh#endif
61111894Speter#if large_memory && maps_memory
6129Sjkh	RILE *I_open P((char const*,struct stat*));
6139Sjkh#	define Iopen(f,m,s) I_open(f,s)
6149Sjkh#else
6159Sjkh	RILE *Iopen P((char const*,char const*,struct stat*));
6169Sjkh#endif
6179Sjkh#if !large_memory
6189Sjkh	void testIeof P((FILE*));
6199Sjkh	void Irewind P((RILE*));
6209Sjkh#endif
6219Sjkh
6229Sjkh/* rcsmap */
62311894Speterextern enum tokens const ctab[];
6249Sjkh
6259Sjkh/* rcsrev */
62611894Speterchar *partialno P((struct buf*,char const*,int));
62711894Speterchar const *namedrev P((char const*,struct hshentry*));
6289Sjkhchar const *tiprev P((void));
62911894Speterint cmpdate P((char const*,char const*));
6309Sjkhint cmpnum P((char const*,char const*));
63111894Speterint cmpnumfld P((char const*,char const*,int));
63211894Speterint compartial P((char const*,char const*,int));
6339Sjkhint expandsym P((char const*,struct buf*));
6349Sjkhint fexpandsym P((char const*,struct buf*,RILE*));
6359Sjkhstruct hshentry *genrevs P((char const*,char const*,char const*,char const*,struct hshentries**));
63611894Speterint countnumflds P((char const*));
6379Sjkhvoid getbranchno P((char const*,struct buf*));
6389Sjkh
6399Sjkh/* rcssyn */
6409Sjkh/* These expand modes must agree with Expand_names[] in rcssyn.c.  */
6419Sjkh#define KEYVAL_EXPAND 0 /* -kkv `$Keyword: value $' */
6429Sjkh#define KEYVALLOCK_EXPAND 1 /* -kkvl `$Keyword: value locker $' */
6439Sjkh#define KEY_EXPAND 2 /* -kk `$Keyword$' */
6449Sjkh#define VAL_EXPAND 3 /* -kv `value' */
6459Sjkh#define OLD_EXPAND 4 /* -ko use old string, omitting expansion */
64611894Speter#define BINARY_EXPAND 5 /* -kb like -ko, but use binary mode I/O */
64711894Speter#define MIN_UNEXPAND OLD_EXPAND /* min value for no logical expansion */
64811894Speter#define MIN_UNCHANGED_EXPAND (OPEN_O_BINARY ? BINARY_EXPAND : OLD_EXPAND)
64911894Speter			/* min value guaranteed to yield an identical file */
6509Sjkhstruct diffcmd {
65111894Speter	long
6529Sjkh		line1, /* number of first line */
6539Sjkh		nlines, /* number of lines affected */
6549Sjkh		adprev, /* previous 'a' line1+1 or 'd' line1 */
6559Sjkh		dafter; /* sum of previous 'd' line1 and previous 'd' nlines */
6569Sjkh};
6579Sjkhextern char const      * Dbranch;
6589Sjkhextern struct access   * AccessList;
6599Sjkhextern struct assoc    * Symbols;
6609Sjkhextern struct cbuf Comment;
66111894Speterextern struct cbuf Ignored;
66211894Speterextern struct rcslock *Locks;
6639Sjkhextern struct hshentry * Head;
6649Sjkhextern int		 Expand;
6659Sjkhextern int               StrictLocks;
66611894Speterextern int               TotalDeltas;
6679Sjkhextern char const *const expand_names[];
66811894Speterextern char const
66911894Speter	Kaccess[], Kauthor[], Kbranch[], Kcomment[],
67011894Speter	Kdate[], Kdesc[], Kexpand[], Khead[], Klocks[], Klog[],
67111894Speter	Knext[], Kstate[], Kstrict[], Ksymbols[], Ktext[];
67211894Spetervoid unexpected_EOF P((void)) exiting;
6739Sjkhint getdiffcmd P((RILE*,int,FILE*,struct diffcmd*));
6749Sjkhint str2expmode P((char const*));
6759Sjkhvoid getadmin P((void));
6769Sjkhvoid getdesc P((int));
6779Sjkhvoid gettree P((void));
67811894Spetervoid ignorephrases P((char const*));
6799Sjkhvoid initdiffcmd P((struct diffcmd*));
68011894Spetervoid putadmin P((void));
6819Sjkhvoid putstring P((FILE*,int,struct cbuf,int));
6829Sjkhvoid puttree P((struct hshentry const*,FILE*));
6839Sjkh
68411894Speter/* rcstime */
68511894Speter#define zonelenmax 9 /* maxiumum length of time zone string, e.g. "+12:34:56" */
68611894Speterchar const *date2str P((char const[datesize],char[datesize + zonelenmax]));
68711894Spetertime_t date2time P((char const[datesize]));
68811894Spetervoid str2date P((char const*,char[datesize]));
68911894Spetervoid time2date P((time_t,char[datesize]));
69011894Spetervoid zone_set P((char const*));
69111894Speter
6929Sjkh/* rcsutil */
6939Sjkhextern int RCSversion;
69411894SpeterFILE *fopenSafer P((char const*,char const*));
6959Sjkhchar *cgetenv P((char const*));
6969Sjkhchar *fstr_save P((char const*));
6979Sjkhchar *str_save P((char const*));
6989Sjkhchar const *getusername P((int));
69911894Speterint fdSafer P((int));
7009Sjkhint getRCSINIT P((int,char**,char***));
70111894Speterint run P((int,char const*,...));
70211894Speterint runv P((int,char const*,char const**));
7039Sjkhmalloc_type fremember P((malloc_type));
7049Sjkhmalloc_type ftestalloc P((size_t));
7059Sjkhmalloc_type testalloc P((size_t));
7069Sjkhmalloc_type testrealloc P((malloc_type,size_t));
7079Sjkh#define ftalloc(T) ftnalloc(T,1)
7089Sjkh#define talloc(T) tnalloc(T,1)
70911894Speter#if RCS_lint
7109Sjkh	extern malloc_type lintalloc;
7119Sjkh#	define ftnalloc(T,n) (lintalloc = ftestalloc(sizeof(T)*(n)), (T*)0)
7129Sjkh#	define tnalloc(T,n) (lintalloc = testalloc(sizeof(T)*(n)), (T*)0)
7139Sjkh#	define trealloc(T,p,n) (lintalloc = testrealloc((malloc_type)0, sizeof(T)*(n)), p)
7149Sjkh#	define tfree(p)
7159Sjkh#else
7169Sjkh#	define ftnalloc(T,n) ((T*) ftestalloc(sizeof(T)*(n)))
7179Sjkh#	define tnalloc(T,n) ((T*) testalloc(sizeof(T)*(n)))
7189Sjkh#	define trealloc(T,p,n) ((T*) testrealloc((malloc_type)(p), sizeof(T)*(n)))
7199Sjkh#	define tfree(p) free((malloc_type)(p))
7209Sjkh#endif
72111894Spetertime_t now P((void));
7229Sjkhvoid awrite P((char const*,size_t,FILE*));
7239Sjkhvoid fastcopy P((RILE*,FILE*));
7249Sjkhvoid ffree P((void));
7259Sjkhvoid ffree1 P((char const*));
7269Sjkhvoid setRCSversion P((char const*));
7279Sjkh#if has_signal
7289Sjkh	void catchints P((void));
7299Sjkh	void ignoreints P((void));
7309Sjkh	void restoreints P((void));
7319Sjkh#else
7329Sjkh#	define catchints()
7339Sjkh#	define ignoreints()
7349Sjkh#	define restoreints()
7359Sjkh#endif
73611894Speter#if has_mmap && large_memory
73711894Speter#   if has_NFS && mmap_signal
73811894Speter	void catchmmapints P((void));
73911894Speter	void readAccessFilenameBuffer P((char const*,unsigned char const*));
74011894Speter#   else
74111894Speter#	define catchmmapints()
74211894Speter#   endif
74311894Speter#endif
7449Sjkh#if has_getuid
7459Sjkh	uid_t ruid P((void));
7469Sjkh#	define myself(u) ((u) == ruid())
7479Sjkh#else
7489Sjkh#	define myself(u) true
7499Sjkh#endif
7509Sjkh#if has_setuid
7519Sjkh	uid_t euid P((void));
7529Sjkh	void nosetid P((void));
7539Sjkh	void seteid P((void));
7549Sjkh	void setrid P((void));
7559Sjkh#else
7569Sjkh#	define nosetid()
7579Sjkh#	define seteid()
7589Sjkh#	define setrid()
7599Sjkh#endif
76011894Speter
76111894Speter/* version */
76211894Speterextern char const RCS_version_string[];
763