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