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