1    | /***************************************
2    |   $Header: /home/amb/cxref/src/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  | }