    1    | /***************************************
    2    |   $Header: /home/amb/cxref/RCS/preproc.c 1.16 1999/01/24 16:53:49 amb Exp $
    3    |
    4    |   C Cross Referencing & Documentation tool. Version 1.5.
    5    |
    6    |   Collects the pre-processing instruction stuff.
    7    |   ******************/ /******************
    8    |   Written by Andrew M. Bishop
    9    |
    10   |   This file Copyright 1995,96,97,99 Andrew M. Bishop
    11   |   It may be distributed under the GNU Public License, version 2, or
    12   |   any higher version.  See section COPYING of the GNU Public license
    13   |   for conditions under which this file may be redistributed.
    14   |   ***************************************/
    15   |
    16   | /*+ Control the output of debugging information for this file. +*/
    17   | #define DEBUG 0
    18   |
    19   | #include <stdlib.h>
    20   | #include <stdio.h>
    21   | #include <string.h>
    22   | #include <unistd.h>
    23   |
    24   | #include <sys/stat.h>
    25   |
    26   | #include "memory.h"
    27   | #include "datatype.h"
    28   | #include "parse-yy.h"
    29   | #include "cxref.h"
    30   |
    31   | /*+ The file that is currently being processed. +*/
    32   | extern File CurFile;
    33   |
    34   | /*+ The name of the include directories specified on the command line. +*/
    35   | extern char **option_incdirs;
    36   |
    37   | /*+ The number of include directories on the command line. +*/
    38   | extern int option_nincdirs;
    39   |
    40   | /*+ When in a header file, this is set to 1, to allow most of the stuff to be skipped. +*/
    41   | int in_header=0;
    42   |
    43   | /*+ The current #include we are looking at. +*/
    44   | static Include cur_inc=NULL;
    45   |
    46   | /*+ The current #define we are looking at. +*/
    47   | static Define cur_def=NULL;
    48   |
    49   | /*+ The depth of includes. +*/
    50   | static int inc_depth=0;
    51   |
    52   | /*+ The type of include at this depth. +*/
    53   | static char *inc_type=NULL;
    54   |
    55   | /*+ The working directory. +*/
    56   | static char *cwd=NULL;
    57   |
    58   |
    59   | static Include NewIncludeType(char *name);
    60   | static Define NewDefineType(char *name);
    61   |
    62   | #ifdef __EMX__
    63   | #define lstat	stat
    64   | #endif
    65   |
    66   | /*++++++++++++++++++++++++++++++++++++++
    67   |   Function that is called when an included file is seen in the current file.
    68   |
    69   |   char *name The name of the file from the source code.
    70   |   ++++++++++++++++++++++++++++++++++++++*/
    71   |
    72   | void SeenInclude(char *name)
    73   | {
    74   | #if DEBUG
    75   |  printf("#Preproc.c# #include %s\n",name);
    76   | #endif
    77   |
    78   |  if(!inc_type || inc_depth==0 || inc_type[inc_depth-1]==LOCAL)
    79   |    {
    80   |     Include inc,*t=&CurFile->includes;
    81   |     int inc_scope=(*name=='"')?LOCAL:GLOBAL;
    82   |     int i;
    83   |
    84   |     name++;
    85   |     name[strlen(name)-1]=0;
    86   |
    87   |     if(inc_scope==LOCAL && option_nincdirs)
    88   |        for(i=0;i<option_nincdirs;i++)
    89   |          {
    90   |           char *newname=CanonicaliseName(ConcatStrings(3,option_incdirs[i],"/",name));
    91   |           struct stat buf;
    92   |
    93   |           if(!lstat(newname,&buf))
    94   |             {name=newname;break;}
    95   |          }
    96   |
    97   |     for(i=0;i<inc_depth;i++)
    98   |       {
    99   |        while(*t && (*t)->next)
    100  |           t=&(*t)->next;
    101  |        t=&(*t)->includes;
    102  |       }
    103  |
    104  |     inc=NewIncludeType(name);
    105  |
    106  |     inc->comment=MallocString(GetCurrentComment());
    107  |     inc->scope=inc_scope;
    108  |
    109  |     AddToLinkedList(*t,Include,inc);
    110  |
    111  |     cur_inc=inc;
    112  |    }
    113  |  else
    114  |     cur_inc=NULL;
    115  | }
    116  |
    117  |
    118  | /*++++++++++++++++++++++++++++++++++++++
    119  |   Function that is called when a comment is seen following a #include.
    120  |   ++++++++++++++++++++++++++++++++++++++*/
    121  |
    122  | void SeenIncludeComment(void)
    123  | {
    124  |  char* comment=GetCurrentComment();
    125  |
    126  | #if DEBUG
    127  |  printf("#Preproc.c# #include trailing comment '%s' for %s\n",comment,cur_inc->name);
    128  | #endif
    129  |
    130  |  if(!cur_inc->comment)
    131  |     cur_inc->comment=MallocString(comment);
    132  | }
    133  |
    134  |
    135  | /*++++++++++++++++++++++++++++++++++++++
    136  |   Function that is called when a change in current file is seen.
    137  |
    138  |   char *name The pathname of the included file as determined by gcc.
    139  |
    140  |   int flag The flags that GCC leaves in the file
    141  |   ++++++++++++++++++++++++++++++++++++++*/
    142  |
    143  | void SeenFileChange(char *name,int flag)
    144  | {
    145  |  if(!cwd)
    146  |    {
    147  |     cwd=(char*)Malloc(256);
    148  |     if(!getcwd(cwd,255))
    149  |        cwd[0]=0;
    150  |    }
    151  |
    152  | #if DEBUG
    153  |  printf("#Preproc.c# FileChange - %s %s (flag=%d)\n",flag&2?"Included ":"Return to",name,flag);
    154  | #endif
    155  |
    156  |  name=CanonicaliseName(name);
    157  |
    158  |  if(!strncmp(name,cwd,strlen(cwd)))
    159  |     name=name+strlen(cwd);
    160  |
    161  |  /* Store the information. */
    162  |
    163  |  if(flag&2 && (!inc_type || inc_depth==0 || inc_type[inc_depth-1]==LOCAL))
    164  |    {
    165  |     if(!cur_inc)
    166  |       {
    167  |        if(flag&8)
    168  |           SeenInclude(ConcatStrings(3,"<",name,">"));
    169  |        else
    170  |           SeenInclude(ConcatStrings(3,"\"",name,"\""));
    171  |       }
    172  |     else if(!(flag&8))
    173  |       {
    174  |        Free(cur_inc->name);
    175  |        cur_inc->name=MallocString(name);
    176  |       }
    177  |    }
    178  |
    179  |  cur_inc=NULL;
    180  |
    181  |  if(flag&2)
    182  |    {
    183  |     inc_depth++;
    184  |
    185  |     if(!inc_type)
    186  |        inc_type=(char*)Malloc(16);
    187  |     else
    188  |        if(!(inc_depth%16))
    189  |           inc_type=(char*)Realloc(inc_type,(unsigned)(inc_depth+16));
    190  |
    191  |     if(inc_depth>1 && inc_type[inc_depth-2]==GLOBAL)
    192  |        inc_type[inc_depth-1]=GLOBAL;
    193  |     else
    194  |        inc_type[inc_depth-1]=(flag&8)?GLOBAL:LOCAL;
    195  |    }
    196  |  else
    197  |     inc_depth--;
    198  |
    199  |  if(inc_type && inc_depth>0)
    200  |     in_header=inc_type[inc_depth-1];
    201  |  else
    202  |     in_header=0;
    203  |
    204  |  SetCurrentComment(NULL);
    205  | }
    206  |
    207  |
    208  | /*++++++++++++++++++++++++++++++++++++++
    209  |   Function that is called when a #define is seen in the current file.
    210  |
    211  |   char* name The name of the #defined symbol.
    212  |   ++++++++++++++++++++++++++++++++++++++*/
    213  |
    214  | void SeenDefine(char* name)
    215  | {
    216  |  Define def;
    217  |
    218  | #if DEBUG
    219  |  printf("#Preproc.c# Defined name '%s'\n",name);
    220  | #endif
    221  |
    222  |  def=NewDefineType(name);
    223  |
    224  |  def->comment=MallocString(GetCurrentComment());
    225  |
    226  |  def->lineno=parse_line;
    227  |
    228  |  AddToLinkedList(CurFile->defines,Define,def);
    229  |
    230  |  cur_def=def;
    231  | }
    232  |
    233  |
    234  | /*++++++++++++++++++++++++++++++++++++++
    235  |   Function that is called when a comment is seen in a #define definition.
    236  |   ++++++++++++++++++++++++++++++++++++++*/
    237  |
    238  | void SeenDefineComment(void)
    239  | {
    240  |  char* comment=GetCurrentComment();
    241  |
    242  | #if DEBUG
    243  |  printf("#Preproc.c# #define inline comment '%s' in %s\n",comment,cur_def->name);
    244  | #endif
    245  |
    246  |  if(!cur_def->comment)
    247  |     cur_def->comment=MallocString(comment);
    248  | }
    249  |
    250  |
    251  | /*++++++++++++++++++++++++++++++++++++++
    252  |   Function that is called when a #define value is seen in the current file.
    253  |
    254  |   char* value The value of the #defined symbol.
    255  |   ++++++++++++++++++++++++++++++++++++++*/
    256  |
    257  | void SeenDefineValue(char* value)
    258  | {
    259  | #if DEBUG
    260  |  printf("#Preproc.c# #define value '%s' for %s\n",value,cur_def->name);
    261  | #endif
    262  |
    263  |  cur_def->value=MallocString(value);
    264  | }
    265  |
    266  |
    267  | /*++++++++++++++++++++++++++++++++++++++
    268  |   Function that is called when a #define function argument is seen in the current definition.
    269  |
    270  |   char* name The argument.
    271  |   ++++++++++++++++++++++++++++++++++++++*/
    272  |
    273  | void SeenDefineFunctionArg(char* name)
    274  | {
    275  | #if DEBUG
    276  |  printf("#Preproc.c# #define Function arg '%s' in %s()\n",name,cur_def->name);
    277  | #endif
    278  |
    279  |  AddToStringList2(cur_def->args,name,SplitComment(&cur_def->comment,name),0,0);
    280  | }
    281  |
    282  |
    283  | /*++++++++++++++++++++++++++++++++++++++
    284  |   Function that is called when a comment is seen in a #define function definition.
    285  |   ++++++++++++++++++++++++++++++++++++++*/
    286  |
    287  | void SeenDefineFuncArgComment(void)
    288  | {
    289  |  char* comment=GetCurrentComment();
    290  |
    291  | #if DEBUG
    292  |  printf("#Preproc.c# #define Function arg comment '%s' in %s()\n",comment,cur_def->name);
    293  | #endif
    294  |
    295  |  if(!cur_def->args->s2[cur_def->args->n-1])
    296  |     cur_def->args->s2[cur_def->args->n-1]=MallocString(comment);
    297  | }
    298  |
    299  |
    300  | /*++++++++++++++++++++++++++++++++++++++
    301  |   Tidy up all of the local variables in case of a problem and abnormal parser termination.
    302  |   ++++++++++++++++++++++++++++++++++++++*/
    303  |
    304  | void ResetPreProcAnalyser(void)
    305  | {
    306  |  in_header=0;
    307  |
    308  |  cur_inc=NULL;
    309  |  cur_def=NULL;
    310  |
    311  |  inc_depth=0;
    312  |
    313  |  if(inc_type) Free(inc_type);
    314  |  inc_type=NULL;
    315  |
    316  |  if(cwd) Free(cwd);
    317  |  cwd=NULL;
    318  | }
    319  |
    320  |
    321  | /*++++++++++++++++++++++++++++++++++++++
    322  |   Create a new Include datatype.
    323  |
    324  |   Include NewIncludeType Return the new Include type.
    325  |
    326  |   char *name The name of the new include.
    327  |   ++++++++++++++++++++++++++++++++++++++*/
    328  |
    329  | static Include NewIncludeType(char *name)
    330  | {
    331  |  Include inc=(Include)Calloc(1,sizeof(struct _Include));
    332  |
    333  |  inc->name=MallocString(name);
    334  |
    335  |  return(inc);
    336  | }
    337  |
    338  |
    339  | /*++++++++++++++++++++++++++++++++++++++
    340  |   Delete the specified Include type.
    341  |
    342  |   Include inc The Include type to be deleted.
    343  |   ++++++++++++++++++++++++++++++++++++++*/
    344  |
    345  | void DeleteIncludeType(Include inc)
    346  | {
    347  |  if(inc->comment) Free(inc->comment);
    348  |  if(inc->name)    Free(inc->name);
    349  |  if(inc->includes)
    350  |    {
    351  |     Include p=inc->includes;
    352  |     do{
    353  |        Include n=p->next;
    354  |        DeleteIncludeType(p);
    355  |        p=n;
    356  |       }
    357  |     while(p);
    358  |    }
    359  |  Free(inc);
    360  | }
    361  |
    362  |
    363  | /*++++++++++++++++++++++++++++++++++++++
    364  |   Create a new Define datatype.
    365  |
    366  |   Define NewDefineType Return the new Define type.
    367  |
    368  |   char *name The name of the new define.
    369  |   ++++++++++++++++++++++++++++++++++++++*/
    370  |
    371  | static Define NewDefineType(char *name)
    372  | {
    373  |  Define def=(Define)Calloc(1,sizeof(struct _Define)); /* clear unused pointers */
    374  |
    375  |  def->name=MallocString(name);
    376  |  def->args=NewStringList2();
    377  |
    378  |  return(def);
    379  | }
    380  |
    381  |
    382  | /*++++++++++++++++++++++++++++++++++++++
    383  |   Delete the specified Define type.
    384  |
    385  |   Define def The Define type to be deleted.
    386  |   ++++++++++++++++++++++++++++++++++++++*/
    387  |
    388  | void DeleteDefineType(Define def)
    389  | {
    390  |  if(def->comment) Free(def->comment);
    391  |  if(def->name)    Free(def->name);
    392  |  if(def->value)   Free(def->value);
    393  |  if(def->args)    DeleteStringList2(def->args);
    394  |  Free(def);
    395  | }