Skip to main content

luaur_vm/functions/
dumpthread.rs

1use crate::functions::dumpref::dumpref;
2use crate::functions::dumprefs::dumprefs;
3use crate::functions::dumpstringdata::dumpstringdata;
4use crate::functions::lua_f_findlocal::luaF_findlocal;
5use crate::macros::ci_func::ci_func;
6use crate::macros::clvalue::clvalue;
7use crate::macros::getstr::getstr;
8use crate::macros::is_lua::isLua;
9use crate::macros::iscollectable::iscollectable;
10use crate::macros::obj_2_gco::obj2gco;
11use crate::macros::pc_rel::pcRel;
12use crate::macros::ttisfunction::ttisfunction;
13use crate::records::call_info::CallInfo;
14use crate::records::closure::Closure;
15use crate::records::loc_var::LocVar;
16use crate::records::lua_state::lua_State;
17use crate::records::proto::Proto;
18use crate::type_aliases::stk_id::StkId;
19use crate::type_aliases::t_value::TValue;
20use core::ffi::{c_char, c_int, c_void};
21
22pub(crate) unsafe fn dumpthread(f: *mut c_void, th: *mut lua_State) {
23    extern "C" {
24        fn fprintf(stream: *mut c_void, format: *const c_char, ...) -> c_int;
25        fn fputc(c: c_int, stream: *mut c_void) -> c_int;
26    }
27
28    let size = core::mem::size_of::<lua_State>()
29        + core::mem::size_of::<TValue>() * (*th).stacksize as usize
30        + core::mem::size_of::<CallInfo>() * (*th).size_ci as usize;
31
32    fprintf(
33        f,
34        c"{\"type\":\"thread\",\"cat\":%d,\"size\":%d".as_ptr(),
35        (*th).hdr.memcat as c_int,
36        size as c_int,
37    );
38
39    fprintf(f, c",\"env\":".as_ptr());
40    dumpref(f, obj2gco!((*th).gt));
41
42    let mut tcl: *mut Closure = core::ptr::null_mut();
43    let mut ci = (*th).base_ci;
44    while ci <= (*th).ci {
45        if ttisfunction!((*ci).func) {
46            tcl = clvalue!((*ci).func);
47            break;
48        }
49        ci = ci.add(1);
50    }
51
52    if !tcl.is_null() && (*tcl).isC == 0 {
53        let tcl_l = core::ptr::addr_of!((*tcl).inner.l).cast::<crate::records::closure::LClosure>();
54        let tcl_p: *mut Proto = (*tcl_l).p;
55        if !(*tcl_p).source.is_null() {
56            let p: *mut Proto = tcl_p;
57            fprintf(f, c",\"source\":\"".as_ptr());
58            dumpstringdata(f, getstr((*p).source), (*(*p).source).len as usize);
59            fprintf(f, c"\",\"line\":%d".as_ptr(), (*p).linedefined);
60        }
61    }
62
63    if (*th).top > (*th).stack {
64        fprintf(f, c",\"stack\":[".as_ptr());
65        dumprefs(f, (*th).stack, (*th).top.offset_from((*th).stack) as usize);
66        fprintf(f, c"]".as_ptr());
67
68        let mut ci = (*th).base_ci;
69        let mut first = true;
70        fprintf(f, c",\"stacknames\":[".as_ptr());
71
72        let mut v: StkId = (*th).stack;
73        while v < (*th).top {
74            if iscollectable!(v) {
75                while ci < (*th).ci && v >= (*ci.add(1)).func {
76                    ci = ci.add(1);
77                }
78
79                if !first {
80                    fputc(',' as c_int, f);
81                }
82                first = false;
83
84                if v == (*ci).func {
85                    let cl = ci_func!(ci);
86                    if (*cl).isC != 0 {
87                        let c = core::ptr::addr_of!((*cl).inner.c)
88                            .cast::<crate::records::closure::CClosure>();
89                        fprintf(
90                            f,
91                            c"\"frame:%s\"".as_ptr(),
92                            if !(*c).debugname.is_null() {
93                                (*c).debugname
94                            } else {
95                                c"[C]".as_ptr()
96                            },
97                        );
98                    } else {
99                        let lcl = core::ptr::addr_of!((*cl).inner.l)
100                            .cast::<crate::records::closure::LClosure>();
101                        let p = (*lcl).p;
102                        fprintf(f, c"\"frame:".as_ptr());
103                        if !(*p).source.is_null() {
104                            dumpstringdata(f, getstr((*p).source), (*(*p).source).len as usize);
105                        }
106                        fprintf(
107                            f,
108                            c":%d:%s\"".as_ptr(),
109                            (*p).linedefined,
110                            if !(*p).debugname.is_null() {
111                                getstr((*p).debugname)
112                            } else {
113                                c"".as_ptr()
114                            },
115                        );
116                    }
117                } else if isLua!(ci) {
118                    let cl = ci_func!(ci);
119                    let lcl = core::ptr::addr_of!((*cl).inner.l)
120                        .cast::<crate::records::closure::LClosure>();
121                    let p = (*lcl).p;
122                    let pc = pcRel!((*ci).savedpc, p);
123                    let var: *const LocVar =
124                        luaF_findlocal(p, v.offset_from((*ci).base) as c_int, pc);
125
126                    if !var.is_null() && !(*var).varname.is_null() {
127                        fprintf(f, c"\"%s\"".as_ptr(), getstr((*var).varname));
128                    } else {
129                        fprintf(f, c"null".as_ptr());
130                    }
131                } else {
132                    fprintf(f, c"null".as_ptr());
133                }
134            }
135
136            v = v.add(1);
137        }
138        fprintf(f, c"]".as_ptr());
139    }
140
141    fprintf(f, c"}".as_ptr());
142}