Skip to main content

luaur_vm/functions/
lua_getargument.rs

1use crate::functions::getluaproto::get_lua_proto;
2use crate::functions::lua_a_pushvalue::luaA_pushvalue;
3use crate::functions::lua_c_barrierback::lua_c_barrierback;
4use crate::macros::lua_callinfo_native::LUA_CALLINFO_NATIVE;
5use crate::records::call_info::CallInfo;
6use crate::records::lua_state::lua_State;
7use crate::records::proto::Proto;
8
9#[no_mangle]
10pub unsafe fn lua_getargument(
11    l: *mut lua_State,
12    level: core::ffi::c_int,
13    n: core::ffi::c_int,
14) -> core::ffi::c_int {
15    if (level as u32) >= ((*l).ci.offset_from((*l).base_ci) as u32) {
16        return 0;
17    }
18
19    let ci: *mut CallInfo = (*l).ci.offset(-(level as isize));
20
21    // changing tables in native functions externally may invalidate safety contracts wrt table state (metatable/size/readonly)
22    if ((*ci).flags & LUA_CALLINFO_NATIVE as u32) != 0 {
23        return 0;
24    }
25
26    let fp: *mut Proto = get_lua_proto(ci);
27    let mut res: core::ffi::c_int = 0;
28
29    if !fp.is_null() && n > 0 {
30        if (n as u32) <= (*fp).numparams as u32 {
31            if ((*l).hdr.marked & 4) != 0 {
32                lua_c_barrierback(l, l as *mut _, &mut (*l).gclist);
33            }
34            luaA_pushvalue(l, (*ci).base.offset((n - 1) as isize));
35            res = 1;
36        } else if (*fp).is_vararg != 0 && (n as isize) < (*ci).base.offset_from((*ci).func) {
37            if ((*l).hdr.marked & 4) != 0 {
38                lua_c_barrierback(l, l as *mut _, &mut (*l).gclist);
39            }
40            luaA_pushvalue(l, (*ci).func.offset(n as isize));
41            res = 1;
42        }
43    }
44
45    res
46}