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