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