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