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