#![allow(missing_docs)]
use std::{
collections::{BTreeMap, HashMap},
io::Write,
};
use tectonic_errors::prelude::*;
#[derive(Clone, Debug, Default)]
pub struct SymbolTable {
by_name: HashMap<String, isize>,
grouped: BTreeMap<SymbolCategory, Vec<String>>,
}
macro_rules! define_categories {
($(#[doc = $doc:expr] $name:ident),+,) => {
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum SymbolCategory {
$(
#[doc = $doc]
$name
),+
}
impl SymbolCategory {
fn emit_header<W: Write>(&self, stream: &mut W) -> Result<()> {
let s = match self {
$(
SymbolCategory::$name => $doc
),+
};
Ok(writeln!(stream, "/*{} */\n", s)?)
}
}
}
}
define_categories! {
FormatVersion,
CsHash,
CharacterConstants,
FixedArrays,
IntPars,
DimenPars,
GluePars,
LocalPars,
EtexPenaltiesPars,
Eqtb,
Commands,
Modes,
MathFontSizes,
NodeTypes,
MathNoadTypes,
GlueNodeSubtypes,
KernNodeSubtypes,
MathNodeSubtypes,
StyleNodeSubtypes,
OpNoadSubtypes,
WhatsitNodeSubtypes,
AboveCodes,
BoxCodes,
ConvertCodes,
ExtensionCodes,
FiOrElseCodes,
IfCodes,
LastItemCodes,
InteractionModes,
SetBoxDimenCodes,
ShorthandDefCodes,
SkipCodes,
TabCrCodes,
TopBotMarkCodes,
XrayCodes,
}
impl SymbolTable {
pub fn add<S: Into<String>>(
&mut self,
cat: SymbolCategory,
name: S,
value: isize,
) -> Result<()> {
let name = name.into();
if let Some(prev) = self.by_name.insert(name.clone(), value) {
ensure!(prev == value, format!("changed symbol name `{name}`"));
} else {
let group = self.grouped.entry(cat).or_default();
group.push(name);
}
Ok(())
}
pub fn lookup(&self, name: &str) -> isize {
*self.by_name.get(name).unwrap()
}
pub fn emit_c_header_stanza<W: Write>(&self, stream: &mut W) -> Result<()> {
let mut first = true;
for (cat, names) in &self.grouped {
if first {
first = false;
} else {
writeln!(stream)?;
}
cat.emit_header(stream)?;
for name in names {
let value = self.by_name.get(name).unwrap();
writeln!(stream, "#define {name} {value} /* = 0x{value:x} */")?;
}
}
Ok(())
}
}
pub trait HasSymbol {
fn symbol(&self) -> &'static str;
}
pub trait DeclaresSymbols {
fn declare_symbols(symbols: &mut SymbolTable) -> Result<()>;
}