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