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