#![deny(missing_docs)]
use std::{ffi::CString, time::SystemTime};
use tectonic_bridge_core::{CoreBridgeLauncher, EngineAbortedError};
use tectonic_errors::prelude::*;
pub const FORMAT_SERIAL: u32 = 31;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TexOutcome {
Spotless,
Warnings,
Errors,
}
#[derive(Debug)]
pub struct TexEngine {
halt_on_error: bool,
initex_mode: bool,
synctex_enabled: bool,
semantic_pagination_enabled: bool,
shell_escape_enabled: bool,
build_date: SystemTime,
}
impl Default for TexEngine {
fn default() -> Self {
TexEngine {
halt_on_error: true,
initex_mode: false,
synctex_enabled: false,
semantic_pagination_enabled: false,
shell_escape_enabled: false,
build_date: SystemTime::UNIX_EPOCH,
}
}
}
impl TexEngine {
pub fn halt_on_error_mode(&mut self, halt_on_error: bool) -> &mut Self {
self.halt_on_error = halt_on_error;
self
}
pub fn initex_mode(&mut self, initex: bool) -> &mut Self {
self.initex_mode = initex;
self
}
pub fn synctex(&mut self, synctex_enabled: bool) -> &mut Self {
self.synctex_enabled = synctex_enabled;
self
}
pub fn semantic_pagination(&mut self, enabled: bool) -> &mut Self {
self.semantic_pagination_enabled = enabled;
self
}
pub fn shell_escape(&mut self, shell_escape_enabled: bool) -> &mut Self {
self.shell_escape_enabled = shell_escape_enabled;
self
}
pub fn build_date(&mut self, date: SystemTime) -> &mut Self {
self.build_date = date;
self
}
pub fn process(
&mut self,
launcher: &mut CoreBridgeLauncher,
format_file_name: &str,
input_file_name: &str,
) -> Result<TexOutcome> {
let cformat = CString::new(format_file_name)?;
let cinput = CString::new(input_file_name)?;
launcher.with_global_lock(|state| {
let v = if self.shell_escape_enabled { 1 } else { 0 };
unsafe {
c_api::tt_xetex_set_int_variable(b"shell_escape_enabled\0".as_ptr() as _, v);
}
let v = if self.halt_on_error { 1 } else { 0 };
unsafe {
c_api::tt_xetex_set_int_variable(b"halt_on_error_p\0".as_ptr() as _, v);
}
let v = if self.initex_mode { 1 } else { 0 };
unsafe {
c_api::tt_xetex_set_int_variable(b"in_initex_mode\0".as_ptr() as _, v);
}
let v = if self.synctex_enabled { 1 } else { 0 };
unsafe {
c_api::tt_xetex_set_int_variable(b"synctex_enabled\0".as_ptr() as _, v);
}
let v = if self.semantic_pagination_enabled {
1
} else {
0
};
unsafe {
c_api::tt_xetex_set_int_variable(b"semantic_pagination_enabled\0".as_ptr() as _, v);
}
let r = unsafe {
c_api::tt_engine_xetex_main(
state,
cformat.as_ptr(),
cinput.as_ptr(),
self.build_date
.duration_since(SystemTime::UNIX_EPOCH)
.expect("invalid build date")
.as_secs() as libc::time_t,
)
};
match r {
0 => Ok(TexOutcome::Spotless),
1 => Ok(TexOutcome::Warnings),
2 => Ok(TexOutcome::Errors),
3 => Err(EngineAbortedError::new_abort_indicator().into()),
x => Err(anyhow!("internal error: unexpected 'history' value {}", x)),
}
})
}
}
#[doc(hidden)]
pub mod c_api {
use tectonic_bridge_core::CoreBridgeState;
#[allow(improper_ctypes)] extern "C" {
pub fn tt_xetex_set_int_variable(
var_name: *const libc::c_char,
value: libc::c_int,
) -> libc::c_int;
pub fn tt_engine_xetex_main(
api: &mut CoreBridgeState,
dump_name: *const libc::c_char,
input_file_name: *const libc::c_char,
build_date: libc::time_t,
) -> libc::c_int;
}
}
mod linkage {
#[allow(unused_imports)]
use tectonic_pdf_io as clipyrenamehack1;
#[allow(unused_imports)]
use tectonic_xetex_layout as clipyrenamehack2;
}
#[test]
fn linkage() {}