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