1 | /*************************************** 2 | $Header: /home/amb/cxref/RCS/rtf.c 1.6 1999/05/15 16:58:57 amb Exp $ 3 | 4 | C Cross Referencing & Documentation tool. Version 1.5a. 5 | 6 | Writes the RTF output. 7 | ******************/ /****************** 8 | Written by Andrew M. Bishop 9 | 10 | This file Copyright 1995,96,97,98 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 | #include <stdlib.h> 17 | #include <stdio.h> 18 | #include <string.h> 19 | #include <sys/types.h> 20 | #include <sys/stat.h> 21 | #include <unistd.h> 22 | 23 | #include "memory.h" 24 | #include "datatype.h" 25 | #include "cxref.h" 26 | 27 | /*+ The name of the output rtf file. +*/ 28 | #define RTF_FILE ".rtf" 29 | #define RTF_FILE_BACKUP ".rtf~" 30 | 31 | /*+ The name of the output rtf file that contains the appendix. +*/ 32 | #define RTF_APDX ".apdx" 33 | 34 | #define STYLE_NORM "\\s0\\f0\\fs24" 35 | #define STYLE_H1 "\\s1\\f0\\fs40\\b\\sb400\\sa200\\keepn\\keep" 36 | #define STYLE_H2 "\\s2\\f0\\fs32\\b\\sb200\\sa100\\keepn\\keep" 37 | #define STYLE_H3 "\\s3\\f0\\fs28\\b\\sb100\\sa100\\keepn\\keep" 38 | #define STYLE_H4 "\\s4\\f0\\fs24\\b\\sb100\\sa50\\keepn\\keep" 39 | #define STYLE_TT "\\s5\\f1\\fs20\\ql\\sb50\\sa50" 40 | #define STYLE_IND "\\s6\\f0\\fs24\\ql\\li720" 41 | 42 | /*+ The comments are to be inserted verbatim. +*/ 43 | extern int option_verbatim_comments; 44 | 45 | /*+ The name of the directory for the output. +*/ 46 | extern char* option_odir; 47 | 48 | /*+ The base name of the file for the output. +*/ 49 | extern char* option_name; 50 | 51 | /*+ The information about the cxref run, +*/ 52 | extern char *run_command, /*+ the command line options. +*/ 53 | *run_cpp_command; /*+ the cpp command and options. +*/ 54 | 55 | static void WriteRTFFilePart(File file); 56 | static void WriteRTFInclude(Include inc); 57 | static void WriteRTFSubInclude(Include inc,int depth); 58 | static void WriteRTFDefine(Define def); 59 | static void WriteRTFTypedef(Typedef type,char* filename); 60 | static void WriteRTFStructUnion(StructUnion su,int depth); 61 | static void WriteRTFVariable(Variable var,char* filename); 62 | static void WriteRTFFunction(Function func,char* filename); 63 | static void WriteRTFPreamble(FILE *f); 64 | static void WriteRTFPostamble(FILE *f); 65 | 66 | static char* rtf(char* c,int verbatim); 67 | 68 | /*+ The output file for the RTF. +*/ 69 | static FILE* of; 70 | 71 | 72 | /*++++++++++++++++++++++++++++++++++++++ 73 | Write an RTF file for a complete File structure and all components. 74 | 75 | File file The File structure to output. 76 | ++++++++++++++++++++++++++++++++++++++*/ 77 | 78 | void WriteRTFFile(File file) 79 | { 80 | char* ofile; 81 | 82 | /* Open the file */ 83 | 84 | ofile=ConcatStrings(4,option_odir,"/",file->name,RTF_FILE); 85 | 86 | of=fopen(ofile,"w"); 87 | if(!of) 88 | { 89 | struct stat stat_buf; 90 | int i,ofl=strlen(ofile); 91 | 92 | for(i=strlen(option_odir)+1;i<ofl;i++) 93 | if(ofile[i]=='/') 94 | { 95 | ofile[i]=0; 96 | if(stat(ofile,&stat_buf)) 97 | mkdir(ofile,S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); 98 | ofile[i]='/'; 99 | } 100 | 101 | of=fopen(ofile,"w"); 102 | } 103 | 104 | if(!of) 105 | {fprintf(stderr,"cxref: Failed to open the RTF output file '%s'\r\n",ofile);exit(1);} 106 | 107 | /* Write out a header. */ 108 | 109 | WriteRTFPreamble(of); 110 | 111 | /*+ The file structure is broken into its components and they are each written out. +*/ 112 | 113 | WriteRTFFilePart(file); 114 | 115 | if(file->includes) 116 | { 117 | Include inc =file->includes; 118 | fprintf(of,"{" STYLE_H2 " Included Files\\par}\r\n"); 119 | do{ 120 | WriteRTFInclude(inc); 121 | } 122 | while((inc=inc->next)); 123 | } 124 | 125 | if(file->defines) 126 | { 127 | Define def =file->defines; 128 | fprintf(of,"{" STYLE_H2 " Preprocessor definitions\\par}\r\n"); 129 | do{ 130 | WriteRTFDefine(def); 131 | } 132 | while((def=def->next)); 133 | } 134 | 135 | if(file->typedefs) 136 | { 137 | Typedef type=file->typedefs; 138 | fprintf(of,"{" STYLE_H2 " Type definitions\\par}\r\n"); 139 | do{ 140 | WriteRTFTypedef(type,file->name); 141 | } 142 | while((type=type->next)); 143 | } 144 | 145 | if(file->variables) 146 | { 147 | int any_to_mention=0; 148 | Variable var=file->variables; 149 | 150 | do{ 151 | if(var->scope&(GLOBAL|LOCAL|EXTERNAL|EXTERN_F)) 152 | any_to_mention=1; 153 | } 154 | while((var=var->next)); 155 | 156 | if(any_to_mention) 157 | { 158 | Variable var=file->variables; 159 | fprintf(of,"{" STYLE_H2 " Variables\\par}\r\n"); 160 | do{ 161 | if(var->scope&GLOBAL) 162 | WriteRTFVariable(var,file->name); 163 | } 164 | while((var=var->next)); 165 | var=file->variables; 166 | do{ 167 | if(var->scope&(EXTERNAL|EXTERN_F) && !(var->scope&GLOBAL)) 168 | { 169 | fprintf(of,"{" STYLE_H3 " External Variables\\par}\r\n"); 170 | WriteRTFVariable(var,file->name); 171 | } 172 | } 173 | while((var=var->next)); 174 | var=file->variables; 175 | do{ 176 | if(var->scope&LOCAL) 177 | { 178 | fprintf(of,"{" STYLE_H3 " Local Variables\\par}\r\n"); 179 | WriteRTFVariable(var,file->name); 180 | } 181 | } 182 | while((var=var->next)); 183 | } 184 | } 185 | 186 | if(file->functions) 187 | { 188 | Function func=file->functions; 189 | fprintf(of,"{" STYLE_H2 " Functions\\par}\r\n"); 190 | do{ 191 | if(func->scope&(GLOBAL|EXTERNAL)) 192 | WriteRTFFunction(func,file->name); 193 | } 194 | while((func=func->next)); 195 | func=file->functions; 196 | do{ 197 | if(func->scope&LOCAL) 198 | WriteRTFFunction(func,file->name); 199 | } 200 | while((func=func->next)); 201 | } 202 | 203 | /* Write out a trailer. */ 204 | 205 | WriteRTFPostamble(of); 206 | 207 | fclose(of); 208 | 209 | /* Clear the memory in rtf() */ 210 | 211 | rtf(NULL,0); rtf(NULL,0); rtf(NULL,0); rtf(NULL,0); 212 | } 213 | 214 | 215 | /*++++++++++++++++++++++++++++++++++++++ 216 | Write a File structure out. 217 | 218 | File file The File to output. 219 | ++++++++++++++++++++++++++++++++++++++*/ 220 | 221 | static void WriteRTFFilePart(File file) 222 | { 223 | int i; 224 | 225 | fprintf(of,"{" STYLE_H1 " File %s\\par}\r\n",rtf(file->name,0)); 226 | 227 | if(file->comment) 228 | if(option_verbatim_comments) 229 | fprintf(of,"{" STYLE_TT "%s\\par}\r\n",rtf(file->comment,1)); 230 | else 231 | { 232 | char *rcs1=strstr(file->comment,"$Header"),*rcs2=NULL; 233 | if(rcs1) 234 | { 235 | rcs2=strstr(&rcs1[1],"$"); 236 | if(rcs2) 237 | { 238 | rcs2[0]=0; 239 | fprintf(of,"{\\b RCS %s}\\par\r\n",rtf(&rcs1[1],0)); 240 | rcs2[0]='$'; 241 | } 242 | } 243 | if(rcs2) 244 | fprintf(of,"%s\\par\r\n",rtf(&rcs2[2],0)); 245 | else 246 | fprintf(of,"%s\\par\r\n",rtf(file->comment,0)); 247 | } 248 | 249 | if(file->inc_in->n) 250 | { 251 | int i; 252 | 253 | fprintf(of,"\\trowd\\trgaph120\\cellx1440\\cellx9000\r\n\\intbl\\plain\r\n"); 254 | for(i=0;i<file->inc_in->n;i++) 255 | { 256 | if(i==0) fprintf(of,"Included in:"); 257 | fprintf(of,"\\cell %s\\cell\\row\r\n",rtf(file->inc_in->s[i],0)); 258 | } 259 | fprintf(of,"\\intbl0\r\n"); 260 | } 261 | 262 | if(file->f_refs->n || file->v_refs->n) 263 | { 264 | fprintf(of,"\\trowd\\trgaph120\\cellx1440\\cellx5220\\cellx9000\r\n\\intbl\\plain\r\n"); 265 | 266 | if(file->f_refs->n) 267 | { 268 | int others=0; 269 | 270 | fprintf(of,"Refs Func:"); 271 | 272 | for(i=0;i<file->f_refs->n;i++) 273 | if(file->f_refs->s2[i]) 274 | fprintf(of,"\\cell %s()\\cell %s\\cell\\row\r\n",rtf(file->f_refs->s1[i],0),rtf(file->f_refs->s2[i],0)); 275 | else 276 | others++; 277 | 278 | if(others) 279 | { 280 | fprintf(of,"\\cell "); 281 | for(i=0;i<file->f_refs->n;i++) 282 | if(!file->f_refs->s2[i]) 283 | fprintf(of,--others?"%s(), ":"%s()",rtf(file->f_refs->s1[i],0)); 284 | fprintf(of,"\\cell\\cell\\row\r\n"); 285 | } 286 | } 287 | 288 | if(file->v_refs->n) 289 | { 290 | int others=0; 291 | 292 | fprintf(of,"Refs Var:"); 293 | 294 | for(i=0;i<file->v_refs->n;i++) 295 | if(file->v_refs->s2[i]) 296 | fprintf(of,"\\cell %s\\cell %s\\cell\\row\r\n",rtf(file->v_refs->s1[i],0),rtf(file->v_refs->s2[i],0)); 297 | else 298 | others++; 299 | 300 | if(others) 301 | { 302 | fprintf(of,"\\cell "); 303 | for(i=0;i<file->v_refs->n;i++) 304 | if(!file->v_refs->s2[i]) 305 | fprintf(of,--others?" %s,":" %s",rtf(file->v_refs->s1[i],0)); 306 | fprintf(of,"\\cell\\cell\\row\r\n"); 307 | } 308 | } 309 | fprintf(of,"\\intbl0\r\n"); 310 | } 311 | } 312 | 313 | 314 | /*++++++++++++++++++++++++++++++++++++++ 315 | Write an Include structure out. 316 | 317 | Include inc The Include structure to output. 318 | ++++++++++++++++++++++++++++++++++++++*/ 319 | 320 | static void WriteRTFInclude(Include inc) 321 | { 322 | if(inc->comment) 323 | fprintf(of,"%s\\par\r\n",rtf(inc->comment,0)); 324 | 325 | if(inc->scope==LOCAL) 326 | fprintf(of,"{" STYLE_TT " #include \"%s\"\\par}\r\n",rtf(inc->name,0)); 327 | else 328 | fprintf(of,"{" STYLE_TT " #include <%s>\\par}\r\n",rtf(inc->name,0)); 329 | 330 | if(inc->includes) 331 | WriteRTFSubInclude(inc->includes,1); 332 | } 333 | 334 | 335 | /*++++++++++++++++++++++++++++++++++++++ 336 | Write an Sub Include structure out. (An include structure that is included from another file.) 337 | 338 | Include inc The Include structure to output. 339 | 340 | int depth The depth of the include hierarchy. 341 | ++++++++++++++++++++++++++++++++++++++*/ 342 | 343 | static void WriteRTFSubInclude(Include inc,int depth) 344 | { 345 | int i; 346 | 347 | while(inc) 348 | { 349 | for(i=0;i<depth;i++) 350 | fprintf(of,"\t"); 351 | 352 | if(inc->scope==LOCAL) 353 | fprintf(of,"{" STYLE_TT " #include \"%s\"\\par}\r\n",rtf(inc->name,0)); 354 | else 355 | fprintf(of,"{" STYLE_TT " #include <%s>\\par}\r\n",rtf(inc->name,0)); 356 | 357 | if(inc->includes) 358 | WriteRTFSubInclude(inc->includes,depth+1); 359 | 360 | inc=inc->next; 361 | } 362 | } 363 | 364 | 365 | /*++++++++++++++++++++++++++++++++++++++ 366 | Write a Define structure out. 367 | 368 | Define def The Define structure to output. 369 | ++++++++++++++++++++++++++++++++++++++*/ 370 | 371 | static void WriteRTFDefine(Define def) 372 | { 373 | int i; 374 | int pargs=0; 375 | 376 | if(def->comment) 377 | fprintf(of,"%s\\par\r\n",rtf(def->comment,0)); 378 | 379 | fprintf(of,"{" STYLE_TT " #define %s",rtf(def->name,0)); 380 | 381 | if(def->value) 382 | fprintf(of," %s",rtf(def->value,0)); 383 | 384 | if(def->args->n) 385 | { 386 | fprintf(of,"( "); 387 | for(i=0;i<def->args->n;i++) 388 | fprintf(of,i?", %s":"%s",rtf(def->args->s1[i],0)); 389 | fprintf(of," )"); 390 | } 391 | fprintf(of,"\\par}\r\n"); 392 | 393 | for(i=0;i<def->args->n;i++) 394 | if(def->args->s2[i]) 395 | pargs=1; 396 | 397 | if(pargs) 398 | { 399 | for(i=0;i<def->args->n;i++) 400 | fprintf(of,"{" STYLE_TT "%s\\par}\r\n{" STYLE_IND " %s\\par}\r\n",rtf(def->args->s1[i],0),def->args->s2[i]?rtf(def->args->s2[i],0):""); 401 | } 402 | } 403 | 404 | 405 | /*++++++++++++++++++++++++++++++++++++++ 406 | Write a Typedef structure out. 407 | 408 | Typedef type The Typedef structure to output. 409 | 410 | char* filename The name of the file that is being processed (required for the cross reference label). 411 | ++++++++++++++++++++++++++++++++++++++*/ 412 | 413 | static void WriteRTFTypedef(Typedef type,char* filename) 414 | { 415 | if(type->type) 416 | fprintf(of,"{" STYLE_H3 " Typedef %s\\par}\r\n",rtf(type->name,0)); 417 | else 418 | fprintf(of,"{" STYLE_H3 " Type %s\\par}\r\n",rtf(type->name,0)); 419 | 420 | if(type->comment) 421 | fprintf(of,"%s\\par\r\n",rtf(type->comment,0)); 422 | 423 | if(type->type) 424 | fprintf(of,"{" STYLE_TT " typedef %s\\par}\r\n",rtf(type->type,0)); 425 | 426 | if(type->sutype) 427 | { 428 | fprintf(of,"\\trowd\\trgaph120\\cellx2880\\cellx9000\r\n\\intbl\\plain\r\n"); 429 | WriteRTFStructUnion(type->sutype,0); 430 | fprintf(of,"\\intbl0\r\n"); 431 | } 432 | else 433 | if(type->typexref) 434 | { 435 | if(type->typexref->type) 436 | fprintf(of,"See:\tTypedef %s\\par\r\n",rtf(type->typexref->name,0)); 437 | else 438 | if(!strncmp("enum",type->typexref->name,4)) 439 | fprintf(of,"See\tType %s\\par\r\n",rtf(type->typexref->name,0)); 440 | else 441 | if(!strncmp("union",type->typexref->name,5)) 442 | fprintf(of,"See:\tType %s\\par\r\n",rtf(type->typexref->name,0)); 443 | else 444 | if(!strncmp("struct",type->typexref->name,6)) 445 | fprintf(of,"See:\tType %s\\par\r\n",rtf(type->typexref->name,0)); 446 | } 447 | } 448 | 449 | 450 | /*++++++++++++++++++++++++++++++++++++++ 451 | Write a structure / union structure out. 452 | 453 | StructUnion su The structure / union to write. 454 | 455 | int depth The current depth within the structure. 456 | ++++++++++++++++++++++++++++++++++++++*/ 457 | 458 | static void WriteRTFStructUnion(StructUnion su, int depth) 459 | { 460 | int i; 461 | char* splitsu=NULL; 462 | 463 | splitsu=strstr(su->name,"{...}"); 464 | if(splitsu) splitsu[-1]=0; 465 | 466 | for(i=0;i<depth;i++) 467 | fprintf(of,"\t"); 468 | 469 | if(depth && su->comment && !su->comps) 470 | fprintf(of,"{" STYLE_TT " %s;}\\cell %s\\cell\\row\r\n",rtf(su->name,0),rtf(su->comment,0)); 471 | else if(!depth || su->comps) 472 | fprintf(of,"{" STYLE_TT " %s}\\cell\\cell\\row\r\n",rtf(su->name,0)); 473 | else 474 | fprintf(of,"{" STYLE_TT " %s;}\\cell\\cell\\row\r\n",rtf(su->name,0)); 475 | 476 | if(!depth || su->comps) 477 | { 478 | for(i=0;i<depth;i++) 479 | fprintf(of,"\t"); 480 | fprintf(of,"{" STYLE_TT " \\{}\\cell\\cell\\row\r\n"); 481 | 482 | for(i=0;i<su->n_comp;i++) 483 | WriteRTFStructUnion(su->comps[i],depth+1); 484 | 485 | for(i=0;i<depth;i++) 486 | fprintf(of,"\t"); 487 | fprintf(of,"{" STYLE_TT " \\}}\\cell\\cell\\row\r\n"); 488 | if(splitsu) 489 | { 490 | for(i=0;i<depth;i++) 491 | fprintf(of,"\t"); 492 | if(depth && su->comment) 493 | fprintf(of,"{" STYLE_TT " %s;}\\cell %s\\par\r\n",splitsu[5]?rtf(&splitsu[6],0):"",rtf(su->comment,0)); 494 | else 495 | fprintf(of,"{" STYLE_TT " %s;}\\cell\\cell\\row\r\n",splitsu[5]?rtf(&splitsu[6],0):""); 496 | } 497 | } 498 | 499 | if(splitsu) splitsu[-1]=' '; 500 | } 501 | 502 | 503 | /*++++++++++++++++++++++++++++++++++++++ 504 | Write a Variable structure out. 505 | 506 | Variable var The Variable structure to output. 507 | 508 | char* filename The name of the file that is being processed (required for the cross reference label). 509 | ++++++++++++++++++++++++++++++++++++++*/ 510 | 511 | static void WriteRTFVariable(Variable var,char* filename) 512 | { 513 | int i; 514 | 515 | if(var->scope&GLOBAL) 516 | fprintf(of,"{" STYLE_H3 " Variable %s\\par}\r\n",rtf(var->name,0)); 517 | else 518 | fprintf(of,"{" STYLE_H4 " Variable %s\\par}\r\n",rtf(var->name,0)); 519 | 520 | if(var->comment) 521 | fprintf(of,"%s\\par\r\n",rtf(var->comment,0)); 522 | 523 | fprintf(of,"{" STYLE_TT " "); 524 | 525 | if(var->scope&LOCAL) 526 | fprintf(of,"static "); 527 | else 528 | if(!(var->scope&GLOBAL) && var->scope&(EXTERNAL|EXTERN_F)) 529 | fprintf(of,"extern "); 530 | 531 | fprintf(of,"%s\\par}\r\n",rtf(var->type,0)); 532 | 533 | if(var->scope&(GLOBAL|LOCAL)) 534 | { 535 | if(var->incfrom || var->used->n || var->visible->n) 536 | { 537 | fprintf(of,"\\trowd\\trgaph120\\cellx1440\\cellx5220\\cellx9000\r\n\\intbl\\plain\r\n"); 538 | 539 | if(var->incfrom) 540 | fprintf(of,"Inc. from:\\cell %s\\cell\\row\r\n",rtf(var->incfrom,0)); 541 | 542 | for(i=0;i<var->visible->n;i++) 543 | { 544 | if(i==0) fprintf(of,"Visible in:"); 545 | if(var->visible->s1[i][0]=='$' && !var->visible->s1[i][1]) 546 | fprintf(of,"\\cell %s\\cell\\cell\\row\r\n",rtf(var->visible->s2[i],0)); 547 | else 548 | fprintf(of,"\\cell %s()\\cell %s\\cell\\row\r\n",rtf(var->visible->s1[i],0),rtf(var->visible->s2[i],0)); 549 | } 550 | 551 | for(i=0;i<var->used->n;i++) 552 | { 553 | if(i==0) fprintf(of,"Used in:"); 554 | if(var->used->s1[i][0]=='$' && !var->used->s1[i][1]) 555 | fprintf(of,"\\cell %s\\cell\\cell\\row\r\n",rtf(var->used->s2[i],0)); 556 | else 557 | if(var->scope&LOCAL) 558 | fprintf(of,"\\cell %s()\\cell\\cell\\row\r\n",rtf(var->used->s1[i],0)); 559 | else 560 | fprintf(of,"\\cell %s()\\cell %s\\cell\\row\r\n",rtf(var->used->s1[i],0),rtf(var->used->s2[i],0)); 561 | } 562 | fprintf(of,"\\intbl0\r\n"); 563 | } 564 | } 565 | else 566 | if(var->scope&(EXTERNAL|EXTERN_F) && var->defined) 567 | { 568 | fprintf(of,"\\trowd\\trgaph120\\cellx1440\\cellx5220\r\n\\intbl\\plain\r\n"); 569 | fprintf(of,"Defined in:\\cell %s\\cell\\row\r\n",rtf(var->defined,0)); 570 | fprintf(of,"\\intbl0\r\n"); 571 | } 572 | } 573 | 574 | 575 | /*++++++++++++++++++++++++++++++++++++++ 576 | Write a Function structure out. 577 | 578 | Function func The Function structure to output. 579 | 580 | char* filename The name of the file that is being processed (required for the cross reference label). 581 | ++++++++++++++++++++++++++++++++++++++*/ 582 | 583 | static void WriteRTFFunction(Function func,char* filename) 584 | { 585 | int i,pret,pargs; 586 | char* comment2=NULL,*type; 587 | 588 | if(func->scope&GLOBAL) 589 | fprintf(of,"{" STYLE_H3 " Global Function %s()\\par}\r\n",rtf(func->name,0)); 590 | else 591 | fprintf(of,"{" STYLE_H3 " Local Function %s()\\par}\r\n",rtf(func->name,0)); 592 | 593 | if(func->comment) 594 | if(option_verbatim_comments) 595 | fprintf(of,"{" STYLE_TT "%s\\par}\r\n",rtf(func->comment,1)); 596 | else 597 | { 598 | comment2=strstr(func->comment,"\r\n\r\n"); 599 | if(comment2) 600 | comment2[0]=0; 601 | fprintf(of,"%s\\par\r\n",rtf(func->comment,0)); 602 | } 603 | 604 | fprintf(of,"{" STYLE_TT " "); 605 | 606 | if(func->scope&LOCAL) 607 | fprintf(of,"static "); 608 | if(func->scope&INLINED) 609 | fprintf(of,"inline "); 610 | 611 | if((type=strstr(func->type,"()"))) 612 | type[0]=0; 613 | fprintf(of,"%s ( ",rtf(func->type,0)); 614 | 615 | for(i=0;i<func->args->n;i++) 616 | fprintf(of,i?", %s":"%s",rtf(func->args->s1[i],0)); 617 | 618 | if(type) 619 | {fprintf(of," %s\\par}\r\n",&type[1]);type[0]='(';} 620 | else 621 | fprintf(of," )\\par}\r\n"); 622 | 623 | pret =strncmp("void ",func->type,5) && func->cret; 624 | for(pargs=0,i=0;i<func->args->n;i++) 625 | pargs = pargs || ( strcmp("void",func->args->s1[i]) && func->args->s2[i] ); 626 | 627 | if(pret || pargs) 628 | { 629 | if(pret) 630 | fprintf(of,"{" STYLE_TT " %s\\par}\r\n{" STYLE_IND " %s\\par}\r\n",rtf(func->type,0),func->cret?rtf(func->cret,0):""); 631 | if(pargs) 632 | for(i=0;i<func->args->n;i++) 633 | fprintf(of,"{" STYLE_TT " %s\\par}\r\n{" STYLE_IND " %s\\par}\r\n",rtf(func->args->s1[i],0),func->args->s2[i]?rtf(func->args->s2[i],0):""); 634 | } 635 | 636 | if(comment2) 637 | { 638 | fprintf(of,"%s\\par\r\n",rtf(&comment2[2],0)); 639 | comment2[0]='\n'; 640 | } 641 | 642 | if(func->protofile || func->incfrom || func->calls->n || func->called->n || func->used->n || func->f_refs->n || func->v_refs->n) 643 | { 644 | fprintf(of,"\\trowd\\trgaph120\\cellx1440\\cellx5220\\cellx9000\r\n\\intbl\\plain\r\n"); 645 | 646 | if(func->protofile) 647 | fprintf(of,"Prototype:\\cell %s\\cell\\cell\\row\r\n",rtf(func->protofile,0)); 648 | 649 | if(func->incfrom) 650 | fprintf(of,"Inc. from:\\cell %s\\cell\\cell\\row\r\n",rtf(func->incfrom,0)); 651 | 652 | if(func->calls->n) 653 | { 654 | int others=0; 655 | 656 | fprintf(of,"Calls: "); 657 | 658 | for(i=0;i<func->calls->n;i++) 659 | if(func->calls->s2[i]) 660 | fprintf(of,"\\cell %s()\\cell %s\\cell\\row\r\n",rtf(func->calls->s1[i],0),rtf(func->calls->s2[i],0)); 661 | else 662 | others++; 663 | 664 | if(others) 665 | { 666 | fprintf(of,"\\cell "); 667 | for(i=0;i<func->calls->n;i++) 668 | if(!func->calls->s2[i]) 669 | fprintf(of,--others?" %s(),":" %s()",rtf(func->calls->s1[i],0)); 670 | fprintf(of,"\\cell\\cell\\row\r\n"); 671 | } 672 | } 673 | 674 | if(func->called->n) 675 | { 676 | for(i=0;i<func->called->n;i++) 677 | { 678 | if(i==0) 679 | fprintf(of,"Called by:"); 680 | fprintf(of,"\\cell %s()\\cell %s\\cell\\row\r\n",rtf(func->called->s1[i],0),rtf(func->called->s2[i],0)); 681 | } 682 | } 683 | 684 | if(func->used->n) 685 | { 686 | for(i=0;i<func->used->n;i++) 687 | { 688 | if(i==0) 689 | fprintf(of,"Used in:"); 690 | if(func->used->s1[i][0]=='$' && !func->used->s1[i][1]) 691 | fprintf(of,"\\cell %s\\cell\\cell\\row\r\n",rtf(func->used->s2[i],0)); 692 | else 693 | fprintf(of,"\\cell %s()\\cell %s\\cell\\row\r\n",rtf(func->used->s1[i],0),rtf(func->used->s2[i],0)); 694 | } 695 | } 696 | 697 | if(func->f_refs->n) 698 | { 699 | int others=0; 700 | 701 | fprintf(of,"Refs Func:"); 702 | 703 | for(i=0;i<func->f_refs->n;i++) 704 | if(func->f_refs->s2[i]) 705 | fprintf(of,"\\cell %s()\\cell %s\\cell\\row\r\n",rtf(func->f_refs->s1[i],0),rtf(func->f_refs->s2[i],0)); 706 | else 707 | others++; 708 | 709 | if(others) 710 | { 711 | fprintf(of,"\\cell "); 712 | for(i=0;i<func->f_refs->n;i++) 713 | if(!func->f_refs->s2[i]) 714 | fprintf(of,--others?" %s(),":" %s()",rtf(func->f_refs->s1[i],0)); 715 | fprintf(of,"\\cell\\cell\\row\r\n"); 716 | } 717 | } 718 | 719 | if(func->v_refs->n) 720 | { 721 | int others=0; 722 | 723 | fprintf(of,"Refs Var:"); 724 | 725 | for(i=0;i<func->v_refs->n;i++) 726 | if(func->v_refs->s2[i]) 727 | fprintf(of,"\\cell %s\\cell %s\\cell\\row\r\n",rtf(func->v_refs->s1[i],0),rtf(func->v_refs->s2[i],0)); 728 | else 729 | others++; 730 | 731 | if(others) 732 | { 733 | fprintf(of,"\\cell "); 734 | for(i=0;i<func->v_refs->n;i++) 735 | if(!func->v_refs->s2[i]) 736 | fprintf(of,--others?" %s,":" %s",rtf(func->v_refs->s1[i],0)); 737 | fprintf(of,"\\cell\\cell\\row\r\n"); 738 | } 739 | } 740 | fprintf(of,"\\intbl0\r\n"); 741 | } 742 | } 743 | 744 | 745 | /*++++++++++++++++++++++++++++++++++++++ 746 | Write out the appendix information. 747 | 748 | StringList files The list of files to write. 749 | 750 | StringList2 funcs The list of functions to write. 751 | 752 | StringList2 vars The list of variables to write. 753 | 754 | StringList2 types The list of types to write. 755 | ++++++++++++++++++++++++++++++++++++++*/ 756 | 757 | void WriteRTFAppendix(StringList files,StringList2 funcs,StringList2 vars,StringList2 types) 758 | { 759 | char* ofile; 760 | int i; 761 | 762 | /* Open the file */ 763 | 764 | ofile=ConcatStrings(5,option_odir,"/",option_name,RTF_APDX,RTF_FILE); 765 | 766 | of=fopen(ofile,"w"); 767 | 768 | if(!of) 769 | {fprintf(stderr,"cxref: Failed to open the RTF appendix file '%s'\r\n",ofile);exit(1);} 770 | 771 | /* Write the header out */ 772 | 773 | WriteRTFPreamble(of); 774 | 775 | fprintf(of,"{" STYLE_H1 " Cross References\\par}\r\n"); 776 | 777 | /* Write out the appendix of files. */ 778 | 779 | if(files->n) 780 | { 781 | fprintf(of,"{" STYLE_H2 " Files\\par}\r\n"); 782 | fprintf(of,"\\trowd\\trgaph120\\cellx4500\r\n\\intbl\\plain\r\n"); 783 | for(i=0;i<files->n;i++) 784 | fprintf(of,"%s\\cell\\row\r\n",rtf(files->s[i],0)); 785 | fprintf(of,"\\intbl0\r\n"); 786 | } 787 | 788 | /* Write out the appendix of functions. */ 789 | 790 | if(funcs->n) 791 | { 792 | fprintf(of,"{" STYLE_H2 " Global Functions\\par}\r\n"); 793 | fprintf(of,"\\trowd\\trgaph120\\cellx4500\\cellx9000\r\n\\intbl\\plain\r\n"); 794 | for(i=0;i<funcs->n;i++) 795 | fprintf(of,"%s\\cell %s\\cell\\row\r\n",rtf(funcs->s1[i],0),rtf(funcs->s2[i],0)); 796 | fprintf(of,"\\intbl0\r\n"); 797 | } 798 | 799 | /* Write out the appendix of variables. */ 800 | 801 | if(vars->n) 802 | { 803 | fprintf(of,"{" STYLE_H2 " Global Variables\\par}\r\n"); 804 | fprintf(of,"\\trowd\\trgaph120\\cellx4500\\cellx9000\r\n\\intbl\\plain\r\n"); 805 | for(i=0;i<vars->n;i++) 806 | fprintf(of,"%s\\cell %s\\cell\\row\r\n",rtf(vars->s1[i],0),rtf(vars->s2[i],0)); 807 | fprintf(of,"\\intbl0\r\n"); 808 | } 809 | 810 | /* Write out the appendix of types. */ 811 | 812 | if(types->n) 813 | { 814 | fprintf(of,"{" STYLE_H2 " Defined Types\\par}\r\n"); 815 | fprintf(of,"\\trowd\\trgaph120\\cellx4500\\cellx9000\r\n\\intbl\\plain\r\n"); 816 | for(i=0;i<types->n;i++) 817 | { 818 | if(!strncmp("enum",types->s1[i],4)) 819 | fprintf(of,"%s\\cell %s\\cell\\row\r\n",rtf(types->s1[i],0),rtf(types->s2[i],0)); 820 | else 821 | if(!strncmp("union",types->s1[i],5)) 822 | fprintf(of,"%s\\cell %s\\cell\\row\r\n",rtf(types->s1[i],0),rtf(types->s2[i],0)); 823 | else 824 | if(!strncmp("struct",types->s1[i],6)) 825 | fprintf(of,"%s\\cell %s\\cell\\row\r\n",rtf(types->s1[i],0),rtf(types->s2[i],0)); 826 | else 827 | fprintf(of,"%s\\cell %s\\cell\\row\r\n",rtf(types->s1[i],0),rtf(types->s2[i],0)); 828 | } 829 | fprintf(of,"\\intbl0\r\n"); 830 | } 831 | 832 | /* Finish up. */ 833 | 834 | WriteRTFPostamble(of); 835 | 836 | fclose(of); 837 | 838 | /* Clear the memory in rtf(,0) */ 839 | 840 | rtf(NULL,0); rtf(NULL,0); rtf(NULL,0); rtf(NULL,0); 841 | } 842 | 843 | 844 | /*++++++++++++++++++++++++++++++++++++++ 845 | Write out the head of an RTF file. 846 | 847 | FILE *f The file to write to. 848 | ++++++++++++++++++++++++++++++++++++++*/ 849 | 850 | static void WriteRTFPreamble(FILE *f) 851 | { 852 | fputs("{\\rtf\\ansi\r\n",f); 853 | fputs("\\deff0\r\n",f); 854 | fputs("{\\fonttbl\r\n",f); 855 | fputs("{\\f0\\froman Times New Roman;}\r\n",f); 856 | fputs("{\\f1\\fmodern Courier New;}\r\n",f); 857 | fputs("}\r\n",f); 858 | fputs("{\\stylesheet\r\n",f); 859 | fputs("{" STYLE_NORM " Normal;}\r\n",f); 860 | fputs("{" STYLE_H1 " Heading 1;}\r\n",f); 861 | fputs("{" STYLE_H2 " Heading 2;}\r\n",f); 862 | fputs("{" STYLE_H3 " Heading 3;}\r\n",f); 863 | fputs("{" STYLE_H4 " Heading 4;}\r\n",f); 864 | fputs("{" STYLE_TT " Code;}\r\n",f); 865 | fputs("}\r\n",f); 866 | 867 | fputs("{\\info{\\comment This RTF file generated by cxref. cxref program (c) Andrew M. Bishop 1995,96,97,98,99.}}\r\n",f); 868 | 869 | if(!strcmp("A4",PAGE)) 870 | fputs("\\paperw11880\\paperh16848\\margl1440\\margr1440\\margt1440\\margb1440\r\n",f); 871 | else 872 | fputs("\\paperw12240\\paperh15840\\margl1440\\margr1440\\margt1440\\margb1440\r\n",f); 873 | 874 | fputs("\\sectd\\plain\r\n" STYLE_NORM "\r\n",f); 875 | } 876 | 877 | 878 | /*++++++++++++++++++++++++++++++++++++++ 879 | Write out the tail of an RTF file. 880 | 881 | FILE *f The file to write to. 882 | ++++++++++++++++++++++++++++++++++++++*/ 883 | 884 | static void WriteRTFPostamble(FILE *f) 885 | { 886 | fputs("}\r\n",f); 887 | } 888 | 889 | 890 | /*++++++++++++++++++++++++++++++++++++++ 891 | Delete the RTF file and main file reference that belong to the named file. 892 | 893 | char *name The name of the file to delete. 894 | ++++++++++++++++++++++++++++++++++++++*/ 895 | 896 | void WriteRTFFileDelete(char *name) 897 | { 898 | char *ofile; 899 | 900 | ofile=ConcatStrings(4,option_odir,"/",name,RTF_FILE); 901 | unlink(ofile); 902 | } 903 | 904 | 905 | /*++++++++++++++++++++++++++++++++++++++ 906 | Make the input string safe to output as RTF ( not \, { or } ). 907 | 908 | char* rtf Returns a safe RTF string. 909 | 910 | char* c A non-safe RTF string. 911 | 912 | int verbatim Set to true inside a verbatim environment. 913 | 914 | The function can only be called four times in each fprintf() since it returns one of only four static strings. 915 | ++++++++++++++++++++++++++++++++++++++*/ 916 | 917 | static char* rtf(char* c,int verbatim) 918 | { 919 | static char safe[4][256],*malloced[4]={NULL,NULL,NULL,NULL}; 920 | static int which=0; 921 | int copy=0,skip=0; 922 | int i=0,j=0,delta=4,len=256-delta; 923 | char *ret; 924 | 925 | which=(which+1)%4; 926 | ret=safe[which]; 927 | 928 | safe[which][0]=0; 929 | 930 | if(malloced[which]) 931 | {Free(malloced[which]);malloced[which]=NULL;} 932 | 933 | if(c) 934 | { 935 | i=CopyOrSkip(c,"rtf",©,&skip); 936 | 937 | while(1) 938 | { 939 | for(;j<len && c[i];i++) 940 | { 941 | if(copy) 942 | {ret[j++]=c[i]; if(c[i]=='\n') copy=0;} 943 | else if(skip) 944 | { if(c[i]=='\n') skip=0;} 945 | else if(!verbatim && (j==0 || ret[j-1]==' ') && (c[i]==' ' || c[i]=='\t' || c[i]=='\n')) 946 | ; 947 | else 948 | switch(c[i]) 949 | { 950 | case '\\': 951 | case '{': 952 | case '}': 953 | ret[j++]='\\'; 954 | ret[j++]=c[i]; 955 | break; 956 | case '\t': 957 | if(!verbatim) 958 | ret[j++]=c[i]; 959 | else 960 | ret[j++]=' '; 961 | break; 962 | case '\n': 963 | if(verbatim) 964 | ret[j++]='\\',ret[j++]='p',ret[j++]='a',ret[j++]='r'; 965 | else 966 | ret[j++]=' '; 967 | break; 968 | default: 969 | ret[j++]=c[i]; 970 | } 971 | if(c[i]=='\n') 972 | i+=CopyOrSkip(c+i,"rtf",©,&skip); 973 | } 974 | 975 | if(c[i]) /* Not finished */ 976 | { 977 | if(malloced[which]) 978 | malloced[which]=Realloc(malloced[which],len+delta+256); 979 | else 980 | {malloced[which]=Malloc(len+delta+256); strncpy(malloced[which],ret,(unsigned)j);} 981 | ret=malloced[which]; 982 | len+=256; 983 | } 984 | else 985 | { 986 | ret[j]=0; 987 | 988 | if(!verbatim && j--) 989 | while(ret[j]==' ') 990 | ret[j--]=0; 991 | 992 | break; 993 | } 994 | } 995 | } 996 | 997 | return(ret); 998 | }