use crate::Engine;
use crate::cmd::Cmd;
use crate::hash::{CsId, CsKind};
use crate::primitives_gen as pg;
use crate::scan::REG_OFFSET;
use crate::token::Token;
impl Engine {
pub fn print_esc_bytes(&mut self, s: &[u8]) {
let c = self.eqtb.int(pg::assign_int::ESCAPECHAR);
if (0..=0x10_FFFF).contains(&c) {
self.printer.print_char(c as u32);
}
self.printer.print_bytes(s);
}
pub fn print_esc_str(&mut self, s: &str) {
self.print_esc_bytes(s.as_bytes());
}
pub fn print_cs(&mut self, p: CsId) {
if !self.hash.contains(p) {
self.print_esc_str("IMPOSSIBLE.");
return;
}
match self.hash.kind(p).clone() {
CsKind::Null => {
self.print_esc_str("csname");
self.print_esc_str("endcsname");
self.printer.print_char(' ' as u32);
}
CsKind::Single(c) => {
self.print_esc_bytes(&crate::utf8x::encode(c));
if self.eqtb.catcode(c) == 11 {
self.printer.print_char(' ' as u32);
}
}
CsKind::Active(c) => self.printer.print_char(c),
CsKind::Undefined => self.print_esc_str("IMPOSSIBLE."),
CsKind::Internal => {
let name = self.hash.name(p).to_vec();
self.printer.print_bytes(&name);
}
CsKind::Multi | CsKind::Frozen => {
let name = self.hash.name(p).to_vec();
self.print_esc_bytes(&name);
self.printer.print_char(' ' as u32);
}
}
}
pub fn sprint_cs(&mut self, p: CsId) {
match self.hash.kind(p).clone() {
CsKind::Null => {
self.print_esc_str("csname");
self.print_esc_str("endcsname");
}
CsKind::Active(c) => self.printer.print_char(c),
CsKind::Undefined => self.print_esc_str("IMPOSSIBLE."),
CsKind::Internal => {
let name = self.hash.name(p).to_vec();
self.printer.print_bytes(&name);
}
_ => {
let name = self.hash.name(p).to_vec();
self.print_esc_bytes(&name);
}
}
}
pub fn show_token_list(&mut self, list: &[Token], start: usize, end: usize, l: i64) {
self.show_token_list_impl(list, start, end, None, l);
}
pub fn show_token_list_ctx(&mut self, list: &[Token], loc: usize, l: i64) {
self.show_token_list_impl(list, 0, list.len(), Some(loc), l);
}
pub fn token_show_list(&mut self, list: &[Token], start: usize, end: usize, l: i64) {
self.show_token_list(list, start, end, l);
}
fn show_token_list_impl(
&mut self,
list: &[Token],
start: usize,
end: usize,
magic: Option<usize>,
l: i64,
) {
let mut match_chr = '#' as u32;
let mut n = b'0';
self.printer.tally = 0;
let mut p = start;
while p < end && (self.printer.tally as i64) < l {
if magic == Some(p) {
self.set_trick_count();
}
let t = list[p];
if t.is_cs() {
self.print_cs(t.cs_id());
} else {
let c = t.chr();
match Cmd::from_u8(t.cmd_code() as u8) {
Cmd::LeftBrace
| Cmd::RightBrace
| Cmd::MathShift
| Cmd::TabMark
| Cmd::SupMark
| Cmd::SubMark
| Cmd::Spacer
| Cmd::Letter
| Cmd::OtherChar => self.printer.print_char(c),
Cmd::MacParam => {
self.printer.print_char(c);
if !self.single_mac_param {
self.printer.print_char(c);
}
}
Cmd::CarRet => {
self.printer.print_char(match_chr);
if c <= 9 {
self.printer.print_char(c + '0' as u32);
} else {
self.printer.print_char('!' as u32);
return;
}
}
Cmd::ParEnd => {
match_chr = c;
self.printer.print_char(c);
n += 1;
self.printer.print_char(u32::from(n));
if n > b'9' {
return;
}
}
Cmd::Stop => self.printer.print_str("->"),
_ => self.print_esc_str("BAD."),
}
}
p += 1;
}
if magic == Some(p) {
self.set_trick_count();
}
if p < end {
self.print_esc_str("ETC.");
}
}
pub fn print_cmd_chr(&mut self, cmd: Cmd, chr: u32) {
let chr_cmd = |e: &mut Engine, s: &str| {
e.printer.print_str(s);
e.printer.print_char(chr);
};
match cmd {
Cmd::LeftBrace => chr_cmd(self, "begin-group character "),
Cmd::RightBrace => chr_cmd(self, "end-group character "),
Cmd::MathShift => chr_cmd(self, "math shift character "),
Cmd::MacParam => chr_cmd(self, "macro parameter character "),
Cmd::SupMark => chr_cmd(self, "superscript character "),
Cmd::SubMark => chr_cmd(self, "subscript character "),
Cmd::Endv => self.printer.print_str("end of alignment template"),
Cmd::Spacer => chr_cmd(self, "blank space "),
Cmd::Letter => chr_cmd(self, "the letter "),
Cmd::OtherChar => chr_cmd(self, "the character "),
Cmd::TabMark if chr < 0x11_0000 => chr_cmd(self, "alignment tab character "),
Cmd::UndefinedCs => self.printer.print_str("undefined"),
Cmd::LuaCall => {
self.printer.print_str("luacall ");
self.printer.print_int(i64::from(chr));
}
Cmd::LuaExpandableCall => {
self.printer.print_str("expandable luacall ");
self.printer.print_int(i64::from(chr));
}
Cmd::Call | Cmd::LongCall | Cmd::OuterCall | Cmd::LongOuterCall => {
let n = cmd as u32 - Cmd::Call as u32;
if n & 1 != 0 {
self.print_esc_str("long");
}
if n & 2 != 0 {
self.print_esc_str("outer");
}
if n > 0 {
self.printer.print_char(' ' as u32);
}
self.printer.print_str("macro");
}
Cmd::EndTemplate => self.print_esc_str("outer endtemplate"),
Cmd::CharGiven => {
self.print_esc_str("char");
self.printer.print_hex(i64::from(chr));
}
Cmd::MathGiven => {
self.print_esc_str("mathchar");
let v = crate::codes::math_given_report(chr) as u32;
self.printer.print_char('"' as u32);
for d in [v / 0x1000, (v >> 8) & 0xF, (v >> 4) & 0xF, v & 0xF] {
let c = if d < 10 {
'0' as u32 + d
} else {
'A' as u32 + d - 10
};
self.printer.print_char(c);
}
}
Cmd::XmathGiven => {
self.print_esc_str("Umathchar");
let code = i64::from(chr);
self.printer
.print_hex(i64::from(crate::codes::math_class(code)));
self.printer
.print_str(&format!("\"{:02X}", crate::codes::math_fam(code)));
self.printer
.print_str(&format!("\"{:06X}", crate::codes::math_char(code)));
}
Cmd::SetFont => {
self.printer.print_str("select font ");
self.print_font_name_and_size(chr);
}
Cmd::AssignInt if chr >= REG_OFFSET => {
self.print_esc_str("count");
self.printer.print_int(i64::from(chr - REG_OFFSET));
}
Cmd::AssignAttr => {
self.print_esc_str("attribute");
self.printer
.print_int(i64::from(chr.saturating_sub(REG_OFFSET)));
}
Cmd::AssignDimen if chr >= REG_OFFSET => {
self.print_esc_str("dimen");
self.printer.print_int(i64::from(chr - REG_OFFSET));
}
Cmd::AssignGlue if chr >= REG_OFFSET => {
self.print_esc_str("skip");
self.printer.print_int(i64::from(chr - REG_OFFSET));
}
Cmd::AssignMuGlue if chr >= REG_OFFSET => {
self.print_esc_str("muskip");
self.printer.print_int(i64::from(chr - REG_OFFSET));
}
Cmd::AssignToks if chr >= REG_OFFSET => {
self.print_esc_str("toks");
self.printer.print_int(i64::from(chr - REG_OFFSET));
}
Cmd::IfTest if chr >= crate::cond::UNLESS_CODE => {
self.print_esc_str("unless");
self.print_cmd_chr(cmd, chr - crate::cond::UNLESS_CODE);
}
Cmd::Relax if chr == crate::input::NO_EXPAND_FLAG => {
self.print_esc_str("notexpanded:");
}
_ => match crate::primitives::name_of(cmd, chr) {
Some(name) => self.print_esc_str(name),
None => {
self.printer.print_str("[unknown command code! (");
self.printer.print_int(i64::from(cmd as u8));
self.printer.print_str(", ");
self.printer.print_int(i64::from(chr));
self.printer.print_str(")]");
}
},
}
}
pub fn print_meaning(&mut self) {
if self.cur_cmd.is_call() {
let mac = if self.cur_cs != crate::hash::NO_CS {
self.eqtb.meaning(self.cur_cs).mac.clone()
} else {
None
};
let n = self.cur_cmd as u32 - Cmd::Call as u32;
let protected = mac.as_ref().is_some_and(|m| m.protected);
if protected {
self.print_esc_str("protected");
}
if n & 1 != 0 {
self.print_esc_str("long");
}
if n & 2 != 0 {
self.print_esc_str("outer");
}
if n > 0 || protected {
self.printer.print_char(' ' as u32);
}
self.printer.print_str("macro");
self.printer.print_char(':' as u32);
self.printer.print_ln();
if let Some(m) = mac {
let toks = m.tokens.clone();
self.token_show_list(&toks, 0, toks.len(), 10_000_000);
}
} else if self.cur_cmd == Cmd::TopBotMark && self.cur_chr < 5 {
self.print_cmd_chr(self.cur_cmd, self.cur_chr);
self.printer.print_char(':' as u32);
self.printer.print_ln();
if let Some(list) = self.marks.get(0, self.cur_chr) {
self.token_show_list(&list, 0, list.len(), 10_000_000);
}
} else {
self.print_cmd_chr(self.cur_cmd, self.cur_chr);
}
}
pub fn show_cur_cmd_chr(&mut self) {
self.begin_diagnostic();
self.printer.print_nl("{");
if self.mode != self.shown_mode {
self.print_mode(self.mode);
self.printer.print_str(": ");
self.shown_mode = self.mode;
}
self.print_cmd_chr(self.cur_cmd, self.cur_chr);
if self.eqtb.int(pg::assign_int::TRACINGIFS) > 0
&& self.cur_cmd >= Cmd::IfTest
&& self.cur_cmd <= Cmd::FiOrElse
{
self.printer.print_str(": ");
let (mut n, l) = if self.cur_cmd == Cmd::FiOrElse {
self.print_cmd_chr(Cmd::IfTest, self.cond.cur_if);
self.printer.print_char(' ' as u32);
(0, self.cond.if_line)
} else {
(1, self.input.line())
};
n += self.cond.stack.len() as i64;
self.printer.print_str("(level ");
self.printer.print_int(n);
self.printer.print_char(')' as u32);
if l != 0 {
self.printer.print_str(" entered on line ");
self.printer.print_int(l.into());
}
}
self.printer.print_char('}' as u32);
self.end_diagnostic(false);
}
}