1 | /***************************************
2 | $Header: /home/amb/CVS/cxref/src/rtf.c,v 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 | }