1/* RCS common definitions and data structures */
2
3#define RCSBASE "$Id: rcsbase.h 3476 2003-06-11 15:56:10Z darkwyrm $"
4
5/* Copyright 1982, 1988, 1989 Walter Tichy
6   Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
7   Distributed under license by the Free Software Foundation, Inc.
8
9This file is part of RCS.
10
11RCS is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2, or (at your option)
14any later version.
15
16RCS is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with RCS; see the file COPYING.
23If not, write to the Free Software Foundation,
2459 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26Report problems and direct all questions to:
27
28    rcs-bugs@cs.purdue.edu
29
30*/
31
32/*
33 * $Log: rcsbase.h,v $
34 * Revision 1.1  2003/06/11 15:56:09  darkwyrm
35 * Added rcs, gzip, sed, and associated utilities.
36 *
37 * Revision 5.20  1995/06/16 06:19:24  eggert
38 * Update FSF address.
39 *
40 * Revision 5.19  1995/06/01 16:23:43  eggert
41 * (SIZEABLE_PATH): Don't depend on PATH_MAX: it's not worth configuring.
42 * (Ioffset_type,BINARY_EXPAND,MIN_UNEXPAND,MIN_UNCHANGED_EXPAND): New macros.
43 * (maps_memory): New macro; replaces many instances of `has_mmap'.
44 * (cacheptr): Renamed from cachetell.
45 * (struct RILE): New alternate name for RILE; the type is now recursive.
46 * (deallocate): New member for RILE, used for generic buffer deallocation.
47 * (cacheunget_): No longer take a failure arg; just call Ierror on failure.
48 * (struct rcslock): Renamed from struct lock, to avoid collisions with
49 * system headers on some hosts.  All users changed.
50 * (basefilename): Renamed from basename, likewise.
51 * (dirtpname): Remove; no longer external.
52 * (dirlen, dateform): Remove; no longer used.
53 * (cmpdate, fopenSafer, fdSafer, readAccessFilenameBuffer): New functions.
54 * (zonelenmax): Increase to 9 for full ISO 8601 format.
55 * (catchmmapints): Depend on has_NFS.
56 *
57 * Revision 5.18  1994/03/17 14:05:48  eggert
58 * Add primitives for reading backwards from a RILE;
59 * this is needed to go back and find the $Log prefix.
60 * Specify subprocess input via file descriptor, not file name.  Remove lint.
61 *
62 * Revision 5.17  1993/11/09 17:40:15  eggert
63 * Move RCS-specific time handling into rcstime.c.
64 * printf_string now takes two arguments, alas.
65 *
66 * Revision 5.16  1993/11/03 17:42:27  eggert
67 * Don't arbitrarily limit the number of joins.  Remove `nil'.
68 * Add Name keyword.  Don't discard ignored phrases.
69 * Add support for merge -A vs -E, and allow up to three labels.
70 * Improve quality of diagnostics and prototypes.
71 *
72 * Revision 5.15  1992/07/28  16:12:44  eggert
73 * Statement macro names now end in _.
74 *
75 * Revision 5.14  1992/02/17  23:02:22  eggert
76 * Add -T support.  Work around NFS mmap SIGBUS problem.
77 *
78 * Revision 5.13  1992/01/24  18:44:19  eggert
79 * Add support for bad_creat0.  lint -> RCS_lint
80 *
81 * Revision 5.12  1992/01/06  02:42:34  eggert
82 * while (E) ; -> while (E) continue;
83 *
84 * Revision 5.11  1991/10/07  17:32:46  eggert
85 * Support piece tables even if !has_mmap.
86 *
87 * Revision 5.10  1991/09/24  00:28:39  eggert
88 * Remove unexported functions.
89 *
90 * Revision 5.9  1991/08/19  03:13:55  eggert
91 * Add piece tables and other tuneups, and NFS workarounds.
92 *
93 * Revision 5.8  1991/04/21  11:58:20  eggert
94 * Add -x, RCSINIT, MS-DOS support.
95 *
96 * Revision 5.7  1991/02/28  19:18:50  eggert
97 * Try setuid() if seteuid() doesn't work.
98 *
99 * Revision 5.6  1991/02/26  17:48:37  eggert
100 * Support new link behavior.  Move ANSI C / Posix declarations into conf.sh.
101 *
102 * Revision 5.5  1990/12/04  05:18:43  eggert
103 * Use -I for prompts and -q for diagnostics.
104 *
105 * Revision 5.4  1990/11/01  05:03:35  eggert
106 * Don't assume that builtins are functions; they may be macros.
107 * Permit arbitrary data in logs.
108 *
109 * Revision 5.3  1990/09/26  23:36:58  eggert
110 * Port wait() to non-Posix ANSI C hosts.
111 *
112 * Revision 5.2  1990/09/04  08:02:20  eggert
113 * Don't redefine NAME_MAX, PATH_MAX.
114 * Improve incomplete line handling.  Standardize yes-or-no procedure.
115 *
116 * Revision 5.1  1990/08/29  07:13:53  eggert
117 * Add -kkvl.  Fix type typos exposed by porting.  Clean old log messages too.
118 *
119 * Revision 5.0  1990/08/22  08:12:44  eggert
120 * Adjust ANSI C / Posix support.  Add -k, -V, setuid.  Don't call access().
121 * Remove compile-time limits; use malloc instead.
122 * Ansify and Posixate.  Add support for ISO 8859.
123 * Remove snoop and v2 support.
124 *
125 * Revision 4.9  89/05/01  15:17:14  narten
126 * botched previous USG fix
127 *
128 * Revision 4.8  89/05/01  14:53:05  narten
129 * changed #include <strings.h> -> string.h for USG systems.
130 *
131 * Revision 4.7  88/11/08  15:58:45  narten
132 * removed defs for functions loaded from libraries
133 *
134 * Revision 4.6  88/08/09  19:12:36  eggert
135 * Shrink stdio code size; remove lint; permit -Dhshsize=nn.
136 *
137 * Revision 4.5  87/12/18  17:06:41  narten
138 * made removed BSD ifdef, now uses V4_2BSD
139 *
140 * Revision 4.4  87/10/18  10:29:49  narten
141 * Updating version numbers
142 * Changes relative to 1.1 are actually relative to 4.2
143 *
144 * Revision 1.3  87/09/24  14:02:25  narten
145 * changes for lint
146 *
147 * Revision 1.2  87/03/27  14:22:02  jenkins
148 * Port to suns
149 *
150 * Revision 4.2  83/12/20  16:04:20  wft
151 * merged 3.6.1.1 and 4.1 (SMALLOG, logsize).
152 * moved setting of STRICT_LOCKING to Makefile.
153 * changed DOLLAR to UNKN (conflict with KDELIM).
154 *
155 * Revision 4.1  83/05/04  09:12:41  wft
156 * Added markers Id and RCSfile.
157 * Added Dbranch for default branches.
158 *
159 * Revision 3.6.1.1  83/12/02  21:56:22  wft
160 * Increased logsize, added macro SMALLOG.
161 *
162 * Revision 3.6  83/01/15  16:43:28  wft
163 * 4.2 prerelease
164 *
165 * Revision 3.6  83/01/15  16:43:28  wft
166 * Replaced dbm.h with BYTESIZ, fixed definition of rindex().
167 * Added variants of NCPFN and NCPPN for bsd 4.2, selected by defining V4_2BSD.
168 * Added macro DELNUMFORM to have uniform format for printing delta text nodes.
169 * Added macro DELETE to mark deleted deltas.
170 *
171 * Revision 3.5  82/12/10  12:16:56  wft
172 * Added two forms of DATEFORM, one using %02d, the other %.2d.
173 *
174 * Revision 3.4  82/12/04  20:01:25  wft
175 * added LOCKER, Locker, and USG (redefinition of rindex).
176 *
177 * Revision 3.3  82/12/03  12:22:04  wft
178 * Added dbm.h, stdio.h, RCSBASE, RCSSEP, RCSSUF, WORKMODE, TMPFILE3,
179 * PRINTDATE, PRINTTIME, map, and ctab; removed Suffix. Redefined keyvallength
180 * using NCPPN. Changed putc() to abort on write error.
181 *
182 * Revision 3.2  82/10/18  15:03:52  wft
183 * added macro STRICT_LOCKING, removed RCSUMASK.
184 * renamed JOINFILE[1,2] to JOINFIL[1,2].
185 *
186 * Revision 3.1  82/10/11  19:41:17  wft
187 * removed NBPW, NBPC, NCPW.
188 * added typdef int void to aid compiling
189 */
190
191
192#include "conf.h"
193
194
195#define EXIT_TROUBLE DIFF_TROUBLE
196
197#ifdef _POSIX_PATH_MAX
198#	define SIZEABLE_PATH _POSIX_PATH_MAX
199#else
200#	define SIZEABLE_PATH 255 /* size of a large path; not a hard limit */
201#endif
202
203/* for traditional C hosts with unusual size arguments */
204#define Fread(p,s,n,f)  fread(p, (freadarg_type)(s), (freadarg_type)(n), f)
205#define Fwrite(p,s,n,f)  fwrite(p, (freadarg_type)(s), (freadarg_type)(n), f)
206
207
208/*
209 * Parameters
210 */
211
212/* backwards compatibility with old versions of RCS */
213#define VERSION_min 3		/* old output RCS format supported */
214#define VERSION_max 5		/* newest output RCS format supported */
215#ifndef VERSION_DEFAULT		/* default RCS output format */
216#	define VERSION_DEFAULT VERSION_max
217#endif
218#define VERSION(n) ((n) - VERSION_DEFAULT) /* internally, 0 is the default */
219
220#ifndef STRICT_LOCKING
221#define STRICT_LOCKING 1
222#endif
223			      /* 0 sets the default locking to non-strict;  */
224                              /* used in experimental environments.         */
225                              /* 1 sets the default locking to strict;      */
226                              /* used in production environments.           */
227
228#define yearlength	   16 /* (good through AD 9,999,999,999,999,999)    */
229#define datesize (yearlength+16)	/* size of output of time2date */
230#define RCSTMPPREFIX '_' /* prefix for temp files in working dir  */
231#define KDELIM            '$' /* delimiter for keywords                     */
232#define VDELIM            ':' /* separates keywords from values             */
233#define DEFAULTSTATE    "Exp" /* default state of revisions                 */
234
235
236
237#define true     1
238#define false    0
239
240
241/*
242 * RILE - readonly file
243 * declarecache; - declares local cache for RILE variable(s)
244 * setupcache - sets up the local RILE cache, but does not initialize it
245 * cache, uncache - caches and uncaches the local RILE;
246 *	(uncache,cache) is needed around functions that advance the RILE pointer
247 * Igeteof_(f,c,s) - get a char c from f, executing statement s at EOF
248 * cachegeteof_(c,s) - Igeteof_ applied to the local RILE
249 * Iget_(f,c) - like Igeteof_, except EOF is an error
250 * cacheget_(c) - Iget_ applied to the local RILE
251 * cacheunget_(f,c,s) - read c backwards from cached f, executing s at BOF
252 * Ifileno, Ioffset_type, Irewind, Itell - analogs to stdio routines
253 *
254 * By conventions, macros whose names end in _ are statements, not expressions.
255 * Following such macros with `; else' results in a syntax error.
256 */
257
258#define maps_memory (has_map_fd || has_mmap)
259
260#if large_memory
261	typedef unsigned char const *Iptr_type;
262	typedef struct RILE {
263		Iptr_type ptr, lim;
264		unsigned char *base; /* not Iptr_type for lint's sake */
265		unsigned char *readlim;
266		int fd;
267#		if maps_memory
268			void (*deallocate) P((struct RILE *));
269#		else
270			FILE *stream;
271#		endif
272	} RILE;
273#	if maps_memory
274#		define declarecache register Iptr_type ptr, lim
275#		define setupcache(f) (lim = (f)->lim)
276#		define Igeteof_(f,c,s) if ((f)->ptr==(f)->lim) s else (c)= *(f)->ptr++;
277#		define cachegeteof_(c,s) if (ptr==lim) s else (c)= *ptr++;
278#	else
279		int Igetmore P((RILE*));
280#		define declarecache register Iptr_type ptr; register RILE *rRILE
281#		define setupcache(f) (rRILE = (f))
282#		define Igeteof_(f,c,s) if ((f)->ptr==(f)->readlim && !Igetmore(f)) s else (c)= *(f)->ptr++;
283#		define cachegeteof_(c,s) if (ptr==rRILE->readlim && !Igetmore(rRILE)) s else (c)= *ptr++;
284#	endif
285#	define uncache(f) ((f)->ptr = ptr)
286#	define cache(f) (ptr = (f)->ptr)
287#	define Iget_(f,c) Igeteof_(f,c,Ieof();)
288#	define cacheget_(c) cachegeteof_(c,Ieof();)
289#	define cacheunget_(f,c) (c)=(--ptr)[-1];
290#	define Ioffset_type size_t
291#	define Itell(f) ((f)->ptr - (f)->base)
292#	define Irewind(f) ((f)->ptr = (f)->base)
293#	define cacheptr() ptr
294#	define Ifileno(f) ((f)->fd)
295#else
296#	define RILE FILE
297#	define declarecache register FILE *ptr
298#	define setupcache(f) (ptr = (f))
299#	define uncache(f)
300#	define cache(f)
301#	define Igeteof_(f,c,s) {if(((c)=getc(f))==EOF){testIerror(f);if(feof(f))s}}
302#	define cachegeteof_(c,s) Igeteof_(ptr,c,s)
303#	define Iget_(f,c) { if (((c)=getc(f))==EOF) testIeof(f); }
304#	define cacheget_(c) Iget_(ptr,c)
305#	define cacheunget_(f,c) if(fseek(ptr,-2L,SEEK_CUR))Ierror();else cacheget_(c)
306#	define Ioffset_type long
307#	define Itell(f) ftell(f)
308#	define Ifileno(f) fileno(f)
309#endif
310
311/* Print a char, but abort on write error.  */
312#define aputc_(c,o) { if (putc(c,o)==EOF) testOerror(o); }
313
314/* Get a character from an RCS file, perhaps copying to a new RCS file.  */
315#define GETCeof_(o,c,s) { cachegeteof_(c,s) if (o) aputc_(c,o) }
316#define GETC_(o,c) { cacheget_(c) if (o) aputc_(c,o) }
317
318
319#define WORKMODE(RCSmode, writable) (((RCSmode)&(mode_t)~(S_IWUSR|S_IWGRP|S_IWOTH)) | ((writable)?S_IWUSR:0))
320/* computes mode of working file: same as RCSmode, but write permission     */
321/* determined by writable */
322
323
324/* character classes and token codes */
325enum tokens {
326/* classes */	DELIM,	DIGIT,	IDCHAR,	NEWLN,	LETTER,	Letter,
327		PERIOD,	SBEGIN,	SPACE,	UNKN,
328/* tokens */	COLON,	ID,	NUM,	SEMI,	STRING
329};
330
331#define SDELIM  '@'     /* the actual character is needed for string handling*/
332/* SDELIM must be consistent with ctab[], so that ctab[SDELIM]==SBEGIN.
333 * there should be no overlap among SDELIM, KDELIM, and VDELIM
334 */
335
336#define isdigit(c) (((unsigned)(c)-'0') <= 9) /* faster than ctab[c]==DIGIT */
337
338
339
340
341
342/***************************************
343 * Data structures for the symbol table
344 ***************************************/
345
346/* Buffer of arbitrary data */
347struct buf {
348	char *string;
349	size_t size;
350};
351struct cbuf {
352	char const *string;
353	size_t size;
354};
355
356/* Hash table entry */
357struct hshentry {
358	char const	  * num;      /* pointer to revision number (ASCIZ) */
359	char const	  * date;     /* pointer to date of checkin	    */
360	char const	  * author;   /* login of person checking in	    */
361	char const	  * lockedby; /* who locks the revision		    */
362	char const	  * state;    /* state of revision (Exp by default) */
363	char const	  * name;     /* name (if any) by which retrieved   */
364	struct cbuf	    log;      /* log message requested at checkin   */
365        struct branchhead * branches; /* list of first revisions on branches*/
366	struct cbuf	    ig;	      /* ignored phrases in admin part	    */
367	struct cbuf	    igtext;   /* ignored phrases in deltatext part  */
368        struct hshentry   * next;     /* next revision on same branch       */
369	struct hshentry   * nexthsh;  /* next revision with same hash value */
370	long		    insertlns;/* lines inserted (computed by rlog)  */
371	long		    deletelns;/* lines deleted  (computed by rlog)  */
372	char		    selector; /* true if selected, false if deleted */
373};
374
375/* list of hash entries */
376struct hshentries {
377	struct hshentries *rest;
378	struct hshentry *first;
379};
380
381/* list element for branch lists */
382struct branchhead {
383        struct hshentry   * hsh;
384        struct branchhead * nextbranch;
385};
386
387/* accesslist element */
388struct access {
389	char const	  * login;
390        struct access     * nextaccess;
391};
392
393/* list element for locks  */
394struct rcslock {
395	char const	  * login;
396        struct hshentry   * delta;
397	struct rcslock    * nextlock;
398};
399
400/* list element for symbolic names */
401struct assoc {
402	char const	  * symbol;
403	char const	  * num;
404        struct assoc      * nextassoc;
405};
406
407
408#define mainArgs (argc,argv) int argc; char **argv;
409
410#if RCS_lint
411#	define libId(name,rcsid)
412#	define mainProg(name,cmd,rcsid) int name mainArgs
413#else
414#	define libId(name,rcsid) char const name[] = rcsid;
415#	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
416#endif
417
418/*
419 * Markers for keyword expansion (used in co and ident)
420 *	Every byte must have class LETTER or Letter.
421 */
422#define AUTHOR          "Author"
423#define DATE            "Date"
424#define HEADER          "Header"
425#define IDH             "Id"
426#define LOCKER          "Locker"
427#define LOG             "Log"
428#define NAME		"Name"
429#define RCSFILE         "RCSfile"
430#define REVISION        "Revision"
431#define SOURCE          "Source"
432#define STATE           "State"
433#define keylength 8 /* max length of any of the above keywords */
434
435enum markers { Nomatch, Author, Date, Header, Id,
436	       Locker, Log, Name, RCSfile, Revision, Source, State };
437	/* This must be in the same order as rcskeys.c's Keyword[] array. */
438
439#define DELNUMFORM      "\n\n%s\n%s\n"
440/* used by putdtext and scanlogtext */
441
442#define EMPTYLOG "*** empty log message ***" /* used by ci and rlog */
443
444/* main program */
445extern char const cmdid[];
446void exiterr P((void)) exiting;
447
448/* merge */
449int merge P((int,char const*,char const*const[3],char const*const[3]));
450
451/* rcsedit */
452#define ciklogsize 23 /* sizeof("checked in with -k by ") */
453extern FILE *fcopy;
454extern char const *resultname;
455extern char const ciklog[ciklogsize];
456extern int locker_expansion;
457RILE *rcswriteopen P((struct buf*,struct stat*,int));
458char const *makedirtemp P((int));
459char const *getcaller P((void));
460int addlock P((struct hshentry*,int));
461int addsymbol P((char const*,char const*,int));
462int checkaccesslist P((void));
463int chnamemod P((FILE**,char const*,char const*,int,mode_t,time_t));
464int donerewrite P((int,time_t));
465int dorewrite P((int,int));
466int expandline P((RILE*,FILE*,struct hshentry const*,int,FILE*,int));
467int findlock P((int,struct hshentry**));
468int setmtime P((char const*,time_t));
469void ORCSclose P((void));
470void ORCSerror P((void));
471void copystring P((void));
472void dirtempunlink P((void));
473void enterstring P((void));
474void finishedit P((struct hshentry const*,FILE*,int));
475void keepdirtemp P((char const*));
476void openfcopy P((FILE*));
477void snapshotedit P((FILE*));
478void xpandstring P((struct hshentry const*));
479#if has_NFS || bad_unlink
480	int un_link P((char const*));
481#else
482#	define un_link(s) unlink(s)
483#endif
484#if large_memory
485	void edit_string P((void));
486#	define editstring(delta) edit_string()
487#else
488	void editstring P((struct hshentry const*));
489#endif
490
491/* rcsfcmp */
492int rcsfcmp P((RILE*,struct stat const*,char const*,struct hshentry const*));
493
494/* rcsfnms */
495#define bufautobegin(b) clear_buf(b)
496#define clear_buf(b) (VOID ((b)->string = 0, (b)->size = 0))
497extern FILE *workstdout;
498extern char *workname;
499extern char const *RCSname;
500extern char const *suffixes;
501extern int fdlock;
502extern struct stat RCSstat;
503RILE *rcsreadopen P((struct buf*,struct stat*,int));
504char *bufenlarge P((struct buf*,char const**));
505char const *basefilename P((char const*));
506char const *getfullRCSname P((void));
507char const *maketemp P((int));
508char const *rcssuffix P((char const*));
509int pairnames P((int,char**,RILE*(*)P((struct buf*,struct stat*,int)),int,int));
510struct cbuf bufremember P((struct buf*,size_t));
511void bufalloc P((struct buf*,size_t));
512void bufautoend P((struct buf*));
513void bufrealloc P((struct buf*,size_t));
514void bufscat P((struct buf*,char const*));
515void bufscpy P((struct buf*,char const*));
516void tempunlink P((void));
517
518/* rcsgen */
519extern int interactiveflag;
520extern struct buf curlogbuf;
521char const *buildrevision P((struct hshentries const*,struct hshentry*,FILE*,int));
522int getcstdin P((void));
523int putdtext P((struct hshentry const*,char const*,FILE*,int));
524int ttystdin P((void));
525int yesorno P((int,char const*,...)) printf_string(2,3);
526struct cbuf cleanlogmsg P((char*,size_t));
527struct cbuf getsstdin P((char const*,char const*,char const*,struct buf*));
528void putdesc P((int,char*));
529void putdftext P((struct hshentry const*,RILE*,FILE*,int));
530
531/* rcskeep */
532extern int prevkeys;
533extern struct buf prevauthor, prevdate, prevname, prevrev, prevstate;
534int getoldkeys P((RILE*));
535
536/* rcskeys */
537extern char const *const Keyword[];
538enum markers trymatch P((char const*));
539
540/* rcslex */
541extern FILE *foutptr;
542extern FILE *frewrite;
543extern RILE *finptr;
544extern char const *NextString;
545extern enum tokens nexttok;
546extern int hshenter;
547extern int nerror;
548extern int nextc;
549extern int quietflag;
550extern long rcsline;
551char const *getid P((void));
552void efaterror P((char const*)) exiting;
553void enfaterror P((int,char const*)) exiting;
554void fatcleanup P((int)) exiting;
555void faterror P((char const*,...)) printf_string_exiting(1,2);
556void fatserror P((char const*,...)) printf_string_exiting(1,2);
557void rcsfaterror P((char const*,...)) printf_string_exiting(1,2);
558void Ieof P((void)) exiting;
559void Ierror P((void)) exiting;
560void Oerror P((void)) exiting;
561char *checkid P((char*,int));
562char *checksym P((char*,int));
563int eoflex P((void));
564int getkeyopt P((char const*));
565int getlex P((enum tokens));
566struct cbuf getphrases P((char const*));
567struct cbuf savestring P((struct buf*));
568struct hshentry *getnum P((void));
569void Ifclose P((RILE*));
570void Izclose P((RILE**));
571void Lexinit P((void));
572void Ofclose P((FILE*));
573void Orewind P((FILE*));
574void Ozclose P((FILE**));
575void aflush P((FILE*));
576void afputc P((int,FILE*));
577void aprintf P((FILE*,char const*,...)) printf_string(2,3);
578void aputs P((char const*,FILE*));
579void checksid P((char*));
580void checkssym P((char*));
581void diagnose P((char const*,...)) printf_string(1,2);
582void eerror P((char const*));
583void eflush P((void));
584void enerror P((int,char const*));
585void error P((char const*,...)) printf_string(1,2);
586void fvfprintf P((FILE*,char const*,va_list));
587void getkey P((char const*));
588void getkeystring P((char const*));
589void nextlex P((void));
590void oflush P((void));
591void printstring P((void));
592void readstring P((void));
593void redefined P((int));
594void rcserror P((char const*,...)) printf_string(1,2);
595void rcswarn P((char const*,...)) printf_string(1,2);
596void testIerror P((FILE*));
597void testOerror P((FILE*));
598void warn P((char const*,...)) printf_string(1,2);
599void warnignore P((void));
600void workerror P((char const*,...)) printf_string(1,2);
601void workwarn P((char const*,...)) printf_string(1,2);
602#if has_madvise && has_mmap && large_memory
603	void advise_access P((RILE*,int));
604#	define if_advise_access(p,f,advice) if (p) advise_access(f,advice)
605#else
606#	define advise_access(f,advice)
607#	define if_advise_access(p,f,advice)
608#endif
609#if large_memory && maps_memory
610	RILE *I_open P((char const*,struct stat*));
611#	define Iopen(f,m,s) I_open(f,s)
612#else
613	RILE *Iopen P((char const*,char const*,struct stat*));
614#endif
615#if !large_memory
616	void testIeof P((FILE*));
617	void Irewind P((RILE*));
618#endif
619
620/* rcsmap */
621extern enum tokens const ctab[];
622
623/* rcsrev */
624char *partialno P((struct buf*,char const*,int));
625char const *namedrev P((char const*,struct hshentry*));
626char const *tiprev P((void));
627int cmpdate P((char const*,char const*));
628int cmpnum P((char const*,char const*));
629int cmpnumfld P((char const*,char const*,int));
630int compartial P((char const*,char const*,int));
631int expandsym P((char const*,struct buf*));
632int fexpandsym P((char const*,struct buf*,RILE*));
633struct hshentry *genrevs P((char const*,char const*,char const*,char const*,struct hshentries**));
634int countnumflds P((char const*));
635void getbranchno P((char const*,struct buf*));
636
637/* rcssyn */
638/* These expand modes must agree with Expand_names[] in rcssyn.c.  */
639#define KEYVAL_EXPAND 0 /* -kkv `$Keyword: value $' */
640#define KEYVALLOCK_EXPAND 1 /* -kkvl `$Keyword: value locker $' */
641#define KEY_EXPAND 2 /* -kk `$Keyword$' */
642#define VAL_EXPAND 3 /* -kv `value' */
643#define OLD_EXPAND 4 /* -ko use old string, omitting expansion */
644#define BINARY_EXPAND 5 /* -kb like -ko, but use binary mode I/O */
645#define MIN_UNEXPAND OLD_EXPAND /* min value for no logical expansion */
646#define MIN_UNCHANGED_EXPAND (OPEN_O_BINARY ? BINARY_EXPAND : OLD_EXPAND)
647			/* min value guaranteed to yield an identical file */
648struct diffcmd {
649	long
650		line1, /* number of first line */
651		nlines, /* number of lines affected */
652		adprev, /* previous 'a' line1+1 or 'd' line1 */
653		dafter; /* sum of previous 'd' line1 and previous 'd' nlines */
654};
655extern char const      * Dbranch;
656extern struct access   * AccessList;
657extern struct assoc    * Symbols;
658extern struct cbuf Comment;
659extern struct cbuf Ignored;
660extern struct rcslock *Locks;
661extern struct hshentry * Head;
662extern int		 Expand;
663extern int               StrictLocks;
664extern int               TotalDeltas;
665extern char const *const expand_names[];
666extern char const
667	Kaccess[], Kauthor[], Kbranch[], Kcomment[],
668	Kdate[], Kdesc[], Kexpand[], Khead[], Klocks[], Klog[],
669	Knext[], Kstate[], Kstrict[], Ksymbols[], Ktext[];
670void unexpected_EOF P((void)) exiting;
671int getdiffcmd P((RILE*,int,FILE*,struct diffcmd*));
672int str2expmode P((char const*));
673void getadmin P((void));
674void getdesc P((int));
675void gettree P((void));
676void ignorephrases P((char const*));
677void initdiffcmd P((struct diffcmd*));
678void putadmin P((void));
679void putstring P((FILE*,int,struct cbuf,int));
680void puttree P((struct hshentry const*,FILE*));
681
682/* rcstime */
683#define zonelenmax 9 /* maxiumum length of time zone string, e.g. "+12:34:56" */
684char const *date2str P((char const[datesize],char[datesize + zonelenmax]));
685time_t date2time P((char const[datesize]));
686void str2date P((char const*,char[datesize]));
687void time2date P((time_t,char[datesize]));
688void zone_set P((char const*));
689
690/* rcsutil */
691extern int RCSversion;
692FILE *fopenSafer P((char const*,char const*));
693char *cgetenv P((char const*));
694char *fstr_save P((char const*));
695char *str_save P((char const*));
696char const *getusername P((int));
697int fdSafer P((int));
698int getRCSINIT P((int,char**,char***));
699int run P((int,char const*,...));
700int runv P((int,char const*,char const**));
701malloc_type fremember P((malloc_type));
702malloc_type ftestalloc P((size_t));
703malloc_type testalloc P((size_t));
704malloc_type testrealloc P((malloc_type,size_t));
705#define ftalloc(T) ftnalloc(T,1)
706#define talloc(T) tnalloc(T,1)
707#if RCS_lint
708	extern malloc_type lintalloc;
709#	define ftnalloc(T,n) (lintalloc = ftestalloc(sizeof(T)*(n)), (T*)0)
710#	define tnalloc(T,n) (lintalloc = testalloc(sizeof(T)*(n)), (T*)0)
711#	define trealloc(T,p,n) (lintalloc = testrealloc((malloc_type)0, sizeof(T)*(n)), p)
712#	define tfree(p)
713#else
714#	define ftnalloc(T,n) ((T*) ftestalloc(sizeof(T)*(n)))
715#	define tnalloc(T,n) ((T*) testalloc(sizeof(T)*(n)))
716#	define trealloc(T,p,n) ((T*) testrealloc((malloc_type)(p), sizeof(T)*(n)))
717#	define tfree(p) free((malloc_type)(p))
718#endif
719time_t now P((void));
720void awrite P((char const*,size_t,FILE*));
721void fastcopy P((RILE*,FILE*));
722void ffree P((void));
723void ffree1 P((char const*));
724void setRCSversion P((char const*));
725#if has_signal
726	void catchints P((void));
727	void ignoreints P((void));
728	void restoreints P((void));
729#else
730#	define catchints()
731#	define ignoreints()
732#	define restoreints()
733#endif
734#if has_mmap && large_memory
735#   if has_NFS && mmap_signal
736	void catchmmapints P((void));
737	void readAccessFilenameBuffer P((char const*,unsigned char const*));
738#   else
739#	define catchmmapints()
740#   endif
741#endif
742#if has_getuid
743	uid_t ruid P((void));
744#	define myself(u) ((u) == ruid())
745#else
746#	define myself(u) true
747#endif
748#if has_setuid
749	uid_t euid P((void));
750	void nosetid P((void));
751	void seteid P((void));
752	void setrid P((void));
753#else
754#	define nosetid()
755#	define seteid()
756#	define setrid()
757#endif
758
759/* version */
760extern char const RCS_version_string[];
761