#include "global.h"
#include "vp.h"
#include "version.h"
#include "scanner.h"
#include <stdlib.h>
#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
#include <ncurses.h>
#else
#include <curses.h>
#endif
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#define EDITOR "vi"
#define SHELL "sh"
#define LINEFLAG "+%s"
#define TMPDIR "/tmp"
#ifndef DFLT_INCDIR
#define DFLT_INCDIR "/usr/include"
#endif
static char const rcsid[] = "$Id: main.c,v 1.3 2002/01/09 19:04:05 umeshv Exp $";
char dichar1[] = " teisaprnl(of)=c";
char dichar2[] = " tnerpla";
char dicode1[256];
char dicode2[256];
char *editor, *home, *shell, *lineflag;
BOOL lineflagafterfile;
char *argv0;
BOOL compress = YES;
BOOL dbtruncated;
int dispcomponents = 1;
#if CCS
BOOL displayversion;
#endif
BOOL editallprompt = YES;
int fileargc;
char **fileargv;
int fileversion;
BOOL incurses = NO;
INVCONTROL invcontrol;
BOOL invertedindex;
BOOL isuptodate;
BOOL kernelmode;
BOOL linemode = NO;
BOOL recurse_dir = NO;
char *namefile;
static char *newinvname;
static char *newinvpost;
char *newreffile;
FILE *newrefs;
BOOL ogs;
FILE *postings;
char *prependpath;
FILE *refsfound;
BOOL select_large = NO;
int symrefs = -1;
char temp1[PATHLEN + 1];
char temp2[PATHLEN + 1];
long totalterms;
BOOL trun_syms;
char tempstring[8192];
static BOOL buildonly = NO;
static BOOL fileschanged;
static char *invname = INVNAME;
static char *invpost = INVPOST;
static long traileroffset;
static BOOL onesearch;
static char *reffile = REFFILE;
static char *reflines;
static char *tmpdir;
static BOOL unconditional;
BOOL samelist(FILE *oldrefs, char **names, int count);
char *getoldfile(void);
int compare(const void *s1, const void *s2);
void copydata(void);
void copyinverted(void);
void initcompress(void);
void movefile(char *new, char *old);
void opendatabase(void);
void putheader(char *dir);
void putinclude(char *s);
void putlist(char **names, int count);
void skiplist(FILE *oldrefs);
static void build(void);
static void usage(void);
static void longusage(void);
int
main(int argc, char **argv)
{
FILE *names;
int oldnum;
char path[PATHLEN + 1];
FILE *oldrefs;
char *s;
int c, i;
pid_t pid;
struct stat stat_buf;
#if SVR2 && !BSD && !V9 && !u3b2 && !sun
void fixkeypad();
#endif
yyin = stdin;
yyout = stdout;
argv0 = argv[0];
while (--argc > 0 && (*++argv)[0] == '-') {
for (s = argv[0] + 1; *s != '\0'; s++) {
if (isdigit((unsigned char)*s)) {
field = *s - '0';
if (field > 8) {
field = 8;
}
if (*++s == '\0' && --argc > 0) {
s = *++argv;
}
if (strlen(s) > PATLEN) {
(void) fprintf(stderr, "cscope: pattern too long, cannot be > %d characters\n", PATLEN);
exit(1);
}
(void) strcpy(pattern, s);
goto nextarg;
}
switch (*s) {
case '-':
--argc;
++argv;
goto lastarg;
case 'V':
#if CCS
displayversion = YES;
break;
#else
(void) fprintf(stderr, "%s: version %d%s\n", argv0,
FILEVERSION, FIXVERSION);
exit(0);
#endif
case 'b':
buildonly = YES;
linemode = YES;
break;
case 'c':
compress = NO;
break;
case 'C':
caseless = YES;
egrepcaseless(caseless);
break;
case 'd':
isuptodate = YES;
break;
case 'e':
editallprompt = NO;
break;
case 'h':
(void) longusage();
exit(1);
case 'k':
kernelmode = YES;
break;
case 'L':
onesearch = YES;
case 'l':
linemode = YES;
break;
case 'o':
ogs = YES;
break;
case 'q':
invertedindex = YES;
break;
case 'T':
trun_syms = YES;
break;
case 'u':
unconditional = YES;
break;
case 'U':
fileschanged = YES;
break;
case 'R':
recurse_dir = YES;
break;
case 'f':
case 'F':
case 'i':
case 'I':
case 'p':
case 'P':
case 's':
case 'S':
c = *s;
if (*++s == '\0' && --argc > 0) {
s = *++argv;
}
if (*s == '\0') {
(void) fprintf(stderr, "%s: -%c option: missing or empty value\n",
argv0, c);
goto usage;
}
switch (c) {
case 'f':
reffile = s;
(void) strcpy(path, s);
#if !BSD || sun
s = mybasename(path);
if (strlen(s) > 11) {
s[11] = '\0';
}
#endif
s = path + strlen(path);
(void) strcpy(s, ".in");
invname = stralloc(path);
(void) strcpy(s, ".po");
invpost = stralloc(path);
break;
case 'F':
reflines = s;
break;
case 'i':
namefile = s;
break;
case 'I':
includedir(s);
break;
case 'p':
if (*s < '0' || *s > '9' ) {
(void) fprintf(stderr, "%s: -p option: missing or invalid numeric value\n",
argv0);
goto usage;
}
dispcomponents = atoi(s);
break;
case 'P':
prependpath = s;
break;
case 's':
case 'S':
sourcedir(s);
break;
}
goto nextarg;
case 't':
select_large = YES;
break;
default:
(void) fprintf(stderr, "%s: unknown option: -%c\n", argv0,
*s);
usage:
(void) usage();
(void) fprintf(stderr, "Try the -h option for more information.\n");
exit(1);
}
}
nextarg: ;
}
lastarg:
editor = mygetenv("EDITOR", EDITOR);
editor = mygetenv("VIEWER", editor);
editor = mygetenv("CSCOPE_EDITOR", editor);
home = getenv("HOME");
shell = mygetenv("SHELL", SHELL);
lineflag = mygetenv("CSCOPE_LINEFLAG", LINEFLAG);
lineflagafterfile = getenv("CSCOPE_LINEFLAG_AFTER_FILE")?1:0;
tmpdir = mygetenv("TMPDIR", TMPDIR);
if (namefile && strcmp(namefile, "-") == 0 && !buildonly)
{
fprintf (stderr, "cscope: Must use -b if file list comes from stdin\n");
exit(1);
}
if (stat (tmpdir, &stat_buf))
{
fprintf (stderr, "cscope: Temporary directory %s does not exist or cannot be accessed\n", tmpdir);
fprintf (stderr, "cscope: Please create the directory or set the environment variable\ncscope: TMPDIR to a valid directory\n");
exit(1);
}
pid = getpid();
(void) sprintf(temp1, "%s/cscope%d.1", tmpdir, pid);
(void) sprintf(temp2, "%s/cscope%d.2", tmpdir, pid);
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
void myexit();
(void) signal(SIGINT, myexit);
(void) signal(SIGQUIT, myexit);
}
(void) signal(SIGHUP, myexit);
if (reffile[0] != '/' && access(".", WRITE) != 0) {
(void) sprintf(path, "%s/%s", home, reffile);
if (isuptodate == NO || access(path, READ) == 0) {
reffile = stralloc(path);
(void) sprintf(path, "%s/%s", home, invname);
invname = stralloc(path);
(void) sprintf(path, "%s/%s", home, invpost);
invpost = stralloc(path);
}
}
if (linemode == NO)
{
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGPIPE, SIG_IGN);
(void) initscr();
entercurses();
#if TERMINFO
(void) keypad(stdscr, TRUE);
#if SVR2 && !BSD && !V9 && !u3b2 && !sun
fixkeypad();
#endif
#endif
#if UNIXPC
standend();
#endif
dispinit();
setfield();
postmsg("");
display();
}
if (isuptodate == YES) {
if ((oldrefs = vpfopen(reffile, "rb")) == NULL) {
posterr("cscope: cannot open file %s\n", reffile);
myexit(1);
}
if (fscanf(oldrefs, "cscope %d %*s", &fileversion) != 1) {
posterr("cscope: cannot read file version from file %s\n", reffile);
myexit(1);
}
if (fileversion >= 8) {
compress = YES;
invertedindex = NO;
for (;;) {
(void) getc(oldrefs);
if ((c = getc(oldrefs)) != '-') {
(void) ungetc(c, oldrefs);
break;
}
switch (c = getc(oldrefs)) {
case 'c':
compress = NO;
break;
case 'q':
invertedindex = YES;
(void) fscanf(oldrefs, "%ld", &totalterms);
break;
case 'T':
dbtruncated = YES;
trun_syms = YES;
break;
}
}
initcompress();
if (fscanf(oldrefs, "%ld", &traileroffset) != 1) {
posterr("cscope: cannot read trailer offset from file %s\n", reffile);
myexit(1);
}
if (fseek(oldrefs, traileroffset, SEEK_SET) == -1) {
posterr("cscope: cannot seek to trailer in file %s\n", reffile);
myexit(1);
}
}
skiplist(oldrefs);
skiplist(oldrefs);
if (fscanf(oldrefs, "%d", &nsrcfiles) != 1) {
posterr("cscope: cannot read source file size from file %s\n", reffile);
myexit(1);
}
srcfiles = mymalloc(nsrcfiles * sizeof(char *));
if (fileversion >= 9) {
if (fscanf(oldrefs, "%d", &oldnum) != 1) {
posterr("cscope: cannot read string space size from file %s\n", reffile);
myexit(1);
}
s = (char *)mymalloc((unsigned) oldnum);
(void) getc(oldrefs);
if (fread(s, oldnum, 1, oldrefs) != 1) {
posterr("cscope: cannot read source file names from file %s\n", reffile);
myexit(1);
}
for (i = 0; i < nsrcfiles; ++i) {
srcfiles[i] = s;
for (++s; *s != '\n'; ++s) {
;
}
*s = '\0';
++s;
}
if ((namefile != NULL && (names = vpfopen(namefile, "r")) != NULL)
|| (names = vpfopen(NAMEFILE, "r")) != NULL) {
while (fscanf(names, "%s", path) == 1 && *path == '-') {
i = path[1];
s = path + 2;
if (*s == '\0') {
(void) fscanf(names, "%s", path);
s = path;
}
switch (i) {
case 'p':
if (*s < '0' || *s > '9') {
posterr("cscope: -p option in file %s: missing or invalid numeric value\n", namefile);
}
dispcomponents = atoi(s);
}
}
(void) fclose(names);
}
}
else {
for (i = 0; i < nsrcfiles; ++i) {
if (fscanf(oldrefs, "%s", path) != 1) {
posterr("cscope: cannot read source file name from file %s\n", reffile);
exit(1);
}
srcfiles[i] = stralloc(path);
}
}
(void) fclose(oldrefs);
}
else {
fileargc = argc;
fileargv = argv;
if ((s = getenv("SOURCEDIRS")) != NULL) {
sourcedir(s);
}
srcfiles = mymalloc(msrcfiles * sizeof(char *));
makefilelist();
if (nsrcfiles == 0) {
posterr( "cscope: no source files found\n");
myexit(1);
}
if ((s = getenv("INCLUDEDIRS")) != NULL) {
includedir(s);
}
if (kernelmode == NO) {
includedir(DFLT_INCDIR);
}
initsymtab();
(void) strcpy(path, reffile);
s = mybasename(path);
*s = '\0';
(void) strcat(path, "n");
++s;
(void) strcpy(s, mybasename(reffile));
newreffile = stralloc(path);
(void) strcpy(s, mybasename(invname));
newinvname = stralloc(path);
(void) strcpy(s, mybasename(invpost));
newinvpost = stralloc(path);
initcompress();
if (linemode == NO )
postmsg("Building cross-reference...");
build();
if (linemode == NO )
postmsg("");
if (buildonly == YES) {
myexit(0);
}
}
opendatabase();
if (linemode == YES) {
if (*pattern != '\0') {
if (search() == YES) {
while ((c = getc(refsfound)) != EOF) {
(void) putchar(c);
}
}
}
if (onesearch == YES) {
myexit(0);
}
for (;;) {
char buf[PATLEN + 2];
(void) printf(">> ");
(void) fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL) {
myexit(0);
}
if (*(s = buf + strlen(buf) - 1) == '\n') {
*s = '\0';
}
switch (*buf) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
field = *buf - '0';
(void) strcpy(pattern, buf + 1);
(void) search();
(void) printf("cscope: %d lines\n", totallines);
while ((c = getc(refsfound)) != EOF) {
(void) putchar(c);
}
break;
case 'c':
case ctrl('C'):
if (caseless == NO) {
caseless = YES;
}
else {
caseless = NO;
}
egrepcaseless(caseless);
break;
case 'r':
case ctrl('R'):
freefilelist();
makefilelist();
case 'R':
rebuild();
(void) putchar('\n');
break;
case 'C':
freefilelist();
(void) putchar('\n');
break;
case 'F':
(void) strcpy(path, buf + 1);
if (infilelist(path) == NO &&
(s = inviewpath(path)) != NULL) {
addsrcfile(path, s);
}
(void) putchar('\n');
break;
case 'q':
case ctrl('D'):
case ctrl('Z'):
myexit(0);
default:
(void) fprintf(stderr, "cscope: unknown command '%s'\n", buf);
break;
}
}
}
if (errorsfound == YES) {
errorsfound = NO;
askforreturn();
}
if (*pattern != '\0') {
atfield();
(void) command(ctrl('Y'));
}
else if (reflines != NULL) {
(void) readrefs(reflines);
}
display();
for (;;) {
if (!selecting)
atfield();
if ((c = mygetch()) == EOF || c == ctrl('D') || c == ctrl('Z')) {
break;
}
if (command(c) == YES) {
display();
}
if (selecting)
{
move(displine[curdispline], 0);
refresh();
}
}
myexit(0);
return 0;
}
void
cannotindex(void)
{
(void) fprintf(stderr, "cscope: cannot create inverted index; ignoring -q option\n");
invertedindex = NO;
errorsfound = YES;
(void) fprintf(stderr, "cscope: removed files %s and %s\n", newinvname, newinvpost);
(void) unlink(newinvname);
(void) unlink(newinvpost);
}
void
cannotopen(char *file)
{
posterr("Cannot open file %s", file);
}
void
cannotwrite(char *file)
{
#if HAVE_SNPRINTF
char msg[MSGLEN + 1];
(void) snprintf(msg, sizeof(msg),
"Removed file %s because write failed", file);
#else
char *msg = mymalloc(50+strlen(file));
(void) sprintf(msg, "Removed file %s because write failed", file);
#endif
myperror(msg);
#if !HAVE_SNPRINTF
free(msg);
#endif
(void) unlink(file);
myexit(1);
}
void
initcompress(void)
{
int i;
if (compress == YES) {
for (i = 0; i < 16; ++i) {
dicode1[(unsigned char) (dichar1[i])] = i * 8 + 1;
}
for (i = 0; i < 8; ++i) {
dicode2[(unsigned char) (dichar2[i])] = i + 1;
}
}
}
void
opendatabase(void)
{
if ((symrefs = vpopen(reffile, O_BINARY | O_RDONLY)) == -1) {
cannotopen(reffile);
myexit(1);
}
blocknumber = -1;
if (invertedindex == YES &&
invopen(&invcontrol, invname, invpost, INVAVAIL) == -1) {
askforreturn();
invertedindex = NO;
}
}
void
rebuild(void)
{
(void) close(symrefs);
if (invertedindex == YES) {
invclose(&invcontrol);
nsrcoffset = 0;
npostings = 0;
}
build();
opendatabase();
if (refsfound != NULL) {
(void) fclose(refsfound);
refsfound = NULL;
}
}
static void
build(void)
{
int i;
FILE *oldrefs;
time_t reftime;
char *file;
char *oldfile;
char newdir[PATHLEN + 1];
char olddir[PATHLEN + 1];
char oldname[PATHLEN + 1];
int oldnum;
struct stat statstruct;
int firstfile;
int lastfile;
int built = 0;
int copied = 0;
BOOL interactive = YES;
(void) strcpy(newdir, currentdir);
if (strcmp(currentdir, home) == 0) {
(void) strcpy(newdir, "$HOME");
}
else if (strncmp(currentdir, home, strlen(home)) == 0) {
(void) sprintf(newdir, "$HOME%s", currentdir + strlen(home));
}
qsort(srcfiles, (unsigned) nsrcfiles, sizeof(char *), compare);
if ((oldrefs = vpfopen(reffile, "rb")) != NULL && unconditional == NO &&
fscanf(oldrefs, "cscope %d %s", &fileversion, olddir) == 2 &&
(strcmp(olddir, currentdir) == 0 ||
strcmp(olddir, newdir) == 0)) {
(void) fstat(fileno(oldrefs), &statstruct);
reftime = statstruct.st_mtime;
if (fileversion >= 8) {
BOOL oldcompress = YES;
BOOL oldinvertedindex = NO;
BOOL oldtruncate = NO;
int c;
for (;;) {
while((c = getc(oldrefs)) == ' ') {
;
}
if (c != '-') {
(void) ungetc(c, oldrefs);
break;
}
switch (c = getc(oldrefs)) {
case 'c':
oldcompress = NO;
break;
case 'q':
oldinvertedindex = YES;
(void) fscanf(oldrefs, "%ld", &totalterms);
break;
case 'T':
oldtruncate = YES;
break;
}
}
if (oldcompress != compress || oldtruncate != trun_syms) {
posterr("cscope: -c or -T option mismatch between command line and old symbol database\n");
goto force;
}
if (oldinvertedindex != invertedindex) {
(void) posterr("cscope: -q option mismatch between command line and old symbol database\n");
if (invertedindex == NO) {
posterr("cscope: removed files %s and %s\n",
invname, invpost);
(void) unlink(invname);
(void) unlink(invpost);
}
goto outofdate;
}
if (fscanf(oldrefs, "%ld", &traileroffset) != 1 ||
fseek(oldrefs, traileroffset, SEEK_SET) == -1) {
posterr("cscope: incorrect symbol database file format\n");
goto force;
}
}
if (fileschanged == YES) {
goto outofdate;
}
if (samelist(oldrefs, srcdirs, nsrcdirs) == NO ||
samelist(oldrefs, incdirs, nincdirs) == NO ||
fscanf(oldrefs, "%d", &oldnum) != 1 ||
(fileversion >= 9 && fscanf(oldrefs, "%*s") != 0)) {
goto outofdate;
}
for (i = 0; i < nsrcfiles; ++i) {
if (fscanf(oldrefs, "%s", oldname) != 1 ||
strnotequal(oldname, srcfiles[i]) ||
stat(srcfiles[i], &statstruct) != 0 ||
statstruct.st_mtime > reftime) {
goto outofdate;
}
}
while (i++ < oldnum && fscanf(oldrefs, "%s", oldname) == 1) {
addsrcfile(mybasename(oldname), oldname);
}
(void) fclose(oldrefs);
return;
outofdate:
if (fileversion != FILEVERSION) {
(void) fprintf(stderr, "cscope: converting to new symbol database file format\n");
goto force;
}
if ((symrefs = vpopen(reffile, O_BINARY | O_RDONLY)) == -1) {
(void) fprintf(stderr, "cscope: cannot open file %s\n", reffile);
myexit(1);
}
blocknumber = -1;
(void) readblock();
(void) scanpast('\t');
oldfile = getoldfile();
}
else {
force: reftime = 0;
oldfile = NULL;
}
if ((newrefs = myfopen(newreffile, "wb")) == NULL) {
(void) fprintf(stderr, "cscope: cannot open file %s\n", reffile);
myexit(1);
}
if (invertedindex == YES && (postings = myfopen(temp1, "wb")) == NULL) {
cannotwrite(temp1);
cannotindex();
}
putheader(newdir);
fileversion = FILEVERSION;
if (buildonly == YES && !isatty(0)) {
interactive = NO;
}
else {
searchcount = 0;
}
dbputc('\t');
firstfile = 0;
lastfile = nsrcfiles;
if (invertedindex == YES) {
srcoffset = mymalloc((nsrcfiles + 1) * sizeof(long));
}
for (;;) {
progress("Building symbol database", (long)built,
(long)lastfile);
if (linemode == NO)
refresh();
for (fileindex = firstfile; fileindex < lastfile; ++fileindex) {
if (interactive == YES && fileindex % 10 == 0) {
progress("Building symbol database",
(long)fileindex, (long)lastfile);
}
file = srcfiles[fileindex];
while (oldfile != NULL && strcmp(file, oldfile) > 0) {
oldfile = getoldfile();
}
if (oldfile == NULL || strcmp(file, oldfile) < 0) {
crossref(file);
++built;
}
else if (stat(file, &statstruct) == 0 &&
statstruct.st_mtime > reftime) {
crossref(file);
++built;
oldfile = getoldfile();
}
else {
putfilename(file);
if (invertedindex == YES) {
copyinverted();
}
else {
copydata();
}
++copied;
oldfile = getoldfile();
}
}
if (lastfile == nsrcfiles) {
break;
}
firstfile = lastfile;
lastfile = nsrcfiles;
if (invertedindex == YES) {
srcoffset = myrealloc(srcoffset,
(nsrcfiles + 1) * sizeof(long));
}
qsort(&srcfiles[firstfile], (unsigned) (lastfile -
firstfile), sizeof(char *), compare);
}
putfilename("");
dbputc('\n');
traileroffset = dboffset;
putlist(srcdirs, nsrcdirs);
putlist(incdirs, nincdirs);
putlist(srcfiles, nsrcfiles);
if (fflush(newrefs) == EOF) {
cannotwrite(newreffile);
}
if (invertedindex == YES) {
char sortcommand[PATHLEN + 1];
if (fflush(postings) == EOF) {
cannotwrite(temp1);
}
(void) fstat(fileno(postings), &statstruct);
(void) fclose(postings);
(void) sprintf(sortcommand, "env LC_ALL=C sort -y -T %s %s", tmpdir, temp1);
if ((postings = mypopen(sortcommand, "r")) == NULL) {
(void) fprintf(stderr, "cscope: cannot open pipe to sort command\n");
cannotindex();
}
else {
if ((totalterms = invmake(newinvname, newinvpost, postings)) > 0) {
movefile(newinvname, invname);
movefile(newinvpost, invpost);
}
else {
cannotindex();
}
#if Darwin
(void) mypclose(postings);
#else
(void) pclose(postings);
#endif
}
(void) unlink(temp1);
(void) free(srcoffset);
}
rewind(newrefs);
putheader(newdir);
(void) fclose(newrefs);
if (symrefs >= 0) {
(void) close(symrefs);
}
if (oldrefs != NULL) {
(void) fclose(oldrefs);
}
movefile(newreffile, reffile);
}
int
compare(const void *arg_s1, const void *arg_s2)
{
const char **s1 = (const char **) arg_s1;
const char **s2 = (const char **) arg_s2;
return(strcmp(*s1, *s2));
}
char *
getoldfile(void)
{
static char file[PATHLEN + 1];
if (blockp != NULL) {
do {
if (*blockp == NEWFILE) {
skiprefchar();
putstring(file);
if (file[0] != '\0') {
return(file);
}
return(NULL);
}
} while (scanpast('\t') != NULL);
}
return(NULL);
}
void
putheader(char *dir)
{
dboffset = fprintf(newrefs, "cscope %d %s", FILEVERSION, dir);
if (compress == NO) {
dboffset += fprintf(newrefs, " -c");
}
if (invertedindex == YES) {
dboffset += fprintf(newrefs, " -q %.10ld", totalterms);
}
else {
dboffset += fprintf(newrefs, " ");
}
if (trun_syms == YES) {
dboffset += fprintf(newrefs, " -T");
}
dboffset += fprintf(newrefs, " %.10ld\n", traileroffset);
#if BSD && !sun
dboffset = ftell(newrefs);
#endif
}
void
putlist(char **names, int count)
{
int i, size = 0;
(void) fprintf(newrefs, "%d\n", count);
if (names == srcfiles) {
for (i = 0; i < count; ++i) {
size += strlen(names[i]) + 1;
}
(void) fprintf(newrefs, "%d\n", size);
}
for (i = 0; i < count; ++i) {
if (fputs(names[i], newrefs) == EOF ||
putc('\n', newrefs) == EOF) {
cannotwrite(newreffile);
}
}
}
BOOL
samelist(FILE *oldrefs, char **names, int count)
{
char oldname[PATHLEN + 1];
int oldcount;
int i;
if (fscanf(oldrefs, "%d", &oldcount) != 1 ||
oldcount != count) {
return(NO);
}
for (i = 0; i < count; ++i) {
if (fscanf(oldrefs, "%s", oldname) != 1 ||
strnotequal(oldname, names[i])) {
return(NO);
}
}
return(YES);
}
void
skiplist(FILE *oldrefs)
{
int i;
if (fscanf(oldrefs, "%d", &i) != 1) {
posterr("cscope: cannot read list size from file %s\n", reffile);
exit(1);
}
while (--i >= 0) {
if (fscanf(oldrefs, "%*s") != 0) {
posterr("cscope: cannot read list name from file %s\n", reffile);
exit(1);
}
}
}
void
copydata(void)
{
char symbol[PATLEN + 1];
char *cp;
setmark('\t');
cp = blockp;
for (;;) {
do {
while (*cp != '\t') {
dbputc(*cp++);
}
} while (*++cp == '\0' && (cp = readblock()) != NULL);
dbputc('\t');
if (*(cp + 1) == '\0') {
cp = readblock();
}
if (cp == NULL || *cp == NEWFILE) {
break;
}
if (*cp == INCLUDE) {
blockp = cp;
putinclude(symbol);
writestring(symbol);
setmark('\t');
cp = blockp;
}
}
blockp = cp;
}
void
copyinverted(void)
{
char *cp;
char c;
int type;
char symbol[PATLEN + 1];
cp = blockp;
for (;;) {
setmark('\n');
do {
while (*cp != '\n') {
dbputc(*cp++);
}
} while (*++cp == '\0' && (cp = readblock()) != NULL);
dbputc('\n');
if (*(cp + 1) == '\0') {
cp = readblock();
}
if (cp == NULL) {
break;
}
switch (*cp) {
case '\n':
lineoffset = dboffset + 1;
continue;
case '\t':
dbputc('\t');
blockp = cp;
type = getrefchar();
switch (type) {
case NEWFILE:
return;
case INCLUDE:
putinclude(symbol);
goto output;
}
dbputc(type);
skiprefchar();
putstring(symbol);
goto output;
}
c = *cp;
if (c & 0200) {
c = dichar1[(c & 0177) / 8];
}
if (isalpha((unsigned char)c) || c == '_') {
blockp = cp;
putstring(symbol);
type = ' ';
output:
putposting(symbol, type);
writestring(symbol);
if (blockp == NULL) {
return;
}
cp = blockp;
}
}
blockp = cp;
}
void
putinclude(char *s)
{
dbputc(INCLUDE);
skiprefchar();
putstring(s);
incfile(s + 1, s);
}
void
movefile(char *new, char *old)
{
(void) unlink(old);
if (rename(new, old) == -1) {
(void) myperror("cscope");
posterr("cscope: cannot rename file %s to file %s\n",
new, old);
myexit(1);
}
}
void
entercurses(void)
{
incurses = YES;
#ifndef __MSDOS__
(void) nonl();
#endif
(void) cbreak();
(void) noecho();
(void) clear();
mouseinit();
drawscrollbar(topline, nextline);
}
void
exitcurses(void)
{
(void) move(LINES - 1, 0);
(void) clrtoeol();
(void) refresh();
(void) endwin();
incurses = NO;
mousecleanup();
(void) fflush(stdout);
}
static void
usage(void)
{
(void) fprintf(stderr, "Usage: cscope [-bcCdehklLqRTuUV] [-f file] [-F file] [-i file] [-I dir] [-s dir]\n");
(void) fprintf(stderr, " [-p number] [-P path] [-[0-8] pattern] [source files]\n");
}
static void
longusage(void)
{
(void) usage();
(void) fprintf(stderr, "\n");
(void) fprintf(stderr, "-b Build the cross-reference only.\n");
(void) fprintf(stderr, "-C Ignore letter case when searching.\n");
(void) fprintf(stderr, "-c Use only ASCII characters in the cross-ref file (don't compress).\n");
(void) fprintf(stderr, "-d Do not update the cross-reference.\n");
(void) fprintf(stderr, "-e Suppress the <Ctrl>-e command prompt between files.\n");
(void) fprintf(stderr, "-F symfile Read symbol reference lines from symfile.\n");
(void) fprintf(stderr, "-f reffile Use reffile as cross-ref file name instead of %s.\n", REFFILE);
(void) fprintf(stderr, "-h This help screen.\n");
(void) fprintf(stderr, "-I incdir Look in incdir for any #include files.\n");
(void) fprintf(stderr, "-i namefile Browse through files listed in namefile, instead of %s\n", NAMEFILE);
(void) fprintf(stderr, "-k Kernel Mode - don't use %s for #include files.\n", DFLT_INCDIR);
(void) fprintf(stderr, "-L Do a single search with line-oriented output.\n");
(void) fprintf(stderr, "-l Line-oriented interface.\n");
(void) fprintf(stderr, "-num pattern Go to input field num (counting from 0) and find pattern.\n");
(void) fprintf(stderr, "-P path Prepend path to relative file names in pre-built cross-ref file.\n");
(void) fprintf(stderr, "-p n Display the last n file path components.\n");
(void) fprintf(stderr, "-q Build an inverted index for quick symbol searching.\n");
(void) fprintf(stderr, "-R Recurse directories for files.\n");
(void) fprintf(stderr, "-s dir Look in dir for additional source files.\n");
(void) fprintf(stderr, "-T Use only the first eight characters to match against C symbols.\n");
(void) fprintf(stderr, "-U Check file time stamps.\n");
(void) fprintf(stderr, "-u Unconditionally build the cross-reference file.\n");
(void) fprintf(stderr, "-V Print the version number.\n");
(void) fprintf(stderr, "\n");
(void) fprintf(stderr, "Please see the manpage for more information.\n");
}
void
myexit(int sig)
{
if (refsfound != NULL)
fclose(refsfound);
if (temp1[0] != '\0') {
(void) unlink(temp1);
(void) unlink(temp2);
}
if (incurses == YES) {
exitcurses();
}
if (sig == SIGQUIT) {
(void) abort();
}
freefilelist();
freeinclist();
freesrclist();
freecrossref();
free(newinvname);
free(newinvpost);
free(newreffile);
exit(sig);
}