1    | /***************************************
2    |   $Header: /home/amb/cxref/RCS/xref.c 1.20 2001/01/06 13:05:13 amb Exp $
3    | 
4    |   C Cross Referencing & Documentation tool. Version 1.5c.
5    | 
6    |   Cross referencing of functions.
7    |   ******************/ /******************
8    |   Written by Andrew M. Bishop
9    | 
10   |   This file Copyright 1995,96,97,99,2001 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  |           func->calls->s2[i]=MallocString(filename);
453  | 
454  |  /* Check the functions that are referenced. */
455  | 
456  |  for(i=0;i<file->f_refs->n;i++)
457  |     if(!strcmp(called,file->f_refs->s1[i]))
458  |        file->f_refs->s2[i]=MallocString(filename);
459  | 
460  |  for(func=file->functions;func;func=func->next)
461  |     for(i=0;i<func->f_refs->n;i++)
462  |        if(!strcmp(called,func->f_refs->s1[i]))
463  |           func->f_refs->s2[i]=MallocString(filename);
464  | }
465  | 
466  | 
467  | /*++++++++++++++++++++++++++++++++++++++
468  |   Check through all of the variables in this file to see if any of them are extern usage of others.
469  | 
470  |   File file The file structure.
471  | 
472  |   char* variable The global variable name.
473  | 
474  |   char* filename The file that the variable is used in.
475  | 
476  |   int scope The scope of the variable in the foreign file.
477  | 
478  |   char* funcname The name of a function that uses the variable.
479  |   ++++++++++++++++++++++++++++++++++++++*/
480  | 
481  | static void check_for_var(File file,char* variable,char* filename,int scope,char* funcname)
482  | {
483  |  Variable var;
484  | 
485  |  if(!funcname)
486  |    {
487  |     if(!(scope&(GLOBAL|EXTERNAL|EXTERN_H)))
488  |        return;
489  | 
490  |     for(var=file->variables;var;var=var->next)
491  |        if((scope&GLOBAL && var->scope&(EXTERNAL|EXTERN_H|EXTERN_F)) ||
492  |           (scope&(GLOBAL|EXTERNAL|EXTERN_H) && var->scope&GLOBAL))
493  |           if(!strcmp(variable,var->name))
494  |             {
495  |              if(scope&GLOBAL && var->scope&(EXTERNAL|EXTERN_H|EXTERN_F))
496  |                 var->defined=MallocString(filename);
497  | 
498  |              if(scope&(GLOBAL|EXTERNAL|EXTERN_H) && var->scope&GLOBAL)
499  |                 AddToStringList2(var->visible,"$",filename,1,0);
500  |             }
501  |    }
502  |  else
503  |    {
504  |     for(var=file->variables;var;var=var->next)
505  |        if(!strcmp(variable,var->name))
506  |          {
507  |           if(funcname[0]=='$' && !funcname[1])
508  |              AddToStringList2(var->used,"$",filename,1,0);
509  |           else
510  |             {
511  |              AddToStringList2(var->used,funcname,filename,1,1);
512  | 
513  |              if(scope&EXTERN_F && var->scope&GLOBAL)
514  |                 AddToStringList2(var->visible,funcname,filename,1,1);
515  |             }
516  |          }
517  |    }
518  | }
519  | 
520  | 
521  | /*++++++++++++++++++++++++++++++++++++++
522  |   Check through the function to see if it uses the variable, if func is NULL then check the file.
523  | 
524  |   int check_for_var_func Returns 1 if the variable is referenced from the function or file.
525  | 
526  |   File file The file that the function belongs to.
527  | 
528  |   Variable var The variable that may be referenced.
529  | 
530  |   Function func The function that is to be checked.
531  |   ++++++++++++++++++++++++++++++++++++++*/
532  | 
533  | static int check_for_var_func(File file,Variable var,Function func)
534  | {
535  |  int i;
536  | 
537  |  if(func)
538  |    {
539  |     for(i=0;i<func->v_refs->n;i++)
540  |        if(!strcmp(var->name,func->v_refs->s1[i]))
541  |          {
542  |           AddToStringList2(var->used,func->name,file->name,1,1);
543  |           if(var->scope&(GLOBAL|LOCAL))
544  |              func->v_refs->s2[i]=MallocString(file->name);
545  |           else
546  |             {
547  |              if(func->v_refs->s2[i]) Free(func->v_refs->s2[i]);
548  |              func->v_refs->s2[i]=MallocString("$");
549  |             }
550  |           return(1);
551  |          }
552  |    }
553  |  else
554  |    {
555  |     for(i=0;i<file->v_refs->n;i++)
556  |        if(!strcmp(var->name,file->v_refs->s1[i]))
557  |          {
558  |           AddToStringList2(var->used,"$",file->name,1,0);
559  |           if(var->scope&(GLOBAL|LOCAL))
560  |              file->v_refs->s2[i]=MallocString(file->name);
561  |           else
562  |             {
563  |              if(file->v_refs->s2[i]) Free(file->v_refs->s2[i]);
564  |              file->v_refs->s2[i]=MallocString("$");
565  |             }
566  |           return(1);
567  |          }
568  |    }
569  | 
570  |  return(0);
571  | }
572  | 
573  | 
574  | /*++++++++++++++++++++++++++++++++++++++
575  |   We can only now put in the location of the external variables that we found were used.
576  |   Previously we did not know the location of their global definition.
577  | 
578  |   Variable var The list of variables for this file.
579  | 
580  |   StringList2 refs A list of variable references from a file or a function.
581  |   ++++++++++++++++++++++++++++++++++++++*/
582  | 
583  | static void fixup_extern_var(Variable var,StringList2 refs)
584  | {
585  |  int i;
586  |  Variable v;
587  | 
588  |  for(i=0;i<refs->n;i++)
589  |    {
590  |     if(refs->s2[i][0]=='$' && !refs->s2[i][1])
591  |        for(v=var;v;v=v->next)
592  |           if(v->scope&(EXTERNAL|EXTERN_H|EXTERN_F) && !strcmp(refs->s1[i],v->name))
593  |             {
594  |              if(v->defined)
595  |                {
596  |                 Free(refs->s2[i]);
597  |                 refs->s2[i]=MallocString(v->defined);
598  |                }
599  |              else
600  |                {
601  |                 Free(refs->s1[i]);
602  |                 refs->s1[i]=MallocString(v->name);
603  |                 Free(refs->s2[i]);
604  |                 refs->s2[i]=NULL;
605  |                }
606  | 
607  |              break;
608  |             }
609  |    }
610  | }
611  | 
612  | 
613  | /*++++++++++++++++++++++++++++++++++++++
614  |   Create the appendix of files, global functions, global variables and types.
615  | 
616  |   StringList files The list of files to create.
617  | 
618  |   StringList2 funcs The list of functions to create.
619  | 
620  |   StringList2 vars The list of variables to create.
621  | 
622  |   StringList2 types The list of types to create.
623  |   ++++++++++++++++++++++++++++++++++++++*/
624  | 
625  | void CreateAppendix(StringList files,StringList2 funcs,StringList2 vars,StringList2 types)
626  | {
627  |  FILE *in;
628  |  char *ifile;
629  | 
630  |  if(option_index&INDEX_FILE) /* First do the files */
631  |    {
632  |     ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE);
633  | 
634  |     in =fopen(ifile,"r");
635  | 
636  |     if(in)
637  |       {
638  |        char include[FILE_MAX_LEN+1],filename[FILE_MAX_LEN+1],ch;
639  | 
640  |        while(fscanf(in,"%s%c",filename,&ch)==2)
641  |          {
642  |           AddToStringList(files,filename,1,1);
643  |           while(ch==' ')
644  |              fscanf(in,"%s%c",include,&ch);
645  |          }
646  | 
647  |        fclose(in);
648  |       }
649  |    }
650  | 
651  |  if(option_index&INDEX_FUNC) /* Now do the functions */
652  |    {
653  |     ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE);
654  | 
655  |     in =fopen(ifile,"r");
656  | 
657  |     if(in)
658  |       {
659  |        char ch,caller[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],called[FUNC_MAX_LEN+1];
660  |        int scope;
661  | 
662  |        while(fscanf(in,"%s %s %d%c",filename,caller,&scope,&ch)==4)
663  |          {
664  |           if(scope&GLOBAL)
665  |              AddToStringList2(funcs,caller,filename,1,1);
666  |           while(ch==' ')
667  |              fscanf(in,"%s%c",called,&ch);
668  |          }
669  | 
670  |        fclose(in);
671  |       }
672  |    }
673  | 
674  |  if(option_index&INDEX_VAR) /* Now do the variables */
675  |    {
676  |     ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE);
677  | 
678  |     in =fopen(ifile,"r");
679  | 
680  |     if(in)
681  |       {
682  |        char variable[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],funcname[FUNC_MAX_LEN+1],ch;
683  |        int scope;
684  | 
685  |        while(fscanf(in,"%s %s %d%c",filename,variable,&scope,&ch)==4)
686  |          {
687  |           if(scope&GLOBAL)
688  |              AddToStringList2(vars,variable,filename,1,1);
689  |           while(ch==' ')
690  |              fscanf(in,"%s%c",funcname,&ch);
691  |          }
692  | 
693  |        fclose(in);
694  |       }
695  |    }
696  | 
697  |  if(option_index&INDEX_TYPE) /* Now do the types */
698  |    {
699  |     ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE);
700  | 
701  |     in =fopen(ifile,"r");
702  | 
703  |     if(in)
704  |       {
705  |        char typename[TYPE_MAX_LEN],filename[FILE_MAX_LEN+1];
706  | 
707  |        while(fscanf(in,"%s %s",filename,typename)==2)
708  |          {
709  |           if(typename[0]=='#')
710  |             {
711  |              fgets(typename,TYPE_MAX_LEN,in);
712  |              typename[strlen(typename)-1]=0;
713  |              AddToStringList2(types,&typename[1],filename,1,1);
714  |             }
715  |           else
716  |             {
717  |              AddToStringList2(types,typename,filename,1,1);
718  |              fgets(typename,TYPE_MAX_LEN,in);
719  |             }
720  |          }
721  | 
722  |        fclose(in);
723  |       }
724  |    }
725  | }
726  | 
727  | 
728  | /*++++++++++++++++++++++++++++++++++++++
729  |   Delete the named file from the cross reference database.
730  | 
731  |   char *name The name of the file that is to be deleted.
732  |   ++++++++++++++++++++++++++++++++++++++*/
733  | 
734  | void CrossReferenceDelete(char *name)
735  | {
736  |  FILE *in,*out;
737  |  char *ifile,*ofile;
738  | 
739  |  /* First do the files */
740  | 
741  |  ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE);
742  |  ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_BACKUP);
743  | 
744  |  in =fopen(ifile,"r");
745  |  out=fopen(ofile,"w");
746  | 
747  |  if(in && !out)
748  |    {fprintf(stderr,"cxref: Failed to open the include cross reference file '%s'\n",ofile);fclose(in);}
749  |  else if(in)
750  |    {
751  |     char include[FILE_MAX_LEN+1],filename[FILE_MAX_LEN+1],ch;
752  | 
753  |     while(fscanf(in,"%s%c",filename,&ch)==2)
754  |       {
755  |        int diff_file=strcmp(filename,name);
756  | 
757  |        if(diff_file)
758  |           fprintf(out,"%s",filename);
759  | 
760  |        while(ch==' ')
761  |          {
762  |           fscanf(in,"%s%c",include,&ch);
763  | 
764  |           if(diff_file)
765  |              fprintf(out," %s",include);
766  |          }
767  | 
768  |        if(diff_file)
769  |           fprintf(out,"\n");
770  |       }
771  | 
772  |     fclose(in);
773  |     unlink(ifile);
774  | 
775  |     fclose(out);
776  |     rename(ofile,ifile);
777  |    }
778  |  else if(out)
779  |    {
780  |     fclose(out);
781  |     unlink(ofile);
782  |    }
783  | 
784  |  /* Now do the functions */
785  | 
786  |  ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE);
787  |  ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_BACKUP);
788  | 
789  |  in =fopen(ifile,"r");
790  |  out=fopen(ofile,"w");
791  | 
792  |  if(in && !out)
793  |    {fprintf(stderr,"cxref: Failed to open the functional cross reference file '%s'\n",ofile);fclose(in);}
794  |  else if(in)
795  |    {
796  |     char ch,funcname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],called[FUNC_MAX_LEN+1];
797  |     int scope;
798  | 
799  |     while(fscanf(in,"%s %s %d%c",filename,funcname,&scope,&ch)==4)
800  |       {
801  |        int diff_file=strcmp(filename,name);
802  | 
803  |        if(diff_file)
804  |           fprintf(out,"%s %s %d",filename,funcname,scope);
805  | 
806  |        while(ch==' ')
807  |          {
808  |           fscanf(in,"%s%c",called,&ch);
809  |           if(diff_file)
810  |              fprintf(out," %s",called);
811  |          }
812  | 
813  |        if(diff_file)
814  |           fprintf(out,"\n");
815  |       }
816  | 
817  |     fclose(in);
818  |     unlink(ifile);
819  | 
820  |     fclose(out);
821  |     rename(ofile,ifile);
822  |    }
823  |  else if(out)
824  |    {
825  |     fclose(out);
826  |     unlink(ofile);
827  |    }
828  | 
829  |  /* Now do the variables */
830  | 
831  |  ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE);
832  |  ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_BACKUP);
833  | 
834  |  in =fopen(ifile,"r");
835  |  out=fopen(ofile,"w");
836  | 
837  |  if(in && !out)
838  |    {fprintf(stderr,"cxref: Failed to open the variable cross reference file '%s'\n",ofile);fclose(in);}
839  |  else if(in)
840  |    {
841  |     char varname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],funcname[FUNC_MAX_LEN+1],ch;
842  |     int scope;
843  | 
844  |     while(fscanf(in,"%s %s %d%c",filename,varname,&scope,&ch)==4)
845  |       {
846  |        int diff_file=strcmp(filename,name);
847  | 
848  |        if(diff_file)
849  |           fprintf(out,"%s %s %d",filename,varname,scope);
850  | 
851  |        while(ch==' ')
852  |          {
853  |           fscanf(in,"%s%c",funcname,&ch);
854  | 
855  |           if(diff_file)
856  |              fprintf(out," %s",funcname);
857  |          }
858  | 
859  |        if(diff_file)
860  |           fprintf(out,"\n");
861  |       }
862  | 
863  |     fclose(in);
864  |     unlink(ifile);
865  | 
866  |     fclose(out);
867  |     rename(ofile,ifile);
868  |    }
869  |  else if(out)
870  |    {
871  |     fclose(out);
872  |     unlink(ofile);
873  |    }
874  | 
875  |  /* Now do the types */
876  | 
877  |  ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE);
878  |  ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_BACKUP);
879  | 
880  |  in =fopen(ifile,"r");
881  |  out=fopen(ofile,"w");
882  | 
883  |  if(in && !out)
884  |    {fprintf(stderr,"cxref: Failed to open the typedef reference file '%s'\n",ofile);fclose(in);}
885  |  else if(in)
886  |    {
887  |     char typename[TYPE_MAX_LEN+1],filename[FILE_MAX_LEN+1];
888  | 
889  |     while(fscanf(in,"%s %s",filename,typename)==2)
890  |       {
891  |        int diff_file=strcmp(filename,name);
892  | 
893  |        if(diff_file)
894  |           fprintf(out,"%s %s",filename,typename);
895  | 
896  |        fgets(typename,TYPE_MAX_LEN,in);
897  | 
898  |        if(diff_file)
899  |           fputs(typename,out);
900  |       }
901  | 
902  |     fclose(in);
903  |     unlink(ifile);
904  | 
905  |     fclose(out);
906  |     rename(ofile,ifile);
907  |    }
908  |  else if(out)
909  |    {
910  |     fclose(out);
911  |     unlink(ofile);
912  |    }
913  | }