1 | /*************************************** 2 | $Header: /home/amb/cxref/RCS/xref.c 1.20 2001/01/06 13:05:13 amb Exp $ 3 | 4 | C Cross Referencing & Documentation tool. Version 1.5c. 5 | 6 | Cross referencing of functions. 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 | /*+ 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 | func->calls->s2[i]=MallocString(filename); 453 | 454 | /* Check the functions that are referenced. */ 455 | 456 | for(i=0;i<file->f_refs->n;i++) 457 | if(!strcmp(called,file->f_refs->s1[i])) 458 | file->f_refs->s2[i]=MallocString(filename); 459 | 460 | for(func=file->functions;func;func=func->next) 461 | for(i=0;i<func->f_refs->n;i++) 462 | if(!strcmp(called,func->f_refs->s1[i])) 463 | func->f_refs->s2[i]=MallocString(filename); 464 | } 465 | 466 | 467 | /*++++++++++++++++++++++++++++++++++++++ 468 | Check through all of the variables in this file to see if any of them are extern usage of others. 469 | 470 | File file The file structure. 471 | 472 | char* variable The global variable name. 473 | 474 | char* filename The file that the variable is used in. 475 | 476 | int scope The scope of the variable in the foreign file. 477 | 478 | char* funcname The name of a function that uses the variable. 479 | ++++++++++++++++++++++++++++++++++++++*/ 480 | 481 | static void check_for_var(File file,char* variable,char* filename,int scope,char* funcname) 482 | { 483 | Variable var; 484 | 485 | if(!funcname) 486 | { 487 | if(!(scope&(GLOBAL|EXTERNAL|EXTERN_H))) 488 | return; 489 | 490 | for(var=file->variables;var;var=var->next) 491 | if((scope&GLOBAL && var->scope&(EXTERNAL|EXTERN_H|EXTERN_F)) || 492 | (scope&(GLOBAL|EXTERNAL|EXTERN_H) && var->scope&GLOBAL)) 493 | if(!strcmp(variable,var->name)) 494 | { 495 | if(scope&GLOBAL && var->scope&(EXTERNAL|EXTERN_H|EXTERN_F)) 496 | var->defined=MallocString(filename); 497 | 498 | if(scope&(GLOBAL|EXTERNAL|EXTERN_H) && var->scope&GLOBAL) 499 | AddToStringList2(var->visible,"$",filename,1,0); 500 | } 501 | } 502 | else 503 | { 504 | for(var=file->variables;var;var=var->next) 505 | if(!strcmp(variable,var->name)) 506 | { 507 | if(funcname[0]=='$' && !funcname[1]) 508 | AddToStringList2(var->used,"$",filename,1,0); 509 | else 510 | { 511 | AddToStringList2(var->used,funcname,filename,1,1); 512 | 513 | if(scope&EXTERN_F && var->scope&GLOBAL) 514 | AddToStringList2(var->visible,funcname,filename,1,1); 515 | } 516 | } 517 | } 518 | } 519 | 520 | 521 | /*++++++++++++++++++++++++++++++++++++++ 522 | Check through the function to see if it uses the variable, if func is NULL then check the file. 523 | 524 | int check_for_var_func Returns 1 if the variable is referenced from the function or file. 525 | 526 | File file The file that the function belongs to. 527 | 528 | Variable var The variable that may be referenced. 529 | 530 | Function func The function that is to be checked. 531 | ++++++++++++++++++++++++++++++++++++++*/ 532 | 533 | static int check_for_var_func(File file,Variable var,Function func) 534 | { 535 | int i; 536 | 537 | if(func) 538 | { 539 | for(i=0;i<func->v_refs->n;i++) 540 | if(!strcmp(var->name,func->v_refs->s1[i])) 541 | { 542 | AddToStringList2(var->used,func->name,file->name,1,1); 543 | if(var->scope&(GLOBAL|LOCAL)) 544 | func->v_refs->s2[i]=MallocString(file->name); 545 | else 546 | { 547 | if(func->v_refs->s2[i]) Free(func->v_refs->s2[i]); 548 | func->v_refs->s2[i]=MallocString("$"); 549 | } 550 | return(1); 551 | } 552 | } 553 | else 554 | { 555 | for(i=0;i<file->v_refs->n;i++) 556 | if(!strcmp(var->name,file->v_refs->s1[i])) 557 | { 558 | AddToStringList2(var->used,"$",file->name,1,0); 559 | if(var->scope&(GLOBAL|LOCAL)) 560 | file->v_refs->s2[i]=MallocString(file->name); 561 | else 562 | { 563 | if(file->v_refs->s2[i]) Free(file->v_refs->s2[i]); 564 | file->v_refs->s2[i]=MallocString("$"); 565 | } 566 | return(1); 567 | } 568 | } 569 | 570 | return(0); 571 | } 572 | 573 | 574 | /*++++++++++++++++++++++++++++++++++++++ 575 | We can only now put in the location of the external variables that we found were used. 576 | Previously we did not know the location of their global definition. 577 | 578 | Variable var The list of variables for this file. 579 | 580 | StringList2 refs A list of variable references from a file or a function. 581 | ++++++++++++++++++++++++++++++++++++++*/ 582 | 583 | static void fixup_extern_var(Variable var,StringList2 refs) 584 | { 585 | int i; 586 | Variable v; 587 | 588 | for(i=0;i<refs->n;i++) 589 | { 590 | if(refs->s2[i][0]=='$' && !refs->s2[i][1]) 591 | for(v=var;v;v=v->next) 592 | if(v->scope&(EXTERNAL|EXTERN_H|EXTERN_F) && !strcmp(refs->s1[i],v->name)) 593 | { 594 | if(v->defined) 595 | { 596 | Free(refs->s2[i]); 597 | refs->s2[i]=MallocString(v->defined); 598 | } 599 | else 600 | { 601 | Free(refs->s1[i]); 602 | refs->s1[i]=MallocString(v->name); 603 | Free(refs->s2[i]); 604 | refs->s2[i]=NULL; 605 | } 606 | 607 | break; 608 | } 609 | } 610 | } 611 | 612 | 613 | /*++++++++++++++++++++++++++++++++++++++ 614 | Create the appendix of files, global functions, global variables and types. 615 | 616 | StringList files The list of files to create. 617 | 618 | StringList2 funcs The list of functions to create. 619 | 620 | StringList2 vars The list of variables to create. 621 | 622 | StringList2 types The list of types to create. 623 | ++++++++++++++++++++++++++++++++++++++*/ 624 | 625 | void CreateAppendix(StringList files,StringList2 funcs,StringList2 vars,StringList2 types) 626 | { 627 | FILE *in; 628 | char *ifile; 629 | 630 | if(option_index&INDEX_FILE) /* First do the files */ 631 | { 632 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE); 633 | 634 | in =fopen(ifile,"r"); 635 | 636 | if(in) 637 | { 638 | char include[FILE_MAX_LEN+1],filename[FILE_MAX_LEN+1],ch; 639 | 640 | while(fscanf(in,"%s%c",filename,&ch)==2) 641 | { 642 | AddToStringList(files,filename,1,1); 643 | while(ch==' ') 644 | fscanf(in,"%s%c",include,&ch); 645 | } 646 | 647 | fclose(in); 648 | } 649 | } 650 | 651 | if(option_index&INDEX_FUNC) /* Now do the functions */ 652 | { 653 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE); 654 | 655 | in =fopen(ifile,"r"); 656 | 657 | if(in) 658 | { 659 | char ch,caller[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],called[FUNC_MAX_LEN+1]; 660 | int scope; 661 | 662 | while(fscanf(in,"%s %s %d%c",filename,caller,&scope,&ch)==4) 663 | { 664 | if(scope&GLOBAL) 665 | AddToStringList2(funcs,caller,filename,1,1); 666 | while(ch==' ') 667 | fscanf(in,"%s%c",called,&ch); 668 | } 669 | 670 | fclose(in); 671 | } 672 | } 673 | 674 | if(option_index&INDEX_VAR) /* Now do the variables */ 675 | { 676 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE); 677 | 678 | in =fopen(ifile,"r"); 679 | 680 | if(in) 681 | { 682 | char variable[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],funcname[FUNC_MAX_LEN+1],ch; 683 | int scope; 684 | 685 | while(fscanf(in,"%s %s %d%c",filename,variable,&scope,&ch)==4) 686 | { 687 | if(scope&GLOBAL) 688 | AddToStringList2(vars,variable,filename,1,1); 689 | while(ch==' ') 690 | fscanf(in,"%s%c",funcname,&ch); 691 | } 692 | 693 | fclose(in); 694 | } 695 | } 696 | 697 | if(option_index&INDEX_TYPE) /* Now do the types */ 698 | { 699 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE); 700 | 701 | in =fopen(ifile,"r"); 702 | 703 | if(in) 704 | { 705 | char typename[TYPE_MAX_LEN],filename[FILE_MAX_LEN+1]; 706 | 707 | while(fscanf(in,"%s %s",filename,typename)==2) 708 | { 709 | if(typename[0]=='#') 710 | { 711 | fgets(typename,TYPE_MAX_LEN,in); 712 | typename[strlen(typename)-1]=0; 713 | AddToStringList2(types,&typename[1],filename,1,1); 714 | } 715 | else 716 | { 717 | AddToStringList2(types,typename,filename,1,1); 718 | fgets(typename,TYPE_MAX_LEN,in); 719 | } 720 | } 721 | 722 | fclose(in); 723 | } 724 | } 725 | } 726 | 727 | 728 | /*++++++++++++++++++++++++++++++++++++++ 729 | Delete the named file from the cross reference database. 730 | 731 | char *name The name of the file that is to be deleted. 732 | ++++++++++++++++++++++++++++++++++++++*/ 733 | 734 | void CrossReferenceDelete(char *name) 735 | { 736 | FILE *in,*out; 737 | char *ifile,*ofile; 738 | 739 | /* First do the files */ 740 | 741 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE); 742 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_BACKUP); 743 | 744 | in =fopen(ifile,"r"); 745 | out=fopen(ofile,"w"); 746 | 747 | if(in && !out) 748 | {fprintf(stderr,"cxref: Failed to open the include cross reference file '%s'\n",ofile);fclose(in);} 749 | else if(in) 750 | { 751 | char include[FILE_MAX_LEN+1],filename[FILE_MAX_LEN+1],ch; 752 | 753 | while(fscanf(in,"%s%c",filename,&ch)==2) 754 | { 755 | int diff_file=strcmp(filename,name); 756 | 757 | if(diff_file) 758 | fprintf(out,"%s",filename); 759 | 760 | while(ch==' ') 761 | { 762 | fscanf(in,"%s%c",include,&ch); 763 | 764 | if(diff_file) 765 | fprintf(out," %s",include); 766 | } 767 | 768 | if(diff_file) 769 | fprintf(out,"\n"); 770 | } 771 | 772 | fclose(in); 773 | unlink(ifile); 774 | 775 | fclose(out); 776 | rename(ofile,ifile); 777 | } 778 | else if(out) 779 | { 780 | fclose(out); 781 | unlink(ofile); 782 | } 783 | 784 | /* Now do the functions */ 785 | 786 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE); 787 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_BACKUP); 788 | 789 | in =fopen(ifile,"r"); 790 | out=fopen(ofile,"w"); 791 | 792 | if(in && !out) 793 | {fprintf(stderr,"cxref: Failed to open the functional cross reference file '%s'\n",ofile);fclose(in);} 794 | else if(in) 795 | { 796 | char ch,funcname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],called[FUNC_MAX_LEN+1]; 797 | int scope; 798 | 799 | while(fscanf(in,"%s %s %d%c",filename,funcname,&scope,&ch)==4) 800 | { 801 | int diff_file=strcmp(filename,name); 802 | 803 | if(diff_file) 804 | fprintf(out,"%s %s %d",filename,funcname,scope); 805 | 806 | while(ch==' ') 807 | { 808 | fscanf(in,"%s%c",called,&ch); 809 | if(diff_file) 810 | fprintf(out," %s",called); 811 | } 812 | 813 | if(diff_file) 814 | fprintf(out,"\n"); 815 | } 816 | 817 | fclose(in); 818 | unlink(ifile); 819 | 820 | fclose(out); 821 | rename(ofile,ifile); 822 | } 823 | else if(out) 824 | { 825 | fclose(out); 826 | unlink(ofile); 827 | } 828 | 829 | /* Now do the variables */ 830 | 831 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE); 832 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_BACKUP); 833 | 834 | in =fopen(ifile,"r"); 835 | out=fopen(ofile,"w"); 836 | 837 | if(in && !out) 838 | {fprintf(stderr,"cxref: Failed to open the variable cross reference file '%s'\n",ofile);fclose(in);} 839 | else if(in) 840 | { 841 | char varname[FUNC_MAX_LEN+1],filename[FILE_MAX_LEN+1],funcname[FUNC_MAX_LEN+1],ch; 842 | int scope; 843 | 844 | while(fscanf(in,"%s %s %d%c",filename,varname,&scope,&ch)==4) 845 | { 846 | int diff_file=strcmp(filename,name); 847 | 848 | if(diff_file) 849 | fprintf(out,"%s %s %d",filename,varname,scope); 850 | 851 | while(ch==' ') 852 | { 853 | fscanf(in,"%s%c",funcname,&ch); 854 | 855 | if(diff_file) 856 | fprintf(out," %s",funcname); 857 | } 858 | 859 | if(diff_file) 860 | fprintf(out,"\n"); 861 | } 862 | 863 | fclose(in); 864 | unlink(ifile); 865 | 866 | fclose(out); 867 | rename(ofile,ifile); 868 | } 869 | else if(out) 870 | { 871 | fclose(out); 872 | unlink(ofile); 873 | } 874 | 875 | /* Now do the types */ 876 | 877 | ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE); 878 | ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_BACKUP); 879 | 880 | in =fopen(ifile,"r"); 881 | out=fopen(ofile,"w"); 882 | 883 | if(in && !out) 884 | {fprintf(stderr,"cxref: Failed to open the typedef reference file '%s'\n",ofile);fclose(in);} 885 | else if(in) 886 | { 887 | char typename[TYPE_MAX_LEN+1],filename[FILE_MAX_LEN+1]; 888 | 889 | while(fscanf(in,"%s %s",filename,typename)==2) 890 | { 891 | int diff_file=strcmp(filename,name); 892 | 893 | if(diff_file) 894 | fprintf(out,"%s %s",filename,typename); 895 | 896 | fgets(typename,TYPE_MAX_LEN,in); 897 | 898 | if(diff_file) 899 | fputs(typename,out); 900 | } 901 | 902 | fclose(in); 903 | unlink(ifile); 904 | 905 | fclose(out); 906 | rename(ofile,ifile); 907 | } 908 | else if(out) 909 | { 910 | fclose(out); 911 | unlink(ofile); 912 | } 913 | }