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