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