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 | }