1 | /*************************************** 2 | $Header: /home/amb/cxref/RCS/preproc.c 1.20 2001/01/06 13:05:13 amb Exp $ 3 | 4 | C Cross Referencing & Documentation tool. Version 1.5c. 5 | 6 | Collects the pre-processing instruction stuff. 7 | ******************/ /****************** 8 | Written by Andrew M. Bishop 9 | 10 | This file Copyright 1995,96,97,99,2001 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 for this file. +*/ 17 | #define DEBUG 0 18 | 19 | #include <stdlib.h> 20 | #include <stdio.h> 21 | #include <string.h> 22 | #include <unistd.h> 23 | 24 | #include <limits.h> 25 | #include <sys/stat.h> 26 | 27 | #include "memory.h" 28 | #include "datatype.h" 29 | #include "parse-yy.h" 30 | #include "cxref.h" 31 | 32 | /*+ The file that is currently being processed. +*/ 33 | extern File CurFile; 34 | 35 | /*+ The name of the include directories specified on the command line. +*/ 36 | extern char **option_incdirs; 37 | 38 | /*+ The number of include directories on the command line. +*/ 39 | extern int option_nincdirs; 40 | 41 | /*+ When in a header file, this is set to 1, to allow most of the stuff to be skipped. +*/ 42 | int in_header=0; 43 | 44 | /*+ The current #include we are looking at. +*/ 45 | static Include cur_inc=NULL; 46 | 47 | /*+ The current #define we are looking at. +*/ 48 | static Define cur_def=NULL; 49 | 50 | /*+ The depth of includes. +*/ 51 | static int inc_depth=0; 52 | 53 | /*+ The type of include at this depth. +*/ 54 | static char *inc_type=NULL; 55 | 56 | /*+ The name of the include file at this depth. +*/ 57 | static char **inc_name=NULL; 58 | 59 | /*+ The working directory. +*/ 60 | static char *cwd=NULL; 61 | 62 | 63 | static Include NewIncludeType(char *name); 64 | static Define NewDefineType(char *name); 65 | 66 | 67 | /*++++++++++++++++++++++++++++++++++++++ 68 | Function that is called when an included file is seen in the current file. 69 | 70 | char *name The name of the file from the source code. 71 | ++++++++++++++++++++++++++++++++++++++*/ 72 | 73 | void SeenInclude(char *name) 74 | { 75 | #if DEBUG 76 | printf("#Preproc.c# #include %s\n",name); 77 | #endif 78 | 79 | if(!inc_type || inc_depth==0 || inc_type[inc_depth-1]==LOCAL) 80 | { 81 | Include inc,*t=&CurFile->includes; 82 | int inc_scope=(*name=='"')?LOCAL:GLOBAL; 83 | int i; 84 | 85 | name++; 86 | name[strlen(name)-1]=0; 87 | 88 | if(inc_scope==LOCAL && option_nincdirs) 89 | for(i=0;i<option_nincdirs;i++) 90 | { 91 | char *newname=CanonicaliseName(ConcatStrings(3,option_incdirs[i],"/",name)); 92 | struct stat buf; 93 | 94 | if(!lstat(newname,&buf)) 95 | {name=newname;break;} 96 | } 97 | 98 | for(i=0;i<inc_depth;i++) 99 | { 100 | while(*t && (*t)->next) 101 | t=&(*t)->next; 102 | t=&(*t)->includes; 103 | } 104 | 105 | inc=NewIncludeType(name); 106 | 107 | inc->comment=MallocString(GetCurrentComment()); 108 | inc->scope=inc_scope; 109 | 110 | AddToLinkedList(*t,Include,inc); 111 | 112 | cur_inc=inc; 113 | } 114 | else 115 | cur_inc=NULL; 116 | } 117 | 118 | 119 | /*++++++++++++++++++++++++++++++++++++++ 120 | Function that is called when a comment is seen following a #include. 121 | ++++++++++++++++++++++++++++++++++++++*/ 122 | 123 | void SeenIncludeComment(void) 124 | { 125 | char* comment=GetCurrentComment(); 126 | 127 | #if DEBUG 128 | printf("#Preproc.c# #include trailing comment '%s' for %s\n",comment,cur_inc->name); 129 | #endif 130 | 131 | if(!cur_inc->comment) 132 | cur_inc->comment=MallocString(comment); 133 | } 134 | 135 | 136 | /*++++++++++++++++++++++++++++++++++++++ 137 | Function that is called when a change in current file is seen. 138 | 139 | char *SeenFileChange Returns the filename that we are now in. 140 | 141 | char *name The pathname of the included file as determined by gcc. 142 | 143 | int flag The flags that GCC leaves in the file 144 | ++++++++++++++++++++++++++++++++++++++*/ 145 | 146 | char *SeenFileChange(char *name,int flag) 147 | { 148 | if(!cwd) 149 | { 150 | cwd=(char*)Malloc(PATH_MAX+1); 151 | if(!getcwd(cwd,PATH_MAX)) 152 | cwd[0]=0; 153 | } 154 | 155 | name=CanonicaliseName(name); 156 | 157 | if(!strncmp(name,cwd,strlen(cwd))) 158 | name=name+strlen(cwd); 159 | 160 | if(flag&4) 161 | { 162 | if(inc_depth>=2) 163 | name=inc_name[inc_depth-2]; 164 | else 165 | name=CurFile->name; 166 | } 167 | 168 | #if DEBUG 169 | printf("#Preproc.c# FileChange - %s %s (flag=%d)\n",flag&2?"Included ":"Return to",name,flag); 170 | #endif 171 | 172 | /* Store the information. */ 173 | 174 | if(flag&2 && (!inc_type || inc_depth==0 || inc_type[inc_depth-1]==LOCAL)) 175 | { 176 | if(!cur_inc) 177 | { 178 | if(flag&8) 179 | SeenInclude(ConcatStrings(3,"<",name,">")); 180 | else 181 | SeenInclude(ConcatStrings(3,"\"",name,"\"")); 182 | } 183 | else if(!(flag&8)) 184 | { 185 | Free(cur_inc->name); 186 | cur_inc->name=MallocString(name); 187 | } 188 | } 189 | 190 | if(flag&2) 191 | { 192 | inc_depth++; 193 | 194 | if(!inc_type) 195 | { 196 | inc_type=(char*)Malloc(16); 197 | inc_name=(char**)Malloc(16*sizeof(char*)); 198 | } 199 | else 200 | if(!(inc_depth%16)) 201 | { 202 | inc_type=(char*)Realloc(inc_type,(unsigned)(inc_depth+16)); 203 | inc_name=(char**)Realloc(inc_name,(unsigned)(sizeof(char*)*(inc_depth+16))); 204 | } 205 | 206 | if(inc_depth>1 && inc_type[inc_depth-2]==GLOBAL) 207 | inc_type[inc_depth-1]=GLOBAL; 208 | else 209 | inc_type[inc_depth-1]=cur_inc?cur_inc->scope:(flag&8)?GLOBAL:LOCAL; 210 | 211 | inc_name[inc_depth-1]=CopyString(name); 212 | } 213 | else 214 | inc_depth--; 215 | 216 | if(inc_type && inc_depth>0) 217 | in_header=inc_type[inc_depth-1]; 218 | else 219 | in_header=0; 220 | 221 | SetCurrentComment(NULL); 222 | 223 | cur_inc=NULL; 224 | 225 | return(name); 226 | } 227 | 228 | 229 | /*++++++++++++++++++++++++++++++++++++++ 230 | Function that is called when a #define is seen in the current file. 231 | 232 | char* name The name of the #defined symbol. 233 | ++++++++++++++++++++++++++++++++++++++*/ 234 | 235 | void SeenDefine(char* name) 236 | { 237 | Define def; 238 | 239 | #if DEBUG 240 | printf("#Preproc.c# Defined name '%s'\n",name); 241 | #endif 242 | 243 | def=NewDefineType(name); 244 | 245 | def->comment=MallocString(GetCurrentComment()); 246 | 247 | def->lineno=parse_line; 248 | 249 | AddToLinkedList(CurFile->defines,Define,def); 250 | 251 | cur_def=def; 252 | } 253 | 254 | 255 | /*++++++++++++++++++++++++++++++++++++++ 256 | Function that is called when a comment is seen in a #define definition. 257 | ++++++++++++++++++++++++++++++++++++++*/ 258 | 259 | void SeenDefineComment(void) 260 | { 261 | char* comment=GetCurrentComment(); 262 | 263 | #if DEBUG 264 | printf("#Preproc.c# #define inline comment '%s' in %s\n",comment,cur_def->name); 265 | #endif 266 | 267 | if(!cur_def->comment) 268 | cur_def->comment=MallocString(comment); 269 | } 270 | 271 | 272 | /*++++++++++++++++++++++++++++++++++++++ 273 | Function that is called when a #define value is seen in the current file. 274 | 275 | char* value The value of the #defined symbol. 276 | ++++++++++++++++++++++++++++++++++++++*/ 277 | 278 | void SeenDefineValue(char* value) 279 | { 280 | #if DEBUG 281 | printf("#Preproc.c# #define value '%s' for %s\n",value,cur_def->name); 282 | #endif 283 | 284 | cur_def->value=MallocString(value); 285 | } 286 | 287 | 288 | /*++++++++++++++++++++++++++++++++++++++ 289 | Function that is called when a #define function argument is seen in the current definition. 290 | 291 | char* name The argument. 292 | ++++++++++++++++++++++++++++++++++++++*/ 293 | 294 | void SeenDefineFunctionArg(char* name) 295 | { 296 | #if DEBUG 297 | printf("#Preproc.c# #define Function arg '%s' in %s()\n",name,cur_def->name); 298 | #endif 299 | 300 | AddToStringList2(cur_def->args,name,SplitComment(&cur_def->comment,name),0,0); 301 | } 302 | 303 | 304 | /*++++++++++++++++++++++++++++++++++++++ 305 | Function that is called when a comment is seen in a #define function definition. 306 | ++++++++++++++++++++++++++++++++++++++*/ 307 | 308 | void SeenDefineFuncArgComment(void) 309 | { 310 | char* comment=GetCurrentComment(); 311 | 312 | #if DEBUG 313 | printf("#Preproc.c# #define Function arg comment '%s' in %s()\n",comment,cur_def->name); 314 | #endif 315 | 316 | if(!cur_def->args->s2[cur_def->args->n-1]) 317 | cur_def->args->s2[cur_def->args->n-1]=MallocString(comment); 318 | } 319 | 320 | 321 | /*++++++++++++++++++++++++++++++++++++++ 322 | Tidy up all of the local variables in case of a problem and abnormal parser termination. 323 | ++++++++++++++++++++++++++++++++++++++*/ 324 | 325 | void ResetPreProcAnalyser(void) 326 | { 327 | in_header=0; 328 | 329 | cur_inc=NULL; 330 | cur_def=NULL; 331 | 332 | inc_depth=0; 333 | 334 | if(inc_type) Free(inc_type); 335 | inc_type=NULL; 336 | if(inc_name) Free(inc_name); 337 | inc_name=NULL; 338 | 339 | if(cwd) Free(cwd); 340 | cwd=NULL; 341 | } 342 | 343 | 344 | /*++++++++++++++++++++++++++++++++++++++ 345 | Create a new Include datatype. 346 | 347 | Include NewIncludeType Return the new Include type. 348 | 349 | char *name The name of the new include. 350 | ++++++++++++++++++++++++++++++++++++++*/ 351 | 352 | static Include NewIncludeType(char *name) 353 | { 354 | Include inc=(Include)Calloc(1,sizeof(struct _Include)); 355 | 356 | inc->name=MallocString(name); 357 | 358 | return(inc); 359 | } 360 | 361 | 362 | /*++++++++++++++++++++++++++++++++++++++ 363 | Delete the specified Include type. 364 | 365 | Include inc The Include type to be deleted. 366 | ++++++++++++++++++++++++++++++++++++++*/ 367 | 368 | void DeleteIncludeType(Include inc) 369 | { 370 | if(inc->comment) Free(inc->comment); 371 | if(inc->name) Free(inc->name); 372 | if(inc->includes) 373 | { 374 | Include p=inc->includes; 375 | do{ 376 | Include n=p->next; 377 | DeleteIncludeType(p); 378 | p=n; 379 | } 380 | while(p); 381 | } 382 | Free(inc); 383 | } 384 | 385 | 386 | /*++++++++++++++++++++++++++++++++++++++ 387 | Create a new Define datatype. 388 | 389 | Define NewDefineType Return the new Define type. 390 | 391 | char *name The name of the new define. 392 | ++++++++++++++++++++++++++++++++++++++*/ 393 | 394 | static Define NewDefineType(char *name) 395 | { 396 | Define def=(Define)Calloc(1,sizeof(struct _Define)); /* clear unused pointers */ 397 | 398 | def->name=MallocString(name); 399 | def->args=NewStringList2(); 400 | 401 | return(def); 402 | } 403 | 404 | 405 | /*++++++++++++++++++++++++++++++++++++++ 406 | Delete the specified Define type. 407 | 408 | Define def The Define type to be deleted. 409 | ++++++++++++++++++++++++++++++++++++++*/ 410 | 411 | void DeleteDefineType(Define def) 412 | { 413 | if(def->comment) Free(def->comment); 414 | if(def->name) Free(def->name); 415 | if(def->value) Free(def->value); 416 | if(def->args) DeleteStringList2(def->args); 417 | Free(def); 418 | }