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",©,&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",©,&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 | }