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