xref: /illumos-gate/usr/src/tools/cscope-fast/main.c (revision c4d175c6)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
23*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
28*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate /*
32*7c478bd9Sstevel@tonic-gate  *	cscope - interactive C symbol cross-reference
33*7c478bd9Sstevel@tonic-gate  *
34*7c478bd9Sstevel@tonic-gate  *	main functions
35*7c478bd9Sstevel@tonic-gate  */
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #include <curses.h>	/* stdscr and TRUE */
38*7c478bd9Sstevel@tonic-gate #include <fcntl.h>	/* O_RDONLY */
39*7c478bd9Sstevel@tonic-gate #include <sys/types.h>	/* needed by stat.h */
40*7c478bd9Sstevel@tonic-gate #include <unistd.h>	/* O_RDONLY */
41*7c478bd9Sstevel@tonic-gate #include <unistd.h>	/* O_RDONLY */
42*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>	/* stat */
43*7c478bd9Sstevel@tonic-gate #include <libgen.h>	/* O_RDONLY */
44*7c478bd9Sstevel@tonic-gate #include "global.h"
45*7c478bd9Sstevel@tonic-gate #include "version.h"	/* FILEVERSION and FIXVERSION */
46*7c478bd9Sstevel@tonic-gate #include "vp.h"		/* vpdirs and vpndirs */
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #define	OPTSEPS	" \t"	/* CSCOPEOPTION separators */
49*7c478bd9Sstevel@tonic-gate #define	MINHOURS 4	/* minimum no activity timeout hours */
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate /* defaults for unset environment variables */
52*7c478bd9Sstevel@tonic-gate #define	EDITOR	"vi"
53*7c478bd9Sstevel@tonic-gate #define	SHELL	"sh"
54*7c478bd9Sstevel@tonic-gate #define	TMPDIR	"/tmp"
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate /*
57*7c478bd9Sstevel@tonic-gate  * note: these digraph character frequencies were calculated from possible
58*7c478bd9Sstevel@tonic-gate  * printable digraphs in the cross-reference for the C compiler
59*7c478bd9Sstevel@tonic-gate  */
60*7c478bd9Sstevel@tonic-gate char	dichar1[] = " teisaprnl(of)=c";	/* 16 most frequent first chars */
61*7c478bd9Sstevel@tonic-gate char	dichar2[] = " tnerpla";		/* 8 most frequent second chars */
62*7c478bd9Sstevel@tonic-gate 					/* using the above as first chars */
63*7c478bd9Sstevel@tonic-gate char	dicode1[256];		/* digraph first character code */
64*7c478bd9Sstevel@tonic-gate char	dicode2[256];		/* digraph second character code */
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate char	*editor, *home, *shell;	/* environment variables */
67*7c478bd9Sstevel@tonic-gate BOOL	compress = YES;		/* compress the characters in the crossref */
68*7c478bd9Sstevel@tonic-gate int	cscopedepth;		/* cscope invocation nesting depth */
69*7c478bd9Sstevel@tonic-gate char	currentdir[PATHLEN + 1]; /* current directory */
70*7c478bd9Sstevel@tonic-gate BOOL	dbtruncated;		/* database symbols are truncated to 8 chars */
71*7c478bd9Sstevel@tonic-gate char	**dbvpdirs;		/* directories (including current) in */
72*7c478bd9Sstevel@tonic-gate 				/* database view path */
73*7c478bd9Sstevel@tonic-gate int	dbvpndirs;		/* # of directories in database view path */
74*7c478bd9Sstevel@tonic-gate int	dispcomponents = 1;	/* file path components to display */
75*7c478bd9Sstevel@tonic-gate BOOL	editallprompt = YES;	/* prompt between editing files */
76*7c478bd9Sstevel@tonic-gate int	fileargc;		/* file argument count */
77*7c478bd9Sstevel@tonic-gate char	**fileargv;		/* file argument values */
78*7c478bd9Sstevel@tonic-gate int	fileversion;		/* cross-reference file version */
79*7c478bd9Sstevel@tonic-gate BOOL	incurses;		/* in curses */
80*7c478bd9Sstevel@tonic-gate INVCONTROL invcontrol;		/* inverted file control structure */
81*7c478bd9Sstevel@tonic-gate BOOL	invertedindex;		/* the database has an inverted index */
82*7c478bd9Sstevel@tonic-gate BOOL	isuptodate;		/* consider the crossref up-to-date */
83*7c478bd9Sstevel@tonic-gate BOOL	linemode;		/* use line oriented user interface */
84*7c478bd9Sstevel@tonic-gate char	*namefile;		/* file of file names */
85*7c478bd9Sstevel@tonic-gate char	*newinvname;		/* new inverted index file name */
86*7c478bd9Sstevel@tonic-gate char	*newinvpost;		/* new inverted index postings file name */
87*7c478bd9Sstevel@tonic-gate char	*newreffile;		/* new cross-reference file name */
88*7c478bd9Sstevel@tonic-gate FILE	*newrefs;		/* new cross-reference */
89*7c478bd9Sstevel@tonic-gate BOOL	noacttimeout;		/* no activity timeout occurred */
90*7c478bd9Sstevel@tonic-gate BOOL	ogs;			/* display OGS book and subsystem names */
91*7c478bd9Sstevel@tonic-gate FILE	*postings;		/* new inverted index postings */
92*7c478bd9Sstevel@tonic-gate char	*prependpath;		/* prepend path to file names */
93*7c478bd9Sstevel@tonic-gate BOOL	returnrequired;		/* RETURN required after selection number */
94*7c478bd9Sstevel@tonic-gate int	symrefs = -1;		/* cross-reference file */
95*7c478bd9Sstevel@tonic-gate char	temp1[PATHLEN + 1];	/* temporary file name */
96*7c478bd9Sstevel@tonic-gate char	temp2[PATHLEN + 1];	/* temporary file name */
97*7c478bd9Sstevel@tonic-gate long	totalterms;		/* total inverted index terms */
98*7c478bd9Sstevel@tonic-gate BOOL	truncatesyms;		/* truncate symbols to 8 characters */
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate static	BOOL	buildonly;		/* only build the database */
101*7c478bd9Sstevel@tonic-gate static	BOOL	fileschanged;		/* assume some files changed */
102*7c478bd9Sstevel@tonic-gate static	char	*invname = INVNAME;	/* inverted index to the database */
103*7c478bd9Sstevel@tonic-gate static	char	*invpost = INVPOST;	/* inverted index postings */
104*7c478bd9Sstevel@tonic-gate static	unsigned noacttime;		/* no activity timeout in seconds */
105*7c478bd9Sstevel@tonic-gate static	BOOL	onesearch;		/* one search only in line mode */
106*7c478bd9Sstevel@tonic-gate static	char	*reffile = REFFILE;	/* cross-reference file path name */
107*7c478bd9Sstevel@tonic-gate static	char	*reflines;		/* symbol reference lines file */
108*7c478bd9Sstevel@tonic-gate static	char	*tmpdir;		/* temporary directory */
109*7c478bd9Sstevel@tonic-gate static	long	traileroffset;		/* file trailer offset */
110*7c478bd9Sstevel@tonic-gate static	BOOL	unconditional;		/* unconditionally build database */
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate static void options(int argc, char **argv);
113*7c478bd9Sstevel@tonic-gate static void printusage(void);
114*7c478bd9Sstevel@tonic-gate static void removeindex(void);
115*7c478bd9Sstevel@tonic-gate static void cannotindex(void);
116*7c478bd9Sstevel@tonic-gate static void initcompress(void);
117*7c478bd9Sstevel@tonic-gate static void opendatabase(void);
118*7c478bd9Sstevel@tonic-gate static void closedatabase(void);
119*7c478bd9Sstevel@tonic-gate static void build(void);
120*7c478bd9Sstevel@tonic-gate static int compare(const void *s1, const void *s2);
121*7c478bd9Sstevel@tonic-gate static char *getoldfile(void);
122*7c478bd9Sstevel@tonic-gate static void putheader(char *dir);
123*7c478bd9Sstevel@tonic-gate static void putlist(char **names, int count);
124*7c478bd9Sstevel@tonic-gate static BOOL samelist(FILE *oldrefs, char **names, int count);
125*7c478bd9Sstevel@tonic-gate static void skiplist(FILE *oldrefs);
126*7c478bd9Sstevel@tonic-gate static void copydata(void);
127*7c478bd9Sstevel@tonic-gate static void copyinverted(void);
128*7c478bd9Sstevel@tonic-gate static void putinclude(char *s);
129*7c478bd9Sstevel@tonic-gate static void movefile(char *new, char *old);
130*7c478bd9Sstevel@tonic-gate static void timedout(int sig);
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)133*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
134*7c478bd9Sstevel@tonic-gate {
135*7c478bd9Sstevel@tonic-gate 	int	envc;			/* environment argument count */
136*7c478bd9Sstevel@tonic-gate 	char	**envv;			/* environment argument list */
137*7c478bd9Sstevel@tonic-gate 	FILE	*names;			/* name file pointer */
138*7c478bd9Sstevel@tonic-gate 	int	oldnum;			/* number in old cross-ref */
139*7c478bd9Sstevel@tonic-gate 	char	path[PATHLEN + 1];	/* file path */
140*7c478bd9Sstevel@tonic-gate 	FILE	*oldrefs;	/* old cross-reference file */
141*7c478bd9Sstevel@tonic-gate 	char	*s;
142*7c478bd9Sstevel@tonic-gate 	int	c, i;
143*7c478bd9Sstevel@tonic-gate 	pid_t	pid;
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 	/* save the command name for messages */
146*7c478bd9Sstevel@tonic-gate 	argv0 = basename(argv[0]);
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	/* get the current directory for build() and line-oriented P command */
149*7c478bd9Sstevel@tonic-gate 	if (mygetwd(currentdir) == NULL) {
150*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
151*7c478bd9Sstevel@tonic-gate 		    "cscope: warning: cannot get current directory name\n");
152*7c478bd9Sstevel@tonic-gate 		(void) strcpy(currentdir, "<unknown>");
153*7c478bd9Sstevel@tonic-gate 	}
154*7c478bd9Sstevel@tonic-gate 	/* initialize any view path; (saves time since currendir is known) */
155*7c478bd9Sstevel@tonic-gate 	vpinit(currentdir);
156*7c478bd9Sstevel@tonic-gate 	dbvpndirs = vpndirs; /* number of directories in database view path */
157*7c478bd9Sstevel@tonic-gate 	/* directories (including current) in database view path */
158*7c478bd9Sstevel@tonic-gate 	dbvpdirs = vpdirs;
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	/* the first source directory is the current directory */
161*7c478bd9Sstevel@tonic-gate 	sourcedir(".");
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 	/* read the environment */
164*7c478bd9Sstevel@tonic-gate 	editor = mygetenv("EDITOR", EDITOR);
165*7c478bd9Sstevel@tonic-gate 	editor = mygetenv("VIEWER", editor);	/* use viewer if set */
166*7c478bd9Sstevel@tonic-gate 	home = getenv("HOME");
167*7c478bd9Sstevel@tonic-gate 	shell = mygetenv("SHELL", SHELL);
168*7c478bd9Sstevel@tonic-gate 	tmpdir = mygetenv("TMPDIR", TMPDIR);
169*7c478bd9Sstevel@tonic-gate 	/* increment nesting depth */
170*7c478bd9Sstevel@tonic-gate 	cscopedepth = atoi(mygetenv("CSCOPEDEPTH", "0"));
171*7c478bd9Sstevel@tonic-gate 	(void) sprintf(path, "CSCOPEDEPTH=%d", ++cscopedepth);
172*7c478bd9Sstevel@tonic-gate 	(void) putenv(stralloc(path));
173*7c478bd9Sstevel@tonic-gate 	if ((s = getenv("CSCOPEOPTIONS")) != NULL) {
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 		/* parse the environment option string */
176*7c478bd9Sstevel@tonic-gate 		envc = 1;
177*7c478bd9Sstevel@tonic-gate 		envv = mymalloc(sizeof (char *));
178*7c478bd9Sstevel@tonic-gate 		s = strtok(stralloc(s), OPTSEPS);
179*7c478bd9Sstevel@tonic-gate 		while (s != NULL) {
180*7c478bd9Sstevel@tonic-gate 			envv = myrealloc(envv, ++envc * sizeof (char *));
181*7c478bd9Sstevel@tonic-gate 			envv[envc - 1] = stralloc(s);
182*7c478bd9Sstevel@tonic-gate 			s = strtok((char *)NULL, OPTSEPS);
183*7c478bd9Sstevel@tonic-gate 		}
184*7c478bd9Sstevel@tonic-gate 		/* set the environment options */
185*7c478bd9Sstevel@tonic-gate 		options(envc, envv);
186*7c478bd9Sstevel@tonic-gate 	}
187*7c478bd9Sstevel@tonic-gate 	/* set the command line options */
188*7c478bd9Sstevel@tonic-gate 	options(argc, argv);
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	/* create the temporary file names */
191*7c478bd9Sstevel@tonic-gate 	pid = getpid();
192*7c478bd9Sstevel@tonic-gate 	(void) sprintf(temp1, "%s/cscope%d.1", tmpdir, (int)pid);
193*7c478bd9Sstevel@tonic-gate 	(void) sprintf(temp2, "%s/cscope%d.2", tmpdir, (int)pid);
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 	/* if running in the foreground */
196*7c478bd9Sstevel@tonic-gate 	if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate 		/* cleanup on the interrupt and quit signals */
199*7c478bd9Sstevel@tonic-gate 		(void) signal(SIGINT, myexit);
200*7c478bd9Sstevel@tonic-gate 		(void) signal(SIGQUIT, myexit);
201*7c478bd9Sstevel@tonic-gate 	}
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 	/* cleanup on the hangup signal */
204*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGHUP, myexit);
205*7c478bd9Sstevel@tonic-gate 	/* if the database path is relative and it can't be created */
206*7c478bd9Sstevel@tonic-gate 	if (reffile[0] != '/' && access(".", WRITE) != 0) {
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 		/* if the database may not be up-to-date or can't be read */
209*7c478bd9Sstevel@tonic-gate 		(void) sprintf(path, "%s/%s", home, reffile);
210*7c478bd9Sstevel@tonic-gate 		if (isuptodate == NO || access(reffile, READ) != 0) {
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate 			/* put it in the home directory */
213*7c478bd9Sstevel@tonic-gate 			reffile = stralloc(path);
214*7c478bd9Sstevel@tonic-gate 			(void) sprintf(path, "%s/%s", home, invname);
215*7c478bd9Sstevel@tonic-gate 			invname = stralloc(path);
216*7c478bd9Sstevel@tonic-gate 			(void) sprintf(path, "%s/%s", home, invpost);
217*7c478bd9Sstevel@tonic-gate 			invpost = stralloc(path);
218*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
219*7c478bd9Sstevel@tonic-gate 			    "cscope: symbol database will be %s\n", reffile);
220*7c478bd9Sstevel@tonic-gate 		}
221*7c478bd9Sstevel@tonic-gate 	}
222*7c478bd9Sstevel@tonic-gate 	/* if the cross-reference is to be considered up-to-date */
223*7c478bd9Sstevel@tonic-gate 	if (isuptodate == YES) {
224*7c478bd9Sstevel@tonic-gate 		if ((oldrefs = vpfopen(reffile, "r")) == NULL) {
225*7c478bd9Sstevel@tonic-gate 			cannotopen(reffile);
226*7c478bd9Sstevel@tonic-gate 			exit(1);
227*7c478bd9Sstevel@tonic-gate 		}
228*7c478bd9Sstevel@tonic-gate 		/*
229*7c478bd9Sstevel@tonic-gate 		 * get the crossref file version but skip the current
230*7c478bd9Sstevel@tonic-gate 		 * directory
231*7c478bd9Sstevel@tonic-gate 		 */
232*7c478bd9Sstevel@tonic-gate 		if (fscanf(oldrefs, "cscope %d %*s", &fileversion) != 1) {
233*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
234*7c478bd9Sstevel@tonic-gate 			    "cscope: cannot read file version from file %s\n",
235*7c478bd9Sstevel@tonic-gate 			    reffile);
236*7c478bd9Sstevel@tonic-gate 			exit(1);
237*7c478bd9Sstevel@tonic-gate 		}
238*7c478bd9Sstevel@tonic-gate 		if (fileversion >= 8) {
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 			/* override these command line options */
241*7c478bd9Sstevel@tonic-gate 			compress = YES;
242*7c478bd9Sstevel@tonic-gate 			invertedindex = NO;
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 			/* see if there are options in the database */
245*7c478bd9Sstevel@tonic-gate 			for (;;) {
246*7c478bd9Sstevel@tonic-gate 				/* no -q leaves multiple blanks */
247*7c478bd9Sstevel@tonic-gate 				while ((c = getc(oldrefs)) == ' ') {
248*7c478bd9Sstevel@tonic-gate 					;
249*7c478bd9Sstevel@tonic-gate 				}
250*7c478bd9Sstevel@tonic-gate 				if (c != '-') {
251*7c478bd9Sstevel@tonic-gate 					(void) ungetc(c, oldrefs);
252*7c478bd9Sstevel@tonic-gate 					break;
253*7c478bd9Sstevel@tonic-gate 				}
254*7c478bd9Sstevel@tonic-gate 				switch (c = getc(oldrefs)) {
255*7c478bd9Sstevel@tonic-gate 				case 'c':	/* ASCII characters only */
256*7c478bd9Sstevel@tonic-gate 					compress = NO;
257*7c478bd9Sstevel@tonic-gate 					break;
258*7c478bd9Sstevel@tonic-gate 				case 'q':	/* quick search */
259*7c478bd9Sstevel@tonic-gate 					invertedindex = YES;
260*7c478bd9Sstevel@tonic-gate 					(void) fscanf(oldrefs,
261*7c478bd9Sstevel@tonic-gate 					    "%ld", &totalterms);
262*7c478bd9Sstevel@tonic-gate 					break;
263*7c478bd9Sstevel@tonic-gate 				case 'T':
264*7c478bd9Sstevel@tonic-gate 					/* truncate symbols to 8 characters */
265*7c478bd9Sstevel@tonic-gate 					dbtruncated = YES;
266*7c478bd9Sstevel@tonic-gate 					truncatesyms = YES;
267*7c478bd9Sstevel@tonic-gate 					break;
268*7c478bd9Sstevel@tonic-gate 				}
269*7c478bd9Sstevel@tonic-gate 			}
270*7c478bd9Sstevel@tonic-gate 			initcompress();
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 			/* seek to the trailer */
273*7c478bd9Sstevel@tonic-gate 			if (fscanf(oldrefs, "%ld", &traileroffset) != 1) {
274*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
275*7c478bd9Sstevel@tonic-gate 				    "cscope: cannot read trailer offset from "
276*7c478bd9Sstevel@tonic-gate 				    "file %s\n", reffile);
277*7c478bd9Sstevel@tonic-gate 				exit(1);
278*7c478bd9Sstevel@tonic-gate 			}
279*7c478bd9Sstevel@tonic-gate 			if (fseek(oldrefs, traileroffset, 0) != 0) {
280*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
281*7c478bd9Sstevel@tonic-gate 				    "cscope: cannot seek to trailer in "
282*7c478bd9Sstevel@tonic-gate 				    "file %s\n", reffile);
283*7c478bd9Sstevel@tonic-gate 				exit(1);
284*7c478bd9Sstevel@tonic-gate 			}
285*7c478bd9Sstevel@tonic-gate 		}
286*7c478bd9Sstevel@tonic-gate 		/*
287*7c478bd9Sstevel@tonic-gate 		 * read the view path for use in converting relative paths to
288*7c478bd9Sstevel@tonic-gate 		 * full paths
289*7c478bd9Sstevel@tonic-gate 		 *
290*7c478bd9Sstevel@tonic-gate 		 * note: don't overwrite vp[n]dirs because this can cause
291*7c478bd9Sstevel@tonic-gate 		 * the wrong database index files to be found in the viewpath
292*7c478bd9Sstevel@tonic-gate 		 */
293*7c478bd9Sstevel@tonic-gate 		if (fileversion >= 13) {
294*7c478bd9Sstevel@tonic-gate 			if (fscanf(oldrefs, "%d", &dbvpndirs) != 1) {
295*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
296*7c478bd9Sstevel@tonic-gate 				    "cscope: cannot read view path size from "
297*7c478bd9Sstevel@tonic-gate 				    "file %s\n", reffile);
298*7c478bd9Sstevel@tonic-gate 				exit(1);
299*7c478bd9Sstevel@tonic-gate 			}
300*7c478bd9Sstevel@tonic-gate 			if (dbvpndirs > 0) {
301*7c478bd9Sstevel@tonic-gate 				dbvpdirs = mymalloc(
302*7c478bd9Sstevel@tonic-gate 				    dbvpndirs * sizeof (char *));
303*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < dbvpndirs; ++i) {
304*7c478bd9Sstevel@tonic-gate 					if (fscanf(oldrefs, "%s", path) != 1) {
305*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
306*7c478bd9Sstevel@tonic-gate 						    "cscope: cannot read view "
307*7c478bd9Sstevel@tonic-gate 						    "path from file %s\n",
308*7c478bd9Sstevel@tonic-gate 						    reffile);
309*7c478bd9Sstevel@tonic-gate 						exit(1);
310*7c478bd9Sstevel@tonic-gate 					}
311*7c478bd9Sstevel@tonic-gate 					dbvpdirs[i] = stralloc(path);
312*7c478bd9Sstevel@tonic-gate 				}
313*7c478bd9Sstevel@tonic-gate 			}
314*7c478bd9Sstevel@tonic-gate 		}
315*7c478bd9Sstevel@tonic-gate 		/* skip the source and include directory lists */
316*7c478bd9Sstevel@tonic-gate 		skiplist(oldrefs);
317*7c478bd9Sstevel@tonic-gate 		skiplist(oldrefs);
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 		/* get the number of source files */
320*7c478bd9Sstevel@tonic-gate 		if (fscanf(oldrefs, "%d", &nsrcfiles) != 1) {
321*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
322*7c478bd9Sstevel@tonic-gate 			    "cscope: cannot read source file size from "
323*7c478bd9Sstevel@tonic-gate 			    "file %s\n", reffile);
324*7c478bd9Sstevel@tonic-gate 			exit(1);
325*7c478bd9Sstevel@tonic-gate 		}
326*7c478bd9Sstevel@tonic-gate 		/* get the source file list */
327*7c478bd9Sstevel@tonic-gate 		srcfiles = mymalloc(nsrcfiles * sizeof (char *));
328*7c478bd9Sstevel@tonic-gate 		if (fileversion >= 9) {
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 			/* allocate the string space */
331*7c478bd9Sstevel@tonic-gate 			if (fscanf(oldrefs, "%d", &oldnum) != 1) {
332*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
333*7c478bd9Sstevel@tonic-gate 				    "cscope: cannot read string space size "
334*7c478bd9Sstevel@tonic-gate 				    "from file %s\n", reffile);
335*7c478bd9Sstevel@tonic-gate 				exit(1);
336*7c478bd9Sstevel@tonic-gate 			}
337*7c478bd9Sstevel@tonic-gate 			s = mymalloc(oldnum);
338*7c478bd9Sstevel@tonic-gate 			(void) getc(oldrefs);	/* skip the newline */
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate 			/* read the strings */
341*7c478bd9Sstevel@tonic-gate 			if (fread(s, oldnum, 1, oldrefs) != 1) {
342*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
343*7c478bd9Sstevel@tonic-gate 				    "cscope: cannot read source file names "
344*7c478bd9Sstevel@tonic-gate 				    "from file %s\n", reffile);
345*7c478bd9Sstevel@tonic-gate 				exit(1);
346*7c478bd9Sstevel@tonic-gate 			}
347*7c478bd9Sstevel@tonic-gate 			/* change newlines to nulls */
348*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < nsrcfiles; ++i) {
349*7c478bd9Sstevel@tonic-gate 				srcfiles[i] = s;
350*7c478bd9Sstevel@tonic-gate 				for (++s; *s != '\n'; ++s) {
351*7c478bd9Sstevel@tonic-gate 					;
352*7c478bd9Sstevel@tonic-gate 				}
353*7c478bd9Sstevel@tonic-gate 				*s = '\0';
354*7c478bd9Sstevel@tonic-gate 				++s;
355*7c478bd9Sstevel@tonic-gate 			}
356*7c478bd9Sstevel@tonic-gate 			/* if there is a file of source file names */
357*7c478bd9Sstevel@tonic-gate 			if (namefile != NULL &&
358*7c478bd9Sstevel@tonic-gate 			    (names = vpfopen(namefile, "r")) != NULL ||
359*7c478bd9Sstevel@tonic-gate 			    (names = vpfopen(NAMEFILE, "r")) != NULL) {
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 				/* read any -p option from it */
362*7c478bd9Sstevel@tonic-gate 				while (fscanf(names, "%s", path) == 1 &&
363*7c478bd9Sstevel@tonic-gate 				    *path == '-') {
364*7c478bd9Sstevel@tonic-gate 					i = path[1];
365*7c478bd9Sstevel@tonic-gate 					s = path + 2;	/* for "-Ipath" */
366*7c478bd9Sstevel@tonic-gate 					if (*s == '\0') {
367*7c478bd9Sstevel@tonic-gate 						/* if "-I path" */
368*7c478bd9Sstevel@tonic-gate 						(void) fscanf(names,
369*7c478bd9Sstevel@tonic-gate 						    "%s", path);
370*7c478bd9Sstevel@tonic-gate 						s = path;
371*7c478bd9Sstevel@tonic-gate 					}
372*7c478bd9Sstevel@tonic-gate 					switch (i) {
373*7c478bd9Sstevel@tonic-gate 					case 'p':
374*7c478bd9Sstevel@tonic-gate 						/* file path components */
375*7c478bd9Sstevel@tonic-gate 						/* to display */
376*7c478bd9Sstevel@tonic-gate 						if (*s < '0' || *s > '9') {
377*7c478bd9Sstevel@tonic-gate 							(void) fprintf(stderr,
378*7c478bd9Sstevel@tonic-gate 							    "cscope: -p option "
379*7c478bd9Sstevel@tonic-gate 							    "in file %s: "
380*7c478bd9Sstevel@tonic-gate 							    "missing or "
381*7c478bd9Sstevel@tonic-gate 							    "invalid numeric "
382*7c478bd9Sstevel@tonic-gate 							    "value\n",
383*7c478bd9Sstevel@tonic-gate 							    namefile);
384*7c478bd9Sstevel@tonic-gate 						}
385*7c478bd9Sstevel@tonic-gate 						dispcomponents = atoi(s);
386*7c478bd9Sstevel@tonic-gate 					}
387*7c478bd9Sstevel@tonic-gate 				}
388*7c478bd9Sstevel@tonic-gate 				(void) fclose(names);
389*7c478bd9Sstevel@tonic-gate 			}
390*7c478bd9Sstevel@tonic-gate 		} else {
391*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < nsrcfiles; ++i) {
392*7c478bd9Sstevel@tonic-gate 				if (fscanf(oldrefs, "%s", path) != 1) {
393*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
394*7c478bd9Sstevel@tonic-gate 					    "cscope: cannot read source file "
395*7c478bd9Sstevel@tonic-gate 					    "name from file %s\n", reffile);
396*7c478bd9Sstevel@tonic-gate 					exit(1);
397*7c478bd9Sstevel@tonic-gate 				}
398*7c478bd9Sstevel@tonic-gate 				srcfiles[i] = stralloc(path);
399*7c478bd9Sstevel@tonic-gate 			}
400*7c478bd9Sstevel@tonic-gate 		}
401*7c478bd9Sstevel@tonic-gate 		(void) fclose(oldrefs);
402*7c478bd9Sstevel@tonic-gate 	} else {
403*7c478bd9Sstevel@tonic-gate 		/* get source directories from the environment */
404*7c478bd9Sstevel@tonic-gate 		if ((s = getenv("SOURCEDIRS")) != NULL) {
405*7c478bd9Sstevel@tonic-gate 			sourcedir(s);
406*7c478bd9Sstevel@tonic-gate 		}
407*7c478bd9Sstevel@tonic-gate 		/* make the source file list */
408*7c478bd9Sstevel@tonic-gate 		srcfiles = mymalloc(msrcfiles * sizeof (char *));
409*7c478bd9Sstevel@tonic-gate 		makefilelist();
410*7c478bd9Sstevel@tonic-gate 		if (nsrcfiles == 0) {
411*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
412*7c478bd9Sstevel@tonic-gate 			    "cscope: no source files found\n");
413*7c478bd9Sstevel@tonic-gate 			printusage();
414*7c478bd9Sstevel@tonic-gate 			exit(1);
415*7c478bd9Sstevel@tonic-gate 		}
416*7c478bd9Sstevel@tonic-gate 		/* get include directories from the environment */
417*7c478bd9Sstevel@tonic-gate 		if ((s = getenv("INCLUDEDIRS")) != NULL) {
418*7c478bd9Sstevel@tonic-gate 			includedir(s);
419*7c478bd9Sstevel@tonic-gate 		}
420*7c478bd9Sstevel@tonic-gate 		/* add /usr/include to the #include directory list */
421*7c478bd9Sstevel@tonic-gate 		includedir("/usr/include");
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate 		/* initialize the C keyword table */
424*7c478bd9Sstevel@tonic-gate 		initsymtab();
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 		/* create the file name(s) used for a new cross-reference */
427*7c478bd9Sstevel@tonic-gate 		(void) strcpy(path, reffile);
428*7c478bd9Sstevel@tonic-gate 		s = basename(path);
429*7c478bd9Sstevel@tonic-gate 		*s = '\0';
430*7c478bd9Sstevel@tonic-gate 		(void) strcat(path, "n");
431*7c478bd9Sstevel@tonic-gate 		++s;
432*7c478bd9Sstevel@tonic-gate 		(void) strcpy(s, basename(reffile));
433*7c478bd9Sstevel@tonic-gate 		newreffile = stralloc(path);
434*7c478bd9Sstevel@tonic-gate 		(void) strcpy(s, basename(invname));
435*7c478bd9Sstevel@tonic-gate 		newinvname = stralloc(path);
436*7c478bd9Sstevel@tonic-gate 		(void) strcpy(s, basename(invpost));
437*7c478bd9Sstevel@tonic-gate 		newinvpost = stralloc(path);
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate 		/* build the cross-reference */
440*7c478bd9Sstevel@tonic-gate 		initcompress();
441*7c478bd9Sstevel@tonic-gate 		build();
442*7c478bd9Sstevel@tonic-gate 		if (buildonly == YES) {
443*7c478bd9Sstevel@tonic-gate 			exit(0);
444*7c478bd9Sstevel@tonic-gate 		}
445*7c478bd9Sstevel@tonic-gate 	}
446*7c478bd9Sstevel@tonic-gate 	opendatabase();
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 	/*
449*7c478bd9Sstevel@tonic-gate 	 * removing a database will not release the disk space if a cscope
450*7c478bd9Sstevel@tonic-gate 	 * process has the file open, so a project may want unattended cscope
451*7c478bd9Sstevel@tonic-gate 	 * processes to exit overnight, including their subshells and editors
452*7c478bd9Sstevel@tonic-gate 	 */
453*7c478bd9Sstevel@tonic-gate 	if (noacttime) {
454*7c478bd9Sstevel@tonic-gate 		(void) signal(SIGALRM, timedout);
455*7c478bd9Sstevel@tonic-gate 		(void) alarm(noacttime);
456*7c478bd9Sstevel@tonic-gate 	}
457*7c478bd9Sstevel@tonic-gate 	/*
458*7c478bd9Sstevel@tonic-gate 	 * if using the line oriented user interface so cscope can be a
459*7c478bd9Sstevel@tonic-gate 	 * subprocess to emacs or samuel
460*7c478bd9Sstevel@tonic-gate 	 */
461*7c478bd9Sstevel@tonic-gate 	if (linemode == YES) {
462*7c478bd9Sstevel@tonic-gate 		if (*pattern != '\0') {		/* do any optional search */
463*7c478bd9Sstevel@tonic-gate 			if (search() == YES) {
464*7c478bd9Sstevel@tonic-gate 				while ((c = getc(refsfound)) != EOF) {
465*7c478bd9Sstevel@tonic-gate 					(void) putchar(c);
466*7c478bd9Sstevel@tonic-gate 				}
467*7c478bd9Sstevel@tonic-gate 			}
468*7c478bd9Sstevel@tonic-gate 		}
469*7c478bd9Sstevel@tonic-gate 		if (onesearch == YES) {
470*7c478bd9Sstevel@tonic-gate 			myexit(0);
471*7c478bd9Sstevel@tonic-gate 		}
472*7c478bd9Sstevel@tonic-gate 		for (;;) {
473*7c478bd9Sstevel@tonic-gate 			char buf[PATLEN + 2];
474*7c478bd9Sstevel@tonic-gate 			if (noacttime) {
475*7c478bd9Sstevel@tonic-gate 				(void) alarm(noacttime);
476*7c478bd9Sstevel@tonic-gate 			}
477*7c478bd9Sstevel@tonic-gate 			(void) printf(">> ");
478*7c478bd9Sstevel@tonic-gate 			(void) fflush(stdout);
479*7c478bd9Sstevel@tonic-gate 			if (fgets(buf, sizeof (buf), stdin) == NULL) {
480*7c478bd9Sstevel@tonic-gate 				myexit(0);
481*7c478bd9Sstevel@tonic-gate 			}
482*7c478bd9Sstevel@tonic-gate 			/* remove any trailing newline character */
483*7c478bd9Sstevel@tonic-gate 			if (*(s = buf + strlen(buf) - 1) == '\n') {
484*7c478bd9Sstevel@tonic-gate 				*s = '\0';
485*7c478bd9Sstevel@tonic-gate 			}
486*7c478bd9Sstevel@tonic-gate 			switch (*buf) {
487*7c478bd9Sstevel@tonic-gate 			case '0':
488*7c478bd9Sstevel@tonic-gate 			case '1':
489*7c478bd9Sstevel@tonic-gate 			case '2':
490*7c478bd9Sstevel@tonic-gate 			case '3':
491*7c478bd9Sstevel@tonic-gate 			case '4':
492*7c478bd9Sstevel@tonic-gate 			case '5':
493*7c478bd9Sstevel@tonic-gate 			case '6':
494*7c478bd9Sstevel@tonic-gate 			case '7':
495*7c478bd9Sstevel@tonic-gate 			case '8':
496*7c478bd9Sstevel@tonic-gate 			case '9':	/* samuel only */
497*7c478bd9Sstevel@tonic-gate 				field = *buf - '0';
498*7c478bd9Sstevel@tonic-gate 				(void) strcpy(pattern, buf + 1);
499*7c478bd9Sstevel@tonic-gate 				(void) search();
500*7c478bd9Sstevel@tonic-gate 				(void) printf("cscope: %d lines\n", totallines);
501*7c478bd9Sstevel@tonic-gate 				while ((c = getc(refsfound)) != EOF) {
502*7c478bd9Sstevel@tonic-gate 					(void) putchar(c);
503*7c478bd9Sstevel@tonic-gate 				}
504*7c478bd9Sstevel@tonic-gate 				break;
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate 			case 'c':	/* toggle caseless mode */
507*7c478bd9Sstevel@tonic-gate 			case ctrl('C'):
508*7c478bd9Sstevel@tonic-gate 				if (caseless == NO) {
509*7c478bd9Sstevel@tonic-gate 					caseless = YES;
510*7c478bd9Sstevel@tonic-gate 				} else {
511*7c478bd9Sstevel@tonic-gate 					caseless = NO;
512*7c478bd9Sstevel@tonic-gate 				}
513*7c478bd9Sstevel@tonic-gate 				egrepcaseless(caseless);
514*7c478bd9Sstevel@tonic-gate 				break;
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 			case 'r':	/* rebuild database cscope style */
517*7c478bd9Sstevel@tonic-gate 			case ctrl('R'):
518*7c478bd9Sstevel@tonic-gate 				freefilelist();
519*7c478bd9Sstevel@tonic-gate 				makefilelist();
520*7c478bd9Sstevel@tonic-gate 				/* FALLTHROUGH */
521*7c478bd9Sstevel@tonic-gate 
522*7c478bd9Sstevel@tonic-gate 			case 'R':	/* rebuild database samuel style */
523*7c478bd9Sstevel@tonic-gate 				rebuild();
524*7c478bd9Sstevel@tonic-gate 				(void) putchar('\n');
525*7c478bd9Sstevel@tonic-gate 				break;
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate 			case 'C':	/* clear file names */
528*7c478bd9Sstevel@tonic-gate 				freefilelist();
529*7c478bd9Sstevel@tonic-gate 				(void) putchar('\n');
530*7c478bd9Sstevel@tonic-gate 				break;
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 			case 'F':	/* add a file name */
533*7c478bd9Sstevel@tonic-gate 				(void) strcpy(path, buf + 1);
534*7c478bd9Sstevel@tonic-gate 				if (infilelist(path) == NO &&
535*7c478bd9Sstevel@tonic-gate 				    vpaccess(path, READ) == 0) {
536*7c478bd9Sstevel@tonic-gate 					addsrcfile(path);
537*7c478bd9Sstevel@tonic-gate 				}
538*7c478bd9Sstevel@tonic-gate 				(void) putchar('\n');
539*7c478bd9Sstevel@tonic-gate 				break;
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate 			case 'P':	/* print the path to the files */
542*7c478bd9Sstevel@tonic-gate 				if (prependpath != NULL) {
543*7c478bd9Sstevel@tonic-gate 					(void) puts(prependpath);
544*7c478bd9Sstevel@tonic-gate 				} else {
545*7c478bd9Sstevel@tonic-gate 					(void) puts(currentdir);
546*7c478bd9Sstevel@tonic-gate 				}
547*7c478bd9Sstevel@tonic-gate 				break;
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 			case 'q':	/* quit */
550*7c478bd9Sstevel@tonic-gate 			case ctrl('D'):
551*7c478bd9Sstevel@tonic-gate 			case ctrl('Z'):
552*7c478bd9Sstevel@tonic-gate 				myexit(0);
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate 			default:
555*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
556*7c478bd9Sstevel@tonic-gate 				    "cscope: unknown command '%s'\n", buf);
557*7c478bd9Sstevel@tonic-gate 				break;
558*7c478bd9Sstevel@tonic-gate 			}
559*7c478bd9Sstevel@tonic-gate 		}
560*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
561*7c478bd9Sstevel@tonic-gate 	}
562*7c478bd9Sstevel@tonic-gate 	/* pause before clearing the screen if there have been error messages */
563*7c478bd9Sstevel@tonic-gate 	if (errorsfound == YES) {
564*7c478bd9Sstevel@tonic-gate 		errorsfound = NO;
565*7c478bd9Sstevel@tonic-gate 		askforreturn();
566*7c478bd9Sstevel@tonic-gate 	}
567*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGINT, SIG_IGN);	/* ignore interrupts */
568*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGPIPE, SIG_IGN); /* | command can cause pipe signal */
569*7c478bd9Sstevel@tonic-gate 	/* initialize the curses display package */
570*7c478bd9Sstevel@tonic-gate 	(void) initscr();	/* initialize the screen */
571*7c478bd9Sstevel@tonic-gate 	setfield();	/* set the initial cursor position */
572*7c478bd9Sstevel@tonic-gate 	entercurses();
573*7c478bd9Sstevel@tonic-gate 	(void) keypad(stdscr, TRUE);	/* enable the keypad */
574*7c478bd9Sstevel@tonic-gate 	dispinit();	/* initialize display parameters */
575*7c478bd9Sstevel@tonic-gate 	putmsg("");	/* clear any build progress message */
576*7c478bd9Sstevel@tonic-gate 	display();	/* display the version number and input fields */
577*7c478bd9Sstevel@tonic-gate 
578*7c478bd9Sstevel@tonic-gate 	/* do any optional search */
579*7c478bd9Sstevel@tonic-gate 	if (*pattern != '\0') {
580*7c478bd9Sstevel@tonic-gate 		atfield();		/* move to the input field */
581*7c478bd9Sstevel@tonic-gate 		(void) command(ctrl('A'));	/* search */
582*7c478bd9Sstevel@tonic-gate 		display();		/* update the display */
583*7c478bd9Sstevel@tonic-gate 	} else if (reflines != NULL) {
584*7c478bd9Sstevel@tonic-gate 		/* read any symbol reference lines file */
585*7c478bd9Sstevel@tonic-gate 		(void) readrefs(reflines);
586*7c478bd9Sstevel@tonic-gate 		display();		/* update the display */
587*7c478bd9Sstevel@tonic-gate 	}
588*7c478bd9Sstevel@tonic-gate 	for (;;) {
589*7c478bd9Sstevel@tonic-gate 		if (noacttime) {
590*7c478bd9Sstevel@tonic-gate 			(void) alarm(noacttime);
591*7c478bd9Sstevel@tonic-gate 		}
592*7c478bd9Sstevel@tonic-gate 		atfield();	/* move to the input field */
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 		/* exit if the quit command is entered */
595*7c478bd9Sstevel@tonic-gate 		if ((c = mygetch()) == EOF || c == ctrl('D') ||
596*7c478bd9Sstevel@tonic-gate 		    c == ctrl('Z')) {
597*7c478bd9Sstevel@tonic-gate 			break;
598*7c478bd9Sstevel@tonic-gate 		}
599*7c478bd9Sstevel@tonic-gate 		/* execute the commmand, updating the display if necessary */
600*7c478bd9Sstevel@tonic-gate 		if (command(c) == YES) {
601*7c478bd9Sstevel@tonic-gate 			display();
602*7c478bd9Sstevel@tonic-gate 		}
603*7c478bd9Sstevel@tonic-gate 	}
604*7c478bd9Sstevel@tonic-gate 	/* cleanup and exit */
605*7c478bd9Sstevel@tonic-gate 	myexit(0);
606*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
607*7c478bd9Sstevel@tonic-gate 	return (0);
608*7c478bd9Sstevel@tonic-gate }
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate static void
options(int argc,char ** argv)611*7c478bd9Sstevel@tonic-gate options(int argc, char **argv)
612*7c478bd9Sstevel@tonic-gate {
613*7c478bd9Sstevel@tonic-gate 	char	path[PATHLEN + 1];	/* file path */
614*7c478bd9Sstevel@tonic-gate 	int	c;
615*7c478bd9Sstevel@tonic-gate 	char	*s;
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 	while (--argc > 0 && (*++argv)[0] == '-') {
618*7c478bd9Sstevel@tonic-gate 		for (s = argv[0] + 1; *s != '\0'; s++) {
619*7c478bd9Sstevel@tonic-gate 			/* look for an input field number */
620*7c478bd9Sstevel@tonic-gate 			if (isdigit(*s)) {
621*7c478bd9Sstevel@tonic-gate 				field = *s - '0';
622*7c478bd9Sstevel@tonic-gate 				if (*++s == '\0' && --argc > 0) {
623*7c478bd9Sstevel@tonic-gate 					s = *++argv;
624*7c478bd9Sstevel@tonic-gate 				}
625*7c478bd9Sstevel@tonic-gate 				if (strlen(s) > PATLEN) {
626*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
627*7c478bd9Sstevel@tonic-gate 					    "cscope: pattern too long, cannot "
628*7c478bd9Sstevel@tonic-gate 					    "be > %d characters\n", PATLEN);
629*7c478bd9Sstevel@tonic-gate 					exit(1);
630*7c478bd9Sstevel@tonic-gate 				}
631*7c478bd9Sstevel@tonic-gate 				(void) strcpy(pattern, s);
632*7c478bd9Sstevel@tonic-gate 				goto nextarg;
633*7c478bd9Sstevel@tonic-gate 			}
634*7c478bd9Sstevel@tonic-gate 			switch (*s) {
635*7c478bd9Sstevel@tonic-gate 			case '-':	/* end of options */
636*7c478bd9Sstevel@tonic-gate 				--argc;
637*7c478bd9Sstevel@tonic-gate 				++argv;
638*7c478bd9Sstevel@tonic-gate 				goto lastarg;
639*7c478bd9Sstevel@tonic-gate 			case 'V':	/* print the version number */
640*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
641*7c478bd9Sstevel@tonic-gate 				    "%s: version %d%s\n", argv0,
642*7c478bd9Sstevel@tonic-gate 				    FILEVERSION, FIXVERSION);
643*7c478bd9Sstevel@tonic-gate 				exit(0);
644*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
645*7c478bd9Sstevel@tonic-gate 			case 'b':	/* only build the cross-reference */
646*7c478bd9Sstevel@tonic-gate 				buildonly = YES;
647*7c478bd9Sstevel@tonic-gate 				break;
648*7c478bd9Sstevel@tonic-gate 			case 'c':	/* ASCII characters only in crossref */
649*7c478bd9Sstevel@tonic-gate 				compress = NO;
650*7c478bd9Sstevel@tonic-gate 				break;
651*7c478bd9Sstevel@tonic-gate 			case 'C':
652*7c478bd9Sstevel@tonic-gate 				/* turn on caseless mode for symbol searches */
653*7c478bd9Sstevel@tonic-gate 				caseless = YES;
654*7c478bd9Sstevel@tonic-gate 				/* simulate egrep -i flag */
655*7c478bd9Sstevel@tonic-gate 				egrepcaseless(caseless);
656*7c478bd9Sstevel@tonic-gate 				break;
657*7c478bd9Sstevel@tonic-gate 			case 'd':	/* consider crossref up-to-date */
658*7c478bd9Sstevel@tonic-gate 				isuptodate = YES;
659*7c478bd9Sstevel@tonic-gate 				break;
660*7c478bd9Sstevel@tonic-gate 			case 'e':	/* suppress ^E prompt between files */
661*7c478bd9Sstevel@tonic-gate 				editallprompt = NO;
662*7c478bd9Sstevel@tonic-gate 				break;
663*7c478bd9Sstevel@tonic-gate 			case 'L':
664*7c478bd9Sstevel@tonic-gate 				onesearch = YES;
665*7c478bd9Sstevel@tonic-gate 				/* FALLTHROUGH */
666*7c478bd9Sstevel@tonic-gate 			case 'l':
667*7c478bd9Sstevel@tonic-gate 				linemode = YES;
668*7c478bd9Sstevel@tonic-gate 				break;
669*7c478bd9Sstevel@tonic-gate 			case 'o':
670*7c478bd9Sstevel@tonic-gate 				/* display OGS book and subsystem names */
671*7c478bd9Sstevel@tonic-gate 				ogs = YES;
672*7c478bd9Sstevel@tonic-gate 				break;
673*7c478bd9Sstevel@tonic-gate 			case 'q':	/* quick search */
674*7c478bd9Sstevel@tonic-gate 				invertedindex = YES;
675*7c478bd9Sstevel@tonic-gate 				break;
676*7c478bd9Sstevel@tonic-gate 			case 'r':	/* display as many lines as possible */
677*7c478bd9Sstevel@tonic-gate 				returnrequired = YES;
678*7c478bd9Sstevel@tonic-gate 				break;
679*7c478bd9Sstevel@tonic-gate 			case 'T':	/* truncate symbols to 8 characters */
680*7c478bd9Sstevel@tonic-gate 				truncatesyms = YES;
681*7c478bd9Sstevel@tonic-gate 				break;
682*7c478bd9Sstevel@tonic-gate 			case 'u':
683*7c478bd9Sstevel@tonic-gate 				/* unconditionally build the cross-reference */
684*7c478bd9Sstevel@tonic-gate 				unconditional = YES;
685*7c478bd9Sstevel@tonic-gate 				break;
686*7c478bd9Sstevel@tonic-gate 			case 'U':	/* assume some files have changed */
687*7c478bd9Sstevel@tonic-gate 				fileschanged = YES;
688*7c478bd9Sstevel@tonic-gate 				break;
689*7c478bd9Sstevel@tonic-gate 			case 'f':	/* alternate cross-reference file */
690*7c478bd9Sstevel@tonic-gate 			case 'F':	/* symbol reference lines file */
691*7c478bd9Sstevel@tonic-gate 			case 'i':	/* file containing file names */
692*7c478bd9Sstevel@tonic-gate 			case 'I':	/* #include file directory */
693*7c478bd9Sstevel@tonic-gate 			case 'p':	/* file path components to display */
694*7c478bd9Sstevel@tonic-gate 			case 'P':	/* prepend path to file names */
695*7c478bd9Sstevel@tonic-gate 			case 's':	/* additional source file directory */
696*7c478bd9Sstevel@tonic-gate 			case 'S':
697*7c478bd9Sstevel@tonic-gate 			case 't':	/* no activity timeout in hours */
698*7c478bd9Sstevel@tonic-gate 				c = *s;
699*7c478bd9Sstevel@tonic-gate 				if (*++s == '\0' && --argc > 0) {
700*7c478bd9Sstevel@tonic-gate 					s = *++argv;
701*7c478bd9Sstevel@tonic-gate 				}
702*7c478bd9Sstevel@tonic-gate 				if (*s == '\0') {
703*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
704*7c478bd9Sstevel@tonic-gate 					    "%s: -%c option: missing or empty "
705*7c478bd9Sstevel@tonic-gate 					    "value\n", argv0, c);
706*7c478bd9Sstevel@tonic-gate 					goto usage;
707*7c478bd9Sstevel@tonic-gate 				}
708*7c478bd9Sstevel@tonic-gate 				switch (c) {
709*7c478bd9Sstevel@tonic-gate 				case 'f':
710*7c478bd9Sstevel@tonic-gate 					/* alternate cross-reference file */
711*7c478bd9Sstevel@tonic-gate 					reffile = s;
712*7c478bd9Sstevel@tonic-gate 					(void) strcpy(path, s);
713*7c478bd9Sstevel@tonic-gate 					/* System V has a 14 character limit */
714*7c478bd9Sstevel@tonic-gate 					s = basename(path);
715*7c478bd9Sstevel@tonic-gate 					if ((int)strlen(s) > 11) {
716*7c478bd9Sstevel@tonic-gate 						s[11] = '\0';
717*7c478bd9Sstevel@tonic-gate 					}
718*7c478bd9Sstevel@tonic-gate 					s = path + strlen(path);
719*7c478bd9Sstevel@tonic-gate 					(void) strcpy(s, ".in");
720*7c478bd9Sstevel@tonic-gate 					invname = stralloc(path);
721*7c478bd9Sstevel@tonic-gate 					(void) strcpy(s, ".po");
722*7c478bd9Sstevel@tonic-gate 					invpost = stralloc(path);
723*7c478bd9Sstevel@tonic-gate 					break;
724*7c478bd9Sstevel@tonic-gate 				case 'F':
725*7c478bd9Sstevel@tonic-gate 					/* symbol reference lines file */
726*7c478bd9Sstevel@tonic-gate 					reflines = s;
727*7c478bd9Sstevel@tonic-gate 					break;
728*7c478bd9Sstevel@tonic-gate 				case 'i':	/* file containing file names */
729*7c478bd9Sstevel@tonic-gate 					namefile = s;
730*7c478bd9Sstevel@tonic-gate 					break;
731*7c478bd9Sstevel@tonic-gate 				case 'I':	/* #include file directory */
732*7c478bd9Sstevel@tonic-gate 					includedir(s);
733*7c478bd9Sstevel@tonic-gate 					break;
734*7c478bd9Sstevel@tonic-gate 				case 'p':
735*7c478bd9Sstevel@tonic-gate 					/* file path components to display */
736*7c478bd9Sstevel@tonic-gate 					if (*s < '0' || *s > '9') {
737*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
738*7c478bd9Sstevel@tonic-gate 						    "%s: -p option: missing "
739*7c478bd9Sstevel@tonic-gate 						    "or invalid numeric "
740*7c478bd9Sstevel@tonic-gate 						    "value\n", argv0);
741*7c478bd9Sstevel@tonic-gate 						goto usage;
742*7c478bd9Sstevel@tonic-gate 					}
743*7c478bd9Sstevel@tonic-gate 					dispcomponents = atoi(s);
744*7c478bd9Sstevel@tonic-gate 					break;
745*7c478bd9Sstevel@tonic-gate 				case 'P':	/* prepend path to file names */
746*7c478bd9Sstevel@tonic-gate 					prependpath = s;
747*7c478bd9Sstevel@tonic-gate 					break;
748*7c478bd9Sstevel@tonic-gate 				case 's':
749*7c478bd9Sstevel@tonic-gate 				case 'S':
750*7c478bd9Sstevel@tonic-gate 					/* additional source directory */
751*7c478bd9Sstevel@tonic-gate 					sourcedir(s);
752*7c478bd9Sstevel@tonic-gate 					break;
753*7c478bd9Sstevel@tonic-gate 				case 't':
754*7c478bd9Sstevel@tonic-gate 					/* no activity timeout in hours */
755*7c478bd9Sstevel@tonic-gate 					if (*s < '1' || *s > '9') {
756*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
757*7c478bd9Sstevel@tonic-gate 						    "%s: -t option: missing or "
758*7c478bd9Sstevel@tonic-gate 						    "invalid numeric value\n",
759*7c478bd9Sstevel@tonic-gate 						    argv0);
760*7c478bd9Sstevel@tonic-gate 						goto usage;
761*7c478bd9Sstevel@tonic-gate 					}
762*7c478bd9Sstevel@tonic-gate 					c = atoi(s);
763*7c478bd9Sstevel@tonic-gate 					if (c < MINHOURS) {
764*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
765*7c478bd9Sstevel@tonic-gate 						    "cscope: minimum timeout "
766*7c478bd9Sstevel@tonic-gate 						    "is %d hours\n", MINHOURS);
767*7c478bd9Sstevel@tonic-gate 						(void) sleep(3);
768*7c478bd9Sstevel@tonic-gate 						c = MINHOURS;
769*7c478bd9Sstevel@tonic-gate 					}
770*7c478bd9Sstevel@tonic-gate 					noacttime = c * 3600;
771*7c478bd9Sstevel@tonic-gate 					break;
772*7c478bd9Sstevel@tonic-gate 				}
773*7c478bd9Sstevel@tonic-gate 				goto nextarg;
774*7c478bd9Sstevel@tonic-gate 			default:
775*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
776*7c478bd9Sstevel@tonic-gate 				    "%s: unknown option: -%c\n", argv0, *s);
777*7c478bd9Sstevel@tonic-gate 			usage:
778*7c478bd9Sstevel@tonic-gate 				printusage();
779*7c478bd9Sstevel@tonic-gate 				exit(1);
780*7c478bd9Sstevel@tonic-gate 			}
781*7c478bd9Sstevel@tonic-gate 		}
782*7c478bd9Sstevel@tonic-gate nextarg:	continue;
783*7c478bd9Sstevel@tonic-gate 	}
784*7c478bd9Sstevel@tonic-gate lastarg:
785*7c478bd9Sstevel@tonic-gate 	/* save the file arguments */
786*7c478bd9Sstevel@tonic-gate 	fileargc = argc;
787*7c478bd9Sstevel@tonic-gate 	fileargv = argv;
788*7c478bd9Sstevel@tonic-gate }
789*7c478bd9Sstevel@tonic-gate 
790*7c478bd9Sstevel@tonic-gate static void
printusage(void)791*7c478bd9Sstevel@tonic-gate printusage(void)
792*7c478bd9Sstevel@tonic-gate {
793*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
794*7c478bd9Sstevel@tonic-gate 	    "Usage:  cscope [-bcdelLoqrtTuUV] [-f file] [-F file] [-i file] "
795*7c478bd9Sstevel@tonic-gate 	    "[-I dir] [-s dir]\n");
796*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
797*7c478bd9Sstevel@tonic-gate 	    "               [-p number] [-P path] [-[0-8] pattern] "
798*7c478bd9Sstevel@tonic-gate 	    "[source files]\n");
799*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
800*7c478bd9Sstevel@tonic-gate 	    "-b		Build the database only.\n");
801*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
802*7c478bd9Sstevel@tonic-gate 	    "-c		Use only ASCII characters in the database file, "
803*7c478bd9Sstevel@tonic-gate 	    "that is,\n");
804*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
805*7c478bd9Sstevel@tonic-gate 	    "		do not compress the data.\n");
806*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
807*7c478bd9Sstevel@tonic-gate 	    "-d		Do not update the database.\n");
808*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
809*7c478bd9Sstevel@tonic-gate 	    "-f \"file\"	Use \"file\" as the database file name "
810*7c478bd9Sstevel@tonic-gate 	    "instead of\n");
811*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
812*7c478bd9Sstevel@tonic-gate 	    "		the default (cscope.out).\n");
813*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
814*7c478bd9Sstevel@tonic-gate 	    "-F \"file\"	Read symbol reference lines from file, just\n");
815*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */
816*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
817*7c478bd9Sstevel@tonic-gate 	    "		like the \"<\" command.\n");
818*7c478bd9Sstevel@tonic-gate /* END CSTYLED */
819*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
820*7c478bd9Sstevel@tonic-gate 	    "-i \"file\"	Read any -I, -p, -q, and -T options and the\n");
821*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
822*7c478bd9Sstevel@tonic-gate 	    "		list of source files from \"file\" instead of the \n");
823*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
824*7c478bd9Sstevel@tonic-gate 	    "		default (cscope.files).\n");
825*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
826*7c478bd9Sstevel@tonic-gate 	    "-I \"dir\"	Look in \"dir\" for #include files.\n");
827*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
828*7c478bd9Sstevel@tonic-gate 	    "-q		Build an inverted index for quick symbol seaching.\n");
829*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
830*7c478bd9Sstevel@tonic-gate 	    "-s \"dir\"	Look in \"dir\" for additional source files.\n");
831*7c478bd9Sstevel@tonic-gate }
832*7c478bd9Sstevel@tonic-gate 
833*7c478bd9Sstevel@tonic-gate static void
removeindex(void)834*7c478bd9Sstevel@tonic-gate removeindex(void)
835*7c478bd9Sstevel@tonic-gate {
836*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
837*7c478bd9Sstevel@tonic-gate 	    "cscope: removed files %s and %s\n", invname, invpost);
838*7c478bd9Sstevel@tonic-gate 	(void) unlink(invname);
839*7c478bd9Sstevel@tonic-gate 	(void) unlink(invpost);
840*7c478bd9Sstevel@tonic-gate }
841*7c478bd9Sstevel@tonic-gate 
842*7c478bd9Sstevel@tonic-gate static void
cannotindex(void)843*7c478bd9Sstevel@tonic-gate cannotindex(void)
844*7c478bd9Sstevel@tonic-gate {
845*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
846*7c478bd9Sstevel@tonic-gate 	    "cscope: cannot create inverted index; ignoring -q option\n");
847*7c478bd9Sstevel@tonic-gate 	invertedindex = NO;
848*7c478bd9Sstevel@tonic-gate 	errorsfound = YES;
849*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
850*7c478bd9Sstevel@tonic-gate 	    "cscope: removed files %s and %s\n", newinvname, newinvpost);
851*7c478bd9Sstevel@tonic-gate 	(void) unlink(newinvname);
852*7c478bd9Sstevel@tonic-gate 	(void) unlink(newinvpost);
853*7c478bd9Sstevel@tonic-gate 	removeindex();	/* remove any existing index to prevent confusion */
854*7c478bd9Sstevel@tonic-gate }
855*7c478bd9Sstevel@tonic-gate 
856*7c478bd9Sstevel@tonic-gate void
cannotopen(char * file)857*7c478bd9Sstevel@tonic-gate cannotopen(char *file)
858*7c478bd9Sstevel@tonic-gate {
859*7c478bd9Sstevel@tonic-gate 	char	msg[MSGLEN + 1];
860*7c478bd9Sstevel@tonic-gate 
861*7c478bd9Sstevel@tonic-gate 	(void) sprintf(msg, "Cannot open file %s", file);
862*7c478bd9Sstevel@tonic-gate 	putmsg(msg);
863*7c478bd9Sstevel@tonic-gate }
864*7c478bd9Sstevel@tonic-gate 
865*7c478bd9Sstevel@tonic-gate void
cannotwrite(char * file)866*7c478bd9Sstevel@tonic-gate cannotwrite(char *file)
867*7c478bd9Sstevel@tonic-gate {
868*7c478bd9Sstevel@tonic-gate 	char	msg[MSGLEN + 1];
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate 	(void) sprintf(msg, "Removed file %s because write failed", file);
871*7c478bd9Sstevel@tonic-gate 	myperror(msg);	/* display the reason */
872*7c478bd9Sstevel@tonic-gate 	(void) unlink(file);
873*7c478bd9Sstevel@tonic-gate 	myexit(1);	/* calls exit(2), which closes files */
874*7c478bd9Sstevel@tonic-gate }
875*7c478bd9Sstevel@tonic-gate 
876*7c478bd9Sstevel@tonic-gate /* set up the digraph character tables for text compression */
877*7c478bd9Sstevel@tonic-gate 
878*7c478bd9Sstevel@tonic-gate static void
initcompress(void)879*7c478bd9Sstevel@tonic-gate initcompress(void)
880*7c478bd9Sstevel@tonic-gate {
881*7c478bd9Sstevel@tonic-gate 	int	i;
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate 	if (compress == YES) {
884*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < 16; ++i) {
885*7c478bd9Sstevel@tonic-gate 			dicode1[(unsigned)(dichar1[i])] = i * 8 + 1;
886*7c478bd9Sstevel@tonic-gate 		}
887*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < 8; ++i) {
888*7c478bd9Sstevel@tonic-gate 			dicode2[(unsigned)(dichar2[i])] = i + 1;
889*7c478bd9Sstevel@tonic-gate 		}
890*7c478bd9Sstevel@tonic-gate 	}
891*7c478bd9Sstevel@tonic-gate }
892*7c478bd9Sstevel@tonic-gate 
893*7c478bd9Sstevel@tonic-gate /* open the database */
894*7c478bd9Sstevel@tonic-gate 
895*7c478bd9Sstevel@tonic-gate static void
opendatabase(void)896*7c478bd9Sstevel@tonic-gate opendatabase(void)
897*7c478bd9Sstevel@tonic-gate {
898*7c478bd9Sstevel@tonic-gate 	if ((symrefs = vpopen(reffile, O_RDONLY)) == -1) {
899*7c478bd9Sstevel@tonic-gate 		cannotopen(reffile);
900*7c478bd9Sstevel@tonic-gate 		myexit(1);
901*7c478bd9Sstevel@tonic-gate 	}
902*7c478bd9Sstevel@tonic-gate 	blocknumber = -1;	/* force next seek to read the first block */
903*7c478bd9Sstevel@tonic-gate 
904*7c478bd9Sstevel@tonic-gate 	/* open any inverted index */
905*7c478bd9Sstevel@tonic-gate 	if (invertedindex == YES &&
906*7c478bd9Sstevel@tonic-gate 	    invopen(&invcontrol, invname, invpost, INVAVAIL) == -1) {
907*7c478bd9Sstevel@tonic-gate 		askforreturn();		/* so user sees message */
908*7c478bd9Sstevel@tonic-gate 		invertedindex = NO;
909*7c478bd9Sstevel@tonic-gate 	}
910*7c478bd9Sstevel@tonic-gate }
911*7c478bd9Sstevel@tonic-gate 
912*7c478bd9Sstevel@tonic-gate /* close the database */
913*7c478bd9Sstevel@tonic-gate 
914*7c478bd9Sstevel@tonic-gate static void
closedatabase(void)915*7c478bd9Sstevel@tonic-gate closedatabase(void)
916*7c478bd9Sstevel@tonic-gate {
917*7c478bd9Sstevel@tonic-gate 	(void) close(symrefs);
918*7c478bd9Sstevel@tonic-gate 	if (invertedindex == YES) {
919*7c478bd9Sstevel@tonic-gate 		invclose(&invcontrol);
920*7c478bd9Sstevel@tonic-gate 		nsrcoffset = 0;
921*7c478bd9Sstevel@tonic-gate 		npostings = 0;
922*7c478bd9Sstevel@tonic-gate 	}
923*7c478bd9Sstevel@tonic-gate }
924*7c478bd9Sstevel@tonic-gate 
925*7c478bd9Sstevel@tonic-gate /* rebuild the database */
926*7c478bd9Sstevel@tonic-gate 
927*7c478bd9Sstevel@tonic-gate void
rebuild(void)928*7c478bd9Sstevel@tonic-gate rebuild(void)
929*7c478bd9Sstevel@tonic-gate {
930*7c478bd9Sstevel@tonic-gate 	closedatabase();
931*7c478bd9Sstevel@tonic-gate 	build();
932*7c478bd9Sstevel@tonic-gate 	opendatabase();
933*7c478bd9Sstevel@tonic-gate 
934*7c478bd9Sstevel@tonic-gate 	/* revert to the initial display */
935*7c478bd9Sstevel@tonic-gate 	if (refsfound != NULL) {
936*7c478bd9Sstevel@tonic-gate 		(void) fclose(refsfound);
937*7c478bd9Sstevel@tonic-gate 		refsfound = NULL;
938*7c478bd9Sstevel@tonic-gate 	}
939*7c478bd9Sstevel@tonic-gate 	*lastfilepath = '\0';	/* last file may have new path */
940*7c478bd9Sstevel@tonic-gate }
941*7c478bd9Sstevel@tonic-gate 
942*7c478bd9Sstevel@tonic-gate /* build the cross-reference */
943*7c478bd9Sstevel@tonic-gate 
944*7c478bd9Sstevel@tonic-gate static void
build(void)945*7c478bd9Sstevel@tonic-gate build(void)
946*7c478bd9Sstevel@tonic-gate {
947*7c478bd9Sstevel@tonic-gate 	int	i;
948*7c478bd9Sstevel@tonic-gate 	FILE	*oldrefs;	/* old cross-reference file */
949*7c478bd9Sstevel@tonic-gate 	time_t	reftime;	/* old crossref modification time */
950*7c478bd9Sstevel@tonic-gate 	char	*file;			/* current file */
951*7c478bd9Sstevel@tonic-gate 	char	*oldfile;		/* file in old cross-reference */
952*7c478bd9Sstevel@tonic-gate 	char	newdir[PATHLEN + 1];	/* directory in new cross-reference */
953*7c478bd9Sstevel@tonic-gate 	char	olddir[PATHLEN + 1];	/* directory in old cross-reference */
954*7c478bd9Sstevel@tonic-gate 	char	oldname[PATHLEN + 1];	/* name in old cross-reference */
955*7c478bd9Sstevel@tonic-gate 	int	oldnum;			/* number in old cross-ref */
956*7c478bd9Sstevel@tonic-gate 	struct	stat statstruct;	/* file status */
957*7c478bd9Sstevel@tonic-gate 	int	firstfile;		/* first source file in pass */
958*7c478bd9Sstevel@tonic-gate 	int	lastfile;		/* last source file in pass */
959*7c478bd9Sstevel@tonic-gate 	int	built = 0;		/* built crossref for these files */
960*7c478bd9Sstevel@tonic-gate 	int	copied = 0;		/* copied crossref for these files */
961*7c478bd9Sstevel@tonic-gate 	BOOL	interactive = YES;	/* output progress messages */
962*7c478bd9Sstevel@tonic-gate 
963*7c478bd9Sstevel@tonic-gate 	/*
964*7c478bd9Sstevel@tonic-gate 	 * normalize the current directory relative to the home directory so
965*7c478bd9Sstevel@tonic-gate 	 * the cross-reference is not rebuilt when the user's login is moved
966*7c478bd9Sstevel@tonic-gate 	 */
967*7c478bd9Sstevel@tonic-gate 	(void) strcpy(newdir, currentdir);
968*7c478bd9Sstevel@tonic-gate 	if (strcmp(currentdir, home) == 0) {
969*7c478bd9Sstevel@tonic-gate 		(void) strcpy(newdir, "$HOME");
970*7c478bd9Sstevel@tonic-gate 	} else if (strncmp(currentdir, home, strlen(home)) == 0) {
971*7c478bd9Sstevel@tonic-gate 		(void) sprintf(newdir, "$HOME%s", currentdir + strlen(home));
972*7c478bd9Sstevel@tonic-gate 	}
973*7c478bd9Sstevel@tonic-gate 	/* sort the source file names (needed for rebuilding) */
974*7c478bd9Sstevel@tonic-gate 	qsort((char *)srcfiles, (unsigned)nsrcfiles, sizeof (char *), compare);
975*7c478bd9Sstevel@tonic-gate 
976*7c478bd9Sstevel@tonic-gate 	/*
977*7c478bd9Sstevel@tonic-gate 	 * if there is an old cross-reference and its current directory
978*7c478bd9Sstevel@tonic-gate 	 * matches or this is an unconditional build
979*7c478bd9Sstevel@tonic-gate 	 */
980*7c478bd9Sstevel@tonic-gate 	if ((oldrefs = vpfopen(reffile, "r")) != NULL && unconditional == NO &&
981*7c478bd9Sstevel@tonic-gate 	    fscanf(oldrefs, "cscope %d %s", &fileversion, olddir) == 2 &&
982*7c478bd9Sstevel@tonic-gate 	    (strcmp(olddir, currentdir) == 0 || /* remain compatible */
983*7c478bd9Sstevel@tonic-gate 	    strcmp(olddir, newdir) == 0)) {
984*7c478bd9Sstevel@tonic-gate 
985*7c478bd9Sstevel@tonic-gate 		/* get the cross-reference file's modification time */
986*7c478bd9Sstevel@tonic-gate 		(void) fstat(fileno(oldrefs), &statstruct);
987*7c478bd9Sstevel@tonic-gate 		reftime = statstruct.st_mtime;
988*7c478bd9Sstevel@tonic-gate 		if (fileversion >= 8) {
989*7c478bd9Sstevel@tonic-gate 			BOOL	oldcompress = YES;
990*7c478bd9Sstevel@tonic-gate 			BOOL	oldinvertedindex = NO;
991*7c478bd9Sstevel@tonic-gate 			BOOL	oldtruncatesyms = NO;
992*7c478bd9Sstevel@tonic-gate 			int	c;
993*7c478bd9Sstevel@tonic-gate 
994*7c478bd9Sstevel@tonic-gate 			/* see if there are options in the database */
995*7c478bd9Sstevel@tonic-gate 			for (;;) {
996*7c478bd9Sstevel@tonic-gate 				while ((c = getc(oldrefs)) == ' ') {
997*7c478bd9Sstevel@tonic-gate 				}
998*7c478bd9Sstevel@tonic-gate 				if (c != '-') {
999*7c478bd9Sstevel@tonic-gate 					(void) ungetc(c, oldrefs);
1000*7c478bd9Sstevel@tonic-gate 					break;
1001*7c478bd9Sstevel@tonic-gate 				}
1002*7c478bd9Sstevel@tonic-gate 				switch (c = getc(oldrefs)) {
1003*7c478bd9Sstevel@tonic-gate 				case 'c':	/* ASCII characters only */
1004*7c478bd9Sstevel@tonic-gate 					oldcompress = NO;
1005*7c478bd9Sstevel@tonic-gate 					break;
1006*7c478bd9Sstevel@tonic-gate 				case 'q':	/* quick search */
1007*7c478bd9Sstevel@tonic-gate 					oldinvertedindex = YES;
1008*7c478bd9Sstevel@tonic-gate 					(void) fscanf(oldrefs,
1009*7c478bd9Sstevel@tonic-gate 					    "%ld", &totalterms);
1010*7c478bd9Sstevel@tonic-gate 					break;
1011*7c478bd9Sstevel@tonic-gate 				case 'T':
1012*7c478bd9Sstevel@tonic-gate 					/* truncate symbols to 8 characters */
1013*7c478bd9Sstevel@tonic-gate 					oldtruncatesyms = YES;
1014*7c478bd9Sstevel@tonic-gate 					break;
1015*7c478bd9Sstevel@tonic-gate 				}
1016*7c478bd9Sstevel@tonic-gate 			}
1017*7c478bd9Sstevel@tonic-gate 			/* check the old and new option settings */
1018*7c478bd9Sstevel@tonic-gate 			if (oldcompress != compress ||
1019*7c478bd9Sstevel@tonic-gate 			    oldtruncatesyms != truncatesyms) {
1020*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1021*7c478bd9Sstevel@tonic-gate 				    "cscope: -c or -T option mismatch between "
1022*7c478bd9Sstevel@tonic-gate 				    "command line and old symbol database\n");
1023*7c478bd9Sstevel@tonic-gate 				goto force;
1024*7c478bd9Sstevel@tonic-gate 			}
1025*7c478bd9Sstevel@tonic-gate 			if (oldinvertedindex != invertedindex) {
1026*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1027*7c478bd9Sstevel@tonic-gate 				    "cscope: -q option mismatch between "
1028*7c478bd9Sstevel@tonic-gate 				    "command line and old symbol database\n");
1029*7c478bd9Sstevel@tonic-gate 				if (invertedindex == NO) {
1030*7c478bd9Sstevel@tonic-gate 					removeindex();
1031*7c478bd9Sstevel@tonic-gate 				}
1032*7c478bd9Sstevel@tonic-gate 				goto outofdate;
1033*7c478bd9Sstevel@tonic-gate 			}
1034*7c478bd9Sstevel@tonic-gate 			/* seek to the trailer */
1035*7c478bd9Sstevel@tonic-gate 			if (fscanf(oldrefs, "%ld", &traileroffset) != 1 ||
1036*7c478bd9Sstevel@tonic-gate 			    fseek(oldrefs, traileroffset, 0) == -1) {
1037*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1038*7c478bd9Sstevel@tonic-gate 				    "cscope: incorrect symbol database file "
1039*7c478bd9Sstevel@tonic-gate 				    "format\n");
1040*7c478bd9Sstevel@tonic-gate 				goto force;
1041*7c478bd9Sstevel@tonic-gate 			}
1042*7c478bd9Sstevel@tonic-gate 		}
1043*7c478bd9Sstevel@tonic-gate 		/* if assuming that some files have changed */
1044*7c478bd9Sstevel@tonic-gate 		if (fileschanged == YES) {
1045*7c478bd9Sstevel@tonic-gate 			goto outofdate;
1046*7c478bd9Sstevel@tonic-gate 		}
1047*7c478bd9Sstevel@tonic-gate 		/* see if the view path is the same */
1048*7c478bd9Sstevel@tonic-gate 		if (fileversion >= 13 &&
1049*7c478bd9Sstevel@tonic-gate 		    samelist(oldrefs, vpdirs, vpndirs) == NO) {
1050*7c478bd9Sstevel@tonic-gate 			goto outofdate;
1051*7c478bd9Sstevel@tonic-gate 		}
1052*7c478bd9Sstevel@tonic-gate 		/* see if the directory lists are the same */
1053*7c478bd9Sstevel@tonic-gate 		if (samelist(oldrefs, srcdirs, nsrcdirs) == NO ||
1054*7c478bd9Sstevel@tonic-gate 		    samelist(oldrefs, incdirs, nincdirs) == NO ||
1055*7c478bd9Sstevel@tonic-gate 		    fscanf(oldrefs, "%d", &oldnum) != 1 ||
1056*7c478bd9Sstevel@tonic-gate 		    fileversion >= 9 && fscanf(oldrefs, "%*s") != 0) {
1057*7c478bd9Sstevel@tonic-gate 			/* skip the string space size */
1058*7c478bd9Sstevel@tonic-gate 			goto outofdate;
1059*7c478bd9Sstevel@tonic-gate 		}
1060*7c478bd9Sstevel@tonic-gate 		/*
1061*7c478bd9Sstevel@tonic-gate 		 * see if the list of source files is the same and
1062*7c478bd9Sstevel@tonic-gate 		 * none have been changed up to the included files
1063*7c478bd9Sstevel@tonic-gate 		 */
1064*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < nsrcfiles; ++i) {
1065*7c478bd9Sstevel@tonic-gate 			if (fscanf(oldrefs, "%s", oldname) != 1 ||
1066*7c478bd9Sstevel@tonic-gate 			    strnotequal(oldname, srcfiles[i]) ||
1067*7c478bd9Sstevel@tonic-gate 			    vpstat(srcfiles[i], &statstruct) != 0 ||
1068*7c478bd9Sstevel@tonic-gate 			    statstruct.st_mtime > reftime) {
1069*7c478bd9Sstevel@tonic-gate 				goto outofdate;
1070*7c478bd9Sstevel@tonic-gate 			}
1071*7c478bd9Sstevel@tonic-gate 		}
1072*7c478bd9Sstevel@tonic-gate 		/* the old cross-reference is up-to-date */
1073*7c478bd9Sstevel@tonic-gate 		/* so get the list of included files */
1074*7c478bd9Sstevel@tonic-gate 		while (i++ < oldnum && fscanf(oldrefs, "%s", oldname) == 1) {
1075*7c478bd9Sstevel@tonic-gate 			addsrcfile(oldname);
1076*7c478bd9Sstevel@tonic-gate 		}
1077*7c478bd9Sstevel@tonic-gate 		(void) fclose(oldrefs);
1078*7c478bd9Sstevel@tonic-gate 		return;
1079*7c478bd9Sstevel@tonic-gate 
1080*7c478bd9Sstevel@tonic-gate outofdate:
1081*7c478bd9Sstevel@tonic-gate 		/* if the database format has changed, rebuild it all */
1082*7c478bd9Sstevel@tonic-gate 		if (fileversion != FILEVERSION) {
1083*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
1084*7c478bd9Sstevel@tonic-gate 			    "cscope: converting to new symbol database file "
1085*7c478bd9Sstevel@tonic-gate 			    "format\n");
1086*7c478bd9Sstevel@tonic-gate 			goto force;
1087*7c478bd9Sstevel@tonic-gate 		}
1088*7c478bd9Sstevel@tonic-gate 		/* reopen the old cross-reference file for fast scanning */
1089*7c478bd9Sstevel@tonic-gate 		if ((symrefs = vpopen(reffile, O_RDONLY)) == -1) {
1090*7c478bd9Sstevel@tonic-gate 			cannotopen(reffile);
1091*7c478bd9Sstevel@tonic-gate 			myexit(1);
1092*7c478bd9Sstevel@tonic-gate 		}
1093*7c478bd9Sstevel@tonic-gate 		/* get the first file name in the old cross-reference */
1094*7c478bd9Sstevel@tonic-gate 		blocknumber = -1;
1095*7c478bd9Sstevel@tonic-gate 		(void) readblock();	/* read the first cross-ref block */
1096*7c478bd9Sstevel@tonic-gate 		(void) scanpast('\t');	/* skip the header */
1097*7c478bd9Sstevel@tonic-gate 		oldfile = getoldfile();
1098*7c478bd9Sstevel@tonic-gate 	} else {	/* force cross-referencing of all the source files */
1099*7c478bd9Sstevel@tonic-gate force:
1100*7c478bd9Sstevel@tonic-gate 		reftime = 0;
1101*7c478bd9Sstevel@tonic-gate 		oldfile = NULL;
1102*7c478bd9Sstevel@tonic-gate 	}
1103*7c478bd9Sstevel@tonic-gate 	/* open the new cross-reference file */
1104*7c478bd9Sstevel@tonic-gate 	if ((newrefs = fopen(newreffile, "w")) == NULL) {
1105*7c478bd9Sstevel@tonic-gate 		cannotopen(newreffile);
1106*7c478bd9Sstevel@tonic-gate 		myexit(1);
1107*7c478bd9Sstevel@tonic-gate 	}
1108*7c478bd9Sstevel@tonic-gate 	if (invertedindex == YES && (postings = fopen(temp1, "w")) == NULL) {
1109*7c478bd9Sstevel@tonic-gate 		cannotopen(temp1);
1110*7c478bd9Sstevel@tonic-gate 		cannotindex();
1111*7c478bd9Sstevel@tonic-gate 	}
1112*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "cscope: building symbol database\n");
1113*7c478bd9Sstevel@tonic-gate 	putheader(newdir);
1114*7c478bd9Sstevel@tonic-gate 	fileversion = FILEVERSION;
1115*7c478bd9Sstevel@tonic-gate 	if (buildonly == YES && !isatty(0)) {
1116*7c478bd9Sstevel@tonic-gate 		interactive = NO;
1117*7c478bd9Sstevel@tonic-gate 	} else {
1118*7c478bd9Sstevel@tonic-gate 		initprogress();
1119*7c478bd9Sstevel@tonic-gate 	}
1120*7c478bd9Sstevel@tonic-gate 	/* output the leading tab expected by crossref() */
1121*7c478bd9Sstevel@tonic-gate 	dbputc('\t');
1122*7c478bd9Sstevel@tonic-gate 
1123*7c478bd9Sstevel@tonic-gate 	/*
1124*7c478bd9Sstevel@tonic-gate 	 * make passes through the source file list until the last level of
1125*7c478bd9Sstevel@tonic-gate 	 * included files is processed
1126*7c478bd9Sstevel@tonic-gate 	 */
1127*7c478bd9Sstevel@tonic-gate 	firstfile = 0;
1128*7c478bd9Sstevel@tonic-gate 	lastfile = nsrcfiles;
1129*7c478bd9Sstevel@tonic-gate 	if (invertedindex == YES) {
1130*7c478bd9Sstevel@tonic-gate 		srcoffset = mymalloc((nsrcfiles + 1) * sizeof (long));
1131*7c478bd9Sstevel@tonic-gate 	}
1132*7c478bd9Sstevel@tonic-gate 	for (;;) {
1133*7c478bd9Sstevel@tonic-gate 
1134*7c478bd9Sstevel@tonic-gate 		/* get the next source file name */
1135*7c478bd9Sstevel@tonic-gate 		for (fileindex = firstfile; fileindex < lastfile; ++fileindex) {
1136*7c478bd9Sstevel@tonic-gate 			/* display the progress about every three seconds */
1137*7c478bd9Sstevel@tonic-gate 			if (interactive == YES && fileindex % 10 == 0) {
1138*7c478bd9Sstevel@tonic-gate 				if (copied == 0) {
1139*7c478bd9Sstevel@tonic-gate 					progress("%ld files built",
1140*7c478bd9Sstevel@tonic-gate 					    (long)built, 0L);
1141*7c478bd9Sstevel@tonic-gate 				} else {
1142*7c478bd9Sstevel@tonic-gate 					progress("%ld files built, %ld "
1143*7c478bd9Sstevel@tonic-gate 					    "files copied", (long)built,
1144*7c478bd9Sstevel@tonic-gate 					    (long)copied);
1145*7c478bd9Sstevel@tonic-gate 				}
1146*7c478bd9Sstevel@tonic-gate 			}
1147*7c478bd9Sstevel@tonic-gate 			/* if the old file has been deleted get the next one */
1148*7c478bd9Sstevel@tonic-gate 			file = srcfiles[fileindex];
1149*7c478bd9Sstevel@tonic-gate 			while (oldfile != NULL && strcmp(file, oldfile) > 0) {
1150*7c478bd9Sstevel@tonic-gate 				oldfile = getoldfile();
1151*7c478bd9Sstevel@tonic-gate 			}
1152*7c478bd9Sstevel@tonic-gate 			/*
1153*7c478bd9Sstevel@tonic-gate 			 * if there isn't an old database or this is
1154*7c478bd9Sstevel@tonic-gate 			 * a new file
1155*7c478bd9Sstevel@tonic-gate 			 */
1156*7c478bd9Sstevel@tonic-gate 			if (oldfile == NULL || strcmp(file, oldfile) < 0) {
1157*7c478bd9Sstevel@tonic-gate 				crossref(file);
1158*7c478bd9Sstevel@tonic-gate 				++built;
1159*7c478bd9Sstevel@tonic-gate 			} else if (vpstat(file, &statstruct) == 0 &&
1160*7c478bd9Sstevel@tonic-gate 			    statstruct.st_mtime > reftime) {
1161*7c478bd9Sstevel@tonic-gate 				/* if this file was modified */
1162*7c478bd9Sstevel@tonic-gate 				crossref(file);
1163*7c478bd9Sstevel@tonic-gate 				++built;
1164*7c478bd9Sstevel@tonic-gate 
1165*7c478bd9Sstevel@tonic-gate 				/*
1166*7c478bd9Sstevel@tonic-gate 				 * skip its old crossref so modifying the last
1167*7c478bd9Sstevel@tonic-gate 				 * source file does not cause all included files
1168*7c478bd9Sstevel@tonic-gate 				 * to be built.  Unfortunately a new file that
1169*7c478bd9Sstevel@tonic-gate 				 * is alphabetically last will cause all
1170*7c478bd9Sstevel@tonic-gate 				 * included files to be built, but this is
1171*7c478bd9Sstevel@tonic-gate 				 * less likely
1172*7c478bd9Sstevel@tonic-gate 				 */
1173*7c478bd9Sstevel@tonic-gate 				oldfile = getoldfile();
1174*7c478bd9Sstevel@tonic-gate 			} else {	/* copy its cross-reference */
1175*7c478bd9Sstevel@tonic-gate 				putfilename(file);
1176*7c478bd9Sstevel@tonic-gate 				if (invertedindex == YES) {
1177*7c478bd9Sstevel@tonic-gate 					copyinverted();
1178*7c478bd9Sstevel@tonic-gate 				} else {
1179*7c478bd9Sstevel@tonic-gate 					copydata();
1180*7c478bd9Sstevel@tonic-gate 				}
1181*7c478bd9Sstevel@tonic-gate 				++copied;
1182*7c478bd9Sstevel@tonic-gate 				oldfile = getoldfile();
1183*7c478bd9Sstevel@tonic-gate 			}
1184*7c478bd9Sstevel@tonic-gate 		}
1185*7c478bd9Sstevel@tonic-gate 		/* see if any included files were found */
1186*7c478bd9Sstevel@tonic-gate 		if (lastfile == nsrcfiles) {
1187*7c478bd9Sstevel@tonic-gate 			break;
1188*7c478bd9Sstevel@tonic-gate 		}
1189*7c478bd9Sstevel@tonic-gate 		firstfile = lastfile;
1190*7c478bd9Sstevel@tonic-gate 		lastfile = nsrcfiles;
1191*7c478bd9Sstevel@tonic-gate 		if (invertedindex == YES) {
1192*7c478bd9Sstevel@tonic-gate 			srcoffset = myrealloc(srcoffset,
1193*7c478bd9Sstevel@tonic-gate 			    (nsrcfiles + 1) * sizeof (long));
1194*7c478bd9Sstevel@tonic-gate 		}
1195*7c478bd9Sstevel@tonic-gate 		/* sort the included file names */
1196*7c478bd9Sstevel@tonic-gate 		qsort((char *)&srcfiles[firstfile],
1197*7c478bd9Sstevel@tonic-gate 		    (unsigned)(lastfile - firstfile), sizeof (char *), compare);
1198*7c478bd9Sstevel@tonic-gate 	}
1199*7c478bd9Sstevel@tonic-gate 	/* add a null file name to the trailing tab */
1200*7c478bd9Sstevel@tonic-gate 	putfilename("");
1201*7c478bd9Sstevel@tonic-gate 	dbputc('\n');
1202*7c478bd9Sstevel@tonic-gate 
1203*7c478bd9Sstevel@tonic-gate 	/* get the file trailer offset */
1204*7c478bd9Sstevel@tonic-gate 
1205*7c478bd9Sstevel@tonic-gate 	traileroffset = dboffset;
1206*7c478bd9Sstevel@tonic-gate 
1207*7c478bd9Sstevel@tonic-gate 	/*
1208*7c478bd9Sstevel@tonic-gate 	 * output the view path and source and include directory and
1209*7c478bd9Sstevel@tonic-gate 	 * file lists
1210*7c478bd9Sstevel@tonic-gate 	 */
1211*7c478bd9Sstevel@tonic-gate 	putlist(vpdirs, vpndirs);
1212*7c478bd9Sstevel@tonic-gate 	putlist(srcdirs, nsrcdirs);
1213*7c478bd9Sstevel@tonic-gate 	putlist(incdirs, nincdirs);
1214*7c478bd9Sstevel@tonic-gate 	putlist(srcfiles, nsrcfiles);
1215*7c478bd9Sstevel@tonic-gate 	if (fflush(newrefs) == EOF) {
1216*7c478bd9Sstevel@tonic-gate 		/* rewind doesn't check for write failure */
1217*7c478bd9Sstevel@tonic-gate 		cannotwrite(newreffile);
1218*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
1219*7c478bd9Sstevel@tonic-gate 	}
1220*7c478bd9Sstevel@tonic-gate 	/* create the inverted index if requested */
1221*7c478bd9Sstevel@tonic-gate 	if (invertedindex == YES) {
1222*7c478bd9Sstevel@tonic-gate 		char	sortcommand[PATHLEN + 1];
1223*7c478bd9Sstevel@tonic-gate 
1224*7c478bd9Sstevel@tonic-gate 		if (fflush(postings) == EOF) {
1225*7c478bd9Sstevel@tonic-gate 			cannotwrite(temp1);
1226*7c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
1227*7c478bd9Sstevel@tonic-gate 		}
1228*7c478bd9Sstevel@tonic-gate 		(void) fstat(fileno(postings), &statstruct);
1229*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1230*7c478bd9Sstevel@tonic-gate 		    "cscope: building symbol index: temporary file size is "
1231*7c478bd9Sstevel@tonic-gate 		    "%ld bytes\n", statstruct.st_size);
1232*7c478bd9Sstevel@tonic-gate 		(void) fclose(postings);
1233*7c478bd9Sstevel@tonic-gate 	/*
1234*7c478bd9Sstevel@tonic-gate 	 * sort -T is broken until it is fixed we don't have too much choice
1235*7c478bd9Sstevel@tonic-gate 	 */
1236*7c478bd9Sstevel@tonic-gate 	/*
1237*7c478bd9Sstevel@tonic-gate 	 * (void) sprintf(sortcommand, "sort -y -T %s %s", tmpdir, temp1);
1238*7c478bd9Sstevel@tonic-gate 	 */
1239*7c478bd9Sstevel@tonic-gate 	(void) sprintf(sortcommand, "LC_ALL=C sort %s", temp1);
1240*7c478bd9Sstevel@tonic-gate 		if ((postings = popen(sortcommand, "r")) == NULL) {
1241*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
1242*7c478bd9Sstevel@tonic-gate 			    "cscope: cannot open pipe to sort command\n");
1243*7c478bd9Sstevel@tonic-gate 			cannotindex();
1244*7c478bd9Sstevel@tonic-gate 		} else {
1245*7c478bd9Sstevel@tonic-gate 			if ((totalterms = invmake(newinvname, newinvpost,
1246*7c478bd9Sstevel@tonic-gate 			    postings)) > 0) {
1247*7c478bd9Sstevel@tonic-gate 				movefile(newinvname, invname);
1248*7c478bd9Sstevel@tonic-gate 				movefile(newinvpost, invpost);
1249*7c478bd9Sstevel@tonic-gate 			} else {
1250*7c478bd9Sstevel@tonic-gate 				cannotindex();
1251*7c478bd9Sstevel@tonic-gate 			}
1252*7c478bd9Sstevel@tonic-gate 			(void) pclose(postings);
1253*7c478bd9Sstevel@tonic-gate 		}
1254*7c478bd9Sstevel@tonic-gate 		(void) unlink(temp1);
1255*7c478bd9Sstevel@tonic-gate 		(void) free(srcoffset);
1256*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1257*7c478bd9Sstevel@tonic-gate 		    "cscope: index has %ld references to %ld symbols\n",
1258*7c478bd9Sstevel@tonic-gate 		    npostings, totalterms);
1259*7c478bd9Sstevel@tonic-gate 	}
1260*7c478bd9Sstevel@tonic-gate 	/* rewrite the header with the trailer offset and final option list */
1261*7c478bd9Sstevel@tonic-gate 	rewind(newrefs);
1262*7c478bd9Sstevel@tonic-gate 	putheader(newdir);
1263*7c478bd9Sstevel@tonic-gate 	(void) fclose(newrefs);
1264*7c478bd9Sstevel@tonic-gate 
1265*7c478bd9Sstevel@tonic-gate 	/* close the old database file */
1266*7c478bd9Sstevel@tonic-gate 	if (symrefs >= 0) {
1267*7c478bd9Sstevel@tonic-gate 		(void) close(symrefs);
1268*7c478bd9Sstevel@tonic-gate 	}
1269*7c478bd9Sstevel@tonic-gate 	if (oldrefs != NULL) {
1270*7c478bd9Sstevel@tonic-gate 		(void) fclose(oldrefs);
1271*7c478bd9Sstevel@tonic-gate 	}
1272*7c478bd9Sstevel@tonic-gate 	/* replace it with the new database file */
1273*7c478bd9Sstevel@tonic-gate 	movefile(newreffile, reffile);
1274*7c478bd9Sstevel@tonic-gate }
1275*7c478bd9Sstevel@tonic-gate 
1276*7c478bd9Sstevel@tonic-gate /* string comparison function for qsort */
1277*7c478bd9Sstevel@tonic-gate 
1278*7c478bd9Sstevel@tonic-gate static int
compare(const void * s1,const void * s2)1279*7c478bd9Sstevel@tonic-gate compare(const void *s1, const void *s2)
1280*7c478bd9Sstevel@tonic-gate {
1281*7c478bd9Sstevel@tonic-gate 	return (strcmp((char *)s1, (char *)s2));
1282*7c478bd9Sstevel@tonic-gate }
1283*7c478bd9Sstevel@tonic-gate 
1284*7c478bd9Sstevel@tonic-gate /* get the next file name in the old cross-reference */
1285*7c478bd9Sstevel@tonic-gate 
1286*7c478bd9Sstevel@tonic-gate static char *
getoldfile(void)1287*7c478bd9Sstevel@tonic-gate getoldfile(void)
1288*7c478bd9Sstevel@tonic-gate {
1289*7c478bd9Sstevel@tonic-gate 	static	char	file[PATHLEN + 1];	/* file name in old crossref */
1290*7c478bd9Sstevel@tonic-gate 
1291*7c478bd9Sstevel@tonic-gate 	if (blockp != NULL) {
1292*7c478bd9Sstevel@tonic-gate 		do {
1293*7c478bd9Sstevel@tonic-gate 			if (*blockp == NEWFILE) {
1294*7c478bd9Sstevel@tonic-gate 				skiprefchar();
1295*7c478bd9Sstevel@tonic-gate 				getstring(file);
1296*7c478bd9Sstevel@tonic-gate 				if (file[0] != '\0') {
1297*7c478bd9Sstevel@tonic-gate 					/* if not end-of-crossref */
1298*7c478bd9Sstevel@tonic-gate 					return (file);
1299*7c478bd9Sstevel@tonic-gate 				}
1300*7c478bd9Sstevel@tonic-gate 				return (NULL);
1301*7c478bd9Sstevel@tonic-gate 			}
1302*7c478bd9Sstevel@tonic-gate 		} while (scanpast('\t') != NULL);
1303*7c478bd9Sstevel@tonic-gate 	}
1304*7c478bd9Sstevel@tonic-gate 	return (NULL);
1305*7c478bd9Sstevel@tonic-gate }
1306*7c478bd9Sstevel@tonic-gate 
1307*7c478bd9Sstevel@tonic-gate /*
1308*7c478bd9Sstevel@tonic-gate  * output the cscope version, current directory, database format options, and
1309*7c478bd9Sstevel@tonic-gate  * the database trailer offset
1310*7c478bd9Sstevel@tonic-gate  */
1311*7c478bd9Sstevel@tonic-gate 
1312*7c478bd9Sstevel@tonic-gate static void
putheader(char * dir)1313*7c478bd9Sstevel@tonic-gate putheader(char *dir)
1314*7c478bd9Sstevel@tonic-gate {
1315*7c478bd9Sstevel@tonic-gate 	dboffset = fprintf(newrefs, "cscope %d %s", FILEVERSION, dir);
1316*7c478bd9Sstevel@tonic-gate 	if (compress == NO) {
1317*7c478bd9Sstevel@tonic-gate 		dboffset += fprintf(newrefs, " -c");
1318*7c478bd9Sstevel@tonic-gate 	}
1319*7c478bd9Sstevel@tonic-gate 	if (invertedindex == YES) {
1320*7c478bd9Sstevel@tonic-gate 		dboffset += fprintf(newrefs, " -q %.10ld", totalterms);
1321*7c478bd9Sstevel@tonic-gate 	} else {
1322*7c478bd9Sstevel@tonic-gate 		/*
1323*7c478bd9Sstevel@tonic-gate 		 * leave space so if the header is overwritten without -q
1324*7c478bd9Sstevel@tonic-gate 		 * because writing the inverted index failed, the header is
1325*7c478bd9Sstevel@tonic-gate 		 * the same length
1326*7c478bd9Sstevel@tonic-gate 		 */
1327*7c478bd9Sstevel@tonic-gate 		dboffset += fprintf(newrefs, "              ");
1328*7c478bd9Sstevel@tonic-gate 	}
1329*7c478bd9Sstevel@tonic-gate 	if (truncatesyms == YES) {
1330*7c478bd9Sstevel@tonic-gate 		dboffset += fprintf(newrefs, " -T");
1331*7c478bd9Sstevel@tonic-gate 	}
1332*7c478bd9Sstevel@tonic-gate 	dbfprintf(newrefs, " %.10ld\n", traileroffset);
1333*7c478bd9Sstevel@tonic-gate }
1334*7c478bd9Sstevel@tonic-gate 
1335*7c478bd9Sstevel@tonic-gate /* put the name list into the cross-reference file */
1336*7c478bd9Sstevel@tonic-gate 
1337*7c478bd9Sstevel@tonic-gate static void
putlist(char ** names,int count)1338*7c478bd9Sstevel@tonic-gate putlist(char **names, int count)
1339*7c478bd9Sstevel@tonic-gate {
1340*7c478bd9Sstevel@tonic-gate 	int	i, size = 0;
1341*7c478bd9Sstevel@tonic-gate 
1342*7c478bd9Sstevel@tonic-gate 	(void) fprintf(newrefs, "%d\n", count);
1343*7c478bd9Sstevel@tonic-gate 	if (names == srcfiles) {
1344*7c478bd9Sstevel@tonic-gate 
1345*7c478bd9Sstevel@tonic-gate 		/* calculate the string space needed */
1346*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < count; ++i) {
1347*7c478bd9Sstevel@tonic-gate 			size += strlen(names[i]) + 1;
1348*7c478bd9Sstevel@tonic-gate 		}
1349*7c478bd9Sstevel@tonic-gate 		(void) fprintf(newrefs, "%d\n", size);
1350*7c478bd9Sstevel@tonic-gate 	}
1351*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < count; ++i) {
1352*7c478bd9Sstevel@tonic-gate 		if (fputs(names[i], newrefs) == EOF ||
1353*7c478bd9Sstevel@tonic-gate 		    putc('\n', newrefs) == EOF) {
1354*7c478bd9Sstevel@tonic-gate 			cannotwrite(newreffile);
1355*7c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
1356*7c478bd9Sstevel@tonic-gate 		}
1357*7c478bd9Sstevel@tonic-gate 	}
1358*7c478bd9Sstevel@tonic-gate }
1359*7c478bd9Sstevel@tonic-gate 
1360*7c478bd9Sstevel@tonic-gate /* see if the name list is the same in the cross-reference file */
1361*7c478bd9Sstevel@tonic-gate 
1362*7c478bd9Sstevel@tonic-gate static BOOL
samelist(FILE * oldrefs,char ** names,int count)1363*7c478bd9Sstevel@tonic-gate samelist(FILE *oldrefs, char **names, int count)
1364*7c478bd9Sstevel@tonic-gate {
1365*7c478bd9Sstevel@tonic-gate 	char	oldname[PATHLEN + 1];	/* name in old cross-reference */
1366*7c478bd9Sstevel@tonic-gate 	int	oldcount;
1367*7c478bd9Sstevel@tonic-gate 	int	i;
1368*7c478bd9Sstevel@tonic-gate 
1369*7c478bd9Sstevel@tonic-gate 	/* see if the number of names is the same */
1370*7c478bd9Sstevel@tonic-gate 	if (fscanf(oldrefs, "%d", &oldcount) != 1 ||
1371*7c478bd9Sstevel@tonic-gate 	    oldcount != count) {
1372*7c478bd9Sstevel@tonic-gate 		return (NO);
1373*7c478bd9Sstevel@tonic-gate 	}
1374*7c478bd9Sstevel@tonic-gate 	/* see if the name list is the same */
1375*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < count; ++i) {
1376*7c478bd9Sstevel@tonic-gate 		if (fscanf(oldrefs, "%s", oldname) != 1 ||
1377*7c478bd9Sstevel@tonic-gate 		    strnotequal(oldname, names[i])) {
1378*7c478bd9Sstevel@tonic-gate 			return (NO);
1379*7c478bd9Sstevel@tonic-gate 		}
1380*7c478bd9Sstevel@tonic-gate 	}
1381*7c478bd9Sstevel@tonic-gate 	return (YES);
1382*7c478bd9Sstevel@tonic-gate }
1383*7c478bd9Sstevel@tonic-gate 
1384*7c478bd9Sstevel@tonic-gate /* skip the list in the cross-reference file */
1385*7c478bd9Sstevel@tonic-gate 
1386*7c478bd9Sstevel@tonic-gate static void
skiplist(FILE * oldrefs)1387*7c478bd9Sstevel@tonic-gate skiplist(FILE *oldrefs)
1388*7c478bd9Sstevel@tonic-gate {
1389*7c478bd9Sstevel@tonic-gate 	int	i;
1390*7c478bd9Sstevel@tonic-gate 
1391*7c478bd9Sstevel@tonic-gate 	if (fscanf(oldrefs, "%d", &i) != 1) {
1392*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1393*7c478bd9Sstevel@tonic-gate 		    "cscope: cannot read list size from file %s\n", reffile);
1394*7c478bd9Sstevel@tonic-gate 		exit(1);
1395*7c478bd9Sstevel@tonic-gate 	}
1396*7c478bd9Sstevel@tonic-gate 	while (--i >= 0) {
1397*7c478bd9Sstevel@tonic-gate 		if (fscanf(oldrefs, "%*s") != 0) {
1398*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
1399*7c478bd9Sstevel@tonic-gate 			    "cscope: cannot read list name from file %s\n",
1400*7c478bd9Sstevel@tonic-gate 			    reffile);
1401*7c478bd9Sstevel@tonic-gate 			exit(1);
1402*7c478bd9Sstevel@tonic-gate 		}
1403*7c478bd9Sstevel@tonic-gate 	}
1404*7c478bd9Sstevel@tonic-gate }
1405*7c478bd9Sstevel@tonic-gate 
1406*7c478bd9Sstevel@tonic-gate /* copy this file's symbol data */
1407*7c478bd9Sstevel@tonic-gate 
1408*7c478bd9Sstevel@tonic-gate static void
copydata(void)1409*7c478bd9Sstevel@tonic-gate copydata(void)
1410*7c478bd9Sstevel@tonic-gate {
1411*7c478bd9Sstevel@tonic-gate 	char	symbol[PATLEN + 1];
1412*7c478bd9Sstevel@tonic-gate 	char	*cp;
1413*7c478bd9Sstevel@tonic-gate 
1414*7c478bd9Sstevel@tonic-gate 	setmark('\t');
1415*7c478bd9Sstevel@tonic-gate 	cp = blockp;
1416*7c478bd9Sstevel@tonic-gate 	for (;;) {
1417*7c478bd9Sstevel@tonic-gate 		/* copy up to the next \t */
1418*7c478bd9Sstevel@tonic-gate 		do {	/* innermost loop optimized to only one test */
1419*7c478bd9Sstevel@tonic-gate 			while (*cp != '\t') {
1420*7c478bd9Sstevel@tonic-gate 				dbputc(*cp++);
1421*7c478bd9Sstevel@tonic-gate 			}
1422*7c478bd9Sstevel@tonic-gate 		} while (*++cp == '\0' && (cp = readblock()) != NULL);
1423*7c478bd9Sstevel@tonic-gate 		dbputc('\t');	/* copy the tab */
1424*7c478bd9Sstevel@tonic-gate 
1425*7c478bd9Sstevel@tonic-gate 		/* get the next character */
1426*7c478bd9Sstevel@tonic-gate 		if (*(cp + 1) == '\0') {
1427*7c478bd9Sstevel@tonic-gate 			cp = readblock();
1428*7c478bd9Sstevel@tonic-gate 		}
1429*7c478bd9Sstevel@tonic-gate 		/* exit if at the end of this file's data */
1430*7c478bd9Sstevel@tonic-gate 		if (cp == NULL || *cp == NEWFILE) {
1431*7c478bd9Sstevel@tonic-gate 			break;
1432*7c478bd9Sstevel@tonic-gate 		}
1433*7c478bd9Sstevel@tonic-gate 		/* look for an #included file */
1434*7c478bd9Sstevel@tonic-gate 		if (*cp == INCLUDE) {
1435*7c478bd9Sstevel@tonic-gate 			blockp = cp;
1436*7c478bd9Sstevel@tonic-gate 			putinclude(symbol);
1437*7c478bd9Sstevel@tonic-gate 			putstring(symbol);
1438*7c478bd9Sstevel@tonic-gate 			setmark('\t');
1439*7c478bd9Sstevel@tonic-gate 			cp = blockp;
1440*7c478bd9Sstevel@tonic-gate 		}
1441*7c478bd9Sstevel@tonic-gate 	}
1442*7c478bd9Sstevel@tonic-gate 	blockp = cp;
1443*7c478bd9Sstevel@tonic-gate }
1444*7c478bd9Sstevel@tonic-gate 
1445*7c478bd9Sstevel@tonic-gate /* copy this file's symbol data and output the inverted index postings */
1446*7c478bd9Sstevel@tonic-gate 
1447*7c478bd9Sstevel@tonic-gate static void
copyinverted(void)1448*7c478bd9Sstevel@tonic-gate copyinverted(void)
1449*7c478bd9Sstevel@tonic-gate {
1450*7c478bd9Sstevel@tonic-gate 	char	*cp;
1451*7c478bd9Sstevel@tonic-gate 	int	c;
1452*7c478bd9Sstevel@tonic-gate 	int	type;	/* reference type (mark character) */
1453*7c478bd9Sstevel@tonic-gate 	char	symbol[PATLEN + 1];
1454*7c478bd9Sstevel@tonic-gate 
1455*7c478bd9Sstevel@tonic-gate 	/* note: this code was expanded in-line for speed */
1456*7c478bd9Sstevel@tonic-gate 	/* while (scanpast('\n') != NULL) { */
1457*7c478bd9Sstevel@tonic-gate 	/* other macros were replaced by code using cp instead of blockp */
1458*7c478bd9Sstevel@tonic-gate 	cp = blockp;
1459*7c478bd9Sstevel@tonic-gate 	for (;;) {
1460*7c478bd9Sstevel@tonic-gate 		setmark('\n');
1461*7c478bd9Sstevel@tonic-gate 		do {	/* innermost loop optimized to only one test */
1462*7c478bd9Sstevel@tonic-gate 			while (*cp != '\n') {
1463*7c478bd9Sstevel@tonic-gate 				dbputc(*cp++);
1464*7c478bd9Sstevel@tonic-gate 			}
1465*7c478bd9Sstevel@tonic-gate 		} while (*++cp == '\0' && (cp = readblock()) != NULL);
1466*7c478bd9Sstevel@tonic-gate 		dbputc('\n');	/* copy the newline */
1467*7c478bd9Sstevel@tonic-gate 
1468*7c478bd9Sstevel@tonic-gate 		/* get the next character */
1469*7c478bd9Sstevel@tonic-gate 		if (*(cp + 1) == '\0') {
1470*7c478bd9Sstevel@tonic-gate 			cp = readblock();
1471*7c478bd9Sstevel@tonic-gate 		}
1472*7c478bd9Sstevel@tonic-gate 		/* exit if at the end of this file's data */
1473*7c478bd9Sstevel@tonic-gate 		if (cp == NULL) {
1474*7c478bd9Sstevel@tonic-gate 			break;
1475*7c478bd9Sstevel@tonic-gate 		}
1476*7c478bd9Sstevel@tonic-gate 		switch (*cp) {
1477*7c478bd9Sstevel@tonic-gate 		case '\n':
1478*7c478bd9Sstevel@tonic-gate 			lineoffset = dboffset + 1;
1479*7c478bd9Sstevel@tonic-gate 			continue;
1480*7c478bd9Sstevel@tonic-gate 		case '\t':
1481*7c478bd9Sstevel@tonic-gate 			dbputc('\t');
1482*7c478bd9Sstevel@tonic-gate 			blockp = cp;
1483*7c478bd9Sstevel@tonic-gate 			type = getrefchar();
1484*7c478bd9Sstevel@tonic-gate 			switch (type) {
1485*7c478bd9Sstevel@tonic-gate 			case NEWFILE:		/* file name */
1486*7c478bd9Sstevel@tonic-gate 				return;
1487*7c478bd9Sstevel@tonic-gate 			case INCLUDE:		/* #included file */
1488*7c478bd9Sstevel@tonic-gate 				putinclude(symbol);
1489*7c478bd9Sstevel@tonic-gate 				goto output;
1490*7c478bd9Sstevel@tonic-gate 			}
1491*7c478bd9Sstevel@tonic-gate 			dbputc(type);
1492*7c478bd9Sstevel@tonic-gate 			skiprefchar();
1493*7c478bd9Sstevel@tonic-gate 			getstring(symbol);
1494*7c478bd9Sstevel@tonic-gate 			goto output;
1495*7c478bd9Sstevel@tonic-gate 		}
1496*7c478bd9Sstevel@tonic-gate 		c = *cp;
1497*7c478bd9Sstevel@tonic-gate 		if (c & 0200) {	/* digraph char? */
1498*7c478bd9Sstevel@tonic-gate 			c = dichar1[(c & 0177) / 8];
1499*7c478bd9Sstevel@tonic-gate 		}
1500*7c478bd9Sstevel@tonic-gate 		/* if this is a symbol */
1501*7c478bd9Sstevel@tonic-gate 		if (isalpha(c) || c == '_') {
1502*7c478bd9Sstevel@tonic-gate 			blockp = cp;
1503*7c478bd9Sstevel@tonic-gate 			getstring(symbol);
1504*7c478bd9Sstevel@tonic-gate 			type = ' ';
1505*7c478bd9Sstevel@tonic-gate 		output:
1506*7c478bd9Sstevel@tonic-gate 			putposting(symbol, type);
1507*7c478bd9Sstevel@tonic-gate 			putstring(symbol);
1508*7c478bd9Sstevel@tonic-gate 			if (blockp == NULL) {
1509*7c478bd9Sstevel@tonic-gate 				return;
1510*7c478bd9Sstevel@tonic-gate 			}
1511*7c478bd9Sstevel@tonic-gate 			cp = blockp;
1512*7c478bd9Sstevel@tonic-gate 		}
1513*7c478bd9Sstevel@tonic-gate 	}
1514*7c478bd9Sstevel@tonic-gate 	blockp = cp;
1515*7c478bd9Sstevel@tonic-gate }
1516*7c478bd9Sstevel@tonic-gate 
1517*7c478bd9Sstevel@tonic-gate /* process the #included file in the old database */
1518*7c478bd9Sstevel@tonic-gate 
1519*7c478bd9Sstevel@tonic-gate static void
putinclude(char * s)1520*7c478bd9Sstevel@tonic-gate putinclude(char *s)
1521*7c478bd9Sstevel@tonic-gate {
1522*7c478bd9Sstevel@tonic-gate 	dbputc(INCLUDE);
1523*7c478bd9Sstevel@tonic-gate 	skiprefchar();
1524*7c478bd9Sstevel@tonic-gate 	getstring(s);
1525*7c478bd9Sstevel@tonic-gate 	incfile(s + 1, *s);
1526*7c478bd9Sstevel@tonic-gate }
1527*7c478bd9Sstevel@tonic-gate 
1528*7c478bd9Sstevel@tonic-gate /* replace the old file with the new file */
1529*7c478bd9Sstevel@tonic-gate 
1530*7c478bd9Sstevel@tonic-gate static void
movefile(char * new,char * old)1531*7c478bd9Sstevel@tonic-gate movefile(char *new, char *old)
1532*7c478bd9Sstevel@tonic-gate {
1533*7c478bd9Sstevel@tonic-gate 	(void) unlink(old);
1534*7c478bd9Sstevel@tonic-gate 	if (link(new, old) == -1) {
1535*7c478bd9Sstevel@tonic-gate 		(void) perror("cscope");
1536*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1537*7c478bd9Sstevel@tonic-gate 		    "cscope: cannot link file %s to file %s\n", new, old);
1538*7c478bd9Sstevel@tonic-gate 		myexit(1);
1539*7c478bd9Sstevel@tonic-gate 	}
1540*7c478bd9Sstevel@tonic-gate 	if (unlink(new) == -1) {
1541*7c478bd9Sstevel@tonic-gate 		(void) perror("cscope");
1542*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "cscope: cannot unlink file %s\n", new);
1543*7c478bd9Sstevel@tonic-gate 		errorsfound = YES;
1544*7c478bd9Sstevel@tonic-gate 	}
1545*7c478bd9Sstevel@tonic-gate }
1546*7c478bd9Sstevel@tonic-gate 
1547*7c478bd9Sstevel@tonic-gate /* enter curses mode */
1548*7c478bd9Sstevel@tonic-gate 
1549*7c478bd9Sstevel@tonic-gate void
entercurses(void)1550*7c478bd9Sstevel@tonic-gate entercurses(void)
1551*7c478bd9Sstevel@tonic-gate {
1552*7c478bd9Sstevel@tonic-gate 	incurses = YES;
1553*7c478bd9Sstevel@tonic-gate 	(void) nonl();		/* don't translate an output \n to \n\r */
1554*7c478bd9Sstevel@tonic-gate 	(void) cbreak();	/* single character input */
1555*7c478bd9Sstevel@tonic-gate 	(void) noecho();	/* don't echo input characters */
1556*7c478bd9Sstevel@tonic-gate 	(void) clear();		/* clear the screen */
1557*7c478bd9Sstevel@tonic-gate 	initmouse();		/* initialize any mouse interface */
1558*7c478bd9Sstevel@tonic-gate 	drawscrollbar(topline, nextline, totallines);
1559*7c478bd9Sstevel@tonic-gate 	atfield();
1560*7c478bd9Sstevel@tonic-gate }
1561*7c478bd9Sstevel@tonic-gate 
1562*7c478bd9Sstevel@tonic-gate /* exit curses mode */
1563*7c478bd9Sstevel@tonic-gate 
1564*7c478bd9Sstevel@tonic-gate void
exitcurses(void)1565*7c478bd9Sstevel@tonic-gate exitcurses(void)
1566*7c478bd9Sstevel@tonic-gate {
1567*7c478bd9Sstevel@tonic-gate 	/* clear the bottom line */
1568*7c478bd9Sstevel@tonic-gate 	(void) move(LINES - 1, 0);
1569*7c478bd9Sstevel@tonic-gate 	(void) clrtoeol();
1570*7c478bd9Sstevel@tonic-gate 	(void) refresh();
1571*7c478bd9Sstevel@tonic-gate 
1572*7c478bd9Sstevel@tonic-gate 	/* exit curses and restore the terminal modes */
1573*7c478bd9Sstevel@tonic-gate 	(void) endwin();
1574*7c478bd9Sstevel@tonic-gate 	incurses = NO;
1575*7c478bd9Sstevel@tonic-gate 
1576*7c478bd9Sstevel@tonic-gate 	/* restore the mouse */
1577*7c478bd9Sstevel@tonic-gate 	cleanupmouse();
1578*7c478bd9Sstevel@tonic-gate 	(void) fflush(stdout);
1579*7c478bd9Sstevel@tonic-gate }
1580*7c478bd9Sstevel@tonic-gate 
1581*7c478bd9Sstevel@tonic-gate /* no activity timeout occurred */
1582*7c478bd9Sstevel@tonic-gate 
1583*7c478bd9Sstevel@tonic-gate static void
timedout(int sig)1584*7c478bd9Sstevel@tonic-gate timedout(int sig)
1585*7c478bd9Sstevel@tonic-gate {
1586*7c478bd9Sstevel@tonic-gate 	/* if there is a child process, don't exit until it does */
1587*7c478bd9Sstevel@tonic-gate 	if (childpid) {
1588*7c478bd9Sstevel@tonic-gate 		closedatabase();
1589*7c478bd9Sstevel@tonic-gate 		noacttimeout = YES;
1590*7c478bd9Sstevel@tonic-gate 		return;
1591*7c478bd9Sstevel@tonic-gate 	}
1592*7c478bd9Sstevel@tonic-gate 	exitcurses();
1593*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "cscope: no activity for %d hours--exiting\n",
1594*7c478bd9Sstevel@tonic-gate 	    noacttime / 3600);
1595*7c478bd9Sstevel@tonic-gate 	myexit(sig);
1596*7c478bd9Sstevel@tonic-gate }
1597*7c478bd9Sstevel@tonic-gate 
1598*7c478bd9Sstevel@tonic-gate /* cleanup and exit */
1599*7c478bd9Sstevel@tonic-gate 
1600*7c478bd9Sstevel@tonic-gate void
myexit(int sig)1601*7c478bd9Sstevel@tonic-gate myexit(int sig)
1602*7c478bd9Sstevel@tonic-gate {
1603*7c478bd9Sstevel@tonic-gate 	/* deleted layer causes multiple signals */
1604*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGHUP, SIG_IGN);
1605*7c478bd9Sstevel@tonic-gate 	/* remove any temporary files */
1606*7c478bd9Sstevel@tonic-gate 	if (temp1[0] != '\0') {
1607*7c478bd9Sstevel@tonic-gate 		(void) unlink(temp1);
1608*7c478bd9Sstevel@tonic-gate 		(void) unlink(temp2);
1609*7c478bd9Sstevel@tonic-gate 	}
1610*7c478bd9Sstevel@tonic-gate 	/* restore the terminal to its original mode */
1611*7c478bd9Sstevel@tonic-gate 	if (incurses == YES) {
1612*7c478bd9Sstevel@tonic-gate 		exitcurses();
1613*7c478bd9Sstevel@tonic-gate 	}
1614*7c478bd9Sstevel@tonic-gate 
1615*7c478bd9Sstevel@tonic-gate 	/* dump core for debugging on the quit signal */
1616*7c478bd9Sstevel@tonic-gate 	if (sig == SIGQUIT) {
1617*7c478bd9Sstevel@tonic-gate 		(void) abort();
1618*7c478bd9Sstevel@tonic-gate 	}
1619*7c478bd9Sstevel@tonic-gate 	exit(sig);
1620*7c478bd9Sstevel@tonic-gate }
1621