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