4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
22 /* Copyright (c) 1988 AT&T */
23 /* All Rights Reserved */
27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 #pragma ident "%Z%%M% %I% %E% SMI"
34 * cscope - interactive C symbol cross-reference
36 * build cross-reference file
41 /* convert long to a string */
42 #define ltobase(value) n = value; \
43 s = buf + (sizeof (buf) - 1); \
50 *--s = i - n * BASE + '!'; \
54 #define SYMBOLINC 20 /* symbol list size increment */
55 #define FREAD "r" /* fopen for reading */
57 long dboffset
; /* new database offset */
58 BOOL errorsfound
; /* prompt before clearing messages */
59 long fileindex
; /* source file name index */
60 long lineoffset
; /* source line database offset */
61 long npostings
; /* number of postings */
62 int nsrcoffset
; /* number of file name database offsets */
63 long *srcoffset
; /* source file name database offsets */
64 int symbols
; /* number of symbols */
66 static char *filename
; /* file name for warning messages */
67 static long fcnoffset
; /* function name database offset */
68 static long macrooffset
; /* macro name database offset */
69 static int msymbols
= SYMBOLINC
; /* maximum number of symbols */
70 static struct symbol
{ /* symbol data */
72 int first
; /* index of first character in text */
73 int last
; /* index of last+1 character in text */
74 int length
; /* symbol length */
77 static void putcrossref(void);
80 crossref(char *srcfile
)
83 int length
; /* symbol length */
84 int token
; /* current token */
86 /* open the source file */
87 if ((yyin
= vpfopen(srcfile
, FREAD
)) == NULL
) {
92 filename
= srcfile
; /* save the file name for warning messages */
93 putfilename(srcfile
); /* output the file name */
97 /* read the source file */
99 fcnoffset
= macrooffset
= 0;
101 if (symbol
== NULL
) {
102 symbol
= mymalloc(msymbols
* sizeof (struct symbol
));
106 /* get the next token */
107 switch (token
= yylex()) {
109 /* if requested, truncate C symbols */
110 length
= last
- first
;
111 if (truncatesyms
&& length
> 8 &&
112 token
!= INCLUDE
&& token
!= NEWFILE
) {
116 /* see if the token has a symbol */
121 /* see if the symbol is already in the list */
122 for (i
= 0; i
< symbols
; ++i
) {
123 if (length
== symbol
[i
].length
&&
124 strncmp(yytext
+ first
, yytext
+
125 symbol
[i
].first
, length
) == 0 &&
127 token
== symbol
[i
].type
)) {
132 if (i
== symbols
) { /* if not already in list */
137 case NEWLINE
: /* end of line containing symbols */
138 --yyleng
; /* remove the newline */
139 putcrossref(); /* output the symbols and source line */
140 lineno
= yylineno
; /* save the symbol line number */
143 case LEXEOF
: /* end of file; last line may not have \n */
146 * if there were symbols, output them and the
152 (void) fclose(yyin
); /* close the source file */
154 /* output the leading tab expected by the next call */
161 /* save the symbol in the list */
164 savesymbol(int token
)
166 /* make sure there is room for the symbol */
167 if (symbols
== msymbols
) {
168 msymbols
+= SYMBOLINC
;
169 symbol
= (struct symbol
*)myrealloc(symbol
,
170 msymbols
* sizeof (struct symbol
));
172 /* save the symbol */
173 symbol
[symbols
].type
= token
;
174 symbol
[symbols
].first
= first
;
175 symbol
[symbols
].last
= last
;
176 symbol
[symbols
].length
= last
- first
;
181 /* output the file name */
184 putfilename(char *srcfile
)
186 /* check for file system out of space */
187 /* note: dbputc is not used to avoid lint complaint */
188 if (putc(NEWFILE
, newrefs
) == EOF
) {
189 cannotwrite(newreffile
);
194 srcoffset
[nsrcoffset
++] = dboffset
;
197 fcnoffset
= macrooffset
= 0;
200 /* output the symbols and source line */
207 BOOL blank
= NO
; /* output blank */
208 BOOL newline
= NO
; /* output newline */
209 int symput
= 0; /* symbols output */
212 /* output the source line */
213 lineoffset
= dboffset
;
214 dbfprintf(newrefs
, "%d ", lineno
);
215 for (i
= 0; i
< yyleng
; ++i
) {
217 /* change a tab to a blank and compress blanks */
218 if ((c
= yytext
[i
]) == ' ' || c
== '\t') {
221 /* look for the start of a symbol */
222 else if (symput
< symbols
&& i
== symbol
[symput
].first
) {
224 /* check for compressed blanks */
232 dbputc('\n'); /* symbols start on a new line */
234 /* output any symbol type */
235 if ((type
= symbol
[symput
].type
) != IDENT
) {
241 /* output the symbol */
242 j
= symbol
[symput
].last
;
246 putposting(yytext
+ i
, type
);
248 putstring(yytext
+ i
);
258 /* check for compressed blanks */
261 c
= (0200 - 2) + dicode1
[' '] +
266 } else if (dicode1
[c
] &&
267 (j
= dicode2
[(unsigned)yytext
[i
+ 1]]) != 0 &&
268 symput
< symbols
&& i
+ 1 != symbol
[symput
].first
) {
269 /* compress digraphs */
270 c
= (0200 - 2) + dicode1
[c
] + j
;
274 * if the last line of the file is a '}' without a
275 * newline, the lex EOF code overwrites it with a 0
284 /* skip compressed characters */
288 /* skip blanks before a preprocesor keyword */
290 * note: don't use isspace() because \f and \v
291 * are used for keywords
293 while ((j
= yytext
[i
]) == ' ' || j
== '\t') {
296 /* skip the rest of the keyword */
297 while (isalpha(yytext
[i
])) {
300 /* skip space after certain keywords */
301 if (keyword
[c
].delim
!= '\0') {
302 while ((j
= yytext
[i
]) == ' ' ||
307 /* skip a '(' after certain keywords */
308 if (keyword
[c
].delim
== '(' &&
312 --i
; /* compensate for ++i in for() */
316 /* ignore trailing blanks */
320 /* output any #define end marker */
322 * note: must not be part of #define so putsource() doesn't discard it
323 * so findcalledbysub() can find it and return
325 if (symput
< symbols
&& symbol
[symput
].type
== DEFINEEND
) {
329 dbputc('\n'); /* mark beginning of next source line */
335 /* output the inverted index posting */
338 putposting(char *term
, int type
)
342 int digits
; /* digits output */
343 long offset
; /* function/macro database offset */
344 char buf
[11]; /* number buffer */
346 /* get the function or macro name offset */
348 if (macrooffset
!= 0) {
349 offset
= macrooffset
;
351 /* then update them to avoid negative relative name offset */
354 macrooffset
= dboffset
;
358 return; /* null term */
360 fcnoffset
= dboffset
;
364 return; /* null term */
366 /* ignore a null term caused by a enum/struct/union without a tag */
370 /* skip any #include secondary type char (< or ") */
371 if (type
== INCLUDE
) {
375 * output the posting, which should be as small as possible to reduce
376 * the temp file size and sort time
378 (void) fputs(term
, postings
);
379 (void) putc(' ', postings
);
382 * the line offset is padded so postings for the same term will sort
383 * in ascending line offset order to order the references as they
384 * appear withing a source file
387 for (i
= PRECISION
- digits
; i
> 0; --i
) {
388 (void) putc('!', postings
);
391 (void) putc(*s
, postings
);
392 } while (*++s
!= '\0');
394 /* postings are also sorted by type */
395 (void) putc(type
, postings
);
397 /* function or macro name offset */
399 (void) putc(' ', postings
);
402 (void) putc(*s
, postings
);
403 } while (*++s
!= '\0');
405 if (putc('\n', postings
) == EOF
) {
412 /* put the string into the new database */
420 /* compress digraphs */
421 for (i
= 0; (c
= s
[i
]) != '\0'; ++i
) {
422 if (dicode1
[c
] && dicode2
[(unsigned)s
[i
+ 1]]) {
423 c
= (0200 - 2) + dicode1
[c
] +
424 dicode2
[(unsigned)s
[i
+ 1]];
431 /* print a warning message with the file name and line number */
439 (void) fprintf(stderr
, "cscope: \"%s\", line %d: warning: %s\n",
440 filename
, yylineno
, text
);