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 | }