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