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