1 | /*************************************** 2 | $Header: /home/amb/CVS/cxref/src/xref.c,v 1.21 2002-06-23 15:57:36 amb Exp $ 3 | 4 | C Cross Referencing & Documentation tool. Version 1.5e. 5 | 6 | Cross referencing of functions. 7 | ******************/ /****************** 8 | Written by Andrew M. Bishop 9 | 10 | This file Copyright 1995,96,97,98,99,2000,01,02 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 | /*+ The names of the function cross reference files. +*/ 17 | #define XREF_FUNC_FILE ".function" 18 | #define XREF_FUNC_BACKUP ".function~" 19 | 20 | /*+ The names of the variable cross reference files. +*/ 21 | #define XREF_VAR_FILE ".variable" 22 | #define XREF_VAR_BACKUP ".variable~" 23 | 24 | /*+ The names of the include cross reference files. +*/ 25 | #define XREF_INC_FILE ".include" 26 | #define XREF_INC_BACKUP ".include~" 27 | 28 | /*+ The names of the type cross reference files. +*/ 29 | #define XREF_TYPE_FILE ".typedef" 30 | #define XREF_TYPE_BACKUP ".typedef~" 31 | 32 | #include <stdlib.h> 33 | #include <stdio.h> 34 | #include <string.h> 35 | #include <unistd.h> 36 | #include <limits.h> 37 | 38 | #define TYPE_MAX_LEN 256 /*+ The maximum type definition length +*/ 39 | #define FUNC_MAX_LEN 64 /*+ The maximum function name length. +*/ 40 | #if defined(PATH_MAX) && defined(NAME_MAX) 41 | #define FILE_MAX_LEN (PATH_MAX+NAME_MAX) /*+ The maximum filename length. +*/ 42 | #elif defined(PATH_MAX) 43 | #define FILE_MAX_LEN (PATH_MAX+256) /*+ The maximum filename length. +*/ 44 | #else 45 | #define FILE_MAX_LEN 512 /*+ The maximum filename length. +*/ 46 | #endif 47 | 48 | #include "memory.h" 49 | #include "datatype.h" 50 | #include "cxref.h" 51 | 52 | /*+ The name of the directory for the output. +*/ 53 | extern char* option_odir; 54 | 55 | /*+ The base name of the file for the output. +*/ 56 | extern char* option_name; 57 | 58 | /*+ The option for cross referencing. +*/ 59 | extern int option_xref; 60 | 61 | /*+ The option for indexing. +*/ 62 | extern int option_index; 63 | 64 | static void check_for_called(File file,char* called,char* caller,char* filename); 65 | static void check_for_caller(File file,char* called,char* filename); 66 | static void check_for_var(File file,char* variable,char* filename,int scope,char* funcname); 67 | static int check_for_var_func(File file,Variable var,Function func); 68 | static void fixup_extern_var(Variable var,StringList2 refs); 69 | 70 | /*++++++++++++++++++++++++++++++++++++++ 71 | Cross reference the functions, variables and includes that are used in this file 72 | with the global functions, variables and includes. The types that are defined are also listed here. 73 | 74 | File file The file structure containing the information. 75 | 76 | int outputs Set to true if any cross referencing to produce outputs is required. 77 | ++++++++++++++++++++++++++++++++++++++*/ 78 | #include <errno.h> 79 | #define massert(a_) \ 80 | ({errno=0;\ 81 | if (!(a_)||errno) {\ 82 | fprintf(stderr,"The assertion %s on line %d of %s in function %s failed: %s",\ 83 | #a_,__LINE__,__FILE__,__FUNCTION__,strerror(errno));\ 84 | exit(1);\ 85 | }\ 86 | }) 87 | 88 | void CrossReference(File file,int outputs) 89 | { 90 | FILE *in,*out; 91 | char *ifile,*ofile; 92 | 93 | /* Format: filename [[%]include1] [[%]include2] ... : Files include1, include2, ... are included in filename; 94 | those with a % are local. */ 95 | 96 | if(option_xref&XREF_FILE) /* First do the files */ 97 | { 98 | Include inc; 99 | 100 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE); 101 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_BACKUP); 102 | 103 | in =fopen(ifile,"r"); 104 | out=fopen(ofile,"w"); 105 | 106 | if(!out) 107 | {fprintf(stderr,"cxref: Failed to open the include cross reference file '%s'\n",ofile);exit(1);} 108 | 109 | fprintf(out,"%s",file->name); 110 | for(inc=file->includes;inc;inc=inc->next) 111 | fprintf(out," %s%s",inc->scope==LOCAL?"%":"",inc->name); 112 | fprintf(out,"\n"); 113 | 114 | if(in) 115 | { 116 | char include[FILE_MAX_LEN+1],filename[FILE_MAX_LEN+1],ch; 117 | 118 | while(fscanf(in,"%s%c",filename,&ch)==2) 119 | { 120 | int diff_file=strcmp(filename,file->name); 121 | 122 | if(diff_file) 123 | fprintf(out,"%s",filename); 124 | 125 | while(ch==' ') 126 | { 127 | massert(fscanf(in,"%s%c",include,&ch)!=EOF); 128 | 129 | if(diff_file) 130 | fprintf(out," %s",include); 131 | 132 | if(outputs) 133 | if(include[0]=='%' && !strcmp(&include[1],file->name)) 134 | AddToStringList(file->inc_in,filename,1,1); 135 | } 136 | 137 | if(diff_file) 138 | fprintf(out,"\n"); 139 | } 140 | 141 | fclose(in); 142 | unlink(ifile); 143 | } 144 | 145 | fclose(out); 146 | rename(ofile,ifile); 147 | } 148 | 149 | /* Format: filename funcname scope [[%][&]funcname1] [[%][&]funcname2] ... : The function funcname in file filename 150 | calls or references functions funcname1, funcname2 ... ; those with a % are local, with a & are references. */ 151 | /* Format: filename $ 0 [[%]&funcname1] [[%]&funcname2] ... : The file references functions funcname1, funcname2 ... ; 152 | those with a % are local. */ 153 | 154 | if(option_xref&XREF_FUNC) /* Now do the functions */ 155 | { 156 | Function func; 157 | int i; 158 | 159 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE); 160 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_BACKUP); 161 | 162 | in =fopen(ifile,"r"); 163 | out=fopen(ofile,"w"); 164 | 165 | if(!out) 166 | {fprintf(stderr,"cxref: Failed to open the functional cross reference file '%s'\n",ofile);exit(1);} 167 | 168 | for(i=0;i<file->f_refs->n;i++) 169 | check_for_called(file,ConcatStrings(2,"&",file->f_refs->s1[i]),NULL,file->name); 170 | 171 | for(func=file->functions;func;func=func->next) 172 | { 173 | for(i=0;i<func->calls->n;i++) 174 | check_for_called(file,func->calls->s1[i],func->name,file->name); 175 | for(i=0;i<func->f_refs->n;i++) 176 | check_for_called(file,ConcatStrings(2,"&",func->f_refs->s1[i]),func->name,file->name); 177 | } 178 | 179 | for(func=file->functions;func;func=func->next) 180 | check_for_caller(file,func->name,file->name); 181 | 182 | if(file->f_refs->n) 183 | { 184 | fprintf(out,"%s $ 0",file->name); 185 | for(i=0;i<file->f_refs->n;i++) 186 | { 187 | if(file->f_refs->s2[i]) 188 | fprintf(out," %%&%s",file->f_refs->s1[i]); 189 | else 190 | fprintf(out," &%s",file->f_refs->s1[i]); 191 | } 192 | fprintf(out,"\n"); 193 | } 194 | 195 | for(func=file->functions;func;func=func->next) 196 | { 197 | fprintf(out,"%s %s %d",file->name,func->name,func->scope); 198 | for(i=0;i<func->calls->n;i++) 199 | { 200 | if(func->calls->s2[i]) 201 | fprintf(out," %%%s",func->calls->s1[i]); 202 | else 203 | fprintf(out," %s",func->calls->s1[i]); 204 | } 205 | for(i=0;i<func->f_refs->n;i++) 206 | { 207 | if(func->f_refs->s2[i]) 208 | fprintf(out," %%&%s",func->f_refs->s1[i]); 209 | else 210 | fprintf(out," &%s",func->f_refs->s1[i]); 211 | } 212 | fprintf(out,"\n"); 213 | } 214 | 215 | if(in) 216 | { 217 | char ch,funcname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],called[FUNC_MAX_LEN+1]; 218 | int scope; 219 | 220 | while(fscanf(in,"%s %s %d%c",filename,funcname,&scope,&ch)==4) 221 | { 222 | int diff_file=strcmp(filename,file->name); 223 | 224 | if(diff_file) 225 | { 226 | if(outputs) 227 | if(funcname[0]!='$' || funcname[1]!=0) 228 | check_for_caller(file,funcname,filename); 229 | fprintf(out,"%s %s %d",filename,funcname,scope); 230 | } 231 | 232 | while(ch==' ') 233 | { 234 | massert(fscanf(in,"%s%c",called,&ch)!=EOF); 235 | 236 | if(diff_file) 237 | { 238 | if(outputs) 239 | { 240 | if(called[0]!='%') 241 | { 242 | if(funcname[0]!='$' || funcname[1]!=0) 243 | check_for_called(file,called,funcname,filename); 244 | else 245 | check_for_called(file,called,NULL,filename); 246 | } 247 | } 248 | fprintf(out," %s",called); 249 | } 250 | } 251 | 252 | if(diff_file) 253 | fprintf(out,"\n"); 254 | } 255 | 256 | fclose(in); 257 | unlink(ifile); 258 | } 259 | 260 | fclose(out); 261 | rename(ofile,ifile); 262 | } 263 | 264 | /* Format: filename varname scope [$] [[%]funcname1] [[%]funcname2] ... : variable varname is used in 265 | the file filename if $, and functions funcname1, funcname2 ... Those with a % are local. */ 266 | 267 | if(option_xref&XREF_VAR) /* Now do the variables */ 268 | { 269 | Variable var; 270 | Function func; 271 | 272 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE); 273 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_BACKUP); 274 | 275 | in =fopen(ifile,"r"); 276 | out=fopen(ofile,"w"); 277 | 278 | if(!out) 279 | {fprintf(stderr,"cxref: Failed to open the variable cross reference file '%s'\n",ofile);exit(1);} 280 | 281 | for(var=file->variables;var;var=var->next) 282 | { 283 | check_for_var(file,var->name,file->name,var->scope,NULL); 284 | fprintf(out,"%s %s %d",file->name,var->name,var->scope); 285 | if(check_for_var_func(file,var,NULL)) 286 | fprintf(out," $"); 287 | for(func=file->functions;func;func=func->next) 288 | if(check_for_var_func(file,var,func)) 289 | fprintf(out," %s%s",func->scope==LOCAL?"%":"",func->name); 290 | fprintf(out,"\n"); 291 | } 292 | 293 | if(in) 294 | { 295 | char varname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],funcname[FUNC_MAX_LEN+1],ch; 296 | int scope; 297 | 298 | while(fscanf(in,"%s %s %d%c",filename,varname,&scope,&ch)==4) 299 | { 300 | int diff_file=strcmp(filename,file->name); 301 | 302 | if(diff_file) 303 | { 304 | if(outputs) 305 | if(!(scope&LOCAL)) 306 | check_for_var(file,varname,filename,scope,NULL); 307 | fprintf(out,"%s %s %d",filename,varname,scope); 308 | } 309 | 310 | while(ch==' ') 311 | { 312 | massert(fscanf(in,"%s%c",funcname,&ch)!=EOF); 313 | 314 | if(diff_file) 315 | { 316 | if(outputs) 317 | { 318 | if(!(scope&LOCAL)) 319 | { 320 | if(funcname[0]=='%') 321 | check_for_var(file,varname,filename,scope,&funcname[1]); 322 | else 323 | check_for_var(file,varname,filename,scope,funcname); 324 | } 325 | } 326 | fprintf(out," %s",funcname); 327 | } 328 | } 329 | 330 | if(diff_file) 331 | fprintf(out,"\n"); 332 | } 333 | 334 | fclose(in); 335 | unlink(ifile); 336 | } 337 | 338 | /* We must fix the location of the extern variables now since it was not known earlier. */ 339 | 340 | if(outputs) 341 | { 342 | fixup_extern_var(file->variables,file->v_refs); 343 | for(func=file->functions;func;func=func->next) 344 | fixup_extern_var(file->variables,func->v_refs); 345 | } 346 | 347 | fclose(out); 348 | rename(ofile,ifile); 349 | } 350 | 351 | /* Format: filename typename type... : For a typedef type. */ 352 | /* Format: filename # type... : For a non typedef type. */ 353 | 354 | if(option_xref&XREF_TYPE) /* Now do the types */ 355 | { 356 | Typedef type; 357 | 358 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE); 359 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_BACKUP); 360 | 361 | in =fopen(ifile,"r"); 362 | out=fopen(ofile,"w"); 363 | 364 | if(!out) 365 | {fprintf(stderr,"cxref: Failed to open the typedef reference file '%s'\n",ofile);exit(1);} 366 | 367 | for(type=file->typedefs;type;type=type->next) 368 | if(type->type) 369 | fprintf(out,"%s %s %s\n",file->name,type->name,type->type); 370 | else 371 | fprintf(out,"%s # %s\n",file->name,type->name); 372 | 373 | if(in) 374 | { 375 | char typename[TYPE_MAX_LEN+1],filename[FILE_MAX_LEN+1]; 376 | 377 | while(fscanf(in,"%s %s",filename,typename)==2) 378 | { 379 | int diff_file=strcmp(filename,file->name); 380 | 381 | if(diff_file) 382 | fprintf(out,"%s %s",filename,typename); 383 | 384 | massert(fgets(typename,TYPE_MAX_LEN,in)!=NULL); 385 | 386 | if(diff_file) 387 | fputs(typename,out); 388 | } 389 | 390 | fclose(in); 391 | unlink(ifile); 392 | } 393 | 394 | fclose(out); 395 | rename(ofile,ifile); 396 | } 397 | } 398 | 399 | 400 | /*++++++++++++++++++++++++++++++++++++++ 401 | Check through all of the functions in this file to see if any of them are called or referenced. 402 | 403 | File file The file structure. 404 | 405 | char* called The function that is called. 406 | 407 | char* caller The function that the called function is called from. 408 | 409 | char* filename The file that the function is called from. 410 | ++++++++++++++++++++++++++++++++++++++*/ 411 | 412 | static void check_for_called(File file,char* called,char* caller,char* filename) 413 | { 414 | Function func; 415 | 416 | /* Check for function calls */ 417 | 418 | if(called[0]!='&') 419 | for(func=file->functions;func;func=func->next) 420 | { 421 | if(!strcmp(called,func->name)) 422 | AddToStringList2(func->called,caller,filename,1,1); 423 | } 424 | 425 | /* Check for function references */ 426 | 427 | else 428 | for(func=file->functions;func;func=func->next) 429 | { 430 | if(!strcmp(&called[1],func->name)) 431 | { 432 | if(caller) 433 | AddToStringList2(func->used,caller,filename,1,1); 434 | else 435 | AddToStringList2(func->used,"$",filename,1,0); 436 | } 437 | } 438 | } 439 | 440 | 441 | /*++++++++++++++++++++++++++++++++++++++ 442 | Check through all of the functions in this file to see if any of them are callers or referencers. 443 | 444 | File file The file structure. 445 | 446 | char* called The function that is called. 447 | 448 | char* filename The file that the called function is in. 449 | ++++++++++++++++++++++++++++++++++++++*/ 450 | 451 | static void check_for_caller(File file,char* called,char* filename) 452 | { 453 | int i; 454 | Function func; 455 | 456 | /* Check the functions that are called. */ 457 | 458 | for(func=file->functions;func;func=func->next) 459 | for(i=0;i<func->calls->n;i++) 460 | if(!strcmp(called,func->calls->s1[i])) 461 | if(!func->calls->s2[i]) 462 | func->calls->s2[i]=MallocString(filename); 463 | 464 | /* Check the functions that are referenced. */ 465 | 466 | for(i=0;i<file->f_refs->n;i++) 467 | if(!strcmp(called,file->f_refs->s1[i])) 468 | if(!file->f_refs->s2[i]) 469 | file->f_refs->s2[i]=MallocString(filename); 470 | 471 | for(func=file->functions;func;func=func->next) 472 | for(i=0;i<func->f_refs->n;i++) 473 | if(!strcmp(called,func->f_refs->s1[i])) 474 | if(!func->f_refs->s2[i]) 475 | func->f_refs->s2[i]=MallocString(filename); 476 | } 477 | 478 | 479 | /*++++++++++++++++++++++++++++++++++++++ 480 | Check through all of the variables in this file to see if any of them are extern usage of others. 481 | 482 | File file The file structure. 483 | 484 | char* variable The global variable name. 485 | 486 | char* filename The file that the variable is used in. 487 | 488 | int scope The scope of the variable in the foreign file. 489 | 490 | char* funcname The name of a function that uses the variable. 491 | ++++++++++++++++++++++++++++++++++++++*/ 492 | 493 | static void check_for_var(File file,char* variable,char* filename,int scope,char* funcname) 494 | { 495 | Variable var; 496 | 497 | if(!funcname) 498 | { 499 | if(!(scope&(GLOBAL|EXTERNAL|EXTERN_H))) 500 | return; 501 | 502 | for(var=file->variables;var;var=var->next) 503 | if((scope&GLOBAL && var->scope&(EXTERNAL|EXTERN_H|EXTERN_F)) || 504 | (scope&(GLOBAL|EXTERNAL|EXTERN_H) && var->scope&GLOBAL)) 505 | if(!strcmp(variable,var->name)) 506 | { 507 | if(scope&GLOBAL && var->scope&(EXTERNAL|EXTERN_H|EXTERN_F)) 508 | var->defined=MallocString(filename); 509 | 510 | if(scope&(GLOBAL|EXTERNAL|EXTERN_H) && var->scope&GLOBAL) 511 | AddToStringList2(var->visible,"$",filename,1,0); 512 | } 513 | } 514 | else 515 | { 516 | for(var=file->variables;var;var=var->next) 517 | if(!strcmp(variable,var->name)) 518 | { 519 | if(funcname[0]=='$' && !funcname[1]) 520 | AddToStringList2(var->used,"$",filename,1,0); 521 | else 522 | { 523 | AddToStringList2(var->used,funcname,filename,1,1); 524 | 525 | if(scope&EXTERN_F && var->scope&GLOBAL) 526 | AddToStringList2(var->visible,funcname,filename,1,1); 527 | } 528 | } 529 | } 530 | } 531 | 532 | 533 | /*++++++++++++++++++++++++++++++++++++++ 534 | Check through the function to see if it uses the variable, if func is NULL then check the file. 535 | 536 | int check_for_var_func Returns 1 if the variable is referenced from the function or file. 537 | 538 | File file The file that the function belongs to. 539 | 540 | Variable var The variable that may be referenced. 541 | 542 | Function func The function that is to be checked. 543 | ++++++++++++++++++++++++++++++++++++++*/ 544 | 545 | static int check_for_var_func(File file,Variable var,Function func) 546 | { 547 | int i; 548 | 549 | if(func) 550 | { 551 | for(i=0;i<func->v_refs->n;i++) 552 | if(!strcmp(var->name,func->v_refs->s1[i])) 553 | { 554 | AddToStringList2(var->used,func->name,file->name,1,1); 555 | if(var->scope&(GLOBAL|LOCAL)) 556 | func->v_refs->s2[i]=MallocString(file->name); 557 | else 558 | { 559 | if(func->v_refs->s2[i]) Free(func->v_refs->s2[i]); 560 | func->v_refs->s2[i]=MallocString("$"); 561 | } 562 | return(1); 563 | } 564 | } 565 | else 566 | { 567 | for(i=0;i<file->v_refs->n;i++) 568 | if(!strcmp(var->name,file->v_refs->s1[i])) 569 | { 570 | AddToStringList2(var->used,"$",file->name,1,0); 571 | if(var->scope&(GLOBAL|LOCAL)) 572 | file->v_refs->s2[i]=MallocString(file->name); 573 | else 574 | { 575 | if(file->v_refs->s2[i]) Free(file->v_refs->s2[i]); 576 | file->v_refs->s2[i]=MallocString("$"); 577 | } 578 | return(1); 579 | } 580 | } 581 | 582 | return(0); 583 | } 584 | 585 | 586 | /*++++++++++++++++++++++++++++++++++++++ 587 | We can only now put in the location of the external variables that we found were used. 588 | Previously we did not know the location of their global definition. 589 | 590 | Variable var The list of variables for this file. 591 | 592 | StringList2 refs A list of variable references from a file or a function. 593 | ++++++++++++++++++++++++++++++++++++++*/ 594 | 595 | static void fixup_extern_var(Variable var,StringList2 refs) 596 | { 597 | int i; 598 | Variable v; 599 | 600 | for(i=0;i<refs->n;i++) 601 | { 602 | if(refs->s2[i][0]=='$' && !refs->s2[i][1]) 603 | for(v=var;v;v=v->next) 604 | if(v->scope&(EXTERNAL|EXTERN_H|EXTERN_F) && !strcmp(refs->s1[i],v->name)) 605 | { 606 | if(v->defined) 607 | { 608 | Free(refs->s2[i]); 609 | refs->s2[i]=MallocString(v->defined); 610 | } 611 | else 612 | { 613 | Free(refs->s1[i]); 614 | refs->s1[i]=MallocString(v->name); 615 | Free(refs->s2[i]); 616 | refs->s2[i]=NULL; 617 | } 618 | 619 | break; 620 | } 621 | } 622 | } 623 | 624 | 625 | /*++++++++++++++++++++++++++++++++++++++ 626 | Create the appendix of files, global functions, global variables and types. 627 | 628 | StringList files The list of files to create. 629 | 630 | StringList2 funcs The list of functions to create. 631 | 632 | StringList2 vars The list of variables to create. 633 | 634 | StringList2 types The list of types to create. 635 | ++++++++++++++++++++++++++++++++++++++*/ 636 | 637 | void CreateAppendix(StringList files,StringList2 funcs,StringList2 vars,StringList2 types) 638 | { 639 | FILE *in; 640 | char *ifile; 641 | 642 | if(option_index&INDEX_FILE) /* First do the files */ 643 | { 644 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE); 645 | 646 | in =fopen(ifile,"r"); 647 | 648 | if(in) 649 | { 650 | char include[FILE_MAX_LEN+1],filename[FILE_MAX_LEN+1],ch; 651 | 652 | while(fscanf(in,"%s%c",filename,&ch)==2) 653 | { 654 | AddToStringList(files,filename,1,1); 655 | while(ch==' ') 656 | massert(fscanf(in,"%s%c",include,&ch)!=EOF); 657 | } 658 | 659 | fclose(in); 660 | } 661 | } 662 | 663 | if(option_index&INDEX_FUNC) /* Now do the functions */ 664 | { 665 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE); 666 | 667 | in =fopen(ifile,"r"); 668 | 669 | if(in) 670 | { 671 | char ch,caller[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],called[FUNC_MAX_LEN+1]; 672 | int scope; 673 | 674 | while(fscanf(in,"%s %s %d%c",filename,caller,&scope,&ch)==4) 675 | { 676 | if(scope&GLOBAL) 677 | AddToStringList2(funcs,caller,filename,1,1); 678 | while(ch==' ') 679 | massert(fscanf(in,"%s%c",called,&ch)!=EOF); 680 | } 681 | 682 | fclose(in); 683 | } 684 | } 685 | 686 | if(option_index&INDEX_VAR) /* Now do the variables */ 687 | { 688 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE); 689 | 690 | in =fopen(ifile,"r"); 691 | 692 | if(in) 693 | { 694 | char variable[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],funcname[FUNC_MAX_LEN+1],ch; 695 | int scope; 696 | 697 | while(fscanf(in,"%s %s %d%c",filename,variable,&scope,&ch)==4) 698 | { 699 | if(scope&GLOBAL) 700 | AddToStringList2(vars,variable,filename,1,1); 701 | while(ch==' ') 702 | massert(fscanf(in,"%s%c",funcname,&ch)!=EOF); 703 | } 704 | 705 | fclose(in); 706 | } 707 | } 708 | 709 | if(option_index&INDEX_TYPE) /* Now do the types */ 710 | { 711 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE); 712 | 713 | in =fopen(ifile,"r"); 714 | 715 | if(in) 716 | { 717 | char typename[TYPE_MAX_LEN],filename[FILE_MAX_LEN+1]; 718 | 719 | while(fscanf(in,"%s %s",filename,typename)==2) 720 | { 721 | if(typename[0]=='#') 722 | { 723 | massert(fgets(typename,TYPE_MAX_LEN,in)!=NULL); 724 | typename[strlen(typename)-1]=0; 725 | AddToStringList2(types,&typename[1],filename,1,1); 726 | } 727 | else 728 | { 729 | AddToStringList2(types,typename,filename,1,1); 730 | massert(fgets(typename,TYPE_MAX_LEN,in)!=NULL); 731 | } 732 | } 733 | 734 | fclose(in); 735 | } 736 | } 737 | } 738 | 739 | 740 | /*++++++++++++++++++++++++++++++++++++++ 741 | Delete the named file from the cross reference database. 742 | 743 | char *name The name of the file that is to be deleted. 744 | ++++++++++++++++++++++++++++++++++++++*/ 745 | 746 | void CrossReferenceDelete(char *name) 747 | { 748 | FILE *in,*out; 749 | char *ifile,*ofile; 750 | 751 | /* First do the files */ 752 | 753 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE); 754 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_BACKUP); 755 | 756 | in =fopen(ifile,"r"); 757 | out=fopen(ofile,"w"); 758 | 759 | if(in && !out) 760 | {fprintf(stderr,"cxref: Failed to open the include cross reference file '%s'\n",ofile);fclose(in);} 761 | else if(in) 762 | { 763 | char include[FILE_MAX_LEN+1],filename[FILE_MAX_LEN+1],ch; 764 | 765 | while(fscanf(in,"%s%c",filename,&ch)==2) 766 | { 767 | int diff_file=strcmp(filename,name); 768 | 769 | if(diff_file) 770 | fprintf(out,"%s",filename); 771 | 772 | while(ch==' ') 773 | { 774 | massert(fscanf(in,"%s%c",include,&ch)!=EOF); 775 | 776 | if(diff_file) 777 | fprintf(out," %s",include); 778 | } 779 | 780 | if(diff_file) 781 | fprintf(out,"\n"); 782 | } 783 | 784 | fclose(in); 785 | unlink(ifile); 786 | 787 | fclose(out); 788 | rename(ofile,ifile); 789 | } 790 | else if(out) 791 | { 792 | fclose(out); 793 | unlink(ofile); 794 | } 795 | 796 | /* Now do the functions */ 797 | 798 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE); 799 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_BACKUP); 800 | 801 | in =fopen(ifile,"r"); 802 | out=fopen(ofile,"w"); 803 | 804 | if(in && !out) 805 | {fprintf(stderr,"cxref: Failed to open the functional cross reference file '%s'\n",ofile);fclose(in);} 806 | else if(in) 807 | { 808 | char ch,funcname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],called[FUNC_MAX_LEN+1]; 809 | int scope; 810 | 811 | while(fscanf(in,"%s %s %d%c",filename,funcname,&scope,&ch)==4) 812 | { 813 | int diff_file=strcmp(filename,name); 814 | 815 | if(diff_file) 816 | fprintf(out,"%s %s %d",filename,funcname,scope); 817 | 818 | while(ch==' ') 819 | { 820 | massert(fscanf(in,"%s%c",called,&ch)!=EOF); 821 | if(diff_file) 822 | fprintf(out," %s",called); 823 | } 824 | 825 | if(diff_file) 826 | fprintf(out,"\n"); 827 | } 828 | 829 | fclose(in); 830 | unlink(ifile); 831 | 832 | fclose(out); 833 | rename(ofile,ifile); 834 | } 835 | else if(out) 836 | { 837 | fclose(out); 838 | unlink(ofile); 839 | } 840 | 841 | /* Now do the variables */ 842 | 843 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE); 844 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_BACKUP); 845 | 846 | in =fopen(ifile,"r"); 847 | out=fopen(ofile,"w"); 848 | 849 | if(in && !out) 850 | {fprintf(stderr,"cxref: Failed to open the variable cross reference file '%s'\n",ofile);fclose(in);} 851 | else if(in) 852 | { 853 | char varname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],funcname[FUNC_MAX_LEN+1],ch; 854 | int scope; 855 | 856 | while(fscanf(in,"%s %s %d%c",filename,varname,&scope,&ch)==4) 857 | { 858 | int diff_file=strcmp(filename,name); 859 | 860 | if(diff_file) 861 | fprintf(out,"%s %s %d",filename,varname,scope); 862 | 863 | while(ch==' ') 864 | { 865 | massert(fscanf(in,"%s%c",funcname,&ch)!=EOF); 866 | 867 | if(diff_file) 868 | fprintf(out," %s",funcname); 869 | } 870 | 871 | if(diff_file) 872 | fprintf(out,"\n"); 873 | } 874 | 875 | fclose(in); 876 | unlink(ifile); 877 | 878 | fclose(out); 879 | rename(ofile,ifile); 880 | } 881 | else if(out) 882 | { 883 | fclose(out); 884 | unlink(ofile); 885 | } 886 | 887 | /* Now do the types */ 888 | 889 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE); 890 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_BACKUP); 891 | 892 | in =fopen(ifile,"r"); 893 | out=fopen(ofile,"w"); 894 | 895 | if(in && !out) 896 | {fprintf(stderr,"cxref: Failed to open the typedef reference file '%s'\n",ofile);fclose(in);} 897 | else if(in) 898 | { 899 | char typename[TYPE_MAX_LEN+1],filename[FILE_MAX_LEN+1]; 900 | 901 | while(fscanf(in,"%s %s",filename,typename)==2) 902 | { 903 | int diff_file=strcmp(filename,name); 904 | 905 | if(diff_file) 906 | fprintf(out,"%s %s",filename,typename); 907 | 908 | massert(fgets(typename,TYPE_MAX_LEN,in)!=NULL); 909 | 910 | if(diff_file) 911 | fputs(typename,out); 912 | } 913 | 914 | fclose(in); 915 | unlink(ifile); 916 | 917 | fclose(out); 918 | rename(ofile,ifile); 919 | } 920 | else if(out) 921 | { 922 | fclose(out); 923 | unlink(ofile); 924 | } 925 | }