1 | /*************************************** 2 | $Header: /home/amb/cxref/RCS/sgml.c 1.7 2004/01/24 19:20:25 amb Exp $ 3 | 4 | C Cross Referencing & Documentation tool. Version 1.5f. 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 "memory.h" 24 | #include "datatype.h" 25 | #include "cxref.h" 26 | 27 | /*+ The name of the output tex file that includes each of the others. +*/ 28 | #define SGML_FILE ".sgml" 29 | #define SGML_FILE_BACKUP ".sgml~" 30 | 31 | /*+ The name of the output tex file that contains the appendix. +*/ 32 | #define SGML_APDX ".apdx" 33 | 34 | /*+ The comments are to be inserted verbatim. +*/ 35 | extern int option_verbatim_comments; 36 | 37 | /*+ The name of the directory for the output. +*/ 38 | extern char* option_odir; 39 | 40 | /*+ The base name of the file for the output. +*/ 41 | extern char* option_name; 42 | 43 | /*+ The information about the cxref run, +*/ 44 | extern char *run_command, /*+ the command line options. +*/ 45 | *run_cpp_command; /*+ the cpp command and options. +*/ 46 | 47 | /*+ The directories to go back to get to the base output directory. +*/ 48 | static char* goback=NULL; 49 | 50 | static void WriteSGMLFilePart(File file); 51 | static void WriteSGMLInclude(Include inc); 52 | static void WriteSGMLSubInclude(Include inc,int depth); 53 | static void WriteSGMLDefine(Define def); 54 | static void WriteSGMLTypedef(Typedef type); 55 | static void WriteSGMLStructUnion(StructUnion su,int depth); 56 | static void WriteSGMLVariable(Variable var); 57 | static void WriteSGMLFunction(Function func); 58 | 59 | static void WriteSGMLPreamble(FILE* f,char* title); 60 | static void WriteSGMLPostamble(FILE* f); 61 | 62 | static char* sgml(char* c,int verbatim); 63 | 64 | /*+ The output file for the SGML. +*/ 65 | static FILE* of; 66 | 67 | /*+ The name of the file. +*/ 68 | static char *filename; 69 | 70 | 71 | /*++++++++++++++++++++++++++++++++++++++ 72 | Write an sgml file for a complete File structure and all components. 73 | 74 | File file The File structure to output. 75 | ++++++++++++++++++++++++++++++++++++++*/ 76 | 77 | void WriteSGMLFile(File file) 78 | { 79 | char* ofile; 80 | int i; 81 | 82 | filename=file->name; 83 | 84 | /* Open the file */ 85 | 86 | ofile=ConcatStrings(4,option_odir,"/",file->name,SGML_FILE); 87 | 88 | of=fopen(ofile,"w"); 89 | if(!of) 90 | { 91 | struct stat stat_buf; 92 | int i,ofl=strlen(ofile); 93 | 94 | for(i=strlen(option_odir)+1;i<ofl;i++) 95 | if(ofile[i]=='/') 96 | { 97 | ofile[i]=0; 98 | if(stat(ofile,&stat_buf)) 99 | mkdir(ofile,S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); 100 | ofile[i]='/'; 101 | } 102 | 103 | of=fopen(ofile,"w"); 104 | } 105 | 106 | if(!of) 107 | {fprintf(stderr,"cxref: Failed to open the SGML output file '%s'\n",ofile);exit(1);} 108 | 109 | for(goback="",i=strlen(file->name);i>0;i--) 110 | if(file->name[i]=='/') 111 | goback=ConcatStrings(2,goback,"../"); 112 | 113 | /* Write out a header. */ 114 | 115 | WriteSGMLPreamble(of,ConcatStrings(5,"Cross reference for ",file->name," of ",option_name,".")); 116 | 117 | /*+ The file structure is broken into its components and they are each written out. +*/ 118 | 119 | WriteSGMLFilePart(file); 120 | 121 | if(file->includes) 122 | { 123 | Include inc =file->includes; 124 | fprintf(of,"\n<sect1>Included Files\n\n<p>\n"); 125 | do{ 126 | WriteSGMLInclude(inc); 127 | } 128 | while((inc=inc->next)); 129 | } 130 | 131 | if(file->defines) 132 | { 133 | Define def =file->defines; 134 | fprintf(of,"\n<sect1>Preprocessor definitions\n\n<p>\n"); 135 | do{ 136 | if(def!=file->defines) 137 | fprintf(of,"<p>\n"); 138 | WriteSGMLDefine(def); 139 | } 140 | while((def=def->next)); 141 | } 142 | 143 | if(file->typedefs) 144 | { 145 | Typedef type=file->typedefs; 146 | do{ 147 | WriteSGMLTypedef(type); 148 | } 149 | while((type=type->next)); 150 | } 151 | 152 | if(file->variables) 153 | { 154 | int any_to_mention=0; 155 | Variable var=file->variables; 156 | 157 | do{ 158 | if(var->scope&(GLOBAL|LOCAL|EXTERNAL|EXTERN_F)) 159 | any_to_mention=1; 160 | } 161 | while((var=var->next)); 162 | 163 | if(any_to_mention) 164 | { 165 | int first_ext=1,first_local=1; 166 | Variable var=file->variables; 167 | do{ 168 | if(var->scope&GLOBAL) 169 | WriteSGMLVariable(var); 170 | } 171 | while((var=var->next)); 172 | var=file->variables; 173 | do{ 174 | if(var->scope&(EXTERNAL|EXTERN_F) && !(var->scope&GLOBAL)) 175 | { 176 | if(first_ext) 177 | {fprintf(of,"\n<sect1>External Variables\n\n"); first_ext=0;} 178 | fprintf(of,"<p>\n"); 179 | WriteSGMLVariable(var); 180 | } 181 | } 182 | while((var=var->next)); 183 | var=file->variables; 184 | do{ 185 | if(var->scope&LOCAL) 186 | { 187 | if(first_local) 188 | {fprintf(of,"\n<sect1>Local Variables\n\n"); first_local=0;} 189 | fprintf(of,"<p>\n"); 190 | WriteSGMLVariable(var); 191 | } 192 | } 193 | while((var=var->next)); 194 | } 195 | } 196 | 197 | if(file->functions) 198 | { 199 | Function func=file->functions; 200 | do{ 201 | if(func->scope&(GLOBAL|EXTERNAL)) 202 | WriteSGMLFunction(func); 203 | } 204 | while((func=func->next)); 205 | func=file->functions; 206 | do{ 207 | if(func->scope&LOCAL) 208 | WriteSGMLFunction(func); 209 | } 210 | while((func=func->next)); 211 | } 212 | 213 | WriteSGMLPostamble(of); 214 | 215 | fclose(of); 216 | 217 | /* Clear the memory in sgml() */ 218 | 219 | sgml(NULL,0); sgml(NULL,0); sgml(NULL,0); sgml(NULL,0); 220 | } 221 | 222 | 223 | /*++++++++++++++++++++++++++++++++++++++ 224 | Write a File structure out. 225 | 226 | File file The File to output. 227 | ++++++++++++++++++++++++++++++++++++++*/ 228 | 229 | static void WriteSGMLFilePart(File file) 230 | { 231 | int i; 232 | 233 | fprintf(of,"<sect>File %s\n",sgml(file->name,0)); 234 | 235 | if(file->comment) 236 | { 237 | if(option_verbatim_comments) 238 | fprintf(of,"<p><tscreen><verb>\n%s\n</verb></tscreen>\n\n",sgml(file->comment,1)); 239 | else 240 | { 241 | char *rcs1=strstr(file->comment,"$Header"),*rcs2=NULL; 242 | if(rcs1) 243 | { 244 | rcs2=strstr(&rcs1[1],"$"); 245 | if(rcs2) 246 | { 247 | rcs2[0]=0; 248 | fprintf(of,"<bf>RCS %s</bf>\n<p>\n",sgml(&rcs1[1],0)); 249 | rcs2[0]='$'; 250 | } 251 | } 252 | if(rcs2) 253 | fprintf(of,"%s\n<p>\n",sgml(&rcs2[2],0)); 254 | else 255 | fprintf(of,"%s\n<p>\n",sgml(file->comment,0)); 256 | } 257 | } 258 | 259 | if(file->inc_in->n) 260 | { 261 | int i; 262 | 263 | fprintf(of,"<p>\n<descrip>\n<tag>Included in:</tag>\n<itemize>\n"); 264 | for(i=0;i<file->inc_in->n;i++) 265 | fprintf(of,"<item>%s\n",sgml(file->inc_in->s[i],0)); 266 | fprintf(of,"</itemize>\n</descrip>\n"); 267 | } 268 | 269 | if(file->f_refs->n || file->v_refs->n) 270 | fprintf(of,"<descrip>\n"); 271 | 272 | if(file->f_refs->n) 273 | { 274 | int others=0; 275 | fprintf(of,"<tag>References Functions:</tag>\n<itemize>\n"); 276 | for(i=0;i<file->f_refs->n;i++) 277 | if(file->f_refs->s2[i]) 278 | fprintf(of,"<item>%s() : %s\n",sgml(file->f_refs->s1[i],0),sgml(file->f_refs->s2[i],0)); 279 | else 280 | others++; 281 | 282 | if(others) 283 | { 284 | fprintf(of,"<item>"); 285 | for(i=0;i<file->f_refs->n;i++) 286 | if(!file->f_refs->s2[i]) 287 | fprintf(of,--others?" %s(),":" %s()",sgml(file->f_refs->s1[i],0)); 288 | fprintf(of,"\n"); 289 | } 290 | fprintf(of,"</itemize>\n"); 291 | } 292 | 293 | if(file->v_refs->n) 294 | { 295 | int others=0; 296 | fprintf(of,"<tag>References Variables:</tag>\n<itemize>\n"); 297 | for(i=0;i<file->v_refs->n;i++) 298 | { 299 | if(file->v_refs->s2[i]) 300 | fprintf(of,"<item>%s : %s\n",sgml(file->v_refs->s1[i],0),sgml(file->v_refs->s2[i],0)); 301 | else 302 | others++; 303 | } 304 | 305 | if(others) 306 | { 307 | fprintf(of,"<item>"); 308 | for(i=0;i<file->v_refs->n;i++) 309 | if(!file->v_refs->s2[i]) 310 | fprintf(of,--others?" %s,":" %s",sgml(file->v_refs->s1[i],0)); 311 | fprintf(of,"\n"); 312 | } 313 | fprintf(of,"</itemize>\n"); 314 | } 315 | 316 | if(file->f_refs->n || file->v_refs->n) 317 | fprintf(of,"</descrip>\n"); 318 | } 319 | 320 | 321 | /*++++++++++++++++++++++++++++++++++++++ 322 | Write an Include structure out. 323 | 324 | Include inc The Include structure to output. 325 | ++++++++++++++++++++++++++++++++++++++*/ 326 | 327 | static void WriteSGMLInclude(Include inc) 328 | { 329 | if(inc->comment) 330 | fprintf(of,"%s\n<p>\n",sgml(inc->comment,0)); 331 | 332 | fprintf(of,"<itemize>\n"); 333 | 334 | if(inc->scope==LOCAL) 335 | fprintf(of,"<item><tt>#include "%s"</tt>\n",sgml(inc->name,0)); 336 | else 337 | fprintf(of,"<item><tt>#include <%s></tt>\n",sgml(inc->name,0)); 338 | 339 | if(inc->includes) 340 | WriteSGMLSubInclude(inc->includes,1); 341 | 342 | fprintf(of,"</itemize>\n"); 343 | } 344 | 345 | 346 | /*++++++++++++++++++++++++++++++++++++++ 347 | Write an Sub Include structure out. (An include structure that is included from another file.) 348 | 349 | Include inc The Include structure to output. 350 | 351 | int depth The depth of the include hierarchy. 352 | ++++++++++++++++++++++++++++++++++++++*/ 353 | 354 | static void WriteSGMLSubInclude(Include inc,int depth) 355 | { 356 | fprintf(of,"<itemize>\n"); 357 | 358 | while(inc) 359 | { 360 | if(inc->scope==LOCAL) 361 | fprintf(of,"<item><tt>#include "%s"</tt>\n",sgml(inc->name,0)); 362 | else 363 | fprintf(of,"<item><tt>#include <%s></tt>\n",sgml(inc->name,0)); 364 | 365 | if(inc->includes) 366 | WriteSGMLSubInclude(inc->includes,depth+1); 367 | 368 | inc=inc->next; 369 | } 370 | 371 | fprintf(of,"</itemize>\n"); 372 | } 373 | 374 | 375 | /*++++++++++++++++++++++++++++++++++++++ 376 | Write a Define structure out. 377 | 378 | Define def The Define structure to output. 379 | ++++++++++++++++++++++++++++++++++++++*/ 380 | 381 | static void WriteSGMLDefine(Define def) 382 | { 383 | int i; 384 | int pargs=0; 385 | 386 | if(def->comment) 387 | fprintf(of,"%s\n<p>\n",sgml(def->comment,0)); 388 | 389 | fprintf(of,"<tt>#define %s",sgml(def->name,0)); 390 | 391 | if(def->value) 392 | fprintf(of," %s",sgml(def->value,0)); 393 | 394 | if(def->args->n) 395 | { 396 | fprintf(of,"( "); 397 | for(i=0;i<def->args->n;i++) 398 | fprintf(of,i?", %s":"%s",sgml(def->args->s1[i],0)); 399 | fprintf(of," )"); 400 | } 401 | fprintf(of,"</tt><newline>\n"); 402 | 403 | for(i=0;i<def->args->n;i++) 404 | if(def->args->s2[i]) 405 | pargs=1; 406 | 407 | if(pargs) 408 | { 409 | fprintf(of,"<descrip>\n"); 410 | for(i=0;i<def->args->n;i++) 411 | 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):""); 412 | fprintf(of,"</descrip>\n"); 413 | } 414 | } 415 | 416 | 417 | /*++++++++++++++++++++++++++++++++++++++ 418 | Write a Typedef structure out. 419 | 420 | Typedef type The Typedef structure to output. 421 | ++++++++++++++++++++++++++++++++++++++*/ 422 | 423 | static void WriteSGMLTypedef(Typedef type) 424 | { 425 | fprintf(of,"\n<sect1>"); 426 | 427 | if(type->type) 428 | fprintf(of,"Typedef %s",sgml(type->name,0)); 429 | else 430 | fprintf(of,"Type %s",sgml(type->name,0)); 431 | 432 | fprintf(of,"\n\n<p>\n"); 433 | 434 | if(type->comment) 435 | fprintf(of,"%s\n<p>\n",sgml(type->comment,0)); 436 | 437 | if(type->type) 438 | fprintf(of,"<tt>typedef %s</tt><newline>\n",sgml(type->type,0)); 439 | 440 | if(type->sutype) 441 | { 442 | fprintf(of,"<itemize>\n"); 443 | WriteSGMLStructUnion(type->sutype,0); 444 | fprintf(of,"</itemize>\n"); 445 | } 446 | else 447 | if(type->typexref) 448 | { 449 | fprintf(of,"<descrip>\n<tag>See:</tag>\n<itemize>\n"); 450 | if(type->typexref->type) 451 | fprintf(of,"<item>Typedef %s\n",sgml(type->typexref->name,0)); 452 | else 453 | if(!strncmp("enum",type->typexref->name,4)) 454 | fprintf(of,"<item>Type %s\n",sgml(type->typexref->name,0)); 455 | else 456 | if(!strncmp("union",type->typexref->name,5)) 457 | fprintf(of,"<item>Type %s\n",sgml(type->typexref->name,0)); 458 | else 459 | 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. -->\n",f); 791 | fputs("<!-- cxref program (c) Andrew M. Bishop 1995,96,97,98,99. -->\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 901 | if(!strncmp("union",types->s1[i],5)) 902 | fprintf(of,"<item>%s : %s\n",sgml(types->s1[i],0),sgml(types->s2[i],0)); 903 | else 904 | if(!strncmp("struct",types->s1[i],6)) 905 | fprintf(of,"<item>%s : %s\n",sgml(types->s1[i],0),sgml(types->s2[i],0)); 906 | else 907 | fprintf(of,"<item>%s : %s\n",sgml(types->s1[i],0),sgml(types->s2[i],0)); 908 | fprintf(of,"</itemize>\n"); 909 | } 910 | 911 | WriteSGMLPostamble(of); 912 | 913 | fclose(of); 914 | 915 | /* Clear the memory in sgml(,0) */ 916 | 917 | sgml(NULL,0); sgml(NULL,0); sgml(NULL,0); sgml(NULL,0); 918 | } 919 | 920 | 921 | /*++++++++++++++++++++++++++++++++++++++ 922 | Delete the SGML file and main file reference that belong to the named file. 923 | 924 | char *name The name of the file to delete. 925 | ++++++++++++++++++++++++++++++++++++++*/ 926 | 927 | void WriteSGMLFileDelete(char *name) 928 | { 929 | char *ofile; 930 | 931 | ofile=ConcatStrings(4,option_odir,"/",name,SGML_FILE); 932 | unlink(ofile); 933 | } 934 | 935 | 936 | /*++++++++++++++++++++++++++++++++++++++ 937 | Make the input string safe to output as SGML ( not <, >, &, ", $, #, % or ~ ). 938 | 939 | char* sgml Returns a safe SGML string. 940 | 941 | char* c A non-safe SGML string. 942 | 943 | int verbatim Set to true inside a verbatim environment. 944 | 945 | The function can only be called four times in each fprintf() since it returns one of only four static strings. 946 | ++++++++++++++++++++++++++++++++++++++*/ 947 | 948 | static char* sgml(char* c,int verbatim) 949 | { 950 | static char safe[4][256],*malloced[4]={NULL,NULL,NULL,NULL}; 951 | static int which=0; 952 | int copy=0,skip=0; 953 | int i=0,j=0,delta=10,len=256-delta; 954 | char* ret; 955 | 956 | which=(which+1)%4; 957 | ret=safe[which]; 958 | 959 | safe[which][0]=0; 960 | 961 | if(malloced[which]) 962 | {Free(malloced[which]);malloced[which]=NULL;} 963 | 964 | if(c) 965 | { 966 | i=CopyOrSkip(c,"sgml",©,&skip); 967 | 968 | while(1) 969 | { 970 | for(;j<len && c[i];i++) 971 | { 972 | if(copy) 973 | {ret[j++]=c[i]; if(c[i]=='\n') copy=0;} 974 | else if(skip) 975 | { if(c[i]=='\n') skip=0;} 976 | else if(verbatim) 977 | switch(c[i]) 978 | { 979 | case '&': 980 | strcpy(&ret[j],"&ero;");j+=5; 981 | break; 982 | case '<': 983 | if(c[i+1]=='/') 984 | {strcpy(&ret[j],"&etago;");j+=7; break;} 985 | default: 986 | ret[j++]=c[i]; 987 | } 988 | else 989 | switch(c[i]) 990 | { 991 | case '<': 992 | if(c[i+1]=='/') 993 | {strcpy(&ret[j],"&etago;");j+=7;} 994 | else 995 | {strcpy(&ret[j],"<");j+=4;} 996 | break; 997 | case '>': 998 | strcpy(&ret[j],">");j+=4; 999 | break; 1000 | case '"': 1001 | strcpy(&ret[j],""");j+=6; 1002 | break; 1003 | case '&': 1004 | strcpy(&ret[j],"&");j+=5; 1005 | break; 1006 | case '$': 1007 | strcpy(&ret[j],"$");j+=8; 1008 | break; 1009 | case '#': 1010 | strcpy(&ret[j],"#");j+=5; 1011 | break; 1012 | case '%': 1013 | strcpy(&ret[j],"%");j+=8; 1014 | break; 1015 | case '~': 1016 | strcpy(&ret[j],"˜");j+=7; 1017 | break; 1018 | case '\n': 1019 | if(j && ret[j-1]=='\n') 1020 | { 1021 | strcpy(&ret[j],"<newline>");j+=9; 1022 | } 1023 | ret[j++]=c[i]; 1024 | break; 1025 | default: 1026 | ret[j++]=c[i]; 1027 | } 1028 | if(c[i]=='\n') 1029 | i+=CopyOrSkip(c+i,"sgml",©,&skip); 1030 | } 1031 | 1032 | if(c[i]) /* Not finished */ 1033 | { 1034 | if(malloced[which]) 1035 | malloced[which]=Realloc(malloced[which],len+delta+256); 1036 | else 1037 | {malloced[which]=Malloc(len+delta+256); strncpy(malloced[which],ret,(unsigned)j);} 1038 | ret=malloced[which]; 1039 | len+=256; 1040 | } 1041 | else 1042 | {ret[j]=0; break;} 1043 | } 1044 | } 1045 | 1046 | return(ret); 1047 | }