    1    | /***************************************
    2    |   $Header: /home/amb/cxref/RCS/type.c 1.17 1999/01/24 16:53:49 amb Exp $
    3    |
    4    |   C Cross Referencing & Documentation tool. Version 1.5.
    5    |
    6    |   Collects the typedef 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 in this file. +*/
    17   | #define DEBUG 0
    18   |
    19   | #include <stdlib.h>
    20   | #include <stdio.h>
    21   | #include <string.h>
    22   |
    23   | #include "memory.h"
    24   | #include "datatype.h"
    25   | #include "parse-yy.h"
    26   | #include "cxref.h"
    27   |
    28   | /*+ The file that is currently being processed. +*/
    29   | extern File CurFile;
    30   |
    31   | /*+ Whether we are parsing a typedef or not. +*/
    32   | extern int in_typedef;
    33   |
    34   | /*+ The defined types that we have seen. +*/
    35   | static StringList2 typedefs=NULL;
    36   |
    37   | /*+ The current struct / union or enum definition. +*/
    38   | static StructUnion cur_su=NULL;
    39   |
    40   | /*+ The current struct / union if seen in a typedef. +*/
    41   | static StructUnion cur_type_su=NULL;
    42   |
    43   | /*+ The last typedef seen, used when two types share a typedef statement. +*/
    44   | static Typedef last_typedef=NULL;
    45   |
    46   | /*+ The line number that a typedef or structure was seen on. +*/
    47   | static int type_lineno=0;
    48   |
    49   | static Typedef NewTypedefType(char *name,char *type);
    50   | static StructUnion NewStructUnionType(char *name);
    51   | static void DeleteStructUnionType(StructUnion su);
    52   | static StructUnion CopyStructUnion(StructUnion su);
    53   |
    54   |
    55   | /*++++++++++++++++++++++++++++++++++++++
    56   |   Function that is called when a typedef is seen in the current file. The name of the typedef is stored for future reference.
    57   |
    58   |   char* name The name of the defined type.
    59   |
    60   |   int what_type Set to 1 for normal types or -1 for a function type (not pointer to function).
    61   |   ++++++++++++++++++++++++++++++++++++++*/
    62   |
    63   | void SeenTypedefName(char* name,int what_type)
    64   | {
    65   | #if DEBUG
    66   |  printf("#Type.c# Type defined '%s'\n",name);
    67   | #endif
    68   |
    69   |  if(!typedefs)
    70   |     typedefs=NewStringList2();
    71   |  AddToStringList2(typedefs,name,what_type==0?"\0":what_type>0?"n":"f",0,1);
    72   | }
    73   |
    74   |
    75   | /*++++++++++++++++++++++++++++++++++++++
    76   |   Function that is called when an IDENTIFIER is seen in the current file, it may be a defined type.
    77   |
    78   |   int IsATypeName Returns 1 if the argument is a type that has been defined.
    79   |
    80   |   char* name The name of the possible defined type.
    81   |   ++++++++++++++++++++++++++++++++++++++*/
    82   |
    83   | int IsATypeName(char* name)
    84   | {
    85   |  int i;
    86   |
    87   |  if(typedefs)
    88   |     for(i=0;i<typedefs->n;i++)
    89   |        if(!strcmp(name,typedefs->s1[i]))
    90   |           return((int)*typedefs->s2[i]);
    91   |
    92   |  return(0);
    93   | }
    94   |
    95   |
    96   | /*++++++++++++++++++++++++++++++++++++++
    97   |   Function that is called when the start of a struct or union or enum definition is seen.
    98   |
    99   |   char* name The name of the struct type.
    100  |   ++++++++++++++++++++++++++++++++++++++*/
    101  |
    102  | void SeenStructUnionStart(char* name)
    103  | {
    104  | #if DEBUG
    105  |  printf("#Type.c# Start Struct / Union '%s'\n",name);
    106  | #endif
    107  |
    108  |  cur_su=NewStructUnionType(name);
    109  |
    110  |  if(!in_typedef)
    111  |     cur_su->comment=MallocString(GetCurrentComment());
    112  |
    113  |  type_lineno=parse_line;
    114  | }
    115  |
    116  |
    117  | /*++++++++++++++++++++++++++++++++++++++
    118  |   Function called when a component of a struct / union / enum is seen.
    119  |
    120  |   char* name The name of the struct / union / enum component.
    121  |
    122  |   int depth The depth within the nested struct / union / enum.
    123  |   ++++++++++++++++++++++++++++++++++++++*/
    124  |
    125  | void SeenStructUnionComp(char* name,int depth)
    126  | {
    127  |  StructUnion s,t=cur_su;
    128  |  int i;
    129  |
    130  | #if DEBUG
    131  |  printf("#Type.c# Struct / Union Component (%d) '%s'\n",depth,name);
    132  | #endif
    133  |
    134  |  for(i=1;i<depth;i++,t=s)
    135  |     s=t->comps[t->n_comp-1];
    136  |
    137  |  if(t->comps && strchr(name,'{'))
    138  |    {
    139  |     char* ob=strchr(name,'{');
    140  |     char* cb=strchr(name,'}'),*nb;
    141  |
    142  |     while((nb=strchr(cb+1,'}'))) cb=nb;
    143  |     ob[1]=0;
    144  |     if(strcmp(name,"enum {") && strcmp(name,"union {") && strcmp(name,"struct {"))
    145  |       {
    146  |        Typedef typdef=NewTypedefType(t->comps[t->n_comp-1]->name,NULL);
    147  |
    148  |        typdef->comment=MallocString(GetCurrentComment());
    149  |        t->comps[t->n_comp-1]->comment=MallocString(typdef->comment);
    150  |
    151  |        typdef->sutype=CopyStructUnion(t->comps[t->n_comp-1]);
    152  |
    153  |        AddToLinkedList(CurFile->typedefs,Typedef,typdef);
    154  |       }
    155  |     else
    156  |        t->comps[t->n_comp-1]->comment=MallocString(GetCurrentComment());
    157  |
    158  |     Free(t->comps[t->n_comp-1]->name);
    159  |     t->comps[t->n_comp-1]->name=MallocString(ConcatStrings(3,name,"...",cb));
    160  |    }
    161  |  else
    162  |    {
    163  |     if(!t->comps)
    164  |        t->comps=(StructUnion*)Malloc(8*sizeof(StructUnion));
    165  |     else
    166  |        if(t->n_comp%8==0)
    167  |           t->comps=(StructUnion*)Realloc(t->comps,(t->n_comp+8)*sizeof(StructUnion));
    168  |
    169  |     s=NewStructUnionType(name);
    170  |     s->comment=MallocString(GetCurrentComment());
    171  |
    172  |     t->comps[t->n_comp++]=s;
    173  |    }
    174  | }
    175  |
    176  |
    177  | /*++++++++++++++++++++++++++++++++++++++
    178  |   Function that is called when the end of a struct or union or enum definition is seen.
    179  |   ++++++++++++++++++++++++++++++++++++++*/
    180  |
    181  | void SeenStructUnionEnd(void)
    182  | {
    183  | #if DEBUG
    184  |  printf("#Type.c# End Struct / Union\n");
    185  | #endif
    186  |
    187  |  if(in_typedef)
    188  |     cur_type_su=cur_su;
    189  |  else
    190  |    {
    191  |     Typedef xref=CurFile->typedefs;
    192  |     Typedef typdef=NewTypedefType(cur_su->name,NULL);
    193  |
    194  |     while(xref)
    195  |       {
    196  |        if(xref->type && !strncmp(cur_su->name,xref->type,strlen(cur_su->name)))
    197  |           xref->typexref=typdef;
    198  |        xref=xref->next;
    199  |       }
    200  |
    201  |     typdef->comment=cur_su->comment; cur_su->comment=NULL;
    202  |     typdef->sutype=cur_su;
    203  |
    204  |     typdef->lineno=type_lineno;
    205  |
    206  |     AddToLinkedList(CurFile->typedefs,Typedef,typdef);
    207  |    }
    208  |
    209  |  cur_su=NULL;
    210  | }
    211  |
    212  |
    213  | /*++++++++++++++++++++++++++++++++++++++
    214  |   Function that is called when a typedef is seen in the current file. This is recorded fully for later output.
    215  |
    216  |   char* name The name of the defined type.
    217  |
    218  |   char* type The type that it is defined to be.
    219  |   ++++++++++++++++++++++++++++++++++++++*/
    220  |
    221  | void SeenTypedef(char* name,char* type)
    222  | {
    223  |  Typedef typdef;
    224  |
    225  |  if(!name)
    226  |    {
    227  |     last_typedef=NULL;
    228  |     type_lineno=parse_line;
    229  |     return;
    230  |    }
    231  |
    232  | #if DEBUG
    233  |  printf("#Type.c# Typedef '%s' '%s'\n",name,type);
    234  | #endif
    235  |
    236  |  typdef=NewTypedefType(name,type);
    237  |
    238  |  typdef->comment=MallocString(GetCurrentComment());
    239  |
    240  |  if(!cur_type_su)
    241  |    {
    242  |     Typedef xref=CurFile->typedefs;
    243  |     typdef->sutype=NULL;
    244  |     typdef->typexref=NULL;
    245  |     while(xref)
    246  |       {
    247  |        if(!strncmp(xref->name,typdef->type,strlen(xref->name)))
    248  |           typdef->typexref=xref;
    249  |        xref=xref->next;
    250  |       }
    251  |     if(!typdef->typexref)
    252  |        typdef->typexref=last_typedef;
    253  |    }
    254  |  else
    255  |    {
    256  |     typdef->sutype=cur_type_su;
    257  |     cur_type_su=NULL;
    258  |     typdef->typexref=NULL;
    259  |    }
    260  |
    261  |  typdef->lineno=type_lineno;
    262  |
    263  |  if(!typdef->typexref)
    264  |     last_typedef=typdef;
    265  |
    266  |  AddToLinkedList(CurFile->typedefs,Typedef,typdef);
    267  | }
    268  |
    269  |
    270  | /*++++++++++++++++++++++++++++++++++++++
    271  |   Tidy up all of the local variables in case of a problem and abnormal parser termination.
    272  |   ++++++++++++++++++++++++++++++++++++++*/
    273  |
    274  | void ResetTypeAnalyser(void)
    275  | {
    276  |  if(typedefs) DeleteStringList2(typedefs);
    277  |  typedefs=NULL;
    278  |
    279  |  cur_su=NULL;
    280  |
    281  |  cur_type_su=NULL;
    282  |
    283  |  last_typedef=NULL;
    284  | }
    285  |
    286  |
    287  | /*++++++++++++++++++++++++++++++++++++++
    288  |   Create a new Typedef type.
    289  |
    290  |   Typedef NewTypedefType Returns the new type.
    291  |
    292  |   char *name The name of the type.
    293  |
    294  |   char *type The type of the type.
    295  |   ++++++++++++++++++++++++++++++++++++++*/
    296  |
    297  | static Typedef NewTypedefType(char *name,char *type)
    298  | {
    299  |  Typedef typed=(Typedef)Calloc(1,sizeof(struct _Typedef)); /* clear unused pointers */
    300  |
    301  |  typed->name=MallocString(name);
    302  |  typed->type=MallocString(type);
    303  |
    304  |  return(typed);
    305  | }
    306  |
    307  |
    308  | /*++++++++++++++++++++++++++++++++++++++
    309  |   Delete the specified Typedef type.
    310  |
    311  |   Typedef type The Typedef type to be deleted.
    312  |   ++++++++++++++++++++++++++++++++++++++*/
    313  |
    314  | void DeleteTypedefType(Typedef type)
    315  | {
    316  |  if(type->comment) Free(type->comment);
    317  |  if(type->name)    Free(type->name);
    318  |  if(type->type)    Free(type->type);
    319  |  if(type->sutype)  DeleteStructUnionType(type->sutype);
    320  |  Free(type);
    321  | }
    322  |
    323  |
    324  | /*++++++++++++++++++++++++++++++++++++++
    325  |   Create a new struct / union type.
    326  |
    327  |   StructUnion NewStructUnionType Return the new StructUnion type.
    328  |
    329  |   char *name The name of the new struct / union.
    330  |   ++++++++++++++++++++++++++++++++++++++*/
    331  |
    332  | static StructUnion NewStructUnionType(char *name)
    333  | {
    334  |  StructUnion su=(StructUnion)Calloc(1,sizeof(struct _StructUnion));
    335  |
    336  |  su->name=MallocString(name);
    337  |
    338  |  return(su);
    339  | }
    340  |
    341  |
    342  | /*++++++++++++++++++++++++++++++++++++++
    343  |   Free the memory associated with a Struct / Union structure.
    344  |
    345  |   StructUnion su The struct / union to delete.
    346  |
    347  |   This needs to call itself recursively.
    348  |   ++++++++++++++++++++++++++++++++++++++*/
    349  |
    350  | static void DeleteStructUnionType(StructUnion su)
    351  | {
    352  |  int i;
    353  |
    354  |  if(su->name)    Free(su->name);
    355  |  if(su->comment) Free(su->comment);
    356  |  for(i=0;i<su->n_comp;i++)
    357  |     if(su->comps[i])
    358  |        DeleteStructUnionType(su->comps[i]);
    359  |  if(su->comps)   Free(su->comps);
    360  |  Free(su);
    361  | }
    362  |
    363  |
    364  | /*++++++++++++++++++++++++++++++++++++++
    365  |   Make a copy of the specified Struct / Union structure.
    366  |
    367  |   StructUnion CopyStructUnion Returns a malloced copy of the specified struct / union.
    368  |
    369  |   StructUnion su The struct / union to copy.
    370  |
    371  |   This needs to call itself recursively.
    372  |   ++++++++++++++++++++++++++++++++++++++*/
    373  |
    374  | static StructUnion CopyStructUnion(StructUnion su)
    375  | {
    376  |  StructUnion new;
    377  |  int i;
    378  |
    379  |  new=NewStructUnionType(su->name);
    380  |
    381  |  new->comment=MallocString(su->comment);
    382  |  new->n_comp=su->n_comp;
    383  |  if(su->n_comp)
    384  |    {
    385  |     new->comps=(StructUnion*)Malloc(su->n_comp*sizeof(StructUnion));
    386  |     for(i=0;i<su->n_comp;i++)
    387  |        new->comps[i]=CopyStructUnion(su->comps[i]);
    388  |    }
    389  |
    390  |  return(new);
    391  | }