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  | }