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