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