1% Change file for BibTeX in C, originally by Howard Trickey. 2% 3% 05/28/84 Initial implementation, version 0.41 of BibTeX 4% 07/01/84 Version 0.41a of BibTeX. 5% 12/17/84 Version 0.97c of BibTeX. 6% 02/12/85 Version 0.98c of BibTeX. 7% 02/25/85 Newer version 0.98c of BibTeX. 8% 03/25/85 Version 0.98f of BibTeX 9% 05/23/85 Version 0.98i of BibTeX 10% 02/11/88 Version 0.99b of BibTeX 11% 04/04/88 Version 0.99c; converted for use with web2c (ETM). 12% 11/30/89 Use FILENAMESIZE instead of 1024 (KB). 13% 03/09/90 `int' is a bad variable name for C. 14% (more recent changes in the ChangeLog) 15 16% [0] Let bibtex.tex work with latest webmac (which defines \ET, hence 17% making E active loses). 18@x 19\catcode`E=13 \uppercase{\def E{e}} 20\def\\#1{\hbox{\let E=\drop\it#1\/\kern.05em}} % italic type for identifiers 21@y 22\let\maybe = \iffalse % process only changed sections 23@z 24 25@x [1] Define my_name 26@d banner=='This is BibTeX, Version 0.99d' {printed when the program starts} 27@y 28@d my_name=='bibtex' 29@d banner=='This is BibTeX, Version 0.99d' {printed when the program starts} 30@z 31 32% [2] `term_in' and `term_out' are standard input and output. But 33% there is a complication: BibTeX passes `term_out' to some routines as 34% a var parameter. web2c turns a var parameter f into &f at the calling 35% side -- and stdout is sometimes implemented as `&_iob[1]' or some 36% such. An address of an address is invalid. Therefore, we define 37% variables `standardinput' and `standardoutput' in openinout.c. 38@x 39@d term_out == tty 40@d term_in == tty 41@y 42@d term_out == standard_output 43@d term_in == standard_input 44 45@<Globals in the outer block@>= 46standard_input, standard_output: text; 47@z 48 49@x [3] Add log_pr macros. 50@d trace_pr_newline == begin write_ln(log_file); end 51@y 52@d trace_pr_newline == begin write_ln(log_file); end 53@# 54@d log_pr(#) == trace_pr(#) 55@d log_pr_ln(#) == trace_pr_ln(#) 56@d log_pr_newline == trace_pr_newline 57@z 58 59@x [4] Turn debug..gubed et al. into #ifdef's. 60@d debug == @{ { remove the `|@{|' when debugging } 61@d gubed == @t@>@} { remove the `|@}|' when debugging } 62@f debug == begin 63@f gubed == end 64@# 65@d stat == @{ { remove the `|@{|' when keeping statistics } 66@d tats == @t@>@} { remove the `|@}|' when keeping statistics } 67@f stat == begin 68@f tats == end 69@# 70@d trace == @{ { remove the `|@{|' when in |trace| mode } 71@d ecart == @t@>@} { remove the `|@}|' when in |trace| mode } 72@f trace == begin 73@f ecart == end 74@y 75@d debug == ifdef('TEXMF_DEBUG') 76@d gubed == endif('TEXMF_DEBUG') 77@f debug == begin 78@f gubed == end 79@# 80@d stat == ifndef('NO_BIBTEX_STAT') 81@d tats == endifn('NO_BIBTEX_STAT') 82@f stat==begin 83@f tats==end 84@# 85@d trace == ifdef@&('TRACE') 86@d ecart == endif@&('TRACE') 87@f trace == begin 88@f ecart == end 89@z 90 91@x [10] Eliminate the |exit_program| label. 92label close_up_shop,@!exit_program @<Labels in the outer block@>; 93@y 94label close_up_shop @<Labels in the outer block@>; 95@z 96 97@x [10] Don't print the banner unless verbose, and initialize dynamic arrays. 98begin 99initialize; 100print_ln(banner);@/ 101@y 102@<Define |parse_arguments|@> 103begin 104standard_input := stdin; 105standard_output := stdout; 106@# 107pool_size := POOL_SIZE; 108buf_size := BUF_SIZE; 109max_bib_files := MAX_BIB_FILES; 110max_glob_strs := MAX_GLOB_STRS; 111max_fields := MAX_FIELDS; 112max_cites := MAX_CITES; 113wiz_fn_space := WIZ_FN_SPACE; 114lit_stk_size := LIT_STK_SIZE; 115@# 116setup_params; 117@# 118{Add one to the sizes because that's what bibtex uses.} 119bib_file := XTALLOC (max_bib_files + 1, alpha_file); 120bib_list := XTALLOC (max_bib_files + 1, str_number); 121entry_ints := nil; 122entry_strs := nil; 123wiz_functions := XTALLOC (wiz_fn_space + 1, hash_ptr2); 124field_info := XTALLOC (max_fields + 1, str_number); 125s_preamble := XTALLOC (max_bib_files + 1, str_number); 126str_pool := XTALLOC (pool_size + 1, ASCII_code); 127buffer := XTALLOC (buf_size + 1, ASCII_code); 128sv_buffer := XTALLOC (buf_size + 1, ASCII_code); 129ex_buf := XTALLOC (buf_size + 1, ASCII_code); 130out_buf := XTALLOC (buf_size + 1, ASCII_code); 131name_tok := XTALLOC (buf_size + 1, buf_pointer); 132name_sep_char := XTALLOC (buf_size + 1, ASCII_code); 133@# 134glb_str_ptr := XTALLOC (max_glob_strs, str_number); 135global_strs := XTALLOC (max_glob_strs * (glob_str_size + 1), ASCII_code); 136glb_str_end := XTALLOC (max_glob_strs, integer); 137@# 138cite_list := XTALLOC (max_cites + 1, str_number); 139type_list := XTALLOC (max_cites + 1, hash_ptr2); 140entry_exists := XTALLOC (max_cites + 1, boolean); 141cite_info := XTALLOC (max_cites + 1, str_number); 142@# 143str_start := XTALLOC (max_strings + 1, pool_pointer); 144@# 145hash_next := XTALLOC (hash_max + 1, hash_pointer); 146hash_text := XTALLOC (hash_max + 1, str_number); 147hash_ilk := XTALLOC (hash_max + 1, str_ilk); 148ilk_info := XTALLOC (hash_max + 1, integer); 149fn_type := XTALLOC (hash_max + 1, fn_class); 150@# 151lit_stack := XTALLOC (lit_stk_size + 1, integer); 152lit_stk_type := XTALLOC (lit_stk_size + 1, stk_type); 153@# 154compute_hash_prime; 155@# 156initialize; 157{This initializes the jmp9998 buffer, which can be used early} 158hack0; 159if verbose then begin 160 print (banner); 161 print_ln (version_string); 162end 163else begin 164 log_pr (banner); 165 log_pr_ln (version_string); 166end; 167log_pr_ln ('Capacity: max_strings=', max_strings:1, 168 ', hash_size=', hash_size:1, ', hash_prime=', hash_prime:1); 169@z 170 171% [10] Possibly exit with bad status. It doesn't seem worth it to move 172% the definitions of the |history| values to above this module; hence the 1. 173@x 174exit_program: 175end. 176@y 177if (history > 1) then uexit (history); 178end. 179@z 180 181@x [13] Remove nonlocal goto. 182 goto exit_program; 183@y 184 uexit (1); 185@z 186 187@x [14] Increase some constants, and uppercase others for dynamic arrays. 188@<Constants in the outer block@>= 189@y 190@<Constants in the outer block@>= 191@!hash_base = empty + 1; {lowest numbered hash-table location} 192@!quote_next_fn = hash_base - 1; {special marker used in defining functions} 193@z 194 195@x [still 14] 196@!buf_size=1000; {maximum number of characters in an input line (or string)} 197@y 198@!BUF_SIZE=20000; {initial maximum number of characters in an input line 199 (or string)} 200@z 201 202@x [still 14] 203@!max_bib_files=20; {maximum number of \.{.bib} files allowed} 204@!pool_size=65000; {maximum number of characters in strings} 205@!max_strings=4000; {maximum number of strings, including pre-defined; 206 must be |<=hash_size|} 207@!max_cites=750; {maximum number of distinct cite keys; must be 208 |<=max_strings|} 209@!min_crossrefs=2; {minimum number of cross-refs required for automatic 210 |cite_list| inclusion} 211@!wiz_fn_space=3000; {maximum amount of |wiz_defined|-function space} 212@y [still 14] 213@!MAX_BIB_FILES=20; {initial number of \.{.bib} files allowed} 214@!POOL_SIZE=65000; {initial number of characters in strings} 215@!MAX_STRINGS=4000; {minimum value for |max_strings|} 216@!MAX_CITES=750; {initial number of distinct cite keys; must be 217 |<=max_strings|} 218@!WIZ_FN_SPACE=3000; {initial amount of |wiz_defined|-function space} 219{|min_crossrefs| can be set at runtime now.} 220@z 221 222@x [still 14] 223@!single_fn_space=100; {maximum amount for a single |wiz_defined|-function} 224@y 225@!SINGLE_FN_SPACE=50; {initial amount for a single |wiz_defined|-function} 226@z 227 228@x [still 14] handle long citation strings 229@!max_ent_ints=3000; {maximum number of |int_entry_var|s 230 (entries $\times$ |int_entry_var|s)} 231@!max_ent_strs=3000; {maximum number of |str_entry_var|s 232 (entries $\times$ |str_entry_var|s)} 233@!ent_str_size=100; {maximum size of a |str_entry_var|; must be |<=buf_size|} 234@!glob_str_size=1000; {maximum size of a |str_global_var|; 235 must be |<=buf_size|} 236@!max_fields=17250; {maximum number of fields (entries $\times$ fields, 237@y 238@!ENT_STR_SIZE=100; {maximum size of a |str_entry_var|; must be |<=buf_size|} 239@!GLOB_STR_SIZE=1000; {maximum size of a |str_global_var|; 240 must be |<=buf_size|} 241@!MAX_GLOB_STRS=10; {initial number of |str_global_var| names} 242@!MAX_FIELDS=5000; {initial number of fields (entries $\times$ fields, 243@z 244 245@x [still 14] 246@!lit_stk_size=100; {maximum number of literal functions on the stack} 247@y 248@!LIT_STK_SIZE=50; {initial space for literal functions on the stack} 249@z 250 251@x [15] Increase more constants in the web defines. 252@d hash_size=5000 {must be |>= max_strings| and |>= hash_prime|} 253@d hash_prime=4253 {a prime number about 85\% of |hash_size| and |>= 128| 254 and |< @t$2^{14}-2^6$@>|} 255@d file_name_size=40 {file names shouldn't be longer than this} 256@d max_glob_strs=10 {maximum number of |str_global_var| names} 257@d max_glb_str_minus_1 = max_glob_strs-1 {to avoid wasting a |str_global_var|} 258@y 259{|hash_size| and |hash_prime| are now computed.} 260@d HASH_SIZE=5000 {minimum value for |hash_size|} 261@# 262@d file_name_size==maxint {file names have no arbitrary maximum length} 263@# 264{For dynamic allocation.} 265@d x_entry_strs_tail(#) == (#)] 266@d x_entry_strs(#) == entry_strs[(#) * (ent_str_size+1) + x_entry_strs_tail 267@d x_global_strs_tail(#) == (#)] 268@d x_global_strs(#) == global_strs[(#) * (glob_str_size+1) + x_global_strs_tail 269@z 270 271@x [16] Add new variables-that-used-to-be-constants for dynamic arrays. 272@<Globals in the outer block@>= 273@y 274@<Globals in the outer block@>= 275@!pool_size: integer; 276@!max_bib_files: integer; 277@!max_cites: integer; 278@!wiz_fn_space: integer; 279@!ent_str_size: integer; 280@!glob_str_size: integer; 281@!max_glob_strs: integer; 282@!max_fields: integer; 283@!lit_stk_size: integer; 284@# 285@!max_strings: integer; 286@!hash_size: integer; 287@!hash_prime: integer; 288@# 289@!hash_max: integer; {highest numbered hash-table location} 290@!end_of_def: integer; {another special marker used in defining functions} 291@!undefined: integer; {a special marker used for |type_list|} 292@z 293 294@x [17] max_strings=hash_size settable at runtime. 295if (hash_prime >= (16384-64)) then bad:=10*bad+6; 296@y 297if (hash_base <> 1) then bad:=10*bad+6; 298@z 299 300@x [17] remove the following, since buf_size changes dynamically. 301if (ent_str_size > buf_size) then bad:=10*bad+9; 302if (glob_str_size > buf_size) then bad:=100*bad+11; 303@y 304@z 305 306@x [22, 23, 27, 28] Allow any character as input. [22] 307@!ASCII_code=0..127; {seven-bit numbers} 308@y 309@!ASCII_code=0..255; {eight-bit numbers} 310@z 311 312@x [23] 313@d text_char == char {the data type of characters in text files} 314@d first_text_char=0 {ordinal number of the smallest element of |text_char|} 315@d last_text_char=127 {ordinal number of the largest element of |text_char|} 316 317@<Local variables for initialization@>= 318i:0..last_text_char; {this is the first one declared} 319@y 320@d text_char == ASCII_code {the data type of characters in text files} 321@d first_text_char=0 {ordinal number of the smallest element of |text_char|} 322@d last_text_char=255 {ordinal number of the largest element of |text_char|} 323 324@<Local variables for initialization@>= 325i:integer; 326@z 327 328@x [27] 329for i:=1 to @'37 do xchr[i]:=' '; 330xchr[tab]:=chr(tab); 331@y 332for i:=0 to @'37 do xchr[i]:=chr(i); 333for i:=@'177 to @'377 do xchr[i]:=chr(i); 334@z 335 336@x [28] 337for i:=first_text_char to last_text_char do xord[chr(i)]:=invalid_code; 338for i:=1 to @'176 do xord[xchr[i]]:=i; 339@y 340for i:=first_text_char to last_text_char do xord[xchr[i]]:=i; 341@z 342 343@x [32] Put the [128..255] range into lex_class alpha. 344for i:=0 to @'177 do lex_class[i] := other_lex; 345@y 346for i:=0 to @'177 do lex_class[i] := other_lex; 347for i:=@'200 to @'377 do lex_class[i] := alpha; 348@z 349 350% [32] Make RET a `white_space' character, so we won't choke on DOS 351% files, which use CR/LF for line endings. 352@x 353lex_class[tab] := white_space; 354@y 355lex_class[tab] := white_space; 356lex_class[13] := white_space; 357@z 358 359@x [33] Allow the [128..255] range in legal_id_char. 360for i:=0 to @'177 do id_class[i] := legal_id_char; 361@y 362for i:=0 to @'377 do id_class[i] := legal_id_char; 363@z 364 365% [37] file_name_size no longer exists. See comments in tex.ch for why 366% we change the element type to text_char. 367@x 368@!name_of_file:packed array[1..file_name_size] of char; 369 {on some systems this is a \&{record} variable} 370@!name_length:0..file_name_size; 371 {this many characters are relevant in |name_of_file| (the rest are blank)} 372@!name_ptr:0..file_name_size+1; {index variable into |name_of_file|} 373@y 374@!name_of_file:^text_char; 375@!name_length:integer; 376 {this many characters are relevant in |name_of_file| } 377@!name_ptr:integer; {index variable into |name_of_file|} 378@z 379 380@x [38] File opening. 381The \ph\ compiler with which the present version of \TeX\ was prepared has 382extended the rules of \PASCAL\ in a very convenient way. To open file~|f|, 383we can write 384$$\vbox{\halign{#\hfil\qquad&#\hfil\cr 385|reset(f,@t\\{name}@>,'/O')|&for input;\cr 386|rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$ 387The `\\{name}' parameter, which is of type `\ignorespaces|packed 388array[@t\<\\{any}>@>] of text_char|', stands for the name of 389the external file that is being opened for input or output. 390Blank spaces that might appear in \\{name} are ignored. 391 392The `\.{/O}' parameter tells the operating system not to issue its own 393error messages if something goes wrong. If a file of the specified name 394cannot be found, or if such a file cannot be opened for some other reason 395(e.g., someone may already be trying to write the same file), we will have 396|@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|. This allows 397\TeX\ to undertake appropriate corrective action. 398 399\TeX's file-opening procedures return |false| if no file identified by 400|name_of_file| could be opened. 401 402@d reset_OK(#)==erstat(#)=0 403@d rewrite_OK(#)==erstat(#)=0 404 405@<Procedures and functions for file-system interacting@>= 406function erstat(var f:file):integer; extern; {in the runtime library} 407@#@t\2@> 408function a_open_in(var f:alpha_file):boolean; {open a text file for input} 409begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f); 410end; 411@# 412function a_open_out(var f:alpha_file):boolean; {open a text file for output} 413begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f); 414end; 415@y 416@ File opening will be done in C. 417@d no_file_path = -1 418@z 419 420@x [39] Do file closing in C. 421@<Procedures and functions for file-system interacting@>= 422procedure a_close(var f:alpha_file); {close a text file} 423begin close(f); 424end; 425@y 426File closing will be done in C, too. 427@z 428 429@x [42] Dynamic buf_size. 430@!buffer:buf_type; {usually, lines of characters being read} 431@y 432@!buf_size:integer; {size of buffer} 433@!buffer:buf_type; {usually, lines of characters being read} 434@z 435 436@x [43] Dyanmic buf_size. 437@!buf_pointer = 0..buf_size; {an index into a |buf_type|} 438@!buf_type = array[buf_pointer] of ASCII_code; {for various buffers} 439@y 440@!buf_pointer = integer; {an index into a |buf_type|} 441@!buf_type = ^ASCII_code; {for various buffers} 442@z 443 444@x [47] Dynamic buf_size. 445overflow('buffer size ',buf_size); 446@y 447BIB_XRETALLOC_NOSET ('buffer', buffer, ASCII_code, 448 buf_size, buf_size + BUF_SIZE); 449BIB_XRETALLOC_NOSET ('sv_buffer', sv_buffer, ASCII_code, 450 buf_size, buf_size + BUF_SIZE); 451BIB_XRETALLOC_NOSET ('ex_buf', ex_buf, ASCII_code, 452 buf_size, buf_size + BUF_SIZE); 453BIB_XRETALLOC_NOSET ('out_buf', out_buf, ASCII_code, 454 buf_size, buf_size + BUF_SIZE); 455BIB_XRETALLOC_NOSET ('name_tok', name_tok, buf_pointer, 456 buf_size, buf_size + BUF_SIZE); 457BIB_XRETALLOC ('name_sep_char', name_sep_char, ASCII_code, 458 buf_size, buf_size + BUF_SIZE); 459@z 460 461@x [48] web2c doesn't understand f^. 462 buffer[last]:=xord[f^]; 463 get(f); incr(last); 464 end; 465 get(f); 466@y 467 buffer[last] := xord[getc (f)]; 468 incr (last); 469 end; 470 vgetc (f); {skip the eol} 471@z 472 473@x [49] Dynamically allocate str_pool. 474@!str_pool : packed array[pool_pointer] of ASCII_code; {the characters} 475@!str_start : packed array[str_number] of pool_pointer; {the starting pointers} 476@y 477@!str_pool : ^ASCII_code; {the characters} 478@!str_start :^pool_pointer; {the starting pointers} 479@z 480 481@x [50] pool_size is a variable now, so can't be used as a constant. 482@!pool_pointer = 0..pool_size; {for variables that point into |str_pool|} 483@!str_number = 0..max_strings; {for variables that point into |str_start|} 484@y 485@!pool_pointer = integer; {for variables that point into |str_pool|} 486@!str_number = integer; {for variables that point into |str_start|} 487@z 488 489@x [51] Add log_pr_pool_str macro. 490@d trace_pr_pool_str(#) == begin 491 out_pool_str(log_file,#); 492 end 493@y 494@d trace_pr_pool_str(#) == begin 495 out_pool_str(log_file,#); 496 end 497@# 498@d log_pr_pool_str(#) == trace_pr_pool_str(#) 499@z 500 501@x [54] Reallocate str_pool. We may need more than POOL_SIZE. 502 if (pool_ptr+# > pool_size) then 503@y 504 while (pool_ptr+# > pool_size) do 505@z 506@x [54] Reallocate str_pool. 507overflow('pool size ',pool_size); 508@y 509BIB_XRETALLOC ('str_pool', str_pool, ASCII_code, pool_size, 510 pool_size + POOL_SIZE); 511@z 512 513% [59] (start_name) reallocate name_of_file for the new name and 514% terminate with null. 515@x 516if (length(file_name) > file_name_size) then 517 begin 518 print ('File='); 519 print_pool_str (file_name); 520 print_ln (','); 521 file_nm_size_overflow; 522 end; 523@y 524free (name_of_file); 525name_of_file := xmalloc_array (ASCII_code, length (file_name) + 1); 526@z 527 528@x 529name_length := length(file_name); 530@y 531name_length := length(file_name); 532name_of_file[name_length + 1] := 0; 533@z 534 535@x [60] (file_nm_size_overflow) This procedure is not used. 536procedure file_nm_size_overflow; 537begin 538overflow('file name size ',file_name_size); 539end; 540@y 541@z 542 543% [61] (add_extension) Don't pad name_of_file with blanks, terminate 544% with null. And junk the overflow check, since Web2c can't translate 545% the print statement properly and it can never happen, anyway. 546@x 547if (name_length + length(ext) > file_name_size) then 548 begin 549 print ('File=',name_of_file,', extension='); 550 print_pool_str (ext); print_ln (','); 551 file_nm_size_overflow; 552 end; 553@y 554@z 555@x 556name_ptr := name_length+1; 557while (name_ptr <= file_name_size) do {pad with blanks} 558 begin 559 name_of_file[name_ptr] := ' '; 560 incr(name_ptr); 561 end; 562@y 563name_of_file[name_length + 1] := 0; 564@z 565 566@x [62] (add_area) This procedure is not used. 567procedure add_area(@!area:str_number); 568var p_ptr: pool_pointer; {running index} 569begin 570if (name_length + length(area) > file_name_size) then 571 begin 572 print ('File='); 573 print_pool_str (area); print (name_of_file,','); 574 file_nm_size_overflow; 575 end; 576name_ptr := name_length; 577while (name_ptr > 0) do {shift up name} 578 begin 579 name_of_file[name_ptr+length(area)] := name_of_file[name_ptr]; 580 decr(name_ptr); 581 end; 582name_ptr := 1; 583p_ptr := str_start[area]; 584while (p_ptr < str_start[area+1]) do 585 begin 586 name_of_file[name_ptr] := chr (str_pool[p_ptr]); 587 incr(name_ptr); incr(p_ptr); 588 end; 589name_length := name_length + length(area); 590end; 591@y 592@z 593 594@x [65] now Pascal consts or vars, instead of web macros. 595@d hash_base = empty + 1 {lowest numbered hash-table location} 596@d hash_max = hash_base + hash_size - 1 {highest numbered hash-table location} 597@y 598@z 599 600@x [65] max_strings=hash_size settable at runtime. 601@!hash_loc=hash_base..hash_max; {a location within the hash table} 602@!hash_pointer=empty..hash_max; {either |empty| or a |hash_loc|} 603@y 604@!hash_loc=integer; {a location within the hash table} 605@!hash_pointer=integer; {either |empty| or a |hash_loc|} 606@z 607 608@x [66] max_strings=hash_size settable at runtime. 609@!hash_next : packed array[hash_loc] of hash_pointer; {coalesced-list link} 610@!hash_text : packed array[hash_loc] of str_number; {pointer to a string} 611@!hash_ilk : packed array[hash_loc] of str_ilk; {the type of string} 612@!ilk_info : packed array[hash_loc] of integer; {|ilk|-specific info} 613@!hash_used : hash_base..hash_max+1; {allocation pointer for hash table} 614@y 615@!hash_next : ^hash_pointer; {coalesced-list link} 616@!hash_text : ^str_number; {pointer to a string} 617@!hash_ilk : ^str_ilk; {the type of string} 618@!ilk_info : ^integer; {|ilk|-specific info} 619@!hash_used : integer; {allocation pointer for hash table} 620@z 621 622@x [69] Not used anymore. 623@d max_hash_value = hash_prime+hash_prime-2+127 {|h|'s maximum value} 624@y 625@z 626 627@x [69] max_strings=hash_size settable at runtime. 628var h:0..max_hash_value; {hash code} 629@y 630var h:integer; {hash code} 631@z 632 633@x [69] str_lookup - Avoid 'uninitialized' warning. 634@!old_string:boolean; {set to |true| if it's an already encountered string} 635@y 636@z 637 638@x [69] str_lookup - Avoid 'uninitialized' warning. 639old_string := false; 640@y 641str_num := 0; {set to |>0| if it's an already encountered string} 642@z 643 644@x [71] str_lookup - Avoid 'uninitialized' warning. 645 old_string := true; 646@y 647@z 648 649@x [72] str_lookup - Avoid 'uninitialized' warning. 650if (old_string) then {it's an already encountered string} 651@y 652if (str_num>0) then {it's an already encountered string} 653@z 654 655@x [74] Pascal Web's char 656@!pds_type = packed array [pds_loc] of char; 657@y 658@!pds_type = const_cstring; 659@z 660 661@x [78] C strings start at zero instead of one. 662for i:=1 to len do 663 buffer[i] := xord[pds[i]]; 664@y 665for i:=1 to len do 666 buffer[i] := xord[ucharcast(pds[i-1])]; 667@z 668 669@x [98] Can't do this tangle-time arithmetic with file_name_size. 670@!aux_name_length : 0..file_name_size+1; {\.{.aux} name sans extension} 671@y 672@!aux_name_length : integer; 673@z 674 675@x [101] Reading the aux file name and command-line processing. 676This procedure consists of a loop that reads and processes a (nonnull) 677\.{.aux} file name. It's this module and the next two that must be 678changed on those systems using command-line arguments. Note: The 679|term_out| and |term_in| files are system dependent. 680 681@<Procedures and functions for the reading and processing of input files@>= 682procedure get_the_top_level_aux_file_name; 683label aux_found,@!aux_not_found; 684var @<Variables for possible command-line processing@>@/ 685begin 686check_cmnd_line := false; {many systems will change this} 687loop 688 begin 689 if (check_cmnd_line) then 690 @<Process a possible command line@> 691 else 692 begin 693 write (term_out,'Please type input file name (no extension)--'); 694 if (eoln(term_in)) then {so the first |read| works} 695 read_ln (term_in); 696 aux_name_length := 0; 697 while (not eoln(term_in)) do 698 begin 699 if (aux_name_length = file_name_size) then 700 begin 701 while (not eoln(term_in)) do {discard the rest of the line} 702 get(term_in); 703 sam_you_made_the_file_name_too_long; 704 end; 705 incr(aux_name_length); 706 name_of_file[aux_name_length] := term_in^; 707 get(term_in); 708 end; 709 end; 710 @<Handle this \.{.aux} name@>; 711aux_not_found: 712 check_cmnd_line := false; 713 end; 714aux_found: {now we're ready to read the \.{.aux} file} 715end; 716@y 717@<Procedures and functions for the reading and processing of input files@>= 718procedure get_the_top_level_aux_file_name; 719label aux_found,@!aux_not_found; 720begin 721 @<Process a possible command line@> 722 {Leave room for the \.., the extension, the junk byte at the 723 beginning, and the null byte at the end.} 724 name_of_file := xmalloc_array (ASCII_code, strlen (cmdline (optind)) + 5); 725 strcpy (stringcast(name_of_file + 1), cmdline (optind)); 726 aux_name_length := strlen (stringcast(name_of_file + 1)); 727 @<Handle this \.{.aux} name@>; 728aux_not_found: uexit (1); 729aux_found: {now we're ready to read the \.{.aux} file} 730end; 731@z 732 733% [101] Don't need this variable; we use argc to check if we have a 734% command line. 735@x 736@<Variables for possible command-line processing@>= 737@!check_cmnd_line : boolean; {|true| if we're to check the command line} 738@y 739@z 740 741@x [103] Get the aux file name from the command line. 742@<Process a possible command line@>= 743begin 744do_nothing; {the ``default system'' doesn't use the command line} 745end 746@y 747@<Process a possible command line@>= 748parse_arguments; 749@z 750 751% [107] Don't use a path to find the aux file, and don't add the 752% extension if it's already there. 753@x 754add_extension (s_aux_extension); {this also sets |name_length|} 755aux_ptr := 0; {initialize the \.{.aux} file stack} 756if (not a_open_in(cur_aux_file)) then 757@y 758if (name_length < 4) or 759 (strcmp (stringcast(name_of_file + 1 + name_length - 4), '.aux') <> 0) 760then 761 add_extension (s_aux_extension) {this also sets |name_length|} 762else 763 aux_name_length := aux_name_length - 4; {set to length without \.{.aux}} 764aux_ptr := 0; {initialize the \.{.aux} file stack} 765if (not kpse_in_name_ok(stringcast(name_of_file+1)) or 766 not a_open_in(cur_aux_file,no_file_path)) then 767@z 768 769@x [107] - Check log_file name. 770if (not a_open_out(log_file)) then 771@y 772if (not kpse_out_name_ok(stringcast(name_of_file+1)) or 773 not a_open_out(log_file)) then 774@z 775 776@x [107] - Check bbl_file name 777if (not a_open_out(bbl_file)) then 778@y 779if (not kpse_out_name_ok(stringcast(name_of_file+1)) or 780 not a_open_out(bbl_file)) then 781@z 782 783@x [109] Add log_pr_aux_name. 784procedure print_aux_name; 785begin 786print_pool_str (cur_aux_str); 787print_newline; 788end; 789@y 790procedure print_aux_name; 791begin 792print_pool_str (cur_aux_str); 793print_newline; 794end; 795@# 796procedure log_pr_aux_name; 797begin 798log_pr_pool_str (cur_aux_str); 799log_pr_newline; 800end; 801@z 802 803@x [111] Be silent unless verbose. 804print ('The top-level auxiliary file: '); 805print_aux_name; 806@y 807if verbose then begin 808 print ('The top-level auxiliary file: '); 809 print_aux_name; 810end 811else begin 812 log_pr ('The top-level auxiliary file: '); 813 log_pr_aux_name; 814end; 815@z 816 817@x [118] bib_list is dynamically allocated. 818@!bib_list : array[bib_number] of str_number; {the \.{.bib} file list} 819@y 820@!bib_list : ^str_number; {the \.{.bib} file list} 821@z 822@x [still 118] bib_file also. 823@!bib_file : array[bib_number] of alpha_file; {corresponding |file| variables} 824@y 825@!bib_file : ^alpha_file; {corresponding |file| variables} 826@z 827 828@x [119] max_bib_files is a variable now, so can't be used as a const. 829@!bib_number = 0..max_bib_files; {gives the |bib_list| range} 830@y 831@!bib_number = integer; {gives the |bib_list| range} 832@z 833 834@x [122] Add log_pr_bib_name. 835procedure print_bib_name; 836begin 837print_pool_str (cur_bib_str); 838print_pool_str (s_bib_extension); 839print_newline; 840end; 841@y 842procedure print_bib_name; 843begin 844print_pool_str (cur_bib_str); 845print_pool_str (s_bib_extension); 846print_newline; 847end; 848@# 849procedure log_pr_bib_name; 850begin 851log_pr_pool_str (cur_bib_str); 852log_pr_pool_str (s_bib_extension); 853log_pr_newline; 854end; 855@z 856 857@x [124] Reallocate when we run out of bib files. 858 overflow('number of database files ',max_bib_files); 859@y 860begin 861 {Keep old value of |max_bib_files| for the last array.} 862 BIB_XRETALLOC_NOSET ('bib_list', bib_list, str_number, max_bib_files, 863 max_bib_files + MAX_BIB_FILES); 864 BIB_XRETALLOC_NOSET ('bib_file', bib_file, alpha_file, max_bib_files, 865 max_bib_files + MAX_BIB_FILES); 866 BIB_XRETALLOC ('s_preamble', s_preamble, str_number, max_bib_files, 867 max_bib_files + MAX_BIB_FILES); 868end; 869@z 870 871@x [still 124] Use BIBINPUTS to search for the .bib file. 872add_extension (s_bib_extension); 873if (not a_open_in(cur_bib_file)) then 874 begin 875 add_area (s_bib_area); 876 if (not a_open_in(cur_bib_file)) then 877 open_bibdata_aux_err ('I couldn''t open database file '); 878 end; 879@y 880if (not kpse_in_name_ok(stringcast(name_of_file+1)) or 881 not a_open_in(cur_bib_file, kpse_bib_format)) then 882 open_bibdata_aux_err ('I couldn''t open database file '); 883@z 884 885@x [128] Use BSTINPUTS/TEXINPUTS to search for .bst files. 886add_extension (s_bst_extension); 887if (not a_open_in(bst_file)) then 888 begin 889 add_area (s_bst_area); 890 if (not a_open_in(bst_file)) then 891 begin 892 print ('I couldn''t open style file '); 893 print_bst_name;@/ 894 bst_str := 0; {mark as unused again} 895 aux_err_return; 896 end; 897 end; 898@y 899if (not kpse_in_name_ok(stringcast(name_of_file+1)) or 900 not a_open_in(bst_file, kpse_bst_format)) then 901 begin 902 print ('I couldn''t open style file '); 903 print_bst_name;@/ 904 bst_str := 0; {mark as unused again} 905 aux_err_return; 906 end; 907@z 908 909@x [128] Be silent unless verbose. 910print ('The style file: '); 911print_bst_name; 912@y 913if verbose then begin 914 print ('The style file: '); 915 print_bst_name; 916end 917else begin 918 log_pr ('The style file: '); 919 log_pr_bst_name; 920end; 921@z 922 923@x [129] Add log_pr_bst_name. 924procedure print_bst_name; 925begin 926print_pool_str (bst_str); 927print_pool_str (s_bst_extension); 928print_newline; 929end; 930@y 931procedure print_bst_name; 932begin 933print_pool_str (bst_str); 934print_pool_str (s_bst_extension); 935print_newline; 936end; 937@# 938procedure log_pr_bst_name; 939begin 940log_pr_pool_str (bst_str); 941log_pr_pool_str (s_bst_extension); 942log_pr_newline; 943end; 944@z 945 946@x [130] cite_list is dynamically allocated. 947@!cite_list : packed array[cite_number] of str_number; {the cite-key list} 948@y 949@!cite_list : ^str_number; {the cite-key list} 950@z 951 952@x [131] max_cites is no longer const. 953@!cite_number = 0..max_cites; {gives the |cite_list| range} 954@y 955@!cite_number = integer; {gives the |cite_list| range} 956@z 957 958@x [139] Dynamic max_cites. 959if (last_cite = max_cites) then 960 begin 961 print_pool_str (hash_text[cite_loc]); 962 print_ln (' is the key:'); 963 overflow('number of cite keys ',max_cites); 964@y 965if (last_cite = max_cites) then 966 begin 967 BIB_XRETALLOC_NOSET ('cite_list', cite_list, str_number, 968 max_cites, max_cites + MAX_CITES); 969 BIB_XRETALLOC_NOSET ('type_list', type_list, hash_ptr2, 970 max_cites, max_cites + MAX_CITES); 971 BIB_XRETALLOC_NOSET ('entry_exists', entry_exists, boolean, 972 max_cites, max_cites + MAX_CITES); 973 BIB_XRETALLOC ('cite_info', cite_info, str_number, 974 max_cites, max_cites + MAX_CITES); 975 while (last_cite < max_cites) do 976 begin 977 type_list[last_cite] := empty;@/ 978 cite_info[last_cite] := any_value; {to appeas \PASCAL's boolean evaluation} 979 incr(last_cite); 980 end; 981@z 982 983% [142] Don't pad with blanks. 984% Don't use a path to search for subsidiary aux files, either. 985@x 986while (name_ptr <= file_name_size) do {pad with blanks} 987 begin 988 name_of_file[name_ptr] := ' '; 989 incr(name_ptr); 990 end; 991if (not a_open_in(cur_aux_file)) then 992@y 993name_of_file[name_ptr] := 0; 994if (not kpse_in_name_ok(stringcast(name_of_file+1)) or 995 not a_open_in(cur_aux_file, no_file_path)) then 996@z 997 998% [152] This goto gets turned into a setjmp/longjmp by ./convert -- 999% unfortunately, it is a nonlocal goto. ekrell@ulysses.att.com 1000% implemented the conversion. 1001@x 1002buf_ptr2 := last; {to get the first input line} 1003loop 1004 begin 1005 if (not eat_bst_white_space) then {the end of the \.{.bst} file} 1006 goto bst_done; 1007 get_bst_command_and_process; 1008 end; 1009bst_done: a_close (bst_file); 1010@y 1011buf_ptr2 := last; {to get the first input line} 1012hack1; 1013 begin 1014 if (not eat_bst_white_space) then {the end of the \.{.bst} file} 1015 hack2; 1016 get_bst_command_and_process; 1017 end; 1018bst_done: a_close (bst_file); 1019@z 1020 1021% max_ent_ints and max_ent_strs are gone, max_fields is no longer const. 1022@x [161] quote_next_fn and end_of_def are Pascal consts, instead of web macros. 1023@d quote_next_fn = hash_base - 1 {special marker used in defining functions} 1024@d end_of_def = hash_max + 1 {another such special marker} 1025 1026@<Types in the outer block@>= 1027@!fn_class = 0..last_fn_class; {the \.{.bst} function classes} 1028@!wiz_fn_loc = 0..wiz_fn_space; {|wiz_defined|-function storage locations} 1029@!int_ent_loc = 0..max_ent_ints; {|int_entry_var| storage locations} 1030@!str_ent_loc = 0..max_ent_strs; {|str_entry_var| storage locations} 1031@!str_glob_loc = 0..max_glb_str_minus_1; {|str_global_var| storage locations} 1032@!field_loc = 0..max_fields; {individual field storage locations} 1033@y 1034@<Types in the outer block@>= 1035@!fn_class = 0..last_fn_class; {the \.{.bst} function classes} 1036@!wiz_fn_loc = integer; {|wiz_defined|-function storage locations} 1037@!int_ent_loc = integer; {|int_entry_var| storage locations} 1038@!str_ent_loc = integer; {|str_entry_var| storage locations} 1039@!str_glob_loc = integer; {|str_global_var| storage locations} 1040@!field_loc = integer; {individual field storage locations} 1041@z 1042 1043@x [162] max_strings=hash_size settable at runtime. 1044@!fn_type : packed array[hash_loc] of fn_class; 1045@y 1046@!fn_type : ^fn_class; 1047@z 1048 1049@x [162] Dynamically allocate wiz_functions. 1050@!wiz_functions : packed array[wiz_fn_loc] of hash_ptr2; 1051@y 1052@!wiz_functions : ^hash_ptr2; 1053@z 1054 1055% [still 162] Convert entry_ints and entry_strs to dynamically-allocated 1056% one-dimensional arrays; too bad C and Pascal lag Fortran in supporting 1057% run-time dimensioning of multidimensional arrays. Other changes that 1058% follow this one will convert every reference to entry_strs[p][q] to 1059% x_entry_strs(p)(q), the equivalent of entry_strs[p*(ent_str_size+1) + 1060% q], but hidden inside a macro to mask the addressing computation. 1061% Although WEB does not have multi-argument macros, webman.tex shows how 1062% to get the equivalent effect. 1063@x 1064@!entry_ints : array[int_ent_loc] of integer; 1065@!num_ent_ints : int_ent_loc; {the number of distinct |int_entry_var| names} 1066@!str_ent_ptr : str_ent_loc; {general |str_entry_var| location} 1067@!entry_strs : array[str_ent_loc] of 1068 packed array[0..ent_str_size] of ASCII_code; 1069@y 1070@!entry_ints : ^integer; {dynamically-allocated array} 1071@!num_ent_ints : int_ent_loc; {the number of distinct |int_entry_var| names} 1072@!str_ent_ptr : str_ent_loc; {general |str_entry_var| location} 1073@!entry_strs : ^ASCII_code; {dynamically-allocated array} 1074@z 1075 1076@x [still 162] Dynamically allocate global strings 1077@!str_glb_ptr : 0..max_glob_strs; {general |str_global_var| location} 1078@!glb_str_ptr : array[str_glob_loc] of str_number; 1079@!global_strs : array[str_glob_loc] of array[0..glob_str_size] of ASCII_code; 1080@!glb_str_end : array[str_glob_loc] of 0..glob_str_size; {end markers} 1081@!num_glb_strs : 0..max_glob_strs; {number of distinct |str_global_var| names} 1082@y 1083@!str_glb_ptr : integer; {general |str_global_var| location} 1084@!glb_str_ptr : ^str_number; 1085@!global_strs : ^ASCII_code; 1086@!glb_str_end : ^integer; {end markers} 1087@!num_glb_strs : integer; {number of distinct |str_global_var| names} 1088@z 1089 1090@x [still 162] Dynamically allocate field_info. 1091@!field_info : packed array[field_loc] of str_number; 1092@y 1093@!field_info : ^str_number; 1094@z 1095 1096@x [188] Dynamically allocate singl_function. 1097type @!fn_def_loc = 0..single_fn_space; {for a single |wiz_defined|-function} 1098var singl_function : packed array[fn_def_loc] of hash_ptr2; 1099@y 1100type @!fn_def_loc = integer; {for a single |wiz_defined|-function} 1101var singl_function : ^hash_ptr2; 1102@!single_fn_space : integer; {space allocated for this |singl_function| instance} 1103@z 1104 1105@x [still 188] Dynamically allocate singl_function. 1106begin 1107eat_bst_white_and_eof_check ('function'); 1108@y 1109begin 1110single_fn_space := SINGLE_FN_SPACE; 1111singl_function := XTALLOC (single_fn_space + 1, hash_ptr2); 1112eat_bst_white_and_eof_check ('function'); 1113@z 1114 1115@x [still 188] Dynamically allocate singl_function. 1116exit: 1117end; 1118@y 1119exit: 1120libc_free (singl_function); 1121end; 1122@z 1123 1124@x [189] Reallocate if out of single function space. 1125 singl_fn_overflow; 1126@y 1127 begin 1128 BIB_XRETALLOC ('singl_function', singl_function, hash_ptr2, 1129 single_fn_space, single_fn_space + SINGLE_FN_SPACE); 1130 end; 1131@z 1132 1133@x [still 189] Procedure |singl_fn_overflow| replaced by inline code. 1134procedure singl_fn_overflow; 1135begin 1136overflow('single function space ',single_fn_space); 1137end; 1138@y 1139@z 1140 1141@x [199] A variable named `int' is no good in C. 1142@<Procedures and functions for handling numbers, characters, and strings@>= 1143@y 1144@d int == the_int 1145@<Procedures and functions for handling numbers, characters, and strings@>= 1146@z 1147 1148@x [201] Reallocate if out of wizard space. 1149if (single_ptr + wiz_def_ptr > wiz_fn_space) then 1150 begin 1151 print (single_ptr + wiz_def_ptr : 0,': '); 1152 overflow('wizard-defined function space ',wiz_fn_space); 1153 end; 1154@y 1155while (single_ptr + wiz_def_ptr > wiz_fn_space) do 1156 begin 1157 BIB_XRETALLOC ('wiz_functions', wiz_functions, hash_ptr2, 1158 wiz_fn_space, wiz_fn_space + WIZ_FN_SPACE); 1159 end; 1160@z 1161 1162@x [217] Reallocate if out of global strings. 1163 overflow('number of string global-variables ',max_glob_strs); 1164@y 1165 begin 1166 BIB_XRETALLOC_NOSET ('glb_str_ptr', glb_str_ptr, str_number, 1167 max_glob_strs, max_glob_strs + MAX_GLOB_STRS); 1168 BIB_XRETALLOC_STRING ('global_strs', global_strs, glob_str_size, 1169 max_glob_strs, max_glob_strs + MAX_GLOB_STRS); 1170 BIB_XRETALLOC ('glb_str_end', glb_str_end, integer, 1171 max_glob_strs, max_glob_strs + MAX_GLOB_STRS); 1172 str_glb_ptr := num_glb_strs; 1173 while (str_glb_ptr < max_glob_strs) do {make new |str_global_var|s empty} 1174 begin 1175 glb_str_ptr[str_glb_ptr] := 0; 1176 glb_str_end[str_glb_ptr] := 0; 1177 incr(str_glb_ptr); 1178 end; 1179 end; 1180@z 1181 1182@x [220] undefined is now a Pascal const, instead of a web macro 1183@d undefined = hash_max + 1 {a special marker used for |type_list|} 1184@y 1185@z 1186 1187@x [220] type_list is dynamically allocated. 1188@!type_list : packed array[cite_number] of hash_ptr2; 1189@y 1190@!type_list : ^hash_ptr2; 1191@z 1192@x [220] entry_exists also. 1193@!entry_exists : packed array[cite_number] of boolean; 1194@y 1195@!entry_exists : ^boolean; 1196@z 1197@x [220] cite_info also. 1198@!cite_info : packed array[cite_number] of str_number; {extra |cite_list| info} 1199@y 1200@!cite_info : ^str_number; {extra |cite_list| info} 1201@z 1202 1203@x [225] Be silent unless verbose. 1204 print ('Database file #',bib_ptr+1:0,': '); 1205 print_bib_name;@/ 1206@y 1207 if verbose then begin 1208 print ('Database file #',bib_ptr+1:0,': '); 1209 print_bib_name; 1210 end 1211 else begin 1212 log_pr ('Database file #',bib_ptr+1:0,': '); 1213 log_pr_bib_name; 1214 end; 1215@z 1216 1217@x [227] Reallocate if out of fields. 1218procedure check_field_overflow (@!total_fields : integer); 1219begin 1220if (total_fields > max_fields) then 1221 begin 1222 print_ln (total_fields:0,' fields:'); 1223 overflow('total number of fields ',max_fields); 1224@y 1225procedure check_field_overflow (@!total_fields : integer); 1226var @!f_ptr: field_loc; 1227 @!start_fields: field_loc; 1228begin 1229if (total_fields > max_fields) then 1230 begin 1231 start_fields := max_fields; 1232 BIB_XRETALLOC ('field_info', field_info, str_number, max_fields, 1233 total_fields + MAX_FIELDS); 1234 {Initialize to |missing|.} 1235 for f_ptr := start_fields to max_fields - 1 do begin 1236 field_info[f_ptr] := missing; 1237 end; 1238@z 1239 1240@x [243] Reallocate when we run out of s_preamble's. 1241 bib_err ('You''ve exceeded ',max_bib_files:0,' preamble commands'); 1242@y 1243begin 1244 {Keep old value of |max_bib_files| for the last array.} 1245 BIB_XRETALLOC_NOSET ('bib_list', bib_list, str_number, max_bib_files, 1246 max_bib_files + MAX_BIB_FILES); 1247 BIB_XRETALLOC_NOSET ('bib_file', bib_file, alpha_file, max_bib_files, 1248 max_bib_files + MAX_BIB_FILES); 1249 BIB_XRETALLOC ('s_preamble', s_preamble, str_number, max_bib_files, 1250 max_bib_files + MAX_BIB_FILES); 1251end; 1252@z 1253 1254@x [264] Add check for fieldinfo[] overflow. 1255field_ptr := entry_cite_ptr * num_fields + fn_info[field_name_loc]; 1256@y 1257field_ptr := entry_cite_ptr * num_fields + fn_info[field_name_loc]; 1258if (field_ptr >= max_fields) then 1259 confusion ('field_info index is out of range'); 1260@z 1261 1262@x [266] Fix bug in the add_database_cite procedure. 1263check_field_overflow (num_fields*new_cite); 1264@y 1265check_field_overflow (num_fields*(new_cite+1)); 1266@z 1267 1268@x [278] Add check for fieldinfo[] overflow. 1269@<Add cross-reference information@>= 1270begin 1271@y 1272@<Add cross-reference information@>= 1273begin 1274if ((num_cites - 1) * num_fields + crossref_num >= max_fields) then 1275 confusion ('field_info index is out of range'); 1276@z 1277 1278@x [280] Add check for fieldinfo[] overflow. 1279@<Subtract cross-reference information@>= 1280begin 1281@y 1282@<Subtract cross-reference information@>= 1283begin 1284if ((num_cites - 1) * num_fields + crossref_num >= max_fields) then 1285 confusion ('field_info index is out of range'); 1286@z 1287 1288@x [286] Add check for fieldinfo[] overflow. 1289@<Slide this cite key down to its permanent spot@>= 1290begin 1291@y 1292@<Slide this cite key down to its permanent spot@>= 1293begin 1294if ((cite_xptr + 1) * num_fields > max_fields) then 1295 confusion ('field_info index is out of range'); 1296@z 1297 1298@x [288] Allocate entry_ints as needed. 1299if (num_ent_ints*num_cites > max_ent_ints) then 1300 begin 1301 print (num_ent_ints*num_cites,': '); 1302 overflow('total number of integer entry-variables ',max_ent_ints); 1303 end; 1304@y 1305entry_ints := XTALLOC ((num_ent_ints + 1) * (num_cites + 1), integer); 1306@z 1307 1308@x [289] Allocate entry_strs as needed. 1309if (num_ent_strs*num_cites > max_ent_strs) then 1310 begin 1311 print (num_ent_strs*num_cites,': '); 1312 overflow('total number of string entry-variables ',max_ent_strs); 1313 end; 1314@y 1315entry_strs := XTALLOC ((num_ent_strs + 1) * (num_cites + 1) * (ent_str_size + 1), ASCII_code); 1316@z 1317 1318@x [289] Macroize entry_strs[][]. 1319 entry_strs[str_ent_ptr][0] := end_of_string; 1320@y 1321 x_entry_strs(str_ent_ptr)(0) := end_of_string; 1322@z 1323 1324@x [291] Dynamic lit_stk_size. 1325@!lit_stack : array[lit_stk_loc] of integer; {the literal function stack} 1326@!lit_stk_type : array[lit_stk_loc] of stk_type; {their corresponding types} 1327@y 1328@!lit_stack : ^integer; {the literal function stack} 1329@!lit_stk_type : ^stk_type; {their corresponding types} 1330@z 1331 1332@x [292] Dynamic lit_stk_size. 1333@!lit_stk_loc = 0..lit_stk_size; {the stack range} 1334@y 1335@!lit_stk_loc = integer; {the stack range} 1336@z 1337 1338@x [302] Macroize entry_strs[][]. 1339 char1 := entry_strs[ptr1][char_ptr]; 1340 char2 := entry_strs[ptr2][char_ptr]; 1341@y 1342 char1 := x_entry_strs(ptr1)(char_ptr); 1343 char2 := x_entry_strs(ptr2)(char_ptr); 1344@z 1345 1346@x [308] Reallocate literal stack. 1347 overflow('literal-stack size ',lit_stk_size); 1348@y 1349 begin 1350 BIB_XRETALLOC_NOSET ('lit_stack', lit_stack, integer, 1351 lit_stk_size, lit_stk_size + LIT_STK_SIZE); 1352 BIB_XRETALLOC ('lit_stk_type', lit_stk_type, stk_type, 1353 lit_stk_size, lit_stk_size + LIT_STK_SIZE); 1354 end; 1355@z 1356 1357@x [321] Dynamic buf_size. 1358if (out_buf_length+(p_ptr2-p_ptr1) > buf_size) then 1359 overflow('output buffer size ',buf_size); 1360@y 1361while (out_buf_length+(p_ptr2-p_ptr1) > buf_size) do 1362 buffer_overflow; 1363@z 1364 1365@x [328] Add check for fieldinfo[] overflow. 1366 field_ptr := cite_ptr*num_fields + fn_info[ex_fn_loc]; 1367@y 1368 field_ptr := cite_ptr*num_fields + fn_info[ex_fn_loc]; 1369 if (field_ptr >= max_fields) then 1370 confusion ('field_info index is out of range'); 1371@z 1372 1373@x [330] Macroize entry_strs[][] 1374 while (entry_strs[str_ent_ptr][ex_buf_ptr] <> end_of_string) do 1375 {copy characters into the buffer} 1376 append_ex_buf_char (entry_strs[str_ent_ptr][ex_buf_ptr]); 1377@y 1378 while (x_entry_strs(str_ent_ptr)(ex_buf_ptr) <> end_of_string) do 1379 {copy characters into the buffer} 1380 append_ex_buf_char (x_entry_strs(str_ent_ptr)(ex_buf_ptr)); 1381@z 1382 1383@x [331] Macroize global_strs[][] 1384 append_char (global_strs[str_glb_ptr][glob_chr_ptr]); 1385@y 1386 append_char (x_global_strs(str_glb_ptr)(glob_chr_ptr)); 1387@z 1388 1389@x [335] Bug fix: remove duplicate entry. 1390build_in('width$ ',6,b_width,n_width); 1391build_in('while$ ',6,b_while,n_while); 1392build_in('width$ ',6,b_width,n_width); 1393@y 1394build_in('while$ ',6,b_while,n_while); 1395build_in('width$ ',6,b_width,n_width); 1396@z 1397 1398@x [338] s_preamble is dynamically allocated. 1399@!s_preamble : array[bib_number] of str_number; 1400@y 1401@!s_preamble : ^str_number; 1402@z 1403 1404@x [345] Dynamic buf_size. 1405@!name_tok : packed array[buf_pointer] of buf_pointer; {name-token ptr list} 1406@!name_sep_char : packed array[buf_pointer] of ASCII_code; {token-ending chars} 1407@y 1408@!name_tok : ^buf_pointer; {name-token ptr list} 1409@!name_sep_char : ^ASCII_code; {token-ending chars} 1410@z 1411 1412@x [358] Macroize entry_strs[][]. 1413 while (sp_ptr < sp_xptr1) do 1414 begin {copy characters into |entry_strs|} 1415 entry_strs[str_ent_ptr][ent_chr_ptr] := str_pool[sp_ptr]; 1416 incr(ent_chr_ptr); 1417 incr(sp_ptr); 1418 end; 1419 entry_strs[str_ent_ptr][ent_chr_ptr] := end_of_string; 1420@y 1421 while (sp_ptr < sp_xptr1) do 1422 begin {copy characters into |entry_strs|} 1423 x_entry_strs(str_ent_ptr)(ent_chr_ptr) := str_pool[sp_ptr]; 1424 incr(ent_chr_ptr); 1425 incr(sp_ptr); 1426 end; 1427 x_entry_strs(str_ent_ptr)(ent_chr_ptr) := end_of_string; 1428@z 1429 1430@x [360] Macroize global_strs[][] 1431 global_strs[str_glb_ptr][glob_chr_ptr] := str_pool[sp_ptr]; 1432@y 1433 x_global_strs(str_glb_ptr)(glob_chr_ptr) := str_pool[sp_ptr]; 1434@z 1435 1436% [389] bibtex.web has mutually exclusive tests here; Oren said he 1437% doesn't want to fix it until 1.0, since it's obviously of no practical 1438% import (or someone would have found it before GCC 2 did). Changing 1439% the second `and' to an `or' makes all but the last of multiple authors 1440% be omitted in the bbl file, so I simply removed the statement. 1441@x 1442while ((ex_buf_xptr < ex_buf_ptr) and 1443 (lex_class[ex_buf[ex_buf_ptr]] = white_space) and 1444 (lex_class[ex_buf[ex_buf_ptr]] = sep_char)) do 1445 incr(ex_buf_xptr); {this removes leading stuff} 1446@y 1447@z 1448 1449% Forgot to check for pool overflow here. Triggered by test case linked 1450% from http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=520920. 1451@x [439] 1452while (sp_ptr < sp_end) do {shift the substring} 1453@y 1454str_room(sp_end - sp_ptr); 1455while (sp_ptr < sp_end) do {shift the substring} 1456@z 1457 1458% Forgot to check for pool overflow here. Triggered by bibtex-mem.test (3). 1459@x [445] 1460if (pop_lit2 >= cmd_str_ptr) then {no shifting---merely change pointers} 1461@y 1462str_room(sp_brace_level + sp_end - sp_ptr); 1463if (pop_lit2 >= cmd_str_ptr) then {no shifting---merely change pointers} 1464@z 1465 1466% [460] Eliminate unreferenced statement label, because `undefined' is 1467% now a constant expression that is not evaluated at the Web level. If 1468% this label were ever required, it could be replaced by the constant 1469% 9997, which is not used as a statement label in BibTeX. 1470@x 1471 undefined : trace_pr ('unknown') 1472@y 1473 trace_pr ('unknown') 1474@z 1475 1476@x [461] Macroize entry_strs[][]. 1477 while (entry_strs[str_ent_ptr][ent_chr_ptr] <> end_of_string) do 1478 begin 1479 trace_pr (xchr[entry_strs[str_ent_ptr][ent_chr_ptr]]); 1480 incr(ent_chr_ptr); 1481 end; 1482@y 1483 while (x_entry_strs(str_ent_ptr)(ent_chr_ptr) <> end_of_string) do 1484 begin 1485 trace_pr (xchr[x_entry_strs(str_ent_ptr)(ent_chr_ptr)]); 1486 incr(ent_chr_ptr); 1487 end; 1488@z 1489 1490@x [463] Add check for fieldinfo[] overflow. 1491 field_ptr := cite_ptr * num_fields; 1492 field_end_ptr := field_ptr + num_fields; 1493@y 1494 field_ptr := cite_ptr * num_fields; 1495 field_end_ptr := field_ptr + num_fields; 1496 if (field_end_ptr > max_fields) then 1497 confusion ('field_info index is out of range'); 1498@z 1499 1500@x [468] System-dependent changes. 1501This section should be replaced, if necessary, by changes to the program 1502that are necessary to make \BibTeX\ work at a particular installation. 1503It is usually best to design your change file so that all changes to 1504previous sections preserve the section numbering; then everybody's version 1505will be consistent with the printed program. More extensive changes, 1506which introduce new sections, can be inserted here; then only the index 1507itself will get a new section number. 1508@y 1509@d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) 1510 1511@<Define |parse_arguments|@> = 1512procedure parse_arguments; 1513const n_options = 4; {Pascal won't count array lengths for us.} 1514var @!long_options: array[0..n_options] of getopt_struct; 1515 @!getopt_return_val: integer; 1516 @!option_index: c_int_type; 1517 @!current_option: 0..n_options; 1518begin 1519 @<Initialize the option variables@>; 1520 @<Define the option table@>; 1521 repeat 1522 getopt_return_val := getopt_long_only (argc, argv, '', long_options, 1523 address_of (option_index)); 1524 if getopt_return_val = -1 then begin 1525 {End of arguments; we exit the loop below.} ; 1526 1527 end else if getopt_return_val = "?" then begin 1528 usage (my_name); 1529 1530 end else if argument_is ('min-crossrefs') then begin 1531 min_crossrefs := atoi (optarg); 1532 1533 end else if argument_is ('help') then begin 1534 usage_help (BIBTEX_HELP, nil); 1535 1536 end else if argument_is ('version') then begin 1537 print_version_and_exit (banner, 'Oren Patashnik', nil, nil); 1538 1539 end; {Else it was a flag; |getopt| has already done the assignment.} 1540 until getopt_return_val = -1; 1541 1542 {Now |optind| is the index of first non-option on the command line. 1543 We must have one remaining argument.} 1544 if (optind + 1 <> argc) then begin 1545 write_ln (stderr, my_name, ': Need exactly one file argument.'); 1546 usage (my_name); 1547 end; 1548end; 1549 1550@ Here is the first of the options we allow. 1551@.-terse@> 1552 1553@<Define the option...@> = 1554current_option := 0; 1555long_options[0].name := 'terse'; 1556long_options[0].has_arg := 0; 1557long_options[0].flag := address_of (verbose); 1558long_options[0].val := 0; 1559incr (current_option); 1560 1561@ The global variable |verbose| determines whether or not we print 1562progress information. 1563 1564@<Glob...@> = 1565@!verbose: c_int_type; 1566 1567@ Start off |true|, to match the default behavior. 1568 1569@<Initialize the option...@> = 1570verbose := true; 1571 1572@ Here is an option to change the minimum number of cross-refs required 1573for automatic |cite_list| inclusion. 1574@.-min-crossrefs@> 1575 1576@<Define the option...@> = 1577long_options[current_option].name := 'min-crossrefs'; 1578long_options[current_option].has_arg := 1; 1579long_options[current_option].flag := 0; 1580long_options[current_option].val := 0; 1581incr (current_option); 1582 1583@ 1584@<Glob...@> = 1585@!min_crossrefs: integer; 1586 1587@ Set |min_crossrefs| to two by default, so we match the 1588documentation (\.{btxdoc.tex}). 1589 1590@<Initialize the option...@> = 1591min_crossrefs := 2; 1592 1593@ One of the standard options. 1594@.-help@> 1595 1596@<Define the option...@> = 1597long_options[current_option].name := 'help'; 1598long_options[current_option].has_arg := 0; 1599long_options[current_option].flag := 0; 1600long_options[current_option].val := 0; 1601incr (current_option); 1602 1603@ Another of the standard options. 1604@.-version@> 1605 1606@<Define the option...@> = 1607long_options[current_option].name := 'version'; 1608long_options[current_option].has_arg := 0; 1609long_options[current_option].flag := 0; 1610long_options[current_option].val := 0; 1611incr (current_option); 1612 1613@ An element with all zeros always ends the list. 1614 1615@<Define the option...@> = 1616long_options[current_option].name := 0; 1617long_options[current_option].has_arg := 0; 1618long_options[current_option].flag := 0; 1619long_options[current_option].val := 0; 1620 1621@ Determine |ent_str_size|, |glob_str_size|, and |max_strings| from the 1622environment, configuration file, or default value. Set 1623|hash_size:=max_strings|, but not less than |HASH_SIZE|. 1624 1625{|setup_bound_var| stuff adapted from \.{tex.ch}.} 1626@d setup_bound_var(#)==bound_default:=#; setup_bound_var_end 1627@d setup_bound_var_end(#)==bound_name:=#; setup_bound_var_end_end 1628@d setup_bound_var_end_end(#)== 1629 setup_bound_variable(address_of(#), bound_name, bound_default); 1630 if # < bound_default then # := bound_default 1631 1632@<Procedures and functions for about everything@>= 1633procedure setup_params; 1634var bound_default: integer; {for setup} 1635@!bound_name: const_cstring; {for setup} 1636begin kpse_set_program_name (argv[0], 'bibtex'); 1637setup_bound_var (ENT_STR_SIZE)('ent_str_size')(ent_str_size); 1638setup_bound_var (GLOB_STR_SIZE)('glob_str_size')(glob_str_size); 1639setup_bound_var (MAX_STRINGS)('max_strings')(max_strings); 1640@# 1641hash_size := max_strings; 1642if hash_size < HASH_SIZE then hash_size := HASH_SIZE; 1643hash_max := hash_size + hash_base - 1; 1644end_of_def := hash_max + 1; 1645undefined := hash_max + 1; 1646end; 1647 1648@ We use the algorithm from Knuth's \.{primes.web} to compute |hash_prime| 1649as the smallest prime number not less than 85\% of |hash_size| (and 1650|>=128|). 1651 1652@d primes == hash_next {array holding the first |k| primes} 1653@d mult == hash_text {array holding odd multiples of the first |o| primes} 1654 1655@<Procedures and functions for about everything@>= 1656procedure compute_hash_prime; 1657var hash_want: integer; {85\% of |hash_size|} 1658@!k: integer; {number of prime numbers $p_i$ in |primes|} 1659@!j: integer; {a prime number candidate} 1660@!o: integer; {number of odd multiples of primes in |mult|} 1661@!square: integer; {$p_o^2$} 1662@!n: integer; {loop index} 1663@!j_prime: boolean; {is |j| a prime?} 1664begin hash_want := (hash_size div 20) * 17; 1665j := 1; 1666k := 1; 1667hash_prime := 2; 1668primes[k] := hash_prime; 1669o := 2; 1670square := 9; 1671while hash_prime < hash_want do 1672 begin 1673 repeat 1674 j := j + 2; 1675 if j = square then 1676 begin 1677 mult[o] := j; 1678 j := j + 2; 1679 incr (o); 1680 square := primes[o] * primes[o]; 1681 end; 1682 n := 2; 1683 j_prime := true; 1684 while (n < o) and j_prime do 1685 begin 1686 while mult[n] < j do mult[n] := mult[n] + 2 * primes[n]; 1687 if mult[n] = j then j_prime := false; 1688 incr (n); 1689 end; 1690 until j_prime; 1691 incr (k); 1692 hash_prime := j; 1693 primes[k] := hash_prime; 1694 end; 1695end; 1696@z 1697