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
WriteLatexFile(File file)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
WriteLatexFilePart(File file)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
WriteLatexInclude(Include inc)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
WriteLatexSubInclude(Include inc,int depth)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
WriteLatexDefine(Define def)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
WriteLatexTypedef(Typedef type)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
WriteLatexStructUnion(StructUnion su,int depth)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
WriteLatexVariable(Variable var)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
WriteLatexFunction(Function func)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
WriteLatexDocument(char * name,int appendix)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
WriteLatexTemplate(char * name)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
WriteLatexAppendix(StringList files,StringList2 funcs,StringList2 vars,StringList2 types)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
WriteLatexFileDelete(char * name)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
latex(char * c,int verbatim)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 }
1262