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