1 | /*************************************** 2 | $Header: /home/amb/cxref/src/RCS/sgml.c 1.10 2004/06/26 18:50:36 amb Exp $ 3 | 4 | C Cross Referencing & Documentation tool. Version 1.6. 5 | 6 | Writes the SGML 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 | #include "version.h" 24 | #include "memory.h" 25 | #include "datatype.h" 26 | #include "cxref.h" 27 | 28 | /*+ The name of the output tex file that includes each of the others. +*/ 29 | #define SGML_FILE ".sgml" 30 | #define SGML_FILE_BACKUP ".sgml~" 31 | 32 | /*+ The name of the output tex file that contains the appendix. +*/ 33 | #define SGML_APDX ".apdx" 34 | 35 | /*+ The comments are to be inserted verbatim. +*/ 36 | extern int option_verbatim_comments; 37 | 38 | /*+ The name of the directory for the output. +*/ 39 | extern char* option_odir; 40 | 41 | /*+ The base name of the file for the output. +*/ 42 | extern char* option_name; 43 | 44 | /*+ The information about the cxref run, +*/ 45 | extern char *run_command, /*+ the command line options. +*/ 46 | *run_cpp_command; /*+ the cpp command and options. +*/ 47 | 48 | /*+ The directories to go back to get to the base output directory. +*/ 49 | static char* goback=NULL; 50 | 51 | /* Local functions */ 52 | 53 | static void WriteSGMLFilePart(File file); 54 | static void WriteSGMLInclude(Include inc); 55 | static void WriteSGMLSubInclude(Include inc,int depth); 56 | static void WriteSGMLDefine(Define def); 57 | static void WriteSGMLTypedef(Typedef type); 58 | static void WriteSGMLStructUnion(StructUnion su,int depth); 59 | static void WriteSGMLVariable(Variable var); 60 | static void WriteSGMLFunction(Function func); 61 | 62 | static void WriteSGMLPreamble(FILE* f,char* title); 63 | static void WriteSGMLPostamble(FILE* f); 64 | 65 | static char* sgml(char* c,int verbatim); 66 | 67 | /*+ The output file for the SGML. +*/ 68 | static FILE* of; 69 | 70 | /*+ The name of the file. +*/ 71 | static char *filename; 72 | 73 | 74 | /*++++++++++++++++++++++++++++++++++++++ 75 | Write an sgml file for a complete File structure and all components. 76 | 77 | File file The File structure to output. 78 | ++++++++++++++++++++++++++++++++++++++*/ 79 | 80 | void WriteSGMLFile(File file) 81 | { 82 | char* ofile; 83 | int i; 84 | 85 | filename=file->name; 86 | 87 | /* Open the file */ 88 | 89 | ofile=ConcatStrings(4,option_odir,"/",file->name,SGML_FILE); 90 | 91 | of=fopen(ofile,"w"); 92 | if(!of) 93 | { 94 | struct stat stat_buf; 95 | int i,ofl=strlen(ofile); 96 | 97 | for(i=strlen(option_odir)+1;i<ofl;i++) 98 | if(ofile[i]=='/') 99 | { 100 | ofile[i]=0; 101 | if(stat(ofile,&stat_buf)) 102 | mkdir(ofile,S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); 103 | ofile[i]='/'; 104 | } 105 | 106 | of=fopen(ofile,"w"); 107 | } 108 | 109 | if(!of) 110 | {fprintf(stderr,"cxref: Failed to open the SGML output file '%s'\n",ofile);exit(1);} 111 | 112 | for(goback="",i=strlen(file->name);i>0;i--) 113 | if(file->name[i]=='/') 114 | goback=ConcatStrings(2,goback,"../"); 115 | 116 | /* Write out a header. */ 117 | 118 | WriteSGMLPreamble(of,ConcatStrings(5,"Cross reference for ",file->name," of ",option_name,".")); 119 | 120 | /*+ The file structure is broken into its components and they are each written out. +*/ 121 | 122 | WriteSGMLFilePart(file); 123 | 124 | if(file->includes) 125 | { 126 | Include inc =file->includes; 127 | fprintf(of,"\n<sect1>Included Files\n\n<p>\n"); 128 | do{ 129 | WriteSGMLInclude(inc); 130 | } 131 | while((inc=inc->next)); 132 | } 133 | 134 | if(file->defines) 135 | { 136 | Define def =file->defines; 137 | fprintf(of,"\n<sect1>Preprocessor definitions\n\n<p>\n"); 138 | do{ 139 | if(def!=file->defines) 140 | fprintf(of,"<p>\n"); 141 | WriteSGMLDefine(def); 142 | } 143 | while((def=def->next)); 144 | } 145 | 146 | if(file->typedefs) 147 | { 148 | Typedef type=file->typedefs; 149 | do{ 150 | WriteSGMLTypedef(type); 151 | } 152 | while((type=type->next)); 153 | } 154 | 155 | if(file->variables) 156 | { 157 | int any_to_mention=0; 158 | Variable var=file->variables; 159 | 160 | do{ 161 | if(var->scope&(GLOBAL|LOCAL|EXTERNAL|EXTERN_F)) 162 | any_to_mention=1; 163 | } 164 | while((var=var->next)); 165 | 166 | if(any_to_mention) 167 | { 168 | int first_ext=1,first_local=1; 169 | Variable var=file->variables; 170 | do{ 171 | if(var->scope&GLOBAL) 172 | WriteSGMLVariable(var); 173 | } 174 | while((var=var->next)); 175 | var=file->variables; 176 | do{ 177 | if(var->scope&(EXTERNAL|EXTERN_F) && !(var->scope&GLOBAL)) 178 | { 179 | if(first_ext) 180 | {fprintf(of,"\n<sect1>External Variables\n\n"); first_ext=0;} 181 | fprintf(of,"<p>\n"); 182 | WriteSGMLVariable(var); 183 | } 184 | } 185 | while((var=var->next)); 186 | var=file->variables; 187 | do{ 188 | if(var->scope&LOCAL) 189 | { 190 | if(first_local) 191 | {fprintf(of,"\n<sect1>Local Variables\n\n"); first_local=0;} 192 | fprintf(of,"<p>\n"); 193 | WriteSGMLVariable(var); 194 | } 195 | } 196 | while((var=var->next)); 197 | } 198 | } 199 | 200 | if(file->functions) 201 | { 202 | Function func=file->functions; 203 | do{ 204 | if(func->scope&(GLOBAL|EXTERNAL)) 205 | WriteSGMLFunction(func); 206 | } 207 | while((func=func->next)); 208 | func=file->functions; 209 | do{ 210 | if(func->scope&LOCAL) 211 | WriteSGMLFunction(func); 212 | } 213 | while((func=func->next)); 214 | } 215 | 216 | WriteSGMLPostamble(of); 217 | 218 | fclose(of); 219 | 220 | /* Clear the memory in sgml() */ 221 | 222 | sgml(NULL,0); sgml(NULL,0); sgml(NULL,0); sgml(NULL,0); 223 | } 224 | 225 | 226 | /*++++++++++++++++++++++++++++++++++++++ 227 | Write a File structure out. 228 | 229 | File file The File to output. 230 | ++++++++++++++++++++++++++++++++++++++*/ 231 | 232 | static void WriteSGMLFilePart(File file) 233 | { 234 | int i; 235 | 236 | fprintf(of,"<sect>File %s\n",sgml(file->name,0)); 237 | 238 | if(file->comment) 239 | { 240 | if(option_verbatim_comments) 241 | fprintf(of,"<p><tscreen><verb>\n%s\n</verb></tscreen>\n\n",sgml(file->comment,1)); 242 | else 243 | { 244 | char *rcs1=strstr(file->comment,"$Header"),*rcs2=NULL; 245 | if(rcs1) 246 | { 247 | rcs2=strstr(&rcs1[1],"$"); 248 | if(rcs2) 249 | { 250 | rcs2[0]=0; 251 | fprintf(of,"<bf>RCS %s</bf>\n<p>\n",sgml(&rcs1[1],0)); 252 | rcs2[0]='$'; 253 | } 254 | } 255 | if(rcs2) 256 | fprintf(of,"%s\n<p>\n",sgml(&rcs2[2],0)); 257 | else 258 | fprintf(of,"%s\n<p>\n",sgml(file->comment,0)); 259 | } 260 | } 261 | 262 | if(file->inc_in->n) 263 | { 264 | int i; 265 | 266 | fprintf(of,"<p>\n<descrip>\n<tag>Included in:</tag>\n<itemize>\n"); 267 | for(i=0;i<file->inc_in->n;i++) 268 | fprintf(of,"<item>%s\n",sgml(file->inc_in->s[i],0)); 269 | fprintf(of,"</itemize>\n</descrip>\n"); 270 | } 271 | 272 | if(file->f_refs->n || file->v_refs->n) 273 | fprintf(of,"<descrip>\n"); 274 | 275 | if(file->f_refs->n) 276 | { 277 | int others=0; 278 | fprintf(of,"<tag>References Functions:</tag>\n<itemize>\n"); 279 | for(i=0;i<file->f_refs->n;i++) 280 | if(file->f_refs->s2[i]) 281 | fprintf(of,"<item>%s() : %s\n",sgml(file->f_refs->s1[i],0),sgml(file->f_refs->s2[i],0)); 282 | else 283 | others++; 284 | 285 | if(others) 286 | { 287 | fprintf(of,"<item>"); 288 | for(i=0;i<file->f_refs->n;i++) 289 | if(!file->f_refs->s2[i]) 290 | fprintf(of,--others?" %s(),":" %s()",sgml(file->f_refs->s1[i],0)); 291 | fprintf(of,"\n"); 292 | } 293 | fprintf(of,"</itemize>\n"); 294 | } 295 | 296 | if(file->v_refs->n) 297 | { 298 | int others=0; 299 | fprintf(of,"<tag>References Variables:</tag>\n<itemize>\n"); 300 | for(i=0;i<file->v_refs->n;i++) 301 | { 302 | if(file->v_refs->s2[i]) 303 | fprintf(of,"<item>%s : %s\n",sgml(file->v_refs->s1[i],0),sgml(file->v_refs->s2[i],0)); 304 | else 305 | others++; 306 | } 307 | 308 | if(others) 309 | { 310 | fprintf(of,"<item>"); 311 | for(i=0;i<file->v_refs->n;i++) 312 | if(!file->v_refs->s2[i]) 313 | fprintf(of,--others?" %s,":" %s",sgml(file->v_refs->s1[i],0)); 314 | fprintf(of,"\n"); 315 | } 316 | fprintf(of,"</itemize>\n"); 317 | } 318 | 319 | if(file->f_refs->n || file->v_refs->n) 320 | fprintf(of,"</descrip>\n"); 321 | } 322 | 323 | 324 | /*++++++++++++++++++++++++++++++++++++++ 325 | Write an Include structure out. 326 | 327 | Include inc The Include structure to output. 328 | ++++++++++++++++++++++++++++++++++++++*/ 329 | 330 | static void WriteSGMLInclude(Include inc) 331 | { 332 | if(inc->comment) 333 | fprintf(of,"%s\n<p>\n",sgml(inc->comment,0)); 334 | 335 | fprintf(of,"<itemize>\n"); 336 | 337 | if(inc->scope==LOCAL) 338 | fprintf(of,"<item><tt>#include "%s"</tt>\n",sgml(inc->name,0)); 339 | else 340 | fprintf(of,"<item><tt>#include <%s></tt>\n",sgml(inc->name,0)); 341 | 342 | if(inc->includes) 343 | WriteSGMLSubInclude(inc->includes,1); 344 | 345 | fprintf(of,"</itemize>\n"); 346 | } 347 | 348 | 349 | /*++++++++++++++++++++++++++++++++++++++ 350 | Write an Sub Include structure out. (An include structure that is included from another file.) 351 | 352 | Include inc The Include structure to output. 353 | 354 | int depth The depth of the include hierarchy. 355 | ++++++++++++++++++++++++++++++++++++++*/ 356 | 357 | static void WriteSGMLSubInclude(Include inc,int depth) 358 | { 359 | fprintf(of,"<itemize>\n"); 360 | 361 | while(inc) 362 | { 363 | if(inc->scope==LOCAL) 364 | fprintf(of,"<item><tt>#include "%s"</tt>\n",sgml(inc->name,0)); 365 | else 366 | fprintf(of,"<item><tt>#include <%s></tt>\n",sgml(inc->name,0)); 367 | 368 | if(inc->includes) 369 | WriteSGMLSubInclude(inc->includes,depth+1); 370 | 371 | inc=inc->next; 372 | } 373 | 374 | fprintf(of,"</itemize>\n"); 375 | } 376 | 377 | 378 | /*++++++++++++++++++++++++++++++++++++++ 379 | Write a Define structure out. 380 | 381 | Define def The Define structure to output. 382 | ++++++++++++++++++++++++++++++++++++++*/ 383 | 384 | static void WriteSGMLDefine(Define def) 385 | { 386 | int i; 387 | int pargs=0; 388 | 389 | if(def->comment) 390 | fprintf(of,"%s\n<p>\n",sgml(def->comment,0)); 391 | 392 | fprintf(of,"<tt>#define %s",sgml(def->name,0)); 393 | 394 | if(def->value) 395 | fprintf(of," %s",sgml(def->value,0)); 396 | 397 | if(def->args->n) 398 | { 399 | fprintf(of,"( "); 400 | for(i=0;i<def->args->n;i++) 401 | fprintf(of,i?", %s":"%s",sgml(def->args->s1[i],0)); 402 | fprintf(of," )"); 403 | } 404 | fprintf(of,"</tt><newline>\n"); 405 | 406 | for(i=0;i<def->args->n;i++) 407 | if(def->args->s2[i]) 408 | pargs=1; 409 | 410 | if(pargs) 411 | { 412 | fprintf(of,"<descrip>\n"); 413 | for(i=0;i<def->args->n;i++) 414 | fprintf(of,"<tag><tt>%s</tt></tag>\n%s\n",sgml(def->args->s1[i],0),def->args->s2[i]?sgml(def->args->s2[i],0):""); 415 | fprintf(of,"</descrip>\n"); 416 | } 417 | } 418 | 419 | 420 | /*++++++++++++++++++++++++++++++++++++++ 421 | Write a Typedef structure out. 422 | 423 | Typedef type The Typedef structure to output. 424 | ++++++++++++++++++++++++++++++++++++++*/ 425 | 426 | static void WriteSGMLTypedef(Typedef type) 427 | { 428 | fprintf(of,"\n<sect1>"); 429 | 430 | if(type->type) 431 | fprintf(of,"Typedef %s",sgml(type->name,0)); 432 | else 433 | fprintf(of,"Type %s",sgml(type->name,0)); 434 | 435 | fprintf(of,"\n\n<p>\n"); 436 | 437 | if(type->comment) 438 | fprintf(of,"%s\n<p>\n",sgml(type->comment,0)); 439 | 440 | if(type->type) 441 | fprintf(of,"<tt>typedef %s</tt><newline>\n",sgml(type->type,0)); 442 | 443 | if(type->sutype) 444 | { 445 | fprintf(of,"<itemize>\n"); 446 | WriteSGMLStructUnion(type->sutype,0); 447 | fprintf(of,"</itemize>\n"); 448 | } 449 | else 450 | if(type->typexref) 451 | { 452 | fprintf(of,"<descrip>\n<tag>See:</tag>\n<itemize>\n"); 453 | if(type->typexref->type) 454 | fprintf(of,"<item>Typedef %s\n",sgml(type->typexref->name,0)); 455 | else if(!strncmp("enum",type->typexref->name,4)) 456 | fprintf(of,"<item>Type %s\n",sgml(type->typexref->name,0)); 457 | else if(!strncmp("union",type->typexref->name,5)) 458 | fprintf(of,"<item>Type %s\n",sgml(type->typexref->name,0)); 459 | else if(!strncmp("struct",type->typexref->name,6)) 460 | fprintf(of,"<item>Type %s\n",sgml(type->typexref->name,0)); 461 | fprintf(of,"</itemize>\n</descrip>\n"); 462 | } 463 | } 464 | 465 | 466 | /*++++++++++++++++++++++++++++++++++++++ 467 | Write a structure / union structure out. 468 | 469 | StructUnion su The structure / union to write. 470 | 471 | int depth The current depth within the structure. 472 | ++++++++++++++++++++++++++++++++++++++*/ 473 | 474 | static void WriteSGMLStructUnion(StructUnion su, int depth) 475 | { 476 | int i; 477 | char* splitsu=NULL; 478 | 479 | splitsu=strstr(su->name,"{...}"); 480 | if(splitsu) splitsu[-1]=0; 481 | 482 | if(depth && su->comment && !su->comps) 483 | fprintf(of,"<item><tt>%s; </tt>%s<newline>\n",sgml(su->name,0),sgml(su->comment,0)); 484 | else if(!depth || su->comps) 485 | fprintf(of,"<item><tt>%s</tt><newline>\n",sgml(su->name,0)); 486 | else 487 | fprintf(of,"<item><tt>%s;</tt><newline>\n",sgml(su->name,0)); 488 | 489 | if(!depth || su->comps) 490 | { 491 | fprintf(of,"<itemize>\n"); 492 | 493 | fprintf(of,"<item><tt>{</tt><newline>\n"); 494 | 495 | for(i=0;i<su->n_comp;i++) 496 | WriteSGMLStructUnion(su->comps[i],depth+1); 497 | 498 | fprintf(of,"<item><tt>}</tt><newline>\n"); 499 | 500 | fprintf(of,"</itemize>\n"); 501 | 502 | if(splitsu) 503 | { 504 | if(depth && su->comment) 505 | fprintf(of,"<item><tt>%s; </tt>%s<newline>\n",splitsu[5]?sgml(&splitsu[6],0):"",sgml(su->comment,0)); 506 | else 507 | fprintf(of,"<item><tt>%s;</tt><newline>\n",splitsu[5]?sgml(&splitsu[6],0):""); 508 | } 509 | } 510 | 511 | if(splitsu) splitsu[-1]=' '; 512 | } 513 | 514 | 515 | /*++++++++++++++++++++++++++++++++++++++ 516 | Write a Variable structure out. 517 | 518 | Variable var The Variable structure to output. 519 | ++++++++++++++++++++++++++++++++++++++*/ 520 | 521 | static void WriteSGMLVariable(Variable var) 522 | { 523 | int i; 524 | 525 | if(var->scope&GLOBAL) 526 | fprintf(of,"\n<sect1>Global Variable %s\n\n<p>\n",sgml(var->name,0)); 527 | else 528 | fprintf(of,"<bf>%s</bf><newline>\n",sgml(var->name,0)); 529 | 530 | if(var->comment) 531 | fprintf(of,"%s\n<p>\n",sgml(var->comment,0)); 532 | 533 | fprintf(of,"<tt>"); 534 | 535 | if(var->scope&LOCAL) 536 | fprintf(of,"static "); 537 | else 538 | if(!(var->scope&GLOBAL) && var->scope&(EXTERNAL|EXTERN_F)) 539 | fprintf(of,"extern "); 540 | 541 | fprintf(of,"%s</tt><newline>\n",sgml(var->type,0)); 542 | 543 | if(var->scope&(GLOBAL|LOCAL)) 544 | { 545 | if(var->incfrom || var->visible->n || var->used->n) 546 | fprintf(of,"<descrip>\n"); 547 | 548 | if(var->incfrom) 549 | { 550 | fprintf(of,"<tag>Included from:</tag>\n<itemize>\n"); 551 | fprintf(of,"<item>%s\n",sgml(var->incfrom,0)); 552 | fprintf(of,"</itemize>\n"); 553 | } 554 | 555 | if(var->visible->n) 556 | { 557 | fprintf(of,"<tag>Visible in:</tag>\n<itemize>\n"); 558 | for(i=0;i<var->visible->n;i++) 559 | if(var->visible->s1[i][0]=='$' && !var->visible->s1[i][1]) 560 | fprintf(of,"<item>%s\n",sgml(var->visible->s2[i],0)); 561 | else 562 | fprintf(of,"<item>%s() : %s\n",sgml(var->visible->s1[i],0),sgml(var->visible->s2[i],0)); 563 | fprintf(of,"</itemize>\n"); 564 | } 565 | 566 | if(var->used->n) 567 | { 568 | fprintf(of,"<tag>Used in:</tag>\n<itemize>\n"); 569 | for(i=0;i<var->used->n;i++) 570 | { 571 | if(var->used->s1[i][0]=='$' && !var->used->s1[i][1]) 572 | fprintf(of,"<item>%s\n",sgml(var->used->s2[i],0)); 573 | else 574 | { 575 | if(var->scope&LOCAL) 576 | fprintf(of,"<item>%s()\n",sgml(var->used->s1[i],0)); 577 | else 578 | fprintf(of,"<item>%s() : %s\n",sgml(var->used->s1[i],0),sgml(var->used->s2[i],0)); 579 | } 580 | } 581 | fprintf(of,"</itemize>\n"); 582 | } 583 | 584 | if(var->incfrom || var->visible->n || var->used->n) 585 | fprintf(of,"</descrip>\n"); 586 | } 587 | else 588 | if(var->scope&(EXTERNAL|EXTERN_F) && var->defined) 589 | { 590 | fprintf(of,"<descrip>\n<tag>Defined in:</tag>\n<itemize>\n"); 591 | fprintf(of,"<item>%s",sgml(var->name,0)); 592 | fprintf(of,"</itemize>\n</descrip>\n"); 593 | } 594 | } 595 | 596 | 597 | /*++++++++++++++++++++++++++++++++++++++ 598 | Write a Function structure out. 599 | 600 | Function func The Function structure to output. 601 | ++++++++++++++++++++++++++++++++++++++*/ 602 | 603 | static void WriteSGMLFunction(Function func) 604 | { 605 | int i,pret,pargs; 606 | char* comment2=NULL,*type; 607 | 608 | if(func->scope&(GLOBAL|EXTERNAL)) 609 | fprintf(of,"\n<sect1>Global Function %s()\n\n<p>",sgml(func->name,0)); 610 | else 611 | fprintf(of,"\n<sect1>Local Function %s()\n\n<p>",sgml(func->name,0)); 612 | 613 | if(func->comment) 614 | { 615 | if(option_verbatim_comments) 616 | fprintf(of,"<tscreen><verb>\n%s\n</verb></tscreen>\n\n",sgml(func->comment,1)); 617 | else 618 | { 619 | comment2=strstr(func->comment,"\n\n"); 620 | if(comment2) 621 | comment2[0]=0; 622 | fprintf(of,"%s\n<p>\n",sgml(func->comment,0)); 623 | } 624 | } 625 | 626 | fprintf(of,"<tt>"); 627 | 628 | if(func->scope&LOCAL) 629 | fprintf(of,"static "); 630 | if(func->scope&INLINED) 631 | fprintf(of,"inline "); 632 | 633 | if((type=strstr(func->type,"()"))) 634 | type[0]=0; 635 | fprintf(of,"%s ( ",sgml(func->type,0)); 636 | 637 | for(i=0;i<func->args->n;i++) 638 | fprintf(of,i?", %s":"%s",sgml(func->args->s1[i],0)); 639 | 640 | if(type) 641 | {fprintf(of," %s</tt><newline>\n",sgml(&type[1],0));type[0]='(';} 642 | else 643 | fprintf(of," )</tt><newline>\n"); 644 | 645 | pret =strncmp("void ",func->type,5) && func->cret; 646 | for(pargs=0,i=0;i<func->args->n;i++) 647 | pargs = pargs || ( strcmp("void",func->args->s1[i]) && func->args->s2[i] ); 648 | 649 | if(pret || pargs) 650 | { 651 | fprintf(of,"<descrip>\n"); 652 | if(pret) 653 | fprintf(of,"<tag><tt>%s</tt></tag>\n%s\n",sgml(func->type,0),func->cret?sgml(func->cret,0):" "); 654 | if(pargs) 655 | for(i=0;i<func->args->n;i++) 656 | fprintf(of,"<tag><tt>%s</tt></tag>\n%s\n",sgml(func->args->s1[i],0),func->args->s2[i]?sgml(func->args->s2[i],0):" "); 657 | fprintf(of,"</descrip>\n"); 658 | } 659 | 660 | if(comment2) 661 | { 662 | fprintf(of,"%s\n<p>\n",sgml(&comment2[2],0)); 663 | comment2[0]='\n'; 664 | } 665 | 666 | if(func->protofile || func->incfrom || func->calls->n || func->called->n || func->used->n || func->f_refs->n || func->v_refs->n) 667 | fprintf(of,"<descrip>\n"); 668 | 669 | if(func->protofile) 670 | { 671 | fprintf(of,"<tag>Prototyped in:</tag>\n<itemize>\n"); 672 | fprintf(of,"<item>%s\n",sgml(func->protofile,0)); 673 | fprintf(of,"</itemize>\n"); 674 | } 675 | 676 | if(func->incfrom) 677 | { 678 | fprintf(of,"<tag>Included from:</tag>\n<itemize>\n"); 679 | fprintf(of,"<item>%s\n",sgml(func->incfrom,0)); 680 | fprintf(of,"</itemize>\n"); 681 | } 682 | 683 | if(func->calls->n) 684 | { 685 | int others=0; 686 | fprintf(of,"<tag>Calls:</tag>\n<itemize>\n"); 687 | for(i=0;i<func->calls->n;i++) 688 | { 689 | if(func->calls->s2[i]) 690 | fprintf(of,"<item>%s() : %s\n",sgml(func->calls->s1[i],0),sgml(func->calls->s2[i],0)); 691 | else 692 | others++; 693 | } 694 | 695 | if(others) 696 | { 697 | fprintf(of,"<item>"); 698 | for(i=0;i<func->calls->n;i++) 699 | if(!func->calls->s2[i]) 700 | fprintf(of,--others?"%s(), ":"%s()",sgml(func->calls->s1[i],0)); 701 | fprintf(of,"\n"); 702 | } 703 | fprintf(of,"</itemize>\n"); 704 | } 705 | 706 | if(func->called->n) 707 | { 708 | fprintf(of,"<tag>Called by:</tag>\n<itemize>\n"); 709 | for(i=0;i<func->called->n;i++) 710 | fprintf(of,"<item>%s() : %s\n",sgml(func->called->s1[i],0),sgml(func->called->s2[i],0)); 711 | fprintf(of,"</itemize>\n"); 712 | } 713 | 714 | if(func->used->n) 715 | { 716 | fprintf(of,"<tag>Used in:</tag>\n<itemize>\n"); 717 | for(i=0;i<func->used->n;i++) 718 | { 719 | if(func->used->s1[i][0]=='$' && !func->used->s1[i][1]) 720 | fprintf(of,"<item>%s\n",sgml(func->used->s2[i],0)); 721 | else 722 | fprintf(of,"<item>%s() : %s\n",sgml(func->used->s1[i],0),sgml(func->used->s2[i],0)); 723 | } 724 | fprintf(of,"</itemize>\n"); 725 | } 726 | 727 | if(func->f_refs->n) 728 | { 729 | int others=0; 730 | fprintf(of,"<tag>References Functions:</tag>\n<itemize>\n"); 731 | for(i=0;i<func->f_refs->n;i++) 732 | { 733 | if(func->f_refs->s2[i]) 734 | fprintf(of,"<item>%s() : %s\n",sgml(func->f_refs->s1[i],0),sgml(func->f_refs->s2[i],0)); 735 | else 736 | others++; 737 | } 738 | 739 | if(others) 740 | { 741 | fprintf(of,"<item>"); 742 | for(i=0;i<func->f_refs->n;i++) 743 | if(!func->f_refs->s2[i]) 744 | fprintf(of,--others?"%s(), ":"%s()",sgml(func->f_refs->s1[i],0)); 745 | fprintf(of,"\n"); 746 | } 747 | fprintf(of,"</itemize>\n"); 748 | } 749 | 750 | if(func->v_refs->n) 751 | { 752 | int others=0; 753 | fprintf(of,"<tag>References Variables:</tag>\n<itemize>\n"); 754 | for(i=0;i<func->v_refs->n;i++) 755 | { 756 | if(func->v_refs->s2[i]) 757 | fprintf(of,"<item>%s : %s\n",sgml(func->v_refs->s1[i],0),sgml(func->v_refs->s2[i],0)); 758 | else 759 | others++; 760 | } 761 | 762 | if(others) 763 | { 764 | fprintf(of,"<item>"); 765 | for(i=0;i<func->v_refs->n;i++) 766 | if(!func->v_refs->s2[i]) 767 | fprintf(of,--others?"%s, ":"%s",sgml(func->v_refs->s1[i],0)); 768 | fprintf(of,"\n"); 769 | } 770 | fprintf(of,"</itemize>\n"); 771 | } 772 | 773 | if(func->protofile || func->incfrom || func->calls->n || func->called->n || func->used->n || func->f_refs->n || func->v_refs->n) 774 | fprintf(of,"</descrip>\n"); 775 | } 776 | 777 | 778 | /*++++++++++++++++++++++++++++++++++++++ 779 | Write out a standard pre-amble. 780 | 781 | FILE* f The file to write the pre amble to. 782 | 783 | char* title The title of the file. 784 | ++++++++++++++++++++++++++++++++++++++*/ 785 | 786 | static void WriteSGMLPreamble(FILE* f,char* title) 787 | { 788 | fputs("<!DOCTYPE LINUXDOC SYSTEM>\n",f); 789 | fputs("\n",f); 790 | fputs("<!-- This SGML file generated by cxref (version " CXREF_VERSION "). -->\n",f); 791 | fputs("<!-- cxref program " CXREF_COPYRIGHT ". -->\n",f); 792 | fputs("\n",f); 793 | fputs("<!--\n",f); 794 | if(filename) 795 | fprintf(f,"Cxref: %s %s\n",run_command,filename); 796 | else 797 | fprintf(f,"Cxref: %s\n",run_command); 798 | fprintf(f,"CPP : %s\n",run_cpp_command); 799 | fputs("-->\n",f); 800 | fputs("\n",f); 801 | fputs("<article>\n",f); 802 | fputs("\n",f); 803 | fputs("<title>",f); 804 | fputs(title,f); 805 | fputs("\n",f); 806 | fputs("<author>cxref\n",f); 807 | fputs("\n",f); 808 | } 809 | 810 | 811 | /*++++++++++++++++++++++++++++++++++++++ 812 | Write out a standard post-amble. This includes the end of document marker. 813 | 814 | FILE* f The file to write the post amble to. 815 | ++++++++++++++++++++++++++++++++++++++*/ 816 | 817 | static void WriteSGMLPostamble(FILE* f) 818 | { 819 | fputs("\n",f); 820 | fputs("</article>\n",f); 821 | } 822 | 823 | 824 | /*++++++++++++++++++++++++++++++++++++++ 825 | Write out the appendix information. 826 | 827 | StringList files The list of files to write. 828 | 829 | StringList2 funcs The list of functions to write. 830 | 831 | StringList2 vars The list of variables to write. 832 | 833 | StringList2 types The list of types to write. 834 | ++++++++++++++++++++++++++++++++++++++*/ 835 | 836 | void WriteSGMLAppendix(StringList files,StringList2 funcs,StringList2 vars,StringList2 types) 837 | { 838 | char* ofile; 839 | int i; 840 | 841 | filename=NULL; 842 | 843 | /* Open the file */ 844 | 845 | ofile=ConcatStrings(5,option_odir,"/",option_name,SGML_APDX,SGML_FILE); 846 | 847 | of=fopen(ofile,"w"); 848 | 849 | if(!of) 850 | {fprintf(stderr,"cxref: Failed to open the SGML appendix file '%s'\n",ofile);exit(1);} 851 | 852 | /* Write the file structure out */ 853 | 854 | WriteSGMLPreamble(of,ConcatStrings(3,"Cross reference index of ",option_name,".")); 855 | 856 | fprintf(of,"<sect>Cross References\n"); 857 | 858 | /* Write out the appendix of files. */ 859 | 860 | if(files->n) 861 | { 862 | fprintf(of,"\n<sect1>Files\n\n<p>\n"); 863 | fprintf(of,"<itemize>\n"); 864 | for(i=0;i<files->n;i++) 865 | fprintf(of,"<item>%s>\n",sgml(files->s[i],0)); 866 | fprintf(of,"</itemize>\n"); 867 | } 868 | 869 | /* Write out the appendix of functions. */ 870 | 871 | if(funcs->n) 872 | { 873 | fprintf(of,"\n<sect1>Global Functions\n\n<p>\n"); 874 | fprintf(of,"<itemize>\n"); 875 | for(i=0;i<funcs->n;i++) 876 | fprintf(of,"<item>%s() : %s\n",sgml(funcs->s1[i],0),sgml(funcs->s2[i],0)); 877 | fprintf(of,"</itemize>\n"); 878 | } 879 | 880 | /* Write out the appendix of variables. */ 881 | 882 | if(vars->n) 883 | { 884 | fprintf(of,"\n<sect1>Global Variables\n\n<p>\n"); 885 | fprintf(of,"<itemize>\n"); 886 | for(i=0;i<vars->n;i++) 887 | fprintf(of,"<item>%s : %s\n",sgml(vars->s1[i],0),sgml(vars->s2[i],0)); 888 | fprintf(of,"</itemize>\n"); 889 | } 890 | 891 | /* Write out the appendix of types. */ 892 | 893 | if(types->n) 894 | { 895 | fprintf(of,"\n<sect1>Defined Types\n\n<p>\n"); 896 | fprintf(of,"<itemize>\n"); 897 | for(i=0;i<types->n;i++) 898 | if(!strncmp("enum",types->s1[i],4)) 899 | fprintf(of,"<item>%s : %s\n",sgml(types->s1[i],0),sgml(types->s2[i],0)); 900 | else if(!strncmp("union",types->s1[i],5)) 901 | fprintf(of,"<item>%s : %s\n",sgml(types->s1[i],0),sgml(types->s2[i],0)); 902 | else if(!strncmp("struct",types->s1[i],6)) 903 | fprintf(of,"<item>%s : %s\n",sgml(types->s1[i],0),sgml(types->s2[i],0)); 904 | else 905 | fprintf(of,"<item>%s : %s\n",sgml(types->s1[i],0),sgml(types->s2[i],0)); 906 | fprintf(of,"</itemize>\n"); 907 | } 908 | 909 | WriteSGMLPostamble(of); 910 | 911 | fclose(of); 912 | 913 | /* Clear the memory in sgml(,0) */ 914 | 915 | sgml(NULL,0); sgml(NULL,0); sgml(NULL,0); sgml(NULL,0); 916 | } 917 | 918 | 919 | /*++++++++++++++++++++++++++++++++++++++ 920 | Delete the SGML file and main file reference that belong to the named file. 921 | 922 | char *name The name of the file to delete. 923 | ++++++++++++++++++++++++++++++++++++++*/ 924 | 925 | void WriteSGMLFileDelete(char *name) 926 | { 927 | char *ofile; 928 | 929 | ofile=ConcatStrings(4,option_odir,"/",name,SGML_FILE); 930 | unlink(ofile); 931 | } 932 | 933 | 934 | /*++++++++++++++++++++++++++++++++++++++ 935 | Make the input string safe to output as SGML ( not <, >, &, ", $, #, % or ~ ). 936 | 937 | char* sgml Returns a safe SGML string. 938 | 939 | char* c A non-safe SGML string. 940 | 941 | int verbatim Set to true inside a verbatim environment. 942 | 943 | The function can only be called four times in each fprintf() since it returns one of only four static strings. 944 | ++++++++++++++++++++++++++++++++++++++*/ 945 | 946 | static char* sgml(char* c,int verbatim) 947 | { 948 | static char safe[4][256],*malloced[4]={NULL,NULL,NULL,NULL}; 949 | static int which=0; 950 | int copy=0,skip=0; 951 | int i=0,j=0,delta=10,len=256-delta; 952 | char* ret; 953 | 954 | which=(which+1)%4; 955 | ret=safe[which]; 956 | 957 | safe[which][0]=0; 958 | 959 | if(malloced[which]) 960 | {Free(malloced[which]);malloced[which]=NULL;} 961 | 962 | if(c) 963 | { 964 | i=CopyOrSkip(c,"sgml",©,&skip); 965 | 966 | while(1) 967 | { 968 | for(;j<len && c[i];i++) 969 | { 970 | if(copy) 971 | {ret[j++]=c[i]; if(c[i]=='\n') copy=0;} 972 | else if(skip) 973 | { if(c[i]=='\n') skip=0;} 974 | else if(verbatim) 975 | switch(c[i]) 976 | { 977 | case '&': 978 | strcpy(&ret[j],"&ero;");j+=5; 979 | break; 980 | case '<': 981 | if(c[i+1]=='/') 982 | {strcpy(&ret[j],"&etago;");j+=7; break;} 983 | default: 984 | ret[j++]=c[i]; 985 | } 986 | else 987 | switch(c[i]) 988 | { 989 | case '<': 990 | if(c[i+1]=='/') 991 | {strcpy(&ret[j],"&etago;");j+=7;} 992 | else 993 | {strcpy(&ret[j],"<");j+=4;} 994 | break; 995 | case '>': 996 | strcpy(&ret[j],">");j+=4; 997 | break; 998 | case '"': 999 | strcpy(&ret[j],""");j+=6; 1000 | break; 1001 | case '&': 1002 | strcpy(&ret[j],"&");j+=5; 1003 | break; 1004 | case '$': 1005 | strcpy(&ret[j],"$");j+=8; 1006 | break; 1007 | case '#': 1008 | strcpy(&ret[j],"#");j+=5; 1009 | break; 1010 | case '%': 1011 | strcpy(&ret[j],"%");j+=8; 1012 | break; 1013 | case '~': 1014 | strcpy(&ret[j],"˜");j+=7; 1015 | break; 1016 | case '\n': 1017 | if(j && ret[j-1]=='\n') 1018 | { 1019 | strcpy(&ret[j],"<newline>");j+=9; 1020 | } 1021 | ret[j++]=c[i]; 1022 | break; 1023 | default: 1024 | ret[j++]=c[i]; 1025 | } 1026 | if(c[i]=='\n') 1027 | i+=CopyOrSkip(c+i,"sgml",©,&skip); 1028 | } 1029 | 1030 | if(c[i]) /* Not finished */ 1031 | { 1032 | if(malloced[which]) 1033 | malloced[which]=Realloc(malloced[which],len+delta+256); 1034 | else 1035 | {malloced[which]=Malloc(len+delta+256); strncpy(malloced[which],ret,(unsigned)j);} 1036 | ret=malloced[which]; 1037 | len+=256; 1038 | } 1039 | else 1040 | {ret[j]=0; break;} 1041 | } 1042 | } 1043 | 1044 | return(ret); 1045 | }