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