/* Bad conversion. */ LJ_NORET static void cconv_err_conv(CTState *cts, CType *d, CType *s, CTInfo flags) { const char *dst = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, d), NULL)); const char *src; if ((flags & CCF_FROMTV)) src = lj_obj_typename[1+(ctype_isnum(s->info) ? LUA_TNUMBER : ctype_isarray(s->info) ? LUA_TSTRING : LUA_TNIL)]; else src = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, s), NULL)); if (CCF_GETARG(flags)) lj_err_argv(cts->L, CCF_GETARG(flags), LJ_ERR_FFI_BADCONV, src, dst); else lj_err_callerv(cts->L, LJ_ERR_FFI_BADCONV, src, dst); }
/* Handle ctype __index/__newindex metamethods. */ static int ffi_index_meta(lua_State *L, CTState *cts, CType *ct, MMS mm) { CTypeID id = ctype_typeid(cts, ct); cTValue *tv = lj_ctype_meta(cts, id, mm); TValue *base = L->base; if (!tv) { const char *s; err_index: s = strdata(lj_ctype_repr(L, id, NULL)); if (tvisstr(L->base+1)) lj_err_callerv(L, LJ_ERR_FFI_BADMEMBER, s, strVdata(L->base+1)); else lj_err_callerv(L, LJ_ERR_FFI_BADIDX, s); } if (!tvisfunc(tv)) { if (mm == MM_index) { cTValue *o = lj_meta_tget(L, tv, base+1); if (o) { if (tvisnil(o)) goto err_index; copyTV(L, L->top-1, o); return 1; } } else { TValue *o = lj_meta_tset(L, tv, base+1); if (o) { copyTV(L, o, base+2); return 0; } } tv = L->top-1; } return lj_meta_tailcall(L, tv); }
/* Bad conversion from TValue. */ LJ_NORET static void cconv_err_convtv(CTState *cts, CType *d, TValue *o, CTInfo flags) { const char *dst = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, d), NULL)); const char *src = lj_typename(o); if (CCF_GETARG(flags)) lj_err_argv(cts->L, CCF_GETARG(flags), LJ_ERR_FFI_BADCONV, src, dst); else lj_err_callerv(cts->L, LJ_ERR_FFI_BADCONV, src, dst); }
/* Convert C type to TValue. Caveat: expects to get the raw CType! */ int lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid, TValue *o, uint8_t *sp) { CTInfo sinfo = s->info; lua_assert(!ctype_isenum(sinfo)); if (ctype_isnum(sinfo)) { if (!ctype_isbool(sinfo)) { if (ctype_isinteger(sinfo) && s->size > 4) goto copyval; if (LJ_DUALNUM && ctype_isinteger(sinfo)) { int32_t i; lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT32), s, (uint8_t *)&i, sp, 0); if ((sinfo & CTF_UNSIGNED) && i < 0) setnumV(o, (lua_Number)(uint32_t)i); else setintV(o, i); } else { lj_cconv_ct_ct(cts, ctype_get(cts, CTID_DOUBLE), s, (uint8_t *)&o->n, sp, 0); /* Numbers are NOT canonicalized here! Beware of uninitialized data. */ lua_assert(tvisnum(o)); } } else { uint32_t b = ((*sp) & 1); setboolV(o, b); setboolV(&cts->g->tmptv2, b); /* Remember for trace recorder. */ } return 0; } else if (ctype_isrefarray(sinfo) || ctype_isstruct(sinfo)) { /* Create reference. */ setcdataV(cts->L, o, lj_cdata_newref(cts, sp, sid)); return 1; /* Need GC step. */ } else { GCcdata *cd; CTSize sz; copyval: /* Copy value. */ sz = s->size; lua_assert(sz != CTSIZE_INVALID); /* Attributes are stripped, qualifiers are kept (but mostly ignored). */ cd = lj_cdata_new(cts, ctype_typeid(cts, s), sz); setcdataV(cts->L, o, cd); memcpy(cdataptr(cd), sp, sz); return 1; /* Need GC step. */ } }
/* Initializer overflow. */ LJ_NORET static void cconv_err_initov(CTState *cts, CType *d) { const char *dst = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, d), NULL)); lj_err_callerv(cts->L, LJ_ERR_FFI_INITOV, dst); }