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