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