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