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