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 | }