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