From 4a9156d0c1cad861db1b8e1bebfe9cfe56ae34c5 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 26 Sep 2023 12:52:49 -0400 Subject: [PATCH 01/23] Preamble from XBuf to Vec --- crates/engine_bibtex/src/auxi.rs | 20 ++++++++++++-------- crates/engine_bibtex/src/bibs.rs | 24 ++++++------------------ crates/engine_bibtex/src/exec.rs | 6 ++---- crates/engine_bibtex/src/lib.rs | 9 ++++----- crates/engine_bibtex/src/log.rs | 4 +--- crates/engine_bibtex/src/scan.rs | 4 +--- 6 files changed, 26 insertions(+), 41 deletions(-) diff --git a/crates/engine_bibtex/src/auxi.rs b/crates/engine_bibtex/src/auxi.rs index 8d678046c..eab1bf680 100644 --- a/crates/engine_bibtex/src/auxi.rs +++ b/crates/engine_bibtex/src/auxi.rs @@ -182,15 +182,19 @@ fn aux_bib_style_command( let name = pool.get_str(ctx.bst_str); let fname = CString::new(name).unwrap(); - let ptr = peekable_open(ctx, &fname, FileFormat::Bst); - if ptr.is_null() { - write_logs("I couldn't open style file "); - print_bst_name(ctx, pool)?; - ctx.bst_str = 0; - aux_err_print(buffers, aux, pool)?; - return Ok(()); + let bst_file = PeekableInput::open(ctx, &fname, FileFormat::Bst); + match bst_file { + Err(_) => { + write_logs("I couldn't open style file "); + print_bst_name(ctx, pool)?; + ctx.bst_str = 0; + aux_err_print(buffers, aux, pool)?; + return Ok(()); + } + Ok(file) => { + ctx.bst_file = Some(file); + } } - ctx.bst_file = NonNull::new(ptr); if ctx.config.verbose { write_logs("The style file: "); diff --git a/crates/engine_bibtex/src/bibs.rs b/crates/engine_bibtex/src/bibs.rs index ee4f39b6e..55805ac7d 100644 --- a/crates/engine_bibtex/src/bibs.rs +++ b/crates/engine_bibtex/src/bibs.rs @@ -23,8 +23,7 @@ pub(crate) struct BibData { bib_list: XBuf, bib_ptr: BibNumber, bib_line_num: i32, - preamble: XBuf, - preamble_ptr: BibNumber, + preamble: Vec, } impl BibData { @@ -34,8 +33,7 @@ impl BibData { bib_list: XBuf::new(MAX_BIB_FILES), bib_ptr: 0, bib_line_num: 0, - preamble: XBuf::new(MAX_BIB_FILES), - preamble_ptr: 0, + preamble: Vec::new(), } } @@ -75,20 +73,15 @@ impl BibData { } pub fn add_preamble(&mut self, s: StrNumber) { - self.preamble[self.preamble_ptr] = s; - self.preamble_ptr += 1; + self.preamble.push(s); } pub fn preamble_ptr(&self) -> usize { - self.preamble_ptr + self.preamble.len() } - pub fn set_preamble_ptr(&mut self, val: usize) { - self.preamble_ptr = val; - } - - pub fn cur_preamble(&self) -> StrNumber { - self.preamble[self.preamble_ptr] + pub fn preamble(&self) -> &[StrNumber] { + &self.preamble } pub fn ptr(&self) -> BibNumber { @@ -106,7 +99,6 @@ impl BibData { pub fn grow(&mut self) { self.bib_list.grow(MAX_BIB_FILES); self.bib_file.grow(MAX_BIB_FILES); - self.preamble.grow(MAX_BIB_FILES); } } @@ -225,10 +217,6 @@ pub(crate) fn get_bib_command_or_entry_and_process( match globals.hash.ilk_info(res.loc) { 0 => (), 1 => { - if globals.bibs.preamble_ptr() == globals.bibs.len() { - globals.bibs.grow(); - } - if !eat_bib_white_space(globals.buffers, globals.bibs) { eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; return Ok(()); diff --git a/crates/engine_bibtex/src/exec.rs b/crates/engine_bibtex/src/exec.rs index 4ec680e12..5436c35d6 100644 --- a/crates/engine_bibtex/src/exec.rs +++ b/crates/engine_bibtex/src/exec.rs @@ -1679,10 +1679,8 @@ fn interp_preamble( bibs: &mut BibData, ) -> Result<(), BibtexError> { let mut out = Vec::with_capacity(ctx.glbl_ctx().num_preamble_strings * 32); - bibs.set_preamble_ptr(0); - while bibs.preamble_ptr() < ctx.glbl_ctx().num_preamble_strings { - out.extend(pool.get_str(bibs.cur_preamble())); - bibs.set_preamble_ptr(bibs.preamble_ptr() + 1); + for s in bibs.preamble() { + out.extend(pool.get_str(*s)); } let s = pool.add_string_raw(&out)?; ctx.push_stack(ExecVal::String(s)); diff --git a/crates/engine_bibtex/src/lib.rs b/crates/engine_bibtex/src/lib.rs index 61efc469c..6dc8cf4a4 100644 --- a/crates/engine_bibtex/src/lib.rs +++ b/crates/engine_bibtex/src/lib.rs @@ -37,13 +37,13 @@ use crate::{ print_confusion, sam_wrong_file_name_print, write_log_file, write_logs, }, other::OtherData, - peekable::{input_ln, peekable_close, PeekableInput}, + peekable::{input_ln, PeekableInput}, pool::{pre_def_certain_strings, StringPool}, scan::eat_bst_white_space, }; use std::{ ffi::{CStr, CString}, - ptr::{self, NonNull}, + ptr, }; use tectonic_bridge_core::{ ttbc_input_close, ttbc_input_open, ttbc_output_close, ttbc_output_open, @@ -195,7 +195,7 @@ impl Default for BibtexConfig { pub(crate) struct Bibtex<'a, 'cbs> { pub engine: &'a mut CoreBridgeState<'cbs>, pub config: BibtexConfig, - pub bst_file: Option>, + pub bst_file: Option>, pub bst_str: StrNumber, pub bst_line_num: usize, @@ -335,8 +335,7 @@ pub(crate) fn bibtex_main(ctx: &mut Bibtex<'_, '_>, aux_file_name: &CStr) -> His match res { Err(BibtexError::Recover) | Ok(History::Spotless) => { // SAFETY: bst_file guaranteed valid at this point - unsafe { peekable_close(ctx, ctx.bst_file) }; - ctx.bst_file = None; + ctx.bst_file.take().map(|file| file.close(ctx)); ttbc_output_close(ctx.engine, ctx.bbl_file); } Err(BibtexError::NoBst) => { diff --git a/crates/engine_bibtex/src/log.rs b/crates/engine_bibtex/src/log.rs index fab19ef8e..2c9ff8d04 100644 --- a/crates/engine_bibtex/src/log.rs +++ b/crates/engine_bibtex/src/log.rs @@ -580,9 +580,7 @@ pub(crate) fn bst_err_print_and_look_for_blank_line( bst_ln_num_print(ctx, pool)?; print_bad_input_line(buffers); while buffers.init(BufTy::Base) != 0 { - // SAFETY: bst_file guaranteed valid - let bst_file = unsafe { ctx.bst_file.map(|mut ptr| ptr.as_mut()) }; - if !input_ln(bst_file, buffers) { + if !input_ln(ctx.bst_file.as_deref_mut(), buffers) { return Err(BibtexError::Recover); } else { ctx.bst_line_num += 1; diff --git a/crates/engine_bibtex/src/scan.rs b/crates/engine_bibtex/src/scan.rs index f6ee68a35..f6fd82023 100644 --- a/crates/engine_bibtex/src/scan.rs +++ b/crates/engine_bibtex/src/scan.rs @@ -166,9 +166,7 @@ pub(crate) fn eat_bst_white_space(ctx: &mut Bibtex<'_, '_>, buffers: &mut Global return true; } - // SAFETY: bst_file guarantee valid if non-null - let bst_file = unsafe { ctx.bst_file.map(|mut ptr| ptr.as_mut()) }; - if !input_ln(bst_file, buffers) { + if !input_ln(ctx.bst_file.as_deref_mut(), buffers) { return false; } From 2baac5aa9c7c85001a4590545805eafa3fe0b489 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 26 Sep 2023 13:22:19 -0400 Subject: [PATCH 02/23] Box up peekable, Vec in BibData --- crates/engine_bibtex/src/auxi.rs | 40 +++++++------ crates/engine_bibtex/src/bibs.rs | 86 ++++++++-------------------- crates/engine_bibtex/src/bst.rs | 23 ++------ crates/engine_bibtex/src/log.rs | 14 ++--- crates/engine_bibtex/src/peekable.rs | 36 +----------- 5 files changed, 60 insertions(+), 139 deletions(-) diff --git a/crates/engine_bibtex/src/auxi.rs b/crates/engine_bibtex/src/auxi.rs index eab1bf680..2e3e384c0 100644 --- a/crates/engine_bibtex/src/auxi.rs +++ b/crates/engine_bibtex/src/auxi.rs @@ -1,5 +1,5 @@ use crate::{ - bibs::BibData, + bibs::{BibData, BibFile}, buffer::{BufTy, GlobalBuffer}, char_info::LexClass, cite::CiteInfo, @@ -12,12 +12,12 @@ use crate::{ log_pr_bst_name, print_a_pool_str, print_a_token, print_aux_name, print_bib_name, print_confusion, print_overflow, write_log_file, write_logs, AuxTy, }, - peekable::{peekable_open, PeekableInput}, + peekable::PeekableInput, pool::StringPool, scan::Scan, Bibtex, BibtexError, GlobalItems, StrIlk, StrNumber, }; -use std::{ffi::CString, ptr::NonNull}; +use std::ffi::CString; use tectonic_bridge_core::FileFormat; const AUX_STACK_SIZE: usize = 20; @@ -101,32 +101,34 @@ fn aux_bib_data_command( return Ok(()); } - if bibs.ptr() == bibs.len() { - bibs.grow(); - } - let file = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; let res = pool.lookup_str_insert(hash, file, StrIlk::BibFile)?; - bibs.set_cur_bib(hash.text(res.loc)); if res.exists { write_logs("This database file appears more than once: "); - print_bib_name(pool, bibs)?; + print_bib_name(pool, hash.text(res.loc))?; aux_err_print(buffers, aux, pool)?; return Ok(()); } - let name = pool.get_str(bibs.cur_bib()); + let name = pool.get_str(hash.text(res.loc)); let fname = CString::new(name).unwrap(); - let bib_in = peekable_open(ctx, &fname, FileFormat::Bib); - if bib_in.is_null() { - write_logs("I couldn't open database file "); - print_bib_name(pool, bibs)?; - aux_err_print(buffers, aux, pool)?; - return Ok(()); + let bib_in = PeekableInput::open(ctx, &fname, FileFormat::Bib); + match bib_in { + Err(_) => { + write_logs("I couldn't open database file "); + print_bib_name(pool, hash.text(res.loc))?; + aux_err_print(buffers, aux, pool)?; + return Ok(()); + } + Ok(file) => { + bibs.push_file(BibFile { + name: hash.text(res.loc), + file, + line: 0, + }); + } } - bibs.set_cur_bib_file(NonNull::new(bib_in)); - bibs.set_ptr(bibs.ptr() + 1); } Ok(()) @@ -472,7 +474,7 @@ pub(crate) fn last_check_for_aux_errors( last_aux: StrNumber, ) -> Result<(), BibtexError> { cites.set_num_cites(cites.ptr()); - ctx.num_bib_files = bibs.ptr(); + ctx.num_bib_files = bibs.len(); if !ctx.citation_seen { aux_end1_err_print(); write_logs("\\citation commands"); diff --git a/crates/engine_bibtex/src/bibs.rs b/crates/engine_bibtex/src/bibs.rs index 55805ac7d..de9e10c34 100644 --- a/crates/engine_bibtex/src/bibs.rs +++ b/crates/engine_bibtex/src/bibs.rs @@ -11,65 +11,42 @@ use crate::{ peekable::{input_ln, PeekableInput}, pool::StringPool, scan::{scan_and_store_the_field_value_and_eat_white, scan_identifier, Scan, ScanRes}, - xbuf::XBuf, BibNumber, Bibtex, BibtexError, CiteNumber, GlobalItems, HashPointer, StrIlk, StrNumber, }; -use std::ptr::NonNull; -const MAX_BIB_FILES: usize = 20; +pub(crate) struct BibFile { + pub(crate) name: StrNumber, + pub(crate) file: Box, + pub(crate) line: u32, +} pub(crate) struct BibData { - bib_file: XBuf>>, - bib_list: XBuf, - bib_ptr: BibNumber, - bib_line_num: i32, + bibs: Vec, preamble: Vec, } impl BibData { pub fn new() -> BibData { BibData { - bib_file: XBuf::new(MAX_BIB_FILES), - bib_list: XBuf::new(MAX_BIB_FILES), - bib_ptr: 0, - bib_line_num: 0, + bibs: Vec::new(), preamble: Vec::new(), } } - pub fn cur_bib(&self) -> StrNumber { - self.bib_list[self.bib_ptr] - } - - pub fn set_cur_bib(&mut self, num: StrNumber) { - self.bib_list[self.bib_ptr] = num; - } - - pub fn cur_bib_file(&mut self) -> Option<&mut PeekableInput> { - match &mut self.bib_file[self.bib_ptr] { - // SAFETY: If non-null, bib files are guaranteed valid inputs - Some(r) => Some(unsafe { r.as_mut() }), - None => None, - } - } - - pub fn take_cur_bib_file(&mut self) -> Option<&mut PeekableInput> { - self.bib_file[self.bib_ptr] - .take() - // SAFETY: Contained file pointer guaranteed valid - .map(|mut ptr| unsafe { ptr.as_mut() }) + pub fn top_file(&self) -> &BibFile { + self.bibs.last().unwrap() } - pub fn set_cur_bib_file(&mut self, input: Option>) { - self.bib_file[self.bib_ptr] = input; + pub fn top_file_mut(&mut self) -> &mut BibFile { + self.bibs.last_mut().unwrap() } - pub fn line_num(&self) -> i32 { - self.bib_line_num + pub fn push_file(&mut self, file: BibFile) { + self.bibs.push(file); } - pub fn set_line_num(&mut self, val: i32) { - self.bib_line_num = val; + pub fn pop_file(&mut self) -> BibFile { + self.bibs.pop().unwrap() } pub fn add_preamble(&mut self, s: StrNumber) { @@ -84,21 +61,8 @@ impl BibData { &self.preamble } - pub fn ptr(&self) -> BibNumber { - self.bib_ptr - } - - pub fn set_ptr(&mut self, val: BibNumber) { - self.bib_ptr = val; - } - - pub fn len(&self) -> usize { - self.bib_list.len() - } - - pub fn grow(&mut self) { - self.bib_list.grow(MAX_BIB_FILES); - self.bib_file.grow(MAX_BIB_FILES); + pub fn len(&self) -> BibNumber { + self.bibs.len() } } @@ -108,12 +72,11 @@ pub(crate) fn eat_bib_white_space(buffers: &mut GlobalBuffer, bibs: &mut BibData .not_class(LexClass::Whitespace) .scan_till(buffers, init) { - let bib_file = bibs.cur_bib_file(); - if !input_ln(bib_file, buffers) { + if !input_ln(Some(&mut bibs.top_file_mut().file), buffers) { return false; } - bibs.set_line_num(bibs.line_num() + 1); + bibs.top_file_mut().line += 1; buffers.set_offset(BufTy::Base, 2, 0); init = buffers.init(BufTy::Base); } @@ -138,14 +101,13 @@ pub(crate) fn compress_bib_white( .not_class(LexClass::Whitespace) .scan_till(buffers, last) { - let bib_file = bibs.cur_bib_file(); - let res = !input_ln(bib_file, buffers); + let res = !input_ln(Some(&mut bibs.top_file_mut().file), buffers); if res { return eat_bib_print(buffers, pool, bibs, at_bib_command).map(|_| false); } - bibs.set_line_num(bibs.line_num() + 1); + bibs.top_file_mut().line += 1; buffers.set_offset(BufTy::Base, 2, 0); last = buffers.init(BufTy::Base); } @@ -166,12 +128,12 @@ pub(crate) fn get_bib_command_or_entry_and_process( let mut at_bib_command = false; let mut init = globals.buffers.init(BufTy::Base); - while !Scan::new().chars(b"@").scan_till(globals.buffers, init) { - if !input_ln(globals.bibs.cur_bib_file(), globals.buffers) { + while !Scan::new().chars(&[b'@']).scan_till(globals.buffers, init) { + if !input_ln(Some(&mut globals.bibs.top_file_mut().file), globals.buffers) { return Ok(()); } - globals.bibs.set_line_num(globals.bibs.line_num() + 1); + globals.bibs.top_file_mut().line += 1; globals.buffers.set_offset(BufTy::Base, 2, 0); init = globals.buffers.init(BufTy::Base); } diff --git a/crates/engine_bibtex/src/bst.rs b/crates/engine_bibtex/src/bst.rs index b1744fcbf..a8f7bd943 100644 --- a/crates/engine_bibtex/src/bst.rs +++ b/crates/engine_bibtex/src/bst.rs @@ -14,12 +14,10 @@ use crate::{ rs_bad_cross_reference_print, rs_nonexistent_cross_reference_error, rs_print_fn_class, write_log_file, write_logs, }, - peekable::{peekable_close, tectonic_eof}, pool::StringPool, scan::{eat_bst_white_space, scan_fn_def, scan_identifier, Scan, ScanRes}, Bibtex, BibtexError, CiteNumber, GlobalItems, HashPointer, StrIlk, }; -use std::ptr::NonNull; macro_rules! eat_bst_white { ($ctx:ident, $globals:ident, $name:literal) => { @@ -559,24 +557,22 @@ fn bst_read_command( } ctx.glbl_ctx_mut().read_performed = true; - globals.bibs.set_ptr(0); - while globals.bibs.ptr() < ctx.glbl_ctx().num_bib_files { + while globals.bibs.len() != 0 { if ctx.glbl_ctx().config.verbose { - write_logs(&format!("Database file #{}: ", globals.bibs.ptr() + 1)); - print_bib_name(globals.pool, globals.bibs)?; + write_logs(&format!("Database file #{}: ", globals.bibs.len())); + print_bib_name(globals.pool, globals.bibs.top_file().name)?; } else { - write_log_file(&format!("Database file #{}: ", globals.bibs.ptr() + 1)); + write_log_file(&format!("Database file #{}: ", globals.bibs.len())); log_pr_bib_name(globals.bibs, globals.pool)?; } - globals.bibs.set_line_num(0); globals .buffers .set_offset(BufTy::Base, 2, globals.buffers.init(BufTy::Base)); let mut cur_macro_loc = 0; let mut field_name_loc = 0; - while !tectonic_eof(globals.bibs.cur_bib_file()) { + while !globals.bibs.top_file_mut().file.eof() { get_bib_command_or_entry_and_process( ctx.glbl_ctx_mut(), globals, @@ -584,14 +580,7 @@ fn bst_read_command( &mut field_name_loc, )?; } - // SAFETY: take_cur_bib_file returns reference to which we're the last owner - unsafe { - peekable_close( - ctx.glbl_ctx_mut(), - globals.bibs.take_cur_bib_file().map(NonNull::from), - ) - }; - globals.bibs.set_ptr(globals.bibs.ptr() + 1); + globals.bibs.pop_file().file.close(ctx.glbl_ctx_mut())?; } ctx.glbl_ctx_mut().reading_completed = true; diff --git a/crates/engine_bibtex/src/log.rs b/crates/engine_bibtex/src/log.rs index 2c9ff8d04..98fea1e46 100644 --- a/crates/engine_bibtex/src/log.rs +++ b/crates/engine_bibtex/src/log.rs @@ -288,10 +288,10 @@ pub(crate) fn aux_end2_err_print(pool: &StringPool, name: StrNumber) -> Result<( Ok(()) } -pub(crate) fn print_bib_name(pool: &StringPool, bibs: &BibData) -> Result<(), BibtexError> { - print_a_pool_str(bibs.cur_bib(), pool)?; +pub(crate) fn print_bib_name(pool: &StringPool, name: StrNumber) -> Result<(), BibtexError> { + print_a_pool_str(name, pool)?; let res = pool - .try_get_str(bibs.cur_bib()) + .try_get_str(name) .map_err(|_| BibtexError::Fatal) .map(|str| str.ends_with(b".bib"))?; if !res { @@ -303,9 +303,9 @@ pub(crate) fn print_bib_name(pool: &StringPool, bibs: &BibData) -> Result<(), Bi pub(crate) fn log_pr_bib_name(bibs: &BibData, pool: &StringPool) -> Result<(), BibtexError> { with_log(|log| { - out_pool_str(pool, log, bibs.cur_bib())?; + out_pool_str(pool, log, bibs.top_file().name)?; let res = pool - .try_get_str(bibs.cur_bib()) + .try_get_str(bibs.top_file().name) .map(|str| str.ends_with(b".bib")) .map_err(|_| BibtexError::Fatal)?; if !res { @@ -378,8 +378,8 @@ pub fn bst_right_brace_print() { } pub(crate) fn bib_ln_num_print(pool: &StringPool, bibs: &BibData) -> Result<(), BibtexError> { - write_logs(&format!("--line {} of file ", bibs.line_num())); - print_bib_name(pool, bibs) + write_logs(&format!("--line {} of file ", bibs.top_file().line)); + print_bib_name(pool, bibs.top_file().name) } pub(crate) fn bib_err_print( diff --git a/crates/engine_bibtex/src/peekable.rs b/crates/engine_bibtex/src/peekable.rs index d2ead5410..d1eea0199 100644 --- a/crates/engine_bibtex/src/peekable.rs +++ b/crates/engine_bibtex/src/peekable.rs @@ -4,7 +4,7 @@ use crate::{ ttbc_input_close, ttbc_input_open, ASCIICode, Bibtex, BibtexError, BufPointer, }; use libc::EOF; -use std::{ffi::CStr, io, ptr, ptr::NonNull}; +use std::{ffi::CStr, io, ptr::NonNull}; use tectonic_bridge_core::FileFormat; use tectonic_io_base::InputHandle; @@ -78,7 +78,7 @@ impl PeekableInput { self.peek_char = c; } - fn eof(&mut self) -> bool { + pub fn eof(&mut self) -> bool { if self.saw_eof { return true; } @@ -102,38 +102,6 @@ impl PeekableInput { } } -pub(crate) fn peekable_open( - ctx: &mut Bibtex<'_, '_>, - path: &CStr, - format: FileFormat, -) -> *mut PeekableInput { - PeekableInput::open(ctx, path, format) - .map(Box::into_raw) - .unwrap_or(ptr::null_mut()) -} - -pub(crate) unsafe fn peekable_close( - ctx: &mut Bibtex<'_, '_>, - peekable: Option>, -) -> libc::c_int { - match peekable { - Some(mut peekable) => { - let rv = ttbc_input_close(ctx.engine, peekable.as_mut().handle.as_ptr()); - drop(Box::::from_raw(peekable.as_ptr())); - rv - } - None => 0, - } -} - -pub(crate) fn tectonic_eof(peekable: Option<&mut PeekableInput>) -> bool { - // Check for EOF following Pascal semantics. - match peekable { - Some(peek) => peek.eof(), - None => true, - } -} - pub(crate) fn input_ln(peekable: Option<&mut PeekableInput>, buffers: &mut GlobalBuffer) -> bool { let peekable = match peekable { Some(p) => p, From 73a3ad027b1a45e906471d4a5f4bf06f40d43b13 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 26 Sep 2023 13:25:42 -0400 Subject: [PATCH 03/23] Don't bother boxing peekable --- crates/engine_bibtex/src/auxi.rs | 2 +- crates/engine_bibtex/src/bibs.rs | 2 +- crates/engine_bibtex/src/lib.rs | 2 +- crates/engine_bibtex/src/log.rs | 2 +- crates/engine_bibtex/src/peekable.rs | 6 +++--- crates/engine_bibtex/src/scan.rs | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/engine_bibtex/src/auxi.rs b/crates/engine_bibtex/src/auxi.rs index 2e3e384c0..c133551c2 100644 --- a/crates/engine_bibtex/src/auxi.rs +++ b/crates/engine_bibtex/src/auxi.rs @@ -24,7 +24,7 @@ const AUX_STACK_SIZE: usize = 20; pub(crate) struct AuxFile { pub(crate) name: StrNumber, - pub(crate) file: Box, + pub(crate) file: PeekableInput, pub(crate) line: i32, } diff --git a/crates/engine_bibtex/src/bibs.rs b/crates/engine_bibtex/src/bibs.rs index de9e10c34..7d5345412 100644 --- a/crates/engine_bibtex/src/bibs.rs +++ b/crates/engine_bibtex/src/bibs.rs @@ -16,7 +16,7 @@ use crate::{ pub(crate) struct BibFile { pub(crate) name: StrNumber, - pub(crate) file: Box, + pub(crate) file: PeekableInput, pub(crate) line: u32, } diff --git a/crates/engine_bibtex/src/lib.rs b/crates/engine_bibtex/src/lib.rs index 6dc8cf4a4..6e172957c 100644 --- a/crates/engine_bibtex/src/lib.rs +++ b/crates/engine_bibtex/src/lib.rs @@ -195,7 +195,7 @@ impl Default for BibtexConfig { pub(crate) struct Bibtex<'a, 'cbs> { pub engine: &'a mut CoreBridgeState<'cbs>, pub config: BibtexConfig, - pub bst_file: Option>, + pub bst_file: Option, pub bst_str: StrNumber, pub bst_line_num: usize, diff --git a/crates/engine_bibtex/src/log.rs b/crates/engine_bibtex/src/log.rs index 98fea1e46..bfce0c3af 100644 --- a/crates/engine_bibtex/src/log.rs +++ b/crates/engine_bibtex/src/log.rs @@ -580,7 +580,7 @@ pub(crate) fn bst_err_print_and_look_for_blank_line( bst_ln_num_print(ctx, pool)?; print_bad_input_line(buffers); while buffers.init(BufTy::Base) != 0 { - if !input_ln(ctx.bst_file.as_deref_mut(), buffers) { + if !input_ln(ctx.bst_file.as_mut(), buffers) { return Err(BibtexError::Recover); } else { ctx.bst_line_num += 1; diff --git a/crates/engine_bibtex/src/peekable.rs b/crates/engine_bibtex/src/peekable.rs index d1eea0199..25b679f25 100644 --- a/crates/engine_bibtex/src/peekable.rs +++ b/crates/engine_bibtex/src/peekable.rs @@ -22,16 +22,16 @@ impl PeekableInput { ctx: &mut Bibtex<'_, '_>, path: &CStr, format: FileFormat, - ) -> Result, BibtexError> { + ) -> Result { // SAFETY: Our CStr is valid for the length of the call, so this can't access bad memory let handle = unsafe { ttbc_input_open(ctx.engine, path.as_ptr(), format, 0) }; if let Some(handle) = NonNull::new(handle) { - Ok(Box::new(PeekableInput { + Ok(PeekableInput { handle, peek_char: EOF, saw_eof: false, - })) + }) } else { Err(BibtexError::Fatal) } diff --git a/crates/engine_bibtex/src/scan.rs b/crates/engine_bibtex/src/scan.rs index f6fd82023..689cfee59 100644 --- a/crates/engine_bibtex/src/scan.rs +++ b/crates/engine_bibtex/src/scan.rs @@ -166,7 +166,7 @@ pub(crate) fn eat_bst_white_space(ctx: &mut Bibtex<'_, '_>, buffers: &mut Global return true; } - if !input_ln(ctx.bst_file.as_deref_mut(), buffers) { + if !input_ln(ctx.bst_file.as_mut(), buffers) { return false; } From 6c5f39080926c5430bef99557688efe8bea169ac Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 26 Sep 2023 16:10:59 -0400 Subject: [PATCH 04/23] Simplify all files into `File` type --- crates/engine_bibtex/src/auxi.rs | 44 +++++++++++++--------------- crates/engine_bibtex/src/bibs.rs | 28 +++++++----------- crates/engine_bibtex/src/bst.rs | 1 - crates/engine_bibtex/src/exec.rs | 16 +++++----- crates/engine_bibtex/src/lib.rs | 32 +++++++++----------- crates/engine_bibtex/src/log.rs | 6 ++-- crates/engine_bibtex/src/peekable.rs | 7 +---- crates/engine_bibtex/src/scan.rs | 4 +-- 8 files changed, 59 insertions(+), 79 deletions(-) diff --git a/crates/engine_bibtex/src/auxi.rs b/crates/engine_bibtex/src/auxi.rs index c133551c2..e45746269 100644 --- a/crates/engine_bibtex/src/auxi.rs +++ b/crates/engine_bibtex/src/auxi.rs @@ -1,5 +1,5 @@ use crate::{ - bibs::{BibData, BibFile}, + bibs::BibData, buffer::{BufTy, GlobalBuffer}, char_info::LexClass, cite::CiteInfo, @@ -15,21 +15,15 @@ use crate::{ peekable::PeekableInput, pool::StringPool, scan::Scan, - Bibtex, BibtexError, GlobalItems, StrIlk, StrNumber, + Bibtex, BibtexError, File, GlobalItems, StrIlk, StrNumber, }; use std::ffi::CString; use tectonic_bridge_core::FileFormat; const AUX_STACK_SIZE: usize = 20; -pub(crate) struct AuxFile { - pub(crate) name: StrNumber, - pub(crate) file: PeekableInput, - pub(crate) line: i32, -} - pub(crate) struct AuxData { - aux: Vec, + aux: Vec, } impl AuxData { @@ -37,20 +31,20 @@ impl AuxData { AuxData { aux: Vec::new() } } - pub fn push_file(&mut self, file: AuxFile) { + pub fn push_file(&mut self, file: File) { self.aux.push(file); } - pub fn pop_file(&mut self) -> (AuxFile, bool) { + pub fn pop_file(&mut self) -> (File, bool) { let out = self.aux.pop().unwrap(); (out, self.aux.is_empty()) } - pub fn top_file(&self) -> &AuxFile { + pub fn top_file(&self) -> &File { self.aux.last().unwrap() } - pub fn top_file_mut(&mut self) -> &mut AuxFile { + pub fn top_file_mut(&mut self) -> &mut File { self.aux.last_mut().unwrap() } @@ -122,7 +116,7 @@ fn aux_bib_data_command( return Ok(()); } Ok(file) => { - bibs.push_file(BibFile { + bibs.push_file(File { name: hash.text(res.loc), file, line: 0, @@ -175,32 +169,35 @@ fn aux_bib_style_command( let file = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; let res = pool.lookup_str_insert(hash, file, StrIlk::BstFile)?; - ctx.bst_str = hash.text(res.loc); if res.exists { write_logs("Already encountered style file"); print_confusion(); return Err(BibtexError::Fatal); } - let name = pool.get_str(ctx.bst_str); + let name = pool.get_str(hash.text(res.loc)); let fname = CString::new(name).unwrap(); let bst_file = PeekableInput::open(ctx, &fname, FileFormat::Bst); match bst_file { Err(_) => { write_logs("I couldn't open style file "); - print_bst_name(ctx, pool)?; - ctx.bst_str = 0; + print_bst_name(pool, hash.text(res.loc))?; + ctx.bst = None; aux_err_print(buffers, aux, pool)?; return Ok(()); } Ok(file) => { - ctx.bst_file = Some(file); + ctx.bst = Some(File { + name: hash.text(res.loc), + file, + line: 0, + }); } } if ctx.config.verbose { write_logs("The style file: "); - print_bst_name(ctx, pool)?; + print_bst_name(pool, ctx.bst.as_ref().unwrap().name)?; } else { write_log_file("The style file: "); log_pr_bst_name(ctx, pool)?; @@ -384,7 +381,7 @@ fn aux_input_command( return Ok(()); } Ok(file) => { - aux.push_file(AuxFile { + aux.push_file(File { name: hash.text(res.loc), file, line: 0, @@ -474,7 +471,6 @@ pub(crate) fn last_check_for_aux_errors( last_aux: StrNumber, ) -> Result<(), BibtexError> { cites.set_num_cites(cites.ptr()); - ctx.num_bib_files = bibs.len(); if !ctx.citation_seen { aux_end1_err_print(); write_logs("\\citation commands"); @@ -489,7 +485,7 @@ pub(crate) fn last_check_for_aux_errors( aux_end1_err_print(); write_logs("\\bibdata command"); aux_end2_err_print(pool, last_aux)?; - } else if ctx.num_bib_files == 0 { + } else if bibs.len() == 0 { aux_end1_err_print(); write_logs("database files"); aux_end2_err_print(pool, last_aux)?; @@ -499,7 +495,7 @@ pub(crate) fn last_check_for_aux_errors( aux_end1_err_print(); write_logs("\\bibstyle command"); aux_end2_err_print(pool, last_aux)?; - } else if ctx.bst_str == 0 { + } else if ctx.bst.is_none() { aux_end1_err_print(); write_logs("style file"); aux_end2_err_print(pool, last_aux)?; diff --git a/crates/engine_bibtex/src/bibs.rs b/crates/engine_bibtex/src/bibs.rs index 7d5345412..ef8f0c591 100644 --- a/crates/engine_bibtex/src/bibs.rs +++ b/crates/engine_bibtex/src/bibs.rs @@ -8,20 +8,14 @@ use crate::{ bib_one_of_two_print, bib_warn_print, cite_key_disappeared_confusion, eat_bib_print, hash_cite_confusion, print_a_token, print_confusion, write_log_file, write_logs, }, - peekable::{input_ln, PeekableInput}, + peekable::input_ln, pool::StringPool, scan::{scan_and_store_the_field_value_and_eat_white, scan_identifier, Scan, ScanRes}, - BibNumber, Bibtex, BibtexError, CiteNumber, GlobalItems, HashPointer, StrIlk, StrNumber, + BibNumber, Bibtex, BibtexError, CiteNumber, File, GlobalItems, HashPointer, StrIlk, StrNumber, }; -pub(crate) struct BibFile { - pub(crate) name: StrNumber, - pub(crate) file: PeekableInput, - pub(crate) line: u32, -} - pub(crate) struct BibData { - bibs: Vec, + bibs: Vec, preamble: Vec, } @@ -33,19 +27,19 @@ impl BibData { } } - pub fn top_file(&self) -> &BibFile { + pub fn top_file(&self) -> &File { self.bibs.last().unwrap() } - pub fn top_file_mut(&mut self) -> &mut BibFile { + pub fn top_file_mut(&mut self) -> &mut File { self.bibs.last_mut().unwrap() } - pub fn push_file(&mut self, file: BibFile) { + pub fn push_file(&mut self, file: File) { self.bibs.push(file); } - pub fn pop_file(&mut self) -> BibFile { + pub fn pop_file(&mut self) -> File { self.bibs.pop().unwrap() } @@ -53,7 +47,7 @@ impl BibData { self.preamble.push(s); } - pub fn preamble_ptr(&self) -> usize { + pub fn preamble_len(&self) -> usize { self.preamble.len() } @@ -72,7 +66,7 @@ pub(crate) fn eat_bib_white_space(buffers: &mut GlobalBuffer, bibs: &mut BibData .not_class(LexClass::Whitespace) .scan_till(buffers, init) { - if !input_ln(Some(&mut bibs.top_file_mut().file), buffers) { + if !input_ln(&mut bibs.top_file_mut().file, buffers) { return false; } @@ -101,7 +95,7 @@ pub(crate) fn compress_bib_white( .not_class(LexClass::Whitespace) .scan_till(buffers, last) { - let res = !input_ln(Some(&mut bibs.top_file_mut().file), buffers); + let res = !input_ln(&mut bibs.top_file_mut().file, buffers); if res { return eat_bib_print(buffers, pool, bibs, at_bib_command).map(|_| false); @@ -129,7 +123,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( let mut init = globals.buffers.init(BufTy::Base); while !Scan::new().chars(&[b'@']).scan_till(globals.buffers, init) { - if !input_ln(Some(&mut globals.bibs.top_file_mut().file), globals.buffers) { + if !input_ln(&mut globals.bibs.top_file_mut().file, globals.buffers) { return Ok(()); } diff --git a/crates/engine_bibtex/src/bst.rs b/crates/engine_bibtex/src/bst.rs index a8f7bd943..07b09c6e3 100644 --- a/crates/engine_bibtex/src/bst.rs +++ b/crates/engine_bibtex/src/bst.rs @@ -585,7 +585,6 @@ fn bst_read_command( ctx.glbl_ctx_mut().reading_completed = true; globals.cites.set_num_cites(globals.cites.ptr()); - ctx.glbl_ctx_mut().num_preamble_strings = globals.bibs.preamble_ptr(); let cites = match globals.cites.num_cites() { 0 => 0, diff --git a/crates/engine_bibtex/src/exec.rs b/crates/engine_bibtex/src/exec.rs index 5436c35d6..be790a92c 100644 --- a/crates/engine_bibtex/src/exec.rs +++ b/crates/engine_bibtex/src/exec.rs @@ -218,15 +218,15 @@ pub(crate) fn bst_ln_num_print( glbl_ctx: &Bibtex<'_, '_>, pool: &StringPool, ) -> Result<(), BibtexError> { - write_logs(&format!("--line {} of file ", glbl_ctx.bst_line_num)); - print_bst_name(glbl_ctx, pool) + write_logs(&format!( + "--line {} of file ", + glbl_ctx.bst.as_ref().unwrap().line + )); + print_bst_name(pool, glbl_ctx.bst.as_ref().unwrap().name) } -pub(crate) fn print_bst_name( - glbl_ctx: &Bibtex<'_, '_>, - pool: &StringPool, -) -> Result<(), BibtexError> { - print_a_pool_str(glbl_ctx.bst_str, pool)?; +pub(crate) fn print_bst_name(pool: &StringPool, name: StrNumber) -> Result<(), BibtexError> { + print_a_pool_str(name, pool)?; write_logs(".bst\n"); Ok(()) } @@ -1678,7 +1678,7 @@ fn interp_preamble( pool: &mut StringPool, bibs: &mut BibData, ) -> Result<(), BibtexError> { - let mut out = Vec::with_capacity(ctx.glbl_ctx().num_preamble_strings * 32); + let mut out = Vec::with_capacity(bibs.preamble_len() * 32); for s in bibs.preamble() { out.extend(pool.get_str(*s)); } diff --git a/crates/engine_bibtex/src/lib.rs b/crates/engine_bibtex/src/lib.rs index 6e172957c..154bb0865 100644 --- a/crates/engine_bibtex/src/lib.rs +++ b/crates/engine_bibtex/src/lib.rs @@ -19,9 +19,7 @@ //! [`tectonic`]: https://docs.rs/tectonic/ use crate::{ - auxi::{ - get_aux_command_and_process, last_check_for_aux_errors, pop_the_aux_stack, AuxData, AuxFile, - }, + auxi::{get_aux_command_and_process, last_check_for_aux_errors, pop_the_aux_stack, AuxData}, bibs::BibData, bst::get_bst_command_and_process, buffer::{BufTy, GlobalBuffer}, @@ -165,6 +163,12 @@ const _: () = assert!(hash::HASH_PRIME <= hash::HASH_SIZE); const _: () = assert!(pool::MAX_STRINGS <= hash::HASH_SIZE); const _: () = assert!(cite::MAX_CITES <= pool::MAX_STRINGS); +pub(crate) struct File { + name: StrNumber, + file: PeekableInput, + line: u32, +} + pub(crate) struct GlobalItems<'a> { buffers: &'a mut GlobalBuffer, pool: &'a mut StringPool, @@ -195,15 +199,12 @@ impl Default for BibtexConfig { pub(crate) struct Bibtex<'a, 'cbs> { pub engine: &'a mut CoreBridgeState<'cbs>, pub config: BibtexConfig, - pub bst_file: Option, - pub bst_str: StrNumber, - pub bst_line_num: usize, + + pub bst: Option, pub bbl_file: *mut OutputHandle, pub bbl_line_num: usize, - pub num_bib_files: usize, - pub num_preamble_strings: usize, pub impl_fn_num: usize, pub cite_xptr: usize, @@ -230,13 +231,9 @@ impl<'a, 'cbs> Bibtex<'a, 'cbs> { Bibtex { engine, config, - bst_file: None, - bst_str: 0, - bst_line_num: 0, + bst: None, bbl_file: ptr::null_mut(), bbl_line_num: 0, - num_bib_files: 0, - num_preamble_strings: 0, impl_fn_num: 0, cite_xptr: 0, bib_seen: false, @@ -335,7 +332,7 @@ pub(crate) fn bibtex_main(ctx: &mut Bibtex<'_, '_>, aux_file_name: &CStr) -> His match res { Err(BibtexError::Recover) | Ok(History::Spotless) => { // SAFETY: bst_file guaranteed valid at this point - ctx.bst_file.take().map(|file| file.close(ctx)); + ctx.bst.take().map(|file| file.file.close(ctx)); ttbc_output_close(ctx.engine, ctx.bbl_file); } Err(BibtexError::NoBst) => { @@ -407,7 +404,7 @@ pub(crate) fn inner_bibtex_main( let last_aux = loop { globals.aux.top_file_mut().line += 1; - if !input_ln(Some(&mut globals.aux.top_file_mut().file), globals.buffers) { + if !input_ln(&mut globals.aux.top_file_mut().file, globals.buffers) { if let Some(last) = pop_the_aux_stack(ctx, globals.aux) { break last; } @@ -418,11 +415,10 @@ pub(crate) fn inner_bibtex_main( last_check_for_aux_errors(ctx, globals.pool, globals.cites, globals.bibs, last_aux)?; - if ctx.bst_str == 0 { + if ctx.bst.is_none() { return Err(BibtexError::NoBst); } - ctx.bst_line_num = 0; ctx.bbl_line_num = 1; globals .buffers @@ -489,7 +485,7 @@ pub(crate) fn get_the_top_level_aux_file_name( Err(_) => return Err(BibtexError::Fatal), }; - aux.push_file(AuxFile { + aux.push_file(File { name: hash.text(lookup.loc), file: aux_file, line: 0, diff --git a/crates/engine_bibtex/src/log.rs b/crates/engine_bibtex/src/log.rs index bfce0c3af..0280573d5 100644 --- a/crates/engine_bibtex/src/log.rs +++ b/crates/engine_bibtex/src/log.rs @@ -319,7 +319,7 @@ pub(crate) fn log_pr_bib_name(bibs: &BibData, pool: &StringPool) -> Result<(), B pub(crate) fn log_pr_bst_name(ctx: &Bibtex<'_, '_>, pool: &StringPool) -> Result<(), BibtexError> { with_log(|log| { // TODO: This call can panic if bst_str doesn't exist - out_pool_str(pool, log, ctx.bst_str)?; + out_pool_str(pool, log, ctx.bst.as_ref().unwrap().name)?; writeln!(log, ".bst").unwrap(); Ok(()) }) @@ -580,10 +580,10 @@ pub(crate) fn bst_err_print_and_look_for_blank_line( bst_ln_num_print(ctx, pool)?; print_bad_input_line(buffers); while buffers.init(BufTy::Base) != 0 { - if !input_ln(ctx.bst_file.as_mut(), buffers) { + if !input_ln(&mut ctx.bst.as_mut().unwrap().file, buffers) { return Err(BibtexError::Recover); } else { - ctx.bst_line_num += 1; + ctx.bst.as_mut().unwrap().line += 1; } } buffers.set_offset(BufTy::Base, 2, buffers.init(BufTy::Base)); diff --git a/crates/engine_bibtex/src/peekable.rs b/crates/engine_bibtex/src/peekable.rs index 25b679f25..a3402612f 100644 --- a/crates/engine_bibtex/src/peekable.rs +++ b/crates/engine_bibtex/src/peekable.rs @@ -102,12 +102,7 @@ impl PeekableInput { } } -pub(crate) fn input_ln(peekable: Option<&mut PeekableInput>, buffers: &mut GlobalBuffer) -> bool { - let peekable = match peekable { - Some(p) => p, - None => return false, - }; - +pub(crate) fn input_ln(peekable: &mut PeekableInput, buffers: &mut GlobalBuffer) -> bool { buffers.set_init(BufTy::Base, 0); let mut last = 0; if peekable.eof() { diff --git a/crates/engine_bibtex/src/scan.rs b/crates/engine_bibtex/src/scan.rs index 689cfee59..0ee6eb361 100644 --- a/crates/engine_bibtex/src/scan.rs +++ b/crates/engine_bibtex/src/scan.rs @@ -166,11 +166,11 @@ pub(crate) fn eat_bst_white_space(ctx: &mut Bibtex<'_, '_>, buffers: &mut Global return true; } - if !input_ln(ctx.bst_file.as_mut(), buffers) { + if !input_ln(&mut ctx.bst.as_mut().unwrap().file, buffers) { return false; } - ctx.bst_line_num += 1; + ctx.bst.as_mut().unwrap().line += 1; buffers.set_offset(BufTy::Base, 2, 0); } } From 0d70cb7dad2b469f146a464c1bc2d5d618e1949d Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 26 Sep 2023 16:24:24 -0400 Subject: [PATCH 05/23] Fns use Vec now --- crates/engine_bibtex/src/lib.rs | 1 - crates/engine_bibtex/src/other.rs | 27 +++++++-------------------- crates/engine_bibtex/src/scan.rs | 7 ++----- 3 files changed, 9 insertions(+), 26 deletions(-) diff --git a/crates/engine_bibtex/src/lib.rs b/crates/engine_bibtex/src/lib.rs index 154bb0865..6410fd103 100644 --- a/crates/engine_bibtex/src/lib.rs +++ b/crates/engine_bibtex/src/lib.rs @@ -298,7 +298,6 @@ type BufPointer = usize; type PoolPointer = usize; type HashPointer = usize; type BibNumber = usize; -type WizFnLoc = usize; type FieldLoc = usize; type FnDefLoc = usize; diff --git a/crates/engine_bibtex/src/other.rs b/crates/engine_bibtex/src/other.rs index 61bb92265..6fc823652 100644 --- a/crates/engine_bibtex/src/other.rs +++ b/crates/engine_bibtex/src/other.rs @@ -1,11 +1,9 @@ -use crate::{xbuf::XBuf, FieldLoc, FnDefLoc, HashPointer, StrNumber, WizFnLoc}; +use crate::{xbuf::XBuf, FieldLoc, HashPointer, StrNumber}; -const WIZ_FN_SPACE: usize = 3000; const MAX_FIELDS: usize = 17250; pub(crate) struct OtherData { - wiz_functions: XBuf, - wiz_def_ptr: WizFnLoc, + wiz_functions: Vec, field_info: XBuf, num_fields: FieldLoc, num_pre_defined_fields: FieldLoc, @@ -15,8 +13,7 @@ pub(crate) struct OtherData { impl OtherData { pub fn new() -> OtherData { OtherData { - wiz_functions: XBuf::new(WIZ_FN_SPACE), - wiz_def_ptr: 0, + wiz_functions: Vec::new(), field_info: XBuf::new(MAX_FIELDS), num_fields: 0, num_pre_defined_fields: 0, @@ -70,21 +67,11 @@ impl OtherData { self.wiz_functions[pos] } - pub fn set_wiz_function(&mut self, pos: usize, val: HashPointer) { - self.wiz_functions[pos] = val + pub fn push_wiz_func(&mut self, val: HashPointer) { + self.wiz_functions.push(val) } - pub fn wiz_def_ptr(&self) -> WizFnLoc { - self.wiz_def_ptr - } - - pub fn set_wiz_def_ptr(&mut self, ptr: WizFnLoc) { - self.wiz_def_ptr = ptr; - } - - pub fn check_wiz_overflow(&mut self, ptr: FnDefLoc) { - while ptr + self.wiz_def_ptr > self.wiz_functions.len() { - self.wiz_functions.grow(WIZ_FN_SPACE) - } + pub fn wiz_func_len(&self) -> usize { + self.wiz_functions.len() } } diff --git a/crates/engine_bibtex/src/scan.rs b/crates/engine_bibtex/src/scan.rs index 0ee6eb361..ce162643c 100644 --- a/crates/engine_bibtex/src/scan.rs +++ b/crates/engine_bibtex/src/scan.rs @@ -366,13 +366,10 @@ pub(crate) fn scan_fn_def( single_function.push(HashData::end_of_def()); - other.check_wiz_overflow(single_function.len()); - hash.set_ilk_info(fn_hash_loc, other.wiz_def_ptr() as i32); + hash.set_ilk_info(fn_hash_loc, other.wiz_func_len() as i32); for ptr in single_function { - let wiz_ptr = other.wiz_def_ptr(); - other.set_wiz_function(wiz_ptr, ptr); - other.set_wiz_def_ptr(wiz_ptr + 1); + other.push_wiz_func(ptr); } buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); From 0883e381fef0342ede5bc0a10f6479d0a57ba0c1 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 20 Feb 2024 21:26:30 -0800 Subject: [PATCH 06/23] Migrate fully to Vec, remove XBuf --- crates/engine_bibtex/src/buffer.rs | 21 ++--- crates/engine_bibtex/src/cite.rs | 29 +++--- crates/engine_bibtex/src/entries.rs | 19 ++-- crates/engine_bibtex/src/global.rs | 25 +++-- crates/engine_bibtex/src/hash.rs | 29 +++--- crates/engine_bibtex/src/lib.rs | 16 ---- crates/engine_bibtex/src/other.rs | 9 +- crates/engine_bibtex/src/pool.rs | 11 +-- crates/engine_bibtex/src/xbuf.rs | 137 ---------------------------- 9 files changed, 70 insertions(+), 226 deletions(-) delete mode 100644 crates/engine_bibtex/src/xbuf.rs diff --git a/crates/engine_bibtex/src/buffer.rs b/crates/engine_bibtex/src/buffer.rs index 9b4fc836b..016bf69d3 100644 --- a/crates/engine_bibtex/src/buffer.rs +++ b/crates/engine_bibtex/src/buffer.rs @@ -1,30 +1,27 @@ -use crate::{ - xbuf::{SafelyZero, XBuf}, - ASCIICode, BufPointer, -}; +use crate::{ASCIICode, BufPointer}; use std::slice; pub(crate) const BUF_SIZE: usize = 20000; -struct Buffer { - ptr: XBuf, +struct Buffer { + ptr: Vec, /// Stateful offsets into the buffer offset: [BufPointer; N], /// Initialized length of the buffer init: BufPointer, } -impl Buffer { +impl Buffer { fn new(len: usize) -> Buffer { Buffer { - ptr: XBuf::new(len), + ptr: vec![T::default(); len], offset: [0; N], init: 0, } } fn grow(&mut self, new_len: usize) { - self.ptr.grow(new_len); + self.ptr.resize(self.ptr.len() + new_len, T::default()); } } @@ -36,7 +33,7 @@ pub(crate) struct GlobalBuffer { ex_buf: Buffer, out_buf: Buffer, name_sep_char: Buffer, - name_tok: XBuf, + name_tok: Vec, } impl GlobalBuffer { @@ -49,7 +46,7 @@ impl GlobalBuffer { ex_buf: Buffer::new(buf_len), out_buf: Buffer::new(buf_len), name_sep_char: Buffer::new(buf_len), - name_tok: XBuf::new(buf_len), + name_tok: vec![0; buf_len], } } @@ -194,7 +191,7 @@ impl GlobalBuffer { self.ex_buf.grow(BUF_SIZE); self.out_buf.grow(BUF_SIZE); self.name_sep_char.grow(BUF_SIZE); - self.name_tok.grow(BUF_SIZE); + self.name_tok.resize(self.name_tok.len() + BUF_SIZE, 0); self.buf_len = new_len; } } diff --git a/crates/engine_bibtex/src/cite.rs b/crates/engine_bibtex/src/cite.rs index 98726c6d9..e1ac66c05 100644 --- a/crates/engine_bibtex/src/cite.rs +++ b/crates/engine_bibtex/src/cite.rs @@ -1,5 +1,5 @@ use crate::{ - entries::EntryData, hash::HashData, other::OtherData, pool::StringPool, xbuf::XBuf, CiteNumber, + entries::EntryData, hash::HashData, other::OtherData, pool::StringPool, CiteNumber, FindCiteLocs, HashPointer, StrIlk, StrNumber, }; use std::{cmp::Ordering, ops::IndexMut}; @@ -7,10 +7,10 @@ use std::{cmp::Ordering, ops::IndexMut}; pub(crate) const MAX_CITES: usize = 750; pub(crate) struct CiteInfo { - cite_list: XBuf, - cite_info: XBuf, - type_list: XBuf, - entry_exists: XBuf, + cite_list: Vec, + cite_info: Vec, + type_list: Vec, + entry_exists: Vec, cite_ptr: CiteNumber, entry_cite_ptr: CiteNumber, @@ -22,10 +22,10 @@ pub(crate) struct CiteInfo { impl CiteInfo { pub fn new() -> CiteInfo { CiteInfo { - cite_list: XBuf::new(MAX_CITES), - cite_info: XBuf::new(MAX_CITES), - type_list: XBuf::new(MAX_CITES), - entry_exists: XBuf::new(MAX_CITES), + cite_list: vec![0; MAX_CITES], + cite_info: vec![0; MAX_CITES], + type_list: vec![0; MAX_CITES], + entry_exists: vec![false; MAX_CITES], cite_ptr: 0, entry_cite_ptr: 0, num_cites: 0, @@ -35,10 +35,11 @@ impl CiteInfo { } pub fn grow(&mut self) { - self.cite_list.grow(MAX_CITES); - self.cite_info.grow(MAX_CITES); - self.type_list.grow(MAX_CITES); - self.entry_exists.grow(MAX_CITES); + self.cite_list.resize(self.cite_list.len() + MAX_CITES, 0); + self.cite_info.resize(self.cite_info.len() + MAX_CITES, 0); + self.type_list.resize(self.type_list.len() + MAX_CITES, 0); + self.entry_exists + .resize(self.entry_exists.len() + MAX_CITES, false); } pub fn get_cite(&self, offset: usize) -> StrNumber { @@ -119,7 +120,7 @@ impl CiteInfo { pub fn sort_info(&mut self, entries: &EntryData, r: I) where - [usize]: IndexMut, + Vec: IndexMut, { self.cite_info[r].sort_by(|a, b| less_than(entries, a, b)) } diff --git a/crates/engine_bibtex/src/entries.rs b/crates/engine_bibtex/src/entries.rs index 2bcc39ace..8bf9088e3 100644 --- a/crates/engine_bibtex/src/entries.rs +++ b/crates/engine_bibtex/src/entries.rs @@ -1,4 +1,4 @@ -use crate::{cite::CiteInfo, xbuf::XBuf, ASCIICode}; +use crate::{cite::CiteInfo, ASCIICode}; pub(crate) const ENT_STR_SIZE: usize = 250; @@ -6,8 +6,8 @@ pub(crate) struct EntryData { num_entry_ints: usize, num_entry_strs: usize, sort_key_num: usize, - entry_ints: Option>, - entry_strs: Option>, + entry_ints: Option>, + entry_strs: Option>, } impl EntryData { @@ -74,11 +74,12 @@ impl EntryData { pub fn init_entries(&mut self, cites: &CiteInfo) { let num_cites = cites.num_cites(); - self.entry_ints = Some(XBuf::new((self.num_entry_ints + 1) * (num_cites + 1))); - - let mut new_buf = - XBuf::new((self.num_entry_strs + 1) * (num_cites + 1) * (ENT_STR_SIZE + 1)); - new_buf.fill(127); - self.entry_strs = Some(new_buf); + self.entry_ints = Some(vec![0; (self.num_entry_ints + 1) * (num_cites + 1)]); + self.entry_strs = Some(vec![ + 127; + (self.num_entry_strs + 1) + * (num_cites + 1) + * (ENT_STR_SIZE + 1) + ]); } } diff --git a/crates/engine_bibtex/src/global.rs b/crates/engine_bibtex/src/global.rs index 939fe53e1..a2087abbe 100644 --- a/crates/engine_bibtex/src/global.rs +++ b/crates/engine_bibtex/src/global.rs @@ -1,29 +1,34 @@ -use crate::{xbuf::XBuf, ASCIICode, StrNumber}; +use crate::{ASCIICode, StrNumber}; const MAX_GLOB_STRS: usize = 10; pub(crate) const GLOB_STR_SIZE: usize = 20000; pub(crate) struct GlobalData { - glb_bib_str_ptr: XBuf, - global_strs: XBuf, - glb_str_end: XBuf, + glb_bib_str_ptr: Vec, + global_strs: Vec, + glb_str_end: Vec, num_glb_strs: i32, } impl GlobalData { pub fn new() -> GlobalData { GlobalData { - glb_bib_str_ptr: XBuf::new(MAX_GLOB_STRS), - global_strs: XBuf::new((GLOB_STR_SIZE + 1) * MAX_GLOB_STRS), - glb_str_end: XBuf::new(MAX_GLOB_STRS), + glb_bib_str_ptr: vec![0; MAX_GLOB_STRS], + global_strs: vec![0; (GLOB_STR_SIZE + 1) * MAX_GLOB_STRS], + glb_str_end: vec![0; MAX_GLOB_STRS], num_glb_strs: 0, } } pub fn grow(&mut self) { - self.glb_bib_str_ptr.grow(MAX_GLOB_STRS); - self.global_strs.grow((GLOB_STR_SIZE + 1) * MAX_GLOB_STRS); - self.glb_str_end.grow(MAX_GLOB_STRS); + self.glb_bib_str_ptr + .resize(self.glb_bib_str_ptr.len() + MAX_GLOB_STRS, 0); + self.global_strs.resize( + self.global_strs.len() + (GLOB_STR_SIZE + 1) * MAX_GLOB_STRS, + 0, + ); + self.glb_str_end + .resize(self.glb_str_end.len() + MAX_GLOB_STRS, 0); } pub fn str(&self, pos: usize) -> &[ASCIICode] { diff --git a/crates/engine_bibtex/src/hash.rs b/crates/engine_bibtex/src/hash.rs index 02987181a..70352557f 100644 --- a/crates/engine_bibtex/src/hash.rs +++ b/crates/engine_bibtex/src/hash.rs @@ -1,8 +1,4 @@ -use crate::{ - pool, - xbuf::{SafelyZero, XBuf}, - HashPointer, StrIlk, StrNumber, -}; +use crate::{pool, HashPointer, StrIlk, StrNumber}; pub(crate) const HASH_BASE: usize = 1; pub(crate) const HASH_SIZE: usize = if pool::MAX_STRINGS > 5000 { @@ -75,27 +71,24 @@ pub(crate) enum FnClass { StrGlblVar, } -// SAFETY: The FnClass type is valid at zero as FnClass::Builtin -unsafe impl SafelyZero for FnClass {} - // TODO: Split string-pool stuff into string pool, executor stuff into execution context pub(crate) struct HashData { - hash_next: XBuf, - hash_text: XBuf, - hash_ilk: XBuf, - ilk_info: XBuf, - fn_type: XBuf, + hash_next: Vec, + hash_text: Vec, + hash_ilk: Vec, + ilk_info: Vec, + fn_type: Vec, hash_used: usize, } impl HashData { pub(crate) fn new() -> HashData { HashData { - hash_next: XBuf::new(HASH_MAX), - hash_text: XBuf::new(HASH_MAX), - hash_ilk: XBuf::new(HASH_MAX), - ilk_info: XBuf::new(HASH_MAX), - fn_type: XBuf::new(HASH_MAX), + hash_next: vec![0; HASH_MAX], + hash_text: vec![0; HASH_MAX], + hash_ilk: vec![StrIlk::Text; HASH_MAX], + ilk_info: vec![0; HASH_MAX], + fn_type: vec![FnClass::Builtin; HASH_MAX], hash_used: HASH_MAX + 1, } } diff --git a/crates/engine_bibtex/src/lib.rs b/crates/engine_bibtex/src/lib.rs index 6410fd103..9d84f5907 100644 --- a/crates/engine_bibtex/src/lib.rs +++ b/crates/engine_bibtex/src/lib.rs @@ -26,7 +26,6 @@ use crate::{ cite::CiteInfo, entries::EntryData, exec::ExecCtx, - external::*, global::GlobalData, hash::HashData, history::{get_history, History}, @@ -49,7 +48,6 @@ use tectonic_bridge_core::{ }; use tectonic_errors::prelude::*; use tectonic_io_base::OutputHandle; -use xbuf::SafelyZero; pub(crate) mod auxi; pub(crate) mod bibs; @@ -67,7 +65,6 @@ pub(crate) mod other; pub(crate) mod peekable; pub(crate) mod pool; pub(crate) mod scan; -pub(crate) mod xbuf; #[doc(hidden)] #[derive(Debug)] @@ -288,9 +285,6 @@ pub(crate) enum StrIlk { ControlSeq, } -// SAFETY: StrIlk is valid at zero as StrIlk::Text -unsafe impl SafelyZero for StrIlk {} - type StrNumber = usize; type CiteNumber = usize; type ASCIICode = u8; @@ -330,7 +324,6 @@ pub(crate) fn bibtex_main(ctx: &mut Bibtex<'_, '_>, aux_file_name: &CStr) -> His let res = inner_bibtex_main(ctx, &mut globals, aux_file_name); match res { Err(BibtexError::Recover) | Ok(History::Spotless) => { - // SAFETY: bst_file guaranteed valid at this point ctx.bst.take().map(|file| file.file.close(ctx)); ttbc_output_close(ctx.engine, ctx.bbl_file); } @@ -524,15 +517,6 @@ fn initialize( get_the_top_level_aux_file_name(ctx, globals, aux_file_name) } -mod external { - #[allow(improper_ctypes)] - extern "C" { - pub(crate) fn xrealloc(ptr: *mut libc::c_void, size: libc::size_t) -> *mut libc::c_void; - - pub(crate) fn xcalloc(elems: libc::size_t, elem_size: libc::size_t) -> *mut libc::c_void; - } -} - /// Does our resulting executable link correctly? #[test] fn linkage() {} diff --git a/crates/engine_bibtex/src/other.rs b/crates/engine_bibtex/src/other.rs index 6fc823652..393b7aac9 100644 --- a/crates/engine_bibtex/src/other.rs +++ b/crates/engine_bibtex/src/other.rs @@ -1,10 +1,10 @@ -use crate::{xbuf::XBuf, FieldLoc, HashPointer, StrNumber}; +use crate::{FieldLoc, HashPointer, StrNumber}; const MAX_FIELDS: usize = 17250; pub(crate) struct OtherData { wiz_functions: Vec, - field_info: XBuf, + field_info: Vec, num_fields: FieldLoc, num_pre_defined_fields: FieldLoc, crossref_num: FieldLoc, @@ -14,7 +14,7 @@ impl OtherData { pub fn new() -> OtherData { OtherData { wiz_functions: Vec::new(), - field_info: XBuf::new(MAX_FIELDS), + field_info: vec![0; MAX_FIELDS], num_fields: 0, num_pre_defined_fields: 0, crossref_num: 0, @@ -51,7 +51,8 @@ impl OtherData { pub fn check_field_overflow(&mut self, fields: usize) { while fields > self.field_info.len() { - self.field_info.grow(MAX_FIELDS); + self.field_info + .resize(self.field_info.len() + MAX_FIELDS, 0); } } diff --git a/crates/engine_bibtex/src/pool.rs b/crates/engine_bibtex/src/pool.rs index 2a61ac1e6..eb0224b6c 100644 --- a/crates/engine_bibtex/src/pool.rs +++ b/crates/engine_bibtex/src/pool.rs @@ -6,7 +6,6 @@ use crate::{ hash, hash::{FnClass, HashData}, log::{output_bbl_line, print_overflow, write_logs}, - xbuf::XBuf, ASCIICode, Bibtex, BibtexError, GlobalItems, HashPointer, LookupRes, PoolPointer, StrIlk, StrNumber, }; @@ -24,10 +23,10 @@ pub(crate) enum LookupErr { } pub(crate) struct StringPool { - strings: XBuf, + strings: Vec, // Stores string starting locations in the string pool // length of string `s` is offsets[s + 1] - offsets[s] - offsets: XBuf, + offsets: Vec, pool_ptr: PoolPointer, str_ptr: StrNumber, } @@ -35,8 +34,8 @@ pub(crate) struct StringPool { impl StringPool { pub(crate) fn new() -> StringPool { StringPool { - strings: XBuf::new(POOL_SIZE), - offsets: XBuf::new(MAX_STRINGS), + strings: vec![0; POOL_SIZE], + offsets: vec![0; MAX_STRINGS], pool_ptr: 0, str_ptr: 1, } @@ -61,7 +60,7 @@ impl StringPool { } pub fn grow(&mut self) { - self.strings.grow(POOL_SIZE); + self.strings.resize(self.strings.len() + POOL_SIZE, 0); } /// Used while defining strings - declare the current `pool_ptr` as the end of the current diff --git a/crates/engine_bibtex/src/xbuf.rs b/crates/engine_bibtex/src/xbuf.rs deleted file mode 100644 index 8f3949e73..000000000 --- a/crates/engine_bibtex/src/xbuf.rs +++ /dev/null @@ -1,137 +0,0 @@ -use crate::{xcalloc, xrealloc}; -use std::{ - mem, - ops::{Deref, DerefMut}, - ptr, - ptr::NonNull, - slice, -}; - -/// # Safety -/// The all-zero byte pattern must be a valid instance of this type -pub unsafe trait SafelyZero {} - -// SAFETY: The bool zero value is false -unsafe impl SafelyZero for bool {} -// SAFETY: All integer types are sound to init as all zeroes -unsafe impl SafelyZero for u8 {} -// SAFETY: All integer types are sound to init as all zeroes -unsafe impl SafelyZero for usize {} -// SAFETY: All integer types are sound to init as all zeroes -unsafe impl SafelyZero for i32 {} -// SAFETY: All integer types are sound to init as all zeroes -unsafe impl SafelyZero for i64 {} -// SAFETY: Pointers are sound to init as all-zero, that's just null -unsafe impl SafelyZero for *mut T {} -// SAFETY: Option> has the same layout as *mut T -unsafe impl SafelyZero for Option> {} -// SAFETY: Option<&mut T> has the same layout as *mut T -unsafe impl SafelyZero for Option<&mut T> {} - -pub fn xcalloc_zeroed(len: usize) -> Option<&'static mut [T]> { - if len == 0 || mem::size_of::() == 0 { - return None; - } - // SAFETY: We're not asking for zero size because of above check - let ptr = unsafe { xcalloc(len, mem::size_of::()) }; - if ptr.is_null() { - None - } else { - // SAFETY: Allocating returns a valid pointer if non-null, it's valid for len * size_of::() - // bytes because that's what we requested - unsafe { ptr::write_bytes(ptr, 0, len) }; - // SAFETY: Same as above, plus `SafelyZero` means it's sound to return a reference to all-zero T - Some(unsafe { slice::from_raw_parts_mut(ptr.cast(), len) }) - } -} - -/// # Safety -/// -/// The provided `old` buffer must be valid, and allocated by `xalloc`/`xcalloc` -pub unsafe fn xrealloc_zeroed( - old: *mut [T], - new_len: usize, -) -> Option<&'static mut [T]> { - let old_len = (*old).len(); - let new_size = new_len * mem::size_of::(); - // SAFETY: realloc can be called with any size, even 0, that will just deallocate and return null - let ptr = unsafe { xrealloc(old.cast(), new_size) }.cast::(); - if ptr.is_null() { - None - } else { - if new_len > old_len { - // SAFETY: If new_len is bigger than old_len, ptr will be at least new_len * mem::size_of::() - // bytes, and it's safe to zero-init the trailing bytes - unsafe { ptr::write_bytes(ptr.add(old_len), 0, new_len - old_len) }; - } - // SAFETY: realloc guarantees `new_size` bytes valid, plus `SafelyZero` means it's sound to - // return a reference to all-zero T - Some(unsafe { slice::from_raw_parts_mut(ptr, new_len) }) - } -} - -#[derive(Debug)] -pub(crate) struct XBuf(&'static mut [T]); - -impl XBuf { - pub fn new(init_len: usize) -> XBuf { - XBuf(xcalloc_zeroed(init_len + 1).unwrap()) - } - - pub fn grow(&mut self, grow_by: usize) { - let slice = mem::take(&mut self.0); - let old_len = slice.len(); - // TODO: Just use system allocator? - self.0 = unsafe { xrealloc_zeroed(slice, grow_by + old_len) }.unwrap(); - } -} - -impl Deref for XBuf { - type Target = [T]; - - fn deref(&self) -> &Self::Target { - self.0 - } -} - -impl DerefMut for XBuf { - fn deref_mut(&mut self) -> &mut Self::Target { - self.0 - } -} - -impl Drop for XBuf { - fn drop(&mut self) { - // SAFETY: Inner pointer is guaranteed valid and not previously freed - unsafe { libc::free((self.0 as *mut [_]).cast()) }; - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_new() { - let buf = XBuf::::new(16); - assert_eq!(buf.len(), 17); - assert_eq!(&*buf, &[0; 17]); - - let buf2 = XBuf::::new(16); - assert_eq!(buf2.len(), 17); - assert_eq!(&*buf2, &[0; 17]); - } - - #[test] - fn test_grow() { - let mut buf = XBuf::::new(16); - buf.iter_mut().enumerate().for_each(|(idx, val)| *val = idx); - buf.grow(16); - assert_eq!(buf.len(), 33); - let expected = &[ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - ]; - assert_eq!(&*buf, expected); - } -} From 866b845266e650be020d3033b01a288151f5e1be Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 20 Feb 2024 21:29:06 -0800 Subject: [PATCH 07/23] Add +1 to vec constructors --- crates/engine_bibtex/src/buffer.rs | 4 ++-- crates/engine_bibtex/src/cite.rs | 8 ++++---- crates/engine_bibtex/src/entries.rs | 3 ++- crates/engine_bibtex/src/global.rs | 6 +++--- crates/engine_bibtex/src/hash.rs | 10 +++++----- crates/engine_bibtex/src/other.rs | 2 +- crates/engine_bibtex/src/pool.rs | 4 ++-- 7 files changed, 19 insertions(+), 18 deletions(-) diff --git a/crates/engine_bibtex/src/buffer.rs b/crates/engine_bibtex/src/buffer.rs index 016bf69d3..015933b94 100644 --- a/crates/engine_bibtex/src/buffer.rs +++ b/crates/engine_bibtex/src/buffer.rs @@ -14,7 +14,7 @@ struct Buffer { impl Buffer { fn new(len: usize) -> Buffer { Buffer { - ptr: vec![T::default(); len], + ptr: vec![T::default(); len + 1], offset: [0; N], init: 0, } @@ -46,7 +46,7 @@ impl GlobalBuffer { ex_buf: Buffer::new(buf_len), out_buf: Buffer::new(buf_len), name_sep_char: Buffer::new(buf_len), - name_tok: vec![0; buf_len], + name_tok: vec![0; buf_len + 1], } } diff --git a/crates/engine_bibtex/src/cite.rs b/crates/engine_bibtex/src/cite.rs index e1ac66c05..d5fd49949 100644 --- a/crates/engine_bibtex/src/cite.rs +++ b/crates/engine_bibtex/src/cite.rs @@ -22,10 +22,10 @@ pub(crate) struct CiteInfo { impl CiteInfo { pub fn new() -> CiteInfo { CiteInfo { - cite_list: vec![0; MAX_CITES], - cite_info: vec![0; MAX_CITES], - type_list: vec![0; MAX_CITES], - entry_exists: vec![false; MAX_CITES], + cite_list: vec![0; MAX_CITES + 1], + cite_info: vec![0; MAX_CITES + 1], + type_list: vec![0; MAX_CITES + 1], + entry_exists: vec![false; MAX_CITES + 1], cite_ptr: 0, entry_cite_ptr: 0, num_cites: 0, diff --git a/crates/engine_bibtex/src/entries.rs b/crates/engine_bibtex/src/entries.rs index 8bf9088e3..1c5b5f06f 100644 --- a/crates/engine_bibtex/src/entries.rs +++ b/crates/engine_bibtex/src/entries.rs @@ -74,12 +74,13 @@ impl EntryData { pub fn init_entries(&mut self, cites: &CiteInfo) { let num_cites = cites.num_cites(); - self.entry_ints = Some(vec![0; (self.num_entry_ints + 1) * (num_cites + 1)]); + self.entry_ints = Some(vec![0; (self.num_entry_ints + 1) * (num_cites + 1) + 1]); self.entry_strs = Some(vec![ 127; (self.num_entry_strs + 1) * (num_cites + 1) * (ENT_STR_SIZE + 1) + + 1 ]); } } diff --git a/crates/engine_bibtex/src/global.rs b/crates/engine_bibtex/src/global.rs index a2087abbe..06c3e3106 100644 --- a/crates/engine_bibtex/src/global.rs +++ b/crates/engine_bibtex/src/global.rs @@ -13,9 +13,9 @@ pub(crate) struct GlobalData { impl GlobalData { pub fn new() -> GlobalData { GlobalData { - glb_bib_str_ptr: vec![0; MAX_GLOB_STRS], - global_strs: vec![0; (GLOB_STR_SIZE + 1) * MAX_GLOB_STRS], - glb_str_end: vec![0; MAX_GLOB_STRS], + glb_bib_str_ptr: vec![0; MAX_GLOB_STRS + 1], + global_strs: vec![0; (GLOB_STR_SIZE + 1) * MAX_GLOB_STRS + 1], + glb_str_end: vec![0; MAX_GLOB_STRS + 1], num_glb_strs: 0, } } diff --git a/crates/engine_bibtex/src/hash.rs b/crates/engine_bibtex/src/hash.rs index 70352557f..35967cd45 100644 --- a/crates/engine_bibtex/src/hash.rs +++ b/crates/engine_bibtex/src/hash.rs @@ -84,11 +84,11 @@ pub(crate) struct HashData { impl HashData { pub(crate) fn new() -> HashData { HashData { - hash_next: vec![0; HASH_MAX], - hash_text: vec![0; HASH_MAX], - hash_ilk: vec![StrIlk::Text; HASH_MAX], - ilk_info: vec![0; HASH_MAX], - fn_type: vec![FnClass::Builtin; HASH_MAX], + hash_next: vec![0; HASH_MAX + 1], + hash_text: vec![0; HASH_MAX + 1], + hash_ilk: vec![StrIlk::Text; HASH_MAX + 1], + ilk_info: vec![0; HASH_MAX + 1], + fn_type: vec![FnClass::Builtin; HASH_MAX + 1], hash_used: HASH_MAX + 1, } } diff --git a/crates/engine_bibtex/src/other.rs b/crates/engine_bibtex/src/other.rs index 393b7aac9..cce82be9a 100644 --- a/crates/engine_bibtex/src/other.rs +++ b/crates/engine_bibtex/src/other.rs @@ -14,7 +14,7 @@ impl OtherData { pub fn new() -> OtherData { OtherData { wiz_functions: Vec::new(), - field_info: vec![0; MAX_FIELDS], + field_info: vec![0; MAX_FIELDS + 1], num_fields: 0, num_pre_defined_fields: 0, crossref_num: 0, diff --git a/crates/engine_bibtex/src/pool.rs b/crates/engine_bibtex/src/pool.rs index eb0224b6c..42fabd46a 100644 --- a/crates/engine_bibtex/src/pool.rs +++ b/crates/engine_bibtex/src/pool.rs @@ -34,8 +34,8 @@ pub(crate) struct StringPool { impl StringPool { pub(crate) fn new() -> StringPool { StringPool { - strings: vec![0; POOL_SIZE], - offsets: vec![0; MAX_STRINGS], + strings: vec![0; POOL_SIZE + 1], + offsets: vec![0; MAX_STRINGS + 1], pool_ptr: 0, str_ptr: 1, } From 711ba573afca31e490b27b0b7de7dd21afab1ec4 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 20 Feb 2024 22:12:44 -0800 Subject: [PATCH 08/23] Remove history thread-local, make history part of Bibtex --- crates/engine_bibtex/src/auxi.rs | 89 ++++++------ crates/engine_bibtex/src/bibs.rs | 197 ++++++++++++++++++++++----- crates/engine_bibtex/src/bst.rs | 120 +++++++++------- crates/engine_bibtex/src/exec.rs | 150 +++++++++++--------- crates/engine_bibtex/src/history.rs | 45 ------ crates/engine_bibtex/src/lib.rs | 46 +++++-- crates/engine_bibtex/src/log.rs | 203 ++++++++++++++++++---------- crates/engine_bibtex/src/pool.rs | 99 +++++++------- crates/engine_bibtex/src/scan.rs | 82 ++++++----- 9 files changed, 630 insertions(+), 401 deletions(-) delete mode 100644 crates/engine_bibtex/src/history.rs diff --git a/crates/engine_bibtex/src/auxi.rs b/crates/engine_bibtex/src/auxi.rs index e45746269..ebc48b9ed 100644 --- a/crates/engine_bibtex/src/auxi.rs +++ b/crates/engine_bibtex/src/auxi.rs @@ -63,7 +63,7 @@ fn aux_bib_data_command( ) -> Result<(), BibtexError> { if ctx.bib_seen { aux_err_illegal_another_print(AuxTy::Data)?; - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } ctx.bib_seen = true; @@ -77,13 +77,13 @@ fn aux_bib_data_command( .scan_till(buffers, init) { aux_err_no_right_brace_print(); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace { aux_err_white_space_in_argument_print(); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } @@ -91,17 +91,17 @@ fn aux_bib_data_command( && buffers.at_offset(BufTy::Base, 2) == b'}' { aux_err_stuff_after_right_brace_print(); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } let file = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(hash, file, StrIlk::BibFile)?; + let res = pool.lookup_str_insert(ctx, hash, file, StrIlk::BibFile)?; if res.exists { write_logs("This database file appears more than once: "); - print_bib_name(pool, hash.text(res.loc))?; - aux_err_print(buffers, aux, pool)?; + print_bib_name(ctx, pool, hash.text(res.loc))?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } @@ -111,8 +111,8 @@ fn aux_bib_data_command( match bib_in { Err(_) => { write_logs("I couldn't open database file "); - print_bib_name(pool, hash.text(res.loc))?; - aux_err_print(buffers, aux, pool)?; + print_bib_name(ctx, pool, hash.text(res.loc))?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } Ok(file) => { @@ -137,7 +137,7 @@ fn aux_bib_style_command( ) -> Result<(), BibtexError> { if ctx.bst_seen { aux_err_illegal_another_print(AuxTy::Style)?; - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } ctx.bst_seen = true; @@ -150,28 +150,28 @@ fn aux_bib_style_command( .scan_till(buffers, init) { aux_err_no_right_brace_print(); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace { aux_err_white_space_in_argument_print(); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if buffers.init(BufTy::Base) > buffers.offset(BufTy::Base, 2) + 1 { aux_err_stuff_after_right_brace_print(); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } let file = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(hash, file, StrIlk::BstFile)?; + let res = pool.lookup_str_insert(ctx, hash, file, StrIlk::BstFile)?; if res.exists { write_logs("Already encountered style file"); - print_confusion(); + print_confusion(ctx); return Err(BibtexError::Fatal); } @@ -181,9 +181,9 @@ fn aux_bib_style_command( match bst_file { Err(_) => { write_logs("I couldn't open style file "); - print_bst_name(pool, hash.text(res.loc))?; + print_bst_name(ctx, pool, hash.text(res.loc))?; ctx.bst = None; - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } Ok(file) => { @@ -197,7 +197,7 @@ fn aux_bib_style_command( if ctx.config.verbose { write_logs("The style file: "); - print_bst_name(pool, ctx.bst.as_ref().unwrap().name)?; + print_bst_name(ctx, pool, ctx.bst.as_ref().unwrap().name)?; } else { write_log_file("The style file: "); log_pr_bst_name(ctx, pool)?; @@ -226,19 +226,19 @@ fn aux_citation_command( .scan_till(buffers, init) { aux_err_no_right_brace_print(); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace { aux_err_white_space_in_argument_print(); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if buffers.init(BufTy::Base) > buffers.offset(BufTy::Base, 2) + 1 && buffers.at_offset(BufTy::Base, 2) == b'}' { aux_err_stuff_after_right_brace_print(); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } @@ -247,7 +247,7 @@ fn aux_citation_command( { if ctx.all_entries { write_logs("Multiple inclusions of entire database\n"); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } else { ctx.all_entries = true; @@ -268,7 +268,7 @@ fn aux_citation_command( let lc_cite = &mut buffers.buffer_mut(BufTy::Ex)[range]; lc_cite.make_ascii_lowercase(); - let lc_res = pool.lookup_str_insert(hash, lc_cite, StrIlk::LcCite)?; + let lc_res = pool.lookup_str_insert(ctx, hash, lc_cite, StrIlk::LcCite)?; if lc_res.exists { let cite = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; @@ -278,19 +278,20 @@ fn aux_citation_command( print_a_token(buffers); write_logs(" and "); print_a_pool_str( + ctx, cites.get_cite(hash.ilk_info(hash.ilk_info(lc_res.loc) as usize) as usize), pool, )?; write_logs("\n"); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } } else { let cite = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let uc_res = pool.lookup_str_insert(hash, cite, StrIlk::Cite)?; + let uc_res = pool.lookup_str_insert(ctx, hash, cite, StrIlk::Cite)?; if uc_res.exists { - hash_cite_confusion(); + hash_cite_confusion(ctx); return Err(BibtexError::Fatal); } @@ -324,24 +325,24 @@ fn aux_input_command( .scan_till(buffers, init) { aux_err_no_right_brace_print(); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace { aux_err_white_space_in_argument_print(); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if buffers.init(BufTy::Base) > buffers.offset(BufTy::Base, 2) + 1 { aux_err_stuff_after_right_brace_print(); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if aux.ptr() == AUX_STACK_SIZE { print_a_token(buffers); write_logs(": "); - print_overflow(); + print_overflow(ctx); write_logs(&format!("auxiliary file depth {}\n", AUX_STACK_SIZE)); return Err(BibtexError::Fatal); } @@ -356,17 +357,17 @@ fn aux_input_command( if !aux_extension_ok { print_a_token(buffers); write_logs(" has a wrong extension"); - aux_err_print(buffers, aux, pool)?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } let file = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(hash, file, StrIlk::AuxFile)?; + let res = pool.lookup_str_insert(ctx, hash, file, StrIlk::AuxFile)?; if res.exists { write_logs("Already encountered file "); - print_aux_name(pool, hash.text(res.loc))?; - aux_err_print(buffers, aux, pool)?; + print_aux_name(ctx, pool, hash.text(res.loc))?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } @@ -376,8 +377,8 @@ fn aux_input_command( match file { Err(_) => { write_logs("I couldn't open auxiliary file "); - print_aux_name(pool, hash.text(res.loc))?; - aux_err_print(buffers, aux, pool)?; + print_aux_name(ctx, pool, hash.text(res.loc))?; + aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } Ok(file) => { @@ -390,7 +391,7 @@ fn aux_input_command( } write_logs(&format!("A level-{} auxiliary file: ", aux.ptr() - 1)); - log_pr_aux_name(aux, pool)?; + log_pr_aux_name(ctx, aux, pool)?; Ok(()) } @@ -445,7 +446,7 @@ pub(crate) fn get_aux_command_and_process( )?, _ => { write_logs("Unknown auxiliary-file command"); - print_confusion(); + print_confusion(ctx); return Err(BibtexError::Fatal); } } @@ -474,31 +475,31 @@ pub(crate) fn last_check_for_aux_errors( if !ctx.citation_seen { aux_end1_err_print(); write_logs("\\citation commands"); - aux_end2_err_print(pool, last_aux)?; + aux_end2_err_print(ctx, pool, last_aux)?; } else if cites.num_cites() == 0 && !ctx.all_entries { aux_end1_err_print(); write_logs("cite keys"); - aux_end2_err_print(pool, last_aux)?; + aux_end2_err_print(ctx, pool, last_aux)?; } if !ctx.bib_seen { aux_end1_err_print(); write_logs("\\bibdata command"); - aux_end2_err_print(pool, last_aux)?; + aux_end2_err_print(ctx, pool, last_aux)?; } else if bibs.len() == 0 { aux_end1_err_print(); write_logs("database files"); - aux_end2_err_print(pool, last_aux)?; + aux_end2_err_print(ctx, pool, last_aux)?; } if !ctx.bst_seen { aux_end1_err_print(); write_logs("\\bibstyle command"); - aux_end2_err_print(pool, last_aux)?; + aux_end2_err_print(ctx, pool, last_aux)?; } else if ctx.bst.is_none() { aux_end1_err_print(); write_logs("style file"); - aux_end2_err_print(pool, last_aux)?; + aux_end2_err_print(ctx, pool, last_aux)?; } Ok(()) diff --git a/crates/engine_bibtex/src/bibs.rs b/crates/engine_bibtex/src/bibs.rs index ef8f0c591..67387df0c 100644 --- a/crates/engine_bibtex/src/bibs.rs +++ b/crates/engine_bibtex/src/bibs.rs @@ -78,6 +78,7 @@ pub(crate) fn eat_bib_white_space(buffers: &mut GlobalBuffer, bibs: &mut BibData } pub(crate) fn compress_bib_white( + ctx: &mut Bibtex<'_, '_>, buffers: &mut GlobalBuffer, pool: &StringPool, bibs: &mut BibData, @@ -98,7 +99,7 @@ pub(crate) fn compress_bib_white( let res = !input_ln(&mut bibs.top_file_mut().file, buffers); if res { - return eat_bib_print(buffers, pool, bibs, at_bib_command).map(|_| false); + return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command).map(|_| false); } bibs.top_file_mut().line += 1; @@ -114,7 +115,7 @@ pub(crate) fn compress_bib_white( // - tied to that, command_num is only used when at_bib_command is true // - There's some messed up control flow that's porting weird `goto` style, can probably be simplified pub(crate) fn get_bib_command_or_entry_and_process( - ctx: &Bibtex<'_, '_>, + ctx: &mut Bibtex<'_, '_>, globals: &mut GlobalItems<'_>, cur_macro_loc: &mut HashPointer, field_name_loc: &mut HashPointer, @@ -134,7 +135,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( if globals.buffers.at_offset(BufTy::Base, 2) != b'@' { write_logs("An \"@\" disappeared"); - print_confusion(); + print_confusion(ctx); return Err(BibtexError::Fatal); } @@ -143,7 +144,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } @@ -151,9 +158,15 @@ pub(crate) fn get_bib_command_or_entry_and_process( match scan_res { ScanRes::WhitespaceAdjacent | ScanRes::SpecifiedCharAdjacent => (), _ => { - bib_id_print(globals.buffers, scan_res)?; + bib_id_print(ctx, globals.buffers, scan_res)?; write_logs("an entry type"); - bib_err_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + bib_err_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } } @@ -174,7 +187,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( 0 => (), 1 => { if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } @@ -183,6 +202,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( b'(' => b')', _ => { bib_one_of_two_print( + ctx, globals.buffers, globals.pool, globals.bibs, @@ -201,7 +221,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( ); if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } @@ -229,7 +255,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( "Missing \"{}\" in preamble command", right_outer_delim )); - bib_err_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + bib_err_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } globals.buffers.set_offset( @@ -240,7 +272,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( } 2 => { if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } @@ -249,6 +287,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( b'(' => b')', _ => { bib_one_of_two_print( + ctx, globals.buffers, globals.pool, globals.bibs, @@ -267,7 +306,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( ); if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } @@ -275,9 +320,15 @@ pub(crate) fn get_bib_command_or_entry_and_process( match scan_res { ScanRes::WhitespaceAdjacent | ScanRes::SpecifiedCharAdjacent => (), _ => { - bib_id_print(globals.buffers, scan_res)?; + bib_id_print(ctx, globals.buffers, scan_res)?; write_logs("a string name"); - bib_err_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + bib_err_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } } @@ -287,22 +338,31 @@ pub(crate) fn get_bib_command_or_entry_and_process( let bib_macro = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bib_macro.make_ascii_lowercase(); - let res = - globals - .pool - .lookup_str_insert(globals.hash, bib_macro, StrIlk::BibCommand)?; + let res = globals.pool.lookup_str_insert( + ctx, + globals.hash, + bib_macro, + StrIlk::BibCommand, + )?; *cur_macro_loc = res.loc; globals .hash .set_ilk_info(res.loc, globals.hash.text(res.loc) as i32); if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } if globals.buffers.at_offset(BufTy::Base, 2) != b'=' { bib_equals_sign_print( + ctx, globals.buffers, globals.pool, globals.bibs, @@ -318,7 +378,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( ); if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } @@ -346,7 +412,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( "Missing \"{}\" in string command", right_outer_delim )); - bib_err_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + bib_err_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } @@ -357,7 +429,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( ); } _ => { - bib_cmd_confusion(); + bib_cmd_confusion(ctx); return Err(BibtexError::Fatal); } } @@ -371,7 +443,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( let type_exists = bst_res.exists && globals.hash.ty(bst_res.loc) == FnClass::Wizard; if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } @@ -380,6 +458,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( b'(' => b')', _ => { bib_one_of_two_print( + ctx, globals.buffers, globals.pool, globals.bibs, @@ -396,7 +475,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } @@ -423,7 +508,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( let lc_res = if ctx.all_entries { globals .pool - .lookup_str_insert(globals.hash, lc_cite, StrIlk::LcCite)? + .lookup_str_insert(ctx, globals.hash, lc_cite, StrIlk::LcCite)? } else { globals .pool @@ -454,7 +539,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( let uc_res = globals .pool - .lookup_str_insert(globals.hash, cite, StrIlk::Cite); + .lookup_str_insert(ctx, globals.hash, cite, StrIlk::Cite); let uc_res = match uc_res { Ok(res) => res, @@ -487,7 +572,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( res = lc_res2; if !lc_res2.exists { - cite_key_disappeared_confusion(); + cite_key_disappeared_confusion(ctx); return Some(Err(BibtexError::Fatal)); } if lc_res2.loc == lc_res.loc { @@ -497,12 +582,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( if globals.cites.get_type(entry_ptr) == 0 { write_logs("The cite list is messed up"); - print_confusion(); + print_confusion(ctx); return Some(Err(BibtexError::Fatal)); } write_logs("Repeated entry"); return Some(bib_err_print( + ctx, globals.buffers, globals.pool, globals.bibs, @@ -537,9 +623,9 @@ pub(crate) fn get_bib_command_or_entry_and_process( [globals.buffers.offset(BufTy::Base, 1)..globals.buffers.offset(BufTy::Base, 2)]; let res = globals .pool - .lookup_str_insert(globals.hash, cite, StrIlk::Cite)?; + .lookup_str_insert(ctx, globals.hash, cite, StrIlk::Cite)?; if res.exists { - hash_cite_confusion(); + hash_cite_confusion(ctx); return Err(BibtexError::Fatal); } globals.cites.set_entry_ptr(globals.cites.ptr()); @@ -570,18 +656,25 @@ pub(crate) fn get_bib_command_or_entry_and_process( write_logs("Warning--entry type for \""); print_a_token(globals.buffers); write_logs("\" isn't style-file defined\n"); - bib_warn_print(globals.pool, globals.bibs)?; + bib_warn_print(ctx, globals.pool, globals.bibs)?; } } if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } while globals.buffers.at_offset(BufTy::Base, 2) != right_outer_delim { if globals.buffers.at_offset(BufTy::Base, 2) != b',' { bib_one_of_two_print( + ctx, globals.buffers, globals.pool, globals.bibs, @@ -597,7 +690,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } @@ -609,9 +708,15 @@ pub(crate) fn get_bib_command_or_entry_and_process( match scan_res { ScanRes::WhitespaceAdjacent | ScanRes::SpecifiedCharAdjacent => (), _ => { - bib_id_print(globals.buffers, scan_res)?; + bib_id_print(ctx, globals.buffers, scan_res)?; write_logs("a field name"); - bib_err_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + bib_err_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } } @@ -632,12 +737,24 @@ pub(crate) fn get_bib_command_or_entry_and_process( } if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } if globals.buffers.at_offset(BufTy::Base, 2) != b'=' { - bib_equals_sign_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + bib_equals_sign_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } @@ -646,7 +763,13 @@ pub(crate) fn get_bib_command_or_entry_and_process( .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); if !eat_bib_white_space(globals.buffers, globals.bibs) { - eat_bib_print(globals.buffers, globals.pool, globals.bibs, at_bib_command)?; + eat_bib_print( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + at_bib_command, + )?; return Ok(()); } diff --git a/crates/engine_bibtex/src/bst.rs b/crates/engine_bibtex/src/bst.rs index 07b09c6e3..0a20838b6 100644 --- a/crates/engine_bibtex/src/bst.rs +++ b/crates/engine_bibtex/src/bst.rs @@ -5,14 +5,13 @@ use crate::{ cite::find_cite_locs_for_this_cite_key, exec::{check_command_execution, execute_fn, ExecCtx}, hash::{FnClass, HashData}, - history::mark_warning, log::{ - already_seen_function_print, bst_err_print_and_look_for_blank_line, bst_id_print, - bst_left_brace_print, bst_right_brace_print, bst_warn_print, - cite_key_disappeared_confusion, eat_bst_print, hash_cite_confusion, log_pr_bib_name, - print_a_token, print_bib_name, print_confusion, print_missing_entry, - rs_bad_cross_reference_print, rs_nonexistent_cross_reference_error, rs_print_fn_class, - write_log_file, write_logs, + already_seen_function_print, bad_cross_reference_print, + bst_err_print_and_look_for_blank_line, bst_id_print, bst_left_brace_print, + bst_right_brace_print, bst_warn_print, cite_key_disappeared_confusion, eat_bst_print, + hash_cite_confusion, log_pr_bib_name, nonexistent_cross_reference_error, print_a_token, + print_bib_name, print_confusion, print_missing_entry, rs_print_fn_class, write_log_file, + write_logs, }, pool::StringPool, scan::{eat_bst_white_space, scan_fn_def, scan_identifier, Scan, ScanRes}, @@ -67,7 +66,7 @@ macro_rules! bst_ident { match scan_res { ScanRes::WhitespaceAdjacent | ScanRes::SpecifiedCharAdjacent => (), _ => { - bst_id_print($globals.buffers, scan_res)?; + bst_id_print($ctx.glbl_ctx_mut(), $globals.buffers, scan_res)?; write_logs($name); bst_err_print_and_look_for_blank_line( $ctx.glbl_ctx_mut(), @@ -104,9 +103,12 @@ fn bst_entry_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = globals - .pool - .lookup_str_insert(globals.hash, bst_fn, StrIlk::BstFn)?; + let res = globals.pool.lookup_str_insert( + ctx.glbl_ctx_mut(), + globals.hash, + bst_fn, + StrIlk::BstFn, + )?; if res.exists { already_seen_function_print( ctx.glbl_ctx_mut(), @@ -134,7 +136,7 @@ fn bst_entry_command( if globals.other.num_fields() == globals.other.pre_defined_fields() { write_logs("Warning--I didn't find any fields"); - bst_warn_print(ctx.glbl_ctx(), globals.pool)?; + bst_warn_print(ctx.glbl_ctx_mut(), globals.pool)?; } bst_brace!('{', ctx, globals, "entry"); @@ -150,9 +152,12 @@ fn bst_entry_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = globals - .pool - .lookup_str_insert(globals.hash, bst_fn, StrIlk::BstFn)?; + let res = globals.pool.lookup_str_insert( + ctx.glbl_ctx_mut(), + globals.hash, + bst_fn, + StrIlk::BstFn, + )?; if res.exists { already_seen_function_print( ctx.glbl_ctx_mut(), @@ -192,9 +197,12 @@ fn bst_entry_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = globals - .pool - .lookup_str_insert(globals.hash, bst_fn, StrIlk::BstFn)?; + let res = globals.pool.lookup_str_insert( + ctx.glbl_ctx_mut(), + globals.hash, + bst_fn, + StrIlk::BstFn, + )?; if res.exists { already_seen_function_print( ctx.glbl_ctx_mut(), @@ -285,9 +293,10 @@ fn bst_function_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = globals - .pool - .lookup_str_insert(globals.hash, bst_fn, StrIlk::BstFn)?; + let res = + globals + .pool + .lookup_str_insert(ctx.glbl_ctx_mut(), globals.hash, bst_fn, StrIlk::BstFn)?; if res.exists { already_seen_function_print( ctx.glbl_ctx_mut(), @@ -344,9 +353,12 @@ fn bst_integers_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = globals - .pool - .lookup_str_insert(globals.hash, bst_fn, StrIlk::BstFn)?; + let res = globals.pool.lookup_str_insert( + ctx.glbl_ctx_mut(), + globals.hash, + bst_fn, + StrIlk::BstFn, + )?; if res.exists { already_seen_function_print( ctx.glbl_ctx_mut(), @@ -442,9 +454,10 @@ fn bst_macro_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = globals - .pool - .lookup_str_insert(globals.hash, bst_fn, StrIlk::Macro)?; + let res = + globals + .pool + .lookup_str_insert(ctx.glbl_ctx_mut(), globals.hash, bst_fn, StrIlk::Macro)?; if res.exists { print_a_token(globals.buffers); write_logs(" is already defined as a macro"); @@ -483,9 +496,10 @@ fn bst_macro_command( let range = globals.buffers.offset(BufTy::Base, 1)..globals.buffers.offset(BufTy::Base, 2); let text = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; - let res2 = globals - .pool - .lookup_str_insert(globals.hash, text, StrIlk::Text)?; + let res2 = + globals + .pool + .lookup_str_insert(ctx.glbl_ctx_mut(), globals.hash, text, StrIlk::Text)?; globals.hash.set_ty(res2.loc, FnClass::StrLit); globals @@ -560,10 +574,10 @@ fn bst_read_command( while globals.bibs.len() != 0 { if ctx.glbl_ctx().config.verbose { write_logs(&format!("Database file #{}: ", globals.bibs.len())); - print_bib_name(globals.pool, globals.bibs.top_file().name)?; + print_bib_name(ctx.glbl_ctx, globals.pool, globals.bibs.top_file().name)?; } else { write_log_file(&format!("Database file #{}: ", globals.bibs.len())); - log_pr_bib_name(globals.bibs, globals.pool)?; + log_pr_bib_name(ctx.glbl_ctx, globals.bibs, globals.pool)?; } globals @@ -594,7 +608,7 @@ fn bst_read_command( >= globals.other.max_fields() { write_logs("field_info index is out of range"); - print_confusion(); + print_confusion(ctx.glbl_ctx); return Err(BibtexError::Fatal); } @@ -640,10 +654,11 @@ fn bst_read_command( if !find.lc_found { if find.cite_found { - hash_cite_confusion(); + hash_cite_confusion(ctx.glbl_ctx_mut()); return Err(BibtexError::Fatal); } - rs_nonexistent_cross_reference_error( + nonexistent_cross_reference_error( + ctx.glbl_ctx_mut(), globals.pool, globals.cites, globals.other, @@ -653,13 +668,14 @@ fn bst_read_command( globals.other.set_field(field_ptr, 0); } else { if find.cite_loc != globals.hash.ilk_info(find.lc_cite_loc) as CiteNumber { - hash_cite_confusion(); + hash_cite_confusion(ctx.glbl_ctx_mut()); return Err(BibtexError::Fatal); } let cite_parent_ptr = globals.hash.ilk_info(find.cite_loc) as CiteNumber; if globals.cites.get_type(cite_parent_ptr) == 0 { - rs_nonexistent_cross_reference_error( + nonexistent_cross_reference_error( + ctx.glbl_ctx_mut(), globals.pool, globals.cites, globals.other, @@ -672,14 +688,15 @@ fn bst_read_command( cite_parent_ptr * globals.other.num_fields() + globals.other.crossref_num(); if globals.other.field(field_parent_ptr) != 0 { write_logs("Warning--you've nested cross references"); - rs_bad_cross_reference_print( + bad_cross_reference_print( + ctx.glbl_ctx_mut(), globals.pool, globals.cites, cite_ptr, globals.cites.get_cite(cite_parent_ptr), )?; write_logs("\", which also refers to something\n"); - mark_warning(); + ctx.glbl_ctx_mut().mark_warning(); } if !ctx.glbl_ctx().all_entries && cite_parent_ptr >= globals.cites.old_num_cites() @@ -695,7 +712,11 @@ fn bst_read_command( for cite_ptr in 0..globals.cites.num_cites() { if globals.cites.get_type(cite_ptr) == 0 { - print_missing_entry(globals.pool, globals.cites.get_cite(cite_ptr))?; + print_missing_entry( + ctx.glbl_ctx_mut(), + globals.pool, + globals.cites.get_cite(cite_ptr), + )?; } else if ctx.glbl_ctx().all_entries || cite_ptr < globals.cites.old_num_cites() || globals.cites.info(cite_ptr) >= ctx.glbl_ctx().config.min_crossrefs as usize @@ -705,7 +726,7 @@ fn bst_read_command( > globals.other.max_fields() { write_logs("field_info index is out of range"); - print_confusion(); + print_confusion(ctx.glbl_ctx); return Err(BibtexError::Fatal); } @@ -722,14 +743,14 @@ fn bst_read_command( globals.cites.get_cite(cite_ptr), ); if !find.lc_found { - cite_key_disappeared_confusion(); + cite_key_disappeared_confusion(ctx.glbl_ctx_mut()); return Err(BibtexError::Fatal); } if !find.cite_found || find.cite_loc != globals.hash.ilk_info(find.lc_cite_loc) as CiteNumber { - hash_cite_confusion(); + hash_cite_confusion(ctx.glbl_ctx_mut()); return Err(BibtexError::Fatal); } @@ -756,7 +777,7 @@ fn bst_read_command( if ctx.glbl_ctx().all_entries { for idx in globals.cites.all_marker()..globals.cites.old_num_cites() { if !globals.cites.exists(idx) { - print_missing_entry(globals.pool, globals.cites.info(idx))?; + print_missing_entry(ctx.glbl_ctx_mut(), globals.pool, globals.cites.info(idx))?; } } } @@ -867,9 +888,12 @@ fn bst_strings_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = globals - .pool - .lookup_str_insert(globals.hash, bst_fn, StrIlk::BstFn)?; + let res = globals.pool.lookup_str_insert( + ctx.glbl_ctx_mut(), + globals.hash, + bst_fn, + StrIlk::BstFn, + )?; if res.exists { already_seen_function_print( @@ -982,7 +1006,7 @@ pub(crate) fn get_bst_command_and_process( 9 => bst_strings_command(ctx, globals), _ => { write_logs("Unknown style-file command"); - print_confusion(); + print_confusion(ctx.glbl_ctx); Err(BibtexError::Fatal) } } diff --git a/crates/engine_bibtex/src/exec.rs b/crates/engine_bibtex/src/exec.rs index be790a92c..0e6b466a4 100644 --- a/crates/engine_bibtex/src/exec.rs +++ b/crates/engine_bibtex/src/exec.rs @@ -6,7 +6,6 @@ use crate::{ entries::{EntryData, ENT_STR_SIZE}, global::{GlobalData, GLOB_STR_SIZE}, hash::{FnClass, HashData}, - history::{mark_error, mark_warning}, log::{ brace_lvl_one_letters_complaint, braces_unbalanced_complaint, bst_1print_string_size_exceeded, bst_2print_string_size_exceeded, @@ -87,7 +86,7 @@ impl<'a, 'bib, 'cbs> ExecCtx<'a, 'bib, 'cbs> { if str >= self.bib_str_ptr { if str != pool.str_ptr() - 1 { write_logs("Nontop top of string stack"); - print_confusion(); + print_confusion(self.glbl_ctx); return Err(BibtexError::Fatal); } pool.set_str_ptr(pool.str_ptr() - 1); @@ -112,6 +111,7 @@ impl<'a, 'bib, 'cbs> ExecCtx<'a, 'bib, 'cbs> { } pub(crate) fn print_lit( + ctx: &mut Bibtex<'_, '_>, pool: &StringPool, hash: &HashData, val: ExecVal, @@ -121,19 +121,19 @@ pub(crate) fn print_lit( write_logs(&format!("{}\n", val)); } ExecVal::String(str) => { - print_a_pool_str(str, pool)?; + print_a_pool_str(ctx, str, pool)?; write_logs("\n"); } ExecVal::Function(f) => { - print_a_pool_str(hash.text(f), pool)?; + print_a_pool_str(ctx, hash.text(f), pool)?; write_logs("\n"); } ExecVal::Missing(s) => { - print_a_pool_str(s, pool)?; + print_a_pool_str(ctx, s, pool)?; write_logs("\n"); } ExecVal::Illegal => { - illegl_literal_confusion(); + illegl_literal_confusion(ctx); return Err(BibtexError::Fatal); } } @@ -141,6 +141,7 @@ pub(crate) fn print_lit( } pub(crate) fn print_stk_lit( + ctx: &mut Bibtex<'_, '_>, val: ExecVal, pool: &StringPool, hash: &HashData, @@ -149,21 +150,21 @@ pub(crate) fn print_stk_lit( ExecVal::Integer(val) => write_logs(&format!("{} is an integer literal", val)), ExecVal::String(str) => { write_logs("\""); - print_a_pool_str(str, pool)?; + print_a_pool_str(ctx, str, pool)?; write_logs("\" is a string literal"); } ExecVal::Function(f) => { write_logs("`"); - print_a_pool_str(hash.text(f), pool)?; + print_a_pool_str(ctx, hash.text(f), pool)?; write_logs("` is a function literal"); } ExecVal::Missing(s) => { write_logs("`"); - print_a_pool_str(s, pool)?; + print_a_pool_str(ctx, s, pool)?; write_logs("` is a missing field"); } ExecVal::Illegal => { - illegl_literal_confusion(); + illegl_literal_confusion(ctx); return Err(BibtexError::Fatal); } } @@ -171,7 +172,7 @@ pub(crate) fn print_stk_lit( } pub(crate) fn print_wrong_stk_lit( - ctx: &ExecCtx<'_, '_, '_>, + ctx: &mut ExecCtx<'_, '_, '_>, pool: &StringPool, hash: &HashData, cites: &CiteInfo, @@ -181,14 +182,14 @@ pub(crate) fn print_wrong_stk_lit( match val { ExecVal::Illegal => Ok(()), _ => { - print_stk_lit(val, pool, hash)?; + print_stk_lit(ctx.glbl_ctx, val, pool, hash)?; match typ2 { StkType::Integer => write_logs(", not an integer,"), StkType::String => write_logs(", not a string,"), StkType::Function => write_logs(", not a function,"), StkType::Missing | StkType::Illegal => { - illegl_literal_confusion(); + illegl_literal_confusion(ctx.glbl_ctx); return Err(BibtexError::Fatal); } }; @@ -199,41 +200,45 @@ pub(crate) fn print_wrong_stk_lit( } pub(crate) fn bst_ex_warn_print( - ctx: &ExecCtx<'_, '_, '_>, + ctx: &mut ExecCtx<'_, '_, '_>, pool: &StringPool, cites: &CiteInfo, ) -> Result<(), BibtexError> { if ctx.mess_with_entries { write_logs(" for entry "); - print_a_pool_str(cites.get_cite(cites.ptr()), pool)?; + print_a_pool_str(ctx.glbl_ctx_mut(), cites.get_cite(cites.ptr()), pool)?; } write_logs("\nwhile executing-"); - bst_ln_num_print(ctx.glbl_ctx(), pool)?; - mark_error(); + bst_ln_num_print(ctx.glbl_ctx_mut(), pool)?; + ctx.glbl_ctx_mut().mark_error(); Ok(()) } pub(crate) fn bst_ln_num_print( - glbl_ctx: &Bibtex<'_, '_>, + ctx: &mut Bibtex<'_, '_>, pool: &StringPool, ) -> Result<(), BibtexError> { write_logs(&format!( "--line {} of file ", - glbl_ctx.bst.as_ref().unwrap().line + ctx.bst.as_ref().unwrap().line )); - print_bst_name(pool, glbl_ctx.bst.as_ref().unwrap().name) + print_bst_name(ctx, pool, ctx.bst.as_ref().unwrap().name) } -pub(crate) fn print_bst_name(pool: &StringPool, name: StrNumber) -> Result<(), BibtexError> { - print_a_pool_str(name, pool)?; +pub(crate) fn print_bst_name( + ctx: &mut Bibtex<'_, '_>, + pool: &StringPool, + name: StrNumber, +) -> Result<(), BibtexError> { + print_a_pool_str(ctx, name, pool)?; write_logs(".bst\n"); Ok(()) } -pub fn illegl_literal_confusion() { +pub fn illegl_literal_confusion(ctx: &mut Bibtex<'_, '_>) { write_logs("Illegal literal type"); - print_confusion(); + print_confusion(ctx); } fn pop_top_and_print( @@ -247,7 +252,7 @@ fn pop_top_and_print( write_logs("Empty literal\n"); Ok(()) } else { - print_lit(pool, hash, val) + print_lit(ctx.glbl_ctx, pool, hash, val) } }) } @@ -279,7 +284,7 @@ pub fn skip_brace_level_greater_than_one(str: &[ASCIICode], brace_level: &mut i3 #[allow(clippy::too_many_arguments)] pub(crate) fn figure_out_the_formatted_name( - ctx: &ExecCtx<'_, '_, '_>, + ctx: &mut ExecCtx<'_, '_, '_>, buffers: &mut GlobalBuffer, pool: &StringPool, cites: &CiteInfo, @@ -620,7 +625,7 @@ pub(crate) fn check_command_execution( } if ctx.bib_str_ptr != pool.str_ptr() { write_logs("Nonempty empty string stack"); - print_confusion(); + print_confusion(ctx.glbl_ctx); return Err(BibtexError::Fatal); } Ok(()) @@ -633,7 +638,8 @@ fn add_pool_buf_and_push( ) -> Result<(), BibtexError> { buffers.set_offset(BufTy::Ex, 1, buffers.init(BufTy::Ex)); let str = &buffers.buffer(BufTy::Ex)[0..buffers.init(BufTy::Ex)]; - ctx.push_stack(ExecVal::String(pool.add_string_raw(str)?)); + let val = ExecVal::String(pool.add_string_raw(ctx.glbl_ctx_mut(), str)?); + ctx.push_stack(val); Ok(()) } @@ -658,9 +664,9 @@ fn interp_eq( } _ if pop1.ty() != pop2.ty() => { if pop1.ty() != StkType::Illegal && pop2.ty() != StkType::Illegal { - print_stk_lit(pop1, pool, hash)?; + print_stk_lit(ctx.glbl_ctx, pop1, pool, hash)?; write_logs(", "); - print_stk_lit(pop2, pool, hash)?; + print_stk_lit(ctx.glbl_ctx, pop2, pool, hash)?; write_logs("\n---they aren't the same literal types"); bst_ex_warn_print(ctx, pool, cites)?; } @@ -668,7 +674,7 @@ fn interp_eq( } _ => { if pop1.ty() != StkType::Illegal { - print_stk_lit(pop1, pool, hash)?; + print_stk_lit(ctx.glbl_ctx, pop1, pool, hash)?; write_logs(", not an integer or a string,"); bst_ex_warn_print(ctx, pool, cites)?; } @@ -821,7 +827,7 @@ fn interp_concat( let ptr = pool.str_start(s2 + 1); pool.copy_raw(s1, ptr); pool.set_pool_ptr(ptr + s1_len); - let new = pool.make_string()?; + let new = pool.make_string(ctx.glbl_ctx_mut())?; ctx.push_stack(ExecVal::String(new)); } } else if s1 >= ctx.bib_str_ptr { @@ -845,7 +851,8 @@ fn interp_concat( pool.copy_raw(s1, pool.str_start(s1 + 1) + s2_len - s1_len); pool.copy_raw(s2, pool.str_start(s1)); pool.set_pool_ptr(pool.str_start(s1) + s1_len + s2_len); - ctx.push_stack(ExecVal::String(pool.make_string()?)); + let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + ctx.push_stack(val); } } else { let str1 = pool.get_str(s1); @@ -864,7 +871,8 @@ fn interp_concat( pool.copy_raw(s2, ptr); pool.copy_raw(s1, ptr + s2_len); pool.set_pool_ptr(ptr + s1_len + s2_len); - ctx.push_stack(ExecVal::String(pool.make_string()?)); + let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + ctx.push_stack(val); } } Ok(()) @@ -1008,7 +1016,8 @@ fn interp_add_period( } } pool.append(b'.'); - ctx.push_stack(ExecVal::String(pool.make_string()?)); + let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + ctx.push_stack(val); } } Ok(()) @@ -1048,7 +1057,7 @@ fn interp_change_case( }; if conv_ty == ConvTy::Bad { - print_a_pool_str(s1, pool)?; + print_a_pool_str(ctx.glbl_ctx, s1, pool)?; write_logs(" is an illegal case-conversion string"); bst_ex_warn_print(ctx, pool, cites)?; } @@ -1164,7 +1173,8 @@ fn interp_change_case( idx += 1; } check_brace_level(ctx, pool, cites, s2, brace_level)?; - ctx.push_stack(ExecVal::String(pool.add_string_raw(&scratch)?)); + let val = ExecVal::String(pool.add_string_raw(ctx.glbl_ctx_mut(), &scratch)?); + ctx.push_stack(val); } (ExecVal::String(_), _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop2, StkType::String)?; @@ -1190,7 +1200,7 @@ fn interp_chr_to_int( let str = pool.get_str(s1); if str.len() != 1 { write_logs("\""); - print_a_pool_str(s1, pool)?; + print_a_pool_str(ctx.glbl_ctx, s1, pool)?; write_logs("\" isn't a single character"); bst_ex_warn_print(ctx, pool, cites)?; ctx.push_stack(ExecVal::Integer(0)); @@ -1242,7 +1252,8 @@ fn interp_dup( let ptr = pool.pool_ptr(); pool.copy_raw(s1, ptr); pool.set_pool_ptr(ptr + str_len); - ctx.push_stack(ExecVal::String(pool.make_string()?)); + let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + ctx.push_stack(val); } } _ => { @@ -1273,7 +1284,7 @@ fn interp_empty( ctx.push_stack(ExecVal::Integer(0)); } _ => { - print_stk_lit(pop1, pool, hash)?; + print_stk_lit(ctx.glbl_ctx, pop1, pool, hash)?; write_logs(", not a string or missing field,"); bst_ex_warn_print(ctx, pool, cites)?; ctx.push_stack(ExecVal::Integer(0)); @@ -1335,7 +1346,7 @@ fn interp_format_name( } else { write_logs(&format!("There aren't {} names in \"", i2)); } - print_a_pool_str(s3, pool)?; + print_a_pool_str(ctx.glbl_ctx, s3, pool)?; write_logs("\""); bst_ex_warn_print(ctx, pool, cites)?; } @@ -1348,7 +1359,7 @@ fn interp_format_name( _ => { if buffers.at(BufTy::Ex, buffers.offset(BufTy::Ex, 1) - 1) == b',' { write_logs(&format!("Name {} in \"", i2)); - print_a_pool_str(s3, pool)?; + print_a_pool_str(ctx.glbl_ctx, s3, pool)?; write_logs("\" has a comma at the end"); bst_ex_warn_print(ctx, pool, cites)?; buffers.set_offset(BufTy::Ex, 1, buffers.offset(BufTy::Ex, 1) - 1); @@ -1384,7 +1395,7 @@ fn interp_format_name( } Commas::Two(_, _) => { write_logs(&format!("Too many commas in name {} of \"", i2)); - print_a_pool_str(s3, pool)?; + print_a_pool_str(ctx.glbl_ctx, s3, pool)?; write_logs("\""); bst_ex_warn_print(ctx, pool, cites)?; } @@ -1420,7 +1431,7 @@ fn interp_format_name( } write_logs(&format!("Name {} of \"", i2)); - print_a_pool_str(s3, pool)?; + print_a_pool_str(ctx.glbl_ctx, s3, pool)?; write_logs("\" isn't brace balanced"); bst_ex_warn_print(ctx, pool, cites)?; xptr += 1; @@ -1474,8 +1485,16 @@ fn interp_format_name( while von_start < last_end - 1 { name_ptr = buffers.name_tok(von_start); name_ptr2 = buffers.name_tok(von_start + 1); - if von_token_found(buffers, hash, pool, &mut name_ptr, name_ptr2)? { + if von_token_found( + ctx.glbl_ctx_mut(), + buffers, + hash, + pool, + &mut name_ptr, + name_ptr2, + )? { von_name_ends_and_last_name_starts_stuff( + ctx.glbl_ctx_mut(), buffers, hash, pool, @@ -1510,6 +1529,7 @@ fn interp_format_name( first_start = jr_end; first_end = num_tokens; von_name_ends_and_last_name_starts_stuff( + ctx.glbl_ctx_mut(), buffers, hash, pool, @@ -1526,6 +1546,7 @@ fn interp_format_name( first_start = jr_end; first_end = num_tokens; von_name_ends_and_last_name_starts_stuff( + ctx.glbl_ctx_mut(), buffers, hash, pool, @@ -1587,7 +1608,8 @@ fn interp_int_to_chr( } pool.append(i1 as u8); - ctx.push_stack(ExecVal::String(pool.make_string()?)); + let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + ctx.push_stack(val); } Ok(()) } @@ -1609,7 +1631,8 @@ fn interp_int_to_str( }; let scratch = i1.to_string(); - ctx.push_stack(ExecVal::String(pool.add_string_raw(scratch.as_bytes())?)); + let val = ExecVal::String(pool.add_string_raw(ctx.glbl_ctx_mut(), scratch.as_bytes())?); + ctx.push_stack(val); Ok(()) } @@ -1635,7 +1658,7 @@ fn interp_missing( ctx.push_stack(ExecVal::Integer(0)); } _ => { - print_stk_lit(pop1, pool, hash)?; + print_stk_lit(ctx.glbl_ctx, pop1, pool, hash)?; write_logs(", not a string or missing field,"); bst_ex_warn_print(ctx, pool, cites)?; ctx.push_stack(ExecVal::Integer(0)); @@ -1682,7 +1705,7 @@ fn interp_preamble( for s in bibs.preamble() { out.extend(pool.get_str(*s)); } - let s = pool.add_string_raw(&out)?; + let s = pool.add_string_raw(ctx.glbl_ctx_mut(), &out)?; ctx.push_stack(ExecVal::String(s)); Ok(()) } @@ -1773,14 +1796,14 @@ fn interp_purify( } scratch.truncate(write_idx); - let out = pool.add_string_raw(&scratch)?; + let out = pool.add_string_raw(ctx.glbl_ctx_mut(), &scratch)?; ctx.push_stack(ExecVal::String(out)); Ok(()) } fn interp_quote(ctx: &mut ExecCtx<'_, '_, '_>, pool: &mut StringPool) -> Result<(), BibtexError> { - let s = pool.add_string_raw(b"\"")?; + let s = pool.add_string_raw(ctx.glbl_ctx_mut(), b"\"")?; ctx.push_stack(ExecVal::String(s)); Ok(()) } @@ -1870,7 +1893,7 @@ fn interp_substr( // TODO: Remove this intermediate allocation, currently can't pass a `&str` from a StringPool // to that StringPool. let new_str = Vec::from(&str[SLRange { start, len }]); - let out = pool.add_string_raw(&new_str)?; + let out = pool.add_string_raw(ctx.glbl_ctx_mut(), &new_str)?; ctx.push_stack(ExecVal::String(out)); Ok(()) @@ -1893,8 +1916,10 @@ fn interp_swap( let ptr = pool.pool_ptr(); pool.copy_raw(s1, ptr); pool.set_pool_ptr(ptr + s1_len); - ctx.push_stack(ExecVal::String(pool.make_string()?)); - ctx.push_stack(ExecVal::String(pool.add_string_raw(&tmp)?)); + let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + ctx.push_stack(val); + let val = ExecVal::String(pool.add_string_raw(ctx.glbl_ctx_mut(), &tmp)?); + ctx.push_stack(val); return Ok(()); } (ExecVal::String(s), _) | (_, ExecVal::String(s)) if s >= ctx.bib_str_ptr => { @@ -2031,7 +2056,8 @@ fn interp_text_prefix( pool.append(b'}'); } - ctx.push_stack(ExecVal::String(pool.make_string()?)); + let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + ctx.push_stack(val); Ok(()) } @@ -2066,8 +2092,8 @@ fn interp_warning( match pop1 { ExecVal::String(_) => { write_logs("Warning--"); - print_lit(pool, hash, pop1)?; - mark_warning(); + print_lit(ctx.glbl_ctx, pool, hash, pop1)?; + ctx.glbl_ctx_mut().mark_warning(); } _ => print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::String)?, } @@ -2350,7 +2376,7 @@ pub(crate) fn execute_fn( ), _ => { write_logs("Unknown built-in function"); - print_confusion(); + print_confusion(ctx.glbl_ctx); Err(BibtexError::Fatal) } }, @@ -2386,7 +2412,7 @@ pub(crate) fn execute_fn( + globals.hash.ilk_info(ex_fn_loc) as usize; if field_ptr >= globals.other.max_fields() { write_logs("field_info index is out of range"); - print_confusion(); + print_confusion(ctx.glbl_ctx); return Err(BibtexError::Fatal); } @@ -2417,7 +2443,8 @@ pub(crate) fn execute_fn( let str_ent_ptr = globals.cites.ptr() * globals.entries.num_ent_strs() + globals.hash.ilk_info(ex_fn_loc) as usize; let str = globals.entries.strs(str_ent_ptr); - ctx.push_stack(ExecVal::String(globals.pool.add_string_raw(str)?)); + let val = ExecVal::String(globals.pool.add_string_raw(ctx.glbl_ctx_mut(), str)?); + ctx.push_stack(val); Ok(()) } } @@ -2432,7 +2459,8 @@ pub(crate) fn execute_fn( ctx.push_stack(ExecVal::String(str_ptr)); } else { let str = globals.globals.str(str_glb_ptr); - ctx.push_stack(ExecVal::String(globals.pool.add_string_raw(str)?)); + let val = ExecVal::String(globals.pool.add_string_raw(ctx.glbl_ctx_mut(), str)?); + ctx.push_stack(val); } Ok(()) } diff --git a/crates/engine_bibtex/src/history.rs b/crates/engine_bibtex/src/history.rs deleted file mode 100644 index 3873e0917..000000000 --- a/crates/engine_bibtex/src/history.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::cell::Cell; - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] -pub enum History { - Spotless, - WarningIssued(u32), - ErrorIssued(u32), - FatalError, -} - -thread_local! { - static HISTORY: Cell = const { Cell::new(History::Spotless) }; -} - -pub(crate) fn reset() { - HISTORY.with(|cell| cell.set(History::Spotless)); -} - -pub(crate) fn get_history() -> History { - HISTORY.with(|h| h.get()) -} - -pub(crate) fn set_history(hist: History) { - HISTORY.with(|h| h.set(hist)) -} - -pub(crate) fn mark_warning() { - match get_history() { - History::WarningIssued(cur) => set_history(History::WarningIssued(cur + 1)), - History::Spotless => set_history(History::WarningIssued(1)), - _ => (), - } -} - -pub(crate) fn mark_error() { - match get_history() { - History::Spotless | History::WarningIssued(_) => set_history(History::ErrorIssued(1)), - History::ErrorIssued(cur) => set_history(History::ErrorIssued(cur + 1)), - _ => (), - } -} - -pub fn mark_fatal() { - set_history(History::FatalError); -} diff --git a/crates/engine_bibtex/src/lib.rs b/crates/engine_bibtex/src/lib.rs index 9d84f5907..2441d4601 100644 --- a/crates/engine_bibtex/src/lib.rs +++ b/crates/engine_bibtex/src/lib.rs @@ -28,7 +28,6 @@ use crate::{ exec::ExecCtx, global::GlobalData, hash::HashData, - history::{get_history, History}, log::{ bib_close_log, init_log_file, init_standard_output, log_pr_aux_name, print_aux_name, print_confusion, sam_wrong_file_name_print, write_log_file, write_logs, @@ -59,13 +58,20 @@ pub(crate) mod entries; pub(crate) mod exec; pub(crate) mod global; pub(crate) mod hash; -pub(crate) mod history; pub(crate) mod log; pub(crate) mod other; pub(crate) mod peekable; pub(crate) mod pool; pub(crate) mod scan; +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] +pub(crate) enum History { + Spotless, + WarningIssued(u32), + ErrorIssued(u32), + FatalError, +} + #[doc(hidden)] #[derive(Debug)] pub(crate) enum BibtexError { @@ -196,6 +202,7 @@ impl Default for BibtexConfig { pub(crate) struct Bibtex<'a, 'cbs> { pub engine: &'a mut CoreBridgeState<'cbs>, pub config: BibtexConfig, + pub history: History, pub bst: Option, @@ -228,6 +235,7 @@ impl<'a, 'cbs> Bibtex<'a, 'cbs> { Bibtex { engine, config, + history: History::Spotless, bst: None, bbl_file: ptr::null_mut(), bbl_line_num: 0, @@ -247,6 +255,26 @@ impl<'a, 'cbs> Bibtex<'a, 'cbs> { s_aux_extension: 0, } } + + pub(crate) fn mark_warning(&mut self) { + match self.history { + History::WarningIssued(cur) => self.history = History::WarningIssued(cur + 1), + History::Spotless => self.history = History::WarningIssued(1), + _ => (), + } + } + + pub(crate) fn mark_error(&mut self) { + match self.history { + History::Spotless | History::WarningIssued(_) => self.history = History::ErrorIssued(1), + History::ErrorIssued(cur) => self.history = History::ErrorIssued(cur + 1), + _ => (), + } + } + + pub(crate) fn mark_fatal(&mut self) { + self.history = History::FatalError; + } } #[derive(Copy, Clone, Debug)] @@ -296,7 +324,7 @@ type FieldLoc = usize; type FnDefLoc = usize; pub(crate) fn bibtex_main(ctx: &mut Bibtex<'_, '_>, aux_file_name: &CStr) -> History { - history::reset(); + ctx.history = History::Spotless; log::reset(); let mut buffers = GlobalBuffer::new(); @@ -334,7 +362,7 @@ pub(crate) fn bibtex_main(ctx: &mut Bibtex<'_, '_>, aux_file_name: &CStr) -> His Ok(hist) => return hist, } - match get_history() { + match ctx.history { History::Spotless => (), History::WarningIssued(warns) => { if warns == 1 { @@ -356,7 +384,7 @@ pub(crate) fn bibtex_main(ctx: &mut Bibtex<'_, '_>, aux_file_name: &CStr) -> His } bib_close_log(ctx); - get_history() + ctx.history } pub(crate) fn inner_bibtex_main( @@ -387,10 +415,10 @@ pub(crate) fn inner_bibtex_main( if ctx.config.verbose { write_logs("The top-level auxiliary file: "); - print_aux_name(globals.pool, globals.aux.top_file().name)?; + print_aux_name(ctx, globals.pool, globals.aux.top_file().name)?; } else { write_log_file("The top-level auxiliary file: "); - log_pr_aux_name(globals.aux, globals.pool)?; + log_pr_aux_name(ctx, globals.aux, globals.pool)?; } let last_aux = loop { @@ -472,7 +500,7 @@ pub(crate) fn get_the_top_level_aux_file_name( } set_extension(&mut path, b".aux"); - let lookup = match pool.lookup_str_insert(hash, &path[..path.len() - 1], StrIlk::AuxFile) { + let lookup = match pool.lookup_str_insert(ctx, hash, &path[..path.len() - 1], StrIlk::AuxFile) { Ok(res) => res, Err(_) => return Err(BibtexError::Fatal), }; @@ -485,7 +513,7 @@ pub(crate) fn get_the_top_level_aux_file_name( if lookup.exists { write_logs("Already encountered auxiliary file"); - print_confusion(); + print_confusion(ctx); return Err(BibtexError::Fatal); } diff --git a/crates/engine_bibtex/src/log.rs b/crates/engine_bibtex/src/log.rs index 0280573d5..5683d5034 100644 --- a/crates/engine_bibtex/src/log.rs +++ b/crates/engine_bibtex/src/log.rs @@ -6,7 +6,6 @@ use crate::{ cite::CiteInfo, exec::{bst_ex_warn_print, bst_ln_num_print, ExecCtx}, hash::{FnClass, HashData}, - history::{mark_error, mark_fatal, mark_warning}, other::OtherData, peekable::input_ln, pool::StringPool, @@ -116,14 +115,14 @@ pub(crate) fn bib_close_log(ctx: &mut Bibtex<'_, '_>) { }) } -pub fn print_overflow() { +pub fn print_overflow(ctx: &mut Bibtex<'_, '_>) { write_logs("Sorry---you've exceeded BibTeX's "); - mark_fatal(); + ctx.mark_fatal(); } -pub fn print_confusion() { +pub fn print_confusion(ctx: &mut Bibtex<'_, '_>) { write_logs("---this can't happen\n*Please notify the Tectonic maintainer*\n"); - mark_fatal(); + ctx.mark_fatal(); } pub(crate) fn out_token(handle: &mut OutputHandle, buffers: &GlobalBuffer) { @@ -138,7 +137,7 @@ pub(crate) fn print_a_token(buffers: &GlobalBuffer) { with_log(|log| out_token(log, buffers)); } -pub(crate) fn print_bad_input_line(buffers: &GlobalBuffer) { +pub(crate) fn print_bad_input_line(ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer) { write_logs(" : "); let offset2 = buffers.offset(BufTy::Base, 2); @@ -177,7 +176,7 @@ pub(crate) fn print_bad_input_line(buffers: &GlobalBuffer) { write_logs("(Error may have been on previous line)\n"); } - mark_error(); + ctx.mark_error(); } pub(crate) fn print_skipping_whatever_remains() { @@ -185,6 +184,7 @@ pub(crate) fn print_skipping_whatever_remains() { } pub(crate) fn out_pool_str( + ctx: &mut Bibtex<'_, '_>, pool: &StringPool, handle: &mut OutputHandle, s: StrNumber, @@ -195,19 +195,23 @@ pub(crate) fn out_pool_str( Ok(()) } else { write_logs(&format!("Illegal string number: {}", s)); - print_confusion(); + print_confusion(ctx); Err(BibtexError::Fatal) } } -pub(crate) fn print_a_pool_str(s: StrNumber, pool: &StringPool) -> Result<(), BibtexError> { +pub(crate) fn print_a_pool_str( + ctx: &mut Bibtex<'_, '_>, + s: StrNumber, + pool: &StringPool, +) -> Result<(), BibtexError> { let str = pool.try_get_str(s); if let Ok(str) = str { write_logs(str); Ok(()) } else { write_logs(&format!("Illegal string number: {}", s)); - print_confusion(); + print_confusion(ctx); Err(BibtexError::Fatal) } } @@ -223,28 +227,37 @@ pub fn sam_wrong_file_name_print(file: &CStr) { }) } -pub(crate) fn print_aux_name(pool: &StringPool, name: StrNumber) -> Result<(), BibtexError> { - print_a_pool_str(name, pool)?; +pub(crate) fn print_aux_name( + ctx: &mut Bibtex<'_, '_>, + pool: &StringPool, + name: StrNumber, +) -> Result<(), BibtexError> { + print_a_pool_str(ctx, name, pool)?; write_logs("\n"); Ok(()) } -pub(crate) fn log_pr_aux_name(aux: &AuxData, pool: &StringPool) -> Result<(), BibtexError> { +pub(crate) fn log_pr_aux_name( + ctx: &mut Bibtex<'_, '_>, + aux: &AuxData, + pool: &StringPool, +) -> Result<(), BibtexError> { with_log(|log| { - out_pool_str(pool, log, aux.top_file().name)?; + out_pool_str(ctx, pool, log, aux.top_file().name)?; writeln!(log).unwrap(); Ok(()) }) } pub(crate) fn aux_err_print( + ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer, aux: &AuxData, pool: &StringPool, ) -> Result<(), BibtexError> { write_logs(&format!("---line {} of file ", aux.top_file().line)); - print_aux_name(pool, aux.top_file().name)?; - print_bad_input_line(buffers); + print_aux_name(ctx, pool, aux.top_file().name)?; + print_bad_input_line(ctx, buffers); print_skipping_whatever_remains(); write_logs("command\n"); Ok(()) @@ -281,15 +294,23 @@ pub fn aux_end1_err_print() { write_logs("I found no "); } -pub(crate) fn aux_end2_err_print(pool: &StringPool, name: StrNumber) -> Result<(), BibtexError> { +pub(crate) fn aux_end2_err_print( + ctx: &mut Bibtex<'_, '_>, + pool: &StringPool, + name: StrNumber, +) -> Result<(), BibtexError> { write_logs("---while reading file "); - print_aux_name(pool, name)?; - mark_error(); + print_aux_name(ctx, pool, name)?; + ctx.mark_error(); Ok(()) } -pub(crate) fn print_bib_name(pool: &StringPool, name: StrNumber) -> Result<(), BibtexError> { - print_a_pool_str(name, pool)?; +pub(crate) fn print_bib_name( + ctx: &mut Bibtex<'_, '_>, + pool: &StringPool, + name: StrNumber, +) -> Result<(), BibtexError> { + print_a_pool_str(ctx, name, pool)?; let res = pool .try_get_str(name) .map_err(|_| BibtexError::Fatal) @@ -301,9 +322,13 @@ pub(crate) fn print_bib_name(pool: &StringPool, name: StrNumber) -> Result<(), B Ok(()) } -pub(crate) fn log_pr_bib_name(bibs: &BibData, pool: &StringPool) -> Result<(), BibtexError> { +pub(crate) fn log_pr_bib_name( + ctx: &mut Bibtex<'_, '_>, + bibs: &BibData, + pool: &StringPool, +) -> Result<(), BibtexError> { with_log(|log| { - out_pool_str(pool, log, bibs.top_file().name)?; + out_pool_str(ctx, pool, log, bibs.top_file().name)?; let res = pool .try_get_str(bibs.top_file().name) .map(|str| str.ends_with(b".bib")) @@ -316,23 +341,29 @@ pub(crate) fn log_pr_bib_name(bibs: &BibData, pool: &StringPool) -> Result<(), B }) } -pub(crate) fn log_pr_bst_name(ctx: &Bibtex<'_, '_>, pool: &StringPool) -> Result<(), BibtexError> { +pub(crate) fn log_pr_bst_name( + ctx: &mut Bibtex<'_, '_>, + pool: &StringPool, +) -> Result<(), BibtexError> { with_log(|log| { // TODO: This call can panic if bst_str doesn't exist - out_pool_str(pool, log, ctx.bst.as_ref().unwrap().name)?; + out_pool_str(ctx, pool, log, ctx.bst.as_ref().unwrap().name)?; writeln!(log, ".bst").unwrap(); Ok(()) }) } -pub(crate) fn hash_cite_confusion() { +pub(crate) fn hash_cite_confusion(ctx: &mut Bibtex<'_, '_>) { write_logs("Cite hash error"); - print_confusion(); + print_confusion(ctx); } -pub(crate) fn bst_warn_print(ctx: &Bibtex<'_, '_>, pool: &StringPool) -> Result<(), BibtexError> { +pub(crate) fn bst_warn_print( + ctx: &mut Bibtex<'_, '_>, + pool: &StringPool, +) -> Result<(), BibtexError> { bst_ln_num_print(ctx, pool)?; - mark_warning(); + ctx.mark_warning(); Ok(()) } @@ -340,12 +371,13 @@ pub fn eat_bst_print() { write_logs("Illegal end of style file in command: "); } -pub fn id_scanning_confusion() { +pub fn id_scanning_confusion(ctx: &mut Bibtex<'_, '_>) { write_logs("Identifier scanning error"); - print_confusion(); + print_confusion(ctx); } pub(crate) fn bst_id_print( + ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer, scan_result: ScanRes, ) -> Result<(), BibtexError> { @@ -363,7 +395,7 @@ pub(crate) fn bst_id_print( Ok(()) } _ => { - id_scanning_confusion(); + id_scanning_confusion(ctx); Err(BibtexError::Fatal) } } @@ -377,20 +409,25 @@ pub fn bst_right_brace_print() { write_logs("\"}\" is missing in command: "); } -pub(crate) fn bib_ln_num_print(pool: &StringPool, bibs: &BibData) -> Result<(), BibtexError> { +pub(crate) fn bib_ln_num_print( + ctx: &mut Bibtex<'_, '_>, + pool: &StringPool, + bibs: &BibData, +) -> Result<(), BibtexError> { write_logs(&format!("--line {} of file ", bibs.top_file().line)); - print_bib_name(pool, bibs.top_file().name) + print_bib_name(ctx, pool, bibs.top_file().name) } pub(crate) fn bib_err_print( + ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer, pool: &StringPool, bibs: &BibData, at_bib_command: bool, ) -> Result<(), BibtexError> { write_logs("-"); - bib_ln_num_print(pool, bibs)?; - print_bad_input_line(buffers); + bib_ln_num_print(ctx, pool, bibs)?; + print_bad_input_line(ctx, buffers); print_skipping_whatever_remains(); if at_bib_command { write_logs("command\n"); @@ -400,23 +437,29 @@ pub(crate) fn bib_err_print( Ok(()) } -pub(crate) fn bib_warn_print(pool: &StringPool, bibs: &BibData) -> Result<(), BibtexError> { - bib_ln_num_print(pool, bibs)?; - mark_warning(); +pub(crate) fn bib_warn_print( + ctx: &mut Bibtex<'_, '_>, + pool: &StringPool, + bibs: &BibData, +) -> Result<(), BibtexError> { + bib_ln_num_print(ctx, pool, bibs)?; + ctx.mark_warning(); Ok(()) } pub(crate) fn eat_bib_print( + ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer, pool: &StringPool, bibs: &BibData, at_bib_command: bool, ) -> Result<(), BibtexError> { write_logs("Illegal end of database file"); - bib_err_print(buffers, pool, bibs, at_bib_command) + bib_err_print(ctx, buffers, pool, bibs, at_bib_command) } pub(crate) fn bib_one_of_two_print( + ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer, pool: &StringPool, bibs: &BibData, @@ -428,27 +471,29 @@ pub(crate) fn bib_one_of_two_print( "I was expecting a `{}' or a `{}'", char1 as char, char2 as char )); - bib_err_print(buffers, pool, bibs, at_bib_command) + bib_err_print(ctx, buffers, pool, bibs, at_bib_command) } pub(crate) fn bib_equals_sign_print( + ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer, pool: &StringPool, bibs: &BibData, at_bib_command: bool, ) -> Result<(), BibtexError> { write_logs("I was expecting an \"=\""); - bib_err_print(buffers, pool, bibs, at_bib_command) + bib_err_print(ctx, buffers, pool, bibs, at_bib_command) } pub(crate) fn bib_unbalanced_braces_print( + ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer, pool: &StringPool, bibs: &BibData, at_bib_command: bool, ) -> Result<(), BibtexError> { write_logs("Unbalanced braces"); - bib_err_print(buffers, pool, bibs, at_bib_command) + bib_err_print(ctx, buffers, pool, bibs, at_bib_command) } pub(crate) fn macro_warn_print(buffers: &GlobalBuffer) { @@ -457,7 +502,11 @@ pub(crate) fn macro_warn_print(buffers: &GlobalBuffer) { write_logs("\" is "); } -pub(crate) fn bib_id_print(buffers: &GlobalBuffer, scan_res: ScanRes) -> Result<(), BibtexError> { +pub(crate) fn bib_id_print( + ctx: &mut Bibtex<'_, '_>, + buffers: &GlobalBuffer, + scan_res: ScanRes, +) -> Result<(), BibtexError> { match scan_res { ScanRes::IdNull => { write_logs("You're missing "); @@ -469,59 +518,64 @@ pub(crate) fn bib_id_print(buffers: &GlobalBuffer, scan_res: ScanRes) -> Result< Ok(()) } _ => { - id_scanning_confusion(); + id_scanning_confusion(ctx); Err(BibtexError::Fatal) } } } -pub(crate) fn bib_cmd_confusion() { +pub(crate) fn bib_cmd_confusion(ctx: &mut Bibtex<'_, '_>) { write_logs("Unknown database-file command"); - print_confusion(); + print_confusion(ctx); } -pub fn cite_key_disappeared_confusion() { +pub fn cite_key_disappeared_confusion(ctx: &mut Bibtex<'_, '_>) { write_logs("A cite key disappeared"); - print_confusion(); + print_confusion(ctx); } -pub(crate) fn rs_bad_cross_reference_print( +pub(crate) fn bad_cross_reference_print( + ctx: &mut Bibtex<'_, '_>, pool: &StringPool, cites: &CiteInfo, cite_ptr: CiteNumber, s: StrNumber, ) -> Result<(), BibtexError> { write_logs("--entry \""); - print_a_pool_str(cites.get_cite(cite_ptr), pool)?; + print_a_pool_str(ctx, cites.get_cite(cite_ptr), pool)?; write_logs("\"\nrefers to entry \""); - print_a_pool_str(s, pool)?; + print_a_pool_str(ctx, s, pool)?; write_logs("\""); Ok(()) } -pub(crate) fn print_missing_entry(pool: &StringPool, s: StrNumber) -> Result<(), BibtexError> { +pub(crate) fn print_missing_entry( + ctx: &mut Bibtex<'_, '_>, + pool: &StringPool, + s: StrNumber, +) -> Result<(), BibtexError> { write_logs("Warning--I didn't find a database entry for \""); - print_a_pool_str(s, pool)?; + print_a_pool_str(ctx, s, pool)?; write_logs("\"\n"); - mark_warning(); + ctx.mark_warning(); Ok(()) } pub(crate) fn bst_mild_ex_warn_print( - ctx: &ExecCtx<'_, '_, '_>, + ctx: &mut ExecCtx<'_, '_, '_>, pool: &StringPool, cites: &CiteInfo, ) -> Result<(), BibtexError> { if ctx.mess_with_entries { write_logs(" for entry "); - print_a_pool_str(cites.get_cite(cites.ptr()), pool)?; + print_a_pool_str(ctx.glbl_ctx_mut(), cites.get_cite(cites.ptr()), pool)?; } write_logs("\nwhile executing"); - bst_warn_print(ctx.glbl_ctx(), pool) + bst_warn_print(ctx.glbl_ctx_mut(), pool) } pub(crate) fn bst_cant_mess_with_entries_print( - ctx: &ExecCtx<'_, '_, '_>, + ctx: &mut ExecCtx<'_, '_, '_>, pool: &StringPool, cites: &CiteInfo, ) -> Result<(), BibtexError> { @@ -534,7 +588,7 @@ pub fn bst_1print_string_size_exceeded() { } pub(crate) fn bst_2print_string_size_exceeded( - ctx: &ExecCtx<'_, '_, '_>, + ctx: &mut ExecCtx<'_, '_, '_>, pool: &StringPool, cites: &CiteInfo, ) -> Result<(), BibtexError> { @@ -545,13 +599,13 @@ pub(crate) fn bst_2print_string_size_exceeded( } pub(crate) fn braces_unbalanced_complaint( - ctx: &ExecCtx<'_, '_, '_>, + ctx: &mut ExecCtx<'_, '_, '_>, pool: &StringPool, cites: &CiteInfo, pop_lit_var: StrNumber, ) -> Result<(), BibtexError> { write_logs("Warning--\""); - print_a_pool_str(pop_lit_var, pool)?; + print_a_pool_str(ctx.glbl_ctx_mut(), pop_lit_var, pool)?; write_logs("\" isn't a brace-balanced string"); bst_mild_ex_warn_print(ctx, pool, cites) } @@ -578,7 +632,7 @@ pub(crate) fn bst_err_print_and_look_for_blank_line( ) -> Result<(), BibtexError> { write_logs("-"); bst_ln_num_print(ctx, pool)?; - print_bad_input_line(buffers); + print_bad_input_line(ctx, buffers); while buffers.init(BufTy::Base) != 0 { if !input_ln(&mut ctx.bst.as_mut().unwrap().file, buffers) { return Err(BibtexError::Recover); @@ -597,14 +651,15 @@ pub(crate) fn already_seen_function_print( hash: &HashData, seen_fn_loc: HashPointer, ) -> Result<(), BibtexError> { - print_a_pool_str(hash.text(seen_fn_loc), pool)?; + print_a_pool_str(ctx, hash.text(seen_fn_loc), pool)?; write_logs(" is already a type \""); rs_print_fn_class(hash, seen_fn_loc); write_logs("\" function name\n"); bst_err_print_and_look_for_blank_line(ctx, buffers, pool) } -pub(crate) fn rs_nonexistent_cross_reference_error( +pub(crate) fn nonexistent_cross_reference_error( + ctx: &mut Bibtex<'_, '_>, pool: &StringPool, cites: &CiteInfo, other: &OtherData, @@ -612,9 +667,9 @@ pub(crate) fn rs_nonexistent_cross_reference_error( field_ptr: FieldLoc, ) -> Result<(), BibtexError> { write_logs("A bad cross reference-"); - rs_bad_cross_reference_print(pool, cites, cite_ptr, other.field(field_ptr))?; + bad_cross_reference_print(ctx, pool, cites, cite_ptr, other.field(field_ptr))?; write_logs(", which doesn't exist\n"); - mark_error(); + ctx.mark_error(); Ok(()) } @@ -643,13 +698,13 @@ pub(crate) fn output_bbl_line(ctx: &mut Bibtex<'_, '_>, buffers: &mut GlobalBuff } pub(crate) fn skip_token_print( - ctx: &Bibtex<'_, '_>, + ctx: &mut Bibtex<'_, '_>, buffers: &mut GlobalBuffer, pool: &StringPool, ) -> Result<(), BibtexError> { write_logs("-"); bst_ln_num_print(ctx, pool)?; - mark_error(); + ctx.mark_error(); Scan::new() .chars(b"}%") @@ -660,7 +715,7 @@ pub(crate) fn skip_token_print( } pub(crate) fn print_recursion_illegal( - ctx: &Bibtex<'_, '_>, + ctx: &mut Bibtex<'_, '_>, buffers: &mut GlobalBuffer, pool: &StringPool, ) -> Result<(), BibtexError> { @@ -671,7 +726,7 @@ pub(crate) fn print_recursion_illegal( } pub(crate) fn skip_token_unknown_function_print( - ctx: &Bibtex<'_, '_>, + ctx: &mut Bibtex<'_, '_>, buffers: &mut GlobalBuffer, pool: &StringPool, ) -> Result<(), BibtexError> { @@ -681,7 +736,7 @@ pub(crate) fn skip_token_unknown_function_print( } pub(crate) fn skip_illegal_stuff_after_token_print( - ctx: &Bibtex<'_, '_>, + ctx: &mut Bibtex<'_, '_>, buffers: &mut GlobalBuffer, pool: &StringPool, ) -> Result<(), BibtexError> { @@ -693,13 +748,13 @@ pub(crate) fn skip_illegal_stuff_after_token_print( } pub(crate) fn brace_lvl_one_letters_complaint( - ctx: &ExecCtx<'_, '_, '_>, + ctx: &mut ExecCtx<'_, '_, '_>, pool: &StringPool, cites: &CiteInfo, str: StrNumber, ) -> Result<(), BibtexError> { write_logs("The format string \""); - print_a_pool_str(str, pool)?; + print_a_pool_str(ctx.glbl_ctx_mut(), str, pool)?; write_logs("\" has an illegal brace-level-1 letter"); bst_ex_warn_print(ctx, pool, cites)?; Ok(()) diff --git a/crates/engine_bibtex/src/pool.rs b/crates/engine_bibtex/src/pool.rs index 42fabd46a..8566f2574 100644 --- a/crates/engine_bibtex/src/pool.rs +++ b/crates/engine_bibtex/src/pool.rs @@ -65,9 +65,9 @@ impl StringPool { /// Used while defining strings - declare the current `pool_ptr` as the end of the current /// string, increment the `str_ptr`, and return the new string's `StrNumber` - pub fn make_string(&mut self) -> Result { + pub fn make_string(&mut self, ctx: &mut Bibtex<'_, '_>) -> Result { if self.str_ptr == MAX_STRINGS { - print_overflow(); + print_overflow(ctx); write_logs(&format!("number of strings {}\n", MAX_STRINGS)); return Err(BibtexError::Fatal); } @@ -110,6 +110,7 @@ impl StringPool { /// string is found or not, only returning `Err` if a called function fails. pub(crate) fn lookup_str_insert( &mut self, + ctx: &mut Bibtex<'_, '_>, hash: &mut HashData, str: &[ASCIICode], ilk: StrIlk, @@ -135,7 +136,7 @@ impl StringPool { if existing > 0 { loop { if hash.used() == hash::HASH_BASE { - print_overflow(); + print_overflow(ctx); write_logs(&format!("hash size {}\n", hash::HASH_SIZE)); return Err(BibtexError::Fatal); } @@ -158,7 +159,7 @@ impl StringPool { self.strings[self.pool_ptr..self.pool_ptr + str.len()].copy_from_slice(str); self.pool_ptr += str.len(); - match self.make_string() { + match self.make_string(ctx) { Ok(str) => hash.set_text(p, str), Err(err) => return Err(err), } @@ -224,13 +225,17 @@ impl StringPool { self.pool_ptr += 1; } - pub fn add_string_raw(&mut self, str: &[ASCIICode]) -> Result { + pub fn add_string_raw( + &mut self, + ctx: &mut Bibtex<'_, '_>, + str: &[ASCIICode], + ) -> Result { while self.pool_ptr + str.len() > self.strings.len() { self.grow(); } self.strings[self.pool_ptr..self.pool_ptr + str.len()].copy_from_slice(str); self.pool_ptr += str.len(); - self.make_string() + self.make_string(ctx) } #[allow(clippy::len_without_is_empty)] @@ -262,48 +267,48 @@ pub(crate) fn pre_def_certain_strings( .. }: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { - let res = pool.lookup_str_insert(hash, b".aux", StrIlk::FileExt)?; + let res = pool.lookup_str_insert(ctx, hash, b".aux", StrIlk::FileExt)?; ctx.s_aux_extension = hash.text(res.loc); - let res = pool.lookup_str_insert(hash, b"\\citation", StrIlk::AuxCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"\\citation", StrIlk::AuxCommand)?; hash.set_ilk_info(res.loc, 2); - let res = pool.lookup_str_insert(hash, b"\\bibdata", StrIlk::AuxCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"\\bibdata", StrIlk::AuxCommand)?; hash.set_ilk_info(res.loc, 0); - let res = pool.lookup_str_insert(hash, b"\\bibstyle", StrIlk::AuxCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"\\bibstyle", StrIlk::AuxCommand)?; hash.set_ilk_info(res.loc, 1); - let res = pool.lookup_str_insert(hash, b"\\@input", StrIlk::AuxCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"\\@input", StrIlk::AuxCommand)?; hash.set_ilk_info(res.loc, 3); - let res = pool.lookup_str_insert(hash, b"entry", StrIlk::BstCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"entry", StrIlk::BstCommand)?; hash.set_ilk_info(res.loc, 0); - let res = pool.lookup_str_insert(hash, b"execute", StrIlk::BstCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"execute", StrIlk::BstCommand)?; hash.set_ilk_info(res.loc, 1); - let res = pool.lookup_str_insert(hash, b"function", StrIlk::BstCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"function", StrIlk::BstCommand)?; hash.set_ilk_info(res.loc, 2); - let res = pool.lookup_str_insert(hash, b"integers", StrIlk::BstCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"integers", StrIlk::BstCommand)?; hash.set_ilk_info(res.loc, 3); - let res = pool.lookup_str_insert(hash, b"iterate", StrIlk::BstCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"iterate", StrIlk::BstCommand)?; hash.set_ilk_info(res.loc, 4); - let res = pool.lookup_str_insert(hash, b"macro", StrIlk::BstCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"macro", StrIlk::BstCommand)?; hash.set_ilk_info(res.loc, 5); - let res = pool.lookup_str_insert(hash, b"read", StrIlk::BstCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"read", StrIlk::BstCommand)?; hash.set_ilk_info(res.loc, 6); - let res = pool.lookup_str_insert(hash, b"reverse", StrIlk::BstCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"reverse", StrIlk::BstCommand)?; hash.set_ilk_info(res.loc, 7); - let res = pool.lookup_str_insert(hash, b"sort", StrIlk::BstCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"sort", StrIlk::BstCommand)?; hash.set_ilk_info(res.loc, 8); - let res = pool.lookup_str_insert(hash, b"strings", StrIlk::BstCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"strings", StrIlk::BstCommand)?; hash.set_ilk_info(res.loc, 9); - let res = pool.lookup_str_insert(hash, b"comment", StrIlk::BibCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"comment", StrIlk::BibCommand)?; hash.set_ilk_info(res.loc, 0); - let res = pool.lookup_str_insert(hash, b"preamble", StrIlk::BibCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"preamble", StrIlk::BibCommand)?; hash.set_ilk_info(res.loc, 1); - let res = pool.lookup_str_insert(hash, b"string", StrIlk::BibCommand)?; + let res = pool.lookup_str_insert(ctx, hash, b"string", StrIlk::BibCommand)?; hash.set_ilk_info(res.loc, 2); let mut build_in = |pds: &[ASCIICode], blt_in_num| { - let res = pool.lookup_str_insert(hash, pds, StrIlk::BstFn)?; + let res = pool.lookup_str_insert(ctx, hash, pds, StrIlk::BstFn)?; hash.set_ty(res.loc, FnClass::Builtin); hash.set_ilk_info(res.loc, blt_in_num); Ok(res.loc) @@ -347,42 +352,42 @@ pub(crate) fn pre_def_certain_strings( build_in(b"width$", 35)?; build_in(b"write$", 36)?; - let res = pool.lookup_str_insert(hash, b"", StrIlk::Text)?; + let res = pool.lookup_str_insert(ctx, hash, b"", StrIlk::Text)?; hash.set_ty(res.loc, FnClass::StrLit); ctx.s_null = hash.text(res.loc); - let res = pool.lookup_str_insert(hash, b"default.type", StrIlk::Text)?; + let res = pool.lookup_str_insert(ctx, hash, b"default.type", StrIlk::Text)?; hash.set_ty(res.loc, FnClass::StrLit); ctx.s_default = hash.text(res.loc); ctx.b_default = skip_loc; - let res = pool.lookup_str_insert(hash, b"i", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"i", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 0); - let res = pool.lookup_str_insert(hash, b"j", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"j", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 1); - let res = pool.lookup_str_insert(hash, b"oe", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"oe", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 2); - let res = pool.lookup_str_insert(hash, b"OE", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"OE", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 3); - let res = pool.lookup_str_insert(hash, b"ae", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"ae", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 4); - let res = pool.lookup_str_insert(hash, b"AE", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"AE", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 5); - let res = pool.lookup_str_insert(hash, b"aa", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"aa", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 6); - let res = pool.lookup_str_insert(hash, b"AA", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"AA", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 7); - let res = pool.lookup_str_insert(hash, b"o", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"o", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 8); - let res = pool.lookup_str_insert(hash, b"O", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"O", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 9); - let res = pool.lookup_str_insert(hash, b"l", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"l", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 10); - let res = pool.lookup_str_insert(hash, b"L", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"L", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 11); - let res = pool.lookup_str_insert(hash, b"ss", StrIlk::ControlSeq)?; + let res = pool.lookup_str_insert(ctx, hash, b"ss", StrIlk::ControlSeq)?; hash.set_ilk_info(res.loc, 12); - let res = pool.lookup_str_insert(hash, b"crossref", StrIlk::BstFn)?; + let res = pool.lookup_str_insert(ctx, hash, b"crossref", StrIlk::BstFn)?; let num_fields = other.num_fields(); hash.set_ty(res.loc, FnClass::Field); hash.set_ilk_info(res.loc, num_fields as i32); @@ -390,17 +395,17 @@ pub(crate) fn pre_def_certain_strings( other.set_num_fields(num_fields + 1); other.set_pre_defined_fields(num_fields + 1); - let res = pool.lookup_str_insert(hash, b"sort.key$", StrIlk::BstFn)?; + let res = pool.lookup_str_insert(ctx, hash, b"sort.key$", StrIlk::BstFn)?; hash.set_ty(res.loc, FnClass::StrEntryVar); hash.set_ilk_info(res.loc, entries.num_ent_strs() as i32); entries.set_sort_key_num(entries.num_ent_strs()); entries.set_num_ent_strs(entries.num_ent_strs() + 1); - let res = pool.lookup_str_insert(hash, b"entry.max$", StrIlk::BstFn)?; + let res = pool.lookup_str_insert(ctx, hash, b"entry.max$", StrIlk::BstFn)?; hash.set_ty(res.loc, FnClass::IntGlblVar); hash.set_ilk_info(res.loc, ENT_STR_SIZE as i32); - let res = pool.lookup_str_insert(hash, b"global.max$", StrIlk::BstFn)?; + let res = pool.lookup_str_insert(ctx, hash, b"global.max$", StrIlk::BstFn)?; hash.set_ty(res.loc, FnClass::IntGlblVar); hash.set_ilk_info(res.loc, GLOB_STR_SIZE as i32); @@ -478,13 +483,15 @@ pub(crate) fn add_out_pool( #[cfg(test)] mod tests { use super::*; + use crate::BibtexConfig; #[test] fn test_pool() { + let mut ctx = Bibtex::new(todo!(), BibtexConfig::default()); let mut hash = HashData::new(); let mut new_pool = StringPool::new(); let res = new_pool - .lookup_str_insert(&mut hash, b"a cool string", StrIlk::Text) + .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", StrIlk::Text) .unwrap(); assert!(!res.exists); assert_eq!( @@ -493,7 +500,7 @@ mod tests { ); let res2 = new_pool - .lookup_str_insert(&mut hash, b"a cool string", StrIlk::Text) + .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", StrIlk::Text) .unwrap(); assert!(res2.exists); assert_eq!( diff --git a/crates/engine_bibtex/src/scan.rs b/crates/engine_bibtex/src/scan.rs index ce162643c..d8c8b6de6 100644 --- a/crates/engine_bibtex/src/scan.rs +++ b/crates/engine_bibtex/src/scan.rs @@ -199,7 +199,7 @@ fn handle_char( let res = { let str = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(hash, str, StrIlk::Integer)?; + let res = pool.lookup_str_insert(ctx, hash, str, StrIlk::Integer)?; if !res.exists { hash.set_ty(res.loc, FnClass::IntLit); @@ -232,7 +232,7 @@ fn handle_char( let res = { let str = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(hash, str, StrIlk::Text)?; + let res = pool.lookup_str_insert(ctx, hash, str, StrIlk::Text)?; hash.set_ty(res.loc, FnClass::StrLit); Ok(res) }?; @@ -281,11 +281,11 @@ fn handle_char( let str = format!("'{}", ctx.impl_fn_num); let res = { - let res = pool.lookup_str_insert(hash, str.as_bytes(), StrIlk::BstFn)?; + let res = pool.lookup_str_insert(ctx, hash, str.as_bytes(), StrIlk::BstFn)?; if res.exists { write_logs("Already encountered implicit function"); - print_confusion(); + print_confusion(ctx); return Err(BibtexError::Fatal); } ctx.impl_fn_num += 1; @@ -378,6 +378,7 @@ pub(crate) fn scan_fn_def( } fn scan_balanced_braces( + ctx: &mut Bibtex<'_, '_>, buffers: &mut GlobalBuffer, pool: &StringPool, bibs: &mut BibData, @@ -389,7 +390,7 @@ fn scan_balanced_braces( if (LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace || buffers.offset(BufTy::Base, 2) == buffers.init(BufTy::Base)) - && !compress_bib_white(buffers, pool, bibs, at_bib_command)? + && !compress_bib_white(ctx, buffers, pool, bibs, at_bib_command)? { return Ok(false); } @@ -420,7 +421,7 @@ fn scan_balanced_braces( if (LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace || buffers.offset(BufTy::Base, 2) == buffers.init(BufTy::Base)) - && !compress_bib_white(buffers, pool, bibs, at_bib_command)? + && !compress_bib_white(ctx, buffers, pool, bibs, at_bib_command)? { return Ok(false); } @@ -459,7 +460,7 @@ fn scan_balanced_braces( if (LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace || buffers.offset(BufTy::Base, 2) == buffers.init(BufTy::Base)) - && !compress_bib_white(buffers, pool, bibs, at_bib_command)? + && !compress_bib_white(ctx, buffers, pool, bibs, at_bib_command)? { return Ok(false); } @@ -470,7 +471,7 @@ fn scan_balanced_braces( } } b'}' => { - return bib_unbalanced_braces_print(buffers, pool, bibs, at_bib_command) + return bib_unbalanced_braces_print(ctx, buffers, pool, bibs, at_bib_command) .map(|_| false); } c => { @@ -489,7 +490,7 @@ fn scan_balanced_braces( if (LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace || buffers.offset(BufTy::Base, 2) == buffers.init(BufTy::Base)) - && !compress_bib_white(buffers, pool, bibs, at_bib_command)? + && !compress_bib_white(ctx, buffers, pool, bibs, at_bib_command)? { return Ok(false); } @@ -503,7 +504,8 @@ fn scan_balanced_braces( brace_level += 1; buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); if !eat_bib_white_space(buffers, bibs) { - return eat_bib_print(buffers, pool, bibs, at_bib_command).map(|_| false); + return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command) + .map(|_| false); } while brace_level > 0 { let c = buffers.at_offset(BufTy::Base, 2); @@ -521,13 +523,13 @@ fn scan_balanced_braces( || !Scan::new().chars(b"{}").scan_till(buffers, init)) && !eat_bib_white_space(buffers, bibs) { - return eat_bib_print(buffers, pool, bibs, at_bib_command) + return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command) .map(|_| false); } } } b'}' => { - return bib_unbalanced_braces_print(buffers, pool, bibs, at_bib_command) + return bib_unbalanced_braces_print(ctx, buffers, pool, bibs, at_bib_command) .map(|_| false); } _ => { @@ -538,7 +540,8 @@ fn scan_balanced_braces( .scan_till(buffers, init) && !eat_bib_white_space(buffers, bibs) { - return eat_bib_print(buffers, pool, bibs, at_bib_command).map(|_| false); + return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command) + .map(|_| false); } } } @@ -551,6 +554,7 @@ fn scan_balanced_braces( #[allow(clippy::too_many_arguments)] fn scan_a_field_token_and_eat_white( + ctx: &mut Bibtex<'_, '_>, buffers: &mut GlobalBuffer, hash: &HashData, pool: &StringPool, @@ -563,12 +567,12 @@ fn scan_a_field_token_and_eat_white( ) -> Result { match buffers.at_offset(BufTy::Base, 2) { b'{' => { - if !scan_balanced_braces(buffers, pool, bibs, store_field, at_bib_command, b'}')? { + if !scan_balanced_braces(ctx, buffers, pool, bibs, store_field, at_bib_command, b'}')? { return Ok(false); } } b'"' => { - if !scan_balanced_braces(buffers, pool, bibs, store_field, at_bib_command, b'"')? { + if !scan_balanced_braces(ctx, buffers, pool, bibs, store_field, at_bib_command, b'"')? { return Ok(false); } } @@ -579,7 +583,7 @@ fn scan_a_field_token_and_eat_white( .scan_till_nonempty(buffers, last) { write_logs("A digit disappeared"); - print_confusion(); + print_confusion(ctx); return Err(BibtexError::Fatal); } @@ -613,9 +617,9 @@ fn scan_a_field_token_and_eat_white( res, ScanRes::WhitespaceAdjacent | ScanRes::SpecifiedCharAdjacent ) { - bib_id_print(buffers, res)?; + bib_id_print(ctx, buffers, res)?; write_logs("a field part"); - bib_err_print(buffers, pool, bibs, at_bib_command)?; + bib_err_print(ctx, buffers, pool, bibs, at_bib_command)?; return Ok(false); } @@ -632,14 +636,14 @@ fn scan_a_field_token_and_eat_white( store_token = false; macro_warn_print(buffers); write_logs("used in its own definition\n"); - bib_warn_print(pool, bibs)?; + bib_warn_print(ctx, pool, bibs)?; } if !res.exists { store_token = false; macro_warn_print(buffers); write_logs("undefined\n"); - bib_warn_print(pool, bibs)?; + bib_warn_print(ctx, pool, bibs)?; } if store_token { @@ -688,7 +692,7 @@ fn scan_a_field_token_and_eat_white( } if !eat_bib_white_space(buffers, bibs) { - return eat_bib_print(buffers, pool, bibs, at_bib_command).map(|_| false); + return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command).map(|_| false); } Ok(true) } @@ -696,7 +700,7 @@ fn scan_a_field_token_and_eat_white( // TODO: Refactor this to bundle up arguments into structs as relevant #[allow(clippy::too_many_arguments)] pub(crate) fn scan_and_store_the_field_value_and_eat_white( - ctx: &Bibtex<'_, '_>, + ctx: &mut Bibtex<'_, '_>, buffers: &mut GlobalBuffer, hash: &mut HashData, pool: &mut StringPool, @@ -714,6 +718,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( // Consume tokens/strings separated by # buffers.set_offset(BufTy::Ex, 1, 0); if !scan_a_field_token_and_eat_white( + ctx, buffers, hash, pool, @@ -729,9 +734,10 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( while buffers.at_offset(BufTy::Base, 2) == b'#' { buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); if !eat_bib_white_space(buffers, bibs) { - return eat_bib_print(buffers, pool, bibs, at_bib_command).map(|_| false); + return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command).map(|_| false); } if !scan_a_field_token_and_eat_white( + ctx, buffers, hash, pool, @@ -765,7 +771,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( let str = &buffers.buffer(BufTy::Ex)[ex_buf_xptr..buffers.offset(BufTy::Ex, 1)]; let res = { - let res = pool.lookup_str_insert(hash, str, StrIlk::Text)?; + let res = pool.lookup_str_insert(ctx, hash, str, StrIlk::Text)?; hash.set_ty(res.loc, FnClass::StrLit); @@ -778,7 +784,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( 2 => hash.set_ilk_info(cur_macro_loc, hash.text(res.loc) as i32), _ => { // TODO: Replace command_num with an enum - bib_cmd_confusion(); + bib_cmd_confusion(ctx); return Err(BibtexError::Fatal); } } @@ -787,7 +793,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( cites.entry_ptr() * other.num_fields() + hash.ilk_info(field_name_loc) as usize; if field_ptr >= other.max_fields() { write_logs("field_info index is out of range"); - print_confusion(); + print_confusion(ctx); return Err(BibtexError::Fatal); } @@ -795,11 +801,11 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( /* missing */ { write_logs("Warning--I'm ignoring "); - print_a_pool_str(cites.get_cite(cites.entry_ptr()), pool)?; + print_a_pool_str(ctx, cites.get_cite(cites.entry_ptr()), pool)?; write_logs("'s extra \""); - print_a_pool_str(hash.text(field_name_loc), pool)?; + print_a_pool_str(ctx, hash.text(field_name_loc), pool)?; write_logs("\" field\n"); - bib_warn_print(pool, bibs)?; + bib_warn_print(ctx, pool, bibs)?; } else { other.set_field(field_ptr, hash.text(res.loc)); if hash.ilk_info(field_name_loc) as usize == other.crossref_num() @@ -816,7 +822,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( ); buffers.buffer_mut(BufTy::Out)[ex_buf_xptr..end].make_ascii_lowercase(); let str = &buffers.buffer(BufTy::Out)[ex_buf_xptr..end]; - let lc_res = pool.lookup_str_insert(hash, str, StrIlk::LcCite)?; + let lc_res = pool.lookup_str_insert(ctx, hash, str, StrIlk::LcCite)?; if let Some(cite_out) = cite_out { *cite_out = lc_res.loc; } @@ -829,9 +835,9 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( } else { let str = &buffers.buffer(BufTy::Ex)[ex_buf_xptr..buffers.offset(BufTy::Ex, 1)]; - let c_res = pool.lookup_str_insert(hash, str, StrIlk::Cite)?; + let c_res = pool.lookup_str_insert(ctx, hash, str, StrIlk::Cite)?; if c_res.exists { - hash_cite_confusion(); + hash_cite_confusion(ctx); return Err(BibtexError::Fatal); } let new_ptr = add_database_cite( @@ -854,7 +860,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( } pub(crate) fn decr_brace_level( - ctx: &ExecCtx<'_, '_, '_>, + ctx: &mut ExecCtx<'_, '_, '_>, pool: &StringPool, cites: &CiteInfo, pop_lit_var: StrNumber, @@ -870,7 +876,7 @@ pub(crate) fn decr_brace_level( } pub(crate) fn check_brace_level( - ctx: &ExecCtx<'_, '_, '_>, + ctx: &mut ExecCtx<'_, '_, '_>, pool: &StringPool, cites: &CiteInfo, pop_lit_var: StrNumber, @@ -883,7 +889,7 @@ pub(crate) fn check_brace_level( } pub(crate) fn name_scan_for_and( - ctx: &ExecCtx<'_, '_, '_>, + ctx: &mut ExecCtx<'_, '_, '_>, pool: &StringPool, buffers: &mut GlobalBuffer, cites: &CiteInfo, @@ -942,6 +948,7 @@ pub(crate) fn name_scan_for_and( } pub(crate) fn von_token_found( + ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer, hash: &HashData, pool: &StringPool, @@ -973,7 +980,7 @@ pub(crate) fn von_token_found( 0 | 1 | 2 | 4 | 6 | 8 | 10 | 12 => return Ok(true), _ => { write_logs("Control-sequence hash error"); - print_confusion(); + print_confusion(ctx); return Err(BibtexError::Fatal); } } @@ -1013,6 +1020,7 @@ pub(crate) fn von_token_found( #[allow(clippy::too_many_arguments)] pub(crate) fn von_name_ends_and_last_name_starts_stuff( + ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer, hash: &HashData, pool: &StringPool, @@ -1026,7 +1034,7 @@ pub(crate) fn von_name_ends_and_last_name_starts_stuff( while *von_end > von_start { *name_bf_ptr = buffers.name_tok(*von_end - 1); *name_bf_xptr = buffers.name_tok(*von_end); - if von_token_found(buffers, hash, pool, name_bf_ptr, *name_bf_xptr)? { + if von_token_found(ctx, buffers, hash, pool, name_bf_ptr, *name_bf_xptr)? { return Ok(()); } *von_end -= 1; From 996c4a349dc138038136ca50d7ab98d91e930d31 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Wed, 21 Feb 2024 09:13:55 -0800 Subject: [PATCH 09/23] Remove logs thread_local, making bibtex engine fully re-entrant, aside from the running context itself --- crates/engine_bibtex/src/auxi.rs | 94 ++++---- crates/engine_bibtex/src/bibs.rs | 26 +-- crates/engine_bibtex/src/bst.rs | 94 ++++---- crates/engine_bibtex/src/exec.rs | 123 ++++++----- crates/engine_bibtex/src/lib.rs | 90 ++++++-- crates/engine_bibtex/src/log.rs | 357 ++++++++++++------------------- crates/engine_bibtex/src/pool.rs | 6 +- crates/engine_bibtex/src/scan.rs | 55 +++-- 8 files changed, 424 insertions(+), 421 deletions(-) diff --git a/crates/engine_bibtex/src/auxi.rs b/crates/engine_bibtex/src/auxi.rs index ebc48b9ed..13aebe8f1 100644 --- a/crates/engine_bibtex/src/auxi.rs +++ b/crates/engine_bibtex/src/auxi.rs @@ -10,7 +10,7 @@ use crate::{ aux_err_no_right_brace_print, aux_err_print, aux_err_stuff_after_right_brace_print, aux_err_white_space_in_argument_print, hash_cite_confusion, log_pr_aux_name, log_pr_bst_name, print_a_pool_str, print_a_token, print_aux_name, print_bib_name, - print_confusion, print_overflow, write_log_file, write_logs, AuxTy, + print_confusion, print_overflow, AuxTy, }, peekable::PeekableInput, pool::StringPool, @@ -62,7 +62,7 @@ fn aux_bib_data_command( hash: &mut HashData, ) -> Result<(), BibtexError> { if ctx.bib_seen { - aux_err_illegal_another_print(AuxTy::Data)?; + aux_err_illegal_another_print(ctx, AuxTy::Data)?; aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } @@ -76,13 +76,13 @@ fn aux_bib_data_command( .class(LexClass::Whitespace) .scan_till(buffers, init) { - aux_err_no_right_brace_print(); + aux_err_no_right_brace_print(ctx); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace { - aux_err_white_space_in_argument_print(); + aux_err_white_space_in_argument_print(ctx); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } @@ -90,7 +90,7 @@ fn aux_bib_data_command( if buffers.init(BufTy::Base) > buffers.offset(BufTy::Base, 2) + 1 && buffers.at_offset(BufTy::Base, 2) == b'}' { - aux_err_stuff_after_right_brace_print(); + aux_err_stuff_after_right_brace_print(ctx); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } @@ -99,7 +99,7 @@ fn aux_bib_data_command( [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; let res = pool.lookup_str_insert(ctx, hash, file, StrIlk::BibFile)?; if res.exists { - write_logs("This database file appears more than once: "); + ctx.write_logs("This database file appears more than once: "); print_bib_name(ctx, pool, hash.text(res.loc))?; aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); @@ -110,7 +110,7 @@ fn aux_bib_data_command( let bib_in = PeekableInput::open(ctx, &fname, FileFormat::Bib); match bib_in { Err(_) => { - write_logs("I couldn't open database file "); + ctx.write_logs("I couldn't open database file "); print_bib_name(ctx, pool, hash.text(res.loc))?; aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); @@ -136,7 +136,7 @@ fn aux_bib_style_command( hash: &mut HashData, ) -> Result<(), BibtexError> { if ctx.bst_seen { - aux_err_illegal_another_print(AuxTy::Style)?; + aux_err_illegal_another_print(ctx, AuxTy::Style)?; aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } @@ -149,19 +149,19 @@ fn aux_bib_style_command( .class(LexClass::Whitespace) .scan_till(buffers, init) { - aux_err_no_right_brace_print(); + aux_err_no_right_brace_print(ctx); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace { - aux_err_white_space_in_argument_print(); + aux_err_white_space_in_argument_print(ctx); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if buffers.init(BufTy::Base) > buffers.offset(BufTy::Base, 2) + 1 { - aux_err_stuff_after_right_brace_print(); + aux_err_stuff_after_right_brace_print(ctx); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } @@ -170,7 +170,7 @@ fn aux_bib_style_command( [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; let res = pool.lookup_str_insert(ctx, hash, file, StrIlk::BstFile)?; if res.exists { - write_logs("Already encountered style file"); + ctx.write_logs("Already encountered style file"); print_confusion(ctx); return Err(BibtexError::Fatal); } @@ -180,7 +180,7 @@ fn aux_bib_style_command( let bst_file = PeekableInput::open(ctx, &fname, FileFormat::Bst); match bst_file { Err(_) => { - write_logs("I couldn't open style file "); + ctx.write_logs("I couldn't open style file "); print_bst_name(ctx, pool, hash.text(res.loc))?; ctx.bst = None; aux_err_print(ctx, buffers, aux, pool)?; @@ -196,10 +196,10 @@ fn aux_bib_style_command( } if ctx.config.verbose { - write_logs("The style file: "); + ctx.write_logs("The style file: "); print_bst_name(ctx, pool, ctx.bst.as_ref().unwrap().name)?; } else { - write_log_file("The style file: "); + ctx.write_log_file("The style file: "); log_pr_bst_name(ctx, pool)?; } @@ -225,19 +225,19 @@ fn aux_citation_command( .class(LexClass::Whitespace) .scan_till(buffers, init) { - aux_err_no_right_brace_print(); + aux_err_no_right_brace_print(ctx); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace { - aux_err_white_space_in_argument_print(); + aux_err_white_space_in_argument_print(ctx); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if buffers.init(BufTy::Base) > buffers.offset(BufTy::Base, 2) + 1 && buffers.at_offset(BufTy::Base, 2) == b'}' { - aux_err_stuff_after_right_brace_print(); + aux_err_stuff_after_right_brace_print(ctx); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } @@ -246,7 +246,7 @@ fn aux_citation_command( && buffers.at_offset(BufTy::Base, 1) == b'*' { if ctx.all_entries { - write_logs("Multiple inclusions of entire database\n"); + ctx.write_logs("Multiple inclusions of entire database\n"); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } else { @@ -274,15 +274,15 @@ fn aux_citation_command( [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; let uc_res = pool.lookup_str(hash, cite, StrIlk::Cite); if !uc_res.exists { - write_logs("Case mismatch error between cite keys "); - print_a_token(buffers); - write_logs(" and "); + ctx.write_logs("Case mismatch error between cite keys "); + print_a_token(ctx, buffers); + ctx.write_logs(" and "); print_a_pool_str( ctx, cites.get_cite(hash.ilk_info(hash.ilk_info(lc_res.loc) as usize) as usize), pool, )?; - write_logs("\n"); + ctx.write_logs("\n"); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } @@ -324,26 +324,26 @@ fn aux_input_command( .class(LexClass::Whitespace) .scan_till(buffers, init) { - aux_err_no_right_brace_print(); + aux_err_no_right_brace_print(ctx); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace { - aux_err_white_space_in_argument_print(); + aux_err_white_space_in_argument_print(ctx); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if buffers.init(BufTy::Base) > buffers.offset(BufTy::Base, 2) + 1 { - aux_err_stuff_after_right_brace_print(); + aux_err_stuff_after_right_brace_print(ctx); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } if aux.ptr() == AUX_STACK_SIZE { - print_a_token(buffers); - write_logs(": "); + print_a_token(ctx, buffers); + ctx.write_logs(": "); print_overflow(ctx); - write_logs(&format!("auxiliary file depth {}\n", AUX_STACK_SIZE)); + ctx.write_logs(&format!("auxiliary file depth {}\n", AUX_STACK_SIZE)); return Err(BibtexError::Fatal); } @@ -355,8 +355,8 @@ fn aux_input_command( [buffers.offset(BufTy::Base, 2) - aux_ext.len()..buffers.offset(BufTy::Base, 2)]); if !aux_extension_ok { - print_a_token(buffers); - write_logs(" has a wrong extension"); + print_a_token(ctx, buffers); + ctx.write_logs(" has a wrong extension"); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); } @@ -365,7 +365,7 @@ fn aux_input_command( [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; let res = pool.lookup_str_insert(ctx, hash, file, StrIlk::AuxFile)?; if res.exists { - write_logs("Already encountered file "); + ctx.write_logs("Already encountered file "); print_aux_name(ctx, pool, hash.text(res.loc))?; aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); @@ -376,7 +376,7 @@ fn aux_input_command( let file = PeekableInput::open(ctx, &fname, FileFormat::Tex); match file { Err(_) => { - write_logs("I couldn't open auxiliary file "); + ctx.write_logs("I couldn't open auxiliary file "); print_aux_name(ctx, pool, hash.text(res.loc))?; aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); @@ -390,7 +390,7 @@ fn aux_input_command( } } - write_logs(&format!("A level-{} auxiliary file: ", aux.ptr() - 1)); + ctx.write_logs(&format!("A level-{} auxiliary file: ", aux.ptr() - 1)); log_pr_aux_name(ctx, aux, pool)?; Ok(()) @@ -445,7 +445,7 @@ pub(crate) fn get_aux_command_and_process( globals.hash, )?, _ => { - write_logs("Unknown auxiliary-file command"); + ctx.write_logs("Unknown auxiliary-file command"); print_confusion(ctx); return Err(BibtexError::Fatal); } @@ -473,32 +473,32 @@ pub(crate) fn last_check_for_aux_errors( ) -> Result<(), BibtexError> { cites.set_num_cites(cites.ptr()); if !ctx.citation_seen { - aux_end1_err_print(); - write_logs("\\citation commands"); + aux_end1_err_print(ctx); + ctx.write_logs("\\citation commands"); aux_end2_err_print(ctx, pool, last_aux)?; } else if cites.num_cites() == 0 && !ctx.all_entries { - aux_end1_err_print(); - write_logs("cite keys"); + aux_end1_err_print(ctx); + ctx.write_logs("cite keys"); aux_end2_err_print(ctx, pool, last_aux)?; } if !ctx.bib_seen { - aux_end1_err_print(); - write_logs("\\bibdata command"); + aux_end1_err_print(ctx); + ctx.write_logs("\\bibdata command"); aux_end2_err_print(ctx, pool, last_aux)?; } else if bibs.len() == 0 { - aux_end1_err_print(); - write_logs("database files"); + aux_end1_err_print(ctx); + ctx.write_logs("database files"); aux_end2_err_print(ctx, pool, last_aux)?; } if !ctx.bst_seen { - aux_end1_err_print(); - write_logs("\\bibstyle command"); + aux_end1_err_print(ctx); + ctx.write_logs("\\bibstyle command"); aux_end2_err_print(ctx, pool, last_aux)?; } else if ctx.bst.is_none() { - aux_end1_err_print(); - write_logs("style file"); + aux_end1_err_print(ctx); + ctx.write_logs("style file"); aux_end2_err_print(ctx, pool, last_aux)?; } diff --git a/crates/engine_bibtex/src/bibs.rs b/crates/engine_bibtex/src/bibs.rs index 67387df0c..abf71015b 100644 --- a/crates/engine_bibtex/src/bibs.rs +++ b/crates/engine_bibtex/src/bibs.rs @@ -6,7 +6,7 @@ use crate::{ log::{ bib_cmd_confusion, bib_equals_sign_print, bib_err_print, bib_id_print, bib_one_of_two_print, bib_warn_print, cite_key_disappeared_confusion, eat_bib_print, - hash_cite_confusion, print_a_token, print_confusion, write_log_file, write_logs, + hash_cite_confusion, print_a_token, print_confusion, }, peekable::input_ln, pool::StringPool, @@ -85,7 +85,7 @@ pub(crate) fn compress_bib_white( at_bib_command: bool, ) -> Result { if buffers.offset(BufTy::Ex, 1) == buffers.len() { - write_log_file("Field filled up at ' ', reallocating.\n"); + ctx.write_log_file("Field filled up at ' ', reallocating.\n"); buffers.grow_all(); } @@ -134,7 +134,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( } if globals.buffers.at_offset(BufTy::Base, 2) != b'@' { - write_logs("An \"@\" disappeared"); + ctx.write_logs("An \"@\" disappeared"); print_confusion(ctx); return Err(BibtexError::Fatal); } @@ -159,7 +159,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( ScanRes::WhitespaceAdjacent | ScanRes::SpecifiedCharAdjacent => (), _ => { bib_id_print(ctx, globals.buffers, scan_res)?; - write_logs("an entry type"); + ctx.write_logs("an entry type"); bib_err_print( ctx, globals.buffers, @@ -251,7 +251,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( } if globals.buffers.at_offset(BufTy::Base, 2) != right_outer_delim { - write_logs(&format!( + ctx.write_logs(&format!( "Missing \"{}\" in preamble command", right_outer_delim )); @@ -321,7 +321,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( ScanRes::WhitespaceAdjacent | ScanRes::SpecifiedCharAdjacent => (), _ => { bib_id_print(ctx, globals.buffers, scan_res)?; - write_logs("a string name"); + ctx.write_logs("a string name"); bib_err_print( ctx, globals.buffers, @@ -408,7 +408,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( } if globals.buffers.at_offset(BufTy::Base, 2) != right_outer_delim { - write_logs(&format!( + ctx.write_logs(&format!( "Missing \"{}\" in string command", right_outer_delim )); @@ -581,12 +581,12 @@ pub(crate) fn get_bib_command_or_entry_and_process( } if globals.cites.get_type(entry_ptr) == 0 { - write_logs("The cite list is messed up"); + ctx.write_logs("The cite list is messed up"); print_confusion(ctx); return Some(Err(BibtexError::Fatal)); } - write_logs("Repeated entry"); + ctx.write_logs("Repeated entry"); return Some(bib_err_print( ctx, globals.buffers, @@ -653,9 +653,9 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals .cites .set_type(globals.cites.entry_ptr(), HashData::undefined()); - write_logs("Warning--entry type for \""); - print_a_token(globals.buffers); - write_logs("\" isn't style-file defined\n"); + ctx.write_logs("Warning--entry type for \""); + print_a_token(ctx, globals.buffers); + ctx.write_logs("\" isn't style-file defined\n"); bib_warn_print(ctx, globals.pool, globals.bibs)?; } } @@ -709,7 +709,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( ScanRes::WhitespaceAdjacent | ScanRes::SpecifiedCharAdjacent => (), _ => { bib_id_print(ctx, globals.buffers, scan_res)?; - write_logs("a field name"); + ctx.write_logs("a field name"); bib_err_print( ctx, globals.buffers, diff --git a/crates/engine_bibtex/src/bst.rs b/crates/engine_bibtex/src/bst.rs index 0a20838b6..ff61dae89 100644 --- a/crates/engine_bibtex/src/bst.rs +++ b/crates/engine_bibtex/src/bst.rs @@ -10,8 +10,7 @@ use crate::{ bst_err_print_and_look_for_blank_line, bst_id_print, bst_left_brace_print, bst_right_brace_print, bst_warn_print, cite_key_disappeared_confusion, eat_bst_print, hash_cite_confusion, log_pr_bib_name, nonexistent_cross_reference_error, print_a_token, - print_bib_name, print_confusion, print_missing_entry, rs_print_fn_class, write_log_file, - write_logs, + print_bib_name, print_confusion, print_fn_class, print_missing_entry, }, pool::StringPool, scan::{eat_bst_white_space, scan_fn_def, scan_identifier, Scan, ScanRes}, @@ -21,8 +20,8 @@ use crate::{ macro_rules! eat_bst_white { ($ctx:ident, $globals:ident, $name:literal) => { if !eat_bst_white_space($ctx.glbl_ctx_mut(), $globals.buffers) { - eat_bst_print(); - write_logs($name); + eat_bst_print($ctx.glbl_ctx_mut()); + $ctx.glbl_ctx_mut().write_logs($name); bst_err_print_and_look_for_blank_line( $ctx.glbl_ctx_mut(), $globals.buffers, @@ -36,8 +35,8 @@ macro_rules! eat_bst_white { macro_rules! bst_brace { ('{', $ctx:expr, $globals:ident, $name:literal) => { if $globals.buffers.at_offset(BufTy::Base, 2) != b'{' { - bst_left_brace_print(); - write_logs($name); + bst_left_brace_print($ctx.glbl_ctx_mut()); + $ctx.glbl_ctx_mut().write_logs($name); bst_err_print_and_look_for_blank_line( $ctx.glbl_ctx_mut(), $globals.buffers, @@ -48,8 +47,8 @@ macro_rules! bst_brace { }; ('}', $ctx:expr, $globals:ident, $name:literal) => { if $globals.buffers.at_offset(BufTy::Base, 2) != b'}' { - bst_right_brace_print(); - write_logs($name); + bst_right_brace_print($ctx.glbl_ctx_mut()); + $ctx.glbl_ctx_mut().write_logs($name); bst_err_print_and_look_for_blank_line( $ctx.glbl_ctx_mut(), $globals.buffers, @@ -67,7 +66,7 @@ macro_rules! bst_ident { ScanRes::WhitespaceAdjacent | ScanRes::SpecifiedCharAdjacent => (), _ => { bst_id_print($ctx.glbl_ctx_mut(), $globals.buffers, scan_res)?; - write_logs($name); + $ctx.glbl_ctx_mut().write_logs($name); bst_err_print_and_look_for_blank_line( $ctx.glbl_ctx_mut(), $globals.buffers, @@ -84,7 +83,8 @@ fn bst_entry_command( globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { if ctx.glbl_ctx().entry_seen { - write_logs("Illegal, another entry command"); + ctx.glbl_ctx_mut() + .write_logs("Illegal, another entry command"); bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } @@ -135,7 +135,8 @@ fn bst_entry_command( eat_bst_white!(ctx, globals, "entry"); if globals.other.num_fields() == globals.other.pre_defined_fields() { - write_logs("Warning--I didn't find any fields"); + ctx.glbl_ctx_mut() + .write_logs("Warning--I didn't find any fields"); bst_warn_print(ctx.glbl_ctx_mut(), globals.pool)?; } @@ -236,7 +237,8 @@ fn bst_execute_command( globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { if !ctx.glbl_ctx().read_seen { - write_logs("Illegal, execute command before read command"); + ctx.glbl_ctx_mut() + .write_logs("Illegal, execute command before read command"); bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } @@ -387,7 +389,8 @@ fn bst_iterate_command( globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { if !ctx.glbl_ctx().read_seen { - write_logs("Illegal, iterate command before read command"); + ctx.glbl_ctx_mut() + .write_logs("Illegal, iterate command before read command"); bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } @@ -437,7 +440,8 @@ fn bst_macro_command( globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { if ctx.glbl_ctx().read_seen { - write_logs("Illegal, macro command after read command"); + ctx.glbl_ctx_mut() + .write_logs("Illegal, macro command after read command"); bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } @@ -459,8 +463,9 @@ fn bst_macro_command( .pool .lookup_str_insert(ctx.glbl_ctx_mut(), globals.hash, bst_fn, StrIlk::Macro)?; if res.exists { - print_a_token(globals.buffers); - write_logs(" is already defined as a macro"); + print_a_token(ctx.glbl_ctx_mut(), globals.buffers); + ctx.glbl_ctx_mut() + .write_logs(" is already defined as a macro"); bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } @@ -480,7 +485,8 @@ fn bst_macro_command( .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); eat_bst_white!(ctx, globals, "macro"); if globals.buffers.at_offset(BufTy::Base, 2) != b'"' { - write_logs("A macro definition must be \"-delimited"); + ctx.glbl_ctx_mut() + .write_logs("A macro definition must be \"-delimited"); bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } @@ -488,8 +494,9 @@ fn bst_macro_command( .buffers .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); let init = globals.buffers.init(BufTy::Base); - if !Scan::new().chars(b"\"").scan_till(globals.buffers, init) { - write_logs("There's no `\"' to end macro definition"); + if !Scan::new().chars(&[b'"']).scan_till(globals.buffers, init) { + ctx.glbl_ctx_mut() + .write_logs("There's no `\"' to end macro definition"); bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } @@ -522,14 +529,16 @@ fn bst_read_command( globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { if ctx.glbl_ctx().read_seen { - write_logs("Illegal, another read command"); + ctx.glbl_ctx_mut() + .write_logs("Illegal, another read command"); bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } ctx.glbl_ctx_mut().read_seen = true; if !ctx.glbl_ctx().entry_seen { - write_logs("Illegal, read command before entry command"); + ctx.glbl_ctx_mut() + .write_logs("Illegal, read command before entry command"); bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } @@ -573,10 +582,12 @@ fn bst_read_command( ctx.glbl_ctx_mut().read_performed = true; while globals.bibs.len() != 0 { if ctx.glbl_ctx().config.verbose { - write_logs(&format!("Database file #{}: ", globals.bibs.len())); + ctx.glbl_ctx_mut() + .write_logs(&format!("Database file #{}: ", globals.bibs.len())); print_bib_name(ctx.glbl_ctx, globals.pool, globals.bibs.top_file().name)?; } else { - write_log_file(&format!("Database file #{}: ", globals.bibs.len())); + ctx.glbl_ctx_mut() + .write_log_file(&format!("Database file #{}: ", globals.bibs.len())); log_pr_bib_name(ctx.glbl_ctx, globals.bibs, globals.pool)?; } @@ -607,7 +618,8 @@ fn bst_read_command( if cites * globals.other.num_fields() + globals.other.crossref_num() >= globals.other.max_fields() { - write_logs("field_info index is out of range"); + ctx.glbl_ctx_mut() + .write_logs("field_info index is out of range"); print_confusion(ctx.glbl_ctx); return Err(BibtexError::Fatal); } @@ -687,7 +699,8 @@ fn bst_read_command( let field_parent_ptr = cite_parent_ptr * globals.other.num_fields() + globals.other.crossref_num(); if globals.other.field(field_parent_ptr) != 0 { - write_logs("Warning--you've nested cross references"); + ctx.glbl_ctx_mut() + .write_logs("Warning--you've nested cross references"); bad_cross_reference_print( ctx.glbl_ctx_mut(), globals.pool, @@ -695,7 +708,8 @@ fn bst_read_command( cite_ptr, globals.cites.get_cite(cite_parent_ptr), )?; - write_logs("\", which also refers to something\n"); + ctx.glbl_ctx_mut() + .write_logs("\", which also refers to something\n"); ctx.glbl_ctx_mut().mark_warning(); } if !ctx.glbl_ctx().all_entries @@ -725,7 +739,8 @@ fn bst_read_command( if (ctx.glbl_ctx().cite_xptr + 1) * globals.other.num_fields() > globals.other.max_fields() { - write_logs("field_info index is out of range"); + ctx.glbl_ctx_mut() + .write_logs("field_info index is out of range"); print_confusion(ctx.glbl_ctx); return Err(BibtexError::Fatal); } @@ -807,7 +822,8 @@ fn bst_reverse_command( globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { if !ctx.glbl_ctx().read_seen { - write_logs("Illegal, reverse command before read command"); + ctx.glbl_ctx_mut() + .write_logs("Illegal, reverse command before read command"); bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } @@ -856,7 +872,8 @@ fn bst_sort_command( globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { if !ctx.glbl_ctx().read_seen { - write_logs("Illegal, sort command before read command"); + ctx.glbl_ctx_mut() + .write_logs("Illegal, sort command before read command"); bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } @@ -947,14 +964,14 @@ fn bad_argument_token( } if !res.exists { - print_a_token(buffers); - write_logs(" is an unknown function"); + print_a_token(ctx, buffers); + ctx.write_logs(" is an unknown function"); bst_err_print_and_look_for_blank_line(ctx, buffers, pool)?; Ok(true) } else if hash.ty(res.loc) != FnClass::Builtin && hash.ty(res.loc) != FnClass::Wizard { - print_a_token(buffers); - write_logs(" has bad function type"); - rs_print_fn_class(hash, res.loc); + print_a_token(ctx, buffers); + ctx.write_logs(" has bad function type"); + print_fn_class(ctx, hash, res.loc); bst_err_print_and_look_for_blank_line(ctx, buffers, pool)?; Ok(true) } else { @@ -971,7 +988,7 @@ pub(crate) fn get_bst_command_and_process( .not_class(LexClass::Alpha) .scan_till_nonempty(globals.buffers, init) { - write_logs(&format!( + ctx.glbl_ctx_mut().write_logs(&format!( "\"{}\" can't start a style-file command", globals.buffers.at_offset(BufTy::Base, 2) as char, )); @@ -987,8 +1004,9 @@ pub(crate) fn get_bst_command_and_process( .pool .lookup_str(globals.hash, bst_cmd, StrIlk::BstCommand); if !res.exists { - print_a_token(globals.buffers); - write_logs(" is an illegal style-file command"); + print_a_token(ctx.glbl_ctx_mut(), globals.buffers); + ctx.glbl_ctx_mut() + .write_logs(" is an illegal style-file command"); bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } @@ -1005,7 +1023,7 @@ pub(crate) fn get_bst_command_and_process( 8 => bst_sort_command(ctx, globals), 9 => bst_strings_command(ctx, globals), _ => { - write_logs("Unknown style-file command"); + ctx.glbl_ctx_mut().write_logs("Unknown style-file command"); print_confusion(ctx.glbl_ctx); Err(BibtexError::Fatal) } diff --git a/crates/engine_bibtex/src/exec.rs b/crates/engine_bibtex/src/exec.rs index 0e6b466a4..3af7246c1 100644 --- a/crates/engine_bibtex/src/exec.rs +++ b/crates/engine_bibtex/src/exec.rs @@ -10,7 +10,7 @@ use crate::{ brace_lvl_one_letters_complaint, braces_unbalanced_complaint, bst_1print_string_size_exceeded, bst_2print_string_size_exceeded, bst_cant_mess_with_entries_print, output_bbl_line, print_a_pool_str, print_confusion, - rs_print_fn_class, write_logs, + print_fn_class, }, pool::{add_buf_pool, add_out_pool, StringPool}, scan::{ @@ -85,7 +85,7 @@ impl<'a, 'bib, 'cbs> ExecCtx<'a, 'bib, 'cbs> { if let ExecVal::String(str) = pop { if str >= self.bib_str_ptr { if str != pool.str_ptr() - 1 { - write_logs("Nontop top of string stack"); + self.glbl_ctx.write_logs("Nontop top of string stack"); print_confusion(self.glbl_ctx); return Err(BibtexError::Fatal); } @@ -95,7 +95,8 @@ impl<'a, 'bib, 'cbs> ExecCtx<'a, 'bib, 'cbs> { } Ok(pop) } else { - write_logs("You can't pop an empty literal stack"); + self.glbl_ctx + .write_logs("You can't pop an empty literal stack"); bst_ex_warn_print(self, pool, cites)?; Ok(ExecVal::Illegal) } @@ -118,19 +119,19 @@ pub(crate) fn print_lit( ) -> Result<(), BibtexError> { match val { ExecVal::Integer(val) => { - write_logs(&format!("{}\n", val)); + ctx.write_logs(&format!("{}\n", val)); } ExecVal::String(str) => { print_a_pool_str(ctx, str, pool)?; - write_logs("\n"); + ctx.write_logs("\n"); } ExecVal::Function(f) => { print_a_pool_str(ctx, hash.text(f), pool)?; - write_logs("\n"); + ctx.write_logs("\n"); } ExecVal::Missing(s) => { print_a_pool_str(ctx, s, pool)?; - write_logs("\n"); + ctx.write_logs("\n"); } ExecVal::Illegal => { illegl_literal_confusion(ctx); @@ -147,21 +148,21 @@ pub(crate) fn print_stk_lit( hash: &HashData, ) -> Result<(), BibtexError> { match val { - ExecVal::Integer(val) => write_logs(&format!("{} is an integer literal", val)), + ExecVal::Integer(val) => ctx.write_logs(&format!("{} is an integer literal", val)), ExecVal::String(str) => { - write_logs("\""); + ctx.write_logs("\""); print_a_pool_str(ctx, str, pool)?; - write_logs("\" is a string literal"); + ctx.write_logs("\" is a string literal"); } ExecVal::Function(f) => { - write_logs("`"); + ctx.write_logs("`"); print_a_pool_str(ctx, hash.text(f), pool)?; - write_logs("` is a function literal"); + ctx.write_logs("` is a function literal"); } ExecVal::Missing(s) => { - write_logs("`"); + ctx.write_logs("`"); print_a_pool_str(ctx, s, pool)?; - write_logs("` is a missing field"); + ctx.write_logs("` is a missing field"); } ExecVal::Illegal => { illegl_literal_confusion(ctx); @@ -185,9 +186,9 @@ pub(crate) fn print_wrong_stk_lit( print_stk_lit(ctx.glbl_ctx, val, pool, hash)?; match typ2 { - StkType::Integer => write_logs(", not an integer,"), - StkType::String => write_logs(", not a string,"), - StkType::Function => write_logs(", not a function,"), + StkType::Integer => ctx.glbl_ctx_mut().write_logs(", not an integer,"), + StkType::String => ctx.glbl_ctx_mut().write_logs(", not a string,"), + StkType::Function => ctx.glbl_ctx_mut().write_logs(", not a function,"), StkType::Missing | StkType::Illegal => { illegl_literal_confusion(ctx.glbl_ctx); return Err(BibtexError::Fatal); @@ -205,11 +206,11 @@ pub(crate) fn bst_ex_warn_print( cites: &CiteInfo, ) -> Result<(), BibtexError> { if ctx.mess_with_entries { - write_logs(" for entry "); + ctx.glbl_ctx_mut().write_logs(" for entry "); print_a_pool_str(ctx.glbl_ctx_mut(), cites.get_cite(cites.ptr()), pool)?; } - write_logs("\nwhile executing-"); + ctx.glbl_ctx_mut().write_logs("\nwhile executing-"); bst_ln_num_print(ctx.glbl_ctx_mut(), pool)?; ctx.glbl_ctx_mut().mark_error(); Ok(()) @@ -219,7 +220,7 @@ pub(crate) fn bst_ln_num_print( ctx: &mut Bibtex<'_, '_>, pool: &StringPool, ) -> Result<(), BibtexError> { - write_logs(&format!( + ctx.write_logs(&format!( "--line {} of file ", ctx.bst.as_ref().unwrap().line )); @@ -232,12 +233,12 @@ pub(crate) fn print_bst_name( name: StrNumber, ) -> Result<(), BibtexError> { print_a_pool_str(ctx, name, pool)?; - write_logs(".bst\n"); + ctx.write_logs(".bst\n"); Ok(()) } pub fn illegl_literal_confusion(ctx: &mut Bibtex<'_, '_>) { - write_logs("Illegal literal type"); + ctx.write_logs("Illegal literal type"); print_confusion(ctx); } @@ -249,7 +250,7 @@ fn pop_top_and_print( ) -> Result<(), BibtexError> { ctx.pop_stack(pool, cites).and_then(|val| { if let ExecVal::Illegal = val { - write_logs("Empty literal\n"); + ctx.glbl_ctx_mut().write_logs("Empty literal\n"); Ok(()) } else { print_lit(ctx.glbl_ctx, pool, hash, val) @@ -618,13 +619,15 @@ pub(crate) fn check_command_execution( cites: &CiteInfo, ) -> Result<(), BibtexError> { if !ctx.lit_stack.is_empty() { - write_logs(&format!("ptr={}, stack=\n", ctx.lit_stack.len())); + let msg = format!("ptr={}, stack=\n", ctx.lit_stack.len()); + ctx.glbl_ctx_mut().write_logs(&msg); pop_whole_stack(ctx, pool, hash, cites)?; - write_logs("---the literal stack isn't empty"); + ctx.glbl_ctx_mut() + .write_logs("---the literal stack isn't empty"); bst_ex_warn_print(ctx, pool, cites)?; } if ctx.bib_str_ptr != pool.str_ptr() { - write_logs("Nonempty empty string stack"); + ctx.glbl_ctx_mut().write_logs("Nonempty empty string stack"); print_confusion(ctx.glbl_ctx); return Err(BibtexError::Fatal); } @@ -665,9 +668,10 @@ fn interp_eq( _ if pop1.ty() != pop2.ty() => { if pop1.ty() != StkType::Illegal && pop2.ty() != StkType::Illegal { print_stk_lit(ctx.glbl_ctx, pop1, pool, hash)?; - write_logs(", "); + ctx.glbl_ctx_mut().write_logs(", "); print_stk_lit(ctx.glbl_ctx, pop2, pool, hash)?; - write_logs("\n---they aren't the same literal types"); + ctx.glbl_ctx_mut() + .write_logs("\n---they aren't the same literal types"); bst_ex_warn_print(ctx, pool, cites)?; } ctx.push_stack(ExecVal::Integer(0)); @@ -675,7 +679,8 @@ fn interp_eq( _ => { if pop1.ty() != StkType::Illegal { print_stk_lit(ctx.glbl_ctx, pop1, pool, hash)?; - write_logs(", not an integer or a string,"); + ctx.glbl_ctx_mut() + .write_logs(", not an integer or a string,"); bst_ex_warn_print(ctx, pool, cites)?; } ctx.push_stack(ExecVal::Integer(0)) @@ -918,8 +923,9 @@ fn interp_gets( if let ExecVal::String(s2) = pop2 { let mut s = pool.get_str(s2); if s.len() > ENT_STR_SIZE { - bst_1print_string_size_exceeded(); - write_logs(&format!("{}, the entry", ENT_STR_SIZE)); + bst_1print_string_size_exceeded(ctx.glbl_ctx_mut()); + ctx.glbl_ctx_mut() + .write_logs(&format!("{}, the entry", ENT_STR_SIZE)); bst_2print_string_size_exceeded(ctx, pool, cites)?; s = &s[..ENT_STR_SIZE]; } @@ -947,8 +953,9 @@ fn interp_gets( globals.set_str_ptr(str_glb_ptr, 0); let mut s = pool.get_str(s2); if s.len() > GLOB_STR_SIZE { - bst_1print_string_size_exceeded(); - write_logs(&format!("{}, the global", GLOB_STR_SIZE)); + bst_1print_string_size_exceeded(ctx.glbl_ctx_mut()); + ctx.glbl_ctx_mut() + .write_logs(&format!("{}, the global", GLOB_STR_SIZE)); bst_2print_string_size_exceeded(ctx, pool, cites)?; s = &s[..GLOB_STR_SIZE]; } @@ -959,9 +966,10 @@ fn interp_gets( } } _ => { - write_logs("You can't assign to type "); - rs_print_fn_class(hash, f1); - write_logs(", a nonvariable function class"); + ctx.glbl_ctx_mut().write_logs("You can't assign to type "); + print_fn_class(ctx.glbl_ctx_mut(), hash, f1); + ctx.glbl_ctx_mut() + .write_logs(", a nonvariable function class"); bst_ex_warn_print(ctx, pool, cites)?; } } @@ -1058,7 +1066,8 @@ fn interp_change_case( if conv_ty == ConvTy::Bad { print_a_pool_str(ctx.glbl_ctx, s1, pool)?; - write_logs(" is an illegal case-conversion string"); + ctx.glbl_ctx_mut() + .write_logs(" is an illegal case-conversion string"); bst_ex_warn_print(ctx, pool, cites)?; } @@ -1199,9 +1208,9 @@ fn interp_chr_to_int( ExecVal::String(s1) => { let str = pool.get_str(s1); if str.len() != 1 { - write_logs("\""); + ctx.glbl_ctx_mut().write_logs("\""); print_a_pool_str(ctx.glbl_ctx, s1, pool)?; - write_logs("\" isn't a single character"); + ctx.glbl_ctx_mut().write_logs("\" isn't a single character"); bst_ex_warn_print(ctx, pool, cites)?; ctx.push_stack(ExecVal::Integer(0)); } else { @@ -1285,7 +1294,8 @@ fn interp_empty( } _ => { print_stk_lit(ctx.glbl_ctx, pop1, pool, hash)?; - write_logs(", not a string or missing field,"); + ctx.glbl_ctx_mut() + .write_logs(", not a string or missing field,"); bst_ex_warn_print(ctx, pool, cites)?; ctx.push_stack(ExecVal::Integer(0)); } @@ -1342,12 +1352,13 @@ fn interp_format_name( if num_names < i2 { if i2 == 1 { - write_logs("There is no name in \""); + ctx.glbl_ctx_mut().write_logs("There is no name in \""); } else { - write_logs(&format!("There aren't {} names in \"", i2)); + ctx.glbl_ctx_mut() + .write_logs(&format!("There aren't {} names in \"", i2)); } print_a_pool_str(ctx.glbl_ctx, s3, pool)?; - write_logs("\""); + ctx.glbl_ctx_mut().write_logs("\""); bst_ex_warn_print(ctx, pool, cites)?; } @@ -1358,9 +1369,9 @@ fn interp_format_name( } _ => { if buffers.at(BufTy::Ex, buffers.offset(BufTy::Ex, 1) - 1) == b',' { - write_logs(&format!("Name {} in \"", i2)); + ctx.glbl_ctx_mut().write_logs(&format!("Name {} in \"", i2)); print_a_pool_str(ctx.glbl_ctx, s3, pool)?; - write_logs("\" has a comma at the end"); + ctx.glbl_ctx_mut().write_logs("\" has a comma at the end"); bst_ex_warn_print(ctx, pool, cites)?; buffers.set_offset(BufTy::Ex, 1, buffers.offset(BufTy::Ex, 1) - 1); } else { @@ -1394,9 +1405,10 @@ fn interp_format_name( buffers.set_at(BufTy::NameSep, num_tokens, b','); } Commas::Two(_, _) => { - write_logs(&format!("Too many commas in name {} of \"", i2)); + ctx.glbl_ctx_mut() + .write_logs(&format!("Too many commas in name {} of \"", i2)); print_a_pool_str(ctx.glbl_ctx, s3, pool)?; - write_logs("\""); + ctx.glbl_ctx_mut().write_logs("\""); bst_ex_warn_print(ctx, pool, cites)?; } } @@ -1430,9 +1442,9 @@ fn interp_format_name( num_tokens += 1; } - write_logs(&format!("Name {} of \"", i2)); + ctx.glbl_ctx_mut().write_logs(&format!("Name {} of \"", i2)); print_a_pool_str(ctx.glbl_ctx, s3, pool)?; - write_logs("\" isn't brace balanced"); + ctx.glbl_ctx_mut().write_logs("\" isn't brace balanced"); bst_ex_warn_print(ctx, pool, cites)?; xptr += 1; token_starting = false; @@ -1599,7 +1611,8 @@ fn interp_int_to_chr( }; if !(0..=127).contains(&i1) { - write_logs(&format!("{} isn't valid ASCII", i1)); + ctx.glbl_ctx_mut() + .write_logs(&format!("{} isn't valid ASCII", i1)); bst_ex_warn_print(ctx, pool, cites)?; ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); } else { @@ -1659,7 +1672,8 @@ fn interp_missing( } _ => { print_stk_lit(ctx.glbl_ctx, pop1, pool, hash)?; - write_logs(", not a string or missing field,"); + ctx.glbl_ctx_mut() + .write_logs(", not a string or missing field,"); bst_ex_warn_print(ctx, pool, cites)?; ctx.push_stack(ExecVal::Integer(0)); } @@ -2091,7 +2105,7 @@ fn interp_warning( let pop1 = ctx.pop_stack(pool, cites)?; match pop1 { ExecVal::String(_) => { - write_logs("Warning--"); + ctx.glbl_ctx_mut().write_logs("Warning--"); print_lit(ctx.glbl_ctx, pool, hash, pop1)?; ctx.glbl_ctx_mut().mark_warning(); } @@ -2375,7 +2389,7 @@ pub(crate) fn execute_fn( globals.cites, ), _ => { - write_logs("Unknown built-in function"); + ctx.glbl_ctx_mut().write_logs("Unknown built-in function"); print_confusion(ctx.glbl_ctx); Err(BibtexError::Fatal) } @@ -2411,7 +2425,8 @@ pub(crate) fn execute_fn( let field_ptr = globals.cites.ptr() * globals.other.num_fields() + globals.hash.ilk_info(ex_fn_loc) as usize; if field_ptr >= globals.other.max_fields() { - write_logs("field_info index is out of range"); + ctx.glbl_ctx_mut() + .write_logs("field_info index is out of range"); print_confusion(ctx.glbl_ctx); return Err(BibtexError::Fatal); } diff --git a/crates/engine_bibtex/src/lib.rs b/crates/engine_bibtex/src/lib.rs index 2441d4601..fcbcf8a91 100644 --- a/crates/engine_bibtex/src/lib.rs +++ b/crates/engine_bibtex/src/lib.rs @@ -29,8 +29,8 @@ use crate::{ global::GlobalData, hash::HashData, log::{ - bib_close_log, init_log_file, init_standard_output, log_pr_aux_name, print_aux_name, - print_confusion, sam_wrong_file_name_print, write_log_file, write_logs, + bib_close_log, log_pr_aux_name, print_aux_name, print_confusion, sam_wrong_file_name_print, + AsBytes, }, other::OtherData, peekable::{input_ln, PeekableInput}, @@ -39,6 +39,7 @@ use crate::{ }; use std::{ ffi::{CStr, CString}, + io::Write, ptr, }; use tectonic_bridge_core::{ @@ -199,10 +200,17 @@ impl Default for BibtexConfig { } } +#[derive(Default)] +pub(crate) struct Logs { + stdout: Option<&'static mut OutputHandle>, + file: Option<&'static mut OutputHandle>, +} + pub(crate) struct Bibtex<'a, 'cbs> { pub engine: &'a mut CoreBridgeState<'cbs>, pub config: BibtexConfig, pub history: History, + pub logs: Logs, pub bst: Option, @@ -236,6 +244,7 @@ impl<'a, 'cbs> Bibtex<'a, 'cbs> { engine, config, history: History::Spotless, + logs: Logs::default(), bst: None, bbl_file: ptr::null_mut(), bbl_line_num: 0, @@ -275,6 +284,47 @@ impl<'a, 'cbs> Bibtex<'a, 'cbs> { pub(crate) fn mark_fatal(&mut self) { self.history = History::FatalError; } + + pub(crate) fn write_logs(&mut self, str: &B) { + let _ = self.logs.file.as_mut().unwrap().write_all(str.as_bytes()); + let _ = self.logs.stdout.as_mut().unwrap().write_all(str.as_bytes()); + } + + pub(crate) fn write_stdout(&mut self, str: &B) { + let _ = self.logs.stdout.as_mut().unwrap().write_all(str.as_bytes()); + } + + pub(crate) fn write_log_file(&mut self, str: &B) { + self.logs + .file + .as_mut() + .unwrap() + .write_all(str.as_bytes()) + .unwrap(); + } + + pub(crate) fn init_stdout(&mut self) -> bool { + if self.logs.stdout.is_none() { + let stdout = ttbc_output_open_stdout(self.engine); + // SAFETY: Pointer from ttstub_output_open_stdout is valid if non-null + self.logs.stdout = unsafe { stdout.as_mut() }; + !stdout.is_null() + } else { + true + } + } + + pub(crate) fn init_log_file(&mut self, file: &CStr) -> bool { + if self.logs.file.is_none() { + // SAFETY: Our CStr is valid for the length of the call, so this can't access bad memory + let new = unsafe { ttbc_output_open(self.engine, file.as_ptr(), 0) }; + // SAFETY: Return of ttstub_output_open should be valid if non-null + self.logs.file = unsafe { new.as_mut() }; + !new.is_null() + } else { + true + } + } } #[derive(Copy, Clone, Debug)] @@ -324,9 +374,6 @@ type FieldLoc = usize; type FnDefLoc = usize; pub(crate) fn bibtex_main(ctx: &mut Bibtex<'_, '_>, aux_file_name: &CStr) -> History { - ctx.history = History::Spotless; - log::reset(); - let mut buffers = GlobalBuffer::new(); let mut pool = StringPool::new(); let mut hash = HashData::new(); @@ -366,20 +413,20 @@ pub(crate) fn bibtex_main(ctx: &mut Bibtex<'_, '_>, aux_file_name: &CStr) -> His History::Spotless => (), History::WarningIssued(warns) => { if warns == 1 { - write_logs("(There was 1 warning)\n") + ctx.write_logs("(There was 1 warning)\n") } else { - write_logs(&format!("(There were {} warnings)\n", warns)) + ctx.write_logs(&format!("(There were {} warnings)\n", warns)) } } History::ErrorIssued(errs) => { if errs == 1 { - write_logs("(There was 1 error message)\n") + ctx.write_logs("(There was 1 error message)\n") } else { - write_logs(&format!("(There were {} error messages)\n", errs)) + ctx.write_logs(&format!("(There were {} error messages)\n", errs)) } } History::FatalError => { - write_logs("(That was a fatal error)\n"); + ctx.write_logs("(That was a fatal error)\n"); } } @@ -392,7 +439,7 @@ pub(crate) fn inner_bibtex_main( globals: &mut GlobalItems<'_>, aux_file_name: &CStr, ) -> Result { - if !init_standard_output(ctx) { + if !ctx.init_stdout() { return Ok(History::FatalError); } @@ -401,12 +448,12 @@ pub(crate) fn inner_bibtex_main( } if ctx.config.verbose { - write_logs("This is BibTeX, Version 0.99d\n"); + ctx.write_logs("This is BibTeX, Version 0.99d\n"); } else { - write_log_file("This is BibTeX, Version 0.99d\n"); + ctx.write_log_file("This is BibTeX, Version 0.99d\n"); } - write_log_file(&format!( + ctx.write_log_file(&format!( "Capacity: max_strings={}, hash_size={}, hash_prime={}\n", pool::MAX_STRINGS, hash::HASH_SIZE, @@ -414,10 +461,10 @@ pub(crate) fn inner_bibtex_main( )); if ctx.config.verbose { - write_logs("The top-level auxiliary file: "); + ctx.write_logs("The top-level auxiliary file: "); print_aux_name(ctx, globals.pool, globals.aux.top_file().name)?; } else { - write_log_file("The top-level auxiliary file: "); + ctx.write_log_file("The top-level auxiliary file: "); log_pr_aux_name(ctx, globals.aux, globals.pool)?; } @@ -462,7 +509,6 @@ pub(crate) fn get_the_top_level_aux_file_name( }: &mut GlobalItems<'_>, aux_file_name: &CStr, ) -> Result { - let ctx = &mut *ctx; let aux_bytes = aux_file_name.to_bytes_with_nul(); // This will be our scratch space for CStr filenames @@ -478,15 +524,15 @@ pub(crate) fn get_the_top_level_aux_file_name( let aux_file = match PeekableInput::open(ctx, aux_file_name, FileFormat::Tex) { Ok(file) => file, Err(_) => { - sam_wrong_file_name_print(aux_file_name); + sam_wrong_file_name_print(ctx, aux_file_name); return Ok(1); } }; set_extension(&mut path, b".blg"); let log_file = CStr::from_bytes_with_nul(&path).unwrap(); - if !init_log_file(ctx, log_file) { - sam_wrong_file_name_print(log_file); + if !ctx.init_log_file(log_file) { + sam_wrong_file_name_print(ctx, log_file); return Ok(1); } @@ -495,7 +541,7 @@ pub(crate) fn get_the_top_level_aux_file_name( // SAFETY: Function sound if provided a valid path pointer ctx.bbl_file = unsafe { ttbc_output_open(ctx.engine, bbl_file.as_ptr(), 0) }; if ctx.bbl_file.is_null() { - sam_wrong_file_name_print(bbl_file); + sam_wrong_file_name_print(ctx, bbl_file); return Ok(1); } @@ -512,7 +558,7 @@ pub(crate) fn get_the_top_level_aux_file_name( }); if lookup.exists { - write_logs("Already encountered auxiliary file"); + ctx.write_logs("Already encountered auxiliary file"); print_confusion(ctx); return Err(BibtexError::Fatal); } diff --git a/crates/engine_bibtex/src/log.rs b/crates/engine_bibtex/src/log.rs index 5683d5034..144f47d19 100644 --- a/crates/engine_bibtex/src/log.rs +++ b/crates/engine_bibtex/src/log.rs @@ -10,10 +10,10 @@ use crate::{ peekable::input_ln, pool::StringPool, scan::{Scan, ScanRes}, - ttbc_output_close, ttbc_output_open, ttbc_output_open_stdout, ASCIICode, Bibtex, BibtexError, - CiteNumber, FieldLoc, HashPointer, StrNumber, + ttbc_output_close, ASCIICode, Bibtex, BibtexError, CiteNumber, FieldLoc, HashPointer, + StrNumber, }; -use std::{cell::Cell, ffi::CStr, io::Write, slice}; +use std::{ffi::CStr, io::Write, slice}; use tectonic_io_base::OutputHandle; pub trait AsBytes { @@ -38,90 +38,19 @@ impl AsBytes for [u8] { } } -thread_local! { - static STANDARD_OUTPUT: Cell> = Cell::new(None); - static LOG_FILE: Cell> = Cell::new(None); -} - -pub(crate) fn reset() { - STANDARD_OUTPUT.with(|cell| cell.set(None)); - LOG_FILE.with(|cell| cell.set(None)); -} - -fn with_stdout(f: impl FnOnce(&mut OutputHandle) -> T) -> T { - STANDARD_OUTPUT.with(|out| { - let mut stdout = out.replace(None); - let res = f(stdout.as_mut().unwrap()); - out.set(stdout); - res - }) -} - -fn with_log(f: impl FnOnce(&mut OutputHandle) -> T) -> T { - LOG_FILE.with(|out| { - let mut log = out.replace(None); - let res = f(log.as_mut().unwrap()); - out.set(log); - res - }) -} - -pub(crate) fn write_logs(str: &B) { - let _ = with_log(|log| log.write_all(str.as_bytes())); - let _ = with_stdout(|out| out.write_all(str.as_bytes())); -} - -pub(crate) fn write_log_file(str: &B) { - with_log(|log| log.write_all(str.as_bytes())).unwrap(); -} - -pub(crate) fn init_log_file(ctx: &mut Bibtex<'_, '_>, file: &CStr) -> bool { - LOG_FILE.with(|log| { - let ptr = log.replace(None); - if ptr.is_none() { - // SAFETY: Our CStr is valid for the length of the call, so this can't access bad memory - let new = unsafe { ttbc_output_open(ctx.engine, file.as_ptr(), 0) }; - // SAFETY: Return of ttstub_output_open should be valid if non-null - log.set(unsafe { new.as_mut() }); - !new.is_null() - } else { - log.set(ptr); - true - } - }) -} - -pub(crate) fn init_standard_output(ctx: &mut Bibtex<'_, '_>) -> bool { - STANDARD_OUTPUT.with(|out| { - let ptr = out.replace(None); - if ptr.is_none() { - let stdout = ttbc_output_open_stdout(ctx.engine); - // SAFETY: Pointer from ttstub_output_open_stdout is valid if non-null - out.set(unsafe { stdout.as_mut() }); - !stdout.is_null() - } else { - out.set(ptr); - true - } - }) -} - pub(crate) fn bib_close_log(ctx: &mut Bibtex<'_, '_>) { - LOG_FILE.with(|log| { - let log = log.replace(None); - if let Some(log) = log { - ttbc_output_close(ctx.engine, log); - } - }) + if let Some(log) = ctx.logs.file.take() { + ttbc_output_close(ctx.engine, log); + } } pub fn print_overflow(ctx: &mut Bibtex<'_, '_>) { - write_logs("Sorry---you've exceeded BibTeX's "); + ctx.write_logs("Sorry---you've exceeded BibTeX's "); ctx.mark_fatal(); } pub fn print_confusion(ctx: &mut Bibtex<'_, '_>) { - write_logs("---this can't happen\n*Please notify the Tectonic maintainer*\n"); + ctx.write_logs("---this can't happen\n*Please notify the Tectonic maintainer*\n"); ctx.mark_fatal(); } @@ -132,13 +61,13 @@ pub(crate) fn out_token(handle: &mut OutputHandle, buffers: &GlobalBuffer) { handle.write_all(&bytes[start..end]).unwrap(); } -pub(crate) fn print_a_token(buffers: &GlobalBuffer) { - with_stdout(|stdout| out_token(stdout, buffers)); - with_log(|log| out_token(log, buffers)); +pub(crate) fn print_a_token(ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer) { + out_token(ctx.logs.stdout.as_mut().unwrap(), buffers); + out_token(ctx.logs.file.as_mut().unwrap(), buffers); } pub(crate) fn print_bad_input_line(ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer) { - write_logs(" : "); + ctx.write_logs(" : "); let offset2 = buffers.offset(BufTy::Base, 2); @@ -146,55 +75,54 @@ pub(crate) fn print_bad_input_line(ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuf for code in slice { if LexClass::of(*code) == LexClass::Whitespace { - write_logs(" "); + ctx.write_logs(" "); } else { - write_logs(slice::from_ref(code)) + ctx.write_logs(slice::from_ref(code)) } } - write_logs("\n : "); + ctx.write_logs("\n : "); let str = (0..offset2).map(|_| ' ').collect::(); - write_logs(&str); + ctx.write_logs(&str); let last = buffers.init(BufTy::Base); if offset2 < last { let slice = &buffers.buffer(BufTy::Base)[offset2..last]; for code in slice { if LexClass::of(*code) == LexClass::Whitespace { - write_logs(" "); + ctx.write_logs(" "); } else { - write_logs(slice::from_ref(code)); + ctx.write_logs(slice::from_ref(code)); } } } - write_logs("\n"); + ctx.write_logs("\n"); if !slice .iter() .any(|c| LexClass::of(*c) != LexClass::Whitespace) { - write_logs("(Error may have been on previous line)\n"); + ctx.write_logs("(Error may have been on previous line)\n"); } ctx.mark_error(); } -pub(crate) fn print_skipping_whatever_remains() { - write_logs("I'm skipping whatever remains of this "); +pub(crate) fn print_skipping_whatever_remains(ctx: &mut Bibtex<'_, '_>) { + ctx.write_logs("I'm skipping whatever remains of this "); } pub(crate) fn out_pool_str( ctx: &mut Bibtex<'_, '_>, pool: &StringPool, - handle: &mut OutputHandle, s: StrNumber, ) -> Result<(), BibtexError> { let str = pool.try_get_str(s); if let Ok(str) = str { - handle.write_all(str).unwrap(); + ctx.write_log_file(str); Ok(()) } else { - write_logs(&format!("Illegal string number: {}", s)); + ctx.write_logs(&format!("Illegal string number: {}", s)); print_confusion(ctx); Err(BibtexError::Fatal) } @@ -207,24 +135,20 @@ pub(crate) fn print_a_pool_str( ) -> Result<(), BibtexError> { let str = pool.try_get_str(s); if let Ok(str) = str { - write_logs(str); + ctx.write_logs(str); Ok(()) } else { - write_logs(&format!("Illegal string number: {}", s)); + ctx.write_logs(&format!("Illegal string number: {}", s)); print_confusion(ctx); Err(BibtexError::Fatal) } } -pub fn sam_wrong_file_name_print(file: &CStr) { - with_stdout(|stdout| { - writeln!( - stdout, - "I couldn't open file name `{}`", - file.to_str().unwrap() - ) - .unwrap(); - }) +pub fn sam_wrong_file_name_print(ctx: &mut Bibtex<'_, '_>, file: &CStr) { + ctx.write_stdout(&format!( + "I couldn't open file name `{}`", + file.to_str().unwrap() + )); } pub(crate) fn print_aux_name( @@ -233,7 +157,7 @@ pub(crate) fn print_aux_name( name: StrNumber, ) -> Result<(), BibtexError> { print_a_pool_str(ctx, name, pool)?; - write_logs("\n"); + ctx.write_logs("\n"); Ok(()) } @@ -242,11 +166,9 @@ pub(crate) fn log_pr_aux_name( aux: &AuxData, pool: &StringPool, ) -> Result<(), BibtexError> { - with_log(|log| { - out_pool_str(ctx, pool, log, aux.top_file().name)?; - writeln!(log).unwrap(); - Ok(()) - }) + out_pool_str(ctx, pool, aux.top_file().name)?; + ctx.write_log_file("\n"); + Ok(()) } pub(crate) fn aux_err_print( @@ -255,11 +177,11 @@ pub(crate) fn aux_err_print( aux: &AuxData, pool: &StringPool, ) -> Result<(), BibtexError> { - write_logs(&format!("---line {} of file ", aux.top_file().line)); + ctx.write_logs(&format!("---line {} of file ", aux.top_file().line)); print_aux_name(ctx, pool, aux.top_file().name)?; print_bad_input_line(ctx, buffers); - print_skipping_whatever_remains(); - write_logs("command\n"); + print_skipping_whatever_remains(ctx); + ctx.write_logs("command\n"); Ok(()) } @@ -268,30 +190,33 @@ pub(crate) enum AuxTy { Style, } -pub(crate) fn aux_err_illegal_another_print(cmd: AuxTy) -> Result<(), BibtexError> { - write_logs("Illegal, another \\bib"); +pub(crate) fn aux_err_illegal_another_print( + ctx: &mut Bibtex<'_, '_>, + cmd: AuxTy, +) -> Result<(), BibtexError> { + ctx.write_logs("Illegal, another \\bib"); match cmd { - AuxTy::Data => write_logs("data"), - AuxTy::Style => write_logs("style"), + AuxTy::Data => ctx.write_logs("data"), + AuxTy::Style => ctx.write_logs("style"), } - write_logs(" command"); + ctx.write_logs(" command"); Ok(()) } -pub fn aux_err_no_right_brace_print() { - write_logs("No \"}\""); +pub fn aux_err_no_right_brace_print(ctx: &mut Bibtex<'_, '_>) { + ctx.write_logs("No \"}\""); } -pub fn aux_err_stuff_after_right_brace_print() { - write_logs("Stuff after \"}\""); +pub fn aux_err_stuff_after_right_brace_print(ctx: &mut Bibtex<'_, '_>) { + ctx.write_logs("Stuff after \"}\""); } -pub fn aux_err_white_space_in_argument_print() { - write_logs("White space in argument"); +pub fn aux_err_white_space_in_argument_print(ctx: &mut Bibtex<'_, '_>) { + ctx.write_logs("White space in argument"); } -pub fn aux_end1_err_print() { - write_logs("I found no "); +pub fn aux_end1_err_print(ctx: &mut Bibtex<'_, '_>) { + ctx.write_logs("I found no "); } pub(crate) fn aux_end2_err_print( @@ -299,7 +224,7 @@ pub(crate) fn aux_end2_err_print( pool: &StringPool, name: StrNumber, ) -> Result<(), BibtexError> { - write_logs("---while reading file "); + ctx.write_logs("---while reading file "); print_aux_name(ctx, pool, name)?; ctx.mark_error(); Ok(()) @@ -316,9 +241,9 @@ pub(crate) fn print_bib_name( .map_err(|_| BibtexError::Fatal) .map(|str| str.ends_with(b".bib"))?; if !res { - write_logs(".bib"); + ctx.write_logs(".bib"); } - write_logs("\n"); + ctx.write_logs("\n"); Ok(()) } @@ -327,34 +252,30 @@ pub(crate) fn log_pr_bib_name( bibs: &BibData, pool: &StringPool, ) -> Result<(), BibtexError> { - with_log(|log| { - out_pool_str(ctx, pool, log, bibs.top_file().name)?; - let res = pool - .try_get_str(bibs.top_file().name) - .map(|str| str.ends_with(b".bib")) - .map_err(|_| BibtexError::Fatal)?; - if !res { - write!(log, ".bib").unwrap(); - } - writeln!(log).unwrap(); - Ok(()) - }) + out_pool_str(ctx, pool, bibs.top_file().name)?; + let res = pool + .try_get_str(bibs.top_file().name) + .map(|str| str.ends_with(b".bib")) + .map_err(|_| BibtexError::Fatal)?; + if !res { + ctx.write_log_file(".bib"); + } + ctx.write_log_file("\n"); + Ok(()) } pub(crate) fn log_pr_bst_name( ctx: &mut Bibtex<'_, '_>, pool: &StringPool, ) -> Result<(), BibtexError> { - with_log(|log| { - // TODO: This call can panic if bst_str doesn't exist - out_pool_str(ctx, pool, log, ctx.bst.as_ref().unwrap().name)?; - writeln!(log, ".bst").unwrap(); - Ok(()) - }) + // TODO: This call can panic if bst_str doesn't exist + out_pool_str(ctx, pool, ctx.bst.as_ref().unwrap().name)?; + ctx.write_log_file(".bst\n"); + Ok(()) } pub(crate) fn hash_cite_confusion(ctx: &mut Bibtex<'_, '_>) { - write_logs("Cite hash error"); + ctx.write_logs("Cite hash error"); print_confusion(ctx); } @@ -367,12 +288,12 @@ pub(crate) fn bst_warn_print( Ok(()) } -pub fn eat_bst_print() { - write_logs("Illegal end of style file in command: "); +pub fn eat_bst_print(ctx: &mut Bibtex<'_, '_>) { + ctx.write_logs("Illegal end of style file in command: "); } pub fn id_scanning_confusion(ctx: &mut Bibtex<'_, '_>) { - write_logs("Identifier scanning error"); + ctx.write_logs("Identifier scanning error"); print_confusion(ctx); } @@ -384,11 +305,11 @@ pub(crate) fn bst_id_print( let char = buffers.at_offset(BufTy::Base, 2) as char; match scan_result { ScanRes::IdNull => { - write_logs(&format!("\"{}\" begins identifier, command: ", char)); + ctx.write_logs(&format!("\"{}\" begins identifier, command: ", char)); Ok(()) } ScanRes::OtherCharAdjacent => { - write_logs(&format!( + ctx.write_logs(&format!( "\"{}\" immediately follows identifier, command: ", char )); @@ -401,12 +322,12 @@ pub(crate) fn bst_id_print( } } -pub fn bst_left_brace_print() { - write_logs("\"{\" is missing in command: "); +pub fn bst_left_brace_print(ctx: &mut Bibtex<'_, '_>) { + ctx.write_logs("\"{\" is missing in command: "); } -pub fn bst_right_brace_print() { - write_logs("\"}\" is missing in command: "); +pub fn bst_right_brace_print(ctx: &mut Bibtex<'_, '_>) { + ctx.write_logs("\"}\" is missing in command: "); } pub(crate) fn bib_ln_num_print( @@ -414,7 +335,7 @@ pub(crate) fn bib_ln_num_print( pool: &StringPool, bibs: &BibData, ) -> Result<(), BibtexError> { - write_logs(&format!("--line {} of file ", bibs.top_file().line)); + ctx.write_logs(&format!("--line {} of file ", bibs.top_file().line)); print_bib_name(ctx, pool, bibs.top_file().name) } @@ -425,14 +346,14 @@ pub(crate) fn bib_err_print( bibs: &BibData, at_bib_command: bool, ) -> Result<(), BibtexError> { - write_logs("-"); + ctx.write_logs("-"); bib_ln_num_print(ctx, pool, bibs)?; print_bad_input_line(ctx, buffers); - print_skipping_whatever_remains(); + print_skipping_whatever_remains(ctx); if at_bib_command { - write_logs("command\n"); + ctx.write_logs("command\n"); } else { - write_logs("entry\n"); + ctx.write_logs("entry\n"); } Ok(()) } @@ -454,7 +375,7 @@ pub(crate) fn eat_bib_print( bibs: &BibData, at_bib_command: bool, ) -> Result<(), BibtexError> { - write_logs("Illegal end of database file"); + ctx.write_logs("Illegal end of database file"); bib_err_print(ctx, buffers, pool, bibs, at_bib_command) } @@ -467,7 +388,7 @@ pub(crate) fn bib_one_of_two_print( char2: ASCIICode, at_bib_command: bool, ) -> Result<(), BibtexError> { - write_logs(&format!( + ctx.write_logs(&format!( "I was expecting a `{}' or a `{}'", char1 as char, char2 as char )); @@ -481,7 +402,7 @@ pub(crate) fn bib_equals_sign_print( bibs: &BibData, at_bib_command: bool, ) -> Result<(), BibtexError> { - write_logs("I was expecting an \"=\""); + ctx.write_logs("I was expecting an \"=\""); bib_err_print(ctx, buffers, pool, bibs, at_bib_command) } @@ -492,14 +413,14 @@ pub(crate) fn bib_unbalanced_braces_print( bibs: &BibData, at_bib_command: bool, ) -> Result<(), BibtexError> { - write_logs("Unbalanced braces"); + ctx.write_logs("Unbalanced braces"); bib_err_print(ctx, buffers, pool, bibs, at_bib_command) } -pub(crate) fn macro_warn_print(buffers: &GlobalBuffer) { - write_logs("Warning--string name \""); - print_a_token(buffers); - write_logs("\" is "); +pub(crate) fn macro_warn_print(ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer) { + ctx.write_logs("Warning--string name \""); + print_a_token(ctx, buffers); + ctx.write_logs("\" is "); } pub(crate) fn bib_id_print( @@ -509,12 +430,12 @@ pub(crate) fn bib_id_print( ) -> Result<(), BibtexError> { match scan_res { ScanRes::IdNull => { - write_logs("You're missing "); + ctx.write_logs("You're missing "); Ok(()) } ScanRes::OtherCharAdjacent => { let char = buffers.at_offset(BufTy::Base, 2); - write_logs(&format!("\"{}\" immediately follows ", char)); + ctx.write_logs(&format!("\"{}\" immediately follows ", char)); Ok(()) } _ => { @@ -525,12 +446,12 @@ pub(crate) fn bib_id_print( } pub(crate) fn bib_cmd_confusion(ctx: &mut Bibtex<'_, '_>) { - write_logs("Unknown database-file command"); + ctx.write_logs("Unknown database-file command"); print_confusion(ctx); } pub fn cite_key_disappeared_confusion(ctx: &mut Bibtex<'_, '_>) { - write_logs("A cite key disappeared"); + ctx.write_logs("A cite key disappeared"); print_confusion(ctx); } @@ -541,11 +462,11 @@ pub(crate) fn bad_cross_reference_print( cite_ptr: CiteNumber, s: StrNumber, ) -> Result<(), BibtexError> { - write_logs("--entry \""); + ctx.write_logs("--entry \""); print_a_pool_str(ctx, cites.get_cite(cite_ptr), pool)?; - write_logs("\"\nrefers to entry \""); + ctx.write_logs("\"\nrefers to entry \""); print_a_pool_str(ctx, s, pool)?; - write_logs("\""); + ctx.write_logs("\""); Ok(()) } @@ -554,9 +475,9 @@ pub(crate) fn print_missing_entry( pool: &StringPool, s: StrNumber, ) -> Result<(), BibtexError> { - write_logs("Warning--I didn't find a database entry for \""); + ctx.write_logs("Warning--I didn't find a database entry for \""); print_a_pool_str(ctx, s, pool)?; - write_logs("\"\n"); + ctx.write_logs("\"\n"); ctx.mark_warning(); Ok(()) } @@ -567,10 +488,10 @@ pub(crate) fn bst_mild_ex_warn_print( cites: &CiteInfo, ) -> Result<(), BibtexError> { if ctx.mess_with_entries { - write_logs(" for entry "); + ctx.glbl_ctx_mut().write_logs(" for entry "); print_a_pool_str(ctx.glbl_ctx_mut(), cites.get_cite(cites.ptr()), pool)?; } - write_logs("\nwhile executing"); + ctx.glbl_ctx_mut().write_logs("\nwhile executing"); bst_warn_print(ctx.glbl_ctx_mut(), pool) } @@ -579,12 +500,13 @@ pub(crate) fn bst_cant_mess_with_entries_print( pool: &StringPool, cites: &CiteInfo, ) -> Result<(), BibtexError> { - write_logs("You can't mess with entries here"); + ctx.glbl_ctx_mut() + .write_logs("You can't mess with entries here"); bst_ex_warn_print(ctx, pool, cites) } -pub fn bst_1print_string_size_exceeded() { - write_logs("Warning--you've exceeded "); +pub fn bst_1print_string_size_exceeded(ctx: &mut Bibtex<'_, '_>) { + ctx.write_logs("Warning--you've exceeded "); } pub(crate) fn bst_2print_string_size_exceeded( @@ -592,9 +514,10 @@ pub(crate) fn bst_2print_string_size_exceeded( pool: &StringPool, cites: &CiteInfo, ) -> Result<(), BibtexError> { - write_logs("-string-size,"); + ctx.glbl_ctx_mut().write_logs("-string-size,"); bst_mild_ex_warn_print(ctx, pool, cites)?; - write_logs("*Please notify the bibstyle designer*\n"); + ctx.glbl_ctx_mut() + .write_logs("*Please notify the bibstyle designer*\n"); Ok(()) } @@ -604,24 +527,25 @@ pub(crate) fn braces_unbalanced_complaint( cites: &CiteInfo, pop_lit_var: StrNumber, ) -> Result<(), BibtexError> { - write_logs("Warning--\""); + ctx.glbl_ctx_mut().write_logs("Warning--\""); print_a_pool_str(ctx.glbl_ctx_mut(), pop_lit_var, pool)?; - write_logs("\" isn't a brace-balanced string"); + ctx.glbl_ctx_mut() + .write_logs("\" isn't a brace-balanced string"); bst_mild_ex_warn_print(ctx, pool, cites) } -pub(crate) fn rs_print_fn_class(hash: &HashData, fn_loc: HashPointer) { +pub(crate) fn print_fn_class(ctx: &mut Bibtex<'_, '_>, hash: &HashData, fn_loc: HashPointer) { let ty = hash.ty(fn_loc); match ty { - FnClass::Builtin => write_logs("built-in"), - FnClass::Wizard => write_logs("wizard-defined"), - FnClass::IntLit => write_logs("integer-literal"), - FnClass::StrLit => write_logs("string-literal"), - FnClass::Field => write_logs("field"), - FnClass::IntEntryVar => write_logs("integer-entry-variable"), - FnClass::StrEntryVar => write_logs("string-entry-variable"), - FnClass::IntGlblVar => write_logs("integer-global-variable"), - FnClass::StrGlblVar => write_logs("string-global-variable"), + FnClass::Builtin => ctx.write_logs("built-in"), + FnClass::Wizard => ctx.write_logs("wizard-defined"), + FnClass::IntLit => ctx.write_logs("integer-literal"), + FnClass::StrLit => ctx.write_logs("string-literal"), + FnClass::Field => ctx.write_logs("field"), + FnClass::IntEntryVar => ctx.write_logs("integer-entry-variable"), + FnClass::StrEntryVar => ctx.write_logs("string-entry-variable"), + FnClass::IntGlblVar => ctx.write_logs("integer-global-variable"), + FnClass::StrGlblVar => ctx.write_logs("string-global-variable"), } } @@ -630,7 +554,7 @@ pub(crate) fn bst_err_print_and_look_for_blank_line( buffers: &mut GlobalBuffer, pool: &StringPool, ) -> Result<(), BibtexError> { - write_logs("-"); + ctx.write_logs("-"); bst_ln_num_print(ctx, pool)?; print_bad_input_line(ctx, buffers); while buffers.init(BufTy::Base) != 0 { @@ -652,9 +576,9 @@ pub(crate) fn already_seen_function_print( seen_fn_loc: HashPointer, ) -> Result<(), BibtexError> { print_a_pool_str(ctx, hash.text(seen_fn_loc), pool)?; - write_logs(" is already a type \""); - rs_print_fn_class(hash, seen_fn_loc); - write_logs("\" function name\n"); + ctx.write_logs(" is already a type \""); + print_fn_class(ctx, hash, seen_fn_loc); + ctx.write_logs("\" function name\n"); bst_err_print_and_look_for_blank_line(ctx, buffers, pool) } @@ -666,9 +590,9 @@ pub(crate) fn nonexistent_cross_reference_error( cite_ptr: CiteNumber, field_ptr: FieldLoc, ) -> Result<(), BibtexError> { - write_logs("A bad cross reference-"); + ctx.write_logs("A bad cross reference-"); bad_cross_reference_print(ctx, pool, cites, cite_ptr, other.field(field_ptr))?; - write_logs(", which doesn't exist\n"); + ctx.write_logs(", which doesn't exist\n"); ctx.mark_error(); Ok(()) } @@ -702,7 +626,7 @@ pub(crate) fn skip_token_print( buffers: &mut GlobalBuffer, pool: &StringPool, ) -> Result<(), BibtexError> { - write_logs("-"); + ctx.write_logs("-"); bst_ln_num_print(ctx, pool)?; ctx.mark_error(); @@ -719,9 +643,9 @@ pub(crate) fn print_recursion_illegal( buffers: &mut GlobalBuffer, pool: &StringPool, ) -> Result<(), BibtexError> { - write_logs("Curse you, wizard, before you recurse me:\nfunction "); - print_a_token(buffers); - write_logs(" is illegal in its own definition\n"); + ctx.write_logs("Curse you, wizard, before you recurse me:\nfunction "); + print_a_token(ctx, buffers); + ctx.write_logs(" is illegal in its own definition\n"); skip_token_print(ctx, buffers, pool) } @@ -730,8 +654,8 @@ pub(crate) fn skip_token_unknown_function_print( buffers: &mut GlobalBuffer, pool: &StringPool, ) -> Result<(), BibtexError> { - print_a_token(buffers); - write_logs(" is an unknown function"); + print_a_token(ctx, buffers); + ctx.write_logs(" is an unknown function"); skip_token_print(ctx, buffers, pool) } @@ -740,7 +664,7 @@ pub(crate) fn skip_illegal_stuff_after_token_print( buffers: &mut GlobalBuffer, pool: &StringPool, ) -> Result<(), BibtexError> { - write_logs(&format!( + ctx.write_logs(&format!( "\"{}\" can't follow a literal", buffers.at_offset(BufTy::Base, 2) as char )); @@ -753,9 +677,10 @@ pub(crate) fn brace_lvl_one_letters_complaint( cites: &CiteInfo, str: StrNumber, ) -> Result<(), BibtexError> { - write_logs("The format string \""); + ctx.glbl_ctx_mut().write_logs("The format string \""); print_a_pool_str(ctx.glbl_ctx_mut(), str, pool)?; - write_logs("\" has an illegal brace-level-1 letter"); + ctx.glbl_ctx_mut() + .write_logs("\" has an illegal brace-level-1 letter"); bst_ex_warn_print(ctx, pool, cites)?; Ok(()) } diff --git a/crates/engine_bibtex/src/pool.rs b/crates/engine_bibtex/src/pool.rs index 8566f2574..7e7865bd5 100644 --- a/crates/engine_bibtex/src/pool.rs +++ b/crates/engine_bibtex/src/pool.rs @@ -5,7 +5,7 @@ use crate::{ global::GLOB_STR_SIZE, hash, hash::{FnClass, HashData}, - log::{output_bbl_line, print_overflow, write_logs}, + log::{output_bbl_line, print_overflow}, ASCIICode, Bibtex, BibtexError, GlobalItems, HashPointer, LookupRes, PoolPointer, StrIlk, StrNumber, }; @@ -68,7 +68,7 @@ impl StringPool { pub fn make_string(&mut self, ctx: &mut Bibtex<'_, '_>) -> Result { if self.str_ptr == MAX_STRINGS { print_overflow(ctx); - write_logs(&format!("number of strings {}\n", MAX_STRINGS)); + ctx.write_logs(&format!("number of strings {}\n", MAX_STRINGS)); return Err(BibtexError::Fatal); } self.str_ptr += 1; @@ -137,7 +137,7 @@ impl StringPool { loop { if hash.used() == hash::HASH_BASE { print_overflow(ctx); - write_logs(&format!("hash size {}\n", hash::HASH_SIZE)); + ctx.write_logs(&format!("hash size {}\n", hash::HASH_SIZE)); return Err(BibtexError::Fatal); } hash.set_used(hash.used() - 1); diff --git a/crates/engine_bibtex/src/scan.rs b/crates/engine_bibtex/src/scan.rs index d8c8b6de6..3c4a01ccf 100644 --- a/crates/engine_bibtex/src/scan.rs +++ b/crates/engine_bibtex/src/scan.rs @@ -11,7 +11,7 @@ use crate::{ bib_warn_print, braces_unbalanced_complaint, bst_err_print_and_look_for_blank_line, eat_bib_print, eat_bst_print, hash_cite_confusion, macro_warn_print, print_a_pool_str, print_confusion, print_recursion_illegal, skip_illegal_stuff_after_token_print, - skip_token_print, skip_token_unknown_function_print, write_log_file, write_logs, + skip_token_print, skip_token_unknown_function_print, }, other::OtherData, peekable::input_ln, @@ -192,7 +192,7 @@ fn handle_char( buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); if !scan_integer(buffers, &mut token_value) { - write_logs("Illegal integer in integer literal"); + ctx.write_logs("Illegal integer in integer literal"); return skip_token_print(ctx, buffers, pool); } @@ -224,8 +224,8 @@ fn handle_char( buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); let init = buffers.init(BufTy::Base); - if !Scan::new().chars(b"\"").scan_till(buffers, init) { - write_logs("No `\"` to end string literal"); + if !Scan::new().chars(&[b'"']).scan_till(buffers, init) { + ctx.write_logs("No `\"` to end string literal"); return skip_token_print(ctx, buffers, pool); } @@ -284,7 +284,7 @@ fn handle_char( let res = pool.lookup_str_insert(ctx, hash, str.as_bytes(), StrIlk::BstFn)?; if res.exists { - write_logs("Already encountered implicit function"); + ctx.write_logs("Already encountered implicit function"); print_confusion(ctx); return Err(BibtexError::Fatal); } @@ -332,12 +332,11 @@ pub(crate) fn scan_fn_def( fn_hash_loc: HashPointer, wiz_loc: HashPointer, ) -> Result<(), BibtexError> { - let ctx = &mut *ctx; let mut single_function = Vec::new(); if !eat_bst_white_space(ctx, buffers) { - eat_bst_print(); - write_logs("function"); + eat_bst_print(ctx); + ctx.write_logs("function"); bst_err_print_and_look_for_blank_line(ctx, buffers, pool)?; return Ok(()); } @@ -356,8 +355,8 @@ pub(crate) fn scan_fn_def( )?; if !eat_bst_white_space(ctx, buffers) { - eat_bst_print(); - write_logs("function"); + eat_bst_print(ctx); + ctx.write_logs("function"); return bst_err_print_and_look_for_blank_line(ctx, buffers, pool); } @@ -410,7 +409,7 @@ fn scan_balanced_braces( b'{' => { brace_level += 1; if buffers.offset(BufTy::Ex, 1) >= buffers.len() { - write_log_file("Field filled up at '{', reallocating.\n"); + ctx.write_log_file("Field filled up at '{', reallocating.\n"); buffers.grow_all(); } @@ -437,13 +436,13 @@ fn scan_balanced_braces( if buffers.offset(BufTy::Ex, 1) >= buffers.len() { match c { b'}' | b'{' => { - write_log_file(&format!( + ctx.write_log_file(&format!( "Field filled up at '{}', reallocating.\n", c as char )); } _ => { - write_log_file(&format!( + ctx.write_log_file(&format!( "Field filled up at {}, reallocating.\n", buffers.offset(BufTy::Base, 2) )); @@ -476,7 +475,7 @@ fn scan_balanced_braces( } c => { if buffers.offset(BufTy::Ex, 1) >= buffers.len() { - write_log_file(&format!( + ctx.write_log_file(&format!( "Field filled up at {}, reallocating.\n", buffers.offset(BufTy::Base, 2) )); @@ -582,7 +581,7 @@ fn scan_a_field_token_and_eat_white( .not_class(LexClass::Numeric) .scan_till_nonempty(buffers, last) { - write_logs("A digit disappeared"); + ctx.write_logs("A digit disappeared"); print_confusion(ctx); return Err(BibtexError::Fatal); } @@ -593,7 +592,7 @@ fn scan_a_field_token_and_eat_white( while len >= buffers.len() { // TODO: This may change output of a field long enough to fill the buffer twice. OTOH, that is a 40KB field roughly - write_log_file(&format!( + ctx.write_log_file(&format!( "Field filled up at {}, reallocating.\n", buffers.at_offset(BufTy::Base, 1) )); @@ -618,7 +617,7 @@ fn scan_a_field_token_and_eat_white( ScanRes::WhitespaceAdjacent | ScanRes::SpecifiedCharAdjacent ) { bib_id_print(ctx, buffers, res)?; - write_logs("a field part"); + ctx.write_logs("a field part"); bib_err_print(ctx, buffers, pool, bibs, at_bib_command)?; return Ok(false); } @@ -634,15 +633,15 @@ fn scan_a_field_token_and_eat_white( cur_macro_loc { store_token = false; - macro_warn_print(buffers); - write_logs("used in its own definition\n"); + macro_warn_print(ctx, buffers); + ctx.write_logs("used in its own definition\n"); bib_warn_print(ctx, pool, bibs)?; } if !res.exists { store_token = false; - macro_warn_print(buffers); - write_logs("undefined\n"); + macro_warn_print(ctx, buffers); + ctx.write_logs("undefined\n"); bib_warn_print(ctx, pool, bibs)?; } @@ -654,7 +653,7 @@ fn scan_a_field_token_and_eat_white( && LexClass::of(str[0]) == LexClass::Whitespace { if buffers.offset(BufTy::Ex, 1) >= buffers.len() { - write_log_file("Field filled up at ' ', reallocating.\n"); + ctx.write_log_file("Field filled up at ' ', reallocating.\n"); buffers.grow_all(); } @@ -674,7 +673,7 @@ fn scan_a_field_token_and_eat_white( }; if buffers.offset(BufTy::Ex, 1) >= buffers.len() { - write_log_file(&msg(c)); + ctx.write_log_file(&msg(c)); buffers.grow_all(); } @@ -792,7 +791,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( let field_ptr = cites.entry_ptr() * other.num_fields() + hash.ilk_info(field_name_loc) as usize; if field_ptr >= other.max_fields() { - write_logs("field_info index is out of range"); + ctx.write_logs("field_info index is out of range"); print_confusion(ctx); return Err(BibtexError::Fatal); } @@ -800,11 +799,11 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( if other.field(field_ptr) != 0 /* missing */ { - write_logs("Warning--I'm ignoring "); + ctx.write_logs("Warning--I'm ignoring "); print_a_pool_str(ctx, cites.get_cite(cites.entry_ptr()), pool)?; - write_logs("'s extra \""); + ctx.write_logs("'s extra \""); print_a_pool_str(ctx, hash.text(field_name_loc), pool)?; - write_logs("\" field\n"); + ctx.write_logs("\" field\n"); bib_warn_print(ctx, pool, bibs)?; } else { other.set_field(field_ptr, hash.text(res.loc)); @@ -979,7 +978,7 @@ pub(crate) fn von_token_found( 3 | 5 | 7 | 9 | 11 => return Ok(false), 0 | 1 | 2 | 4 | 6 | 8 | 10 | 12 => return Ok(true), _ => { - write_logs("Control-sequence hash error"); + ctx.write_logs("Control-sequence hash error"); print_confusion(ctx); return Err(BibtexError::Fatal); } From c7985ad729ee5ff1349a7310a6a8eb309930d841 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Wed, 21 Feb 2024 12:57:21 -0800 Subject: [PATCH 10/23] Make direct CoreBridgeLauncher API, use it to remove most remaining unsafe --- crates/bridge_core/src/lib.rs | 137 +++++++++++++++++---------- crates/engine_bibtex/src/bibs.rs | 42 ++++---- crates/engine_bibtex/src/bst.rs | 2 +- crates/engine_bibtex/src/lib.rs | 68 ++++++------- crates/engine_bibtex/src/log.rs | 20 ++-- crates/engine_bibtex/src/peekable.rs | 47 ++++----- crates/engine_bibtex/src/scan.rs | 14 +-- 7 files changed, 189 insertions(+), 141 deletions(-) diff --git a/crates/bridge_core/src/lib.rs b/crates/bridge_core/src/lib.rs index 0a7405db8..a16fb30b8 100644 --- a/crates/bridge_core/src/lib.rs +++ b/crates/bridge_core/src/lib.rs @@ -1,7 +1,7 @@ // Copyright 2016-2022 the Tectonic Project // Licensed under the MIT License. -#![deny(missing_docs)] +// #![deny(missing_docs)] //! Core APIs for bridging the C and Rust portions of Tectonic’s processing //! backends. @@ -54,6 +54,12 @@ use tectonic_io_base::{ }; use tectonic_status_base::{tt_error, tt_warning, MessageKind, StatusBackend}; +#[derive(Copy, Clone, PartialEq)] +pub struct InputId(*mut InputHandle); + +#[derive(Copy, Clone, PartialEq)] +pub struct OutputId(*mut OutputHandle); + /// Possible failures for "system request" calls to the driver. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum SystemRequestError { @@ -473,16 +479,27 @@ impl<'a> CoreBridgeState<'a> { error_occurred } - fn output_open(&mut self, name: &str, is_gz: bool) -> *mut OutputHandle { + fn output_to_id(&self, output: *mut OutputHandle) -> OutputId { + OutputId(output) + } + + pub fn get_output(&mut self, id: OutputId) -> &mut OutputHandle { + self.output_handles + .iter_mut() + .find(|o| ptr::addr_eq(&***o, id.0)) + .unwrap() + } + + pub fn output_open(&mut self, name: &str, is_gz: bool) -> Option { let io = self.hooks.io(); let name = normalize_tex_path(name); let mut oh = match io.output_open_name(&name) { OpenResult::Ok(oh) => oh, - OpenResult::NotAvailable => return ptr::null_mut(), + OpenResult::NotAvailable => return None, OpenResult::Err(e) => { tt_warning!(self.status, "open of output {} failed", name; e); - return ptr::null_mut(); + return None; } }; @@ -495,23 +512,23 @@ impl<'a> CoreBridgeState<'a> { } self.output_handles.push(Box::new(oh)); - &mut **self.output_handles.last_mut().unwrap() + Some(OutputId(&mut **self.output_handles.last_mut().unwrap())) } - fn output_open_stdout(&mut self) -> *mut OutputHandle { + pub fn output_open_stdout(&mut self) -> Option { let io = self.hooks.io(); let oh = match io.output_open_stdout() { OpenResult::Ok(oh) => oh, - OpenResult::NotAvailable => return ptr::null_mut(), + OpenResult::NotAvailable => return None, OpenResult::Err(e) => { tt_warning!(self.status, "open of stdout failed"; e); - return ptr::null_mut(); + return None; } }; self.output_handles.push(Box::new(oh)); - &mut **self.output_handles.last_mut().unwrap() + Some(OutputId(&mut **self.output_handles.last_mut().unwrap())) } fn output_write(&mut self, handle: *mut OutputHandle, buf: &[u8]) -> bool { @@ -540,45 +557,55 @@ impl<'a> CoreBridgeState<'a> { } } - fn output_close(&mut self, handle: *mut OutputHandle) -> bool { - let len = self.output_handles.len(); + pub fn output_close(&mut self, id: OutputId) -> bool { let mut rv = false; - for i in 0..len { - let p: *const OutputHandle = &*self.output_handles[i]; - - if p == handle { - let mut oh = self.output_handles.swap_remove(i); - if let Err(e) = oh.flush() { - tt_warning!(self.status, "error when closing output {}", oh.name(); e.into()); - rv = true; - } - let (name, digest) = oh.into_name_digest(); - self.hooks.event_output_closed(name, digest); - break; + let pos = self + .output_handles + .iter() + .position(|o| ptr::addr_eq(&**o, id.0)); + if let Some(pos) = pos { + // TODO: How to handle removing IDs? Need a slotmap or some other form of stable ID + let mut oh = self.output_handles.swap_remove(pos); + if let Err(e) = oh.flush() { + tt_warning!(self.status, "error when closing output {}", oh.name(); e.into()); + rv = true; } + let (name, digest) = oh.into_name_digest(); + self.hooks.event_output_closed(name, digest, self.status); } rv } - fn input_open(&mut self, name: &str, format: FileFormat, is_gz: bool) -> *mut InputHandle { + fn input_to_id(&self, input: *mut InputHandle) -> InputId { + InputId(input) + } + + pub fn get_input(&mut self, input: InputId) -> &mut InputHandle { + self.input_handles + .iter_mut() + .find(|i| ptr::addr_eq(&***i, input.0)) + .unwrap() + } + + pub fn input_open(&mut self, name: &str, format: FileFormat, is_gz: bool) -> Option { let name = normalize_tex_path(name); let (ih, path) = match self.input_open_name_format_gz(&name, format, is_gz) { OpenResult::Ok(tup) => tup, OpenResult::NotAvailable => { - return ptr::null_mut(); + return None; } OpenResult::Err(e) => { tt_warning!(self.status, "open of input {} failed", name; e); - return ptr::null_mut(); + return None; } }; self.input_handles.push(Box::new(ih)); self.latest_input_path = path; - &mut **self.input_handles.last_mut().unwrap() + Some(InputId(&mut **self.input_handles.last_mut().unwrap())) } fn input_open_primary(&mut self) -> *mut InputHandle { @@ -650,32 +677,30 @@ impl<'a> CoreBridgeState<'a> { rhandle.ungetc(byte) } - fn input_close(&mut self, handle: *mut InputHandle) -> bool { - let len = self.input_handles.len(); - - for i in 0..len { - let p: *const InputHandle = &*self.input_handles[i]; - - if p == handle { - let mut ih = self.input_handles.swap_remove(i); - let mut rv = false; - - if let Err(e) = ih.scan_remainder() { - tt_warning!(self.status, "error closing out input {}", ih.name(); e); - rv = true; - } - - let (name, digest_opt) = ih.into_name_digest(); - self.hooks.event_input_closed(name, digest_opt, self.status); - return rv; + pub fn input_close(&mut self, id: InputId) -> bool { + let pos = self + .input_handles + .iter() + .position(|i| ptr::addr_eq(&**i, id.0)); + if let Some(pos) = pos { + let mut ih = self.input_handles.swap_remove(pos); + let mut rv = false; + + if let Err(e) = ih.scan_remainder() { + tt_warning!(self.status, "error closing out input {}", ih.name(); e); + rv = true; } + + let (name, digest_opt) = ih.into_name_digest(); + self.hooks.event_input_closed(name, digest_opt, self.status); + return rv; } // TODO: Handle the error better. This indicates a bug in the engine. tt_error!( self.status, "serious internal bug: unexpected handle in input close: {:?}", - handle + id.0 ); true @@ -900,13 +925,19 @@ pub unsafe extern "C" fn ttbc_output_open( let rname = CStr::from_ptr(name).to_string_lossy(); let ris_gz = is_gz != 0; - es.output_open(&rname, ris_gz) + match es.output_open(&rname, ris_gz) { + Some(id) => es.get_output(id), + None => ptr::null_mut(), + } } /// Open the general user output stream as a Tectonic output file. #[no_mangle] pub extern "C" fn ttbc_output_open_stdout(es: &mut CoreBridgeState) -> *mut OutputHandle { - es.output_open_stdout() + match es.output_open_stdout() { + Some(id) => es.get_output(id), + None => ptr::null_mut(), + } } /// Write a single character to a Tectonic output file. @@ -967,7 +998,7 @@ pub extern "C" fn ttbc_output_close( return 0; // This is/was the behavior of close_file() in C. } - libc::c_int::from(es.output_close(handle)) + libc::c_int::from(es.output_close(es.output_to_id(handle))) } /// Open a Tectonic file for input. @@ -984,7 +1015,11 @@ pub unsafe extern "C" fn ttbc_input_open( ) -> *mut InputHandle { let rname = CStr::from_ptr(name).to_string_lossy(); let ris_gz = is_gz != 0; - es.input_open(&rname, format, ris_gz) + let id = es.input_open(&rname, format, ris_gz); + match id { + Some(id) => es.get_input(id), + None => ptr::null_mut(), + } } /// Open the "primary input" file. @@ -1169,7 +1204,7 @@ pub extern "C" fn ttbc_input_close( return 0; // This is/was the behavior of close_file() in C. } - libc::c_int::from(es.input_close(handle)) + libc::c_int::from(es.input_close(es.input_to_id(handle))) } /// A buffer for diagnostic messages. Rust code does not need to use this type. diff --git a/crates/engine_bibtex/src/bibs.rs b/crates/engine_bibtex/src/bibs.rs index abf71015b..a0361712e 100644 --- a/crates/engine_bibtex/src/bibs.rs +++ b/crates/engine_bibtex/src/bibs.rs @@ -60,13 +60,17 @@ impl BibData { } } -pub(crate) fn eat_bib_white_space(buffers: &mut GlobalBuffer, bibs: &mut BibData) -> bool { +pub(crate) fn eat_bib_white_space( + ctx: &mut Bibtex<'_, '_>, + buffers: &mut GlobalBuffer, + bibs: &mut BibData, +) -> bool { let mut init = buffers.init(BufTy::Base); while !Scan::new() .not_class(LexClass::Whitespace) .scan_till(buffers, init) { - if !input_ln(&mut bibs.top_file_mut().file, buffers) { + if !input_ln(ctx.engine, &mut bibs.top_file_mut().file, buffers) { return false; } @@ -96,7 +100,7 @@ pub(crate) fn compress_bib_white( .not_class(LexClass::Whitespace) .scan_till(buffers, last) { - let res = !input_ln(&mut bibs.top_file_mut().file, buffers); + let res = !input_ln(ctx.engine, &mut bibs.top_file_mut().file, buffers); if res { return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command).map(|_| false); @@ -124,7 +128,11 @@ pub(crate) fn get_bib_command_or_entry_and_process( let mut init = globals.buffers.init(BufTy::Base); while !Scan::new().chars(&[b'@']).scan_till(globals.buffers, init) { - if !input_ln(&mut globals.bibs.top_file_mut().file, globals.buffers) { + if !input_ln( + ctx.engine, + &mut globals.bibs.top_file_mut().file, + globals.buffers, + ) { return Ok(()); } @@ -143,7 +151,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( .buffers .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, @@ -186,7 +194,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( match globals.hash.ilk_info(res.loc) { 0 => (), 1 => { - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, @@ -220,7 +228,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers.offset(BufTy::Base, 2) + 1, ); - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, @@ -271,7 +279,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( ); } 2 => { - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, @@ -305,7 +313,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers.offset(BufTy::Base, 2) + 1, ); - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, @@ -349,7 +357,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( .hash .set_ilk_info(res.loc, globals.hash.text(res.loc) as i32); - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, @@ -377,7 +385,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers.offset(BufTy::Base, 2) + 1, ); - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, @@ -442,7 +450,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( let type_exists = bst_res.exists && globals.hash.ty(bst_res.loc) == FnClass::Wizard; - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, @@ -474,7 +482,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( .buffers .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, @@ -660,7 +668,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( } } - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, @@ -689,7 +697,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( .buffers .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, @@ -736,7 +744,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( } } - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, @@ -762,7 +770,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( .buffers .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); - if !eat_bib_white_space(globals.buffers, globals.bibs) { + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, globals.buffers, diff --git a/crates/engine_bibtex/src/bst.rs b/crates/engine_bibtex/src/bst.rs index ff61dae89..b66434024 100644 --- a/crates/engine_bibtex/src/bst.rs +++ b/crates/engine_bibtex/src/bst.rs @@ -597,7 +597,7 @@ fn bst_read_command( let mut cur_macro_loc = 0; let mut field_name_loc = 0; - while !globals.bibs.top_file_mut().file.eof() { + while !globals.bibs.top_file_mut().file.eof(ctx.glbl_ctx.engine) { get_bib_command_or_entry_and_process( ctx.glbl_ctx_mut(), globals, diff --git a/crates/engine_bibtex/src/lib.rs b/crates/engine_bibtex/src/lib.rs index fcbcf8a91..d39cfc8aa 100644 --- a/crates/engine_bibtex/src/lib.rs +++ b/crates/engine_bibtex/src/lib.rs @@ -40,14 +40,9 @@ use crate::{ use std::{ ffi::{CStr, CString}, io::Write, - ptr, -}; -use tectonic_bridge_core::{ - ttbc_input_close, ttbc_input_open, ttbc_output_close, ttbc_output_open, - ttbc_output_open_stdout, CoreBridgeLauncher, CoreBridgeState, FileFormat, }; +use tectonic_bridge_core::{CoreBridgeLauncher, CoreBridgeState, FileFormat, OutputId}; use tectonic_errors::prelude::*; -use tectonic_io_base::OutputHandle; pub(crate) mod auxi; pub(crate) mod bibs; @@ -202,8 +197,8 @@ impl Default for BibtexConfig { #[derive(Default)] pub(crate) struct Logs { - stdout: Option<&'static mut OutputHandle>, - file: Option<&'static mut OutputHandle>, + stdout: Option, + file: Option, } pub(crate) struct Bibtex<'a, 'cbs> { @@ -214,7 +209,7 @@ pub(crate) struct Bibtex<'a, 'cbs> { pub bst: Option, - pub bbl_file: *mut OutputHandle, + pub bbl_file: Option, pub bbl_line_num: usize, pub impl_fn_num: usize, @@ -246,7 +241,7 @@ impl<'a, 'cbs> Bibtex<'a, 'cbs> { history: History::Spotless, logs: Logs::default(), bst: None, - bbl_file: ptr::null_mut(), + bbl_file: None, bbl_line_num: 0, impl_fn_num: 0, cite_xptr: 0, @@ -286,29 +281,34 @@ impl<'a, 'cbs> Bibtex<'a, 'cbs> { } pub(crate) fn write_logs(&mut self, str: &B) { - let _ = self.logs.file.as_mut().unwrap().write_all(str.as_bytes()); - let _ = self.logs.stdout.as_mut().unwrap().write_all(str.as_bytes()); + let _ = self + .engine + .get_output(self.logs.file.unwrap()) + .write_all(str.as_bytes()); + let _ = self + .engine + .get_output(self.logs.stdout.unwrap()) + .write_all(str.as_bytes()); } pub(crate) fn write_stdout(&mut self, str: &B) { - let _ = self.logs.stdout.as_mut().unwrap().write_all(str.as_bytes()); + let _ = self + .engine + .get_output(self.logs.stdout.unwrap()) + .write_all(str.as_bytes()); } pub(crate) fn write_log_file(&mut self, str: &B) { - self.logs - .file - .as_mut() - .unwrap() + self.engine + .get_output(self.logs.file.unwrap()) .write_all(str.as_bytes()) .unwrap(); } pub(crate) fn init_stdout(&mut self) -> bool { if self.logs.stdout.is_none() { - let stdout = ttbc_output_open_stdout(self.engine); - // SAFETY: Pointer from ttstub_output_open_stdout is valid if non-null - self.logs.stdout = unsafe { stdout.as_mut() }; - !stdout.is_null() + self.logs.stdout = self.engine.output_open_stdout(); + self.logs.stdout.is_some() } else { true } @@ -316,11 +316,8 @@ impl<'a, 'cbs> Bibtex<'a, 'cbs> { pub(crate) fn init_log_file(&mut self, file: &CStr) -> bool { if self.logs.file.is_none() { - // SAFETY: Our CStr is valid for the length of the call, so this can't access bad memory - let new = unsafe { ttbc_output_open(self.engine, file.as_ptr(), 0) }; - // SAFETY: Return of ttstub_output_open should be valid if non-null - self.logs.file = unsafe { new.as_mut() }; - !new.is_null() + self.logs.file = self.engine.output_open(file.to_str().unwrap(), false); + self.logs.file.is_some() } else { true } @@ -400,10 +397,14 @@ pub(crate) fn bibtex_main(ctx: &mut Bibtex<'_, '_>, aux_file_name: &CStr) -> His match res { Err(BibtexError::Recover) | Ok(History::Spotless) => { ctx.bst.take().map(|file| file.file.close(ctx)); - ttbc_output_close(ctx.engine, ctx.bbl_file); + if let Some(bbl) = ctx.bbl_file { + ctx.engine.output_close(bbl); + } } Err(BibtexError::NoBst) => { - ttbc_output_close(ctx.engine, ctx.bbl_file); + if let Some(bbl) = ctx.bbl_file { + ctx.engine.output_close(bbl); + } } Err(BibtexError::Fatal) => (), Ok(hist) => return hist, @@ -471,7 +472,11 @@ pub(crate) fn inner_bibtex_main( let last_aux = loop { globals.aux.top_file_mut().line += 1; - if !input_ln(&mut globals.aux.top_file_mut().file, globals.buffers) { + if !input_ln( + ctx.engine, + &mut globals.aux.top_file_mut().file, + globals.buffers, + ) { if let Some(last) = pop_the_aux_stack(ctx, globals.aux) { break last; } @@ -538,9 +543,8 @@ pub(crate) fn get_the_top_level_aux_file_name( set_extension(&mut path, b".bbl"); let bbl_file = CStr::from_bytes_with_nul(&path).unwrap(); - // SAFETY: Function sound if provided a valid path pointer - ctx.bbl_file = unsafe { ttbc_output_open(ctx.engine, bbl_file.as_ptr(), 0) }; - if ctx.bbl_file.is_null() { + ctx.bbl_file = ctx.engine.output_open(bbl_file.to_str().unwrap(), false); + if ctx.bbl_file.is_none() { sam_wrong_file_name_print(ctx, bbl_file); return Ok(1); } diff --git a/crates/engine_bibtex/src/log.rs b/crates/engine_bibtex/src/log.rs index 144f47d19..6f07baffa 100644 --- a/crates/engine_bibtex/src/log.rs +++ b/crates/engine_bibtex/src/log.rs @@ -10,8 +10,7 @@ use crate::{ peekable::input_ln, pool::StringPool, scan::{Scan, ScanRes}, - ttbc_output_close, ASCIICode, Bibtex, BibtexError, CiteNumber, FieldLoc, HashPointer, - StrNumber, + ASCIICode, Bibtex, BibtexError, CiteNumber, FieldLoc, HashPointer, StrNumber, }; use std::{ffi::CStr, io::Write, slice}; use tectonic_io_base::OutputHandle; @@ -40,7 +39,7 @@ impl AsBytes for [u8] { pub(crate) fn bib_close_log(ctx: &mut Bibtex<'_, '_>) { if let Some(log) = ctx.logs.file.take() { - ttbc_output_close(ctx.engine, log); + ctx.engine.output_close(log); } } @@ -62,8 +61,8 @@ pub(crate) fn out_token(handle: &mut OutputHandle, buffers: &GlobalBuffer) { } pub(crate) fn print_a_token(ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer) { - out_token(ctx.logs.stdout.as_mut().unwrap(), buffers); - out_token(ctx.logs.file.as_mut().unwrap(), buffers); + out_token(ctx.engine.get_output(ctx.logs.stdout.unwrap()), buffers); + out_token(ctx.engine.get_output(ctx.logs.file.unwrap()), buffers); } pub(crate) fn print_bad_input_line(ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer) { @@ -558,7 +557,7 @@ pub(crate) fn bst_err_print_and_look_for_blank_line( bst_ln_num_print(ctx, pool)?; print_bad_input_line(ctx, buffers); while buffers.init(BufTy::Base) != 0 { - if !input_ln(&mut ctx.bst.as_mut().unwrap().file, buffers) { + if !input_ln(ctx.engine, &mut ctx.bst.as_mut().unwrap().file, buffers) { return Err(BibtexError::Recover); } else { ctx.bst.as_mut().unwrap().line += 1; @@ -612,11 +611,12 @@ pub(crate) fn output_bbl_line(ctx: &mut Bibtex<'_, '_>, buffers: &mut GlobalBuff return; } let slice = &buffers.buffer(BufTy::Out)[..init]; - // SAFETY: The bbl_file pointer is guaranteed valid - (unsafe { &mut *ctx.bbl_file }).write_all(slice).unwrap(); + ctx.engine + .get_output(ctx.bbl_file.unwrap()) + .write_all(slice) + .unwrap(); } - // SAFETY: The bbl_file pointer is guaranteed valid - writeln!(unsafe { &mut *ctx.bbl_file }).unwrap(); + writeln!(ctx.engine.get_output(ctx.bbl_file.unwrap())).unwrap(); ctx.bbl_line_num += 1; buffers.set_init(BufTy::Out, 0); } diff --git a/crates/engine_bibtex/src/peekable.rs b/crates/engine_bibtex/src/peekable.rs index a3402612f..2a3ce0c8f 100644 --- a/crates/engine_bibtex/src/peekable.rs +++ b/crates/engine_bibtex/src/peekable.rs @@ -1,18 +1,17 @@ use crate::{ buffer::{BufTy, GlobalBuffer}, char_info::LexClass, - ttbc_input_close, ttbc_input_open, ASCIICode, Bibtex, BibtexError, BufPointer, + ASCIICode, Bibtex, BibtexError, BufPointer, }; use libc::EOF; -use std::{ffi::CStr, io, ptr::NonNull}; -use tectonic_bridge_core::FileFormat; -use tectonic_io_base::InputHandle; +use std::{ffi::CStr, io}; +use tectonic_bridge_core::{CoreBridgeState, FileFormat, InputId}; /* Sigh, I'm worried about ungetc() and EOF semantics in Bibtex's I/O, so * here's a tiny wrapper that lets us fake it. */ pub(crate) struct PeekableInput { - handle: NonNull, + id: InputId, peek_char: libc::c_int, saw_eof: bool, } @@ -23,12 +22,11 @@ impl PeekableInput { path: &CStr, format: FileFormat, ) -> Result { - // SAFETY: Our CStr is valid for the length of the call, so this can't access bad memory - let handle = unsafe { ttbc_input_open(ctx.engine, path.as_ptr(), format, 0) }; + let id = ctx.engine.input_open(path.to_str().unwrap(), format, false); - if let Some(handle) = NonNull::new(handle) { + if let Some(id) = id { Ok(PeekableInput { - handle, + id, peek_char: EOF, saw_eof: false, }) @@ -38,15 +36,14 @@ impl PeekableInput { } pub(crate) fn close(self, ctx: &mut Bibtex<'_, '_>) -> Result<(), BibtexError> { - let err = ttbc_input_close(ctx.engine, self.handle.as_ptr()); - if err == 0 { + if !ctx.engine.input_close(self.id) { Ok(()) } else { Err(BibtexError::Fatal) } } - fn getc(&mut self) -> libc::c_int { + fn getc(&mut self, engine: &mut CoreBridgeState<'_>) -> libc::c_int { if self.peek_char != EOF { let rv = self.peek_char; self.peek_char = EOF; @@ -55,7 +52,7 @@ impl PeekableInput { // SAFETY: Internal handle guaranteed valid, unique access to this input is unique access // to the handle - let handle = unsafe { self.handle.as_mut() }; + let handle = engine.get_input(self.id); let rv = match handle.getc() { Ok(c) => libc::c_int::from(c), Err(e) => { @@ -78,11 +75,11 @@ impl PeekableInput { self.peek_char = c; } - pub fn eof(&mut self) -> bool { + pub fn eof(&mut self, engine: &mut CoreBridgeState<'_>) -> bool { if self.saw_eof { return true; } - let c = self.getc(); + let c = self.getc(engine); if c == EOF { return true; } @@ -90,11 +87,11 @@ impl PeekableInput { false } - fn eoln(&mut self) -> bool { + fn eoln(&mut self, engine: &mut CoreBridgeState<'_>) -> bool { if self.saw_eof { return true; } - let c = self.getc(); + let c = self.getc(engine); if c != EOF { self.ungetc(c); } @@ -102,27 +99,31 @@ impl PeekableInput { } } -pub(crate) fn input_ln(peekable: &mut PeekableInput, buffers: &mut GlobalBuffer) -> bool { +pub(crate) fn input_ln( + engine: &mut CoreBridgeState<'_>, + peekable: &mut PeekableInput, + buffers: &mut GlobalBuffer, +) -> bool { buffers.set_init(BufTy::Base, 0); let mut last = 0; - if peekable.eof() { + if peekable.eof(engine) { return false; } // Read up to end-of-line - while !peekable.eoln() { + while !peekable.eoln(engine) { if last >= buffers.len() as BufPointer { buffers.grow_all(); } - buffers.set_at(BufTy::Base, last, peekable.getc() as ASCIICode); + buffers.set_at(BufTy::Base, last, peekable.getc(engine) as ASCIICode); last += 1; } // For side effects - consume the eoln we saw - let eoln = peekable.getc(); + let eoln = peekable.getc(engine); if eoln == '\r' as libc::c_int { - let next = peekable.getc(); + let next = peekable.getc(engine); if next != '\n' as libc::c_int { peekable.ungetc(next); } diff --git a/crates/engine_bibtex/src/scan.rs b/crates/engine_bibtex/src/scan.rs index 3c4a01ccf..6fd939a1b 100644 --- a/crates/engine_bibtex/src/scan.rs +++ b/crates/engine_bibtex/src/scan.rs @@ -166,7 +166,7 @@ pub(crate) fn eat_bst_white_space(ctx: &mut Bibtex<'_, '_>, buffers: &mut Global return true; } - if !input_ln(&mut ctx.bst.as_mut().unwrap().file, buffers) { + if !input_ln(ctx.engine, &mut ctx.bst.as_mut().unwrap().file, buffers) { return false; } @@ -502,7 +502,7 @@ fn scan_balanced_braces( b'{' => { brace_level += 1; buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); - if !eat_bib_white_space(buffers, bibs) { + if !eat_bib_white_space(ctx, buffers, bibs) { return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command) .map(|_| false); } @@ -519,8 +519,8 @@ fn scan_balanced_braces( let init = buffers.init(BufTy::Base); if (c == b'{' || c == b'}' - || !Scan::new().chars(b"{}").scan_till(buffers, init)) - && !eat_bib_white_space(buffers, bibs) + || !Scan::new().chars(&[b'{', b'}']).scan_till(buffers, init)) + && !eat_bib_white_space(ctx, buffers, bibs) { return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command) .map(|_| false); @@ -537,7 +537,7 @@ fn scan_balanced_braces( if !Scan::new() .chars(&[right_str_delim, b'{', b'}']) .scan_till(buffers, init) - && !eat_bib_white_space(buffers, bibs) + && !eat_bib_white_space(ctx, buffers, bibs) { return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command) .map(|_| false); @@ -690,7 +690,7 @@ fn scan_a_field_token_and_eat_white( } } - if !eat_bib_white_space(buffers, bibs) { + if !eat_bib_white_space(ctx, buffers, bibs) { return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command).map(|_| false); } Ok(true) @@ -732,7 +732,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( } while buffers.at_offset(BufTy::Base, 2) == b'#' { buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); - if !eat_bib_white_space(buffers, bibs) { + if !eat_bib_white_space(ctx, buffers, bibs) { return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command).map(|_| false); } if !scan_a_field_token_and_eat_white( From 64fe73cf4c8c7ef3d924a2d9d758179eb0d6b1e0 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sun, 25 Feb 2024 18:56:22 -0800 Subject: [PATCH 11/23] Step 1 of improving hash - simplify arrays, remove set_ilk_info, etc --- crates/engine_bibtex/src/auxi.rs | 16 +- crates/engine_bibtex/src/bibs.rs | 33 ++-- crates/engine_bibtex/src/bst.rs | 69 ++++----- crates/engine_bibtex/src/cite.rs | 11 +- crates/engine_bibtex/src/exec.rs | 4 +- crates/engine_bibtex/src/hash.rs | 131 ++++++++++++---- crates/engine_bibtex/src/lib.rs | 11 +- crates/engine_bibtex/src/pool.rs | 253 +++++++++++++++---------------- crates/engine_bibtex/src/scan.rs | 20 +-- 9 files changed, 303 insertions(+), 245 deletions(-) diff --git a/crates/engine_bibtex/src/auxi.rs b/crates/engine_bibtex/src/auxi.rs index 13aebe8f1..eb41d6db5 100644 --- a/crates/engine_bibtex/src/auxi.rs +++ b/crates/engine_bibtex/src/auxi.rs @@ -4,7 +4,7 @@ use crate::{ char_info::LexClass, cite::CiteInfo, exec::print_bst_name, - hash::HashData, + hash::{HashData, HashExtra}, log::{ aux_end1_err_print, aux_end2_err_print, aux_err_illegal_another_print, aux_err_no_right_brace_print, aux_err_print, aux_err_stuff_after_right_brace_print, @@ -97,7 +97,7 @@ fn aux_bib_data_command( let file = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(ctx, hash, file, StrIlk::BibFile)?; + let res = pool.lookup_str_insert(ctx, hash, file, HashExtra::BibFile)?; if res.exists { ctx.write_logs("This database file appears more than once: "); print_bib_name(ctx, pool, hash.text(res.loc))?; @@ -168,7 +168,7 @@ fn aux_bib_style_command( let file = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(ctx, hash, file, StrIlk::BstFile)?; + let res = pool.lookup_str_insert(ctx, hash, file, HashExtra::BstFile)?; if res.exists { ctx.write_logs("Already encountered style file"); print_confusion(ctx); @@ -268,7 +268,7 @@ fn aux_citation_command( let lc_cite = &mut buffers.buffer_mut(BufTy::Ex)[range]; lc_cite.make_ascii_lowercase(); - let lc_res = pool.lookup_str_insert(ctx, hash, lc_cite, StrIlk::LcCite)?; + let lc_res = pool.lookup_str_insert(ctx, hash, lc_cite, HashExtra::LcCite(0))?; if lc_res.exists { let cite = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; @@ -289,7 +289,7 @@ fn aux_citation_command( } else { let cite = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let uc_res = pool.lookup_str_insert(ctx, hash, cite, StrIlk::Cite)?; + let uc_res = pool.lookup_str_insert(ctx, hash, cite, HashExtra::Cite(0))?; if uc_res.exists { hash_cite_confusion(ctx); return Err(BibtexError::Fatal); @@ -300,8 +300,8 @@ fn aux_citation_command( } cites.set_cite(cites.ptr(), hash.text(uc_res.loc)); - hash.set_ilk_info(uc_res.loc, cites.ptr() as i32); - hash.set_ilk_info(lc_res.loc, uc_res.loc as i32); + hash.node_mut(uc_res.loc).extra = HashExtra::Cite(cites.ptr()); + hash.node_mut(lc_res.loc).extra = HashExtra::LcCite(uc_res.loc); cites.set_ptr(cites.ptr() + 1); } } @@ -363,7 +363,7 @@ fn aux_input_command( let file = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(ctx, hash, file, StrIlk::AuxFile)?; + let res = pool.lookup_str_insert(ctx, hash, file, HashExtra::AuxFile)?; if res.exists { ctx.write_logs("Already encountered file "); print_aux_name(ctx, pool, hash.text(res.loc))?; diff --git a/crates/engine_bibtex/src/bibs.rs b/crates/engine_bibtex/src/bibs.rs index a0361712e..470f3d307 100644 --- a/crates/engine_bibtex/src/bibs.rs +++ b/crates/engine_bibtex/src/bibs.rs @@ -2,7 +2,7 @@ use crate::{ buffer::{BufTy, GlobalBuffer}, char_info::LexClass, cite::add_database_cite, - hash::{FnClass, HashData}, + hash::{FnClass, HashData, HashExtra}, log::{ bib_cmd_confusion, bib_equals_sign_print, bib_err_print, bib_id_print, bib_one_of_two_print, bib_warn_print, cite_key_disappeared_confusion, eat_bib_print, @@ -346,16 +346,16 @@ pub(crate) fn get_bib_command_or_entry_and_process( let bib_macro = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bib_macro.make_ascii_lowercase(); + let text = globals.hash.text(res.loc); let res = globals.pool.lookup_str_insert( ctx, globals.hash, bib_macro, - StrIlk::BibCommand, + HashExtra::BibCommand(text), )?; + // TODO: Insert overwriting? + globals.hash.node_mut(res.loc).extra = HashExtra::BibCommand(text); *cur_macro_loc = res.loc; - globals - .hash - .set_ilk_info(res.loc, globals.hash.text(res.loc) as i32); if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( @@ -516,7 +516,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( let lc_res = if ctx.all_entries { globals .pool - .lookup_str_insert(ctx, globals.hash, lc_cite, StrIlk::LcCite)? + .lookup_str_insert(ctx, globals.hash, lc_cite, HashExtra::LcCite(0))? } else { globals .pool @@ -544,10 +544,12 @@ pub(crate) fn get_bib_command_or_entry_and_process( let range = globals.buffers.offset(BufTy::Base, 1) ..globals.buffers.offset(BufTy::Base, 2); let cite = &globals.buffers.buffer(BufTy::Base)[range]; - let uc_res = - globals - .pool - .lookup_str_insert(ctx, globals.hash, cite, StrIlk::Cite); + let uc_res = globals.pool.lookup_str_insert( + ctx, + globals.hash, + cite, + HashExtra::Cite(0), + ); let uc_res = match uc_res { Ok(res) => res, @@ -557,8 +559,8 @@ pub(crate) fn get_bib_command_or_entry_and_process( res = uc_res; if !uc_res.exists { - globals.hash.set_ilk_info(lc_res.loc, uc_res.loc as i32); - globals.hash.set_ilk_info(uc_res.loc, entry_ptr as i32); + globals.hash.node_mut(lc_res.loc).extra = HashExtra::LcCite(uc_res.loc); + globals.hash.node_mut(uc_res.loc).extra = HashExtra::Cite(entry_ptr); globals .cites .set_cite(entry_ptr, globals.hash.text(uc_res.loc)); @@ -629,9 +631,10 @@ pub(crate) fn get_bib_command_or_entry_and_process( } else { let cite = &globals.buffers.buffer(BufTy::Base) [globals.buffers.offset(BufTy::Base, 1)..globals.buffers.offset(BufTy::Base, 2)]; - let res = globals - .pool - .lookup_str_insert(ctx, globals.hash, cite, StrIlk::Cite)?; + let res = + globals + .pool + .lookup_str_insert(ctx, globals.hash, cite, HashExtra::Cite(0))?; if res.exists { hash_cite_confusion(ctx); return Err(BibtexError::Fatal); diff --git a/crates/engine_bibtex/src/bst.rs b/crates/engine_bibtex/src/bst.rs index b66434024..d6f9321ee 100644 --- a/crates/engine_bibtex/src/bst.rs +++ b/crates/engine_bibtex/src/bst.rs @@ -4,7 +4,7 @@ use crate::{ char_info::LexClass, cite::find_cite_locs_for_this_cite_key, exec::{check_command_execution, execute_fn, ExecCtx}, - hash::{FnClass, HashData}, + hash::{FnClass, HashData, HashExtra}, log::{ already_seen_function_print, bad_cross_reference_print, bst_err_print_and_look_for_blank_line, bst_id_print, bst_left_brace_print, @@ -107,7 +107,7 @@ fn bst_entry_command( ctx.glbl_ctx_mut(), globals.hash, bst_fn, - StrIlk::BstFn, + HashExtra::BstFn(globals.other.num_fields() as i32), )?; if res.exists { already_seen_function_print( @@ -121,9 +121,6 @@ fn bst_entry_command( } globals.hash.set_ty(res.loc, FnClass::Field); - globals - .hash - .set_ilk_info(res.loc, globals.other.num_fields() as i32); globals.other.set_num_fields(globals.other.num_fields() + 1); eat_bst_white!(ctx, globals, "entry"); @@ -157,7 +154,7 @@ fn bst_entry_command( ctx.glbl_ctx_mut(), globals.hash, bst_fn, - StrIlk::BstFn, + HashExtra::BstFn(globals.entries.num_ent_ints() as i32), )?; if res.exists { already_seen_function_print( @@ -171,9 +168,6 @@ fn bst_entry_command( } globals.hash.set_ty(res.loc, FnClass::IntEntryVar); - globals - .hash - .set_ilk_info(res.loc, globals.entries.num_ent_ints() as i32); globals .entries .set_num_ent_ints(globals.entries.num_ent_ints() + 1); @@ -202,7 +196,7 @@ fn bst_entry_command( ctx.glbl_ctx_mut(), globals.hash, bst_fn, - StrIlk::BstFn, + HashExtra::BstFn(globals.entries.num_ent_strs() as i32), )?; if res.exists { already_seen_function_print( @@ -216,9 +210,6 @@ fn bst_entry_command( } globals.hash.set_ty(res.loc, FnClass::StrEntryVar); - globals - .hash - .set_ilk_info(res.loc, globals.entries.num_ent_strs() as i32); globals .entries .set_num_ent_strs(globals.entries.num_ent_strs() + 1); @@ -295,10 +286,12 @@ fn bst_function_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = - globals - .pool - .lookup_str_insert(ctx.glbl_ctx_mut(), globals.hash, bst_fn, StrIlk::BstFn)?; + let res = globals.pool.lookup_str_insert( + ctx.glbl_ctx_mut(), + globals.hash, + bst_fn, + HashExtra::BstFn(0), + )?; if res.exists { already_seen_function_print( ctx.glbl_ctx_mut(), @@ -359,7 +352,7 @@ fn bst_integers_command( ctx.glbl_ctx_mut(), globals.hash, bst_fn, - StrIlk::BstFn, + HashExtra::BstFn(0), )?; if res.exists { already_seen_function_print( @@ -373,7 +366,6 @@ fn bst_integers_command( } globals.hash.set_ty(res.loc, FnClass::IntGlblVar); - globals.hash.set_ilk_info(res.loc, 0); eat_bst_white!(ctx, globals, "integers"); } @@ -458,10 +450,12 @@ fn bst_macro_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = - globals - .pool - .lookup_str_insert(ctx.glbl_ctx_mut(), globals.hash, bst_fn, StrIlk::Macro)?; + let res = globals.pool.lookup_str_insert( + ctx.glbl_ctx_mut(), + globals.hash, + bst_fn, + HashExtra::Macro(0), + )?; if res.exists { print_a_token(ctx.glbl_ctx_mut(), globals.buffers); ctx.glbl_ctx_mut() @@ -469,9 +463,8 @@ fn bst_macro_command( bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; return Ok(()); } - globals - .hash - .set_ilk_info(res.loc, globals.hash.text(res.loc) as i32); + // This is always unused if the macro is successfully defined, but appears to be a fallback for invalid macros. + globals.hash.node_mut(res.loc).extra = HashExtra::Macro(globals.hash.text(res.loc)); eat_bst_white!(ctx, globals, "macro"); bst_brace!('}', ctx, globals, "macro"); @@ -503,15 +496,15 @@ fn bst_macro_command( let range = globals.buffers.offset(BufTy::Base, 1)..globals.buffers.offset(BufTy::Base, 2); let text = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; - let res2 = - globals - .pool - .lookup_str_insert(ctx.glbl_ctx_mut(), globals.hash, text, StrIlk::Text)?; + let res2 = globals.pool.lookup_str_insert( + ctx.glbl_ctx_mut(), + globals.hash, + text, + HashExtra::Text(0), + )?; globals.hash.set_ty(res2.loc, FnClass::StrLit); - globals - .hash - .set_ilk_info(res.loc, globals.hash.text(res2.loc) as i32); + globals.hash.node_mut(res.loc).extra = HashExtra::Macro(globals.hash.text(res2.loc)); globals .buffers .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); @@ -769,9 +762,8 @@ fn bst_read_command( return Err(BibtexError::Fatal); } - globals - .hash - .set_ilk_info(find.cite_loc, ctx.glbl_ctx().cite_xptr as i32); + globals.hash.node_mut(find.cite_loc).extra = + HashExtra::Cite(ctx.glbl_ctx().cite_xptr); let start = ctx.glbl_ctx().cite_xptr * globals.other.num_fields(); let end = start + globals.other.num_fields(); @@ -909,7 +901,7 @@ fn bst_strings_command( ctx.glbl_ctx_mut(), globals.hash, bst_fn, - StrIlk::BstFn, + HashExtra::BstFn(globals.globals.num_glb_strs()), )?; if res.exists { @@ -924,9 +916,6 @@ fn bst_strings_command( } globals.hash.set_ty(res.loc, FnClass::StrGlblVar); - globals - .hash - .set_ilk_info(res.loc, globals.globals.num_glb_strs()); if globals.globals.num_glb_strs() as usize == globals.globals.len() { globals.globals.grow(); diff --git a/crates/engine_bibtex/src/cite.rs b/crates/engine_bibtex/src/cite.rs index d5fd49949..658b5991a 100644 --- a/crates/engine_bibtex/src/cite.rs +++ b/crates/engine_bibtex/src/cite.rs @@ -1,6 +1,9 @@ use crate::{ - entries::EntryData, hash::HashData, other::OtherData, pool::StringPool, CiteNumber, - FindCiteLocs, HashPointer, StrIlk, StrNumber, + entries::EntryData, + hash::{HashData, HashExtra}, + other::OtherData, + pool::StringPool, + CiteNumber, FindCiteLocs, HashPointer, StrIlk, StrNumber, }; use std::{cmp::Ordering, ops::IndexMut}; @@ -150,8 +153,8 @@ pub(crate) fn add_database_cite( other.check_field_overflow(other.num_fields() * (new_cite + 1)); cites.set_cite(new_cite, hash.text(cite_loc)); - hash.set_ilk_info(cite_loc, new_cite as i32); - hash.set_ilk_info(lc_cite_loc, cite_loc as i32); + hash.node_mut(cite_loc).extra = HashExtra::Cite(new_cite); + hash.node_mut(lc_cite_loc).extra = HashExtra::LcCite(cite_loc); new_cite + 1 } diff --git a/crates/engine_bibtex/src/exec.rs b/crates/engine_bibtex/src/exec.rs index 3af7246c1..99bad2580 100644 --- a/crates/engine_bibtex/src/exec.rs +++ b/crates/engine_bibtex/src/exec.rs @@ -5,7 +5,7 @@ use crate::{ cite::CiteInfo, entries::{EntryData, ENT_STR_SIZE}, global::{GlobalData, GLOB_STR_SIZE}, - hash::{FnClass, HashData}, + hash::{FnClass, HashData, HashExtra}, log::{ brace_lvl_one_letters_complaint, braces_unbalanced_complaint, bst_1print_string_size_exceeded, bst_2print_string_size_exceeded, @@ -939,7 +939,7 @@ fn interp_gets( } FnClass::IntGlblVar => { if let ExecVal::Integer(i2) = pop2 { - hash.set_ilk_info(f1, i2); + hash.node_mut(f1).extra = HashExtra::BstFn(i2); } else { print_wrong_stk_lit(ctx, pool, hash, cites, pop2, StkType::Integer)?; } diff --git a/crates/engine_bibtex/src/hash.rs b/crates/engine_bibtex/src/hash.rs index 35967cd45..89a0270a3 100644 --- a/crates/engine_bibtex/src/hash.rs +++ b/crates/engine_bibtex/src/hash.rs @@ -1,4 +1,4 @@ -use crate::{pool, HashPointer, StrIlk, StrNumber}; +use crate::{pool, CiteNumber, HashPointer, StrIlk, StrNumber}; pub(crate) const HASH_BASE: usize = 1; pub(crate) const HASH_SIZE: usize = if pool::MAX_STRINGS > 5000 { @@ -71,25 +71,96 @@ pub(crate) enum FnClass { StrGlblVar, } +#[derive(Clone, Debug)] +pub enum HashExtra { + Text(StrNumber), + Integer(i32), + AuxCommand(i32), // TODO: Make Enum + AuxFile, + BstCommand(i32), // TODO: Make Enum + BstFile, + BibFile, + FileExt, + Cite(CiteNumber), + LcCite(HashPointer), + BstFn(i32), + BibCommand(StrNumber), // TODO: Make Enum + Macro(StrNumber), + ControlSeq(i32), +} + +impl HashExtra { + pub(crate) fn kind(&self) -> StrIlk { + match self { + HashExtra::Text(_) => StrIlk::Text, + HashExtra::Integer(_) => StrIlk::Integer, + HashExtra::AuxCommand(_) => StrIlk::AuxCommand, + HashExtra::AuxFile => StrIlk::AuxFile, + HashExtra::BstCommand(_) => StrIlk::BstCommand, + HashExtra::BstFile => StrIlk::BstFile, + HashExtra::BibFile => StrIlk::BibFile, + HashExtra::FileExt => StrIlk::FileExt, + HashExtra::Cite(_) => StrIlk::Cite, + HashExtra::LcCite(_) => StrIlk::LcCite, + HashExtra::BstFn(_) => StrIlk::BstFn, + HashExtra::BibCommand(_) => StrIlk::BibCommand, + HashExtra::Macro(_) => StrIlk::Macro, + HashExtra::ControlSeq(_) => StrIlk::ControlSeq, + } + } + + fn data_i32(&self) -> i32 { + match self { + HashExtra::Text(s) => *s as i32, + HashExtra::Integer(i) => *i, + HashExtra::AuxCommand(c) => *c, + HashExtra::AuxFile => todo!(), + HashExtra::BstCommand(c) => *c, + HashExtra::BstFile => todo!(), + HashExtra::BibFile => todo!(), + HashExtra::FileExt => todo!(), + HashExtra::Cite(c) => *c as i32, + HashExtra::LcCite(c) => *c as i32, + HashExtra::BstFn(c) => *c, + HashExtra::BibCommand(c) => *c as i32, + HashExtra::Macro(c) => *c as i32, + HashExtra::ControlSeq(c) => *c, + } + } +} + +impl Default for HashExtra { + fn default() -> Self { + HashExtra::Text(0) + } +} + +#[derive(Clone, Default, Debug)] +pub struct HashNode { + next: HashPointer, + text: StrNumber, + pub(crate) extra: HashExtra, +} + +impl HashNode { + pub(crate) fn kind(&self) -> StrIlk { + self.extra.kind() + } +} + // TODO: Split string-pool stuff into string pool, executor stuff into execution context pub(crate) struct HashData { - hash_next: Vec, - hash_text: Vec, - hash_ilk: Vec, - ilk_info: Vec, + hash_data: Vec, fn_type: Vec, - hash_used: usize, + len: usize, } impl HashData { pub(crate) fn new() -> HashData { HashData { - hash_next: vec![0; HASH_MAX + 1], - hash_text: vec![0; HASH_MAX + 1], - hash_ilk: vec![StrIlk::Text; HASH_MAX + 1], - ilk_info: vec![0; HASH_MAX + 1], + hash_data: vec![HashNode::default(); HASH_MAX + 1], fn_type: vec![FnClass::Builtin; HASH_MAX + 1], - hash_used: HASH_MAX + 1, + len: HASH_MAX + 1, } } @@ -101,20 +172,28 @@ impl HashData { HASH_MAX + 1 } + pub fn node(&self, pos: usize) -> &HashNode { + &self.hash_data[pos] + } + + pub fn node_mut(&mut self, pos: usize) -> &mut HashNode { + &mut self.hash_data[pos] + } + pub fn text(&self, pos: usize) -> StrNumber { - self.hash_text[pos] + self.hash_data[pos].text } pub fn set_text(&mut self, pos: usize, val: StrNumber) { - self.hash_text[pos] = val; + self.hash_data[pos].text = val; } pub fn next(&self, pos: usize) -> HashPointer { - self.hash_next[pos] + self.hash_data[pos].next } pub fn set_next(&mut self, pos: usize, val: HashPointer) { - self.hash_next[pos] = val + self.hash_data[pos].next = val } pub fn ty(&self, pos: usize) -> FnClass { @@ -125,31 +204,19 @@ impl HashData { self.fn_type[pos] = class; } - pub fn used(&self) -> usize { - self.hash_used + pub fn len(&self) -> usize { + self.len } - pub fn set_used(&mut self, val: usize) { - self.hash_used = val; + pub fn set_len(&mut self, val: usize) { + self.len = val; } pub fn prime(&self) -> usize { HASH_PRIME } - pub fn hash_ilk(&self, pos: usize) -> StrIlk { - self.hash_ilk[pos] - } - - pub fn set_hash_ilk(&mut self, pos: usize, val: StrIlk) { - self.hash_ilk[pos] = val; - } - pub fn ilk_info(&self, pos: usize) -> i32 { - self.ilk_info[pos] - } - - pub fn set_ilk_info(&mut self, pos: usize, info: i32) { - self.ilk_info[pos] = info; + self.node(pos).extra.data_i32() } } diff --git a/crates/engine_bibtex/src/lib.rs b/crates/engine_bibtex/src/lib.rs index d39cfc8aa..d4f7920d6 100644 --- a/crates/engine_bibtex/src/lib.rs +++ b/crates/engine_bibtex/src/lib.rs @@ -27,7 +27,7 @@ use crate::{ entries::EntryData, exec::ExecCtx, global::GlobalData, - hash::HashData, + hash::{HashData, HashExtra}, log::{ bib_close_log, log_pr_aux_name, print_aux_name, print_confusion, sam_wrong_file_name_print, AsBytes, @@ -550,10 +550,11 @@ pub(crate) fn get_the_top_level_aux_file_name( } set_extension(&mut path, b".aux"); - let lookup = match pool.lookup_str_insert(ctx, hash, &path[..path.len() - 1], StrIlk::AuxFile) { - Ok(res) => res, - Err(_) => return Err(BibtexError::Fatal), - }; + let lookup = + match pool.lookup_str_insert(ctx, hash, &path[..path.len() - 1], HashExtra::AuxFile) { + Ok(res) => res, + Err(_) => return Err(BibtexError::Fatal), + }; aux.push_file(File { name: hash.text(lookup.loc), diff --git a/crates/engine_bibtex/src/pool.rs b/crates/engine_bibtex/src/pool.rs index 7e7865bd5..5628216b5 100644 --- a/crates/engine_bibtex/src/pool.rs +++ b/crates/engine_bibtex/src/pool.rs @@ -4,7 +4,7 @@ use crate::{ entries::ENT_STR_SIZE, global::GLOB_STR_SIZE, hash, - hash::{FnClass, HashData}, + hash::{FnClass, HashData, HashExtra}, log::{output_bbl_line, print_overflow}, ASCIICode, Bibtex, BibtexError, GlobalItems, HashPointer, LookupRes, PoolPointer, StrIlk, StrNumber, @@ -86,24 +86,21 @@ impl StringPool { let h = Self::hash_str(hash, str); let mut p = h as HashPointer + hash::HASH_BASE as HashPointer; - loop { + let exists = loop { let existing = hash.text(p); - if existing > 0 && self.get_str(existing) == str && hash.hash_ilk(p) == ilk { - return LookupRes { - loc: p, - exists: true, - }; + if existing > 0 && self.get_str(existing) == str && hash.node(p).kind() == ilk { + break true; } if hash.next(p) == 0 { - return LookupRes { - loc: p, - exists: false, - }; + break false; } + p = hash.next(p); - } + }; + + LookupRes { loc: p, exists } } /// Lookup a string, inserting it if it isn't found. Note that this returns `Ok` whether the @@ -113,16 +110,22 @@ impl StringPool { ctx: &mut Bibtex<'_, '_>, hash: &mut HashData, str: &[ASCIICode], - ilk: StrIlk, + ilk: HashExtra, ) -> Result { + // Hash string using simple hash function. This hash is capped to HASH_PRIME let h = Self::hash_str(hash, str); let mut str_num = 0; + // Get position by adding HASH_BASE let mut p = (h + hash::HASH_BASE) as HashPointer; - loop { + // Look for an existing match, or the last slot + let existing = loop { + // Get the current text at the position let existing = hash.text(p); - if existing > 0 && self.try_get_str(existing) == Ok(str) { - if hash.hash_ilk(p) == ilk { + // If the text exists and is the same as the text we're adding + if self.try_get_str(existing) == Ok(str) { + // If an existing hash entry exists for this type, return it + if hash.node(p).kind() == ilk.kind() { return Ok(LookupRes { loc: p, exists: true, @@ -133,48 +136,58 @@ impl StringPool { } if hash.next(p) == 0 { - if existing > 0 { - loop { - if hash.used() == hash::HASH_BASE { - print_overflow(ctx); - ctx.write_logs(&format!("hash size {}\n", hash::HASH_SIZE)); - return Err(BibtexError::Fatal); - } - hash.set_used(hash.used() - 1); - - if hash.text(hash.used()) == 0 { - break; - } - } - hash.set_next(p, hash.used()); - p = hash.used(); - } - - if str_num > 0 { - hash.set_text(p, str_num); - } else { - while self.pool_ptr + str.len() > self.strings.len() { - self.grow(); - } - self.strings[self.pool_ptr..self.pool_ptr + str.len()].copy_from_slice(str); - self.pool_ptr += str.len(); + break existing; + } - match self.make_string(ctx) { - Ok(str) => hash.set_text(p, str), - Err(err) => return Err(err), - } + p = hash.next(p); + }; + + // If we hit the end and the slot is already in use + if existing > 0 { + // Walk backwards from our current len to our first empty slot. + // If all slots are full, error + loop { + if hash.len() == hash::HASH_BASE { + print_overflow(ctx); + ctx.write_logs(&format!("hash size {}\n", hash::HASH_SIZE)); + return Err(BibtexError::Fatal); } + hash.set_len(hash.len() - 1); - hash.set_hash_ilk(p, ilk); + if hash.text(hash.len()) == 0 { + break; + } + } + // Set the next item to our new lowest open slot + hash.set_next(p, hash.len()); + // Operate on the new empty slot + p = hash.len(); + } - return Ok(LookupRes { - loc: p, - exists: false, - }); + // We found the string in the string pool while hunting for a slot + if str_num > 0 { + hash.set_text(p, str_num); + // The string isn't in the string pool - add it + } else { + while self.pool_ptr + str.len() > self.strings.len() { + self.grow(); } + self.strings[self.pool_ptr..self.pool_ptr + str.len()].copy_from_slice(str); + self.pool_ptr += str.len(); - p = hash.next(p); + match self.make_string(ctx) { + Ok(str) => hash.set_text(p, str), + Err(err) => return Err(err), + } } + + // Set the type of this slot + hash.node_mut(p).extra = ilk; + + Ok(LookupRes { + loc: p, + exists: false, + }) } pub fn str_ptr(&self) -> usize { @@ -267,50 +280,32 @@ pub(crate) fn pre_def_certain_strings( .. }: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { - let res = pool.lookup_str_insert(ctx, hash, b".aux", StrIlk::FileExt)?; + let res = pool.lookup_str_insert(ctx, hash, b".aux", HashExtra::FileExt)?; ctx.s_aux_extension = hash.text(res.loc); - let res = pool.lookup_str_insert(ctx, hash, b"\\citation", StrIlk::AuxCommand)?; - hash.set_ilk_info(res.loc, 2); - let res = pool.lookup_str_insert(ctx, hash, b"\\bibdata", StrIlk::AuxCommand)?; - hash.set_ilk_info(res.loc, 0); - let res = pool.lookup_str_insert(ctx, hash, b"\\bibstyle", StrIlk::AuxCommand)?; - hash.set_ilk_info(res.loc, 1); - let res = pool.lookup_str_insert(ctx, hash, b"\\@input", StrIlk::AuxCommand)?; - hash.set_ilk_info(res.loc, 3); - - let res = pool.lookup_str_insert(ctx, hash, b"entry", StrIlk::BstCommand)?; - hash.set_ilk_info(res.loc, 0); - let res = pool.lookup_str_insert(ctx, hash, b"execute", StrIlk::BstCommand)?; - hash.set_ilk_info(res.loc, 1); - let res = pool.lookup_str_insert(ctx, hash, b"function", StrIlk::BstCommand)?; - hash.set_ilk_info(res.loc, 2); - let res = pool.lookup_str_insert(ctx, hash, b"integers", StrIlk::BstCommand)?; - hash.set_ilk_info(res.loc, 3); - let res = pool.lookup_str_insert(ctx, hash, b"iterate", StrIlk::BstCommand)?; - hash.set_ilk_info(res.loc, 4); - let res = pool.lookup_str_insert(ctx, hash, b"macro", StrIlk::BstCommand)?; - hash.set_ilk_info(res.loc, 5); - let res = pool.lookup_str_insert(ctx, hash, b"read", StrIlk::BstCommand)?; - hash.set_ilk_info(res.loc, 6); - let res = pool.lookup_str_insert(ctx, hash, b"reverse", StrIlk::BstCommand)?; - hash.set_ilk_info(res.loc, 7); - let res = pool.lookup_str_insert(ctx, hash, b"sort", StrIlk::BstCommand)?; - hash.set_ilk_info(res.loc, 8); - let res = pool.lookup_str_insert(ctx, hash, b"strings", StrIlk::BstCommand)?; - hash.set_ilk_info(res.loc, 9); - - let res = pool.lookup_str_insert(ctx, hash, b"comment", StrIlk::BibCommand)?; - hash.set_ilk_info(res.loc, 0); - let res = pool.lookup_str_insert(ctx, hash, b"preamble", StrIlk::BibCommand)?; - hash.set_ilk_info(res.loc, 1); - let res = pool.lookup_str_insert(ctx, hash, b"string", StrIlk::BibCommand)?; - hash.set_ilk_info(res.loc, 2); + pool.lookup_str_insert(ctx, hash, b"\\bibdata", HashExtra::AuxCommand(0))?; + pool.lookup_str_insert(ctx, hash, b"\\bibstyle", HashExtra::AuxCommand(1))?; + pool.lookup_str_insert(ctx, hash, b"\\citation", HashExtra::AuxCommand(2))?; + pool.lookup_str_insert(ctx, hash, b"\\@input", HashExtra::AuxCommand(3))?; + + pool.lookup_str_insert(ctx, hash, b"entry", HashExtra::BstCommand(0))?; + pool.lookup_str_insert(ctx, hash, b"execute", HashExtra::BstCommand(1))?; + pool.lookup_str_insert(ctx, hash, b"function", HashExtra::BstCommand(2))?; + pool.lookup_str_insert(ctx, hash, b"integers", HashExtra::BstCommand(3))?; + pool.lookup_str_insert(ctx, hash, b"iterate", HashExtra::BstCommand(4))?; + pool.lookup_str_insert(ctx, hash, b"macro", HashExtra::BstCommand(5))?; + pool.lookup_str_insert(ctx, hash, b"read", HashExtra::BstCommand(6))?; + pool.lookup_str_insert(ctx, hash, b"reverse", HashExtra::BstCommand(7))?; + pool.lookup_str_insert(ctx, hash, b"sort", HashExtra::BstCommand(8))?; + pool.lookup_str_insert(ctx, hash, b"strings", HashExtra::BstCommand(9))?; + + pool.lookup_str_insert(ctx, hash, b"comment", HashExtra::BibCommand(0))?; + pool.lookup_str_insert(ctx, hash, b"preamble", HashExtra::BibCommand(1))?; + pool.lookup_str_insert(ctx, hash, b"string", HashExtra::BibCommand(2))?; let mut build_in = |pds: &[ASCIICode], blt_in_num| { - let res = pool.lookup_str_insert(ctx, hash, pds, StrIlk::BstFn)?; + let res = pool.lookup_str_insert(ctx, hash, pds, HashExtra::BstFn(blt_in_num))?; hash.set_ty(res.loc, FnClass::Builtin); - hash.set_ilk_info(res.loc, blt_in_num); Ok(res.loc) }; @@ -352,62 +347,62 @@ pub(crate) fn pre_def_certain_strings( build_in(b"width$", 35)?; build_in(b"write$", 36)?; - let res = pool.lookup_str_insert(ctx, hash, b"", StrIlk::Text)?; + let res = pool.lookup_str_insert(ctx, hash, b"", HashExtra::Text(0))?; hash.set_ty(res.loc, FnClass::StrLit); ctx.s_null = hash.text(res.loc); - let res = pool.lookup_str_insert(ctx, hash, b"default.type", StrIlk::Text)?; + let res = pool.lookup_str_insert(ctx, hash, b"default.type", HashExtra::Text(0))?; hash.set_ty(res.loc, FnClass::StrLit); ctx.s_default = hash.text(res.loc); ctx.b_default = skip_loc; - let res = pool.lookup_str_insert(ctx, hash, b"i", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 0); - let res = pool.lookup_str_insert(ctx, hash, b"j", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 1); - let res = pool.lookup_str_insert(ctx, hash, b"oe", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 2); - let res = pool.lookup_str_insert(ctx, hash, b"OE", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 3); - let res = pool.lookup_str_insert(ctx, hash, b"ae", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 4); - let res = pool.lookup_str_insert(ctx, hash, b"AE", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 5); - let res = pool.lookup_str_insert(ctx, hash, b"aa", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 6); - let res = pool.lookup_str_insert(ctx, hash, b"AA", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 7); - let res = pool.lookup_str_insert(ctx, hash, b"o", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 8); - let res = pool.lookup_str_insert(ctx, hash, b"O", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 9); - let res = pool.lookup_str_insert(ctx, hash, b"l", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 10); - let res = pool.lookup_str_insert(ctx, hash, b"L", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 11); - let res = pool.lookup_str_insert(ctx, hash, b"ss", StrIlk::ControlSeq)?; - hash.set_ilk_info(res.loc, 12); - - let res = pool.lookup_str_insert(ctx, hash, b"crossref", StrIlk::BstFn)?; + pool.lookup_str_insert(ctx, hash, b"i", HashExtra::ControlSeq(0))?; + pool.lookup_str_insert(ctx, hash, b"j", HashExtra::ControlSeq(1))?; + pool.lookup_str_insert(ctx, hash, b"oe", HashExtra::ControlSeq(2))?; + pool.lookup_str_insert(ctx, hash, b"OE", HashExtra::ControlSeq(3))?; + pool.lookup_str_insert(ctx, hash, b"ae", HashExtra::ControlSeq(4))?; + pool.lookup_str_insert(ctx, hash, b"AE", HashExtra::ControlSeq(5))?; + pool.lookup_str_insert(ctx, hash, b"aa", HashExtra::ControlSeq(6))?; + pool.lookup_str_insert(ctx, hash, b"AA", HashExtra::ControlSeq(7))?; + pool.lookup_str_insert(ctx, hash, b"o", HashExtra::ControlSeq(8))?; + pool.lookup_str_insert(ctx, hash, b"O", HashExtra::ControlSeq(9))?; + pool.lookup_str_insert(ctx, hash, b"l", HashExtra::ControlSeq(10))?; + pool.lookup_str_insert(ctx, hash, b"L", HashExtra::ControlSeq(11))?; + pool.lookup_str_insert(ctx, hash, b"ss", HashExtra::ControlSeq(12))?; + let num_fields = other.num_fields(); + let res = + pool.lookup_str_insert(ctx, hash, b"crossref", HashExtra::BstFn(num_fields as i32))?; hash.set_ty(res.loc, FnClass::Field); - hash.set_ilk_info(res.loc, num_fields as i32); other.set_crossref_num(num_fields); other.set_num_fields(num_fields + 1); other.set_pre_defined_fields(num_fields + 1); - let res = pool.lookup_str_insert(ctx, hash, b"sort.key$", StrIlk::BstFn)?; + let num_ent_strs = entries.num_ent_strs(); + let res = pool.lookup_str_insert( + ctx, + hash, + b"sort.key$", + HashExtra::BstFn(num_ent_strs as i32), + )?; hash.set_ty(res.loc, FnClass::StrEntryVar); - hash.set_ilk_info(res.loc, entries.num_ent_strs() as i32); - entries.set_sort_key_num(entries.num_ent_strs()); - entries.set_num_ent_strs(entries.num_ent_strs() + 1); + entries.set_sort_key_num(num_ent_strs); + entries.set_num_ent_strs(num_ent_strs + 1); - let res = pool.lookup_str_insert(ctx, hash, b"entry.max$", StrIlk::BstFn)?; + let res = pool.lookup_str_insert( + ctx, + hash, + b"entry.max$", + HashExtra::BstFn(ENT_STR_SIZE as i32), + )?; hash.set_ty(res.loc, FnClass::IntGlblVar); - hash.set_ilk_info(res.loc, ENT_STR_SIZE as i32); - let res = pool.lookup_str_insert(ctx, hash, b"global.max$", StrIlk::BstFn)?; + let res = pool.lookup_str_insert( + ctx, + hash, + b"global.max$", + HashExtra::BstFn(GLOB_STR_SIZE as i32), + )?; hash.set_ty(res.loc, FnClass::IntGlblVar); - hash.set_ilk_info(res.loc, GLOB_STR_SIZE as i32); Ok(()) } diff --git a/crates/engine_bibtex/src/scan.rs b/crates/engine_bibtex/src/scan.rs index 6fd939a1b..dd1307fb8 100644 --- a/crates/engine_bibtex/src/scan.rs +++ b/crates/engine_bibtex/src/scan.rs @@ -5,7 +5,7 @@ use crate::{ cite::{add_database_cite, CiteInfo}, exec::ExecCtx, hash, - hash::{FnClass, HashData}, + hash::{FnClass, HashData, HashExtra}, log::{ bib_cmd_confusion, bib_err_print, bib_id_print, bib_unbalanced_braces_print, bib_warn_print, braces_unbalanced_complaint, bst_err_print_and_look_for_blank_line, @@ -199,11 +199,11 @@ fn handle_char( let res = { let str = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(ctx, hash, str, StrIlk::Integer)?; + let res = + pool.lookup_str_insert(ctx, hash, str, HashExtra::Integer(token_value))?; if !res.exists { hash.set_ty(res.loc, FnClass::IntLit); - hash.set_ilk_info(res.loc, token_value); } Ok(res) }?; @@ -232,7 +232,7 @@ fn handle_char( let res = { let str = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(ctx, hash, str, StrIlk::Text)?; + let res = pool.lookup_str_insert(ctx, hash, str, HashExtra::Text(0))?; hash.set_ty(res.loc, FnClass::StrLit); Ok(res) }?; @@ -281,7 +281,7 @@ fn handle_char( let str = format!("'{}", ctx.impl_fn_num); let res = { - let res = pool.lookup_str_insert(ctx, hash, str.as_bytes(), StrIlk::BstFn)?; + let res = pool.lookup_str_insert(ctx, hash, str.as_bytes(), HashExtra::BstFn(0))?; if res.exists { ctx.write_logs("Already encountered implicit function"); @@ -365,7 +365,7 @@ pub(crate) fn scan_fn_def( single_function.push(HashData::end_of_def()); - hash.set_ilk_info(fn_hash_loc, other.wiz_func_len() as i32); + hash.node_mut(fn_hash_loc).extra = HashExtra::BstFn(other.wiz_func_len() as i32); for ptr in single_function { other.push_wiz_func(ptr); @@ -770,7 +770,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( let str = &buffers.buffer(BufTy::Ex)[ex_buf_xptr..buffers.offset(BufTy::Ex, 1)]; let res = { - let res = pool.lookup_str_insert(ctx, hash, str, StrIlk::Text)?; + let res = pool.lookup_str_insert(ctx, hash, str, HashExtra::Text(0))?; hash.set_ty(res.loc, FnClass::StrLit); @@ -780,7 +780,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( if at_bib_command { match command_num { 1 => bibs.add_preamble(hash.text(res.loc)), - 2 => hash.set_ilk_info(cur_macro_loc, hash.text(res.loc) as i32), + 2 => hash.node_mut(cur_macro_loc).extra = HashExtra::BibCommand(hash.text(res.loc)), _ => { // TODO: Replace command_num with an enum bib_cmd_confusion(ctx); @@ -821,7 +821,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( ); buffers.buffer_mut(BufTy::Out)[ex_buf_xptr..end].make_ascii_lowercase(); let str = &buffers.buffer(BufTy::Out)[ex_buf_xptr..end]; - let lc_res = pool.lookup_str_insert(ctx, hash, str, StrIlk::LcCite)?; + let lc_res = pool.lookup_str_insert(ctx, hash, str, HashExtra::LcCite(0))?; if let Some(cite_out) = cite_out { *cite_out = lc_res.loc; } @@ -834,7 +834,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( } else { let str = &buffers.buffer(BufTy::Ex)[ex_buf_xptr..buffers.offset(BufTy::Ex, 1)]; - let c_res = pool.lookup_str_insert(ctx, hash, str, StrIlk::Cite)?; + let c_res = pool.lookup_str_insert(ctx, hash, str, HashExtra::Cite(0))?; if c_res.exists { hash_cite_confusion(ctx); return Err(BibtexError::Fatal); From b1514c8bcbaf29802fd8f0cecaba68ad3d2b111a Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sun, 25 Feb 2024 19:01:52 -0800 Subject: [PATCH 12/23] Make ExecCtx deref --- crates/engine_bibtex/src/bst.rs | 335 +++++++++++-------------------- crates/engine_bibtex/src/exec.rs | 255 +++++++++++------------ crates/engine_bibtex/src/lib.rs | 2 +- crates/engine_bibtex/src/log.rs | 30 ++- 4 files changed, 256 insertions(+), 366 deletions(-) diff --git a/crates/engine_bibtex/src/bst.rs b/crates/engine_bibtex/src/bst.rs index d6f9321ee..f79e780c3 100644 --- a/crates/engine_bibtex/src/bst.rs +++ b/crates/engine_bibtex/src/bst.rs @@ -19,14 +19,10 @@ use crate::{ macro_rules! eat_bst_white { ($ctx:ident, $globals:ident, $name:literal) => { - if !eat_bst_white_space($ctx.glbl_ctx_mut(), $globals.buffers) { - eat_bst_print($ctx.glbl_ctx_mut()); - $ctx.glbl_ctx_mut().write_logs($name); - bst_err_print_and_look_for_blank_line( - $ctx.glbl_ctx_mut(), - $globals.buffers, - $globals.pool, - )?; + if !eat_bst_white_space($ctx, $globals.buffers) { + eat_bst_print($ctx); + $ctx.write_logs($name); + bst_err_print_and_look_for_blank_line($ctx, $globals.buffers, $globals.pool)?; return Ok(()); } }; @@ -35,25 +31,17 @@ macro_rules! eat_bst_white { macro_rules! bst_brace { ('{', $ctx:expr, $globals:ident, $name:literal) => { if $globals.buffers.at_offset(BufTy::Base, 2) != b'{' { - bst_left_brace_print($ctx.glbl_ctx_mut()); - $ctx.glbl_ctx_mut().write_logs($name); - bst_err_print_and_look_for_blank_line( - $ctx.glbl_ctx_mut(), - $globals.buffers, - $globals.pool, - )?; + bst_left_brace_print($ctx); + $ctx.write_logs($name); + bst_err_print_and_look_for_blank_line($ctx, $globals.buffers, $globals.pool)?; return Ok(()); } }; ('}', $ctx:expr, $globals:ident, $name:literal) => { if $globals.buffers.at_offset(BufTy::Base, 2) != b'}' { - bst_right_brace_print($ctx.glbl_ctx_mut()); - $ctx.glbl_ctx_mut().write_logs($name); - bst_err_print_and_look_for_blank_line( - $ctx.glbl_ctx_mut(), - $globals.buffers, - $globals.pool, - )?; + bst_right_brace_print($ctx); + $ctx.write_logs($name); + bst_err_print_and_look_for_blank_line($ctx, $globals.buffers, $globals.pool)?; return Ok(()); } }; @@ -65,13 +53,9 @@ macro_rules! bst_ident { match scan_res { ScanRes::WhitespaceAdjacent | ScanRes::SpecifiedCharAdjacent => (), _ => { - bst_id_print($ctx.glbl_ctx_mut(), $globals.buffers, scan_res)?; - $ctx.glbl_ctx_mut().write_logs($name); - bst_err_print_and_look_for_blank_line( - $ctx.glbl_ctx_mut(), - $globals.buffers, - $globals.pool, - )?; + bst_id_print($ctx, $globals.buffers, scan_res)?; + $ctx.write_logs($name); + bst_err_print_and_look_for_blank_line($ctx, $globals.buffers, $globals.pool)?; return Ok(()); } } @@ -82,13 +66,12 @@ fn bst_entry_command( ctx: &mut ExecCtx<'_, '_, '_>, globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { - if ctx.glbl_ctx().entry_seen { - ctx.glbl_ctx_mut() - .write_logs("Illegal, another entry command"); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + if ctx.entry_seen { + ctx.write_logs("Illegal, another entry command"); + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } - ctx.glbl_ctx_mut().entry_seen = true; + ctx.entry_seen = true; eat_bst_white!(ctx, globals, "entry"); bst_brace!('{', ctx, globals, "entry"); @@ -104,19 +87,13 @@ fn bst_entry_command( bst_fn.make_ascii_lowercase(); let res = globals.pool.lookup_str_insert( - ctx.glbl_ctx_mut(), + ctx, globals.hash, bst_fn, HashExtra::BstFn(globals.other.num_fields() as i32), )?; if res.exists { - already_seen_function_print( - ctx.glbl_ctx_mut(), - globals.buffers, - globals.pool, - globals.hash, - res.loc, - )?; + already_seen_function_print(ctx, globals.buffers, globals.pool, globals.hash, res.loc)?; return Ok(()); } @@ -132,9 +109,8 @@ fn bst_entry_command( eat_bst_white!(ctx, globals, "entry"); if globals.other.num_fields() == globals.other.pre_defined_fields() { - ctx.glbl_ctx_mut() - .write_logs("Warning--I didn't find any fields"); - bst_warn_print(ctx.glbl_ctx_mut(), globals.pool)?; + ctx.write_logs("Warning--I didn't find any fields"); + bst_warn_print(ctx, globals.pool)?; } bst_brace!('{', ctx, globals, "entry"); @@ -151,19 +127,13 @@ fn bst_entry_command( bst_fn.make_ascii_lowercase(); let res = globals.pool.lookup_str_insert( - ctx.glbl_ctx_mut(), + ctx, globals.hash, bst_fn, HashExtra::BstFn(globals.entries.num_ent_ints() as i32), )?; if res.exists { - already_seen_function_print( - ctx.glbl_ctx_mut(), - globals.buffers, - globals.pool, - globals.hash, - res.loc, - )?; + already_seen_function_print(ctx, globals.buffers, globals.pool, globals.hash, res.loc)?; return Ok(()); } @@ -193,19 +163,13 @@ fn bst_entry_command( bst_fn.make_ascii_lowercase(); let res = globals.pool.lookup_str_insert( - ctx.glbl_ctx_mut(), + ctx, globals.hash, bst_fn, HashExtra::BstFn(globals.entries.num_ent_strs() as i32), )?; if res.exists { - already_seen_function_print( - ctx.glbl_ctx_mut(), - globals.buffers, - globals.pool, - globals.hash, - res.loc, - )?; + already_seen_function_print(ctx, globals.buffers, globals.pool, globals.hash, res.loc)?; return Ok(()); } @@ -227,10 +191,9 @@ fn bst_execute_command( ctx: &mut ExecCtx<'_, '_, '_>, globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { - if !ctx.glbl_ctx().read_seen { - ctx.glbl_ctx_mut() - .write_logs("Illegal, execute command before read command"); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + if !ctx.read_seen { + ctx.write_logs("Illegal, execute command before read command"); + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } eat_bst_white!(ctx, globals, "execute"); @@ -243,7 +206,7 @@ fn bst_execute_command( let mut fn_loc = 0; if bad_argument_token( - ctx.glbl_ctx_mut(), + ctx, Some(&mut fn_loc), globals.buffers, globals.pool, @@ -286,25 +249,16 @@ fn bst_function_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = globals.pool.lookup_str_insert( - ctx.glbl_ctx_mut(), - globals.hash, - bst_fn, - HashExtra::BstFn(0), - )?; + let res = globals + .pool + .lookup_str_insert(ctx, globals.hash, bst_fn, HashExtra::BstFn(0))?; if res.exists { - already_seen_function_print( - ctx.glbl_ctx_mut(), - globals.buffers, - globals.pool, - globals.hash, - res.loc, - )?; + already_seen_function_print(ctx, globals.buffers, globals.pool, globals.hash, res.loc)?; return Ok(()); } globals.hash.set_ty(res.loc, FnClass::Wizard); - if globals.hash.text(res.loc) == ctx.glbl_ctx().s_default { + if globals.hash.text(res.loc) == ctx.s_default { ctx._default = res.loc; } @@ -319,7 +273,7 @@ fn bst_function_command( .buffers .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); scan_fn_def( - ctx.glbl_ctx_mut(), + ctx, globals.buffers, globals.hash, globals.pool, @@ -348,20 +302,11 @@ fn bst_integers_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = globals.pool.lookup_str_insert( - ctx.glbl_ctx_mut(), - globals.hash, - bst_fn, - HashExtra::BstFn(0), - )?; + let res = globals + .pool + .lookup_str_insert(ctx, globals.hash, bst_fn, HashExtra::BstFn(0))?; if res.exists { - already_seen_function_print( - ctx.glbl_ctx_mut(), - globals.buffers, - globals.pool, - globals.hash, - res.loc, - )?; + already_seen_function_print(ctx, globals.buffers, globals.pool, globals.hash, res.loc)?; return Ok(()); } @@ -380,10 +325,9 @@ fn bst_iterate_command( ctx: &mut ExecCtx<'_, '_, '_>, globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { - if !ctx.glbl_ctx().read_seen { - ctx.glbl_ctx_mut() - .write_logs("Illegal, iterate command before read command"); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + if !ctx.read_seen { + ctx.write_logs("Illegal, iterate command before read command"); + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } @@ -397,7 +341,7 @@ fn bst_iterate_command( let mut fn_loc = 0; if bad_argument_token( - ctx.glbl_ctx_mut(), + ctx, Some(&mut fn_loc), globals.buffers, globals.pool, @@ -431,10 +375,9 @@ fn bst_macro_command( ctx: &mut ExecCtx<'_, '_, '_>, globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { - if ctx.glbl_ctx().read_seen { - ctx.glbl_ctx_mut() - .write_logs("Illegal, macro command after read command"); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + if ctx.read_seen { + ctx.write_logs("Illegal, macro command after read command"); + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } @@ -450,17 +393,13 @@ fn bst_macro_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = globals.pool.lookup_str_insert( - ctx.glbl_ctx_mut(), - globals.hash, - bst_fn, - HashExtra::Macro(0), - )?; + let res = globals + .pool + .lookup_str_insert(ctx, globals.hash, bst_fn, HashExtra::Macro(0))?; if res.exists { - print_a_token(ctx.glbl_ctx_mut(), globals.buffers); - ctx.glbl_ctx_mut() - .write_logs(" is already defined as a macro"); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + print_a_token(ctx, globals.buffers); + ctx.write_logs(" is already defined as a macro"); + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } // This is always unused if the macro is successfully defined, but appears to be a fallback for invalid macros. @@ -478,9 +417,8 @@ fn bst_macro_command( .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); eat_bst_white!(ctx, globals, "macro"); if globals.buffers.at_offset(BufTy::Base, 2) != b'"' { - ctx.glbl_ctx_mut() - .write_logs("A macro definition must be \"-delimited"); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + ctx.write_logs("A macro definition must be \"-delimited"); + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } globals @@ -488,20 +426,16 @@ fn bst_macro_command( .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); let init = globals.buffers.init(BufTy::Base); if !Scan::new().chars(&[b'"']).scan_till(globals.buffers, init) { - ctx.glbl_ctx_mut() - .write_logs("There's no `\"' to end macro definition"); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + ctx.write_logs("There's no `\"' to end macro definition"); + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } let range = globals.buffers.offset(BufTy::Base, 1)..globals.buffers.offset(BufTy::Base, 2); let text = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; - let res2 = globals.pool.lookup_str_insert( - ctx.glbl_ctx_mut(), - globals.hash, - text, - HashExtra::Text(0), - )?; + let res2 = globals + .pool + .lookup_str_insert(ctx, globals.hash, text, HashExtra::Text(0))?; globals.hash.set_ty(res2.loc, FnClass::StrLit); globals.hash.node_mut(res.loc).extra = HashExtra::Macro(globals.hash.text(res2.loc)); @@ -521,18 +455,16 @@ fn bst_read_command( ctx: &mut ExecCtx<'_, '_, '_>, globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { - if ctx.glbl_ctx().read_seen { - ctx.glbl_ctx_mut() - .write_logs("Illegal, another read command"); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + if ctx.read_seen { + ctx.write_logs("Illegal, another read command"); + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } - ctx.glbl_ctx_mut().read_seen = true; + ctx.read_seen = true; - if !ctx.glbl_ctx().entry_seen { - ctx.glbl_ctx_mut() - .write_logs("Illegal, read command before entry command"); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + if !ctx.entry_seen { + ctx.write_logs("Illegal, read command before entry command"); + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } @@ -561,7 +493,7 @@ fn bst_read_command( } globals.cites.set_old_num_cites(globals.cites.num_cites()); - if ctx.glbl_ctx().all_entries { + if ctx.all_entries { for idx in 0..globals.cites.old_num_cites() { globals.cites.set_info(idx, globals.cites.get_cite(idx)); globals.cites.set_exists(idx, false); @@ -572,16 +504,14 @@ fn bst_read_command( globals.cites.set_all_marker(0); } - ctx.glbl_ctx_mut().read_performed = true; + ctx.read_performed = true; while globals.bibs.len() != 0 { - if ctx.glbl_ctx().config.verbose { - ctx.glbl_ctx_mut() - .write_logs(&format!("Database file #{}: ", globals.bibs.len())); - print_bib_name(ctx.glbl_ctx, globals.pool, globals.bibs.top_file().name)?; + if ctx.config.verbose { + ctx.write_logs(&format!("Database file #{}: ", globals.bibs.len())); + print_bib_name(ctx, globals.pool, globals.bibs.top_file().name)?; } else { - ctx.glbl_ctx_mut() - .write_log_file(&format!("Database file #{}: ", globals.bibs.len())); - log_pr_bib_name(ctx.glbl_ctx, globals.bibs, globals.pool)?; + ctx.write_log_file(&format!("Database file #{}: ", globals.bibs.len())); + log_pr_bib_name(ctx, globals.bibs, globals.pool)?; } globals @@ -590,18 +520,18 @@ fn bst_read_command( let mut cur_macro_loc = 0; let mut field_name_loc = 0; - while !globals.bibs.top_file_mut().file.eof(ctx.glbl_ctx.engine) { + while !globals.bibs.top_file_mut().file.eof(ctx.engine) { get_bib_command_or_entry_and_process( - ctx.glbl_ctx_mut(), + ctx, globals, &mut cur_macro_loc, &mut field_name_loc, )?; } - globals.bibs.pop_file().file.close(ctx.glbl_ctx_mut())?; + globals.bibs.pop_file().file.close(ctx)?; } - ctx.glbl_ctx_mut().reading_completed = true; + ctx.reading_completed = true; globals.cites.set_num_cites(globals.cites.ptr()); let cites = match globals.cites.num_cites() { @@ -611,9 +541,8 @@ fn bst_read_command( if cites * globals.other.num_fields() + globals.other.crossref_num() >= globals.other.max_fields() { - ctx.glbl_ctx_mut() - .write_logs("field_info index is out of range"); - print_confusion(ctx.glbl_ctx); + ctx.write_logs("field_info index is out of range"); + print_confusion(ctx); return Err(BibtexError::Fatal); } @@ -659,11 +588,11 @@ fn bst_read_command( if !find.lc_found { if find.cite_found { - hash_cite_confusion(ctx.glbl_ctx_mut()); + hash_cite_confusion(ctx); return Err(BibtexError::Fatal); } nonexistent_cross_reference_error( - ctx.glbl_ctx_mut(), + ctx, globals.pool, globals.cites, globals.other, @@ -673,14 +602,14 @@ fn bst_read_command( globals.other.set_field(field_ptr, 0); } else { if find.cite_loc != globals.hash.ilk_info(find.lc_cite_loc) as CiteNumber { - hash_cite_confusion(ctx.glbl_ctx_mut()); + hash_cite_confusion(ctx); return Err(BibtexError::Fatal); } let cite_parent_ptr = globals.hash.ilk_info(find.cite_loc) as CiteNumber; if globals.cites.get_type(cite_parent_ptr) == 0 { nonexistent_cross_reference_error( - ctx.glbl_ctx_mut(), + ctx, globals.pool, globals.cites, globals.other, @@ -692,23 +621,20 @@ fn bst_read_command( let field_parent_ptr = cite_parent_ptr * globals.other.num_fields() + globals.other.crossref_num(); if globals.other.field(field_parent_ptr) != 0 { - ctx.glbl_ctx_mut() - .write_logs("Warning--you've nested cross references"); + ctx.write_logs("Warning--you've nested cross references"); bad_cross_reference_print( - ctx.glbl_ctx_mut(), + ctx, globals.pool, globals.cites, cite_ptr, globals.cites.get_cite(cite_parent_ptr), )?; - ctx.glbl_ctx_mut() - .write_logs("\", which also refers to something\n"); - ctx.glbl_ctx_mut().mark_warning(); + ctx.write_logs("\", which also refers to something\n"); + ctx.mark_warning(); } - if !ctx.glbl_ctx().all_entries + if !ctx.all_entries && cite_parent_ptr >= globals.cites.old_num_cites() - && globals.cites.info(cite_parent_ptr) - < ctx.glbl_ctx().config.min_crossrefs as usize + && globals.cites.info(cite_parent_ptr) < ctx.config.min_crossrefs as usize { globals.other.set_field(field_ptr, 0); } @@ -719,31 +645,24 @@ fn bst_read_command( for cite_ptr in 0..globals.cites.num_cites() { if globals.cites.get_type(cite_ptr) == 0 { - print_missing_entry( - ctx.glbl_ctx_mut(), - globals.pool, - globals.cites.get_cite(cite_ptr), - )?; - } else if ctx.glbl_ctx().all_entries + print_missing_entry(ctx, globals.pool, globals.cites.get_cite(cite_ptr))?; + } else if ctx.all_entries || cite_ptr < globals.cites.old_num_cites() - || globals.cites.info(cite_ptr) >= ctx.glbl_ctx().config.min_crossrefs as usize + || globals.cites.info(cite_ptr) >= ctx.config.min_crossrefs as usize { - if cite_ptr > ctx.glbl_ctx().cite_xptr { - if (ctx.glbl_ctx().cite_xptr + 1) * globals.other.num_fields() - > globals.other.max_fields() - { - ctx.glbl_ctx_mut() - .write_logs("field_info index is out of range"); - print_confusion(ctx.glbl_ctx); + if cite_ptr > ctx.cite_xptr { + if (ctx.cite_xptr + 1) * globals.other.num_fields() > globals.other.max_fields() { + ctx.write_logs("field_info index is out of range"); + print_confusion(ctx); return Err(BibtexError::Fatal); } globals .cites - .set_cite(ctx.glbl_ctx().cite_xptr, globals.cites.get_cite(cite_ptr)); + .set_cite(ctx.cite_xptr, globals.cites.get_cite(cite_ptr)); globals .cites - .set_type(ctx.glbl_ctx().cite_xptr, globals.cites.get_type(cite_ptr)); + .set_type(ctx.cite_xptr, globals.cites.get_type(cite_ptr)); let find = find_cite_locs_for_this_cite_key( globals.pool, @@ -751,21 +670,20 @@ fn bst_read_command( globals.cites.get_cite(cite_ptr), ); if !find.lc_found { - cite_key_disappeared_confusion(ctx.glbl_ctx_mut()); + cite_key_disappeared_confusion(ctx); return Err(BibtexError::Fatal); } if !find.cite_found || find.cite_loc != globals.hash.ilk_info(find.lc_cite_loc) as CiteNumber { - hash_cite_confusion(ctx.glbl_ctx_mut()); + hash_cite_confusion(ctx); return Err(BibtexError::Fatal); } - globals.hash.node_mut(find.cite_loc).extra = - HashExtra::Cite(ctx.glbl_ctx().cite_xptr); + globals.hash.node_mut(find.cite_loc).extra = HashExtra::Cite(ctx.cite_xptr); - let start = ctx.glbl_ctx().cite_xptr * globals.other.num_fields(); + let start = ctx.cite_xptr * globals.other.num_fields(); let end = start + globals.other.num_fields(); let tmp = cite_ptr * globals.other.num_fields(); @@ -775,16 +693,16 @@ fn bst_read_command( .set_field(idx, globals.other.field(tmp + idx - start)); } } - ctx.glbl_ctx_mut().cite_xptr += 1; + ctx.cite_xptr += 1; } } - globals.cites.set_num_cites(ctx.glbl_ctx().cite_xptr); + globals.cites.set_num_cites(ctx.cite_xptr); - if ctx.glbl_ctx().all_entries { + if ctx.all_entries { for idx in globals.cites.all_marker()..globals.cites.old_num_cites() { if !globals.cites.exists(idx) { - print_missing_entry(ctx.glbl_ctx_mut(), globals.pool, globals.cites.info(idx))?; + print_missing_entry(ctx, globals.pool, globals.cites.info(idx))?; } } } @@ -813,10 +731,9 @@ fn bst_reverse_command( ctx: &mut ExecCtx<'_, '_, '_>, globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { - if !ctx.glbl_ctx().read_seen { - ctx.glbl_ctx_mut() - .write_logs("Illegal, reverse command before read command"); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + if !ctx.read_seen { + ctx.write_logs("Illegal, reverse command before read command"); + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } @@ -830,7 +747,7 @@ fn bst_reverse_command( let mut fn_loc = 0; if bad_argument_token( - ctx.glbl_ctx_mut(), + ctx, Some(&mut fn_loc), globals.buffers, globals.pool, @@ -863,10 +780,9 @@ fn bst_sort_command( ctx: &mut ExecCtx<'_, '_, '_>, globals: &mut GlobalItems<'_>, ) -> Result<(), BibtexError> { - if !ctx.glbl_ctx().read_seen { - ctx.glbl_ctx_mut() - .write_logs("Illegal, sort command before read command"); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + if !ctx.read_seen { + ctx.write_logs("Illegal, sort command before read command"); + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } @@ -898,20 +814,14 @@ fn bst_strings_command( bst_fn.make_ascii_lowercase(); let res = globals.pool.lookup_str_insert( - ctx.glbl_ctx_mut(), + ctx, globals.hash, bst_fn, HashExtra::BstFn(globals.globals.num_glb_strs()), )?; if res.exists { - already_seen_function_print( - ctx.glbl_ctx_mut(), - globals.buffers, - globals.pool, - globals.hash, - res.loc, - )?; + already_seen_function_print(ctx, globals.buffers, globals.pool, globals.hash, res.loc)?; return Ok(()); } @@ -977,11 +887,11 @@ pub(crate) fn get_bst_command_and_process( .not_class(LexClass::Alpha) .scan_till_nonempty(globals.buffers, init) { - ctx.glbl_ctx_mut().write_logs(&format!( + ctx.write_logs(&format!( "\"{}\" can't start a style-file command", globals.buffers.at_offset(BufTy::Base, 2) as char, )); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } @@ -993,10 +903,9 @@ pub(crate) fn get_bst_command_and_process( .pool .lookup_str(globals.hash, bst_cmd, StrIlk::BstCommand); if !res.exists { - print_a_token(ctx.glbl_ctx_mut(), globals.buffers); - ctx.glbl_ctx_mut() - .write_logs(" is an illegal style-file command"); - bst_err_print_and_look_for_blank_line(ctx.glbl_ctx_mut(), globals.buffers, globals.pool)?; + print_a_token(ctx, globals.buffers); + ctx.write_logs(" is an illegal style-file command"); + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } @@ -1012,8 +921,8 @@ pub(crate) fn get_bst_command_and_process( 8 => bst_sort_command(ctx, globals), 9 => bst_strings_command(ctx, globals), _ => { - ctx.glbl_ctx_mut().write_logs("Unknown style-file command"); - print_confusion(ctx.glbl_ctx); + ctx.write_logs("Unknown style-file command"); + print_confusion(ctx); Err(BibtexError::Fatal) } } diff --git a/crates/engine_bibtex/src/exec.rs b/crates/engine_bibtex/src/exec.rs index 99bad2580..bc133e6a1 100644 --- a/crates/engine_bibtex/src/exec.rs +++ b/crates/engine_bibtex/src/exec.rs @@ -20,7 +20,7 @@ use crate::{ ASCIICode, Bibtex, BibtexError, BufPointer, GlobalItems, HashPointer, PoolPointer, StrIlk, StrNumber, }; -use std::ops::Index; +use std::ops::{Deref, DerefMut, Index}; #[derive(Copy, Clone, PartialEq, Eq)] pub(crate) enum StkType { @@ -53,7 +53,7 @@ impl ExecVal { } pub(crate) struct ExecCtx<'a, 'bib, 'cbs> { - pub glbl_ctx: &'a mut Bibtex<'bib, 'cbs>, + glbl_ctx: &'a mut Bibtex<'bib, 'cbs>, pub _default: HashPointer, pub(crate) lit_stack: Vec, pub mess_with_entries: bool, @@ -85,8 +85,8 @@ impl<'a, 'bib, 'cbs> ExecCtx<'a, 'bib, 'cbs> { if let ExecVal::String(str) = pop { if str >= self.bib_str_ptr { if str != pool.str_ptr() - 1 { - self.glbl_ctx.write_logs("Nontop top of string stack"); - print_confusion(self.glbl_ctx); + self.write_logs("Nontop top of string stack"); + print_confusion(self); return Err(BibtexError::Fatal); } pool.set_str_ptr(pool.str_ptr() - 1); @@ -95,19 +95,24 @@ impl<'a, 'bib, 'cbs> ExecCtx<'a, 'bib, 'cbs> { } Ok(pop) } else { - self.glbl_ctx - .write_logs("You can't pop an empty literal stack"); + self.write_logs("You can't pop an empty literal stack"); bst_ex_warn_print(self, pool, cites)?; Ok(ExecVal::Illegal) } } +} + +impl<'bib, 'cbs> Deref for ExecCtx<'_, 'bib, 'cbs> { + type Target = Bibtex<'bib, 'cbs>; - pub(crate) fn glbl_ctx(&self) -> &Bibtex<'bib, 'cbs> { - &*self.glbl_ctx + fn deref(&self) -> &Self::Target { + &self.glbl_ctx } +} - pub(crate) fn glbl_ctx_mut(&mut self) -> &mut Bibtex<'bib, 'cbs> { - &mut *self.glbl_ctx +impl DerefMut for ExecCtx<'_, '_, '_> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.glbl_ctx } } @@ -183,14 +188,14 @@ pub(crate) fn print_wrong_stk_lit( match val { ExecVal::Illegal => Ok(()), _ => { - print_stk_lit(ctx.glbl_ctx, val, pool, hash)?; + print_stk_lit(ctx, val, pool, hash)?; match typ2 { - StkType::Integer => ctx.glbl_ctx_mut().write_logs(", not an integer,"), - StkType::String => ctx.glbl_ctx_mut().write_logs(", not a string,"), - StkType::Function => ctx.glbl_ctx_mut().write_logs(", not a function,"), + StkType::Integer => ctx.write_logs(", not an integer,"), + StkType::String => ctx.write_logs(", not a string,"), + StkType::Function => ctx.write_logs(", not a function,"), StkType::Missing | StkType::Illegal => { - illegl_literal_confusion(ctx.glbl_ctx); + illegl_literal_confusion(ctx); return Err(BibtexError::Fatal); } }; @@ -206,13 +211,13 @@ pub(crate) fn bst_ex_warn_print( cites: &CiteInfo, ) -> Result<(), BibtexError> { if ctx.mess_with_entries { - ctx.glbl_ctx_mut().write_logs(" for entry "); - print_a_pool_str(ctx.glbl_ctx_mut(), cites.get_cite(cites.ptr()), pool)?; + ctx.write_logs(" for entry "); + print_a_pool_str(ctx, cites.get_cite(cites.ptr()), pool)?; } - ctx.glbl_ctx_mut().write_logs("\nwhile executing-"); - bst_ln_num_print(ctx.glbl_ctx_mut(), pool)?; - ctx.glbl_ctx_mut().mark_error(); + ctx.write_logs("\nwhile executing-"); + bst_ln_num_print(ctx, pool)?; + ctx.mark_error(); Ok(()) } @@ -250,10 +255,10 @@ fn pop_top_and_print( ) -> Result<(), BibtexError> { ctx.pop_stack(pool, cites).and_then(|val| { if let ExecVal::Illegal = val { - ctx.glbl_ctx_mut().write_logs("Empty literal\n"); + ctx.write_logs("Empty literal\n"); Ok(()) } else { - print_lit(ctx.glbl_ctx, pool, hash, val) + print_lit(ctx, pool, hash, val) } }) } @@ -620,15 +625,14 @@ pub(crate) fn check_command_execution( ) -> Result<(), BibtexError> { if !ctx.lit_stack.is_empty() { let msg = format!("ptr={}, stack=\n", ctx.lit_stack.len()); - ctx.glbl_ctx_mut().write_logs(&msg); + ctx.write_logs(&msg); pop_whole_stack(ctx, pool, hash, cites)?; - ctx.glbl_ctx_mut() - .write_logs("---the literal stack isn't empty"); + ctx.write_logs("---the literal stack isn't empty"); bst_ex_warn_print(ctx, pool, cites)?; } if ctx.bib_str_ptr != pool.str_ptr() { - ctx.glbl_ctx_mut().write_logs("Nonempty empty string stack"); - print_confusion(ctx.glbl_ctx); + ctx.write_logs("Nonempty empty string stack"); + print_confusion(ctx); return Err(BibtexError::Fatal); } Ok(()) @@ -641,7 +645,7 @@ fn add_pool_buf_and_push( ) -> Result<(), BibtexError> { buffers.set_offset(BufTy::Ex, 1, buffers.init(BufTy::Ex)); let str = &buffers.buffer(BufTy::Ex)[0..buffers.init(BufTy::Ex)]; - let val = ExecVal::String(pool.add_string_raw(ctx.glbl_ctx_mut(), str)?); + let val = ExecVal::String(pool.add_string_raw(ctx, str)?); ctx.push_stack(val); Ok(()) } @@ -667,20 +671,18 @@ fn interp_eq( } _ if pop1.ty() != pop2.ty() => { if pop1.ty() != StkType::Illegal && pop2.ty() != StkType::Illegal { - print_stk_lit(ctx.glbl_ctx, pop1, pool, hash)?; - ctx.glbl_ctx_mut().write_logs(", "); - print_stk_lit(ctx.glbl_ctx, pop2, pool, hash)?; - ctx.glbl_ctx_mut() - .write_logs("\n---they aren't the same literal types"); + print_stk_lit(ctx, pop1, pool, hash)?; + ctx.write_logs(", "); + print_stk_lit(ctx, pop2, pool, hash)?; + ctx.write_logs("\n---they aren't the same literal types"); bst_ex_warn_print(ctx, pool, cites)?; } ctx.push_stack(ExecVal::Integer(0)); } _ => { if pop1.ty() != StkType::Illegal { - print_stk_lit(ctx.glbl_ctx, pop1, pool, hash)?; - ctx.glbl_ctx_mut() - .write_logs(", not an integer or a string,"); + print_stk_lit(ctx, pop1, pool, hash)?; + ctx.write_logs(", not an integer or a string,"); bst_ex_warn_print(ctx, pool, cites)?; } ctx.push_stack(ExecVal::Integer(0)) @@ -802,12 +804,12 @@ fn interp_concat( (ExecVal::String(s1), ExecVal::String(s2)) => (s1, s2), (ExecVal::String(_), _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop2, StkType::String)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } (_, _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::String)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } }; @@ -832,7 +834,7 @@ fn interp_concat( let ptr = pool.str_start(s2 + 1); pool.copy_raw(s1, ptr); pool.set_pool_ptr(ptr + s1_len); - let new = pool.make_string(ctx.glbl_ctx_mut())?; + let new = pool.make_string(ctx)?; ctx.push_stack(ExecVal::String(new)); } } else if s1 >= ctx.bib_str_ptr { @@ -856,7 +858,7 @@ fn interp_concat( pool.copy_raw(s1, pool.str_start(s1 + 1) + s2_len - s1_len); pool.copy_raw(s2, pool.str_start(s1)); pool.set_pool_ptr(pool.str_start(s1) + s1_len + s2_len); - let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + let val = ExecVal::String(pool.make_string(ctx)?); ctx.push_stack(val); } } else { @@ -876,7 +878,7 @@ fn interp_concat( pool.copy_raw(s2, ptr); pool.copy_raw(s1, ptr + s2_len); pool.set_pool_ptr(ptr + s1_len + s2_len); - let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + let val = ExecVal::String(pool.make_string(ctx)?); ctx.push_stack(val); } } @@ -923,9 +925,8 @@ fn interp_gets( if let ExecVal::String(s2) = pop2 { let mut s = pool.get_str(s2); if s.len() > ENT_STR_SIZE { - bst_1print_string_size_exceeded(ctx.glbl_ctx_mut()); - ctx.glbl_ctx_mut() - .write_logs(&format!("{}, the entry", ENT_STR_SIZE)); + bst_1print_string_size_exceeded(ctx); + ctx.write_logs(&format!("{}, the entry", ENT_STR_SIZE)); bst_2print_string_size_exceeded(ctx, pool, cites)?; s = &s[..ENT_STR_SIZE]; } @@ -953,9 +954,8 @@ fn interp_gets( globals.set_str_ptr(str_glb_ptr, 0); let mut s = pool.get_str(s2); if s.len() > GLOB_STR_SIZE { - bst_1print_string_size_exceeded(ctx.glbl_ctx_mut()); - ctx.glbl_ctx_mut() - .write_logs(&format!("{}, the global", GLOB_STR_SIZE)); + bst_1print_string_size_exceeded(ctx); + ctx.write_logs(&format!("{}, the global", GLOB_STR_SIZE)); bst_2print_string_size_exceeded(ctx, pool, cites)?; s = &s[..GLOB_STR_SIZE]; } @@ -966,10 +966,9 @@ fn interp_gets( } } _ => { - ctx.glbl_ctx_mut().write_logs("You can't assign to type "); - print_fn_class(ctx.glbl_ctx_mut(), hash, f1); - ctx.glbl_ctx_mut() - .write_logs(", a nonvariable function class"); + ctx.write_logs("You can't assign to type "); + print_fn_class(ctx, hash, f1); + ctx.write_logs(", a nonvariable function class"); bst_ex_warn_print(ctx, pool, cites)?; } } @@ -988,7 +987,7 @@ fn interp_add_period( ExecVal::String(s1) => s1, _ => { print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::String)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } }; @@ -996,7 +995,7 @@ fn interp_add_period( let str = pool.get_str(s1); if str.is_empty() { - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } @@ -1024,7 +1023,7 @@ fn interp_add_period( } } pool.append(b'.'); - let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + let val = ExecVal::String(pool.make_string(ctx)?); ctx.push_stack(val); } } @@ -1065,9 +1064,8 @@ fn interp_change_case( }; if conv_ty == ConvTy::Bad { - print_a_pool_str(ctx.glbl_ctx, s1, pool)?; - ctx.glbl_ctx_mut() - .write_logs(" is an illegal case-conversion string"); + print_a_pool_str(ctx, s1, pool)?; + ctx.write_logs(" is an illegal case-conversion string"); bst_ex_warn_print(ctx, pool, cites)?; } @@ -1182,16 +1180,16 @@ fn interp_change_case( idx += 1; } check_brace_level(ctx, pool, cites, s2, brace_level)?; - let val = ExecVal::String(pool.add_string_raw(ctx.glbl_ctx_mut(), &scratch)?); + let val = ExecVal::String(pool.add_string_raw(ctx, &scratch)?); ctx.push_stack(val); } (ExecVal::String(_), _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop2, StkType::String)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); } (_, _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::String)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); } } Ok(()) @@ -1208,9 +1206,9 @@ fn interp_chr_to_int( ExecVal::String(s1) => { let str = pool.get_str(s1); if str.len() != 1 { - ctx.glbl_ctx_mut().write_logs("\""); - print_a_pool_str(ctx.glbl_ctx, s1, pool)?; - ctx.glbl_ctx_mut().write_logs("\" isn't a single character"); + ctx.write_logs("\""); + print_a_pool_str(ctx, s1, pool)?; + ctx.write_logs("\" isn't a single character"); bst_ex_warn_print(ctx, pool, cites)?; ctx.push_stack(ExecVal::Integer(0)); } else { @@ -1261,7 +1259,7 @@ fn interp_dup( let ptr = pool.pool_ptr(); pool.copy_raw(s1, ptr); pool.set_pool_ptr(ptr + str_len); - let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + let val = ExecVal::String(pool.make_string(ctx)?); ctx.push_stack(val); } } @@ -1293,9 +1291,8 @@ fn interp_empty( ctx.push_stack(ExecVal::Integer(0)); } _ => { - print_stk_lit(ctx.glbl_ctx, pop1, pool, hash)?; - ctx.glbl_ctx_mut() - .write_logs(", not a string or missing field,"); + print_stk_lit(ctx, pop1, pool, hash)?; + ctx.write_logs(", not a string or missing field,"); bst_ex_warn_print(ctx, pool, cites)?; ctx.push_stack(ExecVal::Integer(0)); } @@ -1318,17 +1315,17 @@ fn interp_format_name( (ExecVal::String(s1), ExecVal::Integer(i2), ExecVal::String(s3)) => (s1, i2, s3), (ExecVal::String(_), ExecVal::Integer(_), _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop3, StkType::String)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } (ExecVal::String(_), _, _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop2, StkType::Integer)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } (_, _, _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::String)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } }; @@ -1352,13 +1349,12 @@ fn interp_format_name( if num_names < i2 { if i2 == 1 { - ctx.glbl_ctx_mut().write_logs("There is no name in \""); + ctx.write_logs("There is no name in \""); } else { - ctx.glbl_ctx_mut() - .write_logs(&format!("There aren't {} names in \"", i2)); + ctx.write_logs(&format!("There aren't {} names in \"", i2)); } - print_a_pool_str(ctx.glbl_ctx, s3, pool)?; - ctx.glbl_ctx_mut().write_logs("\""); + print_a_pool_str(ctx, s3, pool)?; + ctx.write_logs("\""); bst_ex_warn_print(ctx, pool, cites)?; } @@ -1369,9 +1365,9 @@ fn interp_format_name( } _ => { if buffers.at(BufTy::Ex, buffers.offset(BufTy::Ex, 1) - 1) == b',' { - ctx.glbl_ctx_mut().write_logs(&format!("Name {} in \"", i2)); - print_a_pool_str(ctx.glbl_ctx, s3, pool)?; - ctx.glbl_ctx_mut().write_logs("\" has a comma at the end"); + ctx.write_logs(&format!("Name {} in \"", i2)); + print_a_pool_str(ctx, s3, pool)?; + ctx.write_logs("\" has a comma at the end"); bst_ex_warn_print(ctx, pool, cites)?; buffers.set_offset(BufTy::Ex, 1, buffers.offset(BufTy::Ex, 1) - 1); } else { @@ -1405,10 +1401,9 @@ fn interp_format_name( buffers.set_at(BufTy::NameSep, num_tokens, b','); } Commas::Two(_, _) => { - ctx.glbl_ctx_mut() - .write_logs(&format!("Too many commas in name {} of \"", i2)); - print_a_pool_str(ctx.glbl_ctx, s3, pool)?; - ctx.glbl_ctx_mut().write_logs("\""); + ctx.write_logs(&format!("Too many commas in name {} of \"", i2)); + print_a_pool_str(ctx, s3, pool)?; + ctx.write_logs("\""); bst_ex_warn_print(ctx, pool, cites)?; } } @@ -1442,9 +1437,9 @@ fn interp_format_name( num_tokens += 1; } - ctx.glbl_ctx_mut().write_logs(&format!("Name {} of \"", i2)); - print_a_pool_str(ctx.glbl_ctx, s3, pool)?; - ctx.glbl_ctx_mut().write_logs("\" isn't brace balanced"); + ctx.write_logs(&format!("Name {} of \"", i2)); + print_a_pool_str(ctx, s3, pool)?; + ctx.write_logs("\" isn't brace balanced"); bst_ex_warn_print(ctx, pool, cites)?; xptr += 1; token_starting = false; @@ -1497,16 +1492,9 @@ fn interp_format_name( while von_start < last_end - 1 { name_ptr = buffers.name_tok(von_start); name_ptr2 = buffers.name_tok(von_start + 1); - if von_token_found( - ctx.glbl_ctx_mut(), - buffers, - hash, - pool, - &mut name_ptr, - name_ptr2, - )? { + if von_token_found(ctx, buffers, hash, pool, &mut name_ptr, name_ptr2)? { von_name_ends_and_last_name_starts_stuff( - ctx.glbl_ctx_mut(), + ctx, buffers, hash, pool, @@ -1541,7 +1529,7 @@ fn interp_format_name( first_start = jr_end; first_end = num_tokens; von_name_ends_and_last_name_starts_stuff( - ctx.glbl_ctx_mut(), + ctx, buffers, hash, pool, @@ -1558,7 +1546,7 @@ fn interp_format_name( first_start = jr_end; first_end = num_tokens; von_name_ends_and_last_name_starts_stuff( - ctx.glbl_ctx_mut(), + ctx, buffers, hash, pool, @@ -1605,23 +1593,22 @@ fn interp_int_to_chr( ExecVal::Integer(i1) => i1, _ => { print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::Integer)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } }; if !(0..=127).contains(&i1) { - ctx.glbl_ctx_mut() - .write_logs(&format!("{} isn't valid ASCII", i1)); + ctx.write_logs(&format!("{} isn't valid ASCII", i1)); bst_ex_warn_print(ctx, pool, cites)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); } else { if pool.pool_ptr() + 1 > pool.len() { pool.grow(); } pool.append(i1 as u8); - let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + let val = ExecVal::String(pool.make_string(ctx)?); ctx.push_stack(val); } Ok(()) @@ -1638,13 +1625,13 @@ fn interp_int_to_str( ExecVal::Integer(i1) => i1, _ => { print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::Integer)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } }; let scratch = i1.to_string(); - let val = ExecVal::String(pool.add_string_raw(ctx.glbl_ctx_mut(), scratch.as_bytes())?); + let val = ExecVal::String(pool.add_string_raw(ctx, scratch.as_bytes())?); ctx.push_stack(val); Ok(()) } @@ -1671,9 +1658,8 @@ fn interp_missing( ctx.push_stack(ExecVal::Integer(0)); } _ => { - print_stk_lit(ctx.glbl_ctx, pop1, pool, hash)?; - ctx.glbl_ctx_mut() - .write_logs(", not a string or missing field,"); + print_stk_lit(ctx, pop1, pool, hash)?; + ctx.write_logs(", not a string or missing field,"); bst_ex_warn_print(ctx, pool, cites)?; ctx.push_stack(ExecVal::Integer(0)); } @@ -1719,7 +1705,7 @@ fn interp_preamble( for s in bibs.preamble() { out.extend(pool.get_str(*s)); } - let s = pool.add_string_raw(ctx.glbl_ctx_mut(), &out)?; + let s = pool.add_string_raw(ctx, &out)?; ctx.push_stack(ExecVal::String(s)); Ok(()) } @@ -1735,7 +1721,7 @@ fn interp_purify( ExecVal::String(s1) => s1, _ => { print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::String)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } }; @@ -1810,14 +1796,14 @@ fn interp_purify( } scratch.truncate(write_idx); - let out = pool.add_string_raw(ctx.glbl_ctx_mut(), &scratch)?; + let out = pool.add_string_raw(ctx, &scratch)?; ctx.push_stack(ExecVal::String(out)); Ok(()) } fn interp_quote(ctx: &mut ExecCtx<'_, '_, '_>, pool: &mut StringPool) -> Result<(), BibtexError> { - let s = pool.add_string_raw(ctx.glbl_ctx_mut(), b"\"")?; + let s = pool.add_string_raw(ctx, b"\"")?; ctx.push_stack(ExecVal::String(s)); Ok(()) } @@ -1862,17 +1848,17 @@ fn interp_substr( (ExecVal::Integer(i1), ExecVal::Integer(i2), ExecVal::String(s3)) => (i1, i2, s3), (ExecVal::Integer(_), ExecVal::Integer(_), _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop3, StkType::String)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } (ExecVal::Integer(_), _, _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop2, StkType::Integer)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } (_, _, _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::Integer)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } }; @@ -1880,7 +1866,7 @@ fn interp_substr( let str = pool.get_str(s3); if len <= 0 || start == 0 || start.unsigned_abs() as usize > str.len() { - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } @@ -1907,7 +1893,7 @@ fn interp_substr( // TODO: Remove this intermediate allocation, currently can't pass a `&str` from a StringPool // to that StringPool. let new_str = Vec::from(&str[SLRange { start, len }]); - let out = pool.add_string_raw(ctx.glbl_ctx_mut(), &new_str)?; + let out = pool.add_string_raw(ctx, &new_str)?; ctx.push_stack(ExecVal::String(out)); Ok(()) @@ -1930,9 +1916,9 @@ fn interp_swap( let ptr = pool.pool_ptr(); pool.copy_raw(s1, ptr); pool.set_pool_ptr(ptr + s1_len); - let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + let val = ExecVal::String(pool.make_string(ctx)?); ctx.push_stack(val); - let val = ExecVal::String(pool.add_string_raw(ctx.glbl_ctx_mut(), &tmp)?); + let val = ExecVal::String(pool.add_string_raw(ctx, &tmp)?); ctx.push_stack(val); return Ok(()); } @@ -1959,7 +1945,7 @@ fn interp_text_len( ExecVal::String(s1) => s1, _ => { print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::String)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } }; @@ -2009,18 +1995,18 @@ fn interp_text_prefix( (ExecVal::Integer(i1), ExecVal::String(s2)) => (i1, s2), (ExecVal::Integer(_), _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop2, StkType::String)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } (_, _) => { print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::Integer)?; - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } }; if i1 <= 0 { - ctx.push_stack(ExecVal::String(ctx.glbl_ctx().s_null)); + ctx.push_stack(ExecVal::String(ctx.s_null)); return Ok(()); } @@ -2070,7 +2056,7 @@ fn interp_text_prefix( pool.append(b'}'); } - let val = ExecVal::String(pool.make_string(ctx.glbl_ctx_mut())?); + let val = ExecVal::String(pool.make_string(ctx)?); ctx.push_stack(val); Ok(()) } @@ -2088,7 +2074,7 @@ fn interp_ty( let ty = cites.get_type(cites.ptr()); let s = if ty == HashData::undefined() || ty == 0 { - ctx.glbl_ctx().s_null + ctx.s_null } else { hash.text(ty) }; @@ -2105,9 +2091,9 @@ fn interp_warning( let pop1 = ctx.pop_stack(pool, cites)?; match pop1 { ExecVal::String(_) => { - ctx.glbl_ctx_mut().write_logs("Warning--"); - print_lit(ctx.glbl_ctx, pool, hash, pop1)?; - ctx.glbl_ctx_mut().mark_warning(); + ctx.write_logs("Warning--"); + print_lit(ctx, pool, hash, pop1)?; + ctx.mark_warning(); } _ => print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::String)?, } @@ -2211,7 +2197,7 @@ fn interp_write( let pop1 = ctx.pop_stack(pool, cites)?; match pop1 { ExecVal::String(s1) => { - add_out_pool(ctx.glbl_ctx_mut(), buffers, pool, s1); + add_out_pool(ctx, buffers, pool, s1); } _ => { print_wrong_stk_lit(ctx, pool, hash, cites, pop1, StkType::String)?; @@ -2310,7 +2296,7 @@ pub(crate) fn execute_fn( 17 => interp_int_to_str(ctx, globals.pool, globals.hash, globals.cites), 18 => interp_missing(ctx, globals.pool, globals.hash, globals.cites), 19 => { - output_bbl_line(ctx.glbl_ctx_mut(), globals.buffers); + output_bbl_line(ctx, globals.buffers); Ok(()) } 20 => interp_num_names( @@ -2389,8 +2375,8 @@ pub(crate) fn execute_fn( globals.cites, ), _ => { - ctx.glbl_ctx_mut().write_logs("Unknown built-in function"); - print_confusion(ctx.glbl_ctx); + ctx.write_logs("Unknown built-in function"); + print_confusion(ctx); Err(BibtexError::Fatal) } }, @@ -2425,9 +2411,8 @@ pub(crate) fn execute_fn( let field_ptr = globals.cites.ptr() * globals.other.num_fields() + globals.hash.ilk_info(ex_fn_loc) as usize; if field_ptr >= globals.other.max_fields() { - ctx.glbl_ctx_mut() - .write_logs("field_info index is out of range"); - print_confusion(ctx.glbl_ctx); + ctx.write_logs("field_info index is out of range"); + print_confusion(ctx); return Err(BibtexError::Fatal); } @@ -2458,7 +2443,7 @@ pub(crate) fn execute_fn( let str_ent_ptr = globals.cites.ptr() * globals.entries.num_ent_strs() + globals.hash.ilk_info(ex_fn_loc) as usize; let str = globals.entries.strs(str_ent_ptr); - let val = ExecVal::String(globals.pool.add_string_raw(ctx.glbl_ctx_mut(), str)?); + let val = ExecVal::String(globals.pool.add_string_raw(ctx, str)?); ctx.push_stack(val); Ok(()) } @@ -2474,7 +2459,7 @@ pub(crate) fn execute_fn( ctx.push_stack(ExecVal::String(str_ptr)); } else { let str = globals.globals.str(str_glb_ptr); - let val = ExecVal::String(globals.pool.add_string_raw(ctx.glbl_ctx_mut(), str)?); + let val = ExecVal::String(globals.pool.add_string_raw(ctx, str)?); ctx.push_stack(val); } Ok(()) diff --git a/crates/engine_bibtex/src/lib.rs b/crates/engine_bibtex/src/lib.rs index d4f7920d6..2dcb70c88 100644 --- a/crates/engine_bibtex/src/lib.rs +++ b/crates/engine_bibtex/src/lib.rs @@ -498,7 +498,7 @@ pub(crate) fn inner_bibtex_main( let mut exec = ExecCtx::new(ctx); loop { - if !eat_bst_white_space(exec.glbl_ctx_mut(), globals.buffers) { + if !eat_bst_white_space(&mut exec, globals.buffers) { break; } get_bst_command_and_process(&mut exec, globals)?; diff --git a/crates/engine_bibtex/src/log.rs b/crates/engine_bibtex/src/log.rs index 6f07baffa..1f20252be 100644 --- a/crates/engine_bibtex/src/log.rs +++ b/crates/engine_bibtex/src/log.rs @@ -487,11 +487,11 @@ pub(crate) fn bst_mild_ex_warn_print( cites: &CiteInfo, ) -> Result<(), BibtexError> { if ctx.mess_with_entries { - ctx.glbl_ctx_mut().write_logs(" for entry "); - print_a_pool_str(ctx.glbl_ctx_mut(), cites.get_cite(cites.ptr()), pool)?; + ctx.write_logs(" for entry "); + print_a_pool_str(ctx, cites.get_cite(cites.ptr()), pool)?; } - ctx.glbl_ctx_mut().write_logs("\nwhile executing"); - bst_warn_print(ctx.glbl_ctx_mut(), pool) + ctx.write_logs("\nwhile executing"); + bst_warn_print(ctx, pool) } pub(crate) fn bst_cant_mess_with_entries_print( @@ -499,8 +499,7 @@ pub(crate) fn bst_cant_mess_with_entries_print( pool: &StringPool, cites: &CiteInfo, ) -> Result<(), BibtexError> { - ctx.glbl_ctx_mut() - .write_logs("You can't mess with entries here"); + ctx.write_logs("You can't mess with entries here"); bst_ex_warn_print(ctx, pool, cites) } @@ -513,10 +512,9 @@ pub(crate) fn bst_2print_string_size_exceeded( pool: &StringPool, cites: &CiteInfo, ) -> Result<(), BibtexError> { - ctx.glbl_ctx_mut().write_logs("-string-size,"); + ctx.write_logs("-string-size,"); bst_mild_ex_warn_print(ctx, pool, cites)?; - ctx.glbl_ctx_mut() - .write_logs("*Please notify the bibstyle designer*\n"); + ctx.write_logs("*Please notify the bibstyle designer*\n"); Ok(()) } @@ -526,10 +524,9 @@ pub(crate) fn braces_unbalanced_complaint( cites: &CiteInfo, pop_lit_var: StrNumber, ) -> Result<(), BibtexError> { - ctx.glbl_ctx_mut().write_logs("Warning--\""); - print_a_pool_str(ctx.glbl_ctx_mut(), pop_lit_var, pool)?; - ctx.glbl_ctx_mut() - .write_logs("\" isn't a brace-balanced string"); + ctx.write_logs("Warning--\""); + print_a_pool_str(ctx, pop_lit_var, pool)?; + ctx.write_logs("\" isn't a brace-balanced string"); bst_mild_ex_warn_print(ctx, pool, cites) } @@ -677,10 +674,9 @@ pub(crate) fn brace_lvl_one_letters_complaint( cites: &CiteInfo, str: StrNumber, ) -> Result<(), BibtexError> { - ctx.glbl_ctx_mut().write_logs("The format string \""); - print_a_pool_str(ctx.glbl_ctx_mut(), str, pool)?; - ctx.glbl_ctx_mut() - .write_logs("\" has an illegal brace-level-1 letter"); + ctx.write_logs("The format string \""); + print_a_pool_str(ctx, str, pool)?; + ctx.write_logs("\" has an illegal brace-level-1 letter"); bst_ex_warn_print(ctx, pool, cites)?; Ok(()) } From 1daf79bfd1a38c4fc1a031d00fdacce54cbc7aa9 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Mon, 26 Feb 2024 19:31:10 -0800 Subject: [PATCH 13/23] Minor dead-code cleanup --- crates/engine_bibtex/src/bst.rs | 2 +- crates/engine_bibtex/src/exec.rs | 28 ++++++++++++++-------------- crates/engine_bibtex/src/lib.rs | 31 +++---------------------------- 3 files changed, 18 insertions(+), 43 deletions(-) diff --git a/crates/engine_bibtex/src/bst.rs b/crates/engine_bibtex/src/bst.rs index f79e780c3..a9ba1ff6a 100644 --- a/crates/engine_bibtex/src/bst.rs +++ b/crates/engine_bibtex/src/bst.rs @@ -259,7 +259,7 @@ fn bst_function_command( globals.hash.set_ty(res.loc, FnClass::Wizard); if globals.hash.text(res.loc) == ctx.s_default { - ctx._default = res.loc; + ctx.default = res.loc; } eat_bst_white!(ctx, globals, "function"); diff --git a/crates/engine_bibtex/src/exec.rs b/crates/engine_bibtex/src/exec.rs index bc133e6a1..b5de19315 100644 --- a/crates/engine_bibtex/src/exec.rs +++ b/crates/engine_bibtex/src/exec.rs @@ -54,7 +54,7 @@ impl ExecVal { pub(crate) struct ExecCtx<'a, 'bib, 'cbs> { glbl_ctx: &'a mut Bibtex<'bib, 'cbs>, - pub _default: HashPointer, + pub default: HashPointer, pub(crate) lit_stack: Vec, pub mess_with_entries: bool, /// Pointer to the current top of the string pool, used to optimize certain string operations @@ -65,7 +65,7 @@ impl<'a, 'bib, 'cbs> ExecCtx<'a, 'bib, 'cbs> { pub(crate) fn new(glbl_ctx: &'a mut Bibtex<'bib, 'cbs>) -> ExecCtx<'a, 'bib, 'cbs> { ExecCtx { glbl_ctx, - _default: 0, + default: 0, lit_stack: Vec::new(), mess_with_entries: false, bib_str_ptr: 0, @@ -139,7 +139,7 @@ pub(crate) fn print_lit( ctx.write_logs("\n"); } ExecVal::Illegal => { - illegl_literal_confusion(ctx); + illegal_literal_confusion(ctx); return Err(BibtexError::Fatal); } } @@ -148,9 +148,9 @@ pub(crate) fn print_lit( pub(crate) fn print_stk_lit( ctx: &mut Bibtex<'_, '_>, - val: ExecVal, pool: &StringPool, hash: &HashData, + val: ExecVal, ) -> Result<(), BibtexError> { match val { ExecVal::Integer(val) => ctx.write_logs(&format!("{} is an integer literal", val)), @@ -170,7 +170,7 @@ pub(crate) fn print_stk_lit( ctx.write_logs("` is a missing field"); } ExecVal::Illegal => { - illegl_literal_confusion(ctx); + illegal_literal_confusion(ctx); return Err(BibtexError::Fatal); } } @@ -188,14 +188,14 @@ pub(crate) fn print_wrong_stk_lit( match val { ExecVal::Illegal => Ok(()), _ => { - print_stk_lit(ctx, val, pool, hash)?; + print_stk_lit(ctx, pool, hash, val)?; match typ2 { StkType::Integer => ctx.write_logs(", not an integer,"), StkType::String => ctx.write_logs(", not a string,"), StkType::Function => ctx.write_logs(", not a function,"), StkType::Missing | StkType::Illegal => { - illegl_literal_confusion(ctx); + illegal_literal_confusion(ctx); return Err(BibtexError::Fatal); } }; @@ -242,7 +242,7 @@ pub(crate) fn print_bst_name( Ok(()) } -pub fn illegl_literal_confusion(ctx: &mut Bibtex<'_, '_>) { +pub fn illegal_literal_confusion(ctx: &mut Bibtex<'_, '_>) { ctx.write_logs("Illegal literal type"); print_confusion(ctx); } @@ -671,9 +671,9 @@ fn interp_eq( } _ if pop1.ty() != pop2.ty() => { if pop1.ty() != StkType::Illegal && pop2.ty() != StkType::Illegal { - print_stk_lit(ctx, pop1, pool, hash)?; + print_stk_lit(ctx, pool, hash, pop1)?; ctx.write_logs(", "); - print_stk_lit(ctx, pop2, pool, hash)?; + print_stk_lit(ctx, pool, hash, pop2)?; ctx.write_logs("\n---they aren't the same literal types"); bst_ex_warn_print(ctx, pool, cites)?; } @@ -681,7 +681,7 @@ fn interp_eq( } _ => { if pop1.ty() != StkType::Illegal { - print_stk_lit(ctx, pop1, pool, hash)?; + print_stk_lit(ctx, pool, hash, pop1)?; ctx.write_logs(", not an integer or a string,"); bst_ex_warn_print(ctx, pool, cites)?; } @@ -1291,7 +1291,7 @@ fn interp_empty( ctx.push_stack(ExecVal::Integer(0)); } _ => { - print_stk_lit(ctx, pop1, pool, hash)?; + print_stk_lit(ctx, pool, hash, pop1)?; ctx.write_logs(", not a string or missing field,"); bst_ex_warn_print(ctx, pool, cites)?; ctx.push_stack(ExecVal::Integer(0)); @@ -1658,7 +1658,7 @@ fn interp_missing( ctx.push_stack(ExecVal::Integer(0)); } _ => { - print_stk_lit(ctx, pop1, pool, hash)?; + print_stk_lit(ctx, pool, hash, pop1)?; ctx.write_logs(", not a string or missing field,"); bst_ex_warn_print(ctx, pool, cites)?; ctx.push_stack(ExecVal::Integer(0)); @@ -2234,7 +2234,7 @@ pub(crate) fn execute_fn( bst_cant_mess_with_entries_print(ctx, globals.pool, globals.cites)?; Ok(()) } else if default == HashData::undefined() { - execute_fn(ctx, globals, ctx._default) + execute_fn(ctx, globals, ctx.default) } else if default != 0 { execute_fn(ctx, globals, default) } else { diff --git a/crates/engine_bibtex/src/lib.rs b/crates/engine_bibtex/src/lib.rs index 2dcb70c88..ee20a42c9 100644 --- a/crates/engine_bibtex/src/lib.rs +++ b/crates/engine_bibtex/src/lib.rs @@ -242,7 +242,7 @@ impl<'a, 'cbs> Bibtex<'a, 'cbs> { logs: Logs::default(), bst: None, bbl_file: None, - bbl_line_num: 0, + bbl_line_num: 1, impl_fn_num: 0, cite_xptr: 0, bib_seen: false, @@ -444,7 +444,8 @@ pub(crate) fn inner_bibtex_main( return Ok(History::FatalError); } - if initialize(ctx, globals, aux_file_name)? != 0 { + pre_def_certain_strings(ctx, globals)?; + if get_the_top_level_aux_file_name(ctx, globals, aux_file_name)? != 0 { return Ok(History::FatalError); } @@ -491,7 +492,6 @@ pub(crate) fn inner_bibtex_main( return Err(BibtexError::NoBst); } - ctx.bbl_line_num = 1; globals .buffers .set_offset(BufTy::Base, 2, globals.buffers.init(BufTy::Base)); @@ -571,31 +571,6 @@ pub(crate) fn get_the_top_level_aux_file_name( Ok(0) } -fn initialize( - ctx: &mut Bibtex<'_, '_>, - globals: &mut GlobalItems<'_>, - aux_file_name: &CStr, -) -> Result { - globals.pool.set_pool_ptr(0); - globals.pool.set_str_ptr(1); - globals.pool.set_start(globals.pool.str_ptr(), 0); - - ctx.bib_seen = false; - ctx.bst_seen = false; - ctx.citation_seen = false; - ctx.all_entries = false; - - ctx.entry_seen = false; - ctx.read_seen = false; - ctx.read_performed = false; - ctx.reading_completed = false; - ctx.impl_fn_num = 0; - globals.buffers.set_init(BufTy::Out, 0); - - pre_def_certain_strings(ctx, globals)?; - get_the_top_level_aux_file_name(ctx, globals, aux_file_name) -} - /// Does our resulting executable link correctly? #[test] fn linkage() {} From 199cf4387d3ea119ec361848d56b866ddf6ef754 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 27 Feb 2024 16:59:45 -0800 Subject: [PATCH 14/23] No longer use ilk_info - always use HashExtra, and make HashExtra data more type-strict --- crates/engine_bibtex/src/auxi.rs | 51 +++-- crates/engine_bibtex/src/bibs.rs | 79 ++++--- crates/engine_bibtex/src/bst.rs | 123 ++++++----- crates/engine_bibtex/src/exec.rs | 275 ++++++++++++----------- crates/engine_bibtex/src/global.rs | 6 +- crates/engine_bibtex/src/hash.rs | 115 +++++----- crates/engine_bibtex/src/log.rs | 29 ++- crates/engine_bibtex/src/pool.rs | 335 ++++++++++++++++++----------- crates/engine_bibtex/src/scan.rs | 193 +++++++++-------- tests/bibtex.rs | 5 + tests/bibtex/cites/control_seq.aux | 5 + tests/bibtex/cites/control_seq.bbl | 7 + tests/bibtex/cites/control_seq.bib | 4 + tests/bibtex/cites/control_seq.blg | 10 + 14 files changed, 725 insertions(+), 512 deletions(-) create mode 100644 tests/bibtex/cites/control_seq.aux create mode 100644 tests/bibtex/cites/control_seq.bbl create mode 100644 tests/bibtex/cites/control_seq.bib create mode 100644 tests/bibtex/cites/control_seq.blg diff --git a/crates/engine_bibtex/src/auxi.rs b/crates/engine_bibtex/src/auxi.rs index eb41d6db5..019233b63 100644 --- a/crates/engine_bibtex/src/auxi.rs +++ b/crates/engine_bibtex/src/auxi.rs @@ -22,6 +22,14 @@ use tectonic_bridge_core::FileFormat; const AUX_STACK_SIZE: usize = 20; +#[derive(Copy, Clone, Debug)] +pub(crate) enum AuxCommand { + Data, + Style, + Citation, + Input, +} + pub(crate) struct AuxData { aux: Vec, } @@ -270,18 +278,22 @@ fn aux_citation_command( let lc_res = pool.lookup_str_insert(ctx, hash, lc_cite, HashExtra::LcCite(0))?; if lc_res.exists { + let HashExtra::LcCite(cite_loc) = hash.node(lc_res.loc).extra else { + panic!("LcCite lookup didn't have LcCite extra"); + }; + let cite = &buffers.buffer(BufTy::Base) [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; let uc_res = pool.lookup_str(hash, cite, StrIlk::Cite); if !uc_res.exists { + let HashExtra::Cite(cite) = hash.node(cite_loc).extra else { + panic!("LcCite location didn't have a Cite extra"); + }; + ctx.write_logs("Case mismatch error between cite keys "); print_a_token(ctx, buffers); ctx.write_logs(" and "); - print_a_pool_str( - ctx, - cites.get_cite(hash.ilk_info(hash.ilk_info(lc_res.loc) as usize) as usize), - pool, - )?; + print_a_pool_str(ctx, cites.get_cite(cite), pool)?; ctx.write_logs("\n"); aux_err_print(ctx, buffers, aux, pool)?; return Ok(()); @@ -413,43 +425,42 @@ pub(crate) fn get_aux_command_and_process( .lookup_str(globals.hash, line, StrIlk::AuxCommand); if res.exists { - match globals.hash.ilk_info(res.loc) { - 0 => aux_bib_data_command( + let HashExtra::AuxCommand(cmd) = globals.hash.node(res.loc).extra else { + panic!("AuxCommand lookup didn't have AuxCommand extra"); + }; + + match cmd { + AuxCommand::Data => aux_bib_data_command( ctx, globals.buffers, globals.bibs, globals.aux, globals.pool, globals.hash, - )?, - 1 => aux_bib_style_command( + ), + AuxCommand::Style => aux_bib_style_command( ctx, globals.buffers, globals.aux, globals.pool, globals.hash, - )?, - 2 => aux_citation_command( + ), + AuxCommand::Citation => aux_citation_command( ctx, globals.buffers, globals.aux, globals.pool, globals.hash, globals.cites, - )?, - 3 => aux_input_command( + ), + AuxCommand::Input => aux_input_command( ctx, globals.buffers, globals.aux, globals.pool, globals.hash, - )?, - _ => { - ctx.write_logs("Unknown auxiliary-file command"); - print_confusion(ctx); - return Err(BibtexError::Fatal); - } - } + ), + }? } Ok(()) } diff --git a/crates/engine_bibtex/src/bibs.rs b/crates/engine_bibtex/src/bibs.rs index 470f3d307..0206e22ac 100644 --- a/crates/engine_bibtex/src/bibs.rs +++ b/crates/engine_bibtex/src/bibs.rs @@ -2,18 +2,25 @@ use crate::{ buffer::{BufTy, GlobalBuffer}, char_info::LexClass, cite::add_database_cite, - hash::{FnClass, HashData, HashExtra}, + hash::{BstFn, HashData, HashExtra}, log::{ - bib_cmd_confusion, bib_equals_sign_print, bib_err_print, bib_id_print, - bib_one_of_two_print, bib_warn_print, cite_key_disappeared_confusion, eat_bib_print, - hash_cite_confusion, print_a_token, print_confusion, + bib_equals_sign_print, bib_err_print, bib_id_print, bib_one_of_two_print, bib_warn_print, + cite_key_disappeared_confusion, eat_bib_print, hash_cite_confusion, print_a_token, + print_confusion, }, peekable::input_ln, pool::StringPool, scan::{scan_and_store_the_field_value_and_eat_white, scan_identifier, Scan, ScanRes}, - BibNumber, Bibtex, BibtexError, CiteNumber, File, GlobalItems, HashPointer, StrIlk, StrNumber, + BibNumber, Bibtex, BibtexError, File, GlobalItems, HashPointer, StrIlk, StrNumber, }; +#[derive(Copy, Clone, Debug, PartialEq)] +pub(crate) enum BibCommand { + Comment, + Preamble, + String, +} + pub(crate) struct BibData { bibs: Vec, preamble: Vec, @@ -190,10 +197,14 @@ pub(crate) fn get_bib_command_or_entry_and_process( let mut lc_cite_loc = 0; if res.exists { + let HashExtra::BibCommand(cmd) = globals.hash.node(res.loc).extra else { + panic!("BibCommand lookup didn't have BibCommand extra"); + }; + at_bib_command = true; - match globals.hash.ilk_info(res.loc) { - 0 => (), - 1 => { + match cmd { + BibCommand::Comment => (), + BibCommand::Preamble => { if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, @@ -249,7 +260,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.cites, true, at_bib_command, - 1, + cmd, Some(&mut lc_cite_loc), *cur_macro_loc, right_outer_delim, @@ -278,7 +289,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers.offset(BufTy::Base, 2) + 1, ); } - 2 => { + BibCommand::String => { if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( ctx, @@ -346,15 +357,15 @@ pub(crate) fn get_bib_command_or_entry_and_process( let bib_macro = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bib_macro.make_ascii_lowercase(); - let text = globals.hash.text(res.loc); + // let text = globals.hash.text(res.loc); let res = globals.pool.lookup_str_insert( ctx, globals.hash, bib_macro, - HashExtra::BibCommand(text), + HashExtra::Macro(0), )?; // TODO: Insert overwriting? - globals.hash.node_mut(res.loc).extra = HashExtra::BibCommand(text); + globals.hash.node_mut(res.loc).extra = HashExtra::Macro(globals.hash.text(res.loc)); *cur_macro_loc = res.loc; if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { @@ -406,7 +417,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.cites, true, at_bib_command, - 2, + cmd, Some(&mut lc_cite_loc), *cur_macro_loc, right_outer_delim, @@ -436,10 +447,6 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers.offset(BufTy::Base, 2) + 1, ); } - _ => { - bib_cmd_confusion(ctx); - return Err(BibtexError::Fatal); - } } return Ok(()); } @@ -448,7 +455,14 @@ pub(crate) fn get_bib_command_or_entry_and_process( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; let bst_res = globals.pool.lookup_str(globals.hash, bst_fn, StrIlk::BstFn); - let type_exists = bst_res.exists && globals.hash.ty(bst_res.loc) == FnClass::Wizard; + let type_exists = if bst_res.exists { + matches!( + globals.hash.node(bst_res.loc).extra, + HashExtra::BstFn(BstFn::Wizard(_)) + ) + } else { + false + }; if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { eat_bib_print( @@ -528,12 +542,14 @@ pub(crate) fn get_bib_command_or_entry_and_process( // TODO: Improve this tangled control flow let mut inner = || { if lc_res.exists { - globals.cites.set_entry_ptr( - globals - .hash - .ilk_info(globals.hash.ilk_info(lc_res.loc) as usize) - as CiteNumber, - ); + let HashExtra::LcCite(cite_loc) = globals.hash.node(lc_res.loc).extra else { + panic!("LcCite lookup didn't have LcCite extra"); + }; + let HashExtra::Cite(cite) = globals.hash.node(cite_loc).extra else { + panic!("LcCite location didn't have Cite extra"); + }; + + globals.cites.set_entry_ptr(cite); let entry_ptr = globals.cites.entry_ptr(); if !ctx.all_entries || entry_ptr < globals.cites.all_marker() @@ -616,7 +632,9 @@ pub(crate) fn get_bib_command_or_entry_and_process( if res.exists { if globals.cites.entry_ptr() >= globals.cites.all_marker() { globals.cites.set_exists(globals.cites.entry_ptr(), true); - let cite_loc = globals.hash.ilk_info(lc_res.loc) as usize; + let HashExtra::LcCite(cite_loc) = globals.hash.node(lc_res.loc).extra else { + panic!("LcCite lookup didn't have LcCite extra"); + }; globals.cites.set_entry_ptr(globals.cites.ptr()); let num = add_database_cite( globals.cites, @@ -741,9 +759,12 @@ pub(crate) fn get_bib_command_or_entry_and_process( bst_fn.make_ascii_lowercase(); let res = globals.pool.lookup_str(globals.hash, bst_fn, StrIlk::BstFn); + *field_name_loc = res.loc; - if res.exists && globals.hash.ty(res.loc) == FnClass::Field { - store_field = true; + if res.exists { + if let HashExtra::BstFn(BstFn::Field(_)) = &globals.hash.node(res.loc).extra { + store_field = true; + } } } @@ -794,7 +815,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.cites, store_field, at_bib_command, - 0, + BibCommand::Comment, None, *cur_macro_loc, right_outer_delim, diff --git a/crates/engine_bibtex/src/bst.rs b/crates/engine_bibtex/src/bst.rs index a9ba1ff6a..5733133c0 100644 --- a/crates/engine_bibtex/src/bst.rs +++ b/crates/engine_bibtex/src/bst.rs @@ -4,7 +4,7 @@ use crate::{ char_info::LexClass, cite::find_cite_locs_for_this_cite_key, exec::{check_command_execution, execute_fn, ExecCtx}, - hash::{FnClass, HashData, HashExtra}, + hash::{BstFn, HashData, HashExtra}, log::{ already_seen_function_print, bad_cross_reference_print, bst_err_print_and_look_for_blank_line, bst_id_print, bst_left_brace_print, @@ -14,7 +14,7 @@ use crate::{ }, pool::StringPool, scan::{eat_bst_white_space, scan_fn_def, scan_identifier, Scan, ScanRes}, - Bibtex, BibtexError, CiteNumber, GlobalItems, HashPointer, StrIlk, + Bibtex, BibtexError, GlobalItems, HashPointer, StrIlk, }; macro_rules! eat_bst_white { @@ -62,6 +62,20 @@ macro_rules! bst_ident { }; } +#[derive(Copy, Clone, Debug)] +pub(crate) enum BstCommand { + Entry, + Execute, + Function, + Integers, + Iterate, + Macro, + Read, + Reverse, + Sort, + Strings, +} + fn bst_entry_command( ctx: &mut ExecCtx<'_, '_, '_>, globals: &mut GlobalItems<'_>, @@ -90,14 +104,13 @@ fn bst_entry_command( ctx, globals.hash, bst_fn, - HashExtra::BstFn(globals.other.num_fields() as i32), + HashExtra::BstFn(BstFn::Field(globals.other.num_fields())), )?; if res.exists { already_seen_function_print(ctx, globals.buffers, globals.pool, globals.hash, res.loc)?; return Ok(()); } - globals.hash.set_ty(res.loc, FnClass::Field); globals.other.set_num_fields(globals.other.num_fields() + 1); eat_bst_white!(ctx, globals, "entry"); @@ -130,14 +143,13 @@ fn bst_entry_command( ctx, globals.hash, bst_fn, - HashExtra::BstFn(globals.entries.num_ent_ints() as i32), + HashExtra::BstFn(BstFn::IntEntry(globals.entries.num_ent_ints())), )?; if res.exists { already_seen_function_print(ctx, globals.buffers, globals.pool, globals.hash, res.loc)?; return Ok(()); } - globals.hash.set_ty(res.loc, FnClass::IntEntryVar); globals .entries .set_num_ent_ints(globals.entries.num_ent_ints() + 1); @@ -166,14 +178,13 @@ fn bst_entry_command( ctx, globals.hash, bst_fn, - HashExtra::BstFn(globals.entries.num_ent_strs() as i32), + HashExtra::BstFn(BstFn::StrEntry(globals.entries.num_ent_strs())), )?; if res.exists { already_seen_function_print(ctx, globals.buffers, globals.pool, globals.hash, res.loc)?; return Ok(()); } - globals.hash.set_ty(res.loc, FnClass::StrEntryVar); globals .entries .set_num_ent_strs(globals.entries.num_ent_strs() + 1); @@ -249,15 +260,17 @@ fn bst_function_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = globals - .pool - .lookup_str_insert(ctx, globals.hash, bst_fn, HashExtra::BstFn(0))?; + let res = globals.pool.lookup_str_insert( + ctx, + globals.hash, + bst_fn, + HashExtra::BstFn(BstFn::Wizard(0)), + )?; if res.exists { already_seen_function_print(ctx, globals.buffers, globals.pool, globals.hash, res.loc)?; return Ok(()); } - globals.hash.set_ty(res.loc, FnClass::Wizard); if globals.hash.text(res.loc) == ctx.s_default { ctx.default = res.loc; } @@ -302,15 +315,17 @@ fn bst_integers_command( let bst_fn = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; bst_fn.make_ascii_lowercase(); - let res = globals - .pool - .lookup_str_insert(ctx, globals.hash, bst_fn, HashExtra::BstFn(0))?; + let res = globals.pool.lookup_str_insert( + ctx, + globals.hash, + bst_fn, + HashExtra::BstFn(BstFn::IntGlbl(0)), + )?; if res.exists { already_seen_function_print(ctx, globals.buffers, globals.pool, globals.hash, res.loc)?; return Ok(()); } - globals.hash.set_ty(res.loc, FnClass::IntGlblVar); eat_bst_white!(ctx, globals, "integers"); } @@ -435,9 +450,8 @@ fn bst_macro_command( let text = &mut globals.buffers.buffer_mut(BufTy::Base)[range]; let res2 = globals .pool - .lookup_str_insert(ctx, globals.hash, text, HashExtra::Text(0))?; + .lookup_str_insert(ctx, globals.hash, text, HashExtra::Text)?; - globals.hash.set_ty(res2.loc, FnClass::StrLit); globals.hash.node_mut(res.loc).extra = HashExtra::Macro(globals.hash.text(res2.loc)); globals .buffers @@ -556,15 +570,19 @@ fn bst_read_command( ); if find.lc_found { - let cite_loc = globals.hash.ilk_info(find.lc_cite_loc) as CiteNumber; + let HashExtra::LcCite(cite_loc) = globals.hash.node(find.lc_cite_loc).extra else { + panic!("LcCite lookup didn't have LcCite extra"); + }; globals .other .set_field(field_ptr, globals.hash.text(cite_loc)); let field_start = cite_ptr * globals.other.num_fields(); - let mut parent = globals.hash.ilk_info(cite_loc) as usize - * globals.other.num_fields() - + globals.other.pre_defined_fields(); + let HashExtra::Cite(cite) = globals.hash.node(cite_loc).extra else { + panic!("LcCite location didn't have Cite extra"); + }; + let mut parent = + cite * globals.other.num_fields() + globals.other.pre_defined_fields(); for idx in (field_start + globals.other.pre_defined_fields()) ..(field_start + globals.other.num_fields()) { @@ -601,12 +619,18 @@ fn bst_read_command( )?; globals.other.set_field(field_ptr, 0); } else { - if find.cite_loc != globals.hash.ilk_info(find.lc_cite_loc) as CiteNumber { + let HashExtra::LcCite(cite_loc) = globals.hash.node(find.lc_cite_loc).extra else { + panic!("LcCite lookup didn't have LcCite extra"); + }; + if find.cite_loc != cite_loc { hash_cite_confusion(ctx); return Err(BibtexError::Fatal); } - let cite_parent_ptr = globals.hash.ilk_info(find.cite_loc) as CiteNumber; + let HashExtra::Cite(cite) = globals.hash.node(find.cite_loc).extra else { + panic!("Cite lookup didn't have Cite extra"); + }; + let cite_parent_ptr = cite; if globals.cites.get_type(cite_parent_ptr) == 0 { nonexistent_cross_reference_error( ctx, @@ -674,9 +698,10 @@ fn bst_read_command( return Err(BibtexError::Fatal); } - if !find.cite_found - || find.cite_loc != globals.hash.ilk_info(find.lc_cite_loc) as CiteNumber - { + let HashExtra::LcCite(cite_loc) = globals.hash.node(find.lc_cite_loc).extra else { + panic!("LcCite lookup didn't have LcCite extra"); + }; + if !find.cite_found || find.cite_loc != cite_loc { hash_cite_confusion(ctx); return Err(BibtexError::Fatal); } @@ -817,7 +842,7 @@ fn bst_strings_command( ctx, globals.hash, bst_fn, - HashExtra::BstFn(globals.globals.num_glb_strs()), + HashExtra::BstFn(BstFn::StrGlbl(globals.globals.num_glb_strs())), )?; if res.exists { @@ -825,9 +850,7 @@ fn bst_strings_command( return Ok(()); } - globals.hash.set_ty(res.loc, FnClass::StrGlblVar); - - if globals.globals.num_glb_strs() as usize == globals.globals.len() { + if globals.globals.num_glb_strs() == globals.globals.len() { globals.globals.grow(); } @@ -867,14 +890,15 @@ fn bad_argument_token( ctx.write_logs(" is an unknown function"); bst_err_print_and_look_for_blank_line(ctx, buffers, pool)?; Ok(true) - } else if hash.ty(res.loc) != FnClass::Builtin && hash.ty(res.loc) != FnClass::Wizard { + } else if let HashExtra::BstFn(BstFn::Builtin(_) | BstFn::Wizard(_)) = hash.node(res.loc).extra + { + Ok(false) + } else { print_a_token(ctx, buffers); ctx.write_logs(" has bad function type"); print_fn_class(ctx, hash, res.loc); bst_err_print_and_look_for_blank_line(ctx, buffers, pool)?; Ok(true) - } else { - Ok(false) } } @@ -909,21 +933,20 @@ pub(crate) fn get_bst_command_and_process( return Ok(()); } - match globals.hash.ilk_info(res.loc) { - 0 => bst_entry_command(ctx, globals), - 1 => bst_execute_command(ctx, globals), - 2 => bst_function_command(ctx, globals), - 3 => bst_integers_command(ctx, globals), - 4 => bst_iterate_command(ctx, globals), - 5 => bst_macro_command(ctx, globals), - 6 => bst_read_command(ctx, globals), - 7 => bst_reverse_command(ctx, globals), - 8 => bst_sort_command(ctx, globals), - 9 => bst_strings_command(ctx, globals), - _ => { - ctx.write_logs("Unknown style-file command"); - print_confusion(ctx); - Err(BibtexError::Fatal) - } + let HashExtra::BstCommand(cmd) = globals.hash.node(res.loc).extra else { + panic!("BstCommand lookup didn't have BstCommand extra"); + }; + + match cmd { + BstCommand::Entry => bst_entry_command(ctx, globals), + BstCommand::Execute => bst_execute_command(ctx, globals), + BstCommand::Function => bst_function_command(ctx, globals), + BstCommand::Integers => bst_integers_command(ctx, globals), + BstCommand::Iterate => bst_iterate_command(ctx, globals), + BstCommand::Macro => bst_macro_command(ctx, globals), + BstCommand::Read => bst_read_command(ctx, globals), + BstCommand::Reverse => bst_reverse_command(ctx, globals), + BstCommand::Sort => bst_sort_command(ctx, globals), + BstCommand::Strings => bst_strings_command(ctx, globals), } } diff --git a/crates/engine_bibtex/src/exec.rs b/crates/engine_bibtex/src/exec.rs index b5de19315..4f85f9918 100644 --- a/crates/engine_bibtex/src/exec.rs +++ b/crates/engine_bibtex/src/exec.rs @@ -5,7 +5,7 @@ use crate::{ cite::CiteInfo, entries::{EntryData, ENT_STR_SIZE}, global::{GlobalData, GLOB_STR_SIZE}, - hash::{FnClass, HashData, HashExtra}, + hash::{BstBuiltin, BstFn, HashData, HashExtra}, log::{ brace_lvl_one_letters_complaint, braces_unbalanced_complaint, bst_1print_string_size_exceeded, bst_2print_string_size_exceeded, @@ -22,6 +22,23 @@ use crate::{ }; use std::ops::{Deref, DerefMut, Index}; +#[derive(Copy, Clone, Debug, PartialEq)] +pub(crate) enum ControlSeq { + LowerI, + LowerJ, + LowerAA, + UpperAA, + LowerAE, + UpperAE, + LowerOE, + UpperOE, + LowerO, + UpperO, + LowerL, + UpperL, + LowerSS, +} + #[derive(Copy, Clone, PartialEq, Eq)] pub(crate) enum StkType { Integer, @@ -904,24 +921,20 @@ fn interp_gets( } }; - let fn_ty = hash.ty(f1); - if !ctx.mess_with_entries && fn_ty == FnClass::StrEntryVar || fn_ty == FnClass::IntEntryVar { - bst_cant_mess_with_entries_print(ctx, pool, cites)?; - return Ok(()); - } + // TODO: Merge into match below - match fn_ty { - FnClass::IntEntryVar => { + match &hash.node(f1).extra { + HashExtra::BstFn(BstFn::IntEntry(_) | BstFn::StrEntry(_)) if !ctx.mess_with_entries => { + bst_cant_mess_with_entries_print(ctx, pool, cites)?; + } + HashExtra::BstFn(BstFn::IntEntry(entry)) => { if let ExecVal::Integer(i2) = pop2 { - entries.set_int( - cites.ptr() * entries.num_ent_ints() + hash.ilk_info(f1) as usize, - i2, - ) + entries.set_int(cites.ptr() * entries.num_ent_ints() + *entry, i2) } else { print_wrong_stk_lit(ctx, pool, hash, cites, pop2, StkType::Integer)?; } } - FnClass::StrEntryVar => { + HashExtra::BstFn(BstFn::StrEntry(entry)) => { if let ExecVal::String(s2) = pop2 { let mut s = pool.get_str(s2); if s.len() > ENT_STR_SIZE { @@ -930,28 +943,24 @@ fn interp_gets( bst_2print_string_size_exceeded(ctx, pool, cites)?; s = &s[..ENT_STR_SIZE]; } - entries.set_str( - cites.ptr() * entries.num_ent_strs() + hash.ilk_info(f1) as usize, - s, - ); + entries.set_str(cites.ptr() * entries.num_ent_strs() + *entry, s); } else { print_wrong_stk_lit(ctx, pool, hash, cites, pop2, StkType::Integer)?; } } - FnClass::IntGlblVar => { + HashExtra::BstFn(BstFn::IntGlbl(_)) => { if let ExecVal::Integer(i2) = pop2 { - hash.node_mut(f1).extra = HashExtra::BstFn(i2); + hash.node_mut(f1).extra = HashExtra::BstFn(BstFn::IntGlbl(i2)); } else { print_wrong_stk_lit(ctx, pool, hash, cites, pop2, StkType::Integer)?; } } - FnClass::StrGlblVar => { + HashExtra::BstFn(BstFn::StrGlbl(str_ptr)) => { if let ExecVal::String(s2) = pop2 { - let str_glb_ptr = hash.ilk_info(f1) as usize; if s2 < ctx.bib_str_ptr { - globals.set_str_ptr(str_glb_ptr, s2); + globals.set_str_ptr(*str_ptr, s2); } else { - globals.set_str_ptr(str_glb_ptr, 0); + globals.set_str_ptr(*str_ptr, 0); let mut s = pool.get_str(s2); if s.len() > GLOB_STR_SIZE { bst_1print_string_size_exceeded(ctx); @@ -959,7 +968,7 @@ fn interp_gets( bst_2print_string_size_exceeded(ctx, pool, cites)?; s = &s[..GLOB_STR_SIZE]; } - globals.set_str(str_glb_ptr, s); + globals.set_str(*str_ptr, s); } } else { print_wrong_stk_lit(ctx, pool, hash, cites, pop2, StkType::String)?; @@ -1097,21 +1106,33 @@ fn interp_change_case( let res = pool.lookup_str(hash, &scratch[old_idx..idx], StrIlk::ControlSeq); + if res.exists { + let HashExtra::ControlSeq(seq) = hash.node(res.loc).extra else { + panic!("ControlSeq lookup didn't have ControlSeq extra"); + }; match conv_ty { - ConvTy::TitleLower | ConvTy::AllLower => { - match hash.ilk_info(res.loc) { - 3 | 5 | 7 | 9 | 11 => { - scratch[old_idx..idx].make_ascii_lowercase() - } - _ => (), + ConvTy::TitleLower | ConvTy::AllLower => match seq { + ControlSeq::UpperOE + | ControlSeq::UpperAE + | ControlSeq::UpperAA + | ControlSeq::UpperO + | ControlSeq::UpperL => { + scratch[old_idx..idx].make_ascii_lowercase() } - } - ConvTy::AllUpper => match hash.ilk_info(res.loc) { - 2 | 4 | 6 | 8 | 10 => { + _ => (), + }, + ConvTy::AllUpper => match seq { + ControlSeq::LowerOE + | ControlSeq::LowerAE + | ControlSeq::LowerAA + | ControlSeq::LowerO + | ControlSeq::LowerL => { scratch[old_idx..idx].make_ascii_uppercase() } - 0 | 1 | 12 => { + ControlSeq::LowerI + | ControlSeq::LowerJ + | ControlSeq::LowerSS => { scratch[old_idx..idx].make_ascii_uppercase(); scratch.copy_within(old_idx..idx, old_idx - 1); let old_idx = idx - 1; @@ -1492,9 +1513,8 @@ fn interp_format_name( while von_start < last_end - 1 { name_ptr = buffers.name_tok(von_start); name_ptr2 = buffers.name_tok(von_start + 1); - if von_token_found(ctx, buffers, hash, pool, &mut name_ptr, name_ptr2)? { + if von_token_found(buffers, hash, pool, &mut name_ptr, name_ptr2) { von_name_ends_and_last_name_starts_stuff( - ctx, buffers, hash, pool, @@ -1503,7 +1523,7 @@ fn interp_format_name( &mut von_end, &mut name_ptr, &mut name_ptr2, - )?; + ); second_loop = false; break; } @@ -1529,7 +1549,6 @@ fn interp_format_name( first_start = jr_end; first_end = num_tokens; von_name_ends_and_last_name_starts_stuff( - ctx, buffers, hash, pool, @@ -1538,7 +1557,7 @@ fn interp_format_name( &mut von_end, &mut name_ptr, &mut name_ptr2, - )?; + ); } Commas::Two(comma1, comma2) => { last_end = comma1; @@ -1546,7 +1565,6 @@ fn interp_format_name( first_start = jr_end; first_end = num_tokens; von_name_ends_and_last_name_starts_stuff( - ctx, buffers, hash, pool, @@ -1555,7 +1573,7 @@ fn interp_format_name( &mut von_end, &mut name_ptr, &mut name_ptr2, - )?; + ); } } @@ -1758,10 +1776,17 @@ fn interp_purify( let res = pool.lookup_str(hash, &scratch[old_idx..idx], StrIlk::ControlSeq); if res.exists { + let HashExtra::ControlSeq(seq) = hash.node(res.loc).extra else { + panic!("ControlSeq lookup didn't have ControlSeq extra"); + }; scratch[write_idx] = scratch[old_idx]; write_idx += 1; - match hash.ilk_info(res.loc) { - 2 | 3 | 4 | 5 | 12 => { + match seq { + ControlSeq::LowerOE + | ControlSeq::UpperOE + | ControlSeq::LowerAE + | ControlSeq::UpperAE + | ControlSeq::UpperL => { scratch[write_idx] = scratch[old_idx + 1]; write_idx += 1; } @@ -2141,12 +2166,15 @@ fn interp_width( } else { let res = pool.lookup_str(hash, &str[old_idx..idx], StrIlk::ControlSeq); if res.exists { - match hash.ilk_info(res.loc) { - 12 => string_width += 500, - 4 => string_width += 722, - 2 => string_width += 778, - 5 => string_width += 903, - 3 => string_width += 1014, + let HashExtra::ControlSeq(seq) = hash.node(res.loc).extra else { + panic!("ControlSeq lookup didn't have ControlSeq extra"); + }; + match seq { + ControlSeq::LowerSS => string_width += 500, + ControlSeq::LowerAE => string_width += 722, + ControlSeq::LowerOE => string_width += 778, + ControlSeq::UpperAE => string_width += 903, + ControlSeq::UpperOE => string_width += 1014, _ => string_width += CHAR_WIDTH[str[old_idx] as usize], } } @@ -2211,15 +2239,23 @@ pub(crate) fn execute_fn( globals: &mut GlobalItems<'_>, ex_fn_loc: HashPointer, ) -> Result<(), BibtexError> { - match globals.hash.ty(ex_fn_loc) { - FnClass::Builtin => match globals.hash.ilk_info(ex_fn_loc) { - 0 => interp_eq(ctx, globals.pool, globals.hash, globals.cites), - 1 => interp_gt(ctx, globals.pool, globals.hash, globals.cites), - 2 => interp_lt(ctx, globals.pool, globals.hash, globals.cites), - 3 => interp_plus(ctx, globals.pool, globals.hash, globals.cites), - 4 => interp_minus(ctx, globals.pool, globals.hash, globals.cites), - 5 => interp_concat(ctx, globals.pool, globals.hash, globals.cites), - 6 => interp_gets( + match &globals.hash.node(ex_fn_loc).extra { + HashExtra::Text => { + ctx.push_stack(ExecVal::String(globals.hash.text(ex_fn_loc))); + Ok(()) + } + HashExtra::Integer(i) => { + ctx.push_stack(ExecVal::Integer(*i)); + Ok(()) + } + HashExtra::BstFn(BstFn::Builtin(builtin)) => match builtin { + BstBuiltin::Eq => interp_eq(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Gt => interp_gt(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Lt => interp_lt(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Plus => interp_plus(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Minus => interp_minus(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Concat => interp_concat(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Set => interp_gets( ctx, globals.pool, globals.hash, @@ -2227,8 +2263,10 @@ pub(crate) fn execute_fn( globals.globals, globals.cites, ), - 7 => interp_add_period(ctx, globals.pool, globals.hash, globals.cites), - 8 => { + BstBuiltin::AddPeriod => { + interp_add_period(ctx, globals.pool, globals.hash, globals.cites) + } + BstBuiltin::CallType => { let default = globals.cites.get_type(globals.cites.ptr()); if !ctx.mess_with_entries { bst_cant_mess_with_entries_print(ctx, globals.pool, globals.cites)?; @@ -2241,19 +2279,23 @@ pub(crate) fn execute_fn( Ok(()) } } - 9 => interp_change_case(ctx, globals.pool, globals.cites, globals.hash), - 10 => interp_chr_to_int(ctx, globals.pool, globals.hash, globals.cites), - 11 => interp_cite(ctx, globals.pool, globals.cites), - 12 => interp_dup(ctx, globals.pool, globals.cites), - 13 => interp_empty(ctx, globals.pool, globals.hash, globals.cites), - 14 => interp_format_name( + BstBuiltin::ChangeCase => { + interp_change_case(ctx, globals.pool, globals.cites, globals.hash) + } + BstBuiltin::ChrToInt => { + interp_chr_to_int(ctx, globals.pool, globals.hash, globals.cites) + } + BstBuiltin::Cite => interp_cite(ctx, globals.pool, globals.cites), + BstBuiltin::Duplicate => interp_dup(ctx, globals.pool, globals.cites), + BstBuiltin::Empty => interp_empty(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::FormatName => interp_format_name( ctx, globals.pool, globals.buffers, globals.cites, globals.hash, ), - 15 => { + BstBuiltin::If => { let pop1 = ctx.pop_stack(globals.pool, globals.cites)?; let pop2 = ctx.pop_stack(globals.pool, globals.cites)?; let pop3 = ctx.pop_stack(globals.pool, globals.cites)?; @@ -2292,34 +2334,42 @@ pub(crate) fn execute_fn( ), } } - 16 => interp_int_to_chr(ctx, globals.pool, globals.hash, globals.cites), - 17 => interp_int_to_str(ctx, globals.pool, globals.hash, globals.cites), - 18 => interp_missing(ctx, globals.pool, globals.hash, globals.cites), - 19 => { + BstBuiltin::IntToChr => { + interp_int_to_chr(ctx, globals.pool, globals.hash, globals.cites) + } + BstBuiltin::IntToStr => { + interp_int_to_str(ctx, globals.pool, globals.hash, globals.cites) + } + BstBuiltin::Missing => interp_missing(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Newline => { output_bbl_line(ctx, globals.buffers); Ok(()) } - 20 => interp_num_names( + BstBuiltin::NumNames => interp_num_names( ctx, globals.pool, globals.buffers, globals.hash, globals.cites, ), - 21 => ctx.pop_stack(globals.pool, globals.cites).map(|_| ()), - 22 => interp_preamble(ctx, globals.pool, globals.bibs), - 23 => interp_purify(ctx, globals.pool, globals.hash, globals.cites), - 24 => interp_quote(ctx, globals.pool), - 25 => Ok(()), - 26 => pop_whole_stack(ctx, globals.pool, globals.hash, globals.cites), - 27 => interp_substr(ctx, globals.pool, globals.hash, globals.cites), - 28 => interp_swap(ctx, globals.pool, globals.cites), - 29 => interp_text_len(ctx, globals.pool, globals.hash, globals.cites), - 30 => interp_text_prefix(ctx, globals.pool, globals.hash, globals.cites), - 31 => pop_top_and_print(ctx, globals.pool, globals.hash, globals.cites), - 32 => interp_ty(ctx, globals.pool, globals.hash, globals.cites), - 33 => interp_warning(ctx, globals.pool, globals.hash, globals.cites), - 34 => { + BstBuiltin::Pop => ctx.pop_stack(globals.pool, globals.cites).map(|_| ()), + BstBuiltin::Preamble => interp_preamble(ctx, globals.pool, globals.bibs), + BstBuiltin::Purify => interp_purify(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Quote => interp_quote(ctx, globals.pool), + BstBuiltin::Skip => Ok(()), + BstBuiltin::Stack => pop_whole_stack(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Substring => interp_substr(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Swap => interp_swap(ctx, globals.pool, globals.cites), + BstBuiltin::TextLength => { + interp_text_len(ctx, globals.pool, globals.hash, globals.cites) + } + BstBuiltin::TextPrefix => { + interp_text_prefix(ctx, globals.pool, globals.hash, globals.cites) + } + BstBuiltin::Top => pop_top_and_print(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Type => interp_ty(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Warning => interp_warning(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::While => { let pop1 = ctx.pop_stack(globals.pool, globals.cites)?; let pop2 = ctx.pop_stack(globals.pool, globals.cites)?; @@ -2366,22 +2416,16 @@ pub(crate) fn execute_fn( ), } } - 35 => interp_width(ctx, globals.pool, globals.hash, globals.cites), - 36 => interp_write( + BstBuiltin::Width => interp_width(ctx, globals.pool, globals.hash, globals.cites), + BstBuiltin::Write => interp_write( ctx, globals.pool, globals.hash, globals.buffers, globals.cites, ), - _ => { - ctx.write_logs("Unknown built-in function"); - print_confusion(ctx); - Err(BibtexError::Fatal) - } }, - FnClass::Wizard => { - let mut wiz_ptr = globals.hash.ilk_info(ex_fn_loc) as usize; + HashExtra::BstFn(BstFn::Wizard(mut wiz_ptr)) => { let mut cur_fn = globals.other.wiz_function(wiz_ptr); while cur_fn != HashData::end_of_def() { if cur_fn != QUOTE_NEXT_FN { @@ -2396,20 +2440,11 @@ pub(crate) fn execute_fn( } Ok(()) } - FnClass::IntLit => { - ctx.push_stack(ExecVal::Integer(globals.hash.ilk_info(ex_fn_loc))); - Ok(()) - } - FnClass::StrLit => { - ctx.push_stack(ExecVal::String(globals.hash.text(ex_fn_loc))); - Ok(()) - } - FnClass::Field => { + HashExtra::BstFn(BstFn::Field(field)) => { if !ctx.mess_with_entries { bst_cant_mess_with_entries_print(ctx, globals.pool, globals.cites) } else { - let field_ptr = globals.cites.ptr() * globals.other.num_fields() - + globals.hash.ilk_info(ex_fn_loc) as usize; + let field_ptr = globals.cites.ptr() * globals.other.num_fields() + *field; if field_ptr >= globals.other.max_fields() { ctx.write_logs("field_info index is out of range"); print_confusion(ctx); @@ -2425,45 +2460,45 @@ pub(crate) fn execute_fn( Ok(()) } } - FnClass::IntEntryVar => { + HashExtra::BstFn(BstFn::IntEntry(entry)) => { if !ctx.mess_with_entries { bst_cant_mess_with_entries_print(ctx, globals.pool, globals.cites) } else { - ctx.push_stack(ExecVal::Integer(globals.entries.ints( - globals.cites.ptr() * globals.entries.num_ent_ints() - + globals.hash.ilk_info(ex_fn_loc) as usize, - ))); + ctx.push_stack(ExecVal::Integer( + globals + .entries + .ints(globals.cites.ptr() * globals.entries.num_ent_ints() + *entry), + )); Ok(()) } } - FnClass::StrEntryVar => { + HashExtra::BstFn(BstFn::StrEntry(entry)) => { if !ctx.mess_with_entries { bst_cant_mess_with_entries_print(ctx, globals.pool, globals.cites) } else { - let str_ent_ptr = globals.cites.ptr() * globals.entries.num_ent_strs() - + globals.hash.ilk_info(ex_fn_loc) as usize; + let str_ent_ptr = globals.cites.ptr() * globals.entries.num_ent_strs() + *entry; let str = globals.entries.strs(str_ent_ptr); let val = ExecVal::String(globals.pool.add_string_raw(ctx, str)?); ctx.push_stack(val); Ok(()) } } - FnClass::IntGlblVar => { - ctx.push_stack(ExecVal::Integer(globals.hash.ilk_info(ex_fn_loc))); + HashExtra::BstFn(BstFn::IntGlbl(value)) => { + ctx.push_stack(ExecVal::Integer(*value)); Ok(()) } - FnClass::StrGlblVar => { - let str_glb_ptr = globals.hash.ilk_info(ex_fn_loc) as usize; - let str_ptr = globals.globals.str_ptr(str_glb_ptr); + HashExtra::BstFn(BstFn::StrGlbl(glb_ptr)) => { + let str_ptr = globals.globals.str_ptr(*glb_ptr); if str_ptr > 0 { ctx.push_stack(ExecVal::String(str_ptr)); } else { - let str = globals.globals.str(str_glb_ptr); + let str = globals.globals.str(*glb_ptr); let val = ExecVal::String(globals.pool.add_string_raw(ctx, str)?); ctx.push_stack(val); } Ok(()) } + _ => panic!("Invalid node passed as ex_fn_loc"), } } diff --git a/crates/engine_bibtex/src/global.rs b/crates/engine_bibtex/src/global.rs index 06c3e3106..5cdb2a74f 100644 --- a/crates/engine_bibtex/src/global.rs +++ b/crates/engine_bibtex/src/global.rs @@ -7,7 +7,7 @@ pub(crate) struct GlobalData { glb_bib_str_ptr: Vec, global_strs: Vec, glb_str_end: Vec, - num_glb_strs: i32, + num_glb_strs: usize, } impl GlobalData { @@ -50,11 +50,11 @@ impl GlobalData { self.glb_str_end[pos] = val.len(); } - pub fn num_glb_strs(&self) -> i32 { + pub fn num_glb_strs(&self) -> usize { self.num_glb_strs } - pub fn set_num_glb_strs(&mut self, val: i32) { + pub fn set_num_glb_strs(&mut self, val: usize) { self.num_glb_strs = val; } diff --git a/crates/engine_bibtex/src/hash.rs b/crates/engine_bibtex/src/hash.rs index 89a0270a3..e9992fd06 100644 --- a/crates/engine_bibtex/src/hash.rs +++ b/crates/engine_bibtex/src/hash.rs @@ -1,4 +1,7 @@ -use crate::{pool, CiteNumber, HashPointer, StrIlk, StrNumber}; +use crate::{ + auxi::AuxCommand, bibs::BibCommand, bst::BstCommand, exec::ControlSeq, pool, CiteNumber, + FnDefLoc, HashPointer, StrIlk, StrNumber, +}; pub(crate) const HASH_BASE: usize = 1; pub(crate) const HASH_SIZE: usize = if pool::MAX_STRINGS > 5000 { @@ -58,41 +61,80 @@ const fn compute_hash_prime() -> usize { hash_prime } -#[derive(Copy, Clone, PartialEq)] -pub(crate) enum FnClass { - Builtin, - Wizard, - IntLit, - StrLit, - Field, - IntEntryVar, - StrEntryVar, - IntGlblVar, - StrGlblVar, +#[derive(Copy, Clone, Debug, PartialEq)] +pub(crate) enum BstBuiltin { + Eq, + Gt, + Lt, + Plus, + Minus, + Concat, + Set, + AddPeriod, + CallType, + ChangeCase, + ChrToInt, + Cite, + Duplicate, + Empty, + FormatName, + If, + IntToChr, + IntToStr, + Missing, + Newline, + NumNames, + Pop, + Preamble, + Purify, + Quote, + Skip, + Stack, + Substring, + Swap, + TextLength, + TextPrefix, + Top, + Type, + Warning, + While, + Width, + Write, +} + +#[derive(Copy, Clone, Debug)] +pub(crate) enum BstFn { + Builtin(BstBuiltin), + Wizard(FnDefLoc), + Field(usize), + IntEntry(usize), + StrEntry(usize), + IntGlbl(i32), + StrGlbl(usize), } #[derive(Clone, Debug)] pub enum HashExtra { - Text(StrNumber), + Text, Integer(i32), - AuxCommand(i32), // TODO: Make Enum + AuxCommand(AuxCommand), AuxFile, - BstCommand(i32), // TODO: Make Enum + BstCommand(BstCommand), BstFile, BibFile, FileExt, Cite(CiteNumber), LcCite(HashPointer), - BstFn(i32), - BibCommand(StrNumber), // TODO: Make Enum + BstFn(BstFn), + BibCommand(BibCommand), Macro(StrNumber), - ControlSeq(i32), + ControlSeq(ControlSeq), } impl HashExtra { pub(crate) fn kind(&self) -> StrIlk { match self { - HashExtra::Text(_) => StrIlk::Text, + HashExtra::Text => StrIlk::Text, HashExtra::Integer(_) => StrIlk::Integer, HashExtra::AuxCommand(_) => StrIlk::AuxCommand, HashExtra::AuxFile => StrIlk::AuxFile, @@ -108,30 +150,11 @@ impl HashExtra { HashExtra::ControlSeq(_) => StrIlk::ControlSeq, } } - - fn data_i32(&self) -> i32 { - match self { - HashExtra::Text(s) => *s as i32, - HashExtra::Integer(i) => *i, - HashExtra::AuxCommand(c) => *c, - HashExtra::AuxFile => todo!(), - HashExtra::BstCommand(c) => *c, - HashExtra::BstFile => todo!(), - HashExtra::BibFile => todo!(), - HashExtra::FileExt => todo!(), - HashExtra::Cite(c) => *c as i32, - HashExtra::LcCite(c) => *c as i32, - HashExtra::BstFn(c) => *c, - HashExtra::BibCommand(c) => *c as i32, - HashExtra::Macro(c) => *c as i32, - HashExtra::ControlSeq(c) => *c, - } - } } impl Default for HashExtra { fn default() -> Self { - HashExtra::Text(0) + HashExtra::Text } } @@ -151,7 +174,6 @@ impl HashNode { // TODO: Split string-pool stuff into string pool, executor stuff into execution context pub(crate) struct HashData { hash_data: Vec, - fn_type: Vec, len: usize, } @@ -159,7 +181,6 @@ impl HashData { pub(crate) fn new() -> HashData { HashData { hash_data: vec![HashNode::default(); HASH_MAX + 1], - fn_type: vec![FnClass::Builtin; HASH_MAX + 1], len: HASH_MAX + 1, } } @@ -196,14 +217,6 @@ impl HashData { self.hash_data[pos].next = val } - pub fn ty(&self, pos: usize) -> FnClass { - self.fn_type[pos] - } - - pub fn set_ty(&mut self, pos: usize, class: FnClass) { - self.fn_type[pos] = class; - } - pub fn len(&self) -> usize { self.len } @@ -215,8 +228,4 @@ impl HashData { pub fn prime(&self) -> usize { HASH_PRIME } - - pub fn ilk_info(&self, pos: usize) -> i32 { - self.node(pos).extra.data_i32() - } } diff --git a/crates/engine_bibtex/src/log.rs b/crates/engine_bibtex/src/log.rs index 1f20252be..9cc02952d 100644 --- a/crates/engine_bibtex/src/log.rs +++ b/crates/engine_bibtex/src/log.rs @@ -5,7 +5,7 @@ use crate::{ char_info::LexClass, cite::CiteInfo, exec::{bst_ex_warn_print, bst_ln_num_print, ExecCtx}, - hash::{FnClass, HashData}, + hash::{BstFn, HashData, HashExtra}, other::OtherData, peekable::input_ln, pool::StringPool, @@ -444,11 +444,6 @@ pub(crate) fn bib_id_print( } } -pub(crate) fn bib_cmd_confusion(ctx: &mut Bibtex<'_, '_>) { - ctx.write_logs("Unknown database-file command"); - print_confusion(ctx); -} - pub fn cite_key_disappeared_confusion(ctx: &mut Bibtex<'_, '_>) { ctx.write_logs("A cite key disappeared"); print_confusion(ctx); @@ -531,17 +526,17 @@ pub(crate) fn braces_unbalanced_complaint( } pub(crate) fn print_fn_class(ctx: &mut Bibtex<'_, '_>, hash: &HashData, fn_loc: HashPointer) { - let ty = hash.ty(fn_loc); - match ty { - FnClass::Builtin => ctx.write_logs("built-in"), - FnClass::Wizard => ctx.write_logs("wizard-defined"), - FnClass::IntLit => ctx.write_logs("integer-literal"), - FnClass::StrLit => ctx.write_logs("string-literal"), - FnClass::Field => ctx.write_logs("field"), - FnClass::IntEntryVar => ctx.write_logs("integer-entry-variable"), - FnClass::StrEntryVar => ctx.write_logs("string-entry-variable"), - FnClass::IntGlblVar => ctx.write_logs("integer-global-variable"), - FnClass::StrGlblVar => ctx.write_logs("string-global-variable"), + match hash.node(fn_loc).extra { + HashExtra::BstFn(BstFn::Builtin(_)) => ctx.write_logs("built-in"), + HashExtra::BstFn(BstFn::Wizard(_)) => ctx.write_logs("wizard-defined"), + HashExtra::Integer(_) => ctx.write_logs("integer-literal"), + HashExtra::Text => ctx.write_logs("string-literal"), + HashExtra::BstFn(BstFn::Field(_)) => ctx.write_logs("field"), + HashExtra::BstFn(BstFn::IntEntry(_)) => ctx.write_logs("integer-entry-variable"), + HashExtra::BstFn(BstFn::StrEntry(_)) => ctx.write_logs("string-entry-variable"), + HashExtra::BstFn(BstFn::IntGlbl(_)) => ctx.write_logs("integer-global-variable"), + HashExtra::BstFn(BstFn::StrGlbl(_)) => ctx.write_logs("string-global-variable"), + _ => ctx.write_logs("unknown-fn"), } } diff --git a/crates/engine_bibtex/src/pool.rs b/crates/engine_bibtex/src/pool.rs index 5628216b5..bdf30115e 100644 --- a/crates/engine_bibtex/src/pool.rs +++ b/crates/engine_bibtex/src/pool.rs @@ -1,10 +1,14 @@ use crate::{ + auxi::AuxCommand, + bibs::BibCommand, + bst::BstCommand, buffer::{BufTy, GlobalBuffer}, char_info::LexClass, entries::ENT_STR_SIZE, + exec::ControlSeq, global::GLOB_STR_SIZE, hash, - hash::{FnClass, HashData, HashExtra}, + hash::{BstBuiltin, BstFn, HashData, HashExtra}, log::{output_bbl_line, print_overflow}, ASCIICode, Bibtex, BibtexError, GlobalItems, HashPointer, LookupRes, PoolPointer, StrIlk, StrNumber, @@ -283,126 +287,199 @@ pub(crate) fn pre_def_certain_strings( let res = pool.lookup_str_insert(ctx, hash, b".aux", HashExtra::FileExt)?; ctx.s_aux_extension = hash.text(res.loc); - pool.lookup_str_insert(ctx, hash, b"\\bibdata", HashExtra::AuxCommand(0))?; - pool.lookup_str_insert(ctx, hash, b"\\bibstyle", HashExtra::AuxCommand(1))?; - pool.lookup_str_insert(ctx, hash, b"\\citation", HashExtra::AuxCommand(2))?; - pool.lookup_str_insert(ctx, hash, b"\\@input", HashExtra::AuxCommand(3))?; - - pool.lookup_str_insert(ctx, hash, b"entry", HashExtra::BstCommand(0))?; - pool.lookup_str_insert(ctx, hash, b"execute", HashExtra::BstCommand(1))?; - pool.lookup_str_insert(ctx, hash, b"function", HashExtra::BstCommand(2))?; - pool.lookup_str_insert(ctx, hash, b"integers", HashExtra::BstCommand(3))?; - pool.lookup_str_insert(ctx, hash, b"iterate", HashExtra::BstCommand(4))?; - pool.lookup_str_insert(ctx, hash, b"macro", HashExtra::BstCommand(5))?; - pool.lookup_str_insert(ctx, hash, b"read", HashExtra::BstCommand(6))?; - pool.lookup_str_insert(ctx, hash, b"reverse", HashExtra::BstCommand(7))?; - pool.lookup_str_insert(ctx, hash, b"sort", HashExtra::BstCommand(8))?; - pool.lookup_str_insert(ctx, hash, b"strings", HashExtra::BstCommand(9))?; - - pool.lookup_str_insert(ctx, hash, b"comment", HashExtra::BibCommand(0))?; - pool.lookup_str_insert(ctx, hash, b"preamble", HashExtra::BibCommand(1))?; - pool.lookup_str_insert(ctx, hash, b"string", HashExtra::BibCommand(2))?; - - let mut build_in = |pds: &[ASCIICode], blt_in_num| { - let res = pool.lookup_str_insert(ctx, hash, pds, HashExtra::BstFn(blt_in_num))?; - hash.set_ty(res.loc, FnClass::Builtin); + pool.lookup_str_insert( + ctx, + hash, + b"\\bibdata", + HashExtra::AuxCommand(AuxCommand::Data), + )?; + pool.lookup_str_insert( + ctx, + hash, + b"\\bibstyle", + HashExtra::AuxCommand(AuxCommand::Style), + )?; + pool.lookup_str_insert( + ctx, + hash, + b"\\citation", + HashExtra::AuxCommand(AuxCommand::Citation), + )?; + pool.lookup_str_insert( + ctx, + hash, + b"\\@input", + HashExtra::AuxCommand(AuxCommand::Input), + )?; + + pool.lookup_str_insert( + ctx, + hash, + b"entry", + HashExtra::BstCommand(BstCommand::Entry), + )?; + pool.lookup_str_insert( + ctx, + hash, + b"execute", + HashExtra::BstCommand(BstCommand::Execute), + )?; + pool.lookup_str_insert( + ctx, + hash, + b"function", + HashExtra::BstCommand(BstCommand::Function), + )?; + pool.lookup_str_insert( + ctx, + hash, + b"integers", + HashExtra::BstCommand(BstCommand::Integers), + )?; + pool.lookup_str_insert( + ctx, + hash, + b"iterate", + HashExtra::BstCommand(BstCommand::Iterate), + )?; + pool.lookup_str_insert( + ctx, + hash, + b"macro", + HashExtra::BstCommand(BstCommand::Macro), + )?; + pool.lookup_str_insert(ctx, hash, b"read", HashExtra::BstCommand(BstCommand::Read))?; + pool.lookup_str_insert( + ctx, + hash, + b"reverse", + HashExtra::BstCommand(BstCommand::Reverse), + )?; + pool.lookup_str_insert(ctx, hash, b"sort", HashExtra::BstCommand(BstCommand::Sort))?; + pool.lookup_str_insert( + ctx, + hash, + b"strings", + HashExtra::BstCommand(BstCommand::Strings), + )?; + + pool.lookup_str_insert( + ctx, + hash, + b"comment", + HashExtra::BibCommand(BibCommand::Comment), + )?; + pool.lookup_str_insert( + ctx, + hash, + b"preamble", + HashExtra::BibCommand(BibCommand::Preamble), + )?; + pool.lookup_str_insert( + ctx, + hash, + b"string", + HashExtra::BibCommand(BibCommand::String), + )?; + + let mut build_in = |pds: &[ASCIICode], builtin| { + let res = + pool.lookup_str_insert(ctx, hash, pds, HashExtra::BstFn(BstFn::Builtin(builtin)))?; Ok(res.loc) }; - build_in(b"=", 0)?; - build_in(b">", 1)?; - build_in(b"<", 2)?; - build_in(b"+", 3)?; - build_in(b"-", 4)?; - build_in(b"*", 5)?; - build_in(b":=", 6)?; - build_in(b"add.period$", 7)?; - build_in(b"call.type$", 8)?; - build_in(b"change.case$", 9)?; - build_in(b"chr.to.int$", 10)?; - build_in(b"cite$", 11)?; - build_in(b"duplicate$", 12)?; - build_in(b"empty$", 13)?; - build_in(b"format.name$", 14)?; - build_in(b"if$", 15)?; - build_in(b"int.to.chr$", 16)?; - build_in(b"int.to.str$", 17)?; - build_in(b"missing$", 18)?; - build_in(b"newline$", 19)?; - build_in(b"num.names$", 20)?; - build_in(b"pop$", 21)?; - build_in(b"preamble$", 22)?; - build_in(b"purify$", 23)?; - build_in(b"quote$", 24)?; - let skip_loc = build_in(b"skip$", 25)?; - build_in(b"stack$", 26)?; - build_in(b"substring$", 27)?; - build_in(b"swap$", 28)?; - build_in(b"text.length$", 29)?; - build_in(b"text.prefix$", 30)?; - build_in(b"top$", 31)?; - build_in(b"type$", 32)?; - build_in(b"warning$", 33)?; - build_in(b"while$", 34)?; - build_in(b"width$", 35)?; - build_in(b"write$", 36)?; - - let res = pool.lookup_str_insert(ctx, hash, b"", HashExtra::Text(0))?; - hash.set_ty(res.loc, FnClass::StrLit); + build_in(b"=", BstBuiltin::Eq)?; + build_in(b">", BstBuiltin::Gt)?; + build_in(b"<", BstBuiltin::Lt)?; + build_in(b"+", BstBuiltin::Plus)?; + build_in(b"-", BstBuiltin::Minus)?; + build_in(b"*", BstBuiltin::Concat)?; + build_in(b":=", BstBuiltin::Set)?; + build_in(b"add.period$", BstBuiltin::AddPeriod)?; + build_in(b"call.type$", BstBuiltin::CallType)?; + build_in(b"change.case$", BstBuiltin::ChangeCase)?; + build_in(b"chr.to.int$", BstBuiltin::ChrToInt)?; + build_in(b"cite$", BstBuiltin::Cite)?; + build_in(b"duplicate$", BstBuiltin::Duplicate)?; + build_in(b"empty$", BstBuiltin::Empty)?; + build_in(b"format.name$", BstBuiltin::FormatName)?; + build_in(b"if$", BstBuiltin::If)?; + build_in(b"int.to.chr$", BstBuiltin::IntToChr)?; + build_in(b"int.to.str$", BstBuiltin::IntToStr)?; + build_in(b"missing$", BstBuiltin::Missing)?; + build_in(b"newline$", BstBuiltin::Newline)?; + build_in(b"num.names$", BstBuiltin::NumNames)?; + build_in(b"pop$", BstBuiltin::Pop)?; + build_in(b"preamble$", BstBuiltin::Preamble)?; + build_in(b"purify$", BstBuiltin::Purify)?; + build_in(b"quote$", BstBuiltin::Quote)?; + let skip_loc = build_in(b"skip$", BstBuiltin::Skip)?; + build_in(b"stack$", BstBuiltin::Stack)?; + build_in(b"substring$", BstBuiltin::Substring)?; + build_in(b"swap$", BstBuiltin::Swap)?; + build_in(b"text.length$", BstBuiltin::TextLength)?; + build_in(b"text.prefix$", BstBuiltin::TextPrefix)?; + build_in(b"top$", BstBuiltin::Top)?; + build_in(b"type$", BstBuiltin::Type)?; + build_in(b"warning$", BstBuiltin::Warning)?; + build_in(b"while$", BstBuiltin::While)?; + build_in(b"width$", BstBuiltin::Width)?; + build_in(b"write$", BstBuiltin::Write)?; + + let res = pool.lookup_str_insert(ctx, hash, b"", HashExtra::Text)?; ctx.s_null = hash.text(res.loc); - let res = pool.lookup_str_insert(ctx, hash, b"default.type", HashExtra::Text(0))?; - hash.set_ty(res.loc, FnClass::StrLit); + let res = pool.lookup_str_insert(ctx, hash, b"default.type", HashExtra::Text)?; ctx.s_default = hash.text(res.loc); ctx.b_default = skip_loc; - pool.lookup_str_insert(ctx, hash, b"i", HashExtra::ControlSeq(0))?; - pool.lookup_str_insert(ctx, hash, b"j", HashExtra::ControlSeq(1))?; - pool.lookup_str_insert(ctx, hash, b"oe", HashExtra::ControlSeq(2))?; - pool.lookup_str_insert(ctx, hash, b"OE", HashExtra::ControlSeq(3))?; - pool.lookup_str_insert(ctx, hash, b"ae", HashExtra::ControlSeq(4))?; - pool.lookup_str_insert(ctx, hash, b"AE", HashExtra::ControlSeq(5))?; - pool.lookup_str_insert(ctx, hash, b"aa", HashExtra::ControlSeq(6))?; - pool.lookup_str_insert(ctx, hash, b"AA", HashExtra::ControlSeq(7))?; - pool.lookup_str_insert(ctx, hash, b"o", HashExtra::ControlSeq(8))?; - pool.lookup_str_insert(ctx, hash, b"O", HashExtra::ControlSeq(9))?; - pool.lookup_str_insert(ctx, hash, b"l", HashExtra::ControlSeq(10))?; - pool.lookup_str_insert(ctx, hash, b"L", HashExtra::ControlSeq(11))?; - pool.lookup_str_insert(ctx, hash, b"ss", HashExtra::ControlSeq(12))?; + pool.lookup_str_insert(ctx, hash, b"i", HashExtra::ControlSeq(ControlSeq::LowerI))?; + pool.lookup_str_insert(ctx, hash, b"j", HashExtra::ControlSeq(ControlSeq::LowerJ))?; + pool.lookup_str_insert(ctx, hash, b"oe", HashExtra::ControlSeq(ControlSeq::LowerOE))?; + pool.lookup_str_insert(ctx, hash, b"OE", HashExtra::ControlSeq(ControlSeq::UpperOE))?; + pool.lookup_str_insert(ctx, hash, b"ae", HashExtra::ControlSeq(ControlSeq::LowerAE))?; + pool.lookup_str_insert(ctx, hash, b"AE", HashExtra::ControlSeq(ControlSeq::UpperAE))?; + pool.lookup_str_insert(ctx, hash, b"aa", HashExtra::ControlSeq(ControlSeq::LowerAA))?; + pool.lookup_str_insert(ctx, hash, b"AA", HashExtra::ControlSeq(ControlSeq::UpperAA))?; + pool.lookup_str_insert(ctx, hash, b"o", HashExtra::ControlSeq(ControlSeq::LowerO))?; + pool.lookup_str_insert(ctx, hash, b"O", HashExtra::ControlSeq(ControlSeq::UpperO))?; + pool.lookup_str_insert(ctx, hash, b"l", HashExtra::ControlSeq(ControlSeq::LowerL))?; + pool.lookup_str_insert(ctx, hash, b"L", HashExtra::ControlSeq(ControlSeq::UpperL))?; + pool.lookup_str_insert(ctx, hash, b"ss", HashExtra::ControlSeq(ControlSeq::LowerSS))?; let num_fields = other.num_fields(); - let res = - pool.lookup_str_insert(ctx, hash, b"crossref", HashExtra::BstFn(num_fields as i32))?; - hash.set_ty(res.loc, FnClass::Field); + pool.lookup_str_insert( + ctx, + hash, + b"crossref", + HashExtra::BstFn(BstFn::Field(num_fields)), + )?; other.set_crossref_num(num_fields); other.set_num_fields(num_fields + 1); other.set_pre_defined_fields(num_fields + 1); let num_ent_strs = entries.num_ent_strs(); - let res = pool.lookup_str_insert( + pool.lookup_str_insert( ctx, hash, b"sort.key$", - HashExtra::BstFn(num_ent_strs as i32), + HashExtra::BstFn(BstFn::StrEntry(num_ent_strs)), )?; - hash.set_ty(res.loc, FnClass::StrEntryVar); entries.set_sort_key_num(num_ent_strs); entries.set_num_ent_strs(num_ent_strs + 1); - let res = pool.lookup_str_insert( + pool.lookup_str_insert( ctx, hash, b"entry.max$", - HashExtra::BstFn(ENT_STR_SIZE as i32), + HashExtra::BstFn(BstFn::IntGlbl(ENT_STR_SIZE as i32)), )?; - hash.set_ty(res.loc, FnClass::IntGlblVar); - let res = pool.lookup_str_insert( + pool.lookup_str_insert( ctx, hash, b"global.max$", - HashExtra::BstFn(GLOB_STR_SIZE as i32), + HashExtra::BstFn(BstFn::IntGlbl(GLOB_STR_SIZE as i32)), )?; - hash.set_ty(res.loc, FnClass::IntGlblVar); Ok(()) } @@ -479,42 +556,50 @@ pub(crate) fn add_out_pool( mod tests { use super::*; use crate::BibtexConfig; + use tectonic_bridge_core::{CoreBridgeLauncher, CoreBridgeState, Result}; + + fn with_cbs(f: impl FnOnce(&mut CoreBridgeState<'_>) -> T) -> Result { + CoreBridgeLauncher::new(&mut [], &mut []).with_global_lock(f) + } #[test] fn test_pool() { - let mut ctx = Bibtex::new(todo!(), BibtexConfig::default()); - let mut hash = HashData::new(); - let mut new_pool = StringPool::new(); - let res = new_pool - .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", StrIlk::Text) - .unwrap(); - assert!(!res.exists); - assert_eq!( - new_pool.try_get_str(hash.text(res.loc)), - Ok(b"a cool string" as &[_]) - ); - - let res2 = new_pool - .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", StrIlk::Text) - .unwrap(); - assert!(res2.exists); - assert_eq!( - new_pool.try_get_str(hash.text(res2.loc)), - Ok(b"a cool string" as &[_]) - ); - - let res3 = new_pool.lookup_str(&hash, b"a cool string", StrIlk::Text); - assert!(res3.exists); - assert_eq!( - new_pool.try_get_str(hash.text(res3.loc)), - Ok(b"a cool string" as &[_]) - ); - - let res4 = new_pool.lookup_str(&hash, b"a bad string", StrIlk::Text); - assert!(!res4.exists); - assert_eq!( - new_pool.try_get_str(hash.text(res4.loc)), - Err(LookupErr::DoesntExist) - ); + with_cbs(|cbs| { + let mut ctx = Bibtex::new(cbs, BibtexConfig::default()); + let mut hash = HashData::new(); + let mut new_pool = StringPool::new(); + let res = new_pool + .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", HashExtra::Text) + .unwrap(); + assert!(!res.exists); + assert_eq!( + new_pool.try_get_str(hash.text(res.loc)), + Ok(b"a cool string" as &[_]) + ); + + let res2 = new_pool + .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", HashExtra::Text) + .unwrap(); + assert!(res2.exists); + assert_eq!( + new_pool.try_get_str(hash.text(res2.loc)), + Ok(b"a cool string" as &[_]) + ); + + let res3 = new_pool.lookup_str(&hash, b"a cool string", StrIlk::Text); + assert!(res3.exists); + assert_eq!( + new_pool.try_get_str(hash.text(res3.loc)), + Ok(b"a cool string" as &[_]) + ); + + let res4 = new_pool.lookup_str(&hash, b"a bad string", StrIlk::Text); + assert!(!res4.exists); + assert_eq!( + new_pool.try_get_str(hash.text(res4.loc)), + Err(LookupErr::DoesntExist) + ); + }) + .unwrap() } } diff --git a/crates/engine_bibtex/src/scan.rs b/crates/engine_bibtex/src/scan.rs index dd1307fb8..86370c701 100644 --- a/crates/engine_bibtex/src/scan.rs +++ b/crates/engine_bibtex/src/scan.rs @@ -1,17 +1,17 @@ use crate::{ - bibs::{compress_bib_white, eat_bib_white_space, BibData}, + bibs::{compress_bib_white, eat_bib_white_space, BibCommand, BibData}, buffer::{BufTy, GlobalBuffer}, char_info::{IdClass, LexClass}, cite::{add_database_cite, CiteInfo}, - exec::ExecCtx, + exec::{ControlSeq, ExecCtx}, hash, - hash::{FnClass, HashData, HashExtra}, + hash::{BstFn, HashData, HashExtra}, log::{ - bib_cmd_confusion, bib_err_print, bib_id_print, bib_unbalanced_braces_print, - bib_warn_print, braces_unbalanced_complaint, bst_err_print_and_look_for_blank_line, - eat_bib_print, eat_bst_print, hash_cite_confusion, macro_warn_print, print_a_pool_str, - print_confusion, print_recursion_illegal, skip_illegal_stuff_after_token_print, - skip_token_print, skip_token_unknown_function_print, + bib_err_print, bib_id_print, bib_unbalanced_braces_print, bib_warn_print, + braces_unbalanced_complaint, bst_err_print_and_look_for_blank_line, eat_bib_print, + eat_bst_print, hash_cite_confusion, macro_warn_print, print_a_pool_str, print_confusion, + print_recursion_illegal, skip_illegal_stuff_after_token_print, skip_token_print, + skip_token_unknown_function_print, }, other::OtherData, peekable::input_ln, @@ -196,17 +196,9 @@ fn handle_char( return skip_token_print(ctx, buffers, pool); } - let res = { - let str = &buffers.buffer(BufTy::Base) - [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = - pool.lookup_str_insert(ctx, hash, str, HashExtra::Integer(token_value))?; - - if !res.exists { - hash.set_ty(res.loc, FnClass::IntLit); - } - Ok(res) - }?; + let str = &buffers.buffer(BufTy::Base) + [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; + let res = pool.lookup_str_insert(ctx, hash, str, HashExtra::Integer(token_value))?; let char = buffers.at_offset(BufTy::Base, 2); @@ -229,13 +221,9 @@ fn handle_char( return skip_token_print(ctx, buffers, pool); } - let res = { - let str = &buffers.buffer(BufTy::Base) - [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(ctx, hash, str, HashExtra::Text(0))?; - hash.set_ty(res.loc, FnClass::StrLit); - Ok(res) - }?; + let str = &buffers.buffer(BufTy::Base) + [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; + let res = pool.lookup_str_insert(ctx, hash, str, HashExtra::Text)?; buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); @@ -280,18 +268,19 @@ fn handle_char( let str = format!("'{}", ctx.impl_fn_num); - let res = { - let res = pool.lookup_str_insert(ctx, hash, str.as_bytes(), HashExtra::BstFn(0))?; + let res = pool.lookup_str_insert( + ctx, + hash, + str.as_bytes(), + HashExtra::BstFn(BstFn::Wizard(0)), + )?; - if res.exists { - ctx.write_logs("Already encountered implicit function"); - print_confusion(ctx); - return Err(BibtexError::Fatal); - } - ctx.impl_fn_num += 1; - hash.set_ty(res.loc, FnClass::Wizard); - Ok(res) - }?; + if res.exists { + ctx.write_logs("Already encountered implicit function"); + print_confusion(ctx); + return Err(BibtexError::Fatal); + } + ctx.impl_fn_num += 1; single_function.push(QUOTE_NEXT_FN); single_function.push(res.loc); @@ -365,7 +354,7 @@ pub(crate) fn scan_fn_def( single_function.push(HashData::end_of_def()); - hash.node_mut(fn_hash_loc).extra = HashExtra::BstFn(other.wiz_func_len() as i32); + hash.node_mut(fn_hash_loc).extra = HashExtra::BstFn(BstFn::Wizard(other.wiz_func_len())); for ptr in single_function { other.push_wiz_func(ptr); @@ -560,7 +549,7 @@ fn scan_a_field_token_and_eat_white( bibs: &mut BibData, store_field: bool, at_bib_command: bool, - command_num: i32, + command: BibCommand, cur_macro_loc: HashPointer, right_outer_delim: ASCIICode, ) -> Result { @@ -629,9 +618,7 @@ fn scan_a_field_token_and_eat_white( let res = pool.lookup_str(hash, str, StrIlk::Macro); let mut store_token = true; - if at_bib_command && command_num == 2 /* n_bib_string */ && res.loc == - cur_macro_loc - { + if at_bib_command && command == BibCommand::String && res.loc == cur_macro_loc { store_token = false; macro_warn_print(ctx, buffers); ctx.write_logs("used in its own definition\n"); @@ -646,7 +633,9 @@ fn scan_a_field_token_and_eat_white( } if store_token { - let strnum = hash.ilk_info(res.loc) as StrNumber; + let HashExtra::Macro(strnum) = hash.node(res.loc).extra else { + panic!("Macro lookup didn't have Macro extra"); + }; let mut str = pool.get_str(strnum); if buffers.offset(BufTy::Ex, 1) == 0 @@ -708,7 +697,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( cites: &mut CiteInfo, store_field: bool, at_bib_command: bool, - command_num: i32, + command: BibCommand, cite_out: Option<&mut CiteNumber>, cur_macro_loc: HashPointer, right_outer_delim: ASCIICode, @@ -724,7 +713,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( bibs, store_field, at_bib_command, - command_num, + command, cur_macro_loc, right_outer_delim, )? { @@ -743,7 +732,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( bibs, store_field, at_bib_command, - command_num, + command, cur_macro_loc, right_outer_delim, )? { @@ -769,36 +758,31 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( }; let str = &buffers.buffer(BufTy::Ex)[ex_buf_xptr..buffers.offset(BufTy::Ex, 1)]; - let res = { - let res = pool.lookup_str_insert(ctx, hash, str, HashExtra::Text(0))?; - - hash.set_ty(res.loc, FnClass::StrLit); - - Ok(res) - }?; + let res = pool.lookup_str_insert(ctx, hash, str, HashExtra::Text)?; if at_bib_command { - match command_num { - 1 => bibs.add_preamble(hash.text(res.loc)), - 2 => hash.node_mut(cur_macro_loc).extra = HashExtra::BibCommand(hash.text(res.loc)), - _ => { - // TODO: Replace command_num with an enum - bib_cmd_confusion(ctx); - return Err(BibtexError::Fatal); + match command { + // TODO: Should this be `unreachable!`? This way will cover errors, but also shouldn't misbehave + BibCommand::Comment => (), + BibCommand::Preamble => bibs.add_preamble(hash.text(res.loc)), + BibCommand::String => { + hash.node_mut(cur_macro_loc).extra = HashExtra::Macro(hash.text(res.loc)) } } } else { - let field_ptr = - cites.entry_ptr() * other.num_fields() + hash.ilk_info(field_name_loc) as usize; + let HashExtra::BstFn(BstFn::Field(field)) = hash.node(field_name_loc).extra else { + panic!("field_name_loc wasn't a BstFn::Field"); + }; + + let field_ptr = cites.entry_ptr() * other.num_fields() + field; if field_ptr >= other.max_fields() { ctx.write_logs("field_info index is out of range"); print_confusion(ctx); return Err(BibtexError::Fatal); } - if other.field(field_ptr) != 0 /* missing */ - { + if other.field(field_ptr) != 0 { ctx.write_logs("Warning--I'm ignoring "); print_a_pool_str(ctx, cites.get_cite(cites.entry_ptr()), pool)?; ctx.write_logs("'s extra \""); @@ -807,9 +791,7 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( bib_warn_print(ctx, pool, bibs)?; } else { other.set_field(field_ptr, hash.text(res.loc)); - if hash.ilk_info(field_name_loc) as usize == other.crossref_num() - && !ctx.all_entries - { + if field == other.crossref_num() && !ctx.all_entries { let end = buffers.offset(BufTy::Ex, 1); // Move Ex to Out, at the same position buffers.copy_within( @@ -825,11 +807,16 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( if let Some(cite_out) = cite_out { *cite_out = lc_res.loc; } - let cite_loc = hash.ilk_info(lc_res.loc) as usize; + let HashExtra::LcCite(cite_loc) = hash.node(lc_res.loc).extra else { + panic!("LcCite lookup didn't have LcCite extra"); + }; if lc_res.exists { - if hash.ilk_info(cite_loc) as usize >= cites.old_num_cites() { - let old_info = hash.ilk_info(cite_loc) as usize; - cites.set_info(old_info, old_info + 1); + let HashExtra::Cite(cite) = hash.node(cite_loc).extra else { + panic!("LcCite location didn't have Cite extra"); + }; + + if cite >= cites.old_num_cites() { + cites.set_info(cite, cite + 1); } } else { let str = @@ -847,8 +834,12 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( c_res.loc, lc_res.loc, ); + + let HashExtra::Cite(cite) = hash.node(c_res.loc).extra else { + panic!("Cite lookup didn't have Cite extra"); + }; cites.set_ptr(new_ptr); - cites.set_info(hash.ilk_info(c_res.loc) as usize, 1); + cites.set_info(cite, 1); } } } @@ -947,18 +938,17 @@ pub(crate) fn name_scan_for_and( } pub(crate) fn von_token_found( - ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer, hash: &HashData, pool: &StringPool, name_bf_ptr: &mut BufPointer, name_bf_xptr: BufPointer, -) -> Result { +) -> bool { while *name_bf_ptr < name_bf_xptr { let char = buffers.at(BufTy::Sv, *name_bf_ptr); match char { - b'A'..=b'Z' => return Ok(false), - b'a'..=b'z' => return Ok(true), + b'A'..=b'Z' => return false, + b'a'..=b'z' => return true, b'{' => { let mut nm_brace_level = 1; *name_bf_ptr += 1; @@ -972,31 +962,46 @@ pub(crate) fn von_token_found( } let str = &buffers.buffer(BufTy::Sv)[name_bf_yptr..*name_bf_ptr]; let res = pool.lookup_str(hash, str, StrIlk::ControlSeq); - let ilk = res.exists.then(|| hash.ilk_info(res.loc)); - if let Some(ilk) = ilk { - match ilk { - 3 | 5 | 7 | 9 | 11 => return Ok(false), - 0 | 1 | 2 | 4 | 6 | 8 | 10 | 12 => return Ok(true), - _ => { - ctx.write_logs("Control-sequence hash error"); - print_confusion(ctx); - return Err(BibtexError::Fatal); + let ilk = res + .exists + .then(|| { + if let HashExtra::ControlSeq(seq) = hash.node(res.loc).extra { + Some(seq) + } else { + None } - } + }) + .flatten(); + if let Some(seq) = ilk { + return match seq { + ControlSeq::UpperOE + | ControlSeq::UpperAE + | ControlSeq::UpperAA + | ControlSeq::UpperO + | ControlSeq::UpperL => false, + ControlSeq::LowerI + | ControlSeq::LowerJ + | ControlSeq::LowerOE + | ControlSeq::LowerAE + | ControlSeq::LowerAA + | ControlSeq::LowerO + | ControlSeq::LowerL + | ControlSeq::LowerSS => true, + }; } while *name_bf_ptr < name_bf_xptr && nm_brace_level > 0 { let char = buffers.at(BufTy::Sv, *name_bf_ptr); match char { - b'A'..=b'Z' => return Ok(false), - b'a'..=b'z' => return Ok(true), + b'A'..=b'Z' => return false, + b'a'..=b'z' => return true, b'}' => nm_brace_level -= 1, b'{' => nm_brace_level += 1, _ => (), } *name_bf_ptr += 1; } - return Ok(false); + return false; } else { while nm_brace_level > 0 && *name_bf_ptr < name_bf_xptr { let char = buffers.at(BufTy::Sv, *name_bf_ptr); @@ -1014,12 +1019,11 @@ pub(crate) fn von_token_found( } } } - Ok(false) + false } #[allow(clippy::too_many_arguments)] pub(crate) fn von_name_ends_and_last_name_starts_stuff( - ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer, hash: &HashData, pool: &StringPool, @@ -1028,17 +1032,16 @@ pub(crate) fn von_name_ends_and_last_name_starts_stuff( von_end: &mut BufPointer, name_bf_ptr: &mut BufPointer, name_bf_xptr: &mut BufPointer, -) -> Result<(), BibtexError> { +) { *von_end = last_end - 1; while *von_end > von_start { *name_bf_ptr = buffers.name_tok(*von_end - 1); *name_bf_xptr = buffers.name_tok(*von_end); - if von_token_found(ctx, buffers, hash, pool, name_bf_ptr, *name_bf_xptr)? { - return Ok(()); + if von_token_found(buffers, hash, pool, name_bf_ptr, *name_bf_xptr) { + return; } *von_end -= 1; } - Ok(()) } pub(crate) fn enough_text_chars( diff --git a/tests/bibtex.rs b/tests/bibtex.rs index 53c24e7da..c8b81a1ea 100644 --- a/tests/bibtex.rs +++ b/tests/bibtex.rs @@ -112,6 +112,11 @@ fn test_colon() { .go(); } +#[test] +fn test_control_sequences() { + TestCase::new("control_seq", Some("cites")).go(); +} + #[test] fn test_empty_files() { TestCase::new(&["empty"]) diff --git a/tests/bibtex/cites/control_seq.aux b/tests/bibtex/cites/control_seq.aux new file mode 100644 index 000000000..4a89490ec --- /dev/null +++ b/tests/bibtex/cites/control_seq.aux @@ -0,0 +1,5 @@ +\relax +\citation{SequenceExample} +\bibdata{control_seq} +\bibcite{SequenceExample}{1} +\bibstyle{../plain} \ No newline at end of file diff --git a/tests/bibtex/cites/control_seq.bbl b/tests/bibtex/cites/control_seq.bbl new file mode 100644 index 000000000..b2f8d8d0c --- /dev/null +++ b/tests/bibtex/cites/control_seq.bbl @@ -0,0 +1,7 @@ +\begin{thebibliography}{1} + +\bibitem{SequenceExample} +{\i}~{\j} {\oe} {\OE} {\ae} {\AE} {\aa} {\AA} {\o} {\O}~{\l} {\L}~{\ss}. +\newblock {\em A book with many sequences}. + +\end{thebibliography} diff --git a/tests/bibtex/cites/control_seq.bib b/tests/bibtex/cites/control_seq.bib new file mode 100644 index 000000000..1675e0e40 --- /dev/null +++ b/tests/bibtex/cites/control_seq.bib @@ -0,0 +1,4 @@ +@book{SequenceExample, + title = {A book with many sequences}, + author = "{\i} {\j} {\oe} {\OE} {\ae} {\AE} {\aa} {\AA} {\o} {\O} {\l} {\L} {\ss}", +} diff --git a/tests/bibtex/cites/control_seq.blg b/tests/bibtex/cites/control_seq.blg new file mode 100644 index 000000000..7794370f2 --- /dev/null +++ b/tests/bibtex/cites/control_seq.blg @@ -0,0 +1,10 @@ +This is BibTeX, Version 0.99d +Capacity: max_strings=35307, hash_size=35307, hash_prime=30011 +The top-level auxiliary file: control_seq.aux +The style file: ../plain.bst +Database file #1: control_seq.bib +Warning--"i j oe OE ae AE a A o O l L} s" isn't a brace-balanced string for entry SequenceExample +while executing--line 1049 of file ../plain.bst +Warning--empty publisher in SequenceExample +Warning--empty year in SequenceExample +(There were 3 warnings) From 6dd89b07b133618b2be61362cc6896b319e13857 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 27 Feb 2024 17:12:30 -0800 Subject: [PATCH 15/23] Fix clippy --- crates/bridge_core/src/lib.rs | 12 ++++++++++-- crates/engine_bibtex/src/exec.rs | 4 ++-- crates/engine_bibtex/src/hash.rs | 9 ++------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/crates/bridge_core/src/lib.rs b/crates/bridge_core/src/lib.rs index a16fb30b8..a4ea06e04 100644 --- a/crates/bridge_core/src/lib.rs +++ b/crates/bridge_core/src/lib.rs @@ -1,7 +1,7 @@ // Copyright 2016-2022 the Tectonic Project // Licensed under the MIT License. -// #![deny(missing_docs)] +#![deny(missing_docs)] //! Core APIs for bridging the C and Rust portions of Tectonic’s processing //! backends. @@ -54,9 +54,11 @@ use tectonic_io_base::{ }; use tectonic_status_base::{tt_error, tt_warning, MessageKind, StatusBackend}; +/// The ID of an InputHandle, used for Rust core state #[derive(Copy, Clone, PartialEq)] pub struct InputId(*mut InputHandle); +/// The ID of an OutputHandle, used for Rust core state #[derive(Copy, Clone, PartialEq)] pub struct OutputId(*mut OutputHandle); @@ -483,6 +485,7 @@ impl<'a> CoreBridgeState<'a> { OutputId(output) } + /// Get a mutable reference to an [`OutputHandle`] associated with an [`OutputId`] pub fn get_output(&mut self, id: OutputId) -> &mut OutputHandle { self.output_handles .iter_mut() @@ -490,6 +493,7 @@ impl<'a> CoreBridgeState<'a> { .unwrap() } + /// Open a new output, provided the output name and whether it is gzipped. pub fn output_open(&mut self, name: &str, is_gz: bool) -> Option { let io = self.hooks.io(); let name = normalize_tex_path(name); @@ -515,6 +519,7 @@ impl<'a> CoreBridgeState<'a> { Some(OutputId(&mut **self.output_handles.last_mut().unwrap())) } + /// Open a new stdout output. pub fn output_open_stdout(&mut self) -> Option { let io = self.hooks.io(); @@ -557,6 +562,7 @@ impl<'a> CoreBridgeState<'a> { } } + /// Close the provided output, flushing it and performing any necessary handling. pub fn output_close(&mut self, id: OutputId) -> bool { let mut rv = false; @@ -565,7 +571,6 @@ impl<'a> CoreBridgeState<'a> { .iter() .position(|o| ptr::addr_eq(&**o, id.0)); if let Some(pos) = pos { - // TODO: How to handle removing IDs? Need a slotmap or some other form of stable ID let mut oh = self.output_handles.swap_remove(pos); if let Err(e) = oh.flush() { tt_warning!(self.status, "error when closing output {}", oh.name(); e.into()); @@ -582,6 +587,7 @@ impl<'a> CoreBridgeState<'a> { InputId(input) } + /// Get a mutable reference to an [`InputHandle`] associated with an [`InputId`] pub fn get_input(&mut self, input: InputId) -> &mut InputHandle { self.input_handles .iter_mut() @@ -589,6 +595,7 @@ impl<'a> CoreBridgeState<'a> { .unwrap() } + /// Open a new input, provided the input name, the file format, and whether it is gzipped. pub fn input_open(&mut self, name: &str, format: FileFormat, is_gz: bool) -> Option { let name = normalize_tex_path(name); @@ -677,6 +684,7 @@ impl<'a> CoreBridgeState<'a> { rhandle.ungetc(byte) } + /// Close the provided output, performing any necessary handling. pub fn input_close(&mut self, id: InputId) -> bool { let pos = self .input_handles diff --git a/crates/engine_bibtex/src/exec.rs b/crates/engine_bibtex/src/exec.rs index 4f85f9918..f822d3eea 100644 --- a/crates/engine_bibtex/src/exec.rs +++ b/crates/engine_bibtex/src/exec.rs @@ -123,13 +123,13 @@ impl<'bib, 'cbs> Deref for ExecCtx<'_, 'bib, 'cbs> { type Target = Bibtex<'bib, 'cbs>; fn deref(&self) -> &Self::Target { - &self.glbl_ctx + self.glbl_ctx } } impl DerefMut for ExecCtx<'_, '_, '_> { fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.glbl_ctx + self.glbl_ctx } } diff --git a/crates/engine_bibtex/src/hash.rs b/crates/engine_bibtex/src/hash.rs index e9992fd06..a9579f249 100644 --- a/crates/engine_bibtex/src/hash.rs +++ b/crates/engine_bibtex/src/hash.rs @@ -113,8 +113,9 @@ pub(crate) enum BstFn { StrGlbl(usize), } -#[derive(Clone, Debug)] +#[derive(Clone, Default, Debug)] pub enum HashExtra { + #[default] Text, Integer(i32), AuxCommand(AuxCommand), @@ -152,12 +153,6 @@ impl HashExtra { } } -impl Default for HashExtra { - fn default() -> Self { - HashExtra::Text - } -} - #[derive(Clone, Default, Debug)] pub struct HashNode { next: HashPointer, From 0acb0d1da0bde4168e249c79c2293fc2d9abcf3a Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 27 Feb 2024 21:44:06 -0800 Subject: [PATCH 16/23] Fix multi-file logging, add test --- crates/engine_bibtex/src/bibs.rs | 6 +++--- crates/engine_bibtex/src/bst.rs | 11 ++++++----- crates/engine_bibtex/src/log.rs | 6 +++--- tests/bibtex.rs | 5 +++++ tests/bibtex/cites/multi_file.aux | 7 +++++++ tests/bibtex/cites/multi_file.bbl | 13 +++++++++++++ tests/bibtex/cites/multi_file.blg | 6 ++++++ tests/bibtex/cites/multi_file_1.bib | 6 ++++++ tests/bibtex/cites/multi_file_2.bib | 6 ++++++ 9 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 tests/bibtex/cites/multi_file.aux create mode 100644 tests/bibtex/cites/multi_file.bbl create mode 100644 tests/bibtex/cites/multi_file.blg create mode 100644 tests/bibtex/cites/multi_file_1.bib create mode 100644 tests/bibtex/cites/multi_file_2.bib diff --git a/crates/engine_bibtex/src/bibs.rs b/crates/engine_bibtex/src/bibs.rs index 0206e22ac..033e71107 100644 --- a/crates/engine_bibtex/src/bibs.rs +++ b/crates/engine_bibtex/src/bibs.rs @@ -35,11 +35,11 @@ impl BibData { } pub fn top_file(&self) -> &File { - self.bibs.last().unwrap() + self.bibs.first().unwrap() } pub fn top_file_mut(&mut self) -> &mut File { - self.bibs.last_mut().unwrap() + self.bibs.first_mut().unwrap() } pub fn push_file(&mut self, file: File) { @@ -47,7 +47,7 @@ impl BibData { } pub fn pop_file(&mut self) -> File { - self.bibs.pop().unwrap() + self.bibs.remove(0) } pub fn add_preamble(&mut self, s: StrNumber) { diff --git a/crates/engine_bibtex/src/bst.rs b/crates/engine_bibtex/src/bst.rs index 5733133c0..daa8ed046 100644 --- a/crates/engine_bibtex/src/bst.rs +++ b/crates/engine_bibtex/src/bst.rs @@ -519,13 +519,14 @@ fn bst_read_command( } ctx.read_performed = true; - while globals.bibs.len() != 0 { + for idx in 0..globals.bibs.len() { + let file = globals.bibs.top_file(); if ctx.config.verbose { - ctx.write_logs(&format!("Database file #{}: ", globals.bibs.len())); - print_bib_name(ctx, globals.pool, globals.bibs.top_file().name)?; + ctx.write_logs(&format!("Database file #{}: ", idx + 1)); + print_bib_name(ctx, globals.pool, file.name)?; } else { - ctx.write_log_file(&format!("Database file #{}: ", globals.bibs.len())); - log_pr_bib_name(ctx, globals.bibs, globals.pool)?; + ctx.write_log_file(&format!("Database file #{}: ", idx + 1)); + log_pr_bib_name(ctx, globals.pool, file.name)?; } globals diff --git a/crates/engine_bibtex/src/log.rs b/crates/engine_bibtex/src/log.rs index 9cc02952d..7331f1cec 100644 --- a/crates/engine_bibtex/src/log.rs +++ b/crates/engine_bibtex/src/log.rs @@ -248,12 +248,12 @@ pub(crate) fn print_bib_name( pub(crate) fn log_pr_bib_name( ctx: &mut Bibtex<'_, '_>, - bibs: &BibData, pool: &StringPool, + name: StrNumber, ) -> Result<(), BibtexError> { - out_pool_str(ctx, pool, bibs.top_file().name)?; + out_pool_str(ctx, pool, name)?; let res = pool - .try_get_str(bibs.top_file().name) + .try_get_str(name) .map(|str| str.ends_with(b".bib")) .map_err(|_| BibtexError::Fatal)?; if !res { diff --git a/tests/bibtex.rs b/tests/bibtex.rs index c8b81a1ea..8d0d88491 100644 --- a/tests/bibtex.rs +++ b/tests/bibtex.rs @@ -117,6 +117,11 @@ fn test_control_sequences() { TestCase::new("control_seq", Some("cites")).go(); } +#[test] +fn test_multi_bib() { + TestCase::new("multi_file", Some("cites")).go(); +} + #[test] fn test_empty_files() { TestCase::new(&["empty"]) diff --git a/tests/bibtex/cites/multi_file.aux b/tests/bibtex/cites/multi_file.aux new file mode 100644 index 000000000..fa40a30cc --- /dev/null +++ b/tests/bibtex/cites/multi_file.aux @@ -0,0 +1,7 @@ +\relax +\citation{Nobody01} +\citation{Nobody02} +\bibdata{multi_file_1,multi_file_2} +\bibcite{Nobody01}{1} +\bibcite{Nobody02}{1} +\bibstyle{../plain} \ No newline at end of file diff --git a/tests/bibtex/cites/multi_file.bbl b/tests/bibtex/cites/multi_file.bbl new file mode 100644 index 000000000..621f3dfef --- /dev/null +++ b/tests/bibtex/cites/multi_file.bbl @@ -0,0 +1,13 @@ +\begin{thebibliography}{1} + +\bibitem{Nobody01} +Nobody Sr. +\newblock {\em A book}. +\newblock Nobody, 2024. + +\bibitem{Nobody02} +Nobody Sr. +\newblock {\em A book}. +\newblock Nobody, 2024. + +\end{thebibliography} diff --git a/tests/bibtex/cites/multi_file.blg b/tests/bibtex/cites/multi_file.blg new file mode 100644 index 000000000..730024c1e --- /dev/null +++ b/tests/bibtex/cites/multi_file.blg @@ -0,0 +1,6 @@ +This is BibTeX, Version 0.99d +Capacity: max_strings=35307, hash_size=35307, hash_prime=30011 +The top-level auxiliary file: multi_file.aux +The style file: ../plain.bst +Database file #1: multi_file_1.bib +Database file #2: multi_file_2.bib diff --git a/tests/bibtex/cites/multi_file_1.bib b/tests/bibtex/cites/multi_file_1.bib new file mode 100644 index 000000000..5e60c166b --- /dev/null +++ b/tests/bibtex/cites/multi_file_1.bib @@ -0,0 +1,6 @@ +@book{Nobody02, + title = "A book", + author = "Nobody Sr.", + publisher = "Nobody", + year = 2024, +} diff --git a/tests/bibtex/cites/multi_file_2.bib b/tests/bibtex/cites/multi_file_2.bib new file mode 100644 index 000000000..66c1c003d --- /dev/null +++ b/tests/bibtex/cites/multi_file_2.bib @@ -0,0 +1,6 @@ +@book{Nobody01, + title = "A book", + author = "Nobody Sr.", + publisher = "Nobody", + year = 2024, +} From 69f0f45c972d9b0837e2877af97db44af7f5dbf7 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 27 Feb 2024 22:43:52 -0800 Subject: [PATCH 17/23] Comment out pool test for now --- crates/engine_bibtex/src/pool.rs | 94 ++++++++++++++++---------------- 1 file changed, 46 insertions(+), 48 deletions(-) diff --git a/crates/engine_bibtex/src/pool.rs b/crates/engine_bibtex/src/pool.rs index bdf30115e..bf324bd3c 100644 --- a/crates/engine_bibtex/src/pool.rs +++ b/crates/engine_bibtex/src/pool.rs @@ -554,52 +554,50 @@ pub(crate) fn add_out_pool( #[cfg(test)] mod tests { - use super::*; - use crate::BibtexConfig; - use tectonic_bridge_core::{CoreBridgeLauncher, CoreBridgeState, Result}; - - fn with_cbs(f: impl FnOnce(&mut CoreBridgeState<'_>) -> T) -> Result { - CoreBridgeLauncher::new(&mut [], &mut []).with_global_lock(f) - } - - #[test] - fn test_pool() { - with_cbs(|cbs| { - let mut ctx = Bibtex::new(cbs, BibtexConfig::default()); - let mut hash = HashData::new(); - let mut new_pool = StringPool::new(); - let res = new_pool - .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", HashExtra::Text) - .unwrap(); - assert!(!res.exists); - assert_eq!( - new_pool.try_get_str(hash.text(res.loc)), - Ok(b"a cool string" as &[_]) - ); - - let res2 = new_pool - .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", HashExtra::Text) - .unwrap(); - assert!(res2.exists); - assert_eq!( - new_pool.try_get_str(hash.text(res2.loc)), - Ok(b"a cool string" as &[_]) - ); - - let res3 = new_pool.lookup_str(&hash, b"a cool string", StrIlk::Text); - assert!(res3.exists); - assert_eq!( - new_pool.try_get_str(hash.text(res3.loc)), - Ok(b"a cool string" as &[_]) - ); - - let res4 = new_pool.lookup_str(&hash, b"a bad string", StrIlk::Text); - assert!(!res4.exists); - assert_eq!( - new_pool.try_get_str(hash.text(res4.loc)), - Err(LookupErr::DoesntExist) - ); - }) - .unwrap() - } + // use super::*; + // use crate::BibtexConfig; + // use tectonic_bridge_core::{CoreBridgeLauncher, CoreBridgeState, DriverHooks, MinimalDriver}; + + // TODO: Create context without backend? Use custom backend-like type? + // Implement the relevant interfaces ourself? + // #[test] + // fn test_pool() { + // with_cbs(|cbs| { + // let mut ctx = Bibtex::new(cbs, BibtexConfig::default()); + // let mut hash = HashData::new(); + // let mut new_pool = StringPool::new(); + // let res = new_pool + // .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", HashExtra::Text) + // .unwrap(); + // assert!(!res.exists); + // assert_eq!( + // new_pool.try_get_str(hash.text(res.loc)), + // Ok(b"a cool string" as &[_]) + // ); + // + // let res2 = new_pool + // .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", HashExtra::Text) + // .unwrap(); + // assert!(res2.exists); + // assert_eq!( + // new_pool.try_get_str(hash.text(res2.loc)), + // Ok(b"a cool string" as &[_]) + // ); + // + // let res3 = new_pool.lookup_str(&hash, b"a cool string", StrIlk::Text); + // assert!(res3.exists); + // assert_eq!( + // new_pool.try_get_str(hash.text(res3.loc)), + // Ok(b"a cool string" as &[_]) + // ); + // + // let res4 = new_pool.lookup_str(&hash, b"a bad string", StrIlk::Text); + // assert!(!res4.exists); + // assert_eq!( + // new_pool.try_get_str(hash.text(res4.loc)), + // Err(LookupErr::DoesntExist) + // ); + // }) + // .unwrap() + // } } From effef64116935de4e483a0f036eb073807086a49 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 7 Mar 2024 14:38:41 -0800 Subject: [PATCH 18/23] Fix control sequence bug --- crates/engine_bibtex/src/exec.rs | 2 +- tests/bibtex/cites/control_seq.blg | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/engine_bibtex/src/exec.rs b/crates/engine_bibtex/src/exec.rs index f822d3eea..5c7de9fdd 100644 --- a/crates/engine_bibtex/src/exec.rs +++ b/crates/engine_bibtex/src/exec.rs @@ -1786,7 +1786,7 @@ fn interp_purify( | ControlSeq::UpperOE | ControlSeq::LowerAE | ControlSeq::UpperAE - | ControlSeq::UpperL => { + | ControlSeq::LowerSS => { scratch[write_idx] = scratch[old_idx + 1]; write_idx += 1; } diff --git a/tests/bibtex/cites/control_seq.blg b/tests/bibtex/cites/control_seq.blg index 7794370f2..1797d8484 100644 --- a/tests/bibtex/cites/control_seq.blg +++ b/tests/bibtex/cites/control_seq.blg @@ -3,8 +3,6 @@ Capacity: max_strings=35307, hash_size=35307, hash_prime=30011 The top-level auxiliary file: control_seq.aux The style file: ../plain.bst Database file #1: control_seq.bib -Warning--"i j oe OE ae AE a A o O l L} s" isn't a brace-balanced string for entry SequenceExample -while executing--line 1049 of file ../plain.bst Warning--empty publisher in SequenceExample Warning--empty year in SequenceExample -(There were 3 warnings) +(There were 2 warnings) From 9b49d01a87c4d070a3b9620a08034b8eca7f94a0 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 7 Mar 2024 15:14:25 -0800 Subject: [PATCH 19/23] Clean up some clippy annotations --- crates/engine_bibtex/src/bibs.rs | 88 +++--- crates/engine_bibtex/src/bst.rs | 10 +- crates/engine_bibtex/src/exec.rs | 2 - crates/engine_bibtex/src/log.rs | 22 +- crates/engine_bibtex/src/pool.rs | 1 - crates/engine_bibtex/src/scan.rs | 448 ++++++++++++++++++------------- 6 files changed, 301 insertions(+), 270 deletions(-) diff --git a/crates/engine_bibtex/src/bibs.rs b/crates/engine_bibtex/src/bibs.rs index 033e71107..67ea6285a 100644 --- a/crates/engine_bibtex/src/bibs.rs +++ b/crates/engine_bibtex/src/bibs.rs @@ -93,7 +93,7 @@ pub(crate) fn compress_bib_white( buffers: &mut GlobalBuffer, pool: &StringPool, bibs: &mut BibData, - at_bib_command: bool, + bib_command: Option, ) -> Result { if buffers.offset(BufTy::Ex, 1) == buffers.len() { ctx.write_log_file("Field filled up at ' ', reallocating.\n"); @@ -110,7 +110,7 @@ pub(crate) fn compress_bib_white( let res = !input_ln(ctx.engine, &mut bibs.top_file_mut().file, buffers); if res { - return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command).map(|_| false); + return eat_bib_print(ctx, buffers, pool, bibs, bib_command).map(|_| false); } bibs.top_file_mut().line += 1; @@ -131,7 +131,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( cur_macro_loc: &mut HashPointer, field_name_loc: &mut HashPointer, ) -> Result<(), BibtexError> { - let mut at_bib_command = false; + let mut bib_command = None; let mut init = globals.buffers.init(BufTy::Base); while !Scan::new().chars(&[b'@']).scan_till(globals.buffers, init) { @@ -164,7 +164,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -180,7 +180,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -201,7 +201,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( panic!("BibCommand lookup didn't have BibCommand extra"); }; - at_bib_command = true; + bib_command = Some(cmd); match cmd { BibCommand::Comment => (), BibCommand::Preamble => { @@ -211,7 +211,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -227,7 +227,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.bibs, b'{', b'(', - at_bib_command, + bib_command, )?; return Ok(()); } @@ -245,22 +245,16 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } if !scan_and_store_the_field_value_and_eat_white( ctx, - globals.buffers, - globals.hash, - globals.pool, - globals.bibs, - globals.other, - globals.cites, + globals, true, - at_bib_command, - cmd, + bib_command, Some(&mut lc_cite_loc), *cur_macro_loc, right_outer_delim, @@ -279,7 +273,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -296,7 +290,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -312,7 +306,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.bibs, b'{', b'(', - at_bib_command, + bib_command, )?; return Ok(()); } @@ -330,7 +324,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -346,7 +340,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -374,7 +368,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -385,7 +379,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -402,22 +396,16 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } if !scan_and_store_the_field_value_and_eat_white( ctx, - globals.buffers, - globals.hash, - globals.pool, - globals.bibs, - globals.other, - globals.cites, + globals, true, - at_bib_command, - cmd, + bib_command, Some(&mut lc_cite_loc), *cur_macro_loc, right_outer_delim, @@ -436,7 +424,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -470,7 +458,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -486,7 +474,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.bibs, b'{', b'(', - at_bib_command, + bib_command, )?; return Ok(()); } @@ -502,7 +490,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -618,7 +606,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )); } None @@ -695,7 +683,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -709,7 +697,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.bibs, b',', right_outer_delim, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -724,7 +712,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -744,7 +732,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -774,7 +762,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -785,7 +773,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } @@ -800,22 +788,16 @@ pub(crate) fn get_bib_command_or_entry_and_process( globals.buffers, globals.pool, globals.bibs, - at_bib_command, + bib_command, )?; return Ok(()); } if !scan_and_store_the_field_value_and_eat_white( ctx, - globals.buffers, - globals.hash, - globals.pool, - globals.bibs, - globals.other, - globals.cites, + globals, store_field, - at_bib_command, - BibCommand::Comment, + bib_command, None, *cur_macro_loc, right_outer_delim, diff --git a/crates/engine_bibtex/src/bst.rs b/crates/engine_bibtex/src/bst.rs index daa8ed046..3e7470953 100644 --- a/crates/engine_bibtex/src/bst.rs +++ b/crates/engine_bibtex/src/bst.rs @@ -285,15 +285,7 @@ fn bst_function_command( globals .buffers .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); - scan_fn_def( - ctx, - globals.buffers, - globals.hash, - globals.pool, - globals.other, - res.loc, - res.loc, - )?; + scan_fn_def(ctx, globals, res.loc, res.loc)?; Ok(()) } diff --git a/crates/engine_bibtex/src/exec.rs b/crates/engine_bibtex/src/exec.rs index 5c7de9fdd..a7f3db592 100644 --- a/crates/engine_bibtex/src/exec.rs +++ b/crates/engine_bibtex/src/exec.rs @@ -921,8 +921,6 @@ fn interp_gets( } }; - // TODO: Merge into match below - match &hash.node(f1).extra { HashExtra::BstFn(BstFn::IntEntry(_) | BstFn::StrEntry(_)) if !ctx.mess_with_entries => { bst_cant_mess_with_entries_print(ctx, pool, cites)?; diff --git a/crates/engine_bibtex/src/log.rs b/crates/engine_bibtex/src/log.rs index 7331f1cec..a65284566 100644 --- a/crates/engine_bibtex/src/log.rs +++ b/crates/engine_bibtex/src/log.rs @@ -1,6 +1,6 @@ use crate::{ auxi::AuxData, - bibs::BibData, + bibs::{BibCommand, BibData}, buffer::{BufTy, GlobalBuffer}, char_info::LexClass, cite::CiteInfo, @@ -343,13 +343,13 @@ pub(crate) fn bib_err_print( buffers: &GlobalBuffer, pool: &StringPool, bibs: &BibData, - at_bib_command: bool, + bib_command: Option, ) -> Result<(), BibtexError> { ctx.write_logs("-"); bib_ln_num_print(ctx, pool, bibs)?; print_bad_input_line(ctx, buffers); print_skipping_whatever_remains(ctx); - if at_bib_command { + if bib_command.is_some() { ctx.write_logs("command\n"); } else { ctx.write_logs("entry\n"); @@ -372,10 +372,10 @@ pub(crate) fn eat_bib_print( buffers: &GlobalBuffer, pool: &StringPool, bibs: &BibData, - at_bib_command: bool, + bib_command: Option, ) -> Result<(), BibtexError> { ctx.write_logs("Illegal end of database file"); - bib_err_print(ctx, buffers, pool, bibs, at_bib_command) + bib_err_print(ctx, buffers, pool, bibs, bib_command) } pub(crate) fn bib_one_of_two_print( @@ -385,13 +385,13 @@ pub(crate) fn bib_one_of_two_print( bibs: &BibData, char1: ASCIICode, char2: ASCIICode, - at_bib_command: bool, + bib_command: Option, ) -> Result<(), BibtexError> { ctx.write_logs(&format!( "I was expecting a `{}' or a `{}'", char1 as char, char2 as char )); - bib_err_print(ctx, buffers, pool, bibs, at_bib_command) + bib_err_print(ctx, buffers, pool, bibs, bib_command) } pub(crate) fn bib_equals_sign_print( @@ -399,10 +399,10 @@ pub(crate) fn bib_equals_sign_print( buffers: &GlobalBuffer, pool: &StringPool, bibs: &BibData, - at_bib_command: bool, + bib_command: Option, ) -> Result<(), BibtexError> { ctx.write_logs("I was expecting an \"=\""); - bib_err_print(ctx, buffers, pool, bibs, at_bib_command) + bib_err_print(ctx, buffers, pool, bibs, bib_command) } pub(crate) fn bib_unbalanced_braces_print( @@ -410,10 +410,10 @@ pub(crate) fn bib_unbalanced_braces_print( buffers: &GlobalBuffer, pool: &StringPool, bibs: &BibData, - at_bib_command: bool, + bib_command: Option, ) -> Result<(), BibtexError> { ctx.write_logs("Unbalanced braces"); - bib_err_print(ctx, buffers, pool, bibs, at_bib_command) + bib_err_print(ctx, buffers, pool, bibs, bib_command) } pub(crate) fn macro_warn_print(ctx: &mut Bibtex<'_, '_>, buffers: &GlobalBuffer) { diff --git a/crates/engine_bibtex/src/pool.rs b/crates/engine_bibtex/src/pool.rs index bf324bd3c..dd049b60e 100644 --- a/crates/engine_bibtex/src/pool.rs +++ b/crates/engine_bibtex/src/pool.rs @@ -255,7 +255,6 @@ impl StringPool { self.make_string(ctx) } - #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize { self.strings.len() } diff --git a/crates/engine_bibtex/src/scan.rs b/crates/engine_bibtex/src/scan.rs index 86370c701..99c950af5 100644 --- a/crates/engine_bibtex/src/scan.rs +++ b/crates/engine_bibtex/src/scan.rs @@ -13,11 +13,10 @@ use crate::{ print_recursion_illegal, skip_illegal_stuff_after_token_print, skip_token_print, skip_token_unknown_function_print, }, - other::OtherData, peekable::input_ln, pool::StringPool, - ASCIICode, Bibtex, BibtexError, BufPointer, CiteNumber, FnDefLoc, HashPointer, StrIlk, - StrNumber, + ASCIICode, Bibtex, BibtexError, BufPointer, CiteNumber, FnDefLoc, GlobalItems, HashPointer, + StrIlk, StrNumber, }; pub(crate) const QUOTE_NEXT_FN: usize = hash::HASH_BASE - 1; @@ -175,13 +174,9 @@ pub(crate) fn eat_bst_white_space(ctx: &mut Bibtex<'_, '_>, buffers: &mut Global } } -#[allow(clippy::too_many_arguments)] fn handle_char( ctx: &mut Bibtex<'_, '_>, - buffers: &mut GlobalBuffer, - hash: &mut HashData, - pool: &mut StringPool, - other: &mut OtherData, + globals: &mut GlobalItems<'_>, single_function: &mut Vec, wiz_loc: HashPointer, char: ASCIICode, @@ -189,88 +184,106 @@ fn handle_char( match char { b'#' => { let mut token_value = 0; - buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); + globals + .buffers + .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); - if !scan_integer(buffers, &mut token_value) { + if !scan_integer(globals.buffers, &mut token_value) { ctx.write_logs("Illegal integer in integer literal"); - return skip_token_print(ctx, buffers, pool); + return skip_token_print(ctx, globals.buffers, globals.pool); } - let str = &buffers.buffer(BufTy::Base) - [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(ctx, hash, str, HashExtra::Integer(token_value))?; + let str = &globals.buffers.buffer(BufTy::Base) + [globals.buffers.offset(BufTy::Base, 1)..globals.buffers.offset(BufTy::Base, 2)]; + let res = globals.pool.lookup_str_insert( + ctx, + globals.hash, + str, + HashExtra::Integer(token_value), + )?; - let char = buffers.at_offset(BufTy::Base, 2); + let char = globals.buffers.at_offset(BufTy::Base, 2); - if buffers.offset(BufTy::Base, 2) < buffers.init(BufTy::Base) + if globals.buffers.offset(BufTy::Base, 2) < globals.buffers.init(BufTy::Base) && LexClass::of(char) != LexClass::Whitespace && char != b'}' && char != b'%' { - return skip_illegal_stuff_after_token_print(ctx, buffers, pool); + return skip_illegal_stuff_after_token_print(ctx, globals.buffers, globals.pool); } single_function.push(res.loc); } b'"' => { - buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); + globals + .buffers + .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); - let init = buffers.init(BufTy::Base); - if !Scan::new().chars(&[b'"']).scan_till(buffers, init) { + let init = globals.buffers.init(BufTy::Base); + if !Scan::new().chars(&[b'"']).scan_till(globals.buffers, init) { ctx.write_logs("No `\"` to end string literal"); - return skip_token_print(ctx, buffers, pool); + return skip_token_print(ctx, globals.buffers, globals.pool); } - let str = &buffers.buffer(BufTy::Base) - [buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2)]; - let res = pool.lookup_str_insert(ctx, hash, str, HashExtra::Text)?; + let str = &globals.buffers.buffer(BufTy::Base) + [globals.buffers.offset(BufTy::Base, 1)..globals.buffers.offset(BufTy::Base, 2)]; + let res = globals + .pool + .lookup_str_insert(ctx, globals.hash, str, HashExtra::Text)?; - buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); + globals + .buffers + .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); - let char = buffers.at_offset(BufTy::Base, 2); + let char = globals.buffers.at_offset(BufTy::Base, 2); - if buffers.offset(BufTy::Base, 2) < buffers.init(BufTy::Base) + if globals.buffers.offset(BufTy::Base, 2) < globals.buffers.init(BufTy::Base) && LexClass::of(char) != LexClass::Whitespace && char != b'}' && char != b'%' { - return skip_illegal_stuff_after_token_print(ctx, buffers, pool); + return skip_illegal_stuff_after_token_print(ctx, globals.buffers, globals.pool); } single_function.push(res.loc); } b'\'' => { - buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); + globals + .buffers + .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); - let init = buffers.init(BufTy::Base); + let init = globals.buffers.init(BufTy::Base); Scan::new() .chars(b"}%") .class(LexClass::Whitespace) - .scan_till(buffers, init); + .scan_till(globals.buffers, init); - let range = buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2); - buffers.buffer_mut(BufTy::Base)[range.clone()].make_ascii_lowercase(); + let range = + globals.buffers.offset(BufTy::Base, 1)..globals.buffers.offset(BufTy::Base, 2); + globals.buffers.buffer_mut(BufTy::Base)[range.clone()].make_ascii_lowercase(); - let str = &buffers.buffer(BufTy::Base)[range]; - let res = pool.lookup_str(hash, str, StrIlk::BstFn); + let str = &globals.buffers.buffer(BufTy::Base)[range]; + let res = globals.pool.lookup_str(globals.hash, str, StrIlk::BstFn); if !res.exists { - return skip_token_unknown_function_print(ctx, buffers, pool); + return skip_token_unknown_function_print(ctx, globals.buffers, globals.pool); } else if res.loc == wiz_loc { - return print_recursion_illegal(ctx, buffers, pool); + return print_recursion_illegal(ctx, globals.buffers, globals.pool); } single_function.push(QUOTE_NEXT_FN); single_function.push(res.loc); } b'{' => { - buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); + globals + .buffers + .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); let str = format!("'{}", ctx.impl_fn_num); - let res = pool.lookup_str_insert( + let res = globals.pool.lookup_str_insert( ctx, - hash, + globals.hash, str.as_bytes(), HashExtra::BstFn(BstFn::Wizard(0)), )?; @@ -285,25 +298,26 @@ fn handle_char( single_function.push(QUOTE_NEXT_FN); single_function.push(res.loc); - scan_fn_def(ctx, buffers, hash, pool, other, res.loc, wiz_loc)?; + scan_fn_def(ctx, globals, res.loc, wiz_loc)?; } _ => { - let init = buffers.init(BufTy::Base); + let init = globals.buffers.init(BufTy::Base); Scan::new() .chars(b"}%") .class(LexClass::Whitespace) - .scan_till(buffers, init); + .scan_till(globals.buffers, init); - let range = buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2); + let range = + globals.buffers.offset(BufTy::Base, 1)..globals.buffers.offset(BufTy::Base, 2); - buffers.buffer_mut(BufTy::Base)[range.clone()].make_ascii_lowercase(); + globals.buffers.buffer_mut(BufTy::Base)[range.clone()].make_ascii_lowercase(); - let str = &buffers.buffer(BufTy::Base)[range]; - let res = pool.lookup_str(hash, str, StrIlk::BstFn); + let str = &globals.buffers.buffer(BufTy::Base)[range]; + let res = globals.pool.lookup_str(globals.hash, str, StrIlk::BstFn); if !res.exists { - return skip_token_unknown_function_print(ctx, buffers, pool); + return skip_token_unknown_function_print(ctx, globals.buffers, globals.pool); } else if res.loc == wiz_loc { - return print_recursion_illegal(ctx, buffers, pool); + return print_recursion_illegal(ctx, globals.buffers, globals.pool); } single_function.push(res.loc); @@ -314,53 +328,44 @@ fn handle_char( pub(crate) fn scan_fn_def( ctx: &mut Bibtex<'_, '_>, - buffers: &mut GlobalBuffer, - hash: &mut HashData, - pool: &mut StringPool, - other: &mut OtherData, + globals: &mut GlobalItems<'_>, fn_hash_loc: HashPointer, wiz_loc: HashPointer, ) -> Result<(), BibtexError> { let mut single_function = Vec::new(); - if !eat_bst_white_space(ctx, buffers) { + if !eat_bst_white_space(ctx, globals.buffers) { eat_bst_print(ctx); ctx.write_logs("function"); - bst_err_print_and_look_for_blank_line(ctx, buffers, pool)?; + bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); } - let mut char = buffers.at_offset(BufTy::Base, 2); + let mut char = globals.buffers.at_offset(BufTy::Base, 2); while char != b'}' { - handle_char( - ctx, - buffers, - hash, - pool, - other, - &mut single_function, - wiz_loc, - char, - )?; - - if !eat_bst_white_space(ctx, buffers) { + handle_char(ctx, globals, &mut single_function, wiz_loc, char)?; + + if !eat_bst_white_space(ctx, globals.buffers) { eat_bst_print(ctx); ctx.write_logs("function"); - return bst_err_print_and_look_for_blank_line(ctx, buffers, pool); + return bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool); } - char = buffers.at_offset(BufTy::Base, 2); + char = globals.buffers.at_offset(BufTy::Base, 2); } single_function.push(HashData::end_of_def()); - hash.node_mut(fn_hash_loc).extra = HashExtra::BstFn(BstFn::Wizard(other.wiz_func_len())); + globals.hash.node_mut(fn_hash_loc).extra = + HashExtra::BstFn(BstFn::Wizard(globals.other.wiz_func_len())); for ptr in single_function { - other.push_wiz_func(ptr); + globals.other.push_wiz_func(ptr); } - buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); + globals + .buffers + .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); Ok(()) } @@ -371,14 +376,14 @@ fn scan_balanced_braces( pool: &StringPool, bibs: &mut BibData, store_field: bool, - at_bib_command: bool, + bib_command: Option, right_str_delim: ASCIICode, ) -> Result { buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); if (LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace || buffers.offset(BufTy::Base, 2) == buffers.init(BufTy::Base)) - && !compress_bib_white(ctx, buffers, pool, bibs, at_bib_command)? + && !compress_bib_white(ctx, buffers, pool, bibs, bib_command)? { return Ok(false); } @@ -409,7 +414,7 @@ fn scan_balanced_braces( if (LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace || buffers.offset(BufTy::Base, 2) == buffers.init(BufTy::Base)) - && !compress_bib_white(ctx, buffers, pool, bibs, at_bib_command)? + && !compress_bib_white(ctx, buffers, pool, bibs, bib_command)? { return Ok(false); } @@ -448,7 +453,7 @@ fn scan_balanced_braces( if (LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace || buffers.offset(BufTy::Base, 2) == buffers.init(BufTy::Base)) - && !compress_bib_white(ctx, buffers, pool, bibs, at_bib_command)? + && !compress_bib_white(ctx, buffers, pool, bibs, bib_command)? { return Ok(false); } @@ -459,7 +464,7 @@ fn scan_balanced_braces( } } b'}' => { - return bib_unbalanced_braces_print(ctx, buffers, pool, bibs, at_bib_command) + return bib_unbalanced_braces_print(ctx, buffers, pool, bibs, bib_command) .map(|_| false); } c => { @@ -478,7 +483,7 @@ fn scan_balanced_braces( if (LexClass::of(buffers.at_offset(BufTy::Base, 2)) == LexClass::Whitespace || buffers.offset(BufTy::Base, 2) == buffers.init(BufTy::Base)) - && !compress_bib_white(ctx, buffers, pool, bibs, at_bib_command)? + && !compress_bib_white(ctx, buffers, pool, bibs, bib_command)? { return Ok(false); } @@ -492,8 +497,7 @@ fn scan_balanced_braces( brace_level += 1; buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); if !eat_bib_white_space(ctx, buffers, bibs) { - return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command) - .map(|_| false); + return eat_bib_print(ctx, buffers, pool, bibs, bib_command).map(|_| false); } while brace_level > 0 { let c = buffers.at_offset(BufTy::Base, 2); @@ -511,13 +515,13 @@ fn scan_balanced_braces( || !Scan::new().chars(&[b'{', b'}']).scan_till(buffers, init)) && !eat_bib_white_space(ctx, buffers, bibs) { - return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command) + return eat_bib_print(ctx, buffers, pool, bibs, bib_command) .map(|_| false); } } } b'}' => { - return bib_unbalanced_braces_print(ctx, buffers, pool, bibs, at_bib_command) + return bib_unbalanced_braces_print(ctx, buffers, pool, bibs, bib_command) .map(|_| false); } _ => { @@ -528,8 +532,7 @@ fn scan_balanced_braces( .scan_till(buffers, init) && !eat_bib_white_space(ctx, buffers, bibs) { - return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command) - .map(|_| false); + return eat_bib_print(ctx, buffers, pool, bibs, bib_command).map(|_| false); } } } @@ -540,35 +543,46 @@ fn scan_balanced_braces( Ok(true) } -#[allow(clippy::too_many_arguments)] fn scan_a_field_token_and_eat_white( ctx: &mut Bibtex<'_, '_>, - buffers: &mut GlobalBuffer, - hash: &HashData, - pool: &StringPool, - bibs: &mut BibData, + globals: &mut GlobalItems<'_>, store_field: bool, - at_bib_command: bool, - command: BibCommand, + command: Option, cur_macro_loc: HashPointer, right_outer_delim: ASCIICode, ) -> Result { - match buffers.at_offset(BufTy::Base, 2) { + match globals.buffers.at_offset(BufTy::Base, 2) { b'{' => { - if !scan_balanced_braces(ctx, buffers, pool, bibs, store_field, at_bib_command, b'}')? { + if !scan_balanced_braces( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + store_field, + command, + b'}', + )? { return Ok(false); } } b'"' => { - if !scan_balanced_braces(ctx, buffers, pool, bibs, store_field, at_bib_command, b'"')? { + if !scan_balanced_braces( + ctx, + globals.buffers, + globals.pool, + globals.bibs, + store_field, + command, + b'"', + )? { return Ok(false); } } b'0'..=b'9' => { - let last = buffers.init(BufTy::Base); + let last = globals.buffers.init(BufTy::Base); if !Scan::new() .not_class(LexClass::Numeric) - .scan_till_nonempty(buffers, last) + .scan_till_nonempty(globals.buffers, last) { ctx.write_logs("A digit disappeared"); print_confusion(ctx); @@ -576,78 +590,92 @@ fn scan_a_field_token_and_eat_white( } if store_field { - let range = buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2); + let range = + globals.buffers.offset(BufTy::Base, 1)..globals.buffers.offset(BufTy::Base, 2); let len = range.end - range.start; - while len >= buffers.len() { + while len >= globals.buffers.len() { // TODO: This may change output of a field long enough to fill the buffer twice. OTOH, that is a 40KB field roughly ctx.write_log_file(&format!( "Field filled up at {}, reallocating.\n", - buffers.at_offset(BufTy::Base, 1) + globals.buffers.at_offset(BufTy::Base, 1) )); - buffers.grow_all(); + globals.buffers.grow_all(); } - buffers.copy_within( + globals.buffers.copy_within( BufTy::Base, BufTy::Ex, range.start, - buffers.offset(BufTy::Ex, 1), + globals.buffers.offset(BufTy::Ex, 1), len, ); - buffers.set_offset(BufTy::Ex, 1, buffers.offset(BufTy::Ex, 1) + len); + globals.buffers.set_offset( + BufTy::Ex, + 1, + globals.buffers.offset(BufTy::Ex, 1) + len, + ); } } _ => { - let res = scan_identifier(buffers, b',', right_outer_delim, b'#'); + let res = scan_identifier(globals.buffers, b',', right_outer_delim, b'#'); if !matches!( res, ScanRes::WhitespaceAdjacent | ScanRes::SpecifiedCharAdjacent ) { - bib_id_print(ctx, buffers, res)?; + bib_id_print(ctx, globals.buffers, res)?; ctx.write_logs("a field part"); - bib_err_print(ctx, buffers, pool, bibs, at_bib_command)?; + bib_err_print(ctx, globals.buffers, globals.pool, globals.bibs, command)?; return Ok(false); } if store_field { - let range = buffers.offset(BufTy::Base, 1)..buffers.offset(BufTy::Base, 2); - buffers.buffer_mut(BufTy::Base)[range.clone()].make_ascii_lowercase(); - let str = &buffers.buffer(BufTy::Base)[range]; + let range = + globals.buffers.offset(BufTy::Base, 1)..globals.buffers.offset(BufTy::Base, 2); + globals.buffers.buffer_mut(BufTy::Base)[range.clone()].make_ascii_lowercase(); + let str = &globals.buffers.buffer(BufTy::Base)[range]; - let res = pool.lookup_str(hash, str, StrIlk::Macro); + let res = globals.pool.lookup_str(globals.hash, str, StrIlk::Macro); let mut store_token = true; - if at_bib_command && command == BibCommand::String && res.loc == cur_macro_loc { + if command == Some(BibCommand::String) && res.loc == cur_macro_loc { store_token = false; - macro_warn_print(ctx, buffers); + macro_warn_print(ctx, globals.buffers); ctx.write_logs("used in its own definition\n"); - bib_warn_print(ctx, pool, bibs)?; + bib_warn_print(ctx, globals.pool, globals.bibs)?; } if !res.exists { store_token = false; - macro_warn_print(ctx, buffers); + macro_warn_print(ctx, globals.buffers); ctx.write_logs("undefined\n"); - bib_warn_print(ctx, pool, bibs)?; + bib_warn_print(ctx, globals.pool, globals.bibs)?; } if store_token { - let HashExtra::Macro(strnum) = hash.node(res.loc).extra else { + let HashExtra::Macro(strnum) = globals.hash.node(res.loc).extra else { panic!("Macro lookup didn't have Macro extra"); }; - let mut str = pool.get_str(strnum); + let mut str = globals.pool.get_str(strnum); - if buffers.offset(BufTy::Ex, 1) == 0 + if globals.buffers.offset(BufTy::Ex, 1) == 0 && LexClass::of(str[0]) == LexClass::Whitespace { - if buffers.offset(BufTy::Ex, 1) >= buffers.len() { + if globals.buffers.offset(BufTy::Ex, 1) >= globals.buffers.len() { ctx.write_log_file("Field filled up at ' ', reallocating.\n"); - buffers.grow_all(); + globals.buffers.grow_all(); } - buffers.set_at(BufTy::Ex, buffers.offset(BufTy::Ex, 1), b' '); - buffers.set_offset(BufTy::Ex, 1, buffers.offset(BufTy::Ex, 1) + 1); + globals.buffers.set_at( + BufTy::Ex, + globals.buffers.offset(BufTy::Ex, 1), + b' ', + ); + globals.buffers.set_offset( + BufTy::Ex, + 1, + globals.buffers.offset(BufTy::Ex, 1) + 1, + ); while !str.is_empty() && LexClass::of(str[0]) == LexClass::Whitespace { str = &str[1..]; @@ -661,17 +689,33 @@ fn scan_a_field_token_and_eat_white( |_| String::from("Field filled up at ' ', reallocating.\n") }; - if buffers.offset(BufTy::Ex, 1) >= buffers.len() { + if globals.buffers.offset(BufTy::Ex, 1) >= globals.buffers.len() { ctx.write_log_file(&msg(c)); - buffers.grow_all(); + globals.buffers.grow_all(); } if LexClass::of(c) != LexClass::Whitespace { - buffers.set_at(BufTy::Ex, buffers.offset(BufTy::Ex, 1), c); - buffers.set_offset(BufTy::Ex, 1, buffers.offset(BufTy::Ex, 1) + 1); + globals.buffers.set_at( + BufTy::Ex, + globals.buffers.offset(BufTy::Ex, 1), + c, + ); + globals.buffers.set_offset( + BufTy::Ex, + 1, + globals.buffers.offset(BufTy::Ex, 1) + 1, + ); } else if c != b' ' { - buffers.set_at(BufTy::Ex, buffers.offset(BufTy::Ex, 1), b' '); - buffers.set_offset(BufTy::Ex, 1, buffers.offset(BufTy::Ex, 1) + 1); + globals.buffers.set_at( + BufTy::Ex, + globals.buffers.offset(BufTy::Ex, 1), + b' ', + ); + globals.buffers.set_offset( + BufTy::Ex, + 1, + globals.buffers.offset(BufTy::Ex, 1) + 1, + ); } } } @@ -679,8 +723,9 @@ fn scan_a_field_token_and_eat_white( } } - if !eat_bib_white_space(ctx, buffers, bibs) { - return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command).map(|_| false); + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { + return eat_bib_print(ctx, globals.buffers, globals.pool, globals.bibs, command) + .map(|_| false); } Ok(true) } @@ -689,49 +734,38 @@ fn scan_a_field_token_and_eat_white( #[allow(clippy::too_many_arguments)] pub(crate) fn scan_and_store_the_field_value_and_eat_white( ctx: &mut Bibtex<'_, '_>, - buffers: &mut GlobalBuffer, - hash: &mut HashData, - pool: &mut StringPool, - bibs: &mut BibData, - other: &mut OtherData, - cites: &mut CiteInfo, + globals: &mut GlobalItems<'_>, store_field: bool, - at_bib_command: bool, - command: BibCommand, + command: Option, cite_out: Option<&mut CiteNumber>, cur_macro_loc: HashPointer, right_outer_delim: ASCIICode, field_name_loc: HashPointer, ) -> Result { // Consume tokens/strings separated by # - buffers.set_offset(BufTy::Ex, 1, 0); + globals.buffers.set_offset(BufTy::Ex, 1, 0); if !scan_a_field_token_and_eat_white( ctx, - buffers, - hash, - pool, - bibs, + globals, store_field, - at_bib_command, command, cur_macro_loc, right_outer_delim, )? { return Ok(false); } - while buffers.at_offset(BufTy::Base, 2) == b'#' { - buffers.set_offset(BufTy::Base, 2, buffers.offset(BufTy::Base, 2) + 1); - if !eat_bib_white_space(ctx, buffers, bibs) { - return eat_bib_print(ctx, buffers, pool, bibs, at_bib_command).map(|_| false); + while globals.buffers.at_offset(BufTy::Base, 2) == b'#' { + globals + .buffers + .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); + if !eat_bib_white_space(ctx, globals.buffers, globals.bibs) { + return eat_bib_print(ctx, globals.buffers, globals.pool, globals.bibs, command) + .map(|_| false); } if !scan_a_field_token_and_eat_white( ctx, - buffers, - hash, - pool, - bibs, + globals, store_field, - at_bib_command, command, cur_macro_loc, right_outer_delim, @@ -741,105 +775,131 @@ pub(crate) fn scan_and_store_the_field_value_and_eat_white( } if store_field { - if !at_bib_command - && buffers.offset(BufTy::Ex, 1) > 0 - && buffers.at(BufTy::Ex, buffers.offset(BufTy::Ex, 1) - 1) == b' ' + if command.is_none() + && globals.buffers.offset(BufTy::Ex, 1) > 0 + && globals + .buffers + .at(BufTy::Ex, globals.buffers.offset(BufTy::Ex, 1) - 1) + == b' ' { - buffers.set_offset(BufTy::Ex, 1, buffers.offset(BufTy::Ex, 1) - 1); + globals + .buffers + .set_offset(BufTy::Ex, 1, globals.buffers.offset(BufTy::Ex, 1) - 1); } - let ex_buf_xptr = if !at_bib_command - && buffers.at(BufTy::Ex, 0) == b' ' - && buffers.offset(BufTy::Ex, 1) > 0 + let ex_buf_xptr = if command.is_none() + && globals.buffers.at(BufTy::Ex, 0) == b' ' + && globals.buffers.offset(BufTy::Ex, 1) > 0 { 1 } else { 0 }; - let str = &buffers.buffer(BufTy::Ex)[ex_buf_xptr..buffers.offset(BufTy::Ex, 1)]; - let res = pool.lookup_str_insert(ctx, hash, str, HashExtra::Text)?; + let str = + &globals.buffers.buffer(BufTy::Ex)[ex_buf_xptr..globals.buffers.offset(BufTy::Ex, 1)]; + let res = globals + .pool + .lookup_str_insert(ctx, globals.hash, str, HashExtra::Text)?; - if at_bib_command { + if let Some(command) = command { match command { // TODO: Should this be `unreachable!`? This way will cover errors, but also shouldn't misbehave BibCommand::Comment => (), - BibCommand::Preamble => bibs.add_preamble(hash.text(res.loc)), + BibCommand::Preamble => globals.bibs.add_preamble(globals.hash.text(res.loc)), BibCommand::String => { - hash.node_mut(cur_macro_loc).extra = HashExtra::Macro(hash.text(res.loc)) + globals.hash.node_mut(cur_macro_loc).extra = + HashExtra::Macro(globals.hash.text(res.loc)) } } } else { - let HashExtra::BstFn(BstFn::Field(field)) = hash.node(field_name_loc).extra else { + let HashExtra::BstFn(BstFn::Field(field)) = globals.hash.node(field_name_loc).extra + else { panic!("field_name_loc wasn't a BstFn::Field"); }; - let field_ptr = cites.entry_ptr() * other.num_fields() + field; - if field_ptr >= other.max_fields() { + let field_ptr = globals.cites.entry_ptr() * globals.other.num_fields() + field; + if field_ptr >= globals.other.max_fields() { ctx.write_logs("field_info index is out of range"); print_confusion(ctx); return Err(BibtexError::Fatal); } /* missing */ - if other.field(field_ptr) != 0 { + if globals.other.field(field_ptr) != 0 { ctx.write_logs("Warning--I'm ignoring "); - print_a_pool_str(ctx, cites.get_cite(cites.entry_ptr()), pool)?; + print_a_pool_str( + ctx, + globals.cites.get_cite(globals.cites.entry_ptr()), + globals.pool, + )?; ctx.write_logs("'s extra \""); - print_a_pool_str(ctx, hash.text(field_name_loc), pool)?; + print_a_pool_str(ctx, globals.hash.text(field_name_loc), globals.pool)?; ctx.write_logs("\" field\n"); - bib_warn_print(ctx, pool, bibs)?; + bib_warn_print(ctx, globals.pool, globals.bibs)?; } else { - other.set_field(field_ptr, hash.text(res.loc)); - if field == other.crossref_num() && !ctx.all_entries { - let end = buffers.offset(BufTy::Ex, 1); + globals + .other + .set_field(field_ptr, globals.hash.text(res.loc)); + if field == globals.other.crossref_num() && !ctx.all_entries { + let end = globals.buffers.offset(BufTy::Ex, 1); // Move Ex to Out, at the same position - buffers.copy_within( + globals.buffers.copy_within( BufTy::Ex, BufTy::Out, ex_buf_xptr, ex_buf_xptr, end - ex_buf_xptr, ); - buffers.buffer_mut(BufTy::Out)[ex_buf_xptr..end].make_ascii_lowercase(); - let str = &buffers.buffer(BufTy::Out)[ex_buf_xptr..end]; - let lc_res = pool.lookup_str_insert(ctx, hash, str, HashExtra::LcCite(0))?; + globals.buffers.buffer_mut(BufTy::Out)[ex_buf_xptr..end].make_ascii_lowercase(); + let str = &globals.buffers.buffer(BufTy::Out)[ex_buf_xptr..end]; + let lc_res = globals.pool.lookup_str_insert( + ctx, + globals.hash, + str, + HashExtra::LcCite(0), + )?; if let Some(cite_out) = cite_out { *cite_out = lc_res.loc; } - let HashExtra::LcCite(cite_loc) = hash.node(lc_res.loc).extra else { + let HashExtra::LcCite(cite_loc) = globals.hash.node(lc_res.loc).extra else { panic!("LcCite lookup didn't have LcCite extra"); }; if lc_res.exists { - let HashExtra::Cite(cite) = hash.node(cite_loc).extra else { + let HashExtra::Cite(cite) = globals.hash.node(cite_loc).extra else { panic!("LcCite location didn't have Cite extra"); }; - if cite >= cites.old_num_cites() { - cites.set_info(cite, cite + 1); + if cite >= globals.cites.old_num_cites() { + globals.cites.set_info(cite, cite + 1); } } else { - let str = - &buffers.buffer(BufTy::Ex)[ex_buf_xptr..buffers.offset(BufTy::Ex, 1)]; - let c_res = pool.lookup_str_insert(ctx, hash, str, HashExtra::Cite(0))?; + let str = &globals.buffers.buffer(BufTy::Ex) + [ex_buf_xptr..globals.buffers.offset(BufTy::Ex, 1)]; + let c_res = globals.pool.lookup_str_insert( + ctx, + globals.hash, + str, + HashExtra::Cite(0), + )?; if c_res.exists { hash_cite_confusion(ctx); return Err(BibtexError::Fatal); } let new_ptr = add_database_cite( - cites, - other, - hash, - cites.ptr(), + globals.cites, + globals.other, + globals.hash, + globals.cites.ptr(), c_res.loc, lc_res.loc, ); - let HashExtra::Cite(cite) = hash.node(c_res.loc).extra else { + let HashExtra::Cite(cite) = globals.hash.node(c_res.loc).extra else { panic!("Cite lookup didn't have Cite extra"); }; - cites.set_ptr(new_ptr); - cites.set_info(cite, 1); + globals.cites.set_ptr(new_ptr); + globals.cites.set_info(cite, 1); } } } From bfa13712a7cd5049dc8f1cbf61a1fc60c3493947 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sun, 31 Mar 2024 15:27:44 -0700 Subject: [PATCH 20/23] Fix test_pool --- Cargo.lock | 1 + crates/engine_bibtex/Cargo.toml | 3 + crates/engine_bibtex/src/pool.rs | 100 ++++++++++++++++++------------- 3 files changed, 61 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6b42fe223..da1867adc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2818,6 +2818,7 @@ dependencies = [ "tectonic_bridge_core", "tectonic_errors", "tectonic_io_base", + "tectonic_status_base", ] [[package]] diff --git a/crates/engine_bibtex/Cargo.toml b/crates/engine_bibtex/Cargo.toml index 33a581fb5..70ccfb6c7 100644 --- a/crates/engine_bibtex/Cargo.toml +++ b/crates/engine_bibtex/Cargo.toml @@ -23,6 +23,9 @@ tectonic_io_base = { path = "../io_base", version = '0.0.0-dev.0' } tectonic_bridge_core = { path = "../bridge_core", version = "0.0.0-dev.0" } tectonic_errors = { path = "../errors", version = "0.0.0-dev.0" } +[dev-dependencies] +tectonic_status_base = { path = "../status_base", version = "0.0.0-dev.0" } + [package.metadata.internal_dep_versions] tectonic_bridge_core = "thiscommit:2021-01-17:fohCh1sh" tectonic_errors = "5c9ba661edf5ef669f24f9904f99cca369d999e7" diff --git a/crates/engine_bibtex/src/pool.rs b/crates/engine_bibtex/src/pool.rs index dd049b60e..89b2599b0 100644 --- a/crates/engine_bibtex/src/pool.rs +++ b/crates/engine_bibtex/src/pool.rs @@ -553,50 +553,64 @@ pub(crate) fn add_out_pool( #[cfg(test)] mod tests { - // use super::*; - // use crate::BibtexConfig; - // use tectonic_bridge_core::{CoreBridgeLauncher, CoreBridgeState, DriverHooks, MinimalDriver}; + use super::*; + use crate::BibtexConfig; + use tectonic_bridge_core::{CoreBridgeLauncher, CoreBridgeState, MinimalDriver}; + use tectonic_io_base::{stack::IoStack, IoProvider}; + use tectonic_status_base::NoopStatusBackend; + + fn with_cbs(f: impl FnOnce(&mut CoreBridgeState<'_>)) { + let io_list: Vec<&mut dyn IoProvider> = vec![]; + let io = IoStack::new(io_list); + let mut hooks = MinimalDriver::new(io); + let mut status = NoopStatusBackend::default(); + let mut cbl = CoreBridgeLauncher::new(&mut hooks, &mut status); + cbl.with_global_lock(|cbs| { + f(cbs); + Ok(()) + }) + .unwrap(); + } // TODO: Create context without backend? Use custom backend-like type? // Implement the relevant interfaces ourself? - // #[test] - // fn test_pool() { - // with_cbs(|cbs| { - // let mut ctx = Bibtex::new(cbs, BibtexConfig::default()); - // let mut hash = HashData::new(); - // let mut new_pool = StringPool::new(); - // let res = new_pool - // .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", HashExtra::Text) - // .unwrap(); - // assert!(!res.exists); - // assert_eq!( - // new_pool.try_get_str(hash.text(res.loc)), - // Ok(b"a cool string" as &[_]) - // ); - // - // let res2 = new_pool - // .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", HashExtra::Text) - // .unwrap(); - // assert!(res2.exists); - // assert_eq!( - // new_pool.try_get_str(hash.text(res2.loc)), - // Ok(b"a cool string" as &[_]) - // ); - // - // let res3 = new_pool.lookup_str(&hash, b"a cool string", StrIlk::Text); - // assert!(res3.exists); - // assert_eq!( - // new_pool.try_get_str(hash.text(res3.loc)), - // Ok(b"a cool string" as &[_]) - // ); - // - // let res4 = new_pool.lookup_str(&hash, b"a bad string", StrIlk::Text); - // assert!(!res4.exists); - // assert_eq!( - // new_pool.try_get_str(hash.text(res4.loc)), - // Err(LookupErr::DoesntExist) - // ); - // }) - // .unwrap() - // } + #[test] + fn test_pool() { + with_cbs(|cbs| { + let mut ctx = Bibtex::new(cbs, BibtexConfig::default()); + let mut hash = HashData::new(); + let mut new_pool = StringPool::new(); + let res = new_pool + .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", HashExtra::Text) + .unwrap(); + assert!(!res.exists); + assert_eq!( + new_pool.try_get_str(hash.text(res.loc)), + Ok(b"a cool string" as &[_]) + ); + + let res2 = new_pool + .lookup_str_insert(&mut ctx, &mut hash, b"a cool string", HashExtra::Text) + .unwrap(); + assert!(res2.exists); + assert_eq!( + new_pool.try_get_str(hash.text(res2.loc)), + Ok(b"a cool string" as &[_]) + ); + + let res3 = new_pool.lookup_str(&hash, b"a cool string", StrIlk::Text); + assert!(res3.exists); + assert_eq!( + new_pool.try_get_str(hash.text(res3.loc)), + Ok(b"a cool string" as &[_]) + ); + + let res4 = new_pool.lookup_str(&hash, b"a bad string", StrIlk::Text); + assert!(!res4.exists); + assert_eq!( + new_pool.try_get_str(hash.text(res4.loc)), + Err(LookupErr::DoesntExist) + ); + }) + } } From 47261d82bd9e8215216dd2416d9066d121e227f5 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sun, 31 Mar 2024 18:38:23 -0700 Subject: [PATCH 21/23] Add tectonic_status_base commit --- crates/engine_bibtex/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/engine_bibtex/Cargo.toml b/crates/engine_bibtex/Cargo.toml index 70ccfb6c7..068264fc8 100644 --- a/crates/engine_bibtex/Cargo.toml +++ b/crates/engine_bibtex/Cargo.toml @@ -30,3 +30,4 @@ tectonic_status_base = { path = "../status_base", version = "0.0.0-dev.0" } tectonic_bridge_core = "thiscommit:2021-01-17:fohCh1sh" tectonic_errors = "5c9ba661edf5ef669f24f9904f99cca369d999e7" tectonic_io_base = "0d9169ef44b2652d6d70308a83022bfd60358e71" +tectonic_status_base = "0d9169ef44b2652d6d70308a83022bfd60358e71" From 4f6a4284ce11e88de5d2568b7078e370523b4579 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sat, 10 Aug 2024 22:45:49 -0700 Subject: [PATCH 22/23] Fix tests --- tests/bibtex.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/bibtex.rs b/tests/bibtex.rs index 8d0d88491..cef6998a0 100644 --- a/tests/bibtex.rs +++ b/tests/bibtex.rs @@ -114,12 +114,14 @@ fn test_colon() { #[test] fn test_control_sequences() { - TestCase::new("control_seq", Some("cites")).go(); + TestCase::new(&["cites", "control_seq"]) + .expect(Ok(TexOutcome::Warnings)) + .go(); } #[test] fn test_multi_bib() { - TestCase::new("multi_file", Some("cites")).go(); + TestCase::new(&["cites", "multi_file"]).go(); } #[test] From 2617e2671a68d938d95f9a2f8bd2c469985ad39c Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sat, 28 Sep 2024 22:19:32 -0700 Subject: [PATCH 23/23] Re-add clippy fixes --- crates/bridge_core/src/lib.rs | 2 +- crates/engine_bibtex/src/bibs.rs | 2 +- crates/engine_bibtex/src/bst.rs | 2 +- crates/engine_bibtex/src/scan.rs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bridge_core/src/lib.rs b/crates/bridge_core/src/lib.rs index a4ea06e04..6541c0d7a 100644 --- a/crates/bridge_core/src/lib.rs +++ b/crates/bridge_core/src/lib.rs @@ -577,7 +577,7 @@ impl<'a> CoreBridgeState<'a> { rv = true; } let (name, digest) = oh.into_name_digest(); - self.hooks.event_output_closed(name, digest, self.status); + self.hooks.event_output_closed(name, digest); } rv diff --git a/crates/engine_bibtex/src/bibs.rs b/crates/engine_bibtex/src/bibs.rs index 67ea6285a..830467064 100644 --- a/crates/engine_bibtex/src/bibs.rs +++ b/crates/engine_bibtex/src/bibs.rs @@ -134,7 +134,7 @@ pub(crate) fn get_bib_command_or_entry_and_process( let mut bib_command = None; let mut init = globals.buffers.init(BufTy::Base); - while !Scan::new().chars(&[b'@']).scan_till(globals.buffers, init) { + while !Scan::new().chars(b"@").scan_till(globals.buffers, init) { if !input_ln( ctx.engine, &mut globals.bibs.top_file_mut().file, diff --git a/crates/engine_bibtex/src/bst.rs b/crates/engine_bibtex/src/bst.rs index 3e7470953..8ec38dac1 100644 --- a/crates/engine_bibtex/src/bst.rs +++ b/crates/engine_bibtex/src/bst.rs @@ -432,7 +432,7 @@ fn bst_macro_command( .buffers .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); let init = globals.buffers.init(BufTy::Base); - if !Scan::new().chars(&[b'"']).scan_till(globals.buffers, init) { + if !Scan::new().chars(b"\"").scan_till(globals.buffers, init) { ctx.write_logs("There's no `\"' to end macro definition"); bst_err_print_and_look_for_blank_line(ctx, globals.buffers, globals.pool)?; return Ok(()); diff --git a/crates/engine_bibtex/src/scan.rs b/crates/engine_bibtex/src/scan.rs index 99c950af5..32ad9827e 100644 --- a/crates/engine_bibtex/src/scan.rs +++ b/crates/engine_bibtex/src/scan.rs @@ -220,7 +220,7 @@ fn handle_char( .set_offset(BufTy::Base, 2, globals.buffers.offset(BufTy::Base, 2) + 1); let init = globals.buffers.init(BufTy::Base); - if !Scan::new().chars(&[b'"']).scan_till(globals.buffers, init) { + if !Scan::new().chars(b"\"").scan_till(globals.buffers, init) { ctx.write_logs("No `\"` to end string literal"); return skip_token_print(ctx, globals.buffers, globals.pool); } @@ -512,7 +512,7 @@ fn scan_balanced_braces( let init = buffers.init(BufTy::Base); if (c == b'{' || c == b'}' - || !Scan::new().chars(&[b'{', b'}']).scan_till(buffers, init)) + || !Scan::new().chars(b"{}").scan_till(buffers, init)) && !eat_bib_white_space(ctx, buffers, bibs) { return eat_bib_print(ctx, buffers, pool, bibs, bib_command)