rcsbase.h revision 11894
111894Speter/* RCS common definitions and data structures */
29Sjkh
311894Speter#define RCSBASE "$Id: rcsbase.h,v 5.20 1995/06/16 06:19:24 eggert Exp $"
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 * $Log: rcsbase.h,v $
3411894Speter * Revision 5.20  1995/06/16 06:19:24  eggert
3511894Speter * Update FSF address.
368858Srgrimes *
3711894Speter * Revision 5.19  1995/06/01 16:23:43  eggert
3811894Speter * (SIZEABLE_PATH): Don't depend on PATH_MAX: it's not worth configuring.
3911894Speter * (Ioffset_type,BINARY_EXPAND,MIN_UNEXPAND,MIN_UNCHANGED_EXPAND): New macros.
4011894Speter * (maps_memory): New macro; replaces many instances of `has_mmap'.
4111894Speter * (cacheptr): Renamed from cachetell.
4211894Speter * (struct RILE): New alternate name for RILE; the type is now recursive.
4311894Speter * (deallocate): New member for RILE, used for generic buffer deallocation.
4411894Speter * (cacheunget_): No longer take a failure arg; just call Ierror on failure.
4511894Speter * (struct rcslock): Renamed from struct lock, to avoid collisions with
4611894Speter * system headers on some hosts.  All users changed.
4711894Speter * (basefilename): Renamed from basename, likewise.
4811894Speter * (dirtpname): Remove; no longer external.
4911894Speter * (dirlen, dateform): Remove; no longer used.
5011894Speter * (cmpdate, fopenSafer, fdSafer, readAccessFilenameBuffer): New functions.
5111894Speter * (zonelenmax): Increase to 9 for full ISO 8601 format.
5211894Speter * (catchmmapints): Depend on has_NFS.
531494Srgrimes *
5411894Speter * Revision 5.18  1994/03/17 14:05:48  eggert
5511894Speter * Add primitives for reading backwards from a RILE;
5611894Speter * this is needed to go back and find the $Log prefix.
5711894Speter * Specify subprocess input via file descriptor, not file name.  Remove lint.
5811894Speter *
5911894Speter * Revision 5.17  1993/11/09 17:40:15  eggert
6011894Speter * Move RCS-specific time handling into rcstime.c.
6111894Speter * printf_string now takes two arguments, alas.
6211894Speter *
6311894Speter * Revision 5.16  1993/11/03 17:42:27  eggert
6411894Speter * Don't arbitrarily limit the number of joins.  Remove `nil'.
6511894Speter * Add Name keyword.  Don't discard ignored phrases.
6611894Speter * Add support for merge -A vs -E, and allow up to three labels.
6711894Speter * Improve quality of diagnostics and prototypes.
6811894Speter *
6911894Speter * Revision 5.15  1992/07/28  16:12:44  eggert
7011894Speter * Statement macro names now end in _.
7111894Speter *
7211894Speter * Revision 5.14  1992/02/17  23:02:22  eggert
7311894Speter * Add -T support.  Work around NFS mmap SIGBUS problem.
7411894Speter *
7511894Speter * Revision 5.13  1992/01/24  18:44:19  eggert
7611894Speter * Add support for bad_creat0.  lint -> RCS_lint
7711894Speter *
7811894Speter * Revision 5.12  1992/01/06  02:42:34  eggert
7911894Speter * while (E) ; -> while (E) continue;
8011894Speter *
819Sjkh * Revision 5.11  1991/10/07  17:32:46  eggert
829Sjkh * Support piece tables even if !has_mmap.
839Sjkh *
849Sjkh * Revision 5.10  1991/09/24  00:28:39  eggert
859Sjkh * Remove unexported functions.
869Sjkh *
879Sjkh * Revision 5.9  1991/08/19  03:13:55  eggert
889Sjkh * Add piece tables and other tuneups, and NFS workarounds.
899Sjkh *
909Sjkh * Revision 5.8  1991/04/21  11:58:20  eggert
919Sjkh * Add -x, RCSINIT, MS-DOS support.
929Sjkh *
939Sjkh * Revision 5.7  1991/02/28  19:18:50  eggert
949Sjkh * Try setuid() if seteuid() doesn't work.
959Sjkh *
969Sjkh * Revision 5.6  1991/02/26  17:48:37  eggert
979Sjkh * Support new link behavior.  Move ANSI C / Posix declarations into conf.sh.
989Sjkh *
999Sjkh * Revision 5.5  1990/12/04  05:18:43  eggert
1009Sjkh * Use -I for prompts and -q for diagnostics.
1019Sjkh *
1029Sjkh * Revision 5.4  1990/11/01  05:03:35  eggert
1039Sjkh * Don't assume that builtins are functions; they may be macros.
1049Sjkh * Permit arbitrary data in logs.
1059Sjkh *
1069Sjkh * Revision 5.3  1990/09/26  23:36:58  eggert
1079Sjkh * Port wait() to non-Posix ANSI C hosts.
1089Sjkh *
1099Sjkh * Revision 5.2  1990/09/04  08:02:20  eggert
1109Sjkh * Don't redefine NAME_MAX, PATH_MAX.
1119Sjkh * Improve incomplete line handling.  Standardize yes-or-no procedure.
1129Sjkh *
1139Sjkh * Revision 5.1  1990/08/29  07:13:53  eggert
1149Sjkh * Add -kkvl.  Fix type typos exposed by porting.  Clean old log messages too.
1159Sjkh *
1169Sjkh * Revision 5.0  1990/08/22  08:12:44  eggert
1179Sjkh * Adjust ANSI C / Posix support.  Add -k, -V, setuid.  Don't call access().
1189Sjkh * Remove compile-time limits; use malloc instead.
1199Sjkh * Ansify and Posixate.  Add support for ISO 8859.
1209Sjkh * Remove snoop and v2 support.
1219Sjkh *
1229Sjkh * Revision 4.9  89/05/01  15:17:14  narten
1238858Srgrimes * botched previous USG fix
1248858Srgrimes *
1259Sjkh * Revision 4.8  89/05/01  14:53:05  narten
1269Sjkh * changed #include <strings.h> -> string.h for USG systems.
1278858Srgrimes *
1289Sjkh * Revision 4.7  88/11/08  15:58:45  narten
1299Sjkh * removed defs for functions loaded from libraries
1308858Srgrimes *
1319Sjkh * Revision 4.6  88/08/09  19:12:36  eggert
1329Sjkh * Shrink stdio code size; remove lint; permit -Dhshsize=nn.
1338858Srgrimes *
1349Sjkh * Revision 4.5  87/12/18  17:06:41  narten
1359Sjkh * made removed BSD ifdef, now uses V4_2BSD
1368858Srgrimes *
1379Sjkh * Revision 4.4  87/10/18  10:29:49  narten
1389Sjkh * Updating version numbers
1399Sjkh * Changes relative to 1.1 are actually relative to 4.2
1408858Srgrimes *
1419Sjkh * Revision 1.3  87/09/24  14:02:25  narten
1429Sjkh * changes for lint
1438858Srgrimes *
1449Sjkh * Revision 1.2  87/03/27  14:22:02  jenkins
1459Sjkh * Port to suns
1468858Srgrimes *
1479Sjkh * Revision 4.2  83/12/20  16:04:20  wft
1489Sjkh * merged 3.6.1.1 and 4.1 (SMALLOG, logsize).
1499Sjkh * moved setting of STRICT_LOCKING to Makefile.
1509Sjkh * changed DOLLAR to UNKN (conflict with KDELIM).
1518858Srgrimes *
1529Sjkh * Revision 4.1  83/05/04  09:12:41  wft
1539Sjkh * Added markers Id and RCSfile.
1549Sjkh * Added Dbranch for default branches.
1558858Srgrimes *
1569Sjkh * Revision 3.6.1.1  83/12/02  21:56:22  wft
1579Sjkh * Increased logsize, added macro SMALLOG.
1588858Srgrimes *
1599Sjkh * Revision 3.6  83/01/15  16:43:28  wft
1609Sjkh * 4.2 prerelease
1618858Srgrimes *
1629Sjkh * Revision 3.6  83/01/15  16:43:28  wft
1639Sjkh * Replaced dbm.h with BYTESIZ, fixed definition of rindex().
1649Sjkh * Added variants of NCPFN and NCPPN for bsd 4.2, selected by defining V4_2BSD.
1659Sjkh * Added macro DELNUMFORM to have uniform format for printing delta text nodes.
1669Sjkh * Added macro DELETE to mark deleted deltas.
1679Sjkh *
1689Sjkh * Revision 3.5  82/12/10  12:16:56  wft
1699Sjkh * Added two forms of DATEFORM, one using %02d, the other %.2d.
1709Sjkh *
1719Sjkh * Revision 3.4  82/12/04  20:01:25  wft
1729Sjkh * added LOCKER, Locker, and USG (redefinition of rindex).
1739Sjkh *
1749Sjkh * Revision 3.3  82/12/03  12:22:04  wft
1759Sjkh * Added dbm.h, stdio.h, RCSBASE, RCSSEP, RCSSUF, WORKMODE, TMPFILE3,
1769Sjkh * PRINTDATE, PRINTTIME, map, and ctab; removed Suffix. Redefined keyvallength
1779Sjkh * using NCPPN. Changed putc() to abort on write error.
1789Sjkh *
1799Sjkh * Revision 3.2  82/10/18  15:03:52  wft
1809Sjkh * added macro STRICT_LOCKING, removed RCSUMASK.
1819Sjkh * renamed JOINFILE[1,2] to JOINFIL[1,2].
1829Sjkh *
1839Sjkh * Revision 3.1  82/10/11  19:41:17  wft
1849Sjkh * removed NBPW, NBPC, NCPW.
1859Sjkh * added typdef int void to aid compiling
1869Sjkh */
1879Sjkh
1889Sjkh
1899Sjkh#include "conf.h"
1909Sjkh
1919Sjkh
1929Sjkh#define EXIT_TROUBLE DIFF_TROUBLE
1939Sjkh
19411894Speter#ifdef _POSIX_PATH_MAX
19511894Speter#	define SIZEABLE_PATH _POSIX_PATH_MAX
1969Sjkh#else
19711894Speter#	define SIZEABLE_PATH 255 /* size of a large path; not a hard limit */
1989Sjkh#endif
1999Sjkh
2009Sjkh/* for traditional C hosts with unusual size arguments */
2019Sjkh#define Fread(p,s,n,f)  fread(p, (freadarg_type)(s), (freadarg_type)(n), f)
2029Sjkh#define Fwrite(p,s,n,f)  fwrite(p, (freadarg_type)(s), (freadarg_type)(n), f)
2039Sjkh
2049Sjkh
2059Sjkh/*
2069Sjkh * Parameters
2079Sjkh */
2089Sjkh
2099Sjkh/* backwards compatibility with old versions of RCS */
2109Sjkh#define VERSION_min 3		/* old output RCS format supported */
2119Sjkh#define VERSION_max 5		/* newest output RCS format supported */
2129Sjkh#ifndef VERSION_DEFAULT		/* default RCS output format */
2139Sjkh#	define VERSION_DEFAULT VERSION_max
2149Sjkh#endif
2159Sjkh#define VERSION(n) ((n) - VERSION_DEFAULT) /* internally, 0 is the default */
2169Sjkh
2179Sjkh#ifndef STRICT_LOCKING
2189Sjkh#define STRICT_LOCKING 1
2199Sjkh#endif
2209Sjkh			      /* 0 sets the default locking to non-strict;  */
2219Sjkh                              /* used in experimental environments.         */
2229Sjkh                              /* 1 sets the default locking to strict;      */
2239Sjkh                              /* used in production environments.           */
2249Sjkh
2259Sjkh#define yearlength	   16 /* (good through AD 9,999,999,999,999,999)    */
22611894Speter#define datesize (yearlength+16)	/* size of output of time2date */
2279Sjkh#define RCSTMPPREFIX '_' /* prefix for temp files in working dir  */
2289Sjkh#define KDELIM            '$' /* delimiter for keywords                     */
2299Sjkh#define VDELIM            ':' /* separates keywords from values             */
2309Sjkh#define DEFAULTSTATE    "Exp" /* default state of revisions                 */
2319Sjkh
2329Sjkh
2339Sjkh
2349Sjkh#define true     1
2359Sjkh#define false    0
2369Sjkh
2379Sjkh
2389Sjkh/*
2399Sjkh * RILE - readonly file
2409Sjkh * declarecache; - declares local cache for RILE variable(s)
2419Sjkh * setupcache - sets up the local RILE cache, but does not initialize it
2429Sjkh * cache, uncache - caches and uncaches the local RILE;
2439Sjkh *	(uncache,cache) is needed around functions that advance the RILE pointer
24411894Speter * Igeteof_(f,c,s) - get a char c from f, executing statement s at EOF
24511894Speter * cachegeteof_(c,s) - Igeteof_ applied to the local RILE
24611894Speter * Iget_(f,c) - like Igeteof_, except EOF is an error
24711894Speter * cacheget_(c) - Iget_ applied to the local RILE
24811894Speter * cacheunget_(f,c,s) - read c backwards from cached f, executing s at BOF
24911894Speter * Ifileno, Ioffset_type, Irewind, Itell - analogs to stdio routines
25011894Speter *
25111894Speter * By conventions, macros whose names end in _ are statements, not expressions.
25211894Speter * Following such macros with `; else' results in a syntax error.
2539Sjkh */
2549Sjkh
25511894Speter#define maps_memory (has_map_fd || has_mmap)
25611894Speter
2579Sjkh#if large_memory
2589Sjkh	typedef unsigned char const *Iptr_type;
25911894Speter	typedef struct RILE {
2609Sjkh		Iptr_type ptr, lim;
26111894Speter		unsigned char *base; /* not Iptr_type for lint's sake */
26211894Speter		unsigned char *readlim;
26311894Speter		int fd;
26411894Speter#		if maps_memory
26511894Speter			void (*deallocate) P((struct RILE *));
2669Sjkh#		else
2679Sjkh			FILE *stream;
2689Sjkh#		endif
2699Sjkh	} RILE;
27011894Speter#	if maps_memory
2719Sjkh#		define declarecache register Iptr_type ptr, lim
2729Sjkh#		define setupcache(f) (lim = (f)->lim)
27311894Speter#		define Igeteof_(f,c,s) if ((f)->ptr==(f)->lim) s else (c)= *(f)->ptr++;
27411894Speter#		define cachegeteof_(c,s) if (ptr==lim) s else (c)= *ptr++;
2759Sjkh#	else
27611894Speter		int Igetmore P((RILE*));
2779Sjkh#		define declarecache register Iptr_type ptr; register RILE *rRILE
2789Sjkh#		define setupcache(f) (rRILE = (f))
27911894Speter#		define Igeteof_(f,c,s) if ((f)->ptr==(f)->readlim && !Igetmore(f)) s else (c)= *(f)->ptr++;
28011894Speter#		define cachegeteof_(c,s) if (ptr==rRILE->readlim && !Igetmore(rRILE)) s else (c)= *ptr++;
2819Sjkh#	endif
2829Sjkh#	define uncache(f) ((f)->ptr = ptr)
2839Sjkh#	define cache(f) (ptr = (f)->ptr)
28411894Speter#	define Iget_(f,c) Igeteof_(f,c,Ieof();)
28511894Speter#	define cacheget_(c) cachegeteof_(c,Ieof();)
28611894Speter#	define cacheunget_(f,c) (c)=(--ptr)[-1];
28711894Speter#	define Ioffset_type size_t
28811894Speter#	define Itell(f) ((f)->ptr - (f)->base)
28911894Speter#	define Irewind(f) ((f)->ptr = (f)->base)
29011894Speter#	define cacheptr() ptr
29111894Speter#	define Ifileno(f) ((f)->fd)
2929Sjkh#else
2939Sjkh#	define RILE FILE
2949Sjkh#	define declarecache register FILE *ptr
2959Sjkh#	define setupcache(f) (ptr = (f))
2969Sjkh#	define uncache(f)
2979Sjkh#	define cache(f)
29811894Speter#	define Igeteof_(f,c,s) {if(((c)=getc(f))==EOF){testIerror(f);if(feof(f))s}}
29911894Speter#	define cachegeteof_(c,s) Igeteof_(ptr,c,s)
30011894Speter#	define Iget_(f,c) { if (((c)=getc(f))==EOF) testIeof(f); }
30111894Speter#	define cacheget_(c) Iget_(ptr,c)
30211894Speter#	define cacheunget_(f,c) if(fseek(ptr,-2L,SEEK_CUR))Ierror();else cacheget_(c)
30311894Speter#	define Ioffset_type long
30411894Speter#	define Itell(f) ftell(f)
3059Sjkh#	define Ifileno(f) fileno(f)
3069Sjkh#endif
3079Sjkh
3089Sjkh/* Print a char, but abort on write error.  */
30911894Speter#define aputc_(c,o) { if (putc(c,o)==EOF) testOerror(o); }
3109Sjkh
3119Sjkh/* Get a character from an RCS file, perhaps copying to a new RCS file.  */
31211894Speter#define GETCeof_(o,c,s) { cachegeteof_(c,s) if (o) aputc_(c,o) }
31311894Speter#define GETC_(o,c) { cacheget_(c) if (o) aputc_(c,o) }
3149Sjkh
3159Sjkh
31611894Speter#define WORKMODE(RCSmode, writable) (((RCSmode)&(mode_t)~(S_IWUSR|S_IWGRP|S_IWOTH)) | ((writable)?S_IWUSR:0))
3179Sjkh/* computes mode of working file: same as RCSmode, but write permission     */
3189Sjkh/* determined by writable */
3199Sjkh
3209Sjkh
3219Sjkh/* character classes and token codes */
3229Sjkhenum tokens {
3239Sjkh/* classes */	DELIM,	DIGIT,	IDCHAR,	NEWLN,	LETTER,	Letter,
3249Sjkh		PERIOD,	SBEGIN,	SPACE,	UNKN,
3259Sjkh/* tokens */	COLON,	ID,	NUM,	SEMI,	STRING
3269Sjkh};
3279Sjkh
3289Sjkh#define SDELIM  '@'     /* the actual character is needed for string handling*/
3299Sjkh/* SDELIM must be consistent with ctab[], so that ctab[SDELIM]==SBEGIN.
3309Sjkh * there should be no overlap among SDELIM, KDELIM, and VDELIM
3319Sjkh */
3329Sjkh
33311894Speter#define isdigit(c) (((unsigned)(c)-'0') <= 9) /* faster than ctab[c]==DIGIT */
3349Sjkh
3359Sjkh
3369Sjkh
3379Sjkh
3389Sjkh
3399Sjkh/***************************************
3409Sjkh * Data structures for the symbol table
3419Sjkh ***************************************/
3429Sjkh
3439Sjkh/* Buffer of arbitrary data */
3449Sjkhstruct buf {
3459Sjkh	char *string;
3469Sjkh	size_t size;
3479Sjkh};
3489Sjkhstruct cbuf {
3499Sjkh	char const *string;
3509Sjkh	size_t size;
3519Sjkh};
3529Sjkh
3539Sjkh/* Hash table entry */
3549Sjkhstruct hshentry {
3559Sjkh	char const	  * num;      /* pointer to revision number (ASCIZ) */
3569Sjkh	char const	  * date;     /* pointer to date of checkin	    */
3579Sjkh	char const	  * author;   /* login of person checking in	    */
3589Sjkh	char const	  * lockedby; /* who locks the revision		    */
3599Sjkh	char const	  * state;    /* state of revision (Exp by default) */
36011894Speter	char const	  * name;     /* name (if any) by which retrieved   */
3619Sjkh	struct cbuf	    log;      /* log message requested at checkin   */
3629Sjkh        struct branchhead * branches; /* list of first revisions on branches*/
36311894Speter	struct cbuf	    ig;	      /* ignored phrases in admin part	    */
36411894Speter	struct cbuf	    igtext;   /* ignored phrases in deltatext part  */
3659Sjkh        struct hshentry   * next;     /* next revision on same branch       */
3669Sjkh	struct hshentry   * nexthsh;  /* next revision with same hash value */
36711894Speter	long		    insertlns;/* lines inserted (computed by rlog)  */
36811894Speter	long		    deletelns;/* lines deleted  (computed by rlog)  */
3699Sjkh	char		    selector; /* true if selected, false if deleted */
3709Sjkh};
3719Sjkh
3729Sjkh/* list of hash entries */
3739Sjkhstruct hshentries {
3749Sjkh	struct hshentries *rest;
3759Sjkh	struct hshentry *first;
3769Sjkh};
3779Sjkh
3789Sjkh/* list element for branch lists */
3799Sjkhstruct branchhead {
3809Sjkh        struct hshentry   * hsh;
3819Sjkh        struct branchhead * nextbranch;
3829Sjkh};
3839Sjkh
3849Sjkh/* accesslist element */
3859Sjkhstruct access {
3869Sjkh	char const	  * login;
3879Sjkh        struct access     * nextaccess;
3889Sjkh};
3899Sjkh
3909Sjkh/* list element for locks  */
39111894Speterstruct rcslock {
3929Sjkh	char const	  * login;
3939Sjkh        struct hshentry   * delta;
39411894Speter	struct rcslock    * nextlock;
3959Sjkh};
3969Sjkh
3979Sjkh/* list element for symbolic names */
3989Sjkhstruct assoc {
3999Sjkh	char const	  * symbol;
4009Sjkh	char const	  * num;
4019Sjkh        struct assoc      * nextassoc;
4029Sjkh};
4039Sjkh
4049Sjkh
4059Sjkh#define mainArgs (argc,argv) int argc; char **argv;
4069Sjkh
40711894Speter#if RCS_lint
4089Sjkh#	define libId(name,rcsid)
4099Sjkh#	define mainProg(name,cmd,rcsid) int name mainArgs
4109Sjkh#else
4119Sjkh#	define libId(name,rcsid) char const name[] = rcsid;
41211894Speter#	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
4139Sjkh#endif
4149Sjkh
4159Sjkh/*
4169Sjkh * Markers for keyword expansion (used in co and ident)
4179Sjkh *	Every byte must have class LETTER or Letter.
4189Sjkh */
4199Sjkh#define AUTHOR          "Author"
4209Sjkh#define DATE            "Date"
4219Sjkh#define HEADER          "Header"
4229Sjkh#define IDH             "Id"
4239Sjkh#define LOCKER          "Locker"
4249Sjkh#define LOG             "Log"
42511894Speter#define NAME		"Name"
4269Sjkh#define RCSFILE         "RCSfile"
4279Sjkh#define REVISION        "Revision"
4289Sjkh#define SOURCE          "Source"
4299Sjkh#define STATE           "State"
4309Sjkh#define keylength 8 /* max length of any of the above keywords */
4319Sjkh
4329Sjkhenum markers { Nomatch, Author, Date, Header, Id,
43311894Speter	       Locker, Log, Name, RCSfile, Revision, Source, State };
4349Sjkh	/* This must be in the same order as rcskeys.c's Keyword[] array. */
4359Sjkh
4369Sjkh#define DELNUMFORM      "\n\n%s\n%s\n"
4379Sjkh/* used by putdtext and scanlogtext */
4389Sjkh
4399Sjkh#define EMPTYLOG "*** empty log message ***" /* used by ci and rlog */
4409Sjkh
4419Sjkh/* main program */
4429Sjkhextern char const cmdid[];
44311894Spetervoid exiterr P((void)) exiting;
4449Sjkh
4459Sjkh/* merge */
44611894Speterint merge P((int,char const*,char const*const[3],char const*const[3]));
4479Sjkh
4489Sjkh/* rcsedit */
4499Sjkh#define ciklogsize 23 /* sizeof("checked in with -k by ") */
4509Sjkhextern FILE *fcopy;
45111894Speterextern char const *resultname;
4529Sjkhextern char const ciklog[ciklogsize];
4539Sjkhextern int locker_expansion;
4549SjkhRILE *rcswriteopen P((struct buf*,struct stat*,int));
45511894Speterchar const *makedirtemp P((int));
4569Sjkhchar const *getcaller P((void));
45711894Speterint addlock P((struct hshentry*,int));
4589Sjkhint addsymbol P((char const*,char const*,int));
4599Sjkhint checkaccesslist P((void));
46011894Speterint chnamemod P((FILE**,char const*,char const*,int,mode_t,time_t));
46111894Speterint donerewrite P((int,time_t));
4629Sjkhint dorewrite P((int,int));
46311894Speterint expandline P((RILE*,FILE*,struct hshentry const*,int,FILE*,int));
4649Sjkhint findlock P((int,struct hshentry**));
46511894Speterint setmtime P((char const*,time_t));
46611894Spetervoid ORCSclose P((void));
46711894Spetervoid ORCSerror P((void));
4689Sjkhvoid copystring P((void));
4699Sjkhvoid dirtempunlink P((void));
4709Sjkhvoid enterstring P((void));
4719Sjkhvoid finishedit P((struct hshentry const*,FILE*,int));
4729Sjkhvoid keepdirtemp P((char const*));
4739Sjkhvoid openfcopy P((FILE*));
4749Sjkhvoid snapshotedit P((FILE*));
4759Sjkhvoid xpandstring P((struct hshentry const*));
4769Sjkh#if has_NFS || bad_unlink
4779Sjkh	int un_link P((char const*));
4789Sjkh#else
4799Sjkh#	define un_link(s) unlink(s)
4809Sjkh#endif
4819Sjkh#if large_memory
4829Sjkh	void edit_string P((void));
4839Sjkh#	define editstring(delta) edit_string()
4849Sjkh#else
4859Sjkh	void editstring P((struct hshentry const*));
4869Sjkh#endif
4879Sjkh
4889Sjkh/* rcsfcmp */
4899Sjkhint rcsfcmp P((RILE*,struct stat const*,char const*,struct hshentry const*));
4909Sjkh
4919Sjkh/* rcsfnms */
49211894Speter#define bufautobegin(b) clear_buf(b)
49311894Speter#define clear_buf(b) (VOID ((b)->string = 0, (b)->size = 0))
4949Sjkhextern FILE *workstdout;
49511894Speterextern char *workname;
49611894Speterextern char const *RCSname;
4979Sjkhextern char const *suffixes;
49811894Speterextern int fdlock;
4999Sjkhextern struct stat RCSstat;
5009SjkhRILE *rcsreadopen P((struct buf*,struct stat*,int));
5019Sjkhchar *bufenlarge P((struct buf*,char const**));
50211894Speterchar const *basefilename P((char const*));
5039Sjkhchar const *getfullRCSname P((void));
5049Sjkhchar const *maketemp P((int));
5059Sjkhchar const *rcssuffix P((char const*));
50611894Speterint pairnames P((int,char**,RILE*(*)P((struct buf*,struct stat*,int)),int,int));
5079Sjkhstruct cbuf bufremember P((struct buf*,size_t));
5089Sjkhvoid bufalloc P((struct buf*,size_t));
5099Sjkhvoid bufautoend P((struct buf*));
5109Sjkhvoid bufrealloc P((struct buf*,size_t));
5119Sjkhvoid bufscat P((struct buf*,char const*));
5129Sjkhvoid bufscpy P((struct buf*,char const*));
5139Sjkhvoid tempunlink P((void));
5149Sjkh
5159Sjkh/* rcsgen */
5169Sjkhextern int interactiveflag;
5179Sjkhextern struct buf curlogbuf;
5189Sjkhchar const *buildrevision P((struct hshentries const*,struct hshentry*,FILE*,int));
5199Sjkhint getcstdin P((void));
52011894Speterint putdtext P((struct hshentry const*,char const*,FILE*,int));
5219Sjkhint ttystdin P((void));
52211894Speterint yesorno P((int,char const*,...)) printf_string(2,3);
5239Sjkhstruct cbuf cleanlogmsg P((char*,size_t));
5249Sjkhstruct cbuf getsstdin P((char const*,char const*,char const*,struct buf*));
5259Sjkhvoid putdesc P((int,char*));
52611894Spetervoid putdftext P((struct hshentry const*,RILE*,FILE*,int));
5279Sjkh
5289Sjkh/* rcskeep */
5299Sjkhextern int prevkeys;
53011894Speterextern struct buf prevauthor, prevdate, prevname, prevrev, prevstate;
5319Sjkhint getoldkeys P((RILE*));
5329Sjkh
5339Sjkh/* rcskeys */
5349Sjkhextern char const *const Keyword[];
5359Sjkhenum markers trymatch P((char const*));
5369Sjkh
5379Sjkh/* rcslex */
5389Sjkhextern FILE *foutptr;
5399Sjkhextern FILE *frewrite;
5409Sjkhextern RILE *finptr;
5419Sjkhextern char const *NextString;
5429Sjkhextern enum tokens nexttok;
5439Sjkhextern int hshenter;
5449Sjkhextern int nerror;
5459Sjkhextern int nextc;
5469Sjkhextern int quietflag;
54711894Speterextern long rcsline;
5489Sjkhchar const *getid P((void));
54911894Spetervoid efaterror P((char const*)) exiting;
55011894Spetervoid enfaterror P((int,char const*)) exiting;
55111894Spetervoid fatcleanup P((int)) exiting;
55211894Spetervoid faterror P((char const*,...)) printf_string_exiting(1,2);
55311894Spetervoid fatserror P((char const*,...)) printf_string_exiting(1,2);
55411894Spetervoid rcsfaterror P((char const*,...)) printf_string_exiting(1,2);
55511894Spetervoid Ieof P((void)) exiting;
55611894Spetervoid Ierror P((void)) exiting;
55711894Spetervoid Oerror P((void)) exiting;
5589Sjkhchar *checkid P((char*,int));
55911894Speterchar *checksym P((char*,int));
5609Sjkhint eoflex P((void));
5619Sjkhint getkeyopt P((char const*));
5629Sjkhint getlex P((enum tokens));
5639Sjkhstruct cbuf getphrases P((char const*));
5649Sjkhstruct cbuf savestring P((struct buf*));
5659Sjkhstruct hshentry *getnum P((void));
5669Sjkhvoid Ifclose P((RILE*));
5679Sjkhvoid Izclose P((RILE**));
5689Sjkhvoid Lexinit P((void));
5699Sjkhvoid Ofclose P((FILE*));
57011894Spetervoid Orewind P((FILE*));
5719Sjkhvoid Ozclose P((FILE**));
57211894Spetervoid aflush P((FILE*));
5739Sjkhvoid afputc P((int,FILE*));
57411894Spetervoid aprintf P((FILE*,char const*,...)) printf_string(2,3);
5759Sjkhvoid aputs P((char const*,FILE*));
5769Sjkhvoid checksid P((char*));
57711894Spetervoid checkssym P((char*));
57811894Spetervoid diagnose P((char const*,...)) printf_string(1,2);
5799Sjkhvoid eerror P((char const*));
5809Sjkhvoid eflush P((void));
5819Sjkhvoid enerror P((int,char const*));
58211894Spetervoid error P((char const*,...)) printf_string(1,2);
5839Sjkhvoid fvfprintf P((FILE*,char const*,va_list));
5849Sjkhvoid getkey P((char const*));
5859Sjkhvoid getkeystring P((char const*));
5869Sjkhvoid nextlex P((void));
5879Sjkhvoid oflush P((void));
5889Sjkhvoid printstring P((void));
5899Sjkhvoid readstring P((void));
5909Sjkhvoid redefined P((int));
59111894Spetervoid rcserror P((char const*,...)) printf_string(1,2);
59211894Spetervoid rcswarn P((char const*,...)) printf_string(1,2);
5939Sjkhvoid testIerror P((FILE*));
5949Sjkhvoid testOerror P((FILE*));
59511894Spetervoid warn P((char const*,...)) printf_string(1,2);
5969Sjkhvoid warnignore P((void));
59711894Spetervoid workerror P((char const*,...)) printf_string(1,2);
59811894Spetervoid workwarn P((char const*,...)) printf_string(1,2);
5999Sjkh#if has_madvise && has_mmap && large_memory
6009Sjkh	void advise_access P((RILE*,int));
6019Sjkh#	define if_advise_access(p,f,advice) if (p) advise_access(f,advice)
6029Sjkh#else
6039Sjkh#	define advise_access(f,advice)
6049Sjkh#	define if_advise_access(p,f,advice)
6059Sjkh#endif
60611894Speter#if large_memory && maps_memory
6079Sjkh	RILE *I_open P((char const*,struct stat*));
6089Sjkh#	define Iopen(f,m,s) I_open(f,s)
6099Sjkh#else
6109Sjkh	RILE *Iopen P((char const*,char const*,struct stat*));
6119Sjkh#endif
6129Sjkh#if !large_memory
6139Sjkh	void testIeof P((FILE*));
6149Sjkh	void Irewind P((RILE*));
6159Sjkh#endif
6169Sjkh
6179Sjkh/* rcsmap */
61811894Speterextern enum tokens const ctab[];
6199Sjkh
6209Sjkh/* rcsrev */
62111894Speterchar *partialno P((struct buf*,char const*,int));
62211894Speterchar const *namedrev P((char const*,struct hshentry*));
6239Sjkhchar const *tiprev P((void));
62411894Speterint cmpdate P((char const*,char const*));
6259Sjkhint cmpnum P((char const*,char const*));
62611894Speterint cmpnumfld P((char const*,char const*,int));
62711894Speterint compartial P((char const*,char const*,int));
6289Sjkhint expandsym P((char const*,struct buf*));
6299Sjkhint fexpandsym P((char const*,struct buf*,RILE*));
6309Sjkhstruct hshentry *genrevs P((char const*,char const*,char const*,char const*,struct hshentries**));
63111894Speterint countnumflds P((char const*));
6329Sjkhvoid getbranchno P((char const*,struct buf*));
6339Sjkh
6349Sjkh/* rcssyn */
6359Sjkh/* These expand modes must agree with Expand_names[] in rcssyn.c.  */
6369Sjkh#define KEYVAL_EXPAND 0 /* -kkv `$Keyword: value $' */
6379Sjkh#define KEYVALLOCK_EXPAND 1 /* -kkvl `$Keyword: value locker $' */
6389Sjkh#define KEY_EXPAND 2 /* -kk `$Keyword$' */
6399Sjkh#define VAL_EXPAND 3 /* -kv `value' */
6409Sjkh#define OLD_EXPAND 4 /* -ko use old string, omitting expansion */
64111894Speter#define BINARY_EXPAND 5 /* -kb like -ko, but use binary mode I/O */
64211894Speter#define MIN_UNEXPAND OLD_EXPAND /* min value for no logical expansion */
64311894Speter#define MIN_UNCHANGED_EXPAND (OPEN_O_BINARY ? BINARY_EXPAND : OLD_EXPAND)
64411894Speter			/* min value guaranteed to yield an identical file */
6459Sjkhstruct diffcmd {
64611894Speter	long
6479Sjkh		line1, /* number of first line */
6489Sjkh		nlines, /* number of lines affected */
6499Sjkh		adprev, /* previous 'a' line1+1 or 'd' line1 */
6509Sjkh		dafter; /* sum of previous 'd' line1 and previous 'd' nlines */
6519Sjkh};
6529Sjkhextern char const      * Dbranch;
6539Sjkhextern struct access   * AccessList;
6549Sjkhextern struct assoc    * Symbols;
6559Sjkhextern struct cbuf Comment;
65611894Speterextern struct cbuf Ignored;
65711894Speterextern struct rcslock *Locks;
6589Sjkhextern struct hshentry * Head;
6599Sjkhextern int		 Expand;
6609Sjkhextern int               StrictLocks;
66111894Speterextern int               TotalDeltas;
6629Sjkhextern char const *const expand_names[];
66311894Speterextern char const
66411894Speter	Kaccess[], Kauthor[], Kbranch[], Kcomment[],
66511894Speter	Kdate[], Kdesc[], Kexpand[], Khead[], Klocks[], Klog[],
66611894Speter	Knext[], Kstate[], Kstrict[], Ksymbols[], Ktext[];
66711894Spetervoid unexpected_EOF P((void)) exiting;
6689Sjkhint getdiffcmd P((RILE*,int,FILE*,struct diffcmd*));
6699Sjkhint str2expmode P((char const*));
6709Sjkhvoid getadmin P((void));
6719Sjkhvoid getdesc P((int));
6729Sjkhvoid gettree P((void));
67311894Spetervoid ignorephrases P((char const*));
6749Sjkhvoid initdiffcmd P((struct diffcmd*));
67511894Spetervoid putadmin P((void));
6769Sjkhvoid putstring P((FILE*,int,struct cbuf,int));
6779Sjkhvoid puttree P((struct hshentry const*,FILE*));
6789Sjkh
67911894Speter/* rcstime */
68011894Speter#define zonelenmax 9 /* maxiumum length of time zone string, e.g. "+12:34:56" */
68111894Speterchar const *date2str P((char const[datesize],char[datesize + zonelenmax]));
68211894Spetertime_t date2time P((char const[datesize]));
68311894Spetervoid str2date P((char const*,char[datesize]));
68411894Spetervoid time2date P((time_t,char[datesize]));
68511894Spetervoid zone_set P((char const*));
68611894Speter
6879Sjkh/* rcsutil */
6889Sjkhextern int RCSversion;
68911894SpeterFILE *fopenSafer P((char const*,char const*));
6909Sjkhchar *cgetenv P((char const*));
6919Sjkhchar *fstr_save P((char const*));
6929Sjkhchar *str_save P((char const*));
6939Sjkhchar const *getusername P((int));
69411894Speterint fdSafer P((int));
6959Sjkhint getRCSINIT P((int,char**,char***));
69611894Speterint run P((int,char const*,...));
69711894Speterint runv P((int,char const*,char const**));
6989Sjkhmalloc_type fremember P((malloc_type));
6999Sjkhmalloc_type ftestalloc P((size_t));
7009Sjkhmalloc_type testalloc P((size_t));
7019Sjkhmalloc_type testrealloc P((malloc_type,size_t));
7029Sjkh#define ftalloc(T) ftnalloc(T,1)
7039Sjkh#define talloc(T) tnalloc(T,1)
70411894Speter#if RCS_lint
7059Sjkh	extern malloc_type lintalloc;
7069Sjkh#	define ftnalloc(T,n) (lintalloc = ftestalloc(sizeof(T)*(n)), (T*)0)
7079Sjkh#	define tnalloc(T,n) (lintalloc = testalloc(sizeof(T)*(n)), (T*)0)
7089Sjkh#	define trealloc(T,p,n) (lintalloc = testrealloc((malloc_type)0, sizeof(T)*(n)), p)
7099Sjkh#	define tfree(p)
7109Sjkh#else
7119Sjkh#	define ftnalloc(T,n) ((T*) ftestalloc(sizeof(T)*(n)))
7129Sjkh#	define tnalloc(T,n) ((T*) testalloc(sizeof(T)*(n)))
7139Sjkh#	define trealloc(T,p,n) ((T*) testrealloc((malloc_type)(p), sizeof(T)*(n)))
7149Sjkh#	define tfree(p) free((malloc_type)(p))
7159Sjkh#endif
71611894Spetertime_t now P((void));
7179Sjkhvoid awrite P((char const*,size_t,FILE*));
7189Sjkhvoid fastcopy P((RILE*,FILE*));
7199Sjkhvoid ffree P((void));
7209Sjkhvoid ffree1 P((char const*));
7219Sjkhvoid setRCSversion P((char const*));
7229Sjkh#if has_signal
7239Sjkh	void catchints P((void));
7249Sjkh	void ignoreints P((void));
7259Sjkh	void restoreints P((void));
7269Sjkh#else
7279Sjkh#	define catchints()
7289Sjkh#	define ignoreints()
7299Sjkh#	define restoreints()
7309Sjkh#endif
73111894Speter#if has_mmap && large_memory
73211894Speter#   if has_NFS && mmap_signal
73311894Speter	void catchmmapints P((void));
73411894Speter	void readAccessFilenameBuffer P((char const*,unsigned char const*));
73511894Speter#   else
73611894Speter#	define catchmmapints()
73711894Speter#   endif
73811894Speter#endif
7399Sjkh#if has_getuid
7409Sjkh	uid_t ruid P((void));
7419Sjkh#	define myself(u) ((u) == ruid())
7429Sjkh#else
7439Sjkh#	define myself(u) true
7449Sjkh#endif
7459Sjkh#if has_setuid
7469Sjkh	uid_t euid P((void));
7479Sjkh	void nosetid P((void));
7489Sjkh	void seteid P((void));
7499Sjkh	void setrid P((void));
7509Sjkh#else
7519Sjkh#	define nosetid()
7529Sjkh#	define seteid()
7539Sjkh#	define setrid()
7549Sjkh#endif
75511894Speter
75611894Speter/* version */
75711894Speterextern char const RCS_version_string[];
758