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