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