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