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