1    | /***************************************
2    |   $Header: /home/amb/CVS/cxref/src/type.c,v 1.18 2004-11-20 14:14:53 amb Exp $
3    | 
4    |   C Cross Referencing & Documentation tool. Version 1.6a.
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  |  if(cur_su)
109  |     DeleteStructUnionType(cur_su);
110  | 
111  |  cur_su=NewStructUnionType(name);
112  | 
113  |  if(!in_typedef)
114  |     cur_su->comment=MallocString(GetCurrentComment());
115  | 
116  |  type_lineno=parse_line;
117  | }
118  | 
119  | 
120  | /*++++++++++++++++++++++++++++++++++++++
121  |   Function called when a component of a struct / union / enum is seen.
122  | 
123  |   char* name The name of the struct / union / enum component.
124  | 
125  |   int depth The depth within the nested struct / union / enum.
126  |   ++++++++++++++++++++++++++++++++++++++*/
127  | 
128  | void SeenStructUnionComp(char* name,int depth)
129  | {
130  |  StructUnion s,t=cur_su;
131  |  int i;
132  | 
133  | #if DEBUG
134  |  printf("#Type.c# Struct / Union Component (%d) '%s'\n",depth,name);
135  | #endif
136  | 
137  |  for(i=1;i<depth;i++,t=s)
138  |     s=t->comps[t->n_comp-1];
139  | 
140  |  if(t->comps && strchr(name,'{'))
141  |    {
142  |     char* ob=strchr(name,'{');
143  |     char* cb=strchr(name,'}'),*nb;
144  | 
145  |     while((nb=strchr(cb+1,'}'))) cb=nb;
146  |     ob[1]=0;
147  |     if(strcmp(name,"enum {") && strcmp(name,"union {") && strcmp(name,"struct {"))
148  |       {
149  |        Typedef typdef=NewTypedefType(t->comps[t->n_comp-1]->name,NULL);
150  | 
151  |        typdef->comment=MallocString(GetCurrentComment());
152  |        t->comps[t->n_comp-1]->comment=MallocString(typdef->comment);
153  | 
154  |        typdef->sutype=CopyStructUnion(t->comps[t->n_comp-1]);
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  | }