1 /***************************************
2   $Header: /home/amb/CVS/cxref/src/latex.c,v 1.40 2004-06-26 18:50:36 amb Exp $
3 
4   C Cross Referencing & Documentation tool. Version 1.6.
5 
6   Writes the Latex output.
7   ******************/ /******************
8   Written by Andrew M. Bishop
9 
10   This file Copyright 1995,96,97,98,2001,04 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 #ifndef min
24 #define min(x,y) ( (x) < (y) ? (x) : (y) )
25 #endif
26 
27 #include "version.h"
28 #include "memory.h"
29 #include "datatype.h"
30 #include "cxref.h"
31 
32 /*+ The name of the output tex file that includes each of the others. +*/
33 #define LATEX_FILE        ".tex"
34 #define LATEX_FILE_BACKUP ".tex~"
35 
36 /*+ The name of the output tex file that contains the appendix. +*/
37 #define LATEX_APDX        ".apdx"
38 
39 /*+ The comments are to be inserted verbatim. +*/
40 extern int option_verbatim_comments;
41 
42 /*+ The name of the directory for the output. +*/
43 extern char* option_odir;
44 
45 /*+ The base name of the file for the output. +*/
46 extern char* option_name;
47 
48 /*+ The information about the cxref run, +*/
49 extern char *run_command,       /*+ the command line options. +*/
50             *run_cpp_command;   /*+ the cpp command and options. +*/
51 
52 /*+ The built-in style sheets. +*/
53 extern char *latex_fonts_style,*latex_page_style,*latex_cxref_style;
54 
55 /* Local functions */
56 
57 static void WriteLatexFilePart(File file);
58 static void WriteLatexInclude(Include inc);
59 static void WriteLatexSubInclude(Include inc,int depth);
60 static void WriteLatexDefine(Define def);
61 static void WriteLatexTypedef(Typedef type);
62 static void WriteLatexStructUnion(StructUnion su,int depth);
63 static void WriteLatexVariable(Variable var);
64 static void WriteLatexFunction(Function func);
65 
66 static void WriteLatexDocument(char* name,int appendix);
67 static void WriteLatexTemplate(char* name);
68 
69 static char* latex(char* c,int verbatim);
70 
71 /*+ The output file for the latex. +*/
72 static FILE* of;
73 
74 /*+ The name of the file. +*/
75 static char *filename;
76 
77 /*+ Counts the lines in a table to insert breaks. +*/
78 static int countlines=0;
79 
80 
81 /*++++++++++++++++++++++++++++++++++++++
82   Write a Latex file for a complete File structure and all components.
83 
84   File file The File structure to output.
85   ++++++++++++++++++++++++++++++++++++++*/
86 
WriteLatexFile(File file)87 void WriteLatexFile(File file)
88 {
89  char* ofile;
90 
91  filename=file->name;
92 
93  /* Write the including file. */
94 
95  WriteLatexDocument(file->name,0);
96 
97  /* Open the file */
98 
99  ofile=ConcatStrings(4,option_odir,"/",file->name,LATEX_FILE);
100 
101  of=fopen(ofile,"w");
102  if(!of)
103    {
104     struct stat stat_buf;
105     int i,ofl=strlen(ofile);
106 
107     for(i=strlen(option_odir)+1;i<ofl;i++)
108        if(ofile[i]=='/')
109          {
110           ofile[i]=0;
111           if(stat(ofile,&stat_buf))
112              mkdir(ofile,S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
113           ofile[i]='/';
114          }
115 
116     of=fopen(ofile,"w");
117    }
118 
119  if(!of)
120    {fprintf(stderr,"cxref: Failed to open the LaTeX output file '%s'\n",ofile);exit(1);}
121 
122  /* Write out a header. */
123 
124  fputs("% This LaTeX file generated by cxref (version " CXREF_VERSION ").\n",of);
125  fputs("% cxref program " CXREF_COPYRIGHT ".\n",of);
126  fputs("\n",of);
127  fprintf(of,"%% Cxref: %s %s\n",run_command,file->name);
128  fprintf(of,"%% CPP  : %s\n",run_cpp_command);
129  fputs("\n",of);
130 
131  /*+ The file structure is broken into its components and they are each written out. +*/
132 
133  WriteLatexFilePart(file);
134 
135  if(file->includes)
136    {
137     Include inc =file->includes;
138     fprintf(of,"\n\\subsection*{Included Files}\n\n");
139     do{
140        if(inc!=file->includes)
141           fprintf(of,"\\medskip\n");
142        WriteLatexInclude(inc);
143       }
144     while((inc=inc->next));
145    }
146 
147  if(file->defines)
148    {
149     Define def =file->defines;
150     fprintf(of,"\n\\subsection*{Preprocessor definitions}\n\n");
151     do{
152        if(def!=file->defines)
153           fprintf(of,"\\medskip\n");
154        WriteLatexDefine(def);
155       }
156     while((def=def->next));
157    }
158 
159  if(file->typedefs)
160    {
161     Typedef type=file->typedefs;
162     fprintf(of,"\n\\subsection{Type definitions}\n\n");
163     do{
164        WriteLatexTypedef(type);
165       }
166     while((type=type->next));
167    }
168 
169  if(file->variables)
170    {
171     int any_to_mention=0;
172     Variable var=file->variables;
173 
174     do{
175        if(var->scope&(GLOBAL|LOCAL|EXTERNAL|EXTERN_F))
176           any_to_mention=1;
177       }
178     while((var=var->next));
179 
180     if(any_to_mention)
181       {
182        int first_ext=1,first_local=1;
183        Variable var=file->variables;
184        fprintf(of,"\n\\subsection{Variables}\n\n");
185        do{
186           if(var->scope&GLOBAL)
187              WriteLatexVariable(var);
188          }
189        while((var=var->next));
190        var=file->variables;
191        do{
192           if(var->scope&(EXTERNAL|EXTERN_F) && !(var->scope&GLOBAL))
193             {
194              if(first_ext)
195                {fprintf(of,"\n\\subsubsection{External Variables}\n\n"); first_ext=0;}
196              else
197                 fprintf(of,"\\medskip\n");
198              WriteLatexVariable(var);
199             }
200          }
201        while((var=var->next));
202        var=file->variables;
203        do{
204           if(var->scope&LOCAL)
205             {
206              if(first_local)
207                {fprintf(of,"\n\\subsubsection{Local Variables}\n\n"); first_local=0;}
208              else
209                 fprintf(of,"\\medskip\n");
210              WriteLatexVariable(var);
211             }
212          }
213        while((var=var->next));
214       }
215    }
216 
217  if(file->functions)
218    {
219     Function func=file->functions;
220     fprintf(of,"\n\\subsection{Functions}\n\n");
221     do{
222        if(func->scope&(GLOBAL|EXTERNAL))
223           WriteLatexFunction(func);
224       }
225     while((func=func->next));
226     func=file->functions;
227     do{
228        if(func->scope&LOCAL)
229           WriteLatexFunction(func);
230       }
231     while((func=func->next));
232    }
233 
234  fclose(of);
235 
236  /* Clear the memory in latex() */
237 
238  latex(NULL,0); latex(NULL,0); latex(NULL,0); latex(NULL,0);
239 }
240 
241 
242 /*++++++++++++++++++++++++++++++++++++++
243   Write a File structure out.
244 
245   File file The File to output.
246   ++++++++++++++++++++++++++++++++++++++*/
247 
WriteLatexFilePart(File file)248 static void WriteLatexFilePart(File file)
249 {
250  int i;
251 
252  fprintf(of,"\\markboth{File %s}{File %s}\n",latex(file->name,0),latex(file->name,0));
253  fprintf(of,"\\section{File %s}\n",latex(file->name,0));
254  fprintf(of,"\\label{file_%s}\n\n",file->name);
255 
256  if(file->comment)
257    {
258     if(option_verbatim_comments)
259        fprintf(of,"\\begin{verbatim}\n%s\n\\end{verbatim}\n\n",latex(file->comment,1));
260     else
261       {
262        char *rcs1=strstr(file->comment,"$Header"),*rcs2=NULL;
263        if(rcs1)
264          {
265           rcs2=strstr(&rcs1[1],"$");
266           if(rcs2)
267             {
268              rcs2[0]=0;
269              fprintf(of,"{\\bf RCS %s}\n\n",latex(&rcs1[1],0));
270              fprintf(of,"\\smallskip\n");
271              rcs2[0]='$';
272             }
273          }
274        if(rcs2)
275           fprintf(of,"%s\n\n",latex(&rcs2[2],0));
276        else
277           fprintf(of,"%s\n\n",latex(file->comment,0));
278       }
279    }
280 
281  if(file->inc_in->n)
282    {
283     int i;
284 
285     if(file->comment)
286        fprintf(of,"\\medskip\n");
287     fprintf(of,"\\begin{cxreftabii}\nIncluded in:");
288     for(i=0;i<file->inc_in->n;i++)
289       {/* Allow a break in every 8 (or so) items to allow the table to break over the page. */
290        if(min(i,file->inc_in->n-i)%8 == 4)
291           fprintf(of,"\\cxreftabbreak{cxreftabii}\n");
292        fprintf(of,"\\ & %s & \\cxreffile{%s}\\\\\n",latex(file->inc_in->s[i],0),file->inc_in->s[i]);
293       }
294     fprintf(of,"\\end{cxreftabii}\n\n");
295    }
296 
297  if(file->f_refs->n || file->v_refs->n)
298    {
299     int tabcount=0;
300     fprintf(of,"\\smallskip\n");
301     fprintf(of,"\\begin{cxreftabiii}\n");
302 
303     if(file->f_refs->n)
304       {
305        int others=0;
306 
307        fprintf(of,"Refs Func:");
308 
309        for(i=0;i<file->f_refs->n;i++)
310           if(file->f_refs->s2[i])
311             {
312              fprintf(of,"\\ & %s() & %s & \\cxreffunc{%s}{%s}\\\\\n",latex(file->f_refs->s1[i],0),latex(file->f_refs->s2[i],0),file->f_refs->s1[i],file->f_refs->s2[i]);
313              if(++tabcount%8 == 4)
314                 fprintf(of,"\\cxreftabbreak{cxreftabiii}\n");
315             }
316           else
317              others++;
318 
319        if(others)
320          {
321           fprintf(of,"\\ & \\cxreftabiiispan{");
322           for(i=0;i<file->f_refs->n;i++)
323              if(!file->f_refs->s2[i])
324                 fprintf(of,--others?"%s(), ":"%s()",latex(file->f_refs->s1[i],0));
325           fprintf(of,"} &\\\\\n");
326          }
327       }
328 
329     if(file->v_refs->n)
330       {
331        int others=0;
332 
333        fprintf(of,"Refs Var:");
334 
335        for(i=0;i<file->v_refs->n;i++)
336           if(file->v_refs->s2[i])
337             {
338              fprintf(of,"\\ & %s & %s & \\cxrefvar{%s}{%s}\\\\\n",latex(file->v_refs->s1[i],0),latex(file->v_refs->s2[i],0),file->v_refs->s1[i],file->v_refs->s2[i]);
339              if(++tabcount%8 == 4)
340                 fprintf(of,"\\cxreftabbreak{cxreftabiii}\n");
341             }
342           else
343              others++;
344 
345        if(others)
346          {
347           fprintf(of,"\\ & \\cxreftabiiispan{");
348           for(i=0;i<file->v_refs->n;i++)
349              if(!file->v_refs->s2[i])
350                 fprintf(of,--others?" %s,":" %s",latex(file->v_refs->s1[i],0));
351           fprintf(of,"} &\\\\\n");
352          }
353       }
354 
355     fprintf(of,"\\end{cxreftabiii}\n\n");
356    }
357 }
358 
359 
360 /*++++++++++++++++++++++++++++++++++++++
361   Write an Include structure out.
362 
363   Include inc The Include structure to output.
364   ++++++++++++++++++++++++++++++++++++++*/
365 
WriteLatexInclude(Include inc)366 static void WriteLatexInclude(Include inc)
367 {
368  if(inc->comment)
369     fprintf(of,"%s\n\n\\smallskip\n",latex(inc->comment,0));
370 
371  fprintf(of,"\\begin{cxreftabi}\n"); countlines=1;
372 
373  if(inc->scope==LOCAL)
374     fprintf(of,"{\\stt \\#include \"%s\"} &\\cxreffile{%s}\\\\\n",latex(inc->name,0),inc->name);
375  else
376     fprintf(of,"{\\stt \\#include <%s>} &\\\\\n",latex(inc->name,0));
377 
378  if(inc->includes)
379     WriteLatexSubInclude(inc->includes,1);
380 
381  fprintf(of,"\\end{cxreftabi}\n\n");
382 }
383 
384 
385 /*++++++++++++++++++++++++++++++++++++++
386   Write an Sub Include structure out. (An include structure that is included from another file.)
387 
388   Include inc The Include structure to output.
389 
390   int depth The depth of the include hierarchy.
391   ++++++++++++++++++++++++++++++++++++++*/
392 
WriteLatexSubInclude(Include inc,int depth)393 static void WriteLatexSubInclude(Include inc,int depth)
394 {
395  while(inc)
396    {
397     if(countlines++%8==4)
398        fprintf(of,"\\cxreftabbreak{cxreftabi}\n");
399 
400     fprintf(of,"\\hspace*{%3.1fin}",0.2*depth);
401 
402     if(inc->scope==LOCAL)
403        fprintf(of,"{\\stt \\#include \"%s\"} &\\cxreffile{%s}\\\\\n",latex(inc->name,0),inc->name);
404     else
405        fprintf(of,"{\\stt \\#include <%s>} &\\\\\n",latex(inc->name,0));
406 
407     if(inc->includes)
408        WriteLatexSubInclude(inc->includes,depth+1);
409 
410     inc=inc->next;
411    }
412 }
413 
414 
415 /*++++++++++++++++++++++++++++++++++++++
416   Write a Define structure out.
417 
418   Define def The Define structure to output.
419   ++++++++++++++++++++++++++++++++++++++*/
420 
WriteLatexDefine(Define def)421 static void WriteLatexDefine(Define def)
422 {
423  int i;
424  int pargs=0;
425 
426  if(def->comment)
427     fprintf(of,"%s\n\n\\smallskip\n",latex(def->comment,0));
428 
429  fprintf(of,"{\\stt \\#define %s",latex(def->name,0));
430 
431  if(def->value)
432     fprintf(of," %s",latex(def->value,0));
433 
434  if(def->args->n)
435    {
436     fprintf(of,"( ");
437     for(i=0;i<def->args->n;i++)
438        fprintf(of,i?", %s":"%s",latex(def->args->s1[i],0));
439     fprintf(of," )");
440    }
441  fprintf(of,"}\n\n");
442 
443  for(i=0;i<def->args->n;i++)
444     if(def->args->s2[i])
445        pargs=1;
446 
447  if(pargs)
448    {
449     fprintf(of,"\\smallskip\n");
450     fprintf(of,"\\begin{cxrefarglist}\n");
451     for(i=0;i<def->args->n;i++)
452        fprintf(of,"\\cxrefargitem{%s} %s\n",latex(def->args->s1[i],0),def->args->s2[i]?latex(def->args->s2[i],0):"\\ ");
453     fprintf(of,"\\end{cxrefarglist}\n\n");
454    }
455 }
456 
457 
458 /*++++++++++++++++++++++++++++++++++++++
459   Write a Typedef structure out.
460 
461   Typedef type The Typedef structure to output.
462   ++++++++++++++++++++++++++++++++++++++*/
463 
WriteLatexTypedef(Typedef type)464 static void WriteLatexTypedef(Typedef type)
465 {
466  if(type->type)
467     fprintf(of,"\n\\subsubsection{Typedef %s}\n",latex(type->name,0));
468  else
469     fprintf(of,"\n\\subsubsection{Type %s}\n",latex(type->name,0));
470 
471  if(!strncmp("enum",type->name,4))
472     fprintf(of,"\\label{type_enum_%s_%s}\n\n",&type->name[5],filename);
473  else if(!strncmp("union",type->name,5))
474     fprintf(of,"\\label{type_union_%s_%s}\n\n",&type->name[6],filename);
475  else if(!strncmp("struct",type->name,6))
476     fprintf(of,"\\label{type_struct_%s_%s}\n\n",&type->name[7],filename);
477  else
478     fprintf(of,"\\label{type_%s_%s}\n\n",type->name,filename);
479 
480  if(type->comment)
481     fprintf(of,"%s\n\n\\smallskip\n",latex(type->comment,0));
482 
483  if(type->type)
484     fprintf(of,"{\\stt typedef %s}\n\n",latex(type->type,0));
485 
486  if(type->sutype)
487    {
488     fprintf(of,"\\smallskip\n");
489     fprintf(of,"\\begin{cxreftabiia}\n"); countlines=0;
490     WriteLatexStructUnion(type->sutype,0);
491     fprintf(of,"\\end{cxreftabiia}\n\n");
492    }
493  else
494     if(type->typexref)
495       {
496        fprintf(of,"\\smallskip\n");
497        fprintf(of,"\\begin{cxreftabii}\n");
498        if(type->typexref->type)
499           fprintf(of,"See:& Typedef %s & \\cxreftype{%s}{%s}\\\\\n",latex(type->typexref->name,0),type->typexref->name,filename);
500        else if(!strncmp("enum",type->typexref->name,4))
501           fprintf(of,"See:& Type %s & \\cxreftype{enum_%s}{%s}\\\\\n",latex(type->typexref->name,0),&type->typexref->name[5],filename);
502        else if(!strncmp("union",type->typexref->name,5))
503           fprintf(of,"See:& Type %s & \\cxreftype{union_%s}{%s}\\\\\n",latex(type->typexref->name,0),&type->typexref->name[6],filename);
504        else if(!strncmp("struct",type->typexref->name,6))
505           fprintf(of,"See:& Type %s & \\cxreftype{struct_%s}{%s}\\\\\n",latex(type->typexref->name,0),&type->typexref->name[7],filename);
506        fprintf(of,"\\end{cxreftabii}\n\n");
507       }
508 }
509 
510 
511 /*++++++++++++++++++++++++++++++++++++++
512   Write a structure / union structure out.
513 
514   StructUnion su The structure / union to write.
515 
516   int depth The current depth within the structure.
517   ++++++++++++++++++++++++++++++++++++++*/
518 
WriteLatexStructUnion(StructUnion su,int depth)519 static void WriteLatexStructUnion(StructUnion su, int depth)
520 {
521  int i;
522  char* splitsu=NULL;
523 
524  splitsu=strstr(su->name,"{...}");
525  if(splitsu) splitsu[-1]=0;
526 
527  if(countlines++%8==4)
528     fprintf(of,"\\cxreftabbreak{cxreftabiia}\n");
529  fprintf(of,"\\hspace*{%3.1fin}",0.2*depth);
530 
531  if(depth && su->comment && !su->comps)
532     fprintf(of,"{\\stt %s;} & %s \\\\\n",latex(su->name,0),latex(su->comment,0));
533  else if(!depth || su->comps)
534     fprintf(of,"{\\stt %s} &\\\\\n",latex(su->name,0));
535  else
536     fprintf(of,"{\\stt %s;} &\\\\\n",latex(su->name,0));
537 
538  if(!depth || su->comps)
539    {
540     fprintf(of,"\\hspace*{%3.1fin}",0.1+0.2*depth);
541     fprintf(of,"{\\stt \\{} &\\\\\n");
542 
543     for(i=0;i<su->n_comp;i++)
544        WriteLatexStructUnion(su->comps[i],depth+1);
545 
546     fprintf(of,"\\hspace*{%3.1fin}",0.1+0.2*depth);
547     fprintf(of,"{\\stt \\}} &\\\\\n");
548     if(splitsu)
549       {
550        fprintf(of,"\\hspace*{%3.1fin}",0.1+0.2*depth);
551        if(depth && su->comment)
552           fprintf(of,"{\\stt %s;} & %s \\\\\n",splitsu[5]?latex(&splitsu[6],0):"",latex(su->comment,0));
553        else
554           fprintf(of,"{\\stt %s;} &\\\\\n",splitsu[5]?latex(&splitsu[6],0):"");
555       }
556    }
557 
558  if(splitsu) splitsu[-1]=' ';
559 }
560 
561 
562 /*++++++++++++++++++++++++++++++++++++++
563   Write a Variable structure out.
564 
565   Variable var The Variable structure to output.
566   ++++++++++++++++++++++++++++++++++++++*/
567 
WriteLatexVariable(Variable var)568 static void WriteLatexVariable(Variable var)
569 {
570  int i;
571 
572  if(var->scope&GLOBAL)
573     fprintf(of,"\n\\subsubsection{Variable %s}\n",latex(var->name,0));
574  else
575     fprintf(of,"{\\bf %s}\n",latex(var->name,0));
576 
577  fprintf(of,"\\label{var_%s_%s}\n\n",var->name,filename);
578 
579  if(var->comment)
580     fprintf(of,"%s\n\n\\smallskip\n",latex(var->comment,0));
581 
582  fprintf(of,"{\\stt ");
583 
584  if(var->scope&LOCAL)
585     fprintf(of,"static ");
586  else
587     if(!(var->scope&GLOBAL) && var->scope&(EXTERNAL|EXTERN_F))
588        fprintf(of,"extern ");
589 
590  fprintf(of,"%s}\n\n",latex(var->type,0));
591 
592  if(var->scope&(GLOBAL|LOCAL))
593    {
594     if(var->incfrom || var->used->n || var->visible->n)
595       {
596        fprintf(of,"\\smallskip\n");
597        fprintf(of,"\\begin{cxreftabiii}\n");
598 
599        if(var->incfrom)
600           fprintf(of,"Inc. from:& %s & \\ & \\cxrefvar{%s}{%s}\\\\\n",latex(var->incfrom,0),var->name,var->incfrom);
601 
602        for(i=0;i<var->visible->n;i++)
603          {
604           if(min(i,var->visible->n+var->used->n-i)%8 == 4)
605              fprintf(of,"\\cxreftabbreak{cxreftabiii}\n");
606           if(i==0) fprintf(of,"Visible in:");
607           if(var->visible->s1[i][0]=='$' && !var->visible->s1[i][1])
608              fprintf(of,"\\ & %s & \\ & \\cxreffile{%s}\\\\\n",latex(var->visible->s2[i],0),var->visible->s2[i]);
609           else
610              fprintf(of,"\\ & %s() & %s & \\cxreffunc{%s}{%s}\\\\\n",latex(var->visible->s1[i],0),latex(var->visible->s2[i],0),var->visible->s1[i],var->visible->s2[i]);
611          }
612 
613        for(i=0;i<var->used->n;i++)
614          {
615           if(min(i,var->visible->n+var->used->n-i)%8 == 4)
616              fprintf(of,"\\cxreftabbreak{cxreftabiii}\n");
617           if(i==0) fprintf(of,"Used in:");
618           if(var->used->s1[i][0]=='$' && !var->used->s1[i][1])
619              fprintf(of,"\\ & %s & \\ & \\cxreffile{%s}\\\\\n",latex(var->used->s2[i],0),var->used->s2[i]);
620           else
621              if(var->scope&LOCAL)
622                 fprintf(of,"\\ & %s() & \\ & \\cxreffunc{%s}{%s}\\\\\n",latex(var->used->s1[i],0),var->used->s1[i],var->used->s2[i]);
623              else
624                 fprintf(of,"\\ & %s() & %s & \\cxreffunc{%s}{%s}\\\\\n",latex(var->used->s1[i],0),latex(var->used->s2[i],0),var->used->s1[i],var->used->s2[i]);
625          }
626 
627        fprintf(of,"\\end{cxreftabiii}\n\n");
628       }
629    }
630  else
631     if(var->scope&(EXTERNAL|EXTERN_F) && var->defined)
632       {
633        fprintf(of,"\\smallskip\n");
634        fprintf(of,"\\begin{cxreftabiii}\n");
635        fprintf(of,"Defined in:& %s & \\ & \\cxrefvar{%s}{%s}\\\\\n",latex(var->defined,0),var->name,var->defined);
636        fprintf(of,"\\end{cxreftabiii}\n\n");
637       }
638 }
639 
640 
641 /*++++++++++++++++++++++++++++++++++++++
642   Write a Function structure out.
643 
644   Function func The Function structure to output.
645   ++++++++++++++++++++++++++++++++++++++*/
646 
WriteLatexFunction(Function func)647 static void WriteLatexFunction(Function func)
648 {
649  int i,pret,pargs;
650  char* comment2=NULL,*type;
651 
652  if(func->scope&(GLOBAL|EXTERNAL))
653     fprintf(of,"\n\\subsubsection{Global Function %s()}\n",latex(func->name,0));
654  else
655     fprintf(of,"\n\\subsubsection{Local Function %s()}\n",latex(func->name,0));
656  fprintf(of,"\\label{func_%s_%s}\n\n",func->name,filename);
657 
658  if(func->comment)
659    {
660     if(option_verbatim_comments)
661        fprintf(of,"\\begin{verbatim}\n%s\n\\end{verbatim}\n\n",latex(func->comment,1));
662     else
663       {
664        comment2=strstr(func->comment,"\n\n");
665        if(comment2)
666           comment2[0]=0;
667        fprintf(of,"%s\n\n",latex(func->comment,0));
668        fprintf(of,"\\smallskip\n");
669       }
670    }
671 
672  fprintf(of,"{\\stt ");
673 
674  if(func->scope&LOCAL)
675     fprintf(of,"static ");
676  if(func->scope&INLINED)
677    fprintf(of,"inline ");
678 
679  if((type=strstr(func->type,"()")))
680     type[0]=0;
681  fprintf(of,"%s ( ",latex(func->type,0));
682 
683  for(i=0;i<func->args->n;i++)
684     fprintf(of,i?", %s":"%s",latex(func->args->s1[i],0));
685 
686  if(type)
687    {fprintf(of," %s}\n\n",&type[1]);type[0]='(';}
688  else
689     fprintf(of," )}\n\n");
690 
691  pret =strncmp("void ",func->type,5) && func->cret;
692  for(pargs=0,i=0;i<func->args->n;i++)
693     pargs = pargs || ( strcmp("void",func->args->s1[i]) && func->args->s2[i] );
694 
695  if(pret || pargs)
696    {
697     fprintf(of,"\\smallskip\n");
698     fprintf(of,"\\begin{cxrefarglist}\n");
699     if(pret)
700        fprintf(of,"\\cxrefargitem{%s} %s\n",latex(func->type,0),func->cret?latex(func->cret,0):"\\ ");
701     if(pargs)
702        for(i=0;i<func->args->n;i++)
703           fprintf(of,"\\cxrefargitem{%s} %s\n",latex(func->args->s1[i],0),func->args->s2[i]?latex(func->args->s2[i],0):"\\ ");
704     fprintf(of,"\\end{cxrefarglist}\n\n");
705    }
706 
707  if(comment2)
708    {
709     fprintf(of,"\\smallskip\n");
710     fprintf(of,"%s\n\n",latex(&comment2[2],0));
711     comment2[0]='\n';
712    }
713 
714  if(func->protofile || func->incfrom || func->calls->n || func->called->n || func->used->n || func->f_refs->n || func->v_refs->n)
715    {
716     int tabcount=func->protofile?1:0;
717     fprintf(of,"\\smallskip\n");
718     fprintf(of,"\\begin{cxreftabiii}\n");
719 
720     if(func->protofile)
721        fprintf(of,"Prototype:& %s & \\ & \\cxreffile{%s}\\\\\n",latex(func->protofile,0),func->protofile);
722 
723     if(func->incfrom)
724        fprintf(of,"Inc. from:& %s & \\ & \\cxreffunc{%s}{%s}\\\\\n",latex(func->incfrom,0),func->name,func->incfrom);
725 
726     if(func->calls->n)
727       {
728        int others=0;
729 
730        fprintf(of,"Calls:");
731 
732        for(i=0;i<func->calls->n;i++)
733           if(func->calls->s2[i])
734             {
735              fprintf(of,"\\ & %s() & %s & \\cxreffunc{%s}{%s}\\\\\n",latex(func->calls->s1[i],0),latex(func->calls->s2[i],0),func->calls->s1[i],func->calls->s2[i]);
736              if(++tabcount%8 == 4)
737                 fprintf(of,"\\cxreftabbreak{cxreftabiii}\n");
738             }
739           else
740              others++;
741 
742        if(others)
743          {
744           fprintf(of,"\\ & \\cxreftabiiispan{");
745           for(i=0;i<func->calls->n;i++)
746              if(!func->calls->s2[i])
747                 fprintf(of,--others?" %s(),":" %s()",latex(func->calls->s1[i],0));
748           fprintf(of,"} &\\\\\n");
749          }
750       }
751 
752     if(func->called->n)
753       {
754        fprintf(of,"Called by:");
755 
756        for(i=0;i<func->called->n;i++)
757          {
758           fprintf(of,"\\ & %s() & %s & \\cxreffunc{%s}{%s}\\\\\n",latex(func->called->s1[i],0),latex(func->called->s2[i],0),func->called->s1[i],func->called->s2[i]);
759           if(++tabcount%8 == 4)
760              fprintf(of,"\\cxreftabbreak{cxreftabiii}\n");
761          }
762       }
763 
764     if(func->used->n)
765       {
766        fprintf(of,"Used in:");
767 
768        for(i=0;i<func->used->n;i++)
769          {
770           if(func->used->s1[i][0]=='$' && !func->used->s1[i][1])
771              fprintf(of,"\\ & %s & \\ & \\cxreffile{%s}\\\\\n",latex(func->used->s2[i],0),func->used->s2[i]);
772           else
773              fprintf(of,"\\ & %s() & %s & \\cxreffunc{%s}{%s}\\\\\n",latex(func->used->s1[i],0),latex(func->used->s2[i],0),func->used->s1[i],func->used->s2[i]);
774           if(++tabcount%8 == 4)
775              fprintf(of,"\\cxreftabbreak{cxreftabiii}\n");
776          }
777       }
778 
779     if(func->f_refs->n)
780       {
781        int others=0;
782 
783        fprintf(of,"Refs Func:");
784 
785        for(i=0;i<func->f_refs->n;i++)
786           if(func->f_refs->s2[i])
787             {
788              fprintf(of,"\\ & %s() & %s & \\cxreffunc{%s}{%s}\\\\\n",latex(func->f_refs->s1[i],0),latex(func->f_refs->s2[i],0),func->f_refs->s1[i],func->f_refs->s2[i]);
789              if(++tabcount%8 == 4)
790                 fprintf(of,"\\cxreftabbreak{cxreftabiii}\n");
791             }
792           else
793              others++;
794 
795        if(others)
796          {
797           fprintf(of,"\\ & \\cxreftabiiispan{");
798           for(i=0;i<func->f_refs->n;i++)
799              if(!func->f_refs->s2[i])
800                 fprintf(of,--others?" %s(),":" %s()",latex(func->f_refs->s1[i],0));
801           fprintf(of,"} &\\\\\n");
802          }
803       }
804 
805     if(func->v_refs->n)
806       {
807        int others=0;
808 
809        fprintf(of,"Refs Var:");
810 
811        for(i=0;i<func->v_refs->n;i++)
812           if(func->v_refs->s2[i])
813             {
814              fprintf(of,"\\ & %s & %s & \\cxrefvar{%s}{%s}\\\\\n",latex(func->v_refs->s1[i],0),latex(func->v_refs->s2[i],0),func->v_refs->s1[i],func->v_refs->s2[i]);
815              if(++tabcount%8 == 4)
816                 fprintf(of,"\\cxreftabbreak{cxreftabiii}\n");
817             }
818           else
819              others++;
820 
821        if(others)
822          {
823           fprintf(of,"\\ & \\cxreftabiiispan{");
824           for(i=0;i<func->v_refs->n;i++)
825              if(!func->v_refs->s2[i])
826                 fprintf(of,--others?" %s,":" %s",latex(func->v_refs->s1[i],0));
827           fprintf(of,"} &\\\\\n");
828          }
829       }
830 
831     fprintf(of,"\\end{cxreftabiii}\n\n");
832    }
833 }
834 
835 
836 /*++++++++++++++++++++++++++++++++++++++
837   Write out a file that will include the current information.
838 
839   char* name The name of the file (without the LaTeX extension).
840 
841   int appendix set to non-zero if the appendix file is to be added, else a normal source file.
842   ++++++++++++++++++++++++++++++++++++++*/
843 
WriteLatexDocument(char * name,int appendix)844 static void WriteLatexDocument(char* name,int appendix)
845 {
846  FILE *in,*out;
847  char line[256];
848  int seen=0;
849  char *inc_file,*ofile,*ifile;
850 
851  inc_file=ConcatStrings(4,"\\input{",name,LATEX_FILE,"}\n");
852  ifile=ConcatStrings(4,option_odir,"/",option_name,LATEX_FILE);
853  ofile=ConcatStrings(4,option_odir,"/",option_name,LATEX_FILE_BACKUP);
854 
855  in =fopen(ifile,"r");
856  if(!in)
857    {
858     WriteLatexTemplate(ifile);
859     in =fopen(ifile,"r");
860    }
861 
862  out=fopen(ofile,"w");
863 
864  if(!out)
865    {fprintf(stderr,"cxref: Failed to open the main LaTeX output file '%s'\n",ofile);exit(1);}
866 
867  while(fgets(line,256,in))
868    {
869     if(!strcmp(inc_file,line) ||
870        (line[0]=='%' && !strcmp(inc_file,line+1)) ||
871        (line[0]=='%' && line[1]==' ' && !strcmp(inc_file,line+2)))
872        {seen=1;break;}
873     if(line[0]=='%' && !strcmp("% End-Of-Source-Files\n",line))
874       {
875        if(appendix)
876          {
877           fputs(line,out);
878           fputs("\n",out);
879           fputs("% Appendix\n",out);
880           fputs("\n",out);
881           fputs("\\appendix\n",out);
882           fputs("\\markboth{Appendix}{Appendix}\n",out);
883           fputs(inc_file,out);
884          }
885        else
886          {
887           fputs(inc_file,out);
888           fputs("\n",out);
889           fputs(line,out);
890          }
891       }
892     else
893        fputs(line,out);
894    }
895 
896  fclose(in);
897  fclose(out);
898 
899  if(!seen)
900    {
901     unlink(ifile);
902     rename(ofile,ifile);
903    }
904  else
905     unlink(ofile);
906 }
907 
908 
909 /*++++++++++++++++++++++++++++++++++++++
910   Write out the standard template for the main LaTeX file.
911   This sets up the page styles, and includes markers for the start and end of included source code.
912 
913   char* name The name of the file to write the template to.
914   ++++++++++++++++++++++++++++++++++++++*/
915 
WriteLatexTemplate(char * name)916 static void WriteLatexTemplate(char* name)
917 {
918  FILE *template;
919  struct stat stat_buf;
920  char* fname;
921 
922  template=fopen(name,"w");
923 
924  if(!template)
925    {fprintf(stderr,"cxref: Failed to open the main LaTeX output file '%s'\n",name);exit(1);}
926 
927  fputs("% This LaTeX file generated by cxref (version " CXREF_VERSION ").\n",template);
928  fputs("% cxref program " CXREF_COPYRIGHT "\n",template);
929  fputs("\n",template);
930  fputs("\\documentclass{report}\n",template);
931  fputs("\\usepackage{fonts,page,cxref}\n",template);
932  fputs("\\pagestyle{myheadings}\n",template);
933  fputs("\n",template);
934  fputs("\\begin{document}\n",template);
935  fputs("\n",template);
936  fputs("% Contents (Optional, either here or at end)\n",template);
937  fputs("\n",template);
938  fputs("%\\markboth{Contents}{Contents}\n",template);
939  fputs("%\\tableofcontents\n",template);
940  fputs("\n",template);
941  fputs("\\chapter{Source Files}\n",template);
942  fputs("\n",template);
943  fputs("% Begin-Of-Source-Files\n",template);
944  fputs("\n",template);
945  fputs("% End-Of-Source-Files\n",template);
946  fputs("\n",template);
947  fputs("% Contents (Optional, either here or at beginning)\n",template);
948  fputs("\n",template);
949  fputs("\\markboth{Contents}{Contents}\n",template);
950  fputs("\\tableofcontents\n",template);
951  fputs("\n",template);
952  fputs("\\end{document}\n",template);
953 
954  fclose(template);
955 
956  fname=ConcatStrings(2,option_odir,"/fonts.sty");
957  if(stat(fname,&stat_buf))
958    {
959     FILE* file=fopen(fname,"w");
960     if(!file)
961       {fprintf(stderr,"cxref: Cannot write the LaTeX style file '%s'\n",fname);exit(1);}
962     fputs(latex_fonts_style,file);
963     fclose(file);
964    }
965 
966  fname=ConcatStrings(2,option_odir,"/page.sty");
967  if(stat(fname,&stat_buf))
968    {
969     FILE* file=fopen(fname,"w");
970     if(!file)
971       {fprintf(stderr,"cxref: Cannot write the LaTeX style file '%s'\n",fname);exit(1);}
972     fputs(latex_page_style,file);
973     fclose(file);
974    }
975 
976  fname=ConcatStrings(2,option_odir,"/cxref.sty");
977  if(stat(fname,&stat_buf))
978    {
979     FILE* file=fopen(fname,"w");
980     if(!file)
981       {fprintf(stderr,"cxref: Cannot write the LaTeX style file '%s'\n",fname);exit(1);}
982     fputs(latex_cxref_style,file);
983     fclose(file);
984    }
985 }
986 
987 
988 /*++++++++++++++++++++++++++++++++++++++
989   Write out the appendix information.
990 
991   StringList files The list of files to write.
992 
993   StringList2 funcs The list of functions to write.
994 
995   StringList2 vars The list of variables to write.
996 
997   StringList2 types The list of types to write.
998   ++++++++++++++++++++++++++++++++++++++*/
999 
WriteLatexAppendix(StringList files,StringList2 funcs,StringList2 vars,StringList2 types)1000 void WriteLatexAppendix(StringList files,StringList2 funcs,StringList2 vars,StringList2 types)
1001 {
1002  char* ofile;
1003  int i;
1004 
1005  filename=NULL;
1006 
1007  /* Write the bits to the including file. */
1008 
1009  WriteLatexDocument(ConcatStrings(2,option_name,LATEX_APDX),1);
1010 
1011  /* Open the file */
1012 
1013  ofile=ConcatStrings(5,option_odir,"/",option_name,LATEX_APDX,LATEX_FILE);
1014 
1015  of=fopen(ofile,"w");
1016 
1017  if(!of)
1018    {fprintf(stderr,"cxref: Failed to open the LaTeX appendix file '%s'\n",ofile);exit(1);}
1019 
1020  /* Write out a header. */
1021 
1022  fputs("% This LaTeX file generated by cxref (version " CXREF_VERSION ").\n",of);
1023  fputs("% cxref program " CXREF_COPYRIGHT "\n",of);
1024  fputs("\n",of);
1025  fprintf(of,"%% Cxref: %s\n",run_command);
1026  fputs("\n",of);
1027 
1028  /* Write the file structure out */
1029 
1030  fprintf(of,"\\chapter{Cross References}\n");
1031 
1032  /* Write out the appendix of files. */
1033 
1034  if(files->n)
1035    {
1036     fprintf(of,"\n\\section{Files}\n");
1037     fprintf(of,"\\label{appendix_file}\n\n");
1038     fprintf(of,"\\begin{cxreftabiib}\n");
1039     for(i=0;i<files->n;i++)
1040       {
1041        if(min(i,files->n-i)%8 == 4)
1042           fprintf(of,"\\cxreftabbreak{cxreftabiib}\n");
1043        fprintf(of,"%s & \\ & \\cxreffile{%s}\\\\\n",latex(files->s[i],0),files->s[i]);
1044       }
1045     fprintf(of,"\\end{cxreftabiib}\n\n");
1046    }
1047 
1048  /* Write out the appendix of functions. */
1049 
1050  if(funcs->n)
1051    {
1052     fprintf(of,"\n\\section{Global Functions}\n");
1053     fprintf(of,"\\label{appendix_func}\n\n");
1054     fprintf(of,"\\begin{cxreftabiib}\n");
1055     for(i=0;i<funcs->n;i++)
1056       {
1057        if(min(i,funcs->n-i)%8 == 4)
1058           fprintf(of,"\\cxreftabbreak{cxreftabiib}\n");
1059        fprintf(of,"%s & %s & \\cxreffunc{%s}{%s}\\\\\n",latex(funcs->s1[i],0),latex(funcs->s2[i],0),funcs->s1[i],funcs->s2[i]);
1060       }
1061     fprintf(of,"\\end{cxreftabiib}\n\n");
1062    }
1063 
1064  /* Write out the appendix of variables. */
1065 
1066  if(vars->n)
1067    {
1068     fprintf(of,"\n\\section{Global Variables}\n");
1069     fprintf(of,"\\label{appendix_var}\n\n");
1070     fprintf(of,"\\begin{cxreftabiib}\n");
1071     for(i=0;i<vars->n;i++)
1072       {
1073        if(min(i,vars->n-i)%8 == 4)
1074           fprintf(of,"\\cxreftabbreak{cxreftabiib}\n");
1075        fprintf(of,"%s & %s & \\cxrefvar{%s}{%s}\\\\\n",latex(vars->s1[i],0),latex(vars->s2[i],0),vars->s1[i],vars->s2[i]);
1076       }
1077     fprintf(of,"\\end{cxreftabiib}\n\n");
1078    }
1079 
1080  /* Write out the appendix of types. */
1081 
1082  if(types->n)
1083    {
1084     fprintf(of,"\n\\section{Defined Types}\n");
1085     fprintf(of,"\\label{appendix_type}\n\n");
1086     fprintf(of,"\\begin{cxreftabiib}\n");
1087     for(i=0;i<types->n;i++)
1088       {
1089        if(min(i,types->n-i)%8 == 4)
1090           fprintf(of,"\\cxreftabbreak{cxreftabiib}\n");
1091        if(!strncmp("enum",types->s1[i],4))
1092           fprintf(of,"%s & %s & \\cxreftype{enum_%s}{%s}\\\\\n",latex(types->s1[i],0),latex(types->s2[i],0),&types->s1[i][5],types->s2[i]);
1093        else
1094           if(!strncmp("union",types->s1[i],5))
1095              fprintf(of,"%s & %s & \\cxreftype{union_%s}{%s}\\\\\n",latex(types->s1[i],0),latex(types->s2[i],0),&types->s1[i][6],types->s2[i]);
1096           else
1097              if(!strncmp("struct",types->s1[i],6))
1098                 fprintf(of,"%s & %s & \\cxreftype{struct_%s}{%s}\\\\\n",latex(types->s1[i],0),latex(types->s2[i],0),&types->s1[i][7],types->s2[i]);
1099              else
1100                 fprintf(of,"%s & %s & \\cxreftype{%s}{%s}\\\\\n",latex(types->s1[i],0),latex(types->s2[i],0),types->s1[i],types->s2[i]);
1101       }
1102     fprintf(of,"\\end{cxreftabiib}\n\n");
1103    }
1104 
1105  fclose(of);
1106 
1107  /* Clear the memory in latex(,0) */
1108 
1109  latex(NULL,0); latex(NULL,0); latex(NULL,0); latex(NULL,0);
1110 }
1111 
1112 
1113 /*++++++++++++++++++++++++++++++++++++++
1114   Delete the latex file and main file reference that belong to the named file.
1115 
1116   char *name The name of the file to delete.
1117   ++++++++++++++++++++++++++++++++++++++*/
1118 
WriteLatexFileDelete(char * name)1119 void WriteLatexFileDelete(char *name)
1120 {
1121  FILE *in,*out;
1122  char line[256];
1123  int seen=0;
1124  char *inc_file,*ofile,*ifile;
1125 
1126  ofile=ConcatStrings(4,option_odir,"/",name,LATEX_FILE);
1127  unlink(ofile);
1128 
1129  inc_file=ConcatStrings(4,"\\input{",name,LATEX_FILE,"}\n");
1130  ifile=ConcatStrings(4,option_odir,"/",option_name,LATEX_FILE);
1131  ofile=ConcatStrings(4,option_odir,"/",option_name,LATEX_FILE_BACKUP);
1132 
1133  in =fopen(ifile,"r");
1134  out=fopen(ofile,"w");
1135 
1136  if(in && !out)
1137    {fprintf(stderr,"cxref: Failed to open the main LaTeX output file '%s'\n",ofile);fclose(in);}
1138  else if(in)
1139    {
1140     while(fgets(line,256,in))
1141       {
1142        if(!strcmp(inc_file,line) ||
1143           (line[0]=='%' && !strcmp(inc_file,line+1)) ||
1144           (line[0]=='%' && line[1]==' ' && !strcmp(inc_file,line+2)))
1145           seen=1;
1146        else
1147           fputs(line,out);
1148       }
1149 
1150     fclose(in);
1151     fclose(out);
1152 
1153     if(seen)
1154       {
1155        unlink(ifile);
1156        rename(ofile,ifile);
1157       }
1158     else
1159        unlink(ofile);
1160    }
1161  else if(out)
1162    {
1163     fclose(out);
1164     unlink(ofile);
1165    }
1166 }
1167 
1168 
1169 /*++++++++++++++++++++++++++++++++++++++
1170   Make the input string safe to output as LaTeX ( not #, $, %, &, \, ^, _, {, }, <, > or ~ ).
1171 
1172   char* latex Returns a safe LaTeX string.
1173 
1174   char* c A non-safe LaTeX string.
1175 
1176   int verbatim Set to true inside a verbatim environment.
1177 
1178   The function can only be called four times in each fprintf() since it returns one of only four static strings.
1179   ++++++++++++++++++++++++++++++++++++++*/
1180 
latex(char * c,int verbatim)1181 static char* latex(char* c,int verbatim)
1182 {
1183  static char safe[4][256],*malloced[4]={NULL,NULL,NULL,NULL};
1184  static int which=0;
1185  int copy=0,skip=0;
1186  int i=0,j=0,delta=13,len=256-delta;
1187  char* ret;
1188 
1189  which=(which+1)%4;
1190  ret=safe[which];
1191 
1192  safe[which][0]=0;
1193 
1194  if(malloced[which])
1195    {Free(malloced[which]);malloced[which]=NULL;}
1196 
1197  if(c)
1198    {
1199     i=CopyOrSkip(c,"latex",&copy,&skip);
1200 
1201     while(1)
1202        {
1203        for(;j<len && c[i];i++)
1204          {
1205           if(copy)
1206             {ret[j++]=c[i]; if(c[i]=='\n') copy=0;}
1207           else if(skip)
1208             {               if(c[i]=='\n') skip=0;}
1209           else if(verbatim)
1210              ret[j++]=c[i];
1211           else
1212              switch(c[i])
1213                {
1214                case '<':
1215                case '>':
1216                 ret[j++]='$';
1217                 ret[j++]=c[i];
1218                 ret[j++]='$';
1219                 break;
1220                case '\\':
1221                 strcpy(&ret[j],"$\\backslash$");j+=12;
1222                 break;
1223                case '~':
1224                 strcpy(&ret[j],"$\\sim$");j+=6;
1225                 break;
1226                case '^':
1227                 strcpy(&ret[j],"$\\wedge$");j+=8;
1228                 break;
1229                case '#':
1230                case '$':
1231                case '%':
1232                case '&':
1233                case '_':
1234                case '{':
1235                case '}':
1236                 ret[j++]='\\';
1237                 ret[j++]=c[i];
1238                 break;
1239                default:
1240                 ret[j++]=c[i];
1241                }
1242           if(c[i]=='\n')
1243              i+=CopyOrSkip(c+i,"latex",&copy,&skip);
1244          }
1245 
1246        if(c[i])                 /* Not finished */
1247          {
1248           if(malloced[which])
1249              malloced[which]=Realloc(malloced[which],len+delta+256);
1250           else
1251             {malloced[which]=Malloc(len+delta+256); strncpy(malloced[which],ret,(unsigned)j);}
1252           ret=malloced[which];
1253           len+=256;
1254          }
1255        else
1256          {ret[j]=0; break;}
1257       }
1258    }
1259 
1260  return(ret);
1261 }
1262