static void putinclude(char *s) { dbputc(INCLUDE); skiprefchar(); getstring(s); incfile(s + 1, *s); }
static void copydata(void) { char symbol[PATLEN + 1]; char *cp; setmark('\t'); cp = blockp; for (;;) { /* copy up to the next \t */ do { /* innermost loop optimized to only one test */ while (*cp != '\t') { dbputc(*cp++); } } while (*++cp == '\0' && (cp = readblock()) != NULL); dbputc('\t'); /* copy the tab */ /* get the next character */ if (*(cp + 1) == '\0') { cp = readblock(); } /* exit if at the end of this file's data */ if (cp == NULL || *cp == NEWFILE) { break; } /* look for an #included file */ if (*cp == INCLUDE) { blockp = cp; putinclude(symbol); putstring(symbol); setmark('\t'); cp = blockp; } } blockp = cp; }
void writestring(char *s) { unsigned char c; int i; if (compress == NO) { /* Save some I/O overhead by using puts() instead of putc(): */ dbfputs(s); return; } /* compress digraphs */ for (i = 0; (c = s[i]) != '\0'; ++i) { if (/* dicode1[c] && dicode2[(unsigned char) s[i + 1]] */ IS_A_DICODE(c, s[i + 1])) { /* c = (0200 - 2) + dicode1[c] + dicode2[(unsigned char) s[i + 1]]; */ c = DICODE_COMPRESS(c, s[i + 1]); ++i; } dbputc(c); } }
void crossref(char *srcfile) { unsigned int i; unsigned int length; /* symbol length */ unsigned int entry_no; /* function level of the symbol */ int token; /* current token */ struct stat st; if (! ((stat(srcfile, &st) == 0) && S_ISREG(st.st_mode))) { cannotopen(srcfile); errorsfound = YES; return; } entry_no = 0; /* open the source file */ if ((yyin = myfopen(srcfile, "r")) == NULL) { cannotopen(srcfile); errorsfound = YES; return; } filename = srcfile; /* save the file name for warning messages */ putfilename(srcfile); /* output the file name */ dbputc('\n'); dbputc('\n'); /* read the source file */ initscanner(srcfile); fcnoffset = macrooffset = 0; symbols = 0; if (symbol == NULL) { symbol = mymalloc(msymbols * sizeof(struct symbol)); } for (;;) { /* get the next token */ switch (token = yylex()) { default: /* if requested, truncate C symbols */ length = last - first; if (trun_syms == YES && length > 8 && token != INCLUDE && token != NEWFILE) { length = 8; last = first + 8; } /* see if the token has a symbol */ if (length == 0) { savesymbol(token, entry_no); break; } /* update entry_no if see function entry */ if (token == FCNDEF) { entry_no++; } /* see if the symbol is already in the list */ for (i = 0; i < symbols; ++i) { if (length == symbol[i].length && strncmp(my_yytext + first, my_yytext + symbol[i].first, length) == 0 && entry_no == symbol[i].fcn_level && token == symbol[i].type ) { /* could be a::a() */ break; } } if (i == symbols) { /* if not already in list */ savesymbol(token, entry_no); } break; case NEWLINE: /* end of line containing symbols */ entry_no = 0; /* reset entry_no for each line */ #ifdef USING_LEX --yyleng; /* remove the newline */ #endif putcrossref(); /* output the symbols and source line */ lineno = myylineno; /* save the symbol line number */ #ifndef USING_LEX /* HBB 20010425: replaced yyleng-- by this chunk: */ if (my_yytext) *my_yytext = '\0'; my_yyleng = 0; #endif break; case LEXERR: /* Lexer error, abort further parsing of this file */ case LEXEOF: /* end of file; last line may not have \n */ /* if there were symbols, output them and the source line */ if (symbols > 0) { putcrossref(); } (void) fclose(yyin); /* close the source file */ /* output the leading tab expected by the next call */ dbputc('\t'); return; } } }
static void putcrossref(void) { unsigned int i, j; unsigned char c; BOOL blank; /* blank indicator */ unsigned int symput = 0; /* symbols output */ int type; /* output the source line */ lineoffset = dboffset; dboffset += fprintf(newrefs, "%d ", lineno); #ifdef PRINTF_RETVAL_BROKEN dboffset = ftell(newrefs); /* fprintf doesn't return chars written */ #endif /* HBB 20010425: added this line: */ my_yytext[my_yyleng] = '\0'; blank = NO; for (i = 0; i < my_yyleng; ++i) { /* change a tab to a blank and compress blanks */ if ((c = my_yytext[i]) == ' ' || c == '\t') { blank = YES; } else if (symput < symbols && i == symbol[symput].first) { /* look for the start of a symbol */ /* check for compressed blanks */ if (blank == YES) { blank = NO; dbputc(' '); } dbputc('\n'); /* symbols start on a new line */ /* output any symbol type */ if ((type = symbol[symput].type) != IDENT) { dbputc('\t'); dbputc(type); } else { type = ' '; } /* output the symbol */ j = symbol[symput].last; c = my_yytext[j]; my_yytext[j] = '\0'; if (invertedindex == YES) { putposting(my_yytext + i, type); } writestring(my_yytext + i); dbputc('\n'); my_yytext[j] = c; i = j - 1; ++symput; } else { /* HBB: try to save some time by early-out handling of * non-compressed mode */ if (compress == NO) { if (blank == YES) { dbputc(' '); blank = NO; } j = i + strcspn(my_yytext+i, "\t "); if (symput < symbols && j >= symbol[symput].first) j = symbol[symput].first; c = my_yytext[j]; my_yytext[j] = '\0'; writestring(my_yytext + i); my_yytext[j] = c; i = j - 1; /* finished this 'i', continue with the blank */ continue; } /* check for compressed blanks */ if (blank == YES) { if (dicode2[c]) { c = DICODE_COMPRESS(' ', c); } else { dbputc(' '); } } else if (IS_A_DICODE(c, my_yytext[i + 1]) && symput < symbols && i + 1 != symbol[symput].first) { /* compress digraphs */ c = DICODE_COMPRESS(c, my_yytext[i + 1]); ++i; } dbputc((int) c); blank = NO; /* skip compressed characters */ if (c < ' ') { ++i; /* skip blanks before a preprocesor keyword */ /* note: don't use isspace() because \f and \v are used for keywords */ while ((j = my_yytext[i]) == ' ' || j == '\t') { ++i; } /* skip the rest of the keyword */ while (isalpha((unsigned char)my_yytext[i])) { ++i; } /* skip space after certain keywords */ if (keyword[c].delim != '\0') { while ((j = my_yytext[i]) == ' ' || j == '\t') { ++i; } } /* skip a '(' after certain keywords */ if (keyword[c].delim == '(' && my_yytext[i] == '(') { ++i; } --i; /* compensate for ++i in for() */ } /* if compressed char */ } /* else: not a symbol */ } /* for(i) */ /* ignore trailing blanks */ dbputc('\n'); dbputc('\n'); /* output any #define end marker */ /* note: must not be part of #define so putsource() doesn't discard it so findcalledbysub() can find it and return */ if (symput < symbols && symbol[symput].type == DEFINEEND) { dbputc('\t'); dbputc(DEFINEEND); dbputc('\n'); dbputc('\n'); /* mark beginning of next source line */ macrooffset = 0; } symbols = 0; }
static void build(void) { int i; FILE *oldrefs; /* old cross-reference file */ time_t reftime; /* old crossref modification time */ char *file; /* current file */ char *oldfile; /* file in old cross-reference */ char newdir[PATHLEN + 1]; /* directory in new cross-reference */ char olddir[PATHLEN + 1]; /* directory in old cross-reference */ char oldname[PATHLEN + 1]; /* name in old cross-reference */ int oldnum; /* number in old cross-ref */ struct stat statstruct; /* file status */ int firstfile; /* first source file in pass */ int lastfile; /* last source file in pass */ int built = 0; /* built crossref for these files */ int copied = 0; /* copied crossref for these files */ BOOL interactive = YES; /* output progress messages */ /* * normalize the current directory relative to the home directory so * the cross-reference is not rebuilt when the user's login is moved */ (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)); } /* sort the source file names (needed for rebuilding) */ qsort((char *)srcfiles, (unsigned)nsrcfiles, sizeof (char *), compare); /* * if there is an old cross-reference and its current directory * matches or this is an unconditional build */ if ((oldrefs = vpfopen(reffile, "r")) != NULL && unconditional == NO && fscanf(oldrefs, "cscope %d %s", &fileversion, olddir) == 2 && (strcmp(olddir, currentdir) == 0 || /* remain compatible */ strcmp(olddir, newdir) == 0)) { /* get the cross-reference file's modification time */ (void) fstat(fileno(oldrefs), &statstruct); reftime = statstruct.st_mtime; if (fileversion >= 8) { BOOL oldcompress = YES; BOOL oldinvertedindex = NO; BOOL oldtruncatesyms = NO; int c; /* see if there are options in the database */ for (;;) { while ((c = getc(oldrefs)) == ' ') { } if (c != '-') { (void) ungetc(c, oldrefs); break; } switch (c = getc(oldrefs)) { case 'c': /* ASCII characters only */ oldcompress = NO; break; case 'q': /* quick search */ oldinvertedindex = YES; (void) fscanf(oldrefs, "%ld", &totalterms); break; case 'T': /* truncate symbols to 8 characters */ oldtruncatesyms = YES; break; } } /* check the old and new option settings */ if (oldcompress != compress || oldtruncatesyms != truncatesyms) { (void) fprintf(stderr, "cscope: -c or -T option mismatch between " "command line and old symbol database\n"); goto force; } if (oldinvertedindex != invertedindex) { (void) fprintf(stderr, "cscope: -q option mismatch between " "command line and old symbol database\n"); if (invertedindex == NO) { removeindex(); } goto outofdate; } /* seek to the trailer */ if (fscanf(oldrefs, "%ld", &traileroffset) != 1 || fseek(oldrefs, traileroffset, 0) == -1) { (void) fprintf(stderr, "cscope: incorrect symbol database file " "format\n"); goto force; } } /* if assuming that some files have changed */ if (fileschanged == YES) { goto outofdate; } /* see if the view path is the same */ if (fileversion >= 13 && samelist(oldrefs, vpdirs, vpndirs) == NO) { goto outofdate; } /* see if the directory lists are the same */ if (samelist(oldrefs, srcdirs, nsrcdirs) == NO || samelist(oldrefs, incdirs, nincdirs) == NO || fscanf(oldrefs, "%d", &oldnum) != 1 || fileversion >= 9 && fscanf(oldrefs, "%*s") != 0) { /* skip the string space size */ goto outofdate; } /* * see if the list of source files is the same and * none have been changed up to the included files */ for (i = 0; i < nsrcfiles; ++i) { if (fscanf(oldrefs, "%s", oldname) != 1 || strnotequal(oldname, srcfiles[i]) || vpstat(srcfiles[i], &statstruct) != 0 || statstruct.st_mtime > reftime) { goto outofdate; } } /* the old cross-reference is up-to-date */ /* so get the list of included files */ while (i++ < oldnum && fscanf(oldrefs, "%s", oldname) == 1) { addsrcfile(oldname); } (void) fclose(oldrefs); return; outofdate: /* if the database format has changed, rebuild it all */ if (fileversion != FILEVERSION) { (void) fprintf(stderr, "cscope: converting to new symbol database file " "format\n"); goto force; } /* reopen the old cross-reference file for fast scanning */ if ((symrefs = vpopen(reffile, O_RDONLY)) == -1) { cannotopen(reffile); myexit(1); } /* get the first file name in the old cross-reference */ blocknumber = -1; (void) readblock(); /* read the first cross-ref block */ (void) scanpast('\t'); /* skip the header */ oldfile = getoldfile(); } else { /* force cross-referencing of all the source files */ force: reftime = 0; oldfile = NULL; } /* open the new cross-reference file */ if ((newrefs = fopen(newreffile, "w")) == NULL) { cannotopen(newreffile); myexit(1); } if (invertedindex == YES && (postings = fopen(temp1, "w")) == NULL) { cannotopen(temp1); cannotindex(); } (void) fprintf(stderr, "cscope: building symbol database\n"); putheader(newdir); fileversion = FILEVERSION; if (buildonly == YES && !isatty(0)) { interactive = NO; } else { initprogress(); } /* output the leading tab expected by crossref() */ dbputc('\t'); /* * make passes through the source file list until the last level of * included files is processed */ firstfile = 0; lastfile = nsrcfiles; if (invertedindex == YES) { srcoffset = mymalloc((nsrcfiles + 1) * sizeof (long)); } for (;;) { /* get the next source file name */ for (fileindex = firstfile; fileindex < lastfile; ++fileindex) { /* display the progress about every three seconds */ if (interactive == YES && fileindex % 10 == 0) { if (copied == 0) { progress("%ld files built", (long)built, 0L); } else { progress("%ld files built, %ld " "files copied", (long)built, (long)copied); } } /* if the old file has been deleted get the next one */ file = srcfiles[fileindex]; while (oldfile != NULL && strcmp(file, oldfile) > 0) { oldfile = getoldfile(); } /* * if there isn't an old database or this is * a new file */ if (oldfile == NULL || strcmp(file, oldfile) < 0) { crossref(file); ++built; } else if (vpstat(file, &statstruct) == 0 && statstruct.st_mtime > reftime) { /* if this file was modified */ crossref(file); ++built; /* * skip its old crossref so modifying the last * source file does not cause all included files * to be built. Unfortunately a new file that * is alphabetically last will cause all * included files to be built, but this is * less likely */ oldfile = getoldfile(); } else { /* copy its cross-reference */ putfilename(file); if (invertedindex == YES) { copyinverted(); } else { copydata(); } ++copied; oldfile = getoldfile(); } } /* see if any included files were found */ if (lastfile == nsrcfiles) { break; } firstfile = lastfile; lastfile = nsrcfiles; if (invertedindex == YES) { srcoffset = myrealloc(srcoffset, (nsrcfiles + 1) * sizeof (long)); } /* sort the included file names */ qsort((char *)&srcfiles[firstfile], (unsigned)(lastfile - firstfile), sizeof (char *), compare); } /* add a null file name to the trailing tab */ putfilename(""); dbputc('\n'); /* get the file trailer offset */ traileroffset = dboffset; /* * output the view path and source and include directory and * file lists */ putlist(vpdirs, vpndirs); putlist(srcdirs, nsrcdirs); putlist(incdirs, nincdirs); putlist(srcfiles, nsrcfiles); if (fflush(newrefs) == EOF) { /* rewind doesn't check for write failure */ cannotwrite(newreffile); /* NOTREACHED */ } /* create the inverted index if requested */ if (invertedindex == YES) { char sortcommand[PATHLEN + 1]; if (fflush(postings) == EOF) { cannotwrite(temp1); /* NOTREACHED */ } (void) fstat(fileno(postings), &statstruct); (void) fprintf(stderr, "cscope: building symbol index: temporary file size is " "%ld bytes\n", statstruct.st_size); (void) fclose(postings); /* * sort -T is broken until it is fixed we don't have too much choice */ /* * (void) sprintf(sortcommand, "sort -y -T %s %s", tmpdir, temp1); */ (void) sprintf(sortcommand, "LC_ALL=C sort %s", temp1); if ((postings = popen(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(); } (void) pclose(postings); } (void) unlink(temp1); (void) free(srcoffset); (void) fprintf(stderr, "cscope: index has %ld references to %ld symbols\n", npostings, totalterms); } /* rewrite the header with the trailer offset and final option list */ rewind(newrefs); putheader(newdir); (void) fclose(newrefs); /* close the old database file */ if (symrefs >= 0) { (void) close(symrefs); } if (oldrefs != NULL) { (void) fclose(oldrefs); } /* replace it with the new database file */ movefile(newreffile, reffile); }
static void copyinverted(void) { char *cp; int c; int type; /* reference type (mark character) */ char symbol[PATLEN + 1]; /* note: this code was expanded in-line for speed */ /* while (scanpast('\n') != NULL) { */ /* other macros were replaced by code using cp instead of blockp */ cp = blockp; for (;;) { setmark('\n'); do { /* innermost loop optimized to only one test */ while (*cp != '\n') { dbputc(*cp++); } } while (*++cp == '\0' && (cp = readblock()) != NULL); dbputc('\n'); /* copy the newline */ /* get the next character */ if (*(cp + 1) == '\0') { cp = readblock(); } /* exit if at the end of this file's data */ if (cp == NULL) { break; } switch (*cp) { case '\n': lineoffset = dboffset + 1; continue; case '\t': dbputc('\t'); blockp = cp; type = getrefchar(); switch (type) { case NEWFILE: /* file name */ return; case INCLUDE: /* #included file */ putinclude(symbol); goto output; } dbputc(type); skiprefchar(); getstring(symbol); goto output; } c = *cp; if (c & 0200) { /* digraph char? */ c = dichar1[(c & 0177) / 8]; } /* if this is a symbol */ if (isalpha(c) || c == '_') { blockp = cp; getstring(symbol); type = ' '; output: putposting(symbol, type); putstring(symbol); if (blockp == NULL) { return; } cp = blockp; } } blockp = cp; }