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