1% Kpathsea changes for CWEB by Wlodek Bzyl and Olaf Weber 2% Copyright 2002 Wlodek Bzyl and Olaf Weber 3% This file is in the Public Domain. 4 5@x l.20 6\def\title{Common code for CTANGLE and CWEAVE (Version 3.64)} 7\def\topofcontents{\null\vfill 8 \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and 9 {\ttitlefont CWEAVE}} 10 \vskip 15pt 11 \centerline{(Version 3.64)} 12 \vfill} 13@y 14\def\Kpathsea/{{\mc KPATHSEA\spacefactor1000}} 15\def\title{Common code for CTANGLE and CWEAVE (Version 3.64k)} 16\def\topofcontents{\null\vfill 17 \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and 18 {\ttitlefont CWEAVE}} 19 \vskip 15pt 20 \centerline{(Version 3.64k)} 21 \vfill} 22@z 23 24This change can not be applied when `tie' is used 25(TOC file can not be typeset). 26 27%@x l.42 28%\let\maybe=\iftrue 29%@y 30%\let\maybe=\iffalse % print only changed modules 31%@z 32 33Section 1. 34 35@x l.63 36@<Predeclaration of procedures@>@/ 37@y 38#include "cweb.h" 39@<Predeclaration of procedures@>@/ 40@z 41 42Section 2. 43We use the definition from `kpathsea/types.h': 44 45 typedef enum { false = 0, true = 1 } boolean; 46 47Note that this definition also occurs in common.h. 48@x l.74 49typedef short boolean; 50@y 51@z 52 53 54Section 4. 55 56@x l.91 57common_init() 58@y 59common_init (void) 60@z 61 62@x l.93 63 @<Initialize pointers@>; 64@y 65 @<Initialize pointers@>; 66 @<Set up |PROGNAME| feature and initialize the search path mechanism@>; 67@z 68 69Section 5. 70 71@x l.103 72#include <ctype.h> 73@y 74#define CWEB 75#include "cpascal.h" 76#include <ctype.h> 77@z 78 79Section 7. 80 81@x l.153 82@d buf_size 100 /* for \.{CWEAVE} and \.{CTANGLE} */ 83@y 84@d buf_size 1000 /* for \.{CWEAVE} and \.{CTANGLE} */ 85@z 86 87@x l.156 88@d xisspace(c) (isspace(c)&&((unsigned char)c<0200)) 89@d xisupper(c) (isupper(c)&&((unsigned char)c<0200)) 90@y 91@d xisspace(c) (isspace((unsigned char)c)&&((unsigned char)c<0200)) 92@d xisupper(c) (isupper((unsigned char)c)&&((unsigned char)c<0200)) 93@z 94 95Section 9. 96 97@x l.173 98int input_ln(fp) /* copies a line into |buffer| or returns 0 */ 99FILE *fp; /* what file to read from */ 100@y 101int input_ln (FILE *fp) /* copies a line into |buffer| or returns 0 */ 102@z 103 104@x l.181 105 if ((*(k++) = c) != ' ') limit = k; 106@y 107 if ((*(k++) = c) != ' ' && c!='\r') limit = k; 108@z 109 110Section 10. 111 112@x l.207 - max_file_name_length is way too small. 113@d max_file_name_length 60 114@y 115@d max_file_name_length 1024 116@z 117 118@x l.221 - no alt_web_file_name needed. 119char alt_web_file_name[max_file_name_length]; /* alternate name to try */ 120@y 121@z 122 123Section 12. 124 125@x l.252 126void 127prime_the_change_buffer() 128@y 129static void 130prime_the_change_buffer (void) 131@z 132 133@x l.271 134 if (xisupper(buffer[1])) buffer[1]=tolower(buffer[1]); 135@y 136 if (xisupper(buffer[1])) buffer[1]=tolower((unsigned char)buffer[1]); 137@z 138 139Section 16. 140 141@x l.321 142void 143check_change() /* switches to |change_file| if the buffers match */ 144@y 145static void 146check_change (void) /* switches to |change_file| if the buffers match */ 147@z 148 149@x l.340 150 char xyz_code=xisupper(buffer[1])? tolower(buffer[1]): buffer[1]; 151@y 152 char xyz_code=xisupper(buffer[1])? tolower((unsigned char)buffer[1]): buffer[1]; 153@z 154 155Section 18. 156 157@x l.380 158reset_input() 159@y 160reset_input (void) 161@z 162 163Section 19. 164 165@x l.394 166if ((web_file=fopen(web_file_name,"r"))==NULL) { 167 strcpy(web_file_name,alt_web_file_name); 168 if ((web_file=fopen(web_file_name,"r"))==NULL) 169 fatal("! Cannot open input file ", web_file_name); 170} 171@y 172if ((found_filename=kpse_find_cweb(web_file_name))==NULL || 173 (web_file=fopen(found_filename,"r"))==NULL) { 174 fatal("! Cannot open input file ", web_file_name); 175} else if (strlen(found_filename) < max_file_name_length) { 176 strcpy(web_file_name, found_filename); 177 free(found_filename); 178} 179@z 180 181@x l.402 182if ((change_file=fopen(change_file_name,"r"))==NULL) 183 fatal("! Cannot open change file ", change_file_name); 184@y 185if ((found_filename=kpse_find_cweb(change_file_name))==NULL || 186 (change_file=fopen(found_filename,"r"))==NULL) { 187 fatal("! Cannot open change file ", change_file_name); 188} else if (strlen(found_filename) < max_file_name_length) { 189 strcpy(change_file_name, found_filename); 190 free(found_filename); 191} 192@z 193 194@x l.415 195@d max_sections 2000 /* number of identifiers, strings, section names; 196@y 197@d max_sections 10239 /* number of identifiers, strings, section names; 198@z 199 200Section 21. 201 202@x l.427 203int get_line() /* inputs the next line */ 204@y 205int get_line (void) /* inputs the next line */ 206@z 207 208Section 22. 209 210@x l.472 211#include <stdlib.h> /* declaration of |getenv| and |exit| */ 212@y 213#include <kpathsea/kpathsea.h> /* include every \Kpathsea/ header */ 214#include <stdlib.h> /* declaration of |getenv| and |exit| */ 215#include "help.h" 216 217@ The \.{ctangle} and \.{cweave} programs from the original \.{CWEB} 218package use the compile-time default directory or the value of the 219environment variable \.{CWEBINPUTS} as an alternative place to be 220searched for files, if they could not be found in the current 221directory. 222 223This version uses the \Kpathsea/ mechanism for searching files. 224The directories to be searched for come from three sources: 225 226 (a)~a user-set environment variable \.{CWEBINPUTS} 227 (overriden by \.{CWEBINPUTS\_cweb});\par 228 (b)~a line in \Kpathsea/ configuration file \.{texmf.cnf},\hfil\break 229 e.g. \.{CWEBINPUTS=.:$TEXMF/texmf/cweb//} 230 or \.{CWEBINPUTS.cweb=.:$TEXMF/texmf/cweb//};\hangindent=2\parindent\par 231 (c)~compile-time default directories \.{.:$TEXMF/texmf/cweb//} 232 (specified in \.{texmf.in}). 233 234 235@d kpse_find_cweb(name) kpse_find_file(name,kpse_cweb_format,true) 236 237@ The simple file searching is replaced by `path searching' mechanism 238that \Kpathsea/ library provides. 239 240We set |kpse_program_name| to a |"cweb"|. This means if the 241variable |CWEBINPUTS.cweb| is present in \.{texmf.cnf} (or |CWEBINPUTS_cweb| 242in the environment) its value will be used as the search path for 243filenames. This allows different flavors of \.{CWEB} to have 244different search paths. 245 246FIXME: Not sure this is the best way to go about this. 247 248@<Set up |PROGNAME| feature and initialize the search path mechanism@>= 249kpse_set_program_name(argv[0], "cweb"); 250@z 251 252 253Section 23. 254 255@x l.475 256 char temp_file_name[max_file_name_length]; 257 char *cur_file_name_end=cur_file_name+max_file_name_length-1; 258 char *k=cur_file_name, *kk; 259 int l; /* length of file name */ 260@y 261 char *cur_file_name_end=cur_file_name+max_file_name_length-1; 262 char *k=cur_file_name; 263@z 264 265@x l.489 266 if ((cur_file=fopen(cur_file_name,"r"))!=NULL) { 267@y 268 if ((found_filename=kpse_find_cweb(cur_file_name))!=NULL && 269 (cur_file=fopen(found_filename,"r"))!=NULL) { 270 /* Copy name for #line directives. */ 271 if (strlen(found_filename) < max_file_name_length) { 272 strcpy(cur_file_name, found_filename); 273 free(found_filename); 274 } 275@z 276 277Replaced by Kpathsea `kpse_find_file' 278 279@x l.493 280 kk=getenv("CWEBINPUTS"); 281 if (kk!=NULL) { 282 if ((l=strlen(kk))>max_file_name_length-2) too_long(); 283 strcpy(temp_file_name,kk); 284 } 285 else { 286#ifdef CWEBINPUTS 287 if ((l=strlen(CWEBINPUTS))>max_file_name_length-2) too_long(); 288 strcpy(temp_file_name,CWEBINPUTS); 289#else 290 l=0; 291#endif /* |CWEBINPUTS| */ 292 } 293 if (l>0) { 294 if (k+l+2>=cur_file_name_end) too_long(); 295@.Include file name ...@> 296 for (; k>= cur_file_name; k--) *(k+l+1)=*k; 297 strcpy(cur_file_name,temp_file_name); 298 cur_file_name[l]='/'; /* \UNIX/ pathname separator */ 299 if ((cur_file=fopen(cur_file_name,"r"))!=NULL) { 300 cur_line=0; print_where=1; 301 goto restart; /* success */ 302 } 303 } 304@y 305@z 306 307Section 26. 308 309@x l.553 310 if (xisupper(buffer[1])) buffer[1]=tolower(buffer[1]); 311@y 312 if (xisupper(buffer[1])) buffer[1]=tolower((unsigned char)buffer[1]); 313@z 314 315@x l.571 316check_complete(){ 317@y 318check_complete (void) { 319@z 320 321@x l.589 322@d max_bytes 90000 /* the number of bytes in identifiers, 323@y 324@d max_bytes 1000000 /* the number of bytes in identifiers, 325@z 326 327@x l.591 328@d max_names 4000 /* number of identifiers, strings, section names; 329@y 330@d max_names 10239 /* number of identifiers, strings, section names; 331@z 332 333@x l.642 334@d hash_size 353 /* should be prime */ 335@y 336@d hash_size 8501 /* should be prime */ 337@z 338 339Section 33. 340 341@x l.650 342@ @<Predec...@>= 343extern int names_match(); 344@y 345@ @<External functions@>= 346extern int names_match (name_pointer, const char*, int, char); 347@z 348 349Section 35. 350 351@x l.661 352id_lookup(first,last,t) /* looks up a string in the identifier table */ 353char *first; /* first character of string */ 354char *last; /* last character of string plus one */ 355char t; /* the |ilk|; used by \.{CWEAVE} only */ 356@y 357/* looks up a string in the identifier table */ 358id_lookup (const char *first, const char *last, char t) 359@z 360 361@x l.667 362 char *i=first; /* position in |buffer| */ 363@y 364 const char *i=first; /* position in |buffer| */ 365@z 366 367@x l.668 - rename local var, not to shadow global 368 int h; /* hash code */ 369@y 370 int h; /* hash code */ 371@z 372 373Section 36. 374 375@x l.684 - use renamed local var 376h=(unsigned char)*i; 377while (++i<last) h=(h+h+(int)((unsigned char)*i)) % hash_size; 378@y 379h=(unsigned char)*i; 380while (++i<last) h=(h+h+(int)((unsigned char)*i)) % hash_size; 381@z 382 383Section 37. 384 385@x l.692 - use renamed local var 386p=hash[h]; 387@y 388p=hash[h]; 389@z 390 391@x l.696 - use renamed local var 392 p->link=hash[h]; hash[h]=p; /* insert |p| at beginning of hash list */ 393@y 394 p->link=hash[h]; hash[h]=p; /* insert |p| at beginning of hash list */ 395@z 396 397Section 38. 398 399@x l.703 400@<Pred...@>= 401void init_p(); 402@y 403@<External functions@>= 404extern void init_p (name_pointer p, char t); 405@z 406 407Section 42. 408 409@x l.766 410print_section_name(p) 411name_pointer p; 412@y 413print_section_name (name_pointer p) 414@z 415 416Section 43. 417 418@x l.785 419sprint_section_name(dest,p) 420 char*dest; 421 name_pointer p; 422@y 423sprint_section_name (char *dest, name_pointer p) 424@z 425 426Section 44. 427 428@x l.805 429void 430print_prefix_name(p) 431name_pointer p; 432@y 433static void 434print_prefix_name (name_pointer p) 435@z 436 437Section 45. 438 439@x l.826 440int web_strcmp(j,j_len,k,k_len) /* fuller comparison than |strcmp| */ 441 char *j, *k; /* beginning of first and second strings */ 442 int j_len, k_len; /* length of strings */ 443@y 444/* fuller comparison than |strcmp| */ 445static int 446web_strcmp (char *j, int j_len, char *k, int k_len) 447@z 448 449@x l.830 -- rename local vars, not to shadow math function 450 char *j1=j+j_len, *k1=k+k_len; 451 while (k<k1 && j<j1 && *j==*k) k++, j++; 452 if (k==k1) if (j==j1) return equal; 453 else return extension; 454 else if (j==j1) return prefix; 455@y 456 char *j1=j+j_len, *k1=k+k_len; 457 while (k<k1 && j<j1 && *j==*k) k++, j++; 458 if (k==k1) if (j==j1) return equal; 459 else return extension; 460 else if (j==j1) return prefix; 461@z 462 463Section 46. 464 465@x l.852 466@<Prede...@>= 467extern void init_node(); 468@y 469@<External functions@>= 470extern void init_node (name_pointer node); 471@z 472 473Section 47. 474 475@x l.856 476name_pointer 477add_section_name(par,c,first,last,ispref) /* install a new node in the tree */ 478name_pointer par; /* parent of new node */ 479int c; /* right or left? */ 480char *first; /* first character of section name */ 481char *last; /* last character of section name, plus one */ 482int ispref; /* are we adding a prefix or a full name? */ 483@y 484static name_pointer 485add_section_name (name_pointer par, int c, char *first, char *last, 486 int ispref) /* install a new node in the tree */ 487@z 488 489Section 48. 490 491@x l.885 492void 493extend_section_name(p,first,last,ispref) 494name_pointer p; /* name to be extended */ 495char *first; /* beginning of extension text */ 496char *last; /* one beyond end of extension text */ 497int ispref; /* are we adding a prefix or a full name? */ 498@y 499static void 500extend_section_name (name_pointer p, char *first, char *last, int ispref) 501@z 502 503Section 49. 504 505@x l.914 506section_lookup(first,last,ispref) /* find or install section name in tree */ 507char *first, *last; /* first and last characters of new name */ 508int ispref; /* is the new name a prefix or a full name? */ 509@y 510/* find or install section name in tree */ 511section_lookup (char *first, char *last, int ispref) 512@z 513 514Section 53. 515 516@x l.1018 517int section_name_cmp(); 518@y 519static int section_name_cmp (char**, int, name_pointer); 520@z 521 522Section 54. 523 524@x l.1021 525int section_name_cmp(pfirst,len,r) 526char **pfirst; /* pointer to beginning of comparison string */ 527int len; /* length of string */ 528name_pointer r; /* section name being compared */ 529@y 530static int 531section_name_cmp (char **pfirst, int len, name_pointer r) 532@z 533 534Section 57. 535 536@x l.1092 537@<Predecl...@>= 538void err_print(); 539@y 540@<External functions@>= 541extern void err_print (const char*); 542@z 543 544Section 58. 545 546@x l.1098 547err_print(s) /* prints `\..' and location of error message */ 548char *s; 549@y 550err_print (const char *s) /* prints `\..' and location of error message */ 551@z 552 553Section 60. 554 555@x l.1140 556@<Prede...@>= 557int wrap_up(); 558extern void print_stats(); 559@y 560@<External functions@>= 561extern int wrap_up (void); 562extern void print_stats (void); 563@z 564 565Section 61. 566 567@x l.1151 568int wrap_up() { 569@y 570int wrap_up (void) { 571@z 572 573Section 63. 574 575@x l.1173 576@<Predec...@>= 577void fatal(), overflow(); 578@y 579@<External functions@>= 580extern void fatal (const char*, const char*); 581extern void overflow (const char*); 582@z 583 584Section 64. 585 586@x l.1180 587fatal(s,t) 588 char *s,*t; 589@y 590fatal (const char *s, const char *t) 591@z 592 593Section 65. 594 595@x l.1191 596overflow(t) 597 char *t; 598@y 599overflow (const char *t) 600@z 601 602Section 67. 603 604@x l.1212 605the names of those files. Most of the 128 flags are undefined but available 606for future extensions. 607@y 608the names of those files. Most of the 128 flags are undefined but available 609for future extensions. 610 611We use `kpathsea' library functions to find literate sources and 612NLS configuration files. When the files you expect are not 613being found, the thing to do is to enable `kpathsea' runtime 614debugging by assigning to |kpathsea_debug| variable a small number 615via `\.{-d}' option. The meaning of number is shown below. To set 616more than one debugging options sum the corresponding numbers. 617$$\halign{\hskip5em\tt\hfil#&&\qquad\tt#\cr 618 1&report `\.{stat}' calls\cr 619 2&report lookups in all hash tables\cr 620 4&report file openings and closings\cr 621 8&report path information\cr 62216&report directory list\cr 62332&report on each file search\cr 62464&report values of variables being looked up\cr}$$ 625Debugging output is always written to |stderr|, and begins with the string 626`\.{kdebug:}'. 627@z 628 629@x l.1218 630@d show_happiness flags['h'] /* should lack of errors be announced? */ 631@y 632@d show_happiness flags['h'] /* should lack of errors be announced? */ 633@d show_kpathsea_debug flags['d'] 634 /* should results of file searching be shown? */ 635@z 636 637@x l.1234 638show_banner=show_happiness=show_progress=1; 639@y 640show_banner=show_happiness=show_progress=1; 641@z 642 643Section 69. 644 645@x l.1252 646void scan_args(); 647@y 648static void scan_args (void); 649@z 650 651 652Section 70. 653 654@x l.1255 655void 656scan_args() 657@y 658static void 659scan_args (void) 660@z 661 662 663Section 71. 664 665@x l.1282 - use a define for /dev/null 666 if (found_change<=0) strcpy(change_file_name,"/dev/null"); 667@y 668 if (found_change<=0) strcpy(change_file_name,DEV_NULL); 669@z 670 671@x l.1302 - no alt_web_file_name 672 sprintf(alt_web_file_name,"%s.web",*argv); 673@y 674@z 675 676 677Section 74. 678 679@x l.1344 680@ @<Handle flag...@>= 681{ 682@y 683@ @<Handle flag...@>= 684{ 685 if (strcmp("-help",*argv)==0 || strcmp("--help",*argv)==0) 686 @<Display help message and exit@>; 687 if (strcmp("-version",*argv)==0 || strcmp("--version",*argv)==0) 688 @<Display version information and exit@>; 689@z 690 691@x l.1347 692 else flag_change=1; 693@y 694 else flag_change=1; 695 if (*(*argv+1)=='d') 696 if (sscanf(*argv+2,"%u",&kpathsea_debug)!=1) @<Print usage error...@>; 697@z 698 699@x l.1349 700 flags[*dot_pos]=flag_change; 701@y 702 flags[(unsigned char)*dot_pos]=flag_change; 703@z 704 705Section 75. 706 707@x l.1354 708if (program==ctangle) 709 fatal( 710"! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n" 711 ,""); 712@.Usage:@> 713else fatal( 714"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n" 715 ,""); 716@y 717if (program==ctangle) { 718 fprintf(stderr, "ctangle: Need one to three file arguments.\n"); 719 usage("ctangle"); 720} else { 721 fprintf(stderr, "cweave: Need one to three file arguments.\n"); 722 usage("cweave"); 723} 724@z 725 726Section 77. 727 728@x l.1375 729FILE *active_file; /* currently active file for \.{CWEAVE} output */ 730@y 731FILE *active_file; /* currently active file for \.{CWEAVE} output */ 732char *found_filename; /* filename found by |kpse_find_file| */ 733@z 734 735Section 78. 736 737@x l.1380 Use binary mode for output files 738 if ((C_file=fopen(C_file_name,"w"))==NULL) 739@y 740 if ((C_file=fopen(C_file_name,"wb"))==NULL) 741@z 742 743@x l.1386 Use binary mode for output files 744 if ((tex_file=fopen(tex_file_name,"w"))==NULL) 745@y 746 if ((tex_file=fopen(tex_file_name,"wb"))==NULL) 747@z 748 749 750Section 81. (reused) 751 752@x l.1403 753@ We predeclare several standard system functions here instead of including 754their system header files, because the names of the header files are not as 755standard as the names of the functions. (For example, some \CEE/ environments 756have \.{<string.h>} where others have \.{<strings.h>}.) 757 758@<Predecl...@>= 759extern int strlen(); /* length of string */ 760extern int strcmp(); /* compare strings lexicographically */ 761extern char* strcpy(); /* copy one string to another */ 762extern int strncmp(); /* compare up to $n$ string characters */ 763extern char* strncpy(); /* copy up to $n$ string characters */ 764@y 765@ We declare some more prototypes for exported function in cases where this 766could not be done easily without changing section numbers. 767 768@<External functions@>= 769extern void common_init (void); 770extern int input_ln (FILE *fp); 771extern void reset_input (void); 772extern int get_line (void); 773extern void check_complete (void); 774extern name_pointer id_lookup (const char *first, const char *last, char t); 775extern void print_section_name (name_pointer p); 776extern void sprint_section_name (char *dest, name_pointer p); 777extern name_pointer section_lookup (char *first, char *last, int ispref); 778@z 779 780@x 781@** Index. 782@y 783@** External functions. In order to allow for type checking we create a 784header file \.{cweb.h} containing the declaration of all functions defined 785in \.{common.w} and used in \.{ctangle.w} and \.{cweave.w} or vice versa. 786 787@(cweb.h@>= 788@=/* Prototypes for functions, either@> 789@= * declared in common.w and used in ctangle.w and cweave.w, or@> 790@= * used in common.w and declared in ctangle.w and cweave.w. */@> 791@<External functions@>@; 792extern const char *versionstring; 793 794@** System dependent changes. 795 796@ Modules for dealing with help messages and version info. 797 798@<Display help message and exit@>= 799usagehelp(program==ctangle ? CTANGLEHELP : CWEAVEHELP, NULL); 800@.--help@> 801 802@ Will have to change these if the version numbers change (ouch). 803 804@d ctangle_banner "This is CTANGLE, Version 3.64" 805@d cweave_banner "This is CWEAVE, Version 3.64" 806 807@<Display version information and exit@>= 808printversionandexit((program==ctangle ? ctangle_banner : cweave_banner), 809 "Silvio Levy and Donald E. Knuth", NULL, NULL); 810@.--version@> 811 812@** Index. 813@z 814