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