    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 | }