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