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 &quot;%s&quot;</tt>\n",sgml(inc->name,0));
325  |  else
326  |     fprintf(of,"<item><tt>#include &lt;%s&gt;</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 &quot;%s&quot;</tt>\n",sgml(inc->name,0));
351  |     else
352  |        fprintf(of,"<item><tt>#include &lt;%s&gt;</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],"&lt;");j+=4;}
970  |                 break;
971  |                case '>':
972  |                 strcpy(&ret[j],"&gt;");j+=4;
973  |                 break;
974  |                case '"':
975  |                 strcpy(&ret[j],"&quot;");j+=6;
976  |                 break;
977  |                case '&':
978  |                 strcpy(&ret[j],"&amp;");j+=5;
979  |                 break;
980  |                case '$':
981  |                 strcpy(&ret[j],"&dollar;");j+=8;
982  |                 break;
983  |                case '#':
984  |                 strcpy(&ret[j],"&num;");j+=5;
985  |                 break;
986  |                case '%':
987  |                 strcpy(&ret[j],"&percnt;");j+=8;
988  |                 break;
989  |                case '~':
990  |                 strcpy(&ret[j],"&tilde;");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",&copy,&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 | }