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