#include "global.h"
#include "build.h"
#include "scanner.h"
#include <stdlib.h>
#include <sys/stat.h>
static char const rcsid[] = "$Id: crossref.c,v 1.2 2004/07/09 21:34:44 nicolai Exp $";
#define ltobase(value) n = value; \
s = buf + (sizeof(buf) - 1); \
*s = '\0'; \
digits = 1; \
while (n >= BASE) { \
++digits; \
i = n; \
n /= BASE; \
*--s = i - n * BASE + '!'; \
} \
*--s = n + '!';
#define SYMBOLINC 20
long dboffset;
BOOL errorsfound;
long lineoffset;
long npostings;
int nsrcoffset;
long *srcoffset;
int symbols;
static char *filename;
static long fcnoffset;
static long macrooffset;
static int msymbols = SYMBOLINC;
struct symbol {
int type;
int first;
int last;
int length;
int fcn_level;
};
static struct symbol *symbol;
static void putcrossref(void);
static void savesymbol(int token, int num);
void
crossref(char *srcfile)
{
int i;
int length;
int entry_no;
int token;
struct stat st;
if (! ((stat(srcfile, &st) == 0)
&& S_ISREG(st.st_mode))) {
cannotopen(srcfile);
errorsfound = YES;
return;
}
entry_no = 0;
if ((yyin = myfopen(srcfile, "r")) == NULL) {
cannotopen(srcfile);
errorsfound = YES;
return;
}
filename = srcfile;
putfilename(srcfile);
dbputc('\n');
dbputc('\n');
initscanner(srcfile);
fcnoffset = macrooffset = 0;
symbols = 0;
if (symbol == NULL) {
symbol = mymalloc(msymbols * sizeof(struct symbol));
}
for (;;) {
switch (token = yylex()) {
default:
length = last - first;
if (trun_syms == YES && length > 8 &&
token != INCLUDE && token != NEWFILE) {
length = 8;
last = first + 8;
}
if (length == 0) {
savesymbol(token, entry_no);
break;
}
if (token == FCNDEF) {
entry_no++;
}
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
) {
break;
}
}
if (i == symbols) {
savesymbol(token, entry_no);
}
break;
case NEWLINE:
entry_no = 0;
#ifdef USING_LEX
--yyleng;
#endif
putcrossref();
lineno = myylineno;
#ifndef USING_LEX
if (my_yytext)
*my_yytext = '\0';
my_yyleng = 0;
#endif
break;
case LEXEOF:
if (symbols > 0) {
putcrossref();
}
(void) fclose(yyin);
dbputc('\t');
return;
}
}
}
static void
savesymbol(int token, int num)
{
if (symbols == msymbols) {
msymbols += SYMBOLINC;
symbol = myrealloc(symbol,
msymbols * sizeof(struct symbol));
}
symbol[symbols].type = token;
symbol[symbols].first = first;
symbol[symbols].last = last;
symbol[symbols].length = last - first;
symbol[symbols].fcn_level = num;
++symbols;
}
void
putfilename(char *srcfile)
{
if (putc(NEWFILE, newrefs) == EOF) {
cannotwrite(newreffile);
}
++dboffset;
if (invertedindex == YES) {
srcoffset[nsrcoffset++] = dboffset;
}
dbfputs(srcfile);
fcnoffset = macrooffset = 0;
}
static void
putcrossref(void)
{
int i, j;
unsigned char c;
BOOL blank;
int symput = 0;
int type;
lineoffset = dboffset;
dboffset += fprintf(newrefs, "%d ", lineno);
#ifdef PRINTF_RETVAL_BROKEN
dboffset = ftell(newrefs);
#endif
my_yytext[my_yyleng] = '\0';
blank = NO;
for (i = 0; i < my_yyleng; ++i) {
if ((c = my_yytext[i]) == ' ' || c == '\t') {
blank = YES;
}
else if (symput < symbols && i == symbol[symput].first) {
if (blank == YES) {
blank = NO;
dbputc(' ');
}
dbputc('\n');
if ((type = symbol[symput].type) != IDENT) {
dbputc('\t');
dbputc(type);
}
else {
type = ' ';
}
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 {
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;
continue;
}
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
) {
c = DICODE_COMPRESS(c, my_yytext[i + 1]);
++i;
}
dbputc((int) c);
blank = NO;
if (c < ' ') {
++i;
while ((j = my_yytext[i]) == ' ' || j == '\t') {
++i;
}
while (isalpha((unsigned char)my_yytext[i])) {
++i;
}
if (keyword[c].delim != '\0') {
while ((j = my_yytext[i]) == ' ' || j == '\t') {
++i;
}
}
if (keyword[c].delim == '('
&& my_yytext[i] == '(') {
++i;
}
--i;
}
}
}
dbputc('\n');
dbputc('\n');
if (symput < symbols && symbol[symput].type == DEFINEEND) {
dbputc('\t');
dbputc(DEFINEEND);
dbputc('\n');
dbputc('\n');
macrooffset = 0;
}
symbols = 0;
}
void
freecrossref()
{
if (symbol)
free(symbol);
symbol = NULL;
symbols = 0;
}
void
putposting(char *term, int type)
{
long i, n;
char *s;
int digits;
long offset;
char buf[11];
offset = fcnoffset;
if (macrooffset != 0) {
offset = macrooffset;
}
switch (type) {
case DEFINE:
macrooffset = dboffset;
break;
case DEFINEEND:
macrooffset = 0;
return;
case FCNDEF:
fcnoffset = dboffset;
break;
case FCNEND:
fcnoffset = 0;
return;
}
if (*term == '\0') {
return;
}
if (type == INCLUDE) {
++term;
}
(void) fputs(term, postings);
(void) putc(' ', postings);
ltobase(lineoffset);
for (i = PRECISION - digits; i > 0; --i) {
(void) putc('!', postings);
}
do {
(void) putc(*s, postings);
} while (*++s != '\0');
(void) putc(type, postings);
if (offset > 0) {
(void) putc(' ', postings);
ltobase(offset);
do {
(void) putc(*s, postings);
} while (*++s != '\0');
}
if (putc('\n', postings) == EOF) {
cannotwrite(temp1);
}
++npostings;
}
void
writestring(char *s)
{
unsigned char c;
int i;
if (compress == NO) {
dbfputs(s);
return;
}
for (i = 0; (c = s[i]) != '\0'; ++i) {
if (
IS_A_DICODE(c, s[i + 1])) {
c = DICODE_COMPRESS(c, s[i + 1]);
++i;
}
dbputc(c);
}
}
void
warning(char *text)
{
(void) fprintf(stderr, "cscope: \"%s\", line %d: warning: %s\n", filename,
myylineno, text);
errorsfound = YES;
}