Skip to content

Commit 1c66d6a

Browse files
committed
Port print_native_word, begin converting mem to use node structs instead of raw offsets
1 parent 0894324 commit 1c66d6a

File tree

5 files changed

+224
-41
lines changed

5 files changed

+224
-41
lines changed

crates/engine_xetex/src/c_api/engine.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ pub struct EngineCtx {
3333
pub(crate) mem: Vec<MemoryWord>,
3434
}
3535

36+
struct NodeError {
37+
ty: u16,
38+
subty: u16,
39+
}
40+
3641
impl EngineCtx {
3742
fn new() -> EngineCtx {
3843
EngineCtx {
@@ -49,6 +54,36 @@ impl EngineCtx {
4954
}
5055
}
5156

57+
pub fn try_node<T: ?Sized + Node>(&self, idx: usize) -> Result<&T, NodeError> {
58+
let ptr = self.mem.as_ptr().wrapping_add(idx);
59+
let base = unsafe { &*NodeBase::from_ptr(ptr) };
60+
61+
if T::ty() != base.ty() || T::subty() != base.subty() {
62+
return Err(NodeError {
63+
ty: base.ty(),
64+
subty: base.subty(),
65+
});
66+
}
67+
68+
let ptr = unsafe { T::from_ptr(ptr) };
69+
Ok(unsafe { &*ptr })
70+
}
71+
72+
pub fn node<T: ?Sized + Node>(&self, idx: usize) -> &T {
73+
match self.try_node::<T>(idx) {
74+
Ok(node) => node,
75+
Err(e) => {
76+
panic!(
77+
"Invalid node type. expected {}:{}, found {}:{}",
78+
e.ty,
79+
e.subty,
80+
T::ty(),
81+
T::subty(),
82+
);
83+
}
84+
}
85+
}
86+
5287
pub fn int_par(&self, par: IntPar) -> i32 {
5388
unsafe { self.eqtb[INT_BASE + par as usize].b32.s1 }
5489
}

crates/engine_xetex/src/c_api/engine/memory.rs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
*
3232
*/
3333

34+
use std::{fmt, ptr};
35+
3436
#[cfg(target_endian = "big")]
3537
mod data {
3638
#[derive(Copy, Clone)]
@@ -80,6 +82,40 @@ pub union MemoryWord {
8082
pub(crate) ptr: *mut (),
8183
}
8284

85+
impl MemoryWord {
86+
pub fn i32_0(&self) -> i32 {
87+
unsafe { self.b32.s0 }
88+
}
89+
90+
pub fn i32_1(&self) -> i32 {
91+
unsafe { self.b32.s1 }
92+
}
93+
94+
pub fn u16_0(&self) -> u16 {
95+
unsafe { self.b16.s0 }
96+
}
97+
98+
pub fn u16_1(&self) -> u16 {
99+
unsafe { self.b16.s1 }
100+
}
101+
102+
pub fn u16_2(&self) -> u16 {
103+
unsafe { self.b16.s2 }
104+
}
105+
106+
pub fn u16_3(&self) -> u16 {
107+
unsafe { self.b16.s3 }
108+
}
109+
110+
pub fn f64(&self) -> f64 {
111+
unsafe { self.gr }
112+
}
113+
114+
pub fn ptr(&self) -> *mut () {
115+
unsafe { self.ptr }
116+
}
117+
}
118+
83119
/* ## THE ORIGINAL SITUATION (archived for posterity)
84120
*
85121
* In XeTeX, a "quarterword" is 16 bits. Who knows why. A "halfword" is,
@@ -172,6 +208,96 @@ pub union MemoryWord {
172208
*
173209
*/
174210

211+
/* Types of nodes that can occur in general lists. */
212+
pub const WHATSIT_NODE: u16 = 8;
213+
214+
/* Subtypes for whatsit nodes. */
215+
pub const NATIVE_WORD_NODE: u16 = 40;
216+
217+
pub trait Node {
218+
fn ty() -> u16;
219+
fn subty() -> u16;
220+
221+
unsafe fn from_ptr(ptr: *const MemoryWord) -> *const Self;
222+
unsafe fn from_ptr_mut(ptr: *mut MemoryWord) -> *mut Self;
223+
}
224+
225+
#[repr(C)]
226+
pub struct NodeBase(B16x4);
227+
228+
impl NodeBase {
229+
pub(super) fn from_ptr(ptr: *const MemoryWord) -> *const NodeBase {
230+
ptr.cast()
231+
}
232+
233+
pub fn ty(&self) -> u16 {
234+
self.0.s1
235+
}
236+
237+
pub fn subty(&self) -> u16 {
238+
self.0.s0
239+
}
240+
}
241+
242+
impl fmt::Debug for NodeBase {
243+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244+
f.debug_struct("NodeBase")
245+
.field("ty", &self.ty())
246+
.field("subty", &self.subty())
247+
.finish()
248+
}
249+
}
250+
251+
#[repr(C)]
252+
pub struct NativeWordNode {
253+
// p
254+
node: NodeBase,
255+
// p + 1..p + 3
256+
_priv: [MemoryWord; 3],
257+
// p + 4 - most data is here
258+
data: B16x4,
259+
// p + 5 - glyph_info pointer
260+
glyph_info: *mut (),
261+
// p+6.. - text in this node
262+
text: [u16],
263+
}
264+
265+
impl Node for NativeWordNode {
266+
fn ty() -> u16 {
267+
WHATSIT_NODE
268+
}
269+
270+
fn subty() -> u16 {
271+
NATIVE_WORD_NODE
272+
}
273+
274+
unsafe fn from_ptr(ptr: *const MemoryWord) -> *const Self {
275+
let this = ptr::slice_from_raw_parts(ptr, 0) as *const Self;
276+
let len = (*this).size();
277+
ptr::slice_from_raw_parts(ptr, len) as *const Self
278+
}
279+
280+
unsafe fn from_ptr_mut(ptr: *mut MemoryWord) -> *mut Self {
281+
let this = ptr::slice_from_raw_parts_mut(ptr, 0) as *mut Self;
282+
let len = (*this).size();
283+
ptr::slice_from_raw_parts_mut(ptr, len) as *mut Self
284+
}
285+
}
286+
287+
impl NativeWordNode {
288+
pub fn base(&self) -> &NodeBase {
289+
&self.node
290+
}
291+
292+
pub fn size(&self) -> usize {
293+
self.data.s3 as usize
294+
}
295+
296+
pub fn text(&self) -> &[u16] {
297+
&self.text
298+
}
299+
}
300+
175301
pub const EQTB_SIZE: usize = 0x886f92;
176302

177303
pub const ACTIVE_BASE: usize = 0x1;

crates/engine_xetex/src/c_api/output.rs

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::c_api::engine::{
2-
rs_gettexstring, CatCode, IntPar, Selector, ACTIVE_BASE, EQTB_SIZE, FROZEN_NULL_FONT, NULL_CS,
3-
PRIM_EQTB_BASE, SCRIPT_SIZE, SINGLE_BASE, TEXT_SIZE, UNDEFINED_CONTROL_SEQUENCE,
2+
rs_gettexstring, CatCode, IntPar, NativeWordNode, Selector, ACTIVE_BASE, EQTB_SIZE,
3+
FROZEN_NULL_FONT, NULL_CS, PRIM_EQTB_BASE, SCRIPT_SIZE, SINGLE_BASE, TEXT_SIZE,
4+
UNDEFINED_CONTROL_SEQUENCE,
45
};
56
use crate::c_api::globals::Globals;
67
use crate::c_api::hash::HASH_BASE;
@@ -802,3 +803,57 @@ pub fn rs_print_size(globals: &mut Globals<'_, '_>, s: i32) {
802803
pub extern "C" fn print_size(s: i32) {
803804
Globals::with(|globals| rs_print_size(globals, s))
804805
}
806+
807+
pub fn rs_print_write_whatsit(globals: &mut Globals<'_, '_>, s: &[u8], p: i32) {
808+
rs_print_esc_bytes(globals, s);
809+
let p = p as usize;
810+
811+
let val = globals.engine.mem[p + 1].i32_0();
812+
if val < 16 {
813+
rs_print_int(globals, val)
814+
} else if val == 16 {
815+
rs_print_char(globals, '*' as i32);
816+
} else {
817+
rs_print_char(globals, '-' as i32);
818+
}
819+
}
820+
821+
#[no_mangle]
822+
pub extern "C" fn print_write_whatsit(s: *const libc::c_char, p: i32) {
823+
let s = unsafe { CStr::from_ptr(s) }.to_bytes();
824+
Globals::with(|globals| rs_print_write_whatsit(globals, s, p))
825+
}
826+
827+
pub fn rs_print_native_word(globals: &mut Globals<'_, '_>, p: i32) {
828+
let p = p as usize;
829+
let size = globals.engine.node::<NativeWordNode>(p).size();
830+
let mut skip = false;
831+
for i in 0..size {
832+
if skip {
833+
skip = false;
834+
continue;
835+
}
836+
837+
let node = globals.engine.node::<NativeWordNode>(p);
838+
let c = node.text()[i];
839+
if c >= 0xD800 && c < 0xDC00 {
840+
if i < size - 1 {
841+
let cc = node.text()[i + 1];
842+
if cc >= 0xDC00 && cc < 0xE000 {
843+
let c = 0x10000 + (c as i32 - 0xD800) * 1024 + (cc as i32 - 0xDC00);
844+
rs_print_char(globals, c);
845+
skip = true;
846+
}
847+
} else {
848+
rs_print(globals, '.' as i32);
849+
}
850+
} else {
851+
rs_print_char(globals, c as i32);
852+
}
853+
}
854+
}
855+
856+
#[no_mangle]
857+
pub extern "C" fn print_native_word(p: i32) {
858+
Globals::with(|globals| rs_print_native_word(globals, p))
859+
}

crates/engine_xetex/xetex/xetex-output.c

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,45 +9,6 @@
99
#include "tectonic_bridge_core.h"
1010
#include "xetex_bindings.h"
1111

12-
void
13-
print_write_whatsit(const char* s, int32_t p)
14-
{
15-
16-
print_esc_cstr(s);
17-
18-
if (mem(p + 1).b32.s0 < 16)
19-
print_int(mem(p + 1).b32.s0);
20-
else if (mem(p + 1).b32.s0 == 16)
21-
print_char('*');
22-
else
23-
print_char('-');
24-
}
25-
26-
27-
void
28-
print_native_word(int32_t p)
29-
{
30-
int32_t i, c, cc;
31-
int32_t for_end = mem(p + 4).b16.s1 - 1;
32-
33-
for (i = 0; i <= for_end; i++) {
34-
c = NATIVE_NODE_text(p)[i];
35-
if ((c >= 0xD800) && (c < 0xDC00)) {
36-
if (i < mem(p + 4).b16.s1 - 1) {
37-
cc = NATIVE_NODE_text(p)[i + 1];
38-
if ((cc >= 0xDC00) && (cc < 0xE000)) {
39-
c = 0x10000 + (c - 0xD800) * 1024 + (cc - 0xDC00);
40-
print_char(c);
41-
i++;
42-
} else
43-
print('.');
44-
} else
45-
print('.');
46-
} else
47-
print_char(c);
48-
}
49-
}
50-
5112

5213
void
5314
print_sa_num(int32_t q)

crates/engine_xetex/xetex/xetex_bindings.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232

3333
#define SCRIPT_SCRIPT_SIZE 512
3434

35+
#define NATIVE_NODE_SIZE 6
36+
3537
#define EQTB_SIZE 8941458
3638

3739
#define ACTIVE_BASE 1
@@ -280,6 +282,10 @@ void print_file_name(int32_t n, int32_t a, int32_t e);
280282

281283
void print_size(int32_t s);
282284

285+
void print_write_whatsit(const char *s, int32_t p);
286+
287+
void print_native_word(int32_t p);
288+
283289
void resize_str_pool(uintptr_t size);
284290

285291
void clear_str_pool(void);

0 commit comments

Comments
 (0)