diff options
Diffstat (limited to 'src/lj_carith.c')
-rw-r--r-- | src/lj_carith.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/src/lj_carith.c b/src/lj_carith.c index c5275f70..8c76abe9 100644 --- a/src/lj_carith.c +++ b/src/lj_carith.c | |||
@@ -46,6 +46,7 @@ static int carith_checkarg(lua_State *L, CTState *cts, CDArith *ca) | |||
46 | ct = ctype_get(cts, | 46 | ct = ctype_get(cts, |
47 | lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|id), CTSIZE_PTR)); | 47 | lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|id), CTSIZE_PTR)); |
48 | } | 48 | } |
49 | if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); | ||
49 | ca->ct[i] = ct; | 50 | ca->ct[i] = ct; |
50 | ca->p[i] = p; | 51 | ca->p[i] = p; |
51 | } else if (tvisint(o)) { | 52 | } else if (tvisint(o)) { |
@@ -57,6 +58,25 @@ static int carith_checkarg(lua_State *L, CTState *cts, CDArith *ca) | |||
57 | } else if (tvisnil(o)) { | 58 | } else if (tvisnil(o)) { |
58 | ca->ct[i] = ctype_get(cts, CTID_P_VOID); | 59 | ca->ct[i] = ctype_get(cts, CTID_P_VOID); |
59 | ca->p[i] = (uint8_t *)0; | 60 | ca->p[i] = (uint8_t *)0; |
61 | } else if (tvisstr(o)) { | ||
62 | TValue *o2 = i == 0 ? o+1 : o-1; | ||
63 | CType *ct = ctype_raw(cts, cdataV(o2)->ctypeid); | ||
64 | ca->ct[i] = NULL; | ||
65 | ca->p[i] = NULL; | ||
66 | ok = 0; | ||
67 | if (ctype_isenum(ct->info)) { | ||
68 | CTSize ofs; | ||
69 | CType *cct = lj_ctype_getfield(cts, ct, strV(o), &ofs); | ||
70 | if (cct && ctype_isconstval(cct->info)) { | ||
71 | ca->ct[i] = ctype_child(cts, cct); | ||
72 | ca->p[i] = (uint8_t *)&cct->size; /* Assumes ct does not grow. */ | ||
73 | ok = 1; | ||
74 | } else { | ||
75 | ca->ct[1-i] = ct; /* Use enum to improve error message. */ | ||
76 | ca->p[1-i] = NULL; | ||
77 | break; | ||
78 | } | ||
79 | } | ||
60 | } else { | 80 | } else { |
61 | ca->ct[i] = NULL; | 81 | ca->ct[i] = NULL; |
62 | ca->p[i] = NULL; | 82 | ca->p[i] = NULL; |
@@ -204,17 +224,22 @@ static int lj_carith_meta(lua_State *L, CTState *cts, CDArith *ca, MMS mm) | |||
204 | tv = lj_ctype_meta(cts, cdataV(L->base+1)->ctypeid, mm); | 224 | tv = lj_ctype_meta(cts, cdataV(L->base+1)->ctypeid, mm); |
205 | if (!tv) { | 225 | if (!tv) { |
206 | const char *repr[2]; | 226 | const char *repr[2]; |
207 | int i; | 227 | int i, isenum = -1, isstr = -1; |
208 | if (mm == MM_eq) { /* Equality checks never raise an error. */ | 228 | if (mm == MM_eq) { /* Equality checks never raise an error. */ |
209 | setboolV(L->top-1, 0); | 229 | setboolV(L->top-1, 0); |
210 | return 1; | 230 | return 1; |
211 | } | 231 | } |
212 | for (i = 0; i < 2; i++) { | 232 | for (i = 0; i < 2; i++) { |
213 | if (ca->ct[i]) | 233 | if (ca->ct[i]) { |
234 | if (ctype_isenum(ca->ct[i]->info)) isenum = i; | ||
214 | repr[i] = strdata(lj_ctype_repr(L, ctype_typeid(cts, ca->ct[i]), NULL)); | 235 | repr[i] = strdata(lj_ctype_repr(L, ctype_typeid(cts, ca->ct[i]), NULL)); |
215 | else | 236 | } else { |
237 | if (tvisstr(&L->base[i])) isstr = i; | ||
216 | repr[i] = lj_typename(&L->base[i]); | 238 | repr[i] = lj_typename(&L->base[i]); |
239 | } | ||
217 | } | 240 | } |
241 | if ((isenum ^ isstr) == 1) | ||
242 | lj_err_callerv(L, LJ_ERR_FFI_BADCONV, repr[isstr], repr[isenum]); | ||
218 | lj_err_callerv(L, mm == MM_len ? LJ_ERR_FFI_BADLEN : | 243 | lj_err_callerv(L, mm == MM_len ? LJ_ERR_FFI_BADLEN : |
219 | mm == MM_concat ? LJ_ERR_FFI_BADCONCAT : | 244 | mm == MM_concat ? LJ_ERR_FFI_BADCONCAT : |
220 | mm < MM_add ? LJ_ERR_FFI_BADCOMP : LJ_ERR_FFI_BADARITH, | 245 | mm < MM_add ? LJ_ERR_FFI_BADCOMP : LJ_ERR_FFI_BADARITH, |