luaur_vm/functions/
dumpthread.rs1use 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}