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 |
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 | if(!func->calls->s2[i])
453 | func->calls->s2[i]=MallocString(filename);
454 |
455 | /* Check the functions that are referenced. */
456 |
457 | for(i=0;i<file->f_refs->n;i++)
458 | if(!strcmp(called,file->f_refs->s1[i]))
459 | if(!file->f_refs->s2[i])
460 | file->f_refs->s2[i]=MallocString(filename);
461 |
462 | for(func=file->functions;func;func=func->next)
463 | for(i=0;i<func->f_refs->n;i++)
464 | if(!strcmp(called,func->f_refs->s1[i]))
465 | if(!func->f_refs->s2[i])
466 | func->f_refs->s2[i]=MallocString(filename);
467 | }
468 |
469 |
470 | /*++++++++++++++++++++++++++++++++++++++
471 | Check through all of the variables in this file to see if any of them are extern usage of others.
472 |
473 | File file The file structure.
474 |
475 | char* variable The global variable name.
476 |
477 | char* filename The file that the variable is used in.
478 |
479 | int scope The scope of the variable in the foreign file.
480 |
481 | char* funcname The name of a function that uses the variable.
482 | ++++++++++++++++++++++++++++++++++++++*/
483 |
484 | static void check_for_var(File file,char* variable,char* filename,int scope,char* funcname)
485 | {
486 | Variable var;
487 |
488 | if(!funcname)
489 | {
490 | if(!(scope&(GLOBAL|EXTERNAL|EXTERN_H)))
491 | return;
492 |
493 | for(var=file->variables;var;var=var->next)
494 | if((scope&GLOBAL && var->scope&(EXTERNAL|EXTERN_H|EXTERN_F)) ||
495 | (scope&(GLOBAL|EXTERNAL|EXTERN_H) && var->scope&GLOBAL))
496 | if(!strcmp(variable,var->name))
497 | {
498 | if(scope&GLOBAL && var->scope&(EXTERNAL|EXTERN_H|EXTERN_F))
499 | var->defined=MallocString(filename);
500 |
501 | if(scope&(GLOBAL|EXTERNAL|EXTERN_H) && var->scope&GLOBAL)
502 | AddToStringList2(var->visible,"$",filename,1,0);
503 | }
504 | }
505 | else
506 | {
507 | for(var=file->variables;var;var=var->next)
508 | if(!strcmp(variable,var->name))
509 | {
510 | if(funcname[0]=='$' && !funcname[1])
511 | AddToStringList2(var->used,"$",filename,1,0);
512 | else
513 | {
514 | AddToStringList2(var->used,funcname,filename,1,1);
515 |
516 | if(scope&EXTERN_F && var->scope&GLOBAL)
517 | AddToStringList2(var->visible,funcname,filename,1,1);
518 | }
519 | }
520 | }
521 | }
522 |
523 |
524 | /*++++++++++++++++++++++++++++++++++++++
525 | Check through the function to see if it uses the variable, if func is NULL then check the file.
526 |
527 | int check_for_var_func Returns 1 if the variable is referenced from the function or file.
528 |
529 | File file The file that the function belongs to.
530 |
531 | Variable var The variable that may be referenced.
532 |
533 | Function func The function that is to be checked.
534 | ++++++++++++++++++++++++++++++++++++++*/
535 |
536 | static int check_for_var_func(File file,Variable var,Function func)
537 | {
538 | int i;
539 |
540 | if(func)
541 | {
542 | for(i=0;i<func->v_refs->n;i++)
543 | if(!strcmp(var->name,func->v_refs->s1[i]))
544 | {
545 | AddToStringList2(var->used,func->name,file->name,1,1);
546 | if(var->scope&(GLOBAL|LOCAL))
547 | func->v_refs->s2[i]=MallocString(file->name);
548 | else
549 | {
550 | if(func->v_refs->s2[i]) Free(func->v_refs->s2[i]);
551 | func->v_refs->s2[i]=MallocString("$");
552 | }
553 | return(1);
554 | }
555 | }
556 | else
557 | {
558 | for(i=0;i<file->v_refs->n;i++)
559 | if(!strcmp(var->name,file->v_refs->s1[i]))
560 | {
561 | AddToStringList2(var->used,"$",file->name,1,0);
562 | if(var->scope&(GLOBAL|LOCAL))
563 | file->v_refs->s2[i]=MallocString(file->name);
564 | else
565 | {
566 | if(file->v_refs->s2[i]) Free(file->v_refs->s2[i]);
567 | file->v_refs->s2[i]=MallocString("$");
568 | }
569 | return(1);
570 | }
571 | }
572 |
573 | return(0);
574 | }
575 |
576 |
577 | /*++++++++++++++++++++++++++++++++++++++
578 | We can only now put in the location of the external variables that we found were used.
579 | Previously we did not know the location of their global definition.
580 |
581 | Variable var The list of variables for this file.
582 |
583 | StringList2 refs A list of variable references from a file or a function.
584 | ++++++++++++++++++++++++++++++++++++++*/
585 |
586 | static void fixup_extern_var(Variable var,StringList2 refs)
587 | {
588 | int i;
589 | Variable v;
590 |
591 | for(i=0;i<refs->n;i++)
592 | {
593 | if(refs->s2[i][0]=='$' && !refs->s2[i][1])
594 | for(v=var;v;v=v->next)
595 | if(v->scope&(EXTERNAL|EXTERN_H|EXTERN_F) && !strcmp(refs->s1[i],v->name))
596 | {
597 | if(v->defined)
598 | {
599 | Free(refs->s2[i]);
600 | refs->s2[i]=MallocString(v->defined);
601 | }
602 | else
603 | {
604 | Free(refs->s1[i]);
605 | refs->s1[i]=MallocString(v->name);
606 | Free(refs->s2[i]);
607 | refs->s2[i]=NULL;
608 | }
609 |
610 | break;
611 | }
612 | }
613 | }
614 |
615 |
616 | /*++++++++++++++++++++++++++++++++++++++
617 | Create the appendix of files, global functions, global variables and types.
618 |
619 | StringList files The list of files to create.
620 |
621 | StringList2 funcs The list of functions to create.
622 |
623 | StringList2 vars The list of variables to create.
624 |
625 | StringList2 types The list of types to create.
626 | ++++++++++++++++++++++++++++++++++++++*/
627 |
628 | void CreateAppendix(StringList files,StringList2 funcs,StringList2 vars,StringList2 types)
629 | {
630 | FILE *in;
631 | char *ifile;
632 |
633 | if(option_index&INDEX_FILE) /* First do the files */
634 | {
635 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE);
636 |
637 | in =fopen(ifile,"r");
638 |
639 | if(in)
640 | {
641 | char include[FILE_MAX_LEN+1],filename[FILE_MAX_LEN+1],ch;
642 |
643 | while(fscanf(in,"%s%c",filename,&ch)==2)
644 | {
645 | AddToStringList(files,filename,1,1);
646 | while(ch==' ')
647 | fscanf(in,"%s%c",include,&ch);
648 | }
649 |
650 | fclose(in);
651 | }
652 | }
653 |
654 | if(option_index&INDEX_FUNC) /* Now do the functions */
655 | {
656 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE);
657 |
658 | in =fopen(ifile,"r");
659 |
660 | if(in)
661 | {
662 | char ch,caller[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],called[FUNC_MAX_LEN+1];
663 | int scope;
664 |
665 | while(fscanf(in,"%s %s %d%c",filename,caller,&scope,&ch)==4)
666 | {
667 | if(scope&GLOBAL)
668 | AddToStringList2(funcs,caller,filename,1,1);
669 | while(ch==' ')
670 | fscanf(in,"%s%c",called,&ch);
671 | }
672 |
673 | fclose(in);
674 | }
675 | }
676 |
677 | if(option_index&INDEX_VAR) /* Now do the variables */
678 | {
679 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE);
680 |
681 | in =fopen(ifile,"r");
682 |
683 | if(in)
684 | {
685 | char variable[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],funcname[FUNC_MAX_LEN+1],ch;
686 | int scope;
687 |
688 | while(fscanf(in,"%s %s %d%c",filename,variable,&scope,&ch)==4)
689 | {
690 | if(scope&GLOBAL)
691 | AddToStringList2(vars,variable,filename,1,1);
692 | while(ch==' ')
693 | fscanf(in,"%s%c",funcname,&ch);
694 | }
695 |
696 | fclose(in);
697 | }
698 | }
699 |
700 | if(option_index&INDEX_TYPE) /* Now do the types */
701 | {
702 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE);
703 |
704 | in =fopen(ifile,"r");
705 |
706 | if(in)
707 | {
708 | char typename[TYPE_MAX_LEN],filename[FILE_MAX_LEN+1];
709 |
710 | while(fscanf(in,"%s %s",filename,typename)==2)
711 | {
712 | if(typename[0]=='#')
713 | {
714 | fgets(typename,TYPE_MAX_LEN,in);
715 | typename[strlen(typename)-1]=0;
716 | AddToStringList2(types,&typename[1],filename,1,1);
717 | }
718 | else
719 | {
720 | AddToStringList2(types,typename,filename,1,1);
721 | fgets(typename,TYPE_MAX_LEN,in);
722 | }
723 | }
724 |
725 | fclose(in);
726 | }
727 | }
728 | }
729 |
730 |
731 | /*++++++++++++++++++++++++++++++++++++++
732 | Delete the named file from the cross reference database.
733 |
734 | char *name The name of the file that is to be deleted.
735 | ++++++++++++++++++++++++++++++++++++++*/
736 |
737 | void CrossReferenceDelete(char *name)
738 | {
739 | FILE *in,*out;
740 | char *ifile,*ofile;
741 |
742 | /* First do the files */
743 |
744 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE);
745 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_BACKUP);
746 |
747 | in =fopen(ifile,"r");
748 | out=fopen(ofile,"w");
749 |
750 | if(in && !out)
751 | {fprintf(stderr,"cxref: Failed to open the include cross reference file '%s'\n",ofile);fclose(in);}
752 | else if(in)
753 | {
754 | char include[FILE_MAX_LEN+1],filename[FILE_MAX_LEN+1],ch;
755 |
756 | while(fscanf(in,"%s%c",filename,&ch)==2)
757 | {
758 | int diff_file=strcmp(filename,name);
759 |
760 | if(diff_file)
761 | fprintf(out,"%s",filename);
762 |
763 | while(ch==' ')
764 | {
765 | fscanf(in,"%s%c",include,&ch);
766 |
767 | if(diff_file)
768 | fprintf(out," %s",include);
769 | }
770 |
771 | if(diff_file)
772 | fprintf(out,"\n");
773 | }
774 |
775 | fclose(in);
776 | unlink(ifile);
777 |
778 | fclose(out);
779 | rename(ofile,ifile);
780 | }
781 | else if(out)
782 | {
783 | fclose(out);
784 | unlink(ofile);
785 | }
786 |
787 | /* Now do the functions */
788 |
789 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE);
790 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_BACKUP);
791 |
792 | in =fopen(ifile,"r");
793 | out=fopen(ofile,"w");
794 |
795 | if(in && !out)
796 | {fprintf(stderr,"cxref: Failed to open the functional cross reference file '%s'\n",ofile);fclose(in);}
797 | else if(in)
798 | {
799 | char ch,funcname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],called[FUNC_MAX_LEN+1];
800 | int scope;
801 |
802 | while(fscanf(in,"%s %s %d%c",filename,funcname,&scope,&ch)==4)
803 | {
804 | int diff_file=strcmp(filename,name);
805 |
806 | if(diff_file)
807 | fprintf(out,"%s %s %d",filename,funcname,scope);
808 |
809 | while(ch==' ')
810 | {
811 | fscanf(in,"%s%c",called,&ch);
812 | if(diff_file)
813 | fprintf(out," %s",called);
814 | }
815 |
816 | if(diff_file)
817 | fprintf(out,"\n");
818 | }
819 |
820 | fclose(in);
821 | unlink(ifile);
822 |
823 | fclose(out);
824 | rename(ofile,ifile);
825 | }
826 | else if(out)
827 | {
828 | fclose(out);
829 | unlink(ofile);
830 | }
831 |
832 | /* Now do the variables */
833 |
834 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE);
835 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_BACKUP);
836 |
837 | in =fopen(ifile,"r");
838 | out=fopen(ofile,"w");
839 |
840 | if(in && !out)
841 | {fprintf(stderr,"cxref: Failed to open the variable cross reference file '%s'\n",ofile);fclose(in);}
842 | else if(in)
843 | {
844 | char varname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],funcname[FUNC_MAX_LEN+1],ch;
845 | int scope;
846 |
847 | while(fscanf(in,"%s %s %d%c",filename,varname,&scope,&ch)==4)
848 | {
849 | int diff_file=strcmp(filename,name);
850 |
851 | if(diff_file)
852 | fprintf(out,"%s %s %d",filename,varname,scope);
853 |
854 | while(ch==' ')
855 | {
856 | fscanf(in,"%s%c",funcname,&ch);
857 |
858 | if(diff_file)
859 | fprintf(out," %s",funcname);
860 | }
861 |
862 | if(diff_file)
863 | fprintf(out,"\n");
864 | }
865 |
866 | fclose(in);
867 | unlink(ifile);
868 |
869 | fclose(out);
870 | rename(ofile,ifile);
871 | }
872 | else if(out)
873 | {
874 | fclose(out);
875 | unlink(ofile);
876 | }
877 |
878 | /* Now do the types */
879 |
880 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE);
881 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_BACKUP);
882 |
883 | in =fopen(ifile,"r");
884 | out=fopen(ofile,"w");
885 |
886 | if(in && !out)
887 | {fprintf(stderr,"cxref: Failed to open the typedef reference file '%s'\n",ofile);fclose(in);}
888 | else if(in)
889 | {
890 | char typename[TYPE_MAX_LEN+1],filename[FILE_MAX_LEN+1];
891 |
892 | while(fscanf(in,"%s %s",filename,typename)==2)
893 | {
894 | int diff_file=strcmp(filename,name);
895 |
896 | if(diff_file)
897 | fprintf(out,"%s %s",filename,typename);
898 |
899 | fgets(typename,TYPE_MAX_LEN,in);
900 |
901 | if(diff_file)
902 | fputs(typename,out);
903 | }
904 |
905 | fclose(in);
906 | unlink(ifile);
907 |
908 | fclose(out);
909 | rename(ofile,ifile);
910 | }
911 | else if(out)
912 | {
913 | fclose(out);
914 | unlink(ofile);
915 | }
916 | }