1    | /***************************************
2    |   $Header: /home/amb/cxref/RCS/sgml.c 1.5 2001/01/06 13:05:13 amb Exp $
3    | 
4    |   C Cross Referencing & Documentation tool. Version 1.5c.
5    | 
6    |   Writes the SGML output.
7    |   ******************/ /******************
8    |   Written by Andrew M. Bishop
9    | 
10   |   This file Copyright 1995,96,97,98,2001 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  |    {
237  |     if(option_verbatim_comments)
238  |        fprintf(of,"<p><tscreen><verb>\n%s\n</verb></tscreen>\n\n",sgml(file->comment,1));
239  |     else
240  |       {
241  |        char *rcs1=strstr(file->comment,"$Header"),*rcs2=NULL;
242  |        if(rcs1)
243  |          {
244  |           rcs2=strstr(&rcs1[1],"$");
245  |           if(rcs2)
246  |             {
247  |              rcs2[0]=0;
248  |              fprintf(of,"<bf>RCS %s</bf>\n<p>\n",sgml(&rcs1[1],0));
249  |              rcs2[0]='$';
250  |             }
251  |          }
252  |        if(rcs2)
253  |           fprintf(of,"%s\n<p>\n",sgml(&rcs2[2],0));
254  |        else
255  |           fprintf(of,"%s\n<p>\n",sgml(file->comment,0));
256  |       }
257  |    }
258  | 
259  |  if(file->inc_in->n)
260  |    {
261  |     int i;
262  | 
263  |     fprintf(of,"<p>\n<descrip>\n<tag>Included in:</tag>\n<itemize>\n");
264  |     for(i=0;i<file->inc_in->n;i++)
265  |        fprintf(of,"<item>%s\n",sgml(file->inc_in->s[i],0));
266  |     fprintf(of,"</itemize>\n</descrip>\n");
267  |    }
268  | 
269  |  if(file->f_refs->n || file->v_refs->n)
270  |     fprintf(of,"<descrip>\n");
271  | 
272  |  if(file->f_refs->n)
273  |    {
274  |     int others=0;
275  |     fprintf(of,"<tag>References Functions:</tag>\n<itemize>\n");
276  |     for(i=0;i<file->f_refs->n;i++)
277  |        if(file->f_refs->s2[i])
278  |           fprintf(of,"<item>%s()  :  %s\n",sgml(file->f_refs->s1[i],0),sgml(file->f_refs->s2[i],0));
279  |        else
280  |           others++;
281  | 
282  |     if(others)
283  |       {
284  |        fprintf(of,"<item>");
285  |        for(i=0;i<file->f_refs->n;i++)
286  |           if(!file->f_refs->s2[i])
287  |              fprintf(of,--others?" %s(),":" %s()",sgml(file->f_refs->s1[i],0));
288  |        fprintf(of,"\n");
289  |       }
290  |     fprintf(of,"</itemize>\n");
291  |    }
292  | 
293  |  if(file->v_refs->n)
294  |    {
295  |     int others=0;
296  |     fprintf(of,"<tag>References Variables:</tag>\n<itemize>\n");
297  |     for(i=0;i<file->v_refs->n;i++)
298  |       {
299  |        if(file->v_refs->s2[i])
300  |           fprintf(of,"<item>%s  :  %s\n",sgml(file->v_refs->s1[i],0),sgml(file->v_refs->s2[i],0));
301  |        else
302  |           others++;
303  |       }
304  | 
305  |     if(others)
306  |       {
307  |        fprintf(of,"<item>");
308  |        for(i=0;i<file->v_refs->n;i++)
309  |           if(!file->v_refs->s2[i])
310  |              fprintf(of,--others?" %s,":" %s",sgml(file->v_refs->s1[i],0));
311  |        fprintf(of,"\n");
312  |       }
313  |     fprintf(of,"</itemize>\n");
314  |    }
315  | 
316  |  if(file->f_refs->n || file->v_refs->n)
317  |     fprintf(of,"</descrip>\n");
318  | }
319  | 
320  | 
321  | /*++++++++++++++++++++++++++++++++++++++
322  |   Write an Include structure out.
323  | 
324  |   Include inc The Include structure to output.
325  |   ++++++++++++++++++++++++++++++++++++++*/
326  | 
327  | static void WriteSGMLInclude(Include inc)
328  | {
329  |  if(inc->comment)
330  |     fprintf(of,"%s\n<p>\n",sgml(inc->comment,0));
331  | 
332  |  fprintf(of,"<itemize>\n");
333  | 
334  |  if(inc->scope==LOCAL)
335  |     fprintf(of,"<item><tt>#include &quot;%s&quot;</tt>\n",sgml(inc->name,0));
336  |  else
337  |     fprintf(of,"<item><tt>#include &lt;%s&gt;</tt>\n",sgml(inc->name,0));
338  | 
339  |  if(inc->includes)
340  |     WriteSGMLSubInclude(inc->includes,1);
341  | 
342  |  fprintf(of,"</itemize>\n");
343  | }
344  | 
345  | 
346  | /*++++++++++++++++++++++++++++++++++++++
347  |   Write an Sub Include structure out. (An include structure that is included from another file.)
348  | 
349  |   Include inc The Include structure to output.
350  | 
351  |   int depth The depth of the include hierarchy.
352  |   ++++++++++++++++++++++++++++++++++++++*/
353  | 
354  | static void WriteSGMLSubInclude(Include inc,int depth)
355  | {
356  |  fprintf(of,"<itemize>\n");
357  | 
358  |  while(inc)
359  |    {
360  |     if(inc->scope==LOCAL)
361  |        fprintf(of,"<item><tt>#include &quot;%s&quot;</tt>\n",sgml(inc->name,0));
362  |     else
363  |        fprintf(of,"<item><tt>#include &lt;%s&gt;</tt>\n",sgml(inc->name,0));
364  | 
365  |     if(inc->includes)
366  |        WriteSGMLSubInclude(inc->includes,depth+1);
367  | 
368  |     inc=inc->next;
369  |    }
370  | 
371  |  fprintf(of,"</itemize>\n");
372  | }
373  | 
374  | 
375  | /*++++++++++++++++++++++++++++++++++++++
376  |   Write a Define structure out.
377  | 
378  |   Define def The Define structure to output.
379  |   ++++++++++++++++++++++++++++++++++++++*/
380  | 
381  | static void WriteSGMLDefine(Define def)
382  | {
383  |  int i;
384  |  int pargs=0;
385  | 
386  |  if(def->comment)
387  |     fprintf(of,"%s\n<p>\n",sgml(def->comment,0));
388  | 
389  |  fprintf(of,"<tt>#define %s",sgml(def->name,0));
390  | 
391  |  if(def->value)
392  |     fprintf(of," %s",sgml(def->value,0));
393  | 
394  |  if(def->args->n)
395  |    {
396  |     fprintf(of,"( ");
397  |     for(i=0;i<def->args->n;i++)
398  |        fprintf(of,i?", %s":"%s",sgml(def->args->s1[i],0));
399  |     fprintf(of," )");
400  |    }
401  |  fprintf(of,"</tt><newline>\n");
402  | 
403  |  for(i=0;i<def->args->n;i++)
404  |     if(def->args->s2[i])
405  |        pargs=1;
406  | 
407  |  if(pargs)
408  |    {
409  |     fprintf(of,"<descrip>\n");
410  |     for(i=0;i<def->args->n;i++)
411  |        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):"");
412  |     fprintf(of,"</descrip>\n");
413  |    }
414  | }
415  | 
416  | 
417  | /*++++++++++++++++++++++++++++++++++++++
418  |   Write a Typedef structure out.
419  | 
420  |   Typedef type The Typedef structure to output.
421  |   ++++++++++++++++++++++++++++++++++++++*/
422  | 
423  | static void WriteSGMLTypedef(Typedef type)
424  | {
425  |  fprintf(of,"\n<sect1>");
426  | 
427  |  if(type->type)
428  |     fprintf(of,"Typedef %s",sgml(type->name,0));
429  |  else
430  |     fprintf(of,"Type %s",sgml(type->name,0));
431  | 
432  |  fprintf(of,"\n\n<p>\n");
433  | 
434  |  if(type->comment)
435  |     fprintf(of,"%s\n<p>\n",sgml(type->comment,0));
436  | 
437  |  if(type->type)
438  |     fprintf(of,"<tt>typedef %s</tt><newline>\n",sgml(type->type,0));
439  | 
440  |  if(type->sutype)
441  |    {
442  |     fprintf(of,"<itemize>\n");
443  |     WriteSGMLStructUnion(type->sutype,0);
444  |     fprintf(of,"</itemize>\n");
445  |    }
446  |  else
447  |     if(type->typexref)
448  |       {
449  |        fprintf(of,"<descrip>\n<tag>See:</tag>\n<itemize>\n");
450  |        if(type->typexref->type)
451  |           fprintf(of,"<item>Typedef %s\n",sgml(type->typexref->name,0));
452  |        else
453  |           if(!strncmp("enum",type->typexref->name,4))
454  |              fprintf(of,"<item>Type %s\n",sgml(type->typexref->name,0));
455  |           else
456  |              if(!strncmp("union",type->typexref->name,5))
457  |                 fprintf(of,"<item>Type %s\n",sgml(type->typexref->name,0));
458  |              else
459  |                 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)
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):"&nbs;");
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):"&nbs;");
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. -->\n",f);
791  |  fputs("<!-- cxref program (c) Andrew M. Bishop 1995,96,97,98,99. -->\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
901  |           if(!strncmp("union",types->s1[i],5))
902  |              fprintf(of,"<item>%s  :  %s\n",sgml(types->s1[i],0),sgml(types->s2[i],0));
903  |           else
904  |              if(!strncmp("struct",types->s1[i],6))
905  |                 fprintf(of,"<item>%s  :  %s\n",sgml(types->s1[i],0),sgml(types->s2[i],0));
906  |              else
907  |                 fprintf(of,"<item>%s  :  %s\n",sgml(types->s1[i],0),sgml(types->s2[i],0));
908  |     fprintf(of,"</itemize>\n");
909  |    }
910  | 
911  |  WriteSGMLPostamble(of);
912  | 
913  |  fclose(of);
914  | 
915  |  /* Clear the memory in sgml(,0) */
916  | 
917  |  sgml(NULL,0); sgml(NULL,0); sgml(NULL,0); sgml(NULL,0);
918  | }
919  | 
920  | 
921  | /*++++++++++++++++++++++++++++++++++++++
922  |   Delete the SGML file and main file reference that belong to the named file.
923  | 
924  |   char *name The name of the file to delete.
925  |   ++++++++++++++++++++++++++++++++++++++*/
926  | 
927  | void WriteSGMLFileDelete(char *name)
928  | {
929  |  char *ofile;
930  | 
931  |  ofile=ConcatStrings(4,option_odir,"/",name,SGML_FILE);
932  |  unlink(ofile);
933  | }
934  | 
935  | 
936  | /*++++++++++++++++++++++++++++++++++++++
937  |   Make the input string safe to output as SGML ( not <,  >,  &,  ",  $,  #,  % or ~ ).
938  | 
939  |   char* sgml Returns a safe SGML string.
940  | 
941  |   char* c A non-safe SGML string.
942  | 
943  |   int verbatim Set to true inside a verbatim environment.
944  | 
945  |   The function can only be called four times in each fprintf() since it returns one of only four static strings.
946  |   ++++++++++++++++++++++++++++++++++++++*/
947  | 
948  | static char* sgml(char* c,int verbatim)
949  | {
950  |  static char safe[4][256],*malloced[4]={NULL,NULL,NULL,NULL};
951  |  static int which=0;
952  |  int copy=0,skip=0;
953  |  int i=0,j=0,delta=10,len=256-delta;
954  |  char* ret;
955  | 
956  |  which=(which+1)%4;
957  |  ret=safe[which];
958  | 
959  |  safe[which][0]=0;
960  | 
961  |  if(malloced[which])
962  |    {Free(malloced[which]);malloced[which]=NULL;}
963  | 
964  |  if(c)
965  |    {
966  |     i=CopyOrSkip(c,"sgml",&copy,&skip);
967  | 
968  |     while(1)
969  |       {
970  |        for(;j<len && c[i];i++)
971  |          {
972  |           if(copy)
973  |             {ret[j++]=c[i]; if(c[i]=='\n') copy=0;}
974  |           else if(skip)
975  |             {               if(c[i]=='\n') skip=0;}
976  |           else if(verbatim)
977  |              switch(c[i])
978  |                {
979  |                case '&':
980  |                 strcpy(&ret[j],"&ero;");j+=5;
981  |                 break;
982  |                case '<':
983  |                 if(c[i+1]=='/')
984  |                   {strcpy(&ret[j],"&etago;");j+=7; break;}
985  |                default:
986  |                 ret[j++]=c[i];
987  |                }
988  |           else
989  |              switch(c[i])
990  |                {
991  |                case '<':
992  |                 if(c[i+1]=='/')
993  |                   {strcpy(&ret[j],"&etago;");j+=7;}
994  |                 else
995  |                   {strcpy(&ret[j],"&lt;");j+=4;}
996  |                 break;
997  |                case '>':
998  |                 strcpy(&ret[j],"&gt;");j+=4;
999  |                 break;
1000 |                case '"':
1001 |                 strcpy(&ret[j],"&quot;");j+=6;
1002 |                 break;
1003 |                case '&':
1004 |                 strcpy(&ret[j],"&amp;");j+=5;
1005 |                 break;
1006 |                case '$':
1007 |                 strcpy(&ret[j],"&dollar;");j+=8;
1008 |                 break;
1009 |                case '#':
1010 |                 strcpy(&ret[j],"&num;");j+=5;
1011 |                 break;
1012 |                case '%':
1013 |                 strcpy(&ret[j],"&percnt;");j+=8;
1014 |                 break;
1015 |                case '~':
1016 |                 strcpy(&ret[j],"&tilde;");j+=7;
1017 |                 break;
1018 |                case '\n':
1019 |                 if(j && ret[j-1]=='\n')
1020 |                   {
1021 |                    strcpy(&ret[j],"<newline>");j+=9;
1022 |                   }
1023 |                 ret[j++]=c[i];
1024 |                 break;
1025 |                default:
1026 |                 ret[j++]=c[i];
1027 |                }
1028 |           if(c[i]=='\n')
1029 |              i+=CopyOrSkip(c+i,"sgml",&copy,&skip);
1030 |          }
1031 | 
1032 |        if(c[i])                 /* Not finished */
1033 |          {
1034 |           if(malloced[which])
1035 |              malloced[which]=Realloc(malloced[which],len+delta+256);
1036 |           else
1037 |             {malloced[which]=Malloc(len+delta+256); strncpy(malloced[which],ret,(unsigned)j);}
1038 |           ret=malloced[which];
1039 |           len+=256;
1040 |          }
1041 |        else
1042 |          {ret[j]=0; break;}
1043 |       }
1044 |    }
1045 | 
1046 |  return(ret);
1047 | }