Esempio n. 1
0
static void
putinclude(char *s)
{
	dbputc(INCLUDE);
	skiprefchar();
	getstring(s);
	incfile(s + 1, *s);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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);	
	}
}
Esempio n. 4
0
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;
	}
    }
}
Esempio n. 5
0
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;
}
Esempio n. 6
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);
}
Esempio n. 7
0
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;
}