Skip to main content

luaur_vm/functions/
enumthread.rs

1use crate::functions::enumedge::enumedge;
2use crate::functions::enumedges::enumedges;
3use crate::functions::enumnode::enumnode;
4use crate::macros::clvalue::clvalue;
5use crate::macros::getstr::getstr;
6use crate::macros::lua_idsize::LUA_IDSIZE;
7use crate::macros::obj_2_gco::obj2gco;
8use crate::macros::ttisfunction::ttisfunction;
9use crate::records::call_info::CallInfo;
10use crate::records::enum_context::EnumContext;
11use crate::records::gc_object::GCObject;
12use crate::records::lua_state::lua_State;
13use crate::records::proto::Proto;
14use crate::records::t_string::TString;
15use crate::type_aliases::closure::Closure;
16use crate::type_aliases::t_value::TValue;
17use core::ffi::{c_char, c_int};
18
19#[allow(non_snake_case)]
20pub unsafe fn enumthread(ctx: *mut EnumContext, th: *mut lua_State) {
21    let size = core::mem::size_of::<lua_State>()
22        + core::mem::size_of::<TValue>() * (*th).stacksize as usize
23        + core::mem::size_of::<CallInfo>() * (*th).size_ci as usize;
24
25    let mut tcl: *mut Closure = core::ptr::null_mut();
26    let mut ci: *mut CallInfo = (*th).base_ci;
27    while ci <= (*th).ci {
28        if ttisfunction!((*ci).func) {
29            tcl = clvalue!((*ci).func);
30            break;
31        }
32        ci = ci.wrapping_add(1);
33    }
34
35    if !tcl.is_null() && (*tcl).isC == 0 {
36        let tcl_l = core::ptr::addr_of!((*tcl).inner.l).cast::<crate::records::closure::LClosure>();
37        let p: *mut Proto = (*tcl_l).p;
38        if !p.is_null() {
39            let mut buf: [c_char; 256] = [0; 256];
40
41            let src_str = if !(*p).source.is_null() {
42                getstr((*p).source)
43            } else {
44                c"unnamed".as_ptr()
45            };
46            let debugname_str = if !(*p).debugname.is_null() {
47                getstr((*p).debugname)
48            } else {
49                c"unnamed".as_ptr()
50            };
51
52            let _ = snprintf(
53                buf.as_mut_ptr(),
54                buf.len() as u32,
55                c"thread at %s:%d %s".as_ptr(),
56                debugname_str,
57                (*p).linedefined,
58                src_str,
59            );
60
61            enumnode(ctx, obj2gco!(th as *mut GCObject), size, buf.as_ptr());
62        } else {
63            enumnode(ctx, obj2gco!(th as *mut GCObject), size, core::ptr::null());
64        }
65    } else {
66        enumnode(ctx, obj2gco!(th as *mut GCObject), size, core::ptr::null());
67    }
68
69    enumedge(
70        ctx,
71        obj2gco!(th as *mut GCObject),
72        obj2gco!((*th).gt as *mut GCObject),
73        c"globals".as_ptr(),
74    );
75
76    if (*th).top > (*th).stack {
77        enumedges(
78            ctx,
79            obj2gco!(th as *mut GCObject),
80            (*th).stack,
81            (*th).top.offset_from((*th).stack) as usize,
82            c"stack".as_ptr(),
83        );
84    }
85}
86
87// snprintf is not available in core::ffi, but luau-vm already provides it via lobject.h
88extern "C" {
89    fn snprintf(s: *mut c_char, n: u32, format: *const c_char, ...) -> c_int;
90}