1 | /***************************************
2 | $Header: /home/amb/CVS/cxref/src/xref.c,v 1.21 2002-06-23 15:57:36 amb Exp $
3 |
4 | C Cross Referencing & Documentation tool. Version 1.5e.
5 |
6 | Cross referencing of functions.
7 | ******************/ /******************
8 | Written by Andrew M. Bishop
9 |
10 | This file Copyright 1995,96,97,98,99,2000,01,02 Andrew M. Bishop
11 | It may be distributed under the GNU Public License, version 2, or
12 | any higher version. See section COPYING of the GNU Public license
13 | for conditions under which this file may be redistributed.
14 | ***************************************/
15 |
16 | /*+ The names of the function cross reference files. +*/
17 | #define XREF_FUNC_FILE ".function"
18 | #define XREF_FUNC_BACKUP ".function~"
19 |
20 | /*+ The names of the variable cross reference files. +*/
21 | #define XREF_VAR_FILE ".variable"
22 | #define XREF_VAR_BACKUP ".variable~"
23 |
24 | /*+ The names of the include cross reference files. +*/
25 | #define XREF_INC_FILE ".include"
26 | #define XREF_INC_BACKUP ".include~"
27 |
28 | /*+ The names of the type cross reference files. +*/
29 | #define XREF_TYPE_FILE ".typedef"
30 | #define XREF_TYPE_BACKUP ".typedef~"
31 |
32 | #include <stdlib.h>
33 | #include <stdio.h>
34 | #include <string.h>
35 | #include <unistd.h>
36 | #include <limits.h>
37 |
38 | #define TYPE_MAX_LEN 256 /*+ The maximum type definition length +*/
39 | #define FUNC_MAX_LEN 64 /*+ The maximum function name length. +*/
40 | #if defined(PATH_MAX) && defined(NAME_MAX)
41 | #define FILE_MAX_LEN (PATH_MAX+NAME_MAX) /*+ The maximum filename length. +*/
42 | #elif defined(PATH_MAX)
43 | #define FILE_MAX_LEN (PATH_MAX+256) /*+ The maximum filename length. +*/
44 | #else
45 | #define FILE_MAX_LEN 512 /*+ The maximum filename length. +*/
46 | #endif
47 |
48 | #include "memory.h"
49 | #include "datatype.h"
50 | #include "cxref.h"
51 |
52 | /*+ The name of the directory for the output. +*/
53 | extern char* option_odir;
54 |
55 | /*+ The base name of the file for the output. +*/
56 | extern char* option_name;
57 |
58 | /*+ The option for cross referencing. +*/
59 | extern int option_xref;
60 |
61 | /*+ The option for indexing. +*/
62 | extern int option_index;
63 |
64 | static void check_for_called(File file,char* called,char* caller,char* filename);
65 | static void check_for_caller(File file,char* called,char* filename);
66 | static void check_for_var(File file,char* variable,char* filename,int scope,char* funcname);
67 | static int check_for_var_func(File file,Variable var,Function func);
68 | static void fixup_extern_var(Variable var,StringList2 refs);
69 |
70 | /*++++++++++++++++++++++++++++++++++++++
71 | Cross reference the functions, variables and includes that are used in this file
72 | with the global functions, variables and includes. The types that are defined are also listed here.
73 |
74 | File file The file structure containing the information.
75 |
76 | int outputs Set to true if any cross referencing to produce outputs is required.
77 | ++++++++++++++++++++++++++++++++++++++*/
78 | #include <errno.h>
79 | #define massert(a_) \
80 | ({errno=0;\
81 | if (!(a_)||errno) {\
82 | fprintf(stderr,"The assertion %s on line %d of %s in function %s failed: %s",\
83 | #a_,__LINE__,__FILE__,__FUNCTION__,strerror(errno));\
84 | exit(1);\
85 | }\
86 | })
87 |
88 | void CrossReference(File file,int outputs)
89 | {
90 | FILE *in,*out;
91 | char *ifile,*ofile;
92 |
93 | /* Format: filename [[%]include1] [[%]include2] ... : Files include1, include2, ... are included in filename;
94 | those with a % are local. */
95 |
96 | if(option_xref&XREF_FILE) /* First do the files */
97 | {
98 | Include inc;
99 |
100 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE);
101 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_BACKUP);
102 |
103 | in =fopen(ifile,"r");
104 | out=fopen(ofile,"w");
105 |
106 | if(!out)
107 | {fprintf(stderr,"cxref: Failed to open the include cross reference file '%s'\n",ofile);exit(1);}
108 |
109 | fprintf(out,"%s",file->name);
110 | for(inc=file->includes;inc;inc=inc->next)
111 | fprintf(out," %s%s",inc->scope==LOCAL?"%":"",inc->name);
112 | fprintf(out,"\n");
113 |
114 | if(in)
115 | {
116 | char include[FILE_MAX_LEN+1],filename[FILE_MAX_LEN+1],ch;
117 |
118 | while(fscanf(in,"%s%c",filename,&ch)==2)
119 | {
120 | int diff_file=strcmp(filename,file->name);
121 |
122 | if(diff_file)
123 | fprintf(out,"%s",filename);
124 |
125 | while(ch==' ')
126 | {
127 | massert(fscanf(in,"%s%c",include,&ch)!=EOF);
128 |
129 | if(diff_file)
130 | fprintf(out," %s",include);
131 |
132 | if(outputs)
133 | if(include[0]=='%' && !strcmp(&include[1],file->name))
134 | AddToStringList(file->inc_in,filename,1,1);
135 | }
136 |
137 | if(diff_file)
138 | fprintf(out,"\n");
139 | }
140 |
141 | fclose(in);
142 | unlink(ifile);
143 | }
144 |
145 | fclose(out);
146 | rename(ofile,ifile);
147 | }
148 |
149 | /* Format: filename funcname scope [[%][&]funcname1] [[%][&]funcname2] ... : The function funcname in file filename
150 | calls or references functions funcname1, funcname2 ... ; those with a % are local, with a & are references. */
151 | /* Format: filename $ 0 [[%]&funcname1] [[%]&funcname2] ... : The file references functions funcname1, funcname2 ... ;
152 | those with a % are local. */
153 |
154 | if(option_xref&XREF_FUNC) /* Now do the functions */
155 | {
156 | Function func;
157 | int i;
158 |
159 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE);
160 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_BACKUP);
161 |
162 | in =fopen(ifile,"r");
163 | out=fopen(ofile,"w");
164 |
165 | if(!out)
166 | {fprintf(stderr,"cxref: Failed to open the functional cross reference file '%s'\n",ofile);exit(1);}
167 |
168 | for(i=0;i<file->f_refs->n;i++)
169 | check_for_called(file,ConcatStrings(2,"&",file->f_refs->s1[i]),NULL,file->name);
170 |
171 | for(func=file->functions;func;func=func->next)
172 | {
173 | for(i=0;i<func->calls->n;i++)
174 | check_for_called(file,func->calls->s1[i],func->name,file->name);
175 | for(i=0;i<func->f_refs->n;i++)
176 | check_for_called(file,ConcatStrings(2,"&",func->f_refs->s1[i]),func->name,file->name);
177 | }
178 |
179 | for(func=file->functions;func;func=func->next)
180 | check_for_caller(file,func->name,file->name);
181 |
182 | if(file->f_refs->n)
183 | {
184 | fprintf(out,"%s $ 0",file->name);
185 | for(i=0;i<file->f_refs->n;i++)
186 | {
187 | if(file->f_refs->s2[i])
188 | fprintf(out," %%&%s",file->f_refs->s1[i]);
189 | else
190 | fprintf(out," &%s",file->f_refs->s1[i]);
191 | }
192 | fprintf(out,"\n");
193 | }
194 |
195 | for(func=file->functions;func;func=func->next)
196 | {
197 | fprintf(out,"%s %s %d",file->name,func->name,func->scope);
198 | for(i=0;i<func->calls->n;i++)
199 | {
200 | if(func->calls->s2[i])
201 | fprintf(out," %%%s",func->calls->s1[i]);
202 | else
203 | fprintf(out," %s",func->calls->s1[i]);
204 | }
205 | for(i=0;i<func->f_refs->n;i++)
206 | {
207 | if(func->f_refs->s2[i])
208 | fprintf(out," %%&%s",func->f_refs->s1[i]);
209 | else
210 | fprintf(out," &%s",func->f_refs->s1[i]);
211 | }
212 | fprintf(out,"\n");
213 | }
214 |
215 | if(in)
216 | {
217 | char ch,funcname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],called[FUNC_MAX_LEN+1];
218 | int scope;
219 |
220 | while(fscanf(in,"%s %s %d%c",filename,funcname,&scope,&ch)==4)
221 | {
222 | int diff_file=strcmp(filename,file->name);
223 |
224 | if(diff_file)
225 | {
226 | if(outputs)
227 | if(funcname[0]!='$' || funcname[1]!=0)
228 | check_for_caller(file,funcname,filename);
229 | fprintf(out,"%s %s %d",filename,funcname,scope);
230 | }
231 |
232 | while(ch==' ')
233 | {
234 | massert(fscanf(in,"%s%c",called,&ch)!=EOF);
235 |
236 | if(diff_file)
237 | {
238 | if(outputs)
239 | {
240 | if(called[0]!='%')
241 | {
242 | if(funcname[0]!='$' || funcname[1]!=0)
243 | check_for_called(file,called,funcname,filename);
244 | else
245 | check_for_called(file,called,NULL,filename);
246 | }
247 | }
248 | fprintf(out," %s",called);
249 | }
250 | }
251 |
252 | if(diff_file)
253 | fprintf(out,"\n");
254 | }
255 |
256 | fclose(in);
257 | unlink(ifile);
258 | }
259 |
260 | fclose(out);
261 | rename(ofile,ifile);
262 | }
263 |
264 | /* Format: filename varname scope [$] [[%]funcname1] [[%]funcname2] ... : variable varname is used in
265 | the file filename if $, and functions funcname1, funcname2 ... Those with a % are local. */
266 |
267 | if(option_xref&XREF_VAR) /* Now do the variables */
268 | {
269 | Variable var;
270 | Function func;
271 |
272 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE);
273 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_BACKUP);
274 |
275 | in =fopen(ifile,"r");
276 | out=fopen(ofile,"w");
277 |
278 | if(!out)
279 | {fprintf(stderr,"cxref: Failed to open the variable cross reference file '%s'\n",ofile);exit(1);}
280 |
281 | for(var=file->variables;var;var=var->next)
282 | {
283 | check_for_var(file,var->name,file->name,var->scope,NULL);
284 | fprintf(out,"%s %s %d",file->name,var->name,var->scope);
285 | if(check_for_var_func(file,var,NULL))
286 | fprintf(out," $");
287 | for(func=file->functions;func;func=func->next)
288 | if(check_for_var_func(file,var,func))
289 | fprintf(out," %s%s",func->scope==LOCAL?"%":"",func->name);
290 | fprintf(out,"\n");
291 | }
292 |
293 | if(in)
294 | {
295 | char varname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],funcname[FUNC_MAX_LEN+1],ch;
296 | int scope;
297 |
298 | while(fscanf(in,"%s %s %d%c",filename,varname,&scope,&ch)==4)
299 | {
300 | int diff_file=strcmp(filename,file->name);
301 |
302 | if(diff_file)
303 | {
304 | if(outputs)
305 | if(!(scope&LOCAL))
306 | check_for_var(file,varname,filename,scope,NULL);
307 | fprintf(out,"%s %s %d",filename,varname,scope);
308 | }
309 |
310 | while(ch==' ')
311 | {
312 | massert(fscanf(in,"%s%c",funcname,&ch)!=EOF);
313 |
314 | if(diff_file)
315 | {
316 | if(outputs)
317 | {
318 | if(!(scope&LOCAL))
319 | {
320 | if(funcname[0]=='%')
321 | check_for_var(file,varname,filename,scope,&funcname[1]);
322 | else
323 | check_for_var(file,varname,filename,scope,funcname);
324 | }
325 | }
326 | fprintf(out," %s",funcname);
327 | }
328 | }
329 |
330 | if(diff_file)
331 | fprintf(out,"\n");
332 | }
333 |
334 | fclose(in);
335 | unlink(ifile);
336 | }
337 |
338 | /* We must fix the location of the extern variables now since it was not known earlier. */
339 |
340 | if(outputs)
341 | {
342 | fixup_extern_var(file->variables,file->v_refs);
343 | for(func=file->functions;func;func=func->next)
344 | fixup_extern_var(file->variables,func->v_refs);
345 | }
346 |
347 | fclose(out);
348 | rename(ofile,ifile);
349 | }
350 |
351 | /* Format: filename typename type... : For a typedef type. */
352 | /* Format: filename # type... : For a non typedef type. */
353 |
354 | if(option_xref&XREF_TYPE) /* Now do the types */
355 | {
356 | Typedef type;
357 |
358 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE);
359 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_BACKUP);
360 |
361 | in =fopen(ifile,"r");
362 | out=fopen(ofile,"w");
363 |
364 | if(!out)
365 | {fprintf(stderr,"cxref: Failed to open the typedef reference file '%s'\n",ofile);exit(1);}
366 |
367 | for(type=file->typedefs;type;type=type->next)
368 | if(type->type)
369 | fprintf(out,"%s %s %s\n",file->name,type->name,type->type);
370 | else
371 | fprintf(out,"%s # %s\n",file->name,type->name);
372 |
373 | if(in)
374 | {
375 | char typename[TYPE_MAX_LEN+1],filename[FILE_MAX_LEN+1];
376 |
377 | while(fscanf(in,"%s %s",filename,typename)==2)
378 | {
379 | int diff_file=strcmp(filename,file->name);
380 |
381 | if(diff_file)
382 | fprintf(out,"%s %s",filename,typename);
383 |
384 | massert(fgets(typename,TYPE_MAX_LEN,in)!=NULL);
385 |
386 | if(diff_file)
387 | fputs(typename,out);
388 | }
389 |
390 | fclose(in);
391 | unlink(ifile);
392 | }
393 |
394 | fclose(out);
395 | rename(ofile,ifile);
396 | }
397 | }
398 |
399 |
400 | /*++++++++++++++++++++++++++++++++++++++
401 | Check through all of the functions in this file to see if any of them are called or referenced.
402 |
403 | File file The file structure.
404 |
405 | char* called The function that is called.
406 |
407 | char* caller The function that the called function is called from.
408 |
409 | char* filename The file that the function is called from.
410 | ++++++++++++++++++++++++++++++++++++++*/
411 |
412 | static void check_for_called(File file,char* called,char* caller,char* filename)
413 | {
414 | Function func;
415 |
416 | /* Check for function calls */
417 |
418 | if(called[0]!='&')
419 | for(func=file->functions;func;func=func->next)
420 | {
421 | if(!strcmp(called,func->name))
422 | AddToStringList2(func->called,caller,filename,1,1);
423 | }
424 |
425 | /* Check for function references */
426 |
427 | else
428 | for(func=file->functions;func;func=func->next)
429 | {
430 | if(!strcmp(&called[1],func->name))
431 | {
432 | if(caller)
433 | AddToStringList2(func->used,caller,filename,1,1);
434 | else
435 | AddToStringList2(func->used,"$",filename,1,0);
436 | }
437 | }
438 | }
439 |
440 |
441 | /*++++++++++++++++++++++++++++++++++++++
442 | Check through all of the functions in this file to see if any of them are callers or referencers.
443 |
444 | File file The file structure.
445 |
446 | char* called The function that is called.
447 |
448 | char* filename The file that the called function is in.
449 | ++++++++++++++++++++++++++++++++++++++*/
450 |
451 | static void check_for_caller(File file,char* called,char* filename)
452 | {
453 | int i;
454 | Function func;
455 |
456 | /* Check the functions that are called. */
457 |
458 | for(func=file->functions;func;func=func->next)
459 | for(i=0;i<func->calls->n;i++)
460 | if(!strcmp(called,func->calls->s1[i]))
461 | if(!func->calls->s2[i])
462 | func->calls->s2[i]=MallocString(filename);
463 |
464 | /* Check the functions that are referenced. */
465 |
466 | for(i=0;i<file->f_refs->n;i++)
467 | if(!strcmp(called,file->f_refs->s1[i]))
468 | if(!file->f_refs->s2[i])
469 | file->f_refs->s2[i]=MallocString(filename);
470 |
471 | for(func=file->functions;func;func=func->next)
472 | for(i=0;i<func->f_refs->n;i++)
473 | if(!strcmp(called,func->f_refs->s1[i]))
474 | if(!func->f_refs->s2[i])
475 | func->f_refs->s2[i]=MallocString(filename);
476 | }
477 |
478 |
479 | /*++++++++++++++++++++++++++++++++++++++
480 | Check through all of the variables in this file to see if any of them are extern usage of others.
481 |
482 | File file The file structure.
483 |
484 | char* variable The global variable name.
485 |
486 | char* filename The file that the variable is used in.
487 |
488 | int scope The scope of the variable in the foreign file.
489 |
490 | char* funcname The name of a function that uses the variable.
491 | ++++++++++++++++++++++++++++++++++++++*/
492 |
493 | static void check_for_var(File file,char* variable,char* filename,int scope,char* funcname)
494 | {
495 | Variable var;
496 |
497 | if(!funcname)
498 | {
499 | if(!(scope&(GLOBAL|EXTERNAL|EXTERN_H)))
500 | return;
501 |
502 | for(var=file->variables;var;var=var->next)
503 | if((scope&GLOBAL && var->scope&(EXTERNAL|EXTERN_H|EXTERN_F)) ||
504 | (scope&(GLOBAL|EXTERNAL|EXTERN_H) && var->scope&GLOBAL))
505 | if(!strcmp(variable,var->name))
506 | {
507 | if(scope&GLOBAL && var->scope&(EXTERNAL|EXTERN_H|EXTERN_F))
508 | var->defined=MallocString(filename);
509 |
510 | if(scope&(GLOBAL|EXTERNAL|EXTERN_H) && var->scope&GLOBAL)
511 | AddToStringList2(var->visible,"$",filename,1,0);
512 | }
513 | }
514 | else
515 | {
516 | for(var=file->variables;var;var=var->next)
517 | if(!strcmp(variable,var->name))
518 | {
519 | if(funcname[0]=='$' && !funcname[1])
520 | AddToStringList2(var->used,"$",filename,1,0);
521 | else
522 | {
523 | AddToStringList2(var->used,funcname,filename,1,1);
524 |
525 | if(scope&EXTERN_F && var->scope&GLOBAL)
526 | AddToStringList2(var->visible,funcname,filename,1,1);
527 | }
528 | }
529 | }
530 | }
531 |
532 |
533 | /*++++++++++++++++++++++++++++++++++++++
534 | Check through the function to see if it uses the variable, if func is NULL then check the file.
535 |
536 | int check_for_var_func Returns 1 if the variable is referenced from the function or file.
537 |
538 | File file The file that the function belongs to.
539 |
540 | Variable var The variable that may be referenced.
541 |
542 | Function func The function that is to be checked.
543 | ++++++++++++++++++++++++++++++++++++++*/
544 |
545 | static int check_for_var_func(File file,Variable var,Function func)
546 | {
547 | int i;
548 |
549 | if(func)
550 | {
551 | for(i=0;i<func->v_refs->n;i++)
552 | if(!strcmp(var->name,func->v_refs->s1[i]))
553 | {
554 | AddToStringList2(var->used,func->name,file->name,1,1);
555 | if(var->scope&(GLOBAL|LOCAL))
556 | func->v_refs->s2[i]=MallocString(file->name);
557 | else
558 | {
559 | if(func->v_refs->s2[i]) Free(func->v_refs->s2[i]);
560 | func->v_refs->s2[i]=MallocString("$");
561 | }
562 | return(1);
563 | }
564 | }
565 | else
566 | {
567 | for(i=0;i<file->v_refs->n;i++)
568 | if(!strcmp(var->name,file->v_refs->s1[i]))
569 | {
570 | AddToStringList2(var->used,"$",file->name,1,0);
571 | if(var->scope&(GLOBAL|LOCAL))
572 | file->v_refs->s2[i]=MallocString(file->name);
573 | else
574 | {
575 | if(file->v_refs->s2[i]) Free(file->v_refs->s2[i]);
576 | file->v_refs->s2[i]=MallocString("$");
577 | }
578 | return(1);
579 | }
580 | }
581 |
582 | return(0);
583 | }
584 |
585 |
586 | /*++++++++++++++++++++++++++++++++++++++
587 | We can only now put in the location of the external variables that we found were used.
588 | Previously we did not know the location of their global definition.
589 |
590 | Variable var The list of variables for this file.
591 |
592 | StringList2 refs A list of variable references from a file or a function.
593 | ++++++++++++++++++++++++++++++++++++++*/
594 |
595 | static void fixup_extern_var(Variable var,StringList2 refs)
596 | {
597 | int i;
598 | Variable v;
599 |
600 | for(i=0;i<refs->n;i++)
601 | {
602 | if(refs->s2[i][0]=='$' && !refs->s2[i][1])
603 | for(v=var;v;v=v->next)
604 | if(v->scope&(EXTERNAL|EXTERN_H|EXTERN_F) && !strcmp(refs->s1[i],v->name))
605 | {
606 | if(v->defined)
607 | {
608 | Free(refs->s2[i]);
609 | refs->s2[i]=MallocString(v->defined);
610 | }
611 | else
612 | {
613 | Free(refs->s1[i]);
614 | refs->s1[i]=MallocString(v->name);
615 | Free(refs->s2[i]);
616 | refs->s2[i]=NULL;
617 | }
618 |
619 | break;
620 | }
621 | }
622 | }
623 |
624 |
625 | /*++++++++++++++++++++++++++++++++++++++
626 | Create the appendix of files, global functions, global variables and types.
627 |
628 | StringList files The list of files to create.
629 |
630 | StringList2 funcs The list of functions to create.
631 |
632 | StringList2 vars The list of variables to create.
633 |
634 | StringList2 types The list of types to create.
635 | ++++++++++++++++++++++++++++++++++++++*/
636 |
637 | void CreateAppendix(StringList files,StringList2 funcs,StringList2 vars,StringList2 types)
638 | {
639 | FILE *in;
640 | char *ifile;
641 |
642 | if(option_index&INDEX_FILE) /* First do the files */
643 | {
644 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE);
645 |
646 | in =fopen(ifile,"r");
647 |
648 | if(in)
649 | {
650 | char include[FILE_MAX_LEN+1],filename[FILE_MAX_LEN+1],ch;
651 |
652 | while(fscanf(in,"%s%c",filename,&ch)==2)
653 | {
654 | AddToStringList(files,filename,1,1);
655 | while(ch==' ')
656 | massert(fscanf(in,"%s%c",include,&ch)!=EOF);
657 | }
658 |
659 | fclose(in);
660 | }
661 | }
662 |
663 | if(option_index&INDEX_FUNC) /* Now do the functions */
664 | {
665 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE);
666 |
667 | in =fopen(ifile,"r");
668 |
669 | if(in)
670 | {
671 | char ch,caller[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],called[FUNC_MAX_LEN+1];
672 | int scope;
673 |
674 | while(fscanf(in,"%s %s %d%c",filename,caller,&scope,&ch)==4)
675 | {
676 | if(scope&GLOBAL)
677 | AddToStringList2(funcs,caller,filename,1,1);
678 | while(ch==' ')
679 | massert(fscanf(in,"%s%c",called,&ch)!=EOF);
680 | }
681 |
682 | fclose(in);
683 | }
684 | }
685 |
686 | if(option_index&INDEX_VAR) /* Now do the variables */
687 | {
688 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE);
689 |
690 | in =fopen(ifile,"r");
691 |
692 | if(in)
693 | {
694 | char variable[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],funcname[FUNC_MAX_LEN+1],ch;
695 | int scope;
696 |
697 | while(fscanf(in,"%s %s %d%c",filename,variable,&scope,&ch)==4)
698 | {
699 | if(scope&GLOBAL)
700 | AddToStringList2(vars,variable,filename,1,1);
701 | while(ch==' ')
702 | massert(fscanf(in,"%s%c",funcname,&ch)!=EOF);
703 | }
704 |
705 | fclose(in);
706 | }
707 | }
708 |
709 | if(option_index&INDEX_TYPE) /* Now do the types */
710 | {
711 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE);
712 |
713 | in =fopen(ifile,"r");
714 |
715 | if(in)
716 | {
717 | char typename[TYPE_MAX_LEN],filename[FILE_MAX_LEN+1];
718 |
719 | while(fscanf(in,"%s %s",filename,typename)==2)
720 | {
721 | if(typename[0]=='#')
722 | {
723 | massert(fgets(typename,TYPE_MAX_LEN,in)!=NULL);
724 | typename[strlen(typename)-1]=0;
725 | AddToStringList2(types,&typename[1],filename,1,1);
726 | }
727 | else
728 | {
729 | AddToStringList2(types,typename,filename,1,1);
730 | massert(fgets(typename,TYPE_MAX_LEN,in)!=NULL);
731 | }
732 | }
733 |
734 | fclose(in);
735 | }
736 | }
737 | }
738 |
739 |
740 | /*++++++++++++++++++++++++++++++++++++++
741 | Delete the named file from the cross reference database.
742 |
743 | char *name The name of the file that is to be deleted.
744 | ++++++++++++++++++++++++++++++++++++++*/
745 |
746 | void CrossReferenceDelete(char *name)
747 | {
748 | FILE *in,*out;
749 | char *ifile,*ofile;
750 |
751 | /* First do the files */
752 |
753 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE);
754 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_BACKUP);
755 |
756 | in =fopen(ifile,"r");
757 | out=fopen(ofile,"w");
758 |
759 | if(in && !out)
760 | {fprintf(stderr,"cxref: Failed to open the include cross reference file '%s'\n",ofile);fclose(in);}
761 | else if(in)
762 | {
763 | char include[FILE_MAX_LEN+1],filename[FILE_MAX_LEN+1],ch;
764 |
765 | while(fscanf(in,"%s%c",filename,&ch)==2)
766 | {
767 | int diff_file=strcmp(filename,name);
768 |
769 | if(diff_file)
770 | fprintf(out,"%s",filename);
771 |
772 | while(ch==' ')
773 | {
774 | massert(fscanf(in,"%s%c",include,&ch)!=EOF);
775 |
776 | if(diff_file)
777 | fprintf(out," %s",include);
778 | }
779 |
780 | if(diff_file)
781 | fprintf(out,"\n");
782 | }
783 |
784 | fclose(in);
785 | unlink(ifile);
786 |
787 | fclose(out);
788 | rename(ofile,ifile);
789 | }
790 | else if(out)
791 | {
792 | fclose(out);
793 | unlink(ofile);
794 | }
795 |
796 | /* Now do the functions */
797 |
798 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE);
799 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_BACKUP);
800 |
801 | in =fopen(ifile,"r");
802 | out=fopen(ofile,"w");
803 |
804 | if(in && !out)
805 | {fprintf(stderr,"cxref: Failed to open the functional cross reference file '%s'\n",ofile);fclose(in);}
806 | else if(in)
807 | {
808 | char ch,funcname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],called[FUNC_MAX_LEN+1];
809 | int scope;
810 |
811 | while(fscanf(in,"%s %s %d%c",filename,funcname,&scope,&ch)==4)
812 | {
813 | int diff_file=strcmp(filename,name);
814 |
815 | if(diff_file)
816 | fprintf(out,"%s %s %d",filename,funcname,scope);
817 |
818 | while(ch==' ')
819 | {
820 | massert(fscanf(in,"%s%c",called,&ch)!=EOF);
821 | if(diff_file)
822 | fprintf(out," %s",called);
823 | }
824 |
825 | if(diff_file)
826 | fprintf(out,"\n");
827 | }
828 |
829 | fclose(in);
830 | unlink(ifile);
831 |
832 | fclose(out);
833 | rename(ofile,ifile);
834 | }
835 | else if(out)
836 | {
837 | fclose(out);
838 | unlink(ofile);
839 | }
840 |
841 | /* Now do the variables */
842 |
843 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE);
844 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_BACKUP);
845 |
846 | in =fopen(ifile,"r");
847 | out=fopen(ofile,"w");
848 |
849 | if(in && !out)
850 | {fprintf(stderr,"cxref: Failed to open the variable cross reference file '%s'\n",ofile);fclose(in);}
851 | else if(in)
852 | {
853 | char varname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],funcname[FUNC_MAX_LEN+1],ch;
854 | int scope;
855 |
856 | while(fscanf(in,"%s %s %d%c",filename,varname,&scope,&ch)==4)
857 | {
858 | int diff_file=strcmp(filename,name);
859 |
860 | if(diff_file)
861 | fprintf(out,"%s %s %d",filename,varname,scope);
862 |
863 | while(ch==' ')
864 | {
865 | massert(fscanf(in,"%s%c",funcname,&ch)!=EOF);
866 |
867 | if(diff_file)
868 | fprintf(out," %s",funcname);
869 | }
870 |
871 | if(diff_file)
872 | fprintf(out,"\n");
873 | }
874 |
875 | fclose(in);
876 | unlink(ifile);
877 |
878 | fclose(out);
879 | rename(ofile,ifile);
880 | }
881 | else if(out)
882 | {
883 | fclose(out);
884 | unlink(ofile);
885 | }
886 |
887 | /* Now do the types */
888 |
889 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE);
890 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_BACKUP);
891 |
892 | in =fopen(ifile,"r");
893 | out=fopen(ofile,"w");
894 |
895 | if(in && !out)
896 | {fprintf(stderr,"cxref: Failed to open the typedef reference file '%s'\n",ofile);fclose(in);}
897 | else if(in)
898 | {
899 | char typename[TYPE_MAX_LEN+1],filename[FILE_MAX_LEN+1];
900 |
901 | while(fscanf(in,"%s %s",filename,typename)==2)
902 | {
903 | int diff_file=strcmp(filename,name);
904 |
905 | if(diff_file)
906 | fprintf(out,"%s %s",filename,typename);
907 |
908 | massert(fgets(typename,TYPE_MAX_LEN,in)!=NULL);
909 |
910 | if(diff_file)
911 | fputs(typename,out);
912 | }
913 |
914 | fclose(in);
915 | unlink(ifile);
916 |
917 | fclose(out);
918 | rename(ofile,ifile);
919 | }
920 | else if(out)
921 | {
922 | fclose(out);
923 | unlink(ofile);
924 | }
925 | }