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