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