1 | /*************************************** 2 | $Header: /home/amb/cxref/RCS/preproc.c 1.19 1999/07/21 18:26:21 amb Exp $ 3 | 4 | C Cross Referencing & Documentation tool. Version 1.5b. 5 | 6 | Collects the pre-processing instruction 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 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 | if(inc_depth>=2) 162 | name=inc_name[inc_depth-2]; 163 | else 164 | name=CurFile->name; 165 | 166 | #if DEBUG 167 | printf("#Preproc.c# FileChange - %s %s (flag=%d)\n",flag&2?"Included ":"Return to",name,flag); 168 | #endif 169 | 170 | /* Store the information. */ 171 | 172 | if(flag&2 && (!inc_type || inc_depth==0 || inc_type[inc_depth-1]==LOCAL)) 173 | { 174 | if(!cur_inc) 175 | { 176 | if(flag&8) 177 | SeenInclude(ConcatStrings(3,"<",name,">")); 178 | else 179 | SeenInclude(ConcatStrings(3,"\"",name,"\"")); 180 | } 181 | else if(!(flag&8)) 182 | { 183 | Free(cur_inc->name); 184 | cur_inc->name=MallocString(name); 185 | } 186 | } 187 | 188 | if(flag&2) 189 | { 190 | inc_depth++; 191 | 192 | if(!inc_type) 193 | { 194 | inc_type=(char*)Malloc(16); 195 | inc_name=(char**)Malloc(16*sizeof(char*)); 196 | } 197 | else 198 | if(!(inc_depth%16)) 199 | { 200 | inc_type=(char*)Realloc(inc_type,(unsigned)(inc_depth+16)); 201 | inc_name=(char**)Realloc(inc_name,(unsigned)(sizeof(char*)*(inc_depth+16))); 202 | } 203 | 204 | if(inc_depth>1 && inc_type[inc_depth-2]==GLOBAL) 205 | inc_type[inc_depth-1]=GLOBAL; 206 | else 207 | inc_type[inc_depth-1]=cur_inc?cur_inc->scope:(flag&8)?GLOBAL:LOCAL; 208 | 209 | inc_name[inc_depth-1]=CopyString(name); 210 | } 211 | else 212 | inc_depth--; 213 | 214 | if(inc_type && inc_depth>0) 215 | in_header=inc_type[inc_depth-1]; 216 | else 217 | in_header=0; 218 | 219 | SetCurrentComment(NULL); 220 | 221 | cur_inc=NULL; 222 | 223 | return(name); 224 | } 225 | 226 | 227 | /*++++++++++++++++++++++++++++++++++++++ 228 | Function that is called when a #define is seen in the current file. 229 | 230 | char* name The name of the #defined symbol. 231 | ++++++++++++++++++++++++++++++++++++++*/ 232 | 233 | void SeenDefine(char* name) 234 | { 235 | Define def; 236 | 237 | #if DEBUG 238 | printf("#Preproc.c# Defined name '%s'\n",name); 239 | #endif 240 | 241 | def=NewDefineType(name); 242 | 243 | def->comment=MallocString(GetCurrentComment()); 244 | 245 | def->lineno=parse_line; 246 | 247 | AddToLinkedList(CurFile->defines,Define,def); 248 | 249 | cur_def=def; 250 | } 251 | 252 | 253 | /*++++++++++++++++++++++++++++++++++++++ 254 | Function that is called when a comment is seen in a #define definition. 255 | ++++++++++++++++++++++++++++++++++++++*/ 256 | 257 | void SeenDefineComment(void) 258 | { 259 | char* comment=GetCurrentComment(); 260 | 261 | #if DEBUG 262 | printf("#Preproc.c# #define inline comment '%s' in %s\n",comment,cur_def->name); 263 | #endif 264 | 265 | if(!cur_def->comment) 266 | cur_def->comment=MallocString(comment); 267 | } 268 | 269 | 270 | /*++++++++++++++++++++++++++++++++++++++ 271 | Function that is called when a #define value is seen in the current file. 272 | 273 | char* value The value of the #defined symbol. 274 | ++++++++++++++++++++++++++++++++++++++*/ 275 | 276 | void SeenDefineValue(char* value) 277 | { 278 | #if DEBUG 279 | printf("#Preproc.c# #define value '%s' for %s\n",value,cur_def->name); 280 | #endif 281 | 282 | cur_def->value=MallocString(value); 283 | } 284 | 285 | 286 | /*++++++++++++++++++++++++++++++++++++++ 287 | Function that is called when a #define function argument is seen in the current definition. 288 | 289 | char* name The argument. 290 | ++++++++++++++++++++++++++++++++++++++*/ 291 | 292 | void SeenDefineFunctionArg(char* name) 293 | { 294 | #if DEBUG 295 | printf("#Preproc.c# #define Function arg '%s' in %s()\n",name,cur_def->name); 296 | #endif 297 | 298 | AddToStringList2(cur_def->args,name,SplitComment(&cur_def->comment,name),0,0); 299 | } 300 | 301 | 302 | /*++++++++++++++++++++++++++++++++++++++ 303 | Function that is called when a comment is seen in a #define function definition. 304 | ++++++++++++++++++++++++++++++++++++++*/ 305 | 306 | void SeenDefineFuncArgComment(void) 307 | { 308 | char* comment=GetCurrentComment(); 309 | 310 | #if DEBUG 311 | printf("#Preproc.c# #define Function arg comment '%s' in %s()\n",comment,cur_def->name); 312 | #endif 313 | 314 | if(!cur_def->args->s2[cur_def->args->n-1]) 315 | cur_def->args->s2[cur_def->args->n-1]=MallocString(comment); 316 | } 317 | 318 | 319 | /*++++++++++++++++++++++++++++++++++++++ 320 | Tidy up all of the local variables in case of a problem and abnormal parser termination. 321 | ++++++++++++++++++++++++++++++++++++++*/ 322 | 323 | void ResetPreProcAnalyser(void) 324 | { 325 | in_header=0; 326 | 327 | cur_inc=NULL; 328 | cur_def=NULL; 329 | 330 | inc_depth=0; 331 | 332 | if(inc_type) Free(inc_type); 333 | inc_type=NULL; 334 | if(inc_name) Free(inc_name); 335 | inc_name=NULL; 336 | 337 | if(cwd) Free(cwd); 338 | cwd=NULL; 339 | } 340 | 341 | 342 | /*++++++++++++++++++++++++++++++++++++++ 343 | Create a new Include datatype. 344 | 345 | Include NewIncludeType Return the new Include type. 346 | 347 | char *name The name of the new include. 348 | ++++++++++++++++++++++++++++++++++++++*/ 349 | 350 | static Include NewIncludeType(char *name) 351 | { 352 | Include inc=(Include)Calloc(1,sizeof(struct _Include)); 353 | 354 | inc->name=MallocString(name); 355 | 356 | return(inc); 357 | } 358 | 359 | 360 | /*++++++++++++++++++++++++++++++++++++++ 361 | Delete the specified Include type. 362 | 363 | Include inc The Include type to be deleted. 364 | ++++++++++++++++++++++++++++++++++++++*/ 365 | 366 | void DeleteIncludeType(Include inc) 367 | { 368 | if(inc->comment) Free(inc->comment); 369 | if(inc->name) Free(inc->name); 370 | if(inc->includes) 371 | { 372 | Include p=inc->includes; 373 | do{ 374 | Include n=p->next; 375 | DeleteIncludeType(p); 376 | p=n; 377 | } 378 | while(p); 379 | } 380 | Free(inc); 381 | } 382 | 383 | 384 | /*++++++++++++++++++++++++++++++++++++++ 385 | Create a new Define datatype. 386 | 387 | Define NewDefineType Return the new Define type. 388 | 389 | char *name The name of the new define. 390 | ++++++++++++++++++++++++++++++++++++++*/ 391 | 392 | static Define NewDefineType(char *name) 393 | { 394 | Define def=(Define)Calloc(1,sizeof(struct _Define)); /* clear unused pointers */ 395 | 396 | def->name=MallocString(name); 397 | def->args=NewStringList2(); 398 | 399 | return(def); 400 | } 401 | 402 | 403 | /*++++++++++++++++++++++++++++++++++++++ 404 | Delete the specified Define type. 405 | 406 | Define def The Define type to be deleted. 407 | ++++++++++++++++++++++++++++++++++++++*/ 408 | 409 | void DeleteDefineType(Define def) 410 | { 411 | if(def->comment) Free(def->comment); 412 | if(def->name) Free(def->name); 413 | if(def->value) Free(def->value); 414 | if(def->args) DeleteStringList2(def->args); 415 | Free(def); 416 | }