diff options
| author | Mike Pall <mike> | 2012-06-14 19:54:07 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2012-06-14 19:54:07 +0200 |
| commit | 946c7418d59dd201386ee66686075595754cd86d (patch) | |
| tree | 1930adb8b7f969b8b69ed3b634fd1736e7d5944e /src | |
| parent | ca6bf2d9a41fb2c0c80bafdbaf2e29421b2cb55d (diff) | |
| download | luajit-946c7418d59dd201386ee66686075595754cd86d.tar.gz luajit-946c7418d59dd201386ee66686075595754cd86d.tar.bz2 luajit-946c7418d59dd201386ee66686075595754cd86d.zip | |
FFI: Add support for parameterized C types.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib_ffi.c | 21 | ||||
| -rw-r--r-- | src/lj_cparse.c | 44 | ||||
| -rw-r--r-- | src/lj_cparse.h | 1 | ||||
| -rw-r--r-- | src/lj_errmsg.h | 1 |
4 files changed, 57 insertions, 10 deletions
diff --git a/src/lib_ffi.c b/src/lib_ffi.c index 2a674b88..f4097041 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | /* -- C type checks ------------------------------------------------------- */ | 35 | /* -- C type checks ------------------------------------------------------- */ |
| 36 | 36 | ||
| 37 | /* Check first argument for a C type and returns its ID. */ | 37 | /* Check first argument for a C type and returns its ID. */ |
| 38 | static CTypeID ffi_checkctype(lua_State *L, CTState *cts) | 38 | static CTypeID ffi_checkctype(lua_State *L, CTState *cts, TValue *param) |
| 39 | { | 39 | { |
| 40 | TValue *o = L->base; | 40 | TValue *o = L->base; |
| 41 | if (!(o < L->top)) { | 41 | if (!(o < L->top)) { |
| @@ -50,6 +50,7 @@ static CTypeID ffi_checkctype(lua_State *L, CTState *cts) | |||
| 50 | cp.cts = cts; | 50 | cp.cts = cts; |
| 51 | cp.srcname = strdata(s); | 51 | cp.srcname = strdata(s); |
| 52 | cp.p = strdata(s); | 52 | cp.p = strdata(s); |
| 53 | cp.param = param; | ||
| 53 | cp.mode = CPARSE_MODE_ABSTRACT|CPARSE_MODE_NOIMPLICIT; | 54 | cp.mode = CPARSE_MODE_ABSTRACT|CPARSE_MODE_NOIMPLICIT; |
| 54 | errcode = lj_cparse(&cp); | 55 | errcode = lj_cparse(&cp); |
| 55 | if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */ | 56 | if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */ |
| @@ -57,6 +58,7 @@ static CTypeID ffi_checkctype(lua_State *L, CTState *cts) | |||
| 57 | } else { | 58 | } else { |
| 58 | GCcdata *cd; | 59 | GCcdata *cd; |
| 59 | if (!tviscdata(o)) goto err_argtype; | 60 | if (!tviscdata(o)) goto err_argtype; |
| 61 | if (param && param < L->top) lj_err_arg(L, 1, LJ_ERR_FFI_NUMPARAM); | ||
| 60 | cd = cdataV(o); | 62 | cd = cdataV(o); |
| 61 | return cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->typeid; | 63 | return cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->typeid; |
| 62 | } | 64 | } |
| @@ -442,6 +444,7 @@ LJLIB_CF(ffi_cdef) | |||
| 442 | cp.cts = ctype_cts(L); | 444 | cp.cts = ctype_cts(L); |
| 443 | cp.srcname = strdata(s); | 445 | cp.srcname = strdata(s); |
| 444 | cp.p = strdata(s); | 446 | cp.p = strdata(s); |
| 447 | cp.param = L->base+1; | ||
| 445 | cp.mode = CPARSE_MODE_MULTI|CPARSE_MODE_DIRECT; | 448 | cp.mode = CPARSE_MODE_MULTI|CPARSE_MODE_DIRECT; |
| 446 | errcode = lj_cparse(&cp); | 449 | errcode = lj_cparse(&cp); |
| 447 | if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */ | 450 | if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */ |
| @@ -452,7 +455,7 @@ LJLIB_CF(ffi_cdef) | |||
| 452 | LJLIB_CF(ffi_new) LJLIB_REC(.) | 455 | LJLIB_CF(ffi_new) LJLIB_REC(.) |
| 453 | { | 456 | { |
| 454 | CTState *cts = ctype_cts(L); | 457 | CTState *cts = ctype_cts(L); |
| 455 | CTypeID id = ffi_checkctype(L, cts); | 458 | CTypeID id = ffi_checkctype(L, cts, NULL); |
| 456 | CType *ct = ctype_raw(cts, id); | 459 | CType *ct = ctype_raw(cts, id); |
| 457 | CTSize sz; | 460 | CTSize sz; |
| 458 | CTInfo info = lj_ctype_info(cts, id, &sz); | 461 | CTInfo info = lj_ctype_info(cts, id, &sz); |
| @@ -492,7 +495,7 @@ LJLIB_CF(ffi_new) LJLIB_REC(.) | |||
| 492 | LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new) | 495 | LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new) |
| 493 | { | 496 | { |
| 494 | CTState *cts = ctype_cts(L); | 497 | CTState *cts = ctype_cts(L); |
| 495 | CTypeID id = ffi_checkctype(L, cts); | 498 | CTypeID id = ffi_checkctype(L, cts, NULL); |
| 496 | CType *d = ctype_raw(cts, id); | 499 | CType *d = ctype_raw(cts, id); |
| 497 | TValue *o = lj_lib_checkany(L, 2); | 500 | TValue *o = lj_lib_checkany(L, 2); |
| 498 | L->top = o+1; /* Make sure this is the last item on the stack. */ | 501 | L->top = o+1; /* Make sure this is the last item on the stack. */ |
| @@ -510,7 +513,7 @@ LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new) | |||
| 510 | LJLIB_CF(ffi_typeof) | 513 | LJLIB_CF(ffi_typeof) |
| 511 | { | 514 | { |
| 512 | CTState *cts = ctype_cts(L); | 515 | CTState *cts = ctype_cts(L); |
| 513 | CTypeID id = ffi_checkctype(L, cts); | 516 | CTypeID id = ffi_checkctype(L, cts, L->base+1); |
| 514 | GCcdata *cd = lj_cdata_new(cts, CTID_CTYPEID, 4); | 517 | GCcdata *cd = lj_cdata_new(cts, CTID_CTYPEID, 4); |
| 515 | *(CTypeID *)cdataptr(cd) = id; | 518 | *(CTypeID *)cdataptr(cd) = id; |
| 516 | setcdataV(L, L->top-1, cd); | 519 | setcdataV(L, L->top-1, cd); |
| @@ -521,7 +524,7 @@ LJLIB_CF(ffi_typeof) | |||
| 521 | LJLIB_CF(ffi_istype) LJLIB_REC(ffi_istype) | 524 | LJLIB_CF(ffi_istype) LJLIB_REC(ffi_istype) |
| 522 | { | 525 | { |
| 523 | CTState *cts = ctype_cts(L); | 526 | CTState *cts = ctype_cts(L); |
| 524 | CTypeID id1 = ffi_checkctype(L, cts); | 527 | CTypeID id1 = ffi_checkctype(L, cts, NULL); |
| 525 | TValue *o = lj_lib_checkany(L, 2); | 528 | TValue *o = lj_lib_checkany(L, 2); |
| 526 | int b = 0; | 529 | int b = 0; |
| 527 | if (tviscdata(o)) { | 530 | if (tviscdata(o)) { |
| @@ -551,7 +554,7 @@ LJLIB_CF(ffi_istype) LJLIB_REC(ffi_istype) | |||
| 551 | LJLIB_CF(ffi_sizeof) | 554 | LJLIB_CF(ffi_sizeof) |
| 552 | { | 555 | { |
| 553 | CTState *cts = ctype_cts(L); | 556 | CTState *cts = ctype_cts(L); |
| 554 | CTypeID id = ffi_checkctype(L, cts); | 557 | CTypeID id = ffi_checkctype(L, cts, NULL); |
| 555 | CTSize sz; | 558 | CTSize sz; |
| 556 | if (LJ_UNLIKELY(tviscdata(L->base) && cdataisv(cdataV(L->base)))) { | 559 | if (LJ_UNLIKELY(tviscdata(L->base) && cdataisv(cdataV(L->base)))) { |
| 557 | sz = cdatavlen(cdataV(L->base)); | 560 | sz = cdatavlen(cdataV(L->base)); |
| @@ -573,7 +576,7 @@ LJLIB_CF(ffi_sizeof) | |||
| 573 | LJLIB_CF(ffi_alignof) | 576 | LJLIB_CF(ffi_alignof) |
| 574 | { | 577 | { |
| 575 | CTState *cts = ctype_cts(L); | 578 | CTState *cts = ctype_cts(L); |
| 576 | CTypeID id = ffi_checkctype(L, cts); | 579 | CTypeID id = ffi_checkctype(L, cts, NULL); |
| 577 | CTSize sz = 0; | 580 | CTSize sz = 0; |
| 578 | CTInfo info = lj_ctype_info(cts, id, &sz); | 581 | CTInfo info = lj_ctype_info(cts, id, &sz); |
| 579 | setintV(L->top-1, 1 << ctype_align(info)); | 582 | setintV(L->top-1, 1 << ctype_align(info)); |
| @@ -583,7 +586,7 @@ LJLIB_CF(ffi_alignof) | |||
| 583 | LJLIB_CF(ffi_offsetof) | 586 | LJLIB_CF(ffi_offsetof) |
| 584 | { | 587 | { |
| 585 | CTState *cts = ctype_cts(L); | 588 | CTState *cts = ctype_cts(L); |
| 586 | CTypeID id = ffi_checkctype(L, cts); | 589 | CTypeID id = ffi_checkctype(L, cts, NULL); |
| 587 | GCstr *name = lj_lib_checkstr(L, 2); | 590 | GCstr *name = lj_lib_checkstr(L, 2); |
| 588 | CType *ct = lj_ctype_rawref(cts, id); | 591 | CType *ct = lj_ctype_rawref(cts, id); |
| 589 | CTSize ofs; | 592 | CTSize ofs; |
| @@ -700,7 +703,7 @@ LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */ | |||
| 700 | LJLIB_CF(ffi_metatype) | 703 | LJLIB_CF(ffi_metatype) |
| 701 | { | 704 | { |
| 702 | CTState *cts = ctype_cts(L); | 705 | CTState *cts = ctype_cts(L); |
| 703 | CTypeID id = ffi_checkctype(L, cts); | 706 | CTypeID id = ffi_checkctype(L, cts, NULL); |
| 704 | GCtab *mt = lj_lib_checktab(L, 2); | 707 | GCtab *mt = lj_lib_checktab(L, 2); |
| 705 | GCtab *t = cts->miscmap; | 708 | GCtab *t = cts->miscmap; |
| 706 | CType *ct = ctype_get(cts, id); /* Only allow raw types. */ | 709 | CType *ct = ctype_get(cts, id); /* Only allow raw types. */ |
diff --git a/src/lj_cparse.c b/src/lj_cparse.c index ff5abc70..0f8c2857 100644 --- a/src/lj_cparse.c +++ b/src/lj_cparse.c | |||
| @@ -121,6 +121,7 @@ LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...) | |||
| 121 | tokstr = NULL; | 121 | tokstr = NULL; |
| 122 | } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING || | 122 | } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING || |
| 123 | tok >= CTOK_FIRSTDECL) { | 123 | tok >= CTOK_FIRSTDECL) { |
| 124 | if (cp->sb.n == 0) cp_save(cp, '$'); | ||
| 124 | cp_save(cp, '\0'); | 125 | cp_save(cp, '\0'); |
| 125 | tokstr = cp->sb.buf; | 126 | tokstr = cp->sb.buf; |
| 126 | } else { | 127 | } else { |
| @@ -203,6 +204,38 @@ static CPToken cp_ident(CPState *cp) | |||
| 203 | return CTOK_IDENT; | 204 | return CTOK_IDENT; |
| 204 | } | 205 | } |
| 205 | 206 | ||
| 207 | /* Parse parameter. */ | ||
| 208 | static CPToken cp_param(CPState *cp) | ||
| 209 | { | ||
| 210 | CPChar c = cp_get(cp); | ||
| 211 | TValue *o = cp->param; | ||
| 212 | if (lj_char_isident(c) || c == '$') /* Reserve $xyz for future extensions. */ | ||
| 213 | cp_errmsg(cp, c, LJ_ERR_XSYNTAX); | ||
| 214 | if (!o || o >= cp->L->top) | ||
| 215 | cp_err(cp, LJ_ERR_FFI_NUMPARAM); | ||
| 216 | cp->param = o+1; | ||
| 217 | if (tvisstr(o)) { | ||
| 218 | cp->str = strV(o); | ||
| 219 | cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask); | ||
| 220 | if (ctype_type(cp->ct->info) == CT_KW) | ||
| 221 | return ctype_cid(cp->ct->info); | ||
| 222 | return CTOK_IDENT; | ||
| 223 | } else if (tvisnumber(o)) { | ||
| 224 | cp->val.i32 = numberVint(o); | ||
| 225 | cp->val.id = CTID_INT32; | ||
| 226 | return CTOK_INTEGER; | ||
| 227 | } else { | ||
| 228 | GCcdata *cd; | ||
| 229 | if (!tviscdata(o)) lj_err_argtype(cp->L, o-cp->L->base+1, "type parameter"); | ||
| 230 | cd = cdataV(o); | ||
| 231 | if (cd->typeid == CTID_CTYPEID) | ||
| 232 | cp->val.id = *(CTypeID *)cdataptr(cd); | ||
| 233 | else | ||
| 234 | cp->val.id = cd->typeid; | ||
| 235 | return '$'; | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 206 | /* Parse string or character constant. */ | 239 | /* Parse string or character constant. */ |
| 207 | static CPToken cp_string(CPState *cp) | 240 | static CPToken cp_string(CPState *cp) |
| 208 | { | 241 | { |
| @@ -317,6 +350,8 @@ static CPToken cp_next_(CPState *cp) | |||
| 317 | return '>'; | 350 | return '>'; |
| 318 | case '-': | 351 | case '-': |
| 319 | cp_get(cp); if (cp->c != '>') return '-'; cp_get(cp); return CTOK_DEREF; | 352 | cp_get(cp); if (cp->c != '>') return '-'; cp_get(cp); return CTOK_DEREF; |
| 353 | case '$': | ||
| 354 | return cp_param(cp); | ||
| 320 | case '\0': return CTOK_EOF; | 355 | case '\0': return CTOK_EOF; |
| 321 | default: { CPToken c = cp->c; cp_get(cp); return c; } | 356 | default: { CPToken c = cp->c; cp_get(cp); return c; } |
| 322 | } | 357 | } |
| @@ -403,6 +438,7 @@ static int cp_istypedecl(CPState *cp) | |||
| 403 | { | 438 | { |
| 404 | if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1; | 439 | if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1; |
| 405 | if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1; | 440 | if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1; |
| 441 | if (cp->tok == '$') return 1; | ||
| 406 | return 0; | 442 | return 0; |
| 407 | } | 443 | } |
| 408 | 444 | ||
| @@ -1441,7 +1477,7 @@ static CTypeID cp_decl_enum(CPState *cp, CPDecl *sdecl) | |||
| 1441 | static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl) | 1477 | static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl) |
| 1442 | { | 1478 | { |
| 1443 | uint32_t cds = 0, sz = 0; | 1479 | uint32_t cds = 0, sz = 0; |
| 1444 | CTInfo tdef = 0; | 1480 | CTypeID tdef = 0; |
| 1445 | 1481 | ||
| 1446 | decl->cp = cp; | 1482 | decl->cp = cp; |
| 1447 | decl->mode = cp->mode; | 1483 | decl->mode = cp->mode; |
| @@ -1471,6 +1507,10 @@ static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl) | |||
| 1471 | tdef = ctype_cid(cp->ct->info); /* Get typedef. */ | 1507 | tdef = ctype_cid(cp->ct->info); /* Get typedef. */ |
| 1472 | cp_next(cp); | 1508 | cp_next(cp); |
| 1473 | break; | 1509 | break; |
| 1510 | case '$': | ||
| 1511 | tdef = cp->val.id; | ||
| 1512 | cp_next(cp); | ||
| 1513 | break; | ||
| 1474 | default: | 1514 | default: |
| 1475 | if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) { | 1515 | if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) { |
| 1476 | uint32_t cbit; | 1516 | uint32_t cbit; |
| @@ -1826,6 +1866,8 @@ static TValue *cpcparser(lua_State *L, lua_CFunction dummy, void *ud) | |||
| 1826 | cp_decl_multi(cp); | 1866 | cp_decl_multi(cp); |
| 1827 | else | 1867 | else |
| 1828 | cp_decl_single(cp); | 1868 | cp_decl_single(cp); |
| 1869 | if (cp->param && cp->param != cp->L->top) | ||
| 1870 | cp_err(cp, LJ_ERR_FFI_NUMPARAM); | ||
| 1829 | lua_assert(cp->depth == 0); | 1871 | lua_assert(cp->depth == 0); |
| 1830 | return NULL; | 1872 | return NULL; |
| 1831 | } | 1873 | } |
diff --git a/src/lj_cparse.h b/src/lj_cparse.h index eaa1bdb5..29188c69 100644 --- a/src/lj_cparse.h +++ b/src/lj_cparse.h | |||
| @@ -48,6 +48,7 @@ typedef struct CPState { | |||
| 48 | SBuf sb; /* String buffer for tokens. */ | 48 | SBuf sb; /* String buffer for tokens. */ |
| 49 | lua_State *L; /* Lua state. */ | 49 | lua_State *L; /* Lua state. */ |
| 50 | CTState *cts; /* C type state. */ | 50 | CTState *cts; /* C type state. */ |
| 51 | TValue *param; /* C type parameters. */ | ||
| 51 | const char *srcname; /* Current source name. */ | 52 | const char *srcname; /* Current source name. */ |
| 52 | BCLine linenumber; /* Input line counter. */ | 53 | BCLine linenumber; /* Input line counter. */ |
| 53 | int depth; /* Recursive declaration depth. */ | 54 | int depth; /* Recursive declaration depth. */ |
diff --git a/src/lj_errmsg.h b/src/lj_errmsg.h index 5ba619bf..2d677cca 100644 --- a/src/lj_errmsg.h +++ b/src/lj_errmsg.h | |||
| @@ -149,6 +149,7 @@ ERRDEF(FFI_BADSCL, "bad storage class") | |||
| 149 | ERRDEF(FFI_DECLSPEC, "declaration specifier expected") | 149 | ERRDEF(FFI_DECLSPEC, "declaration specifier expected") |
| 150 | ERRDEF(FFI_BADTAG, "undeclared or implicit tag " LUA_QS) | 150 | ERRDEF(FFI_BADTAG, "undeclared or implicit tag " LUA_QS) |
| 151 | ERRDEF(FFI_REDEF, "attempt to redefine " LUA_QS) | 151 | ERRDEF(FFI_REDEF, "attempt to redefine " LUA_QS) |
| 152 | ERRDEF(FFI_NUMPARAM, "wrong number of type parameters") | ||
| 152 | ERRDEF(FFI_INITOV, "too many initializers for " LUA_QS) | 153 | ERRDEF(FFI_INITOV, "too many initializers for " LUA_QS) |
| 153 | ERRDEF(FFI_BADCONV, "cannot convert " LUA_QS " to " LUA_QS) | 154 | ERRDEF(FFI_BADCONV, "cannot convert " LUA_QS " to " LUA_QS) |
| 154 | ERRDEF(FFI_BADLEN, "attempt to get length of " LUA_QS) | 155 | ERRDEF(FFI_BADLEN, "attempt to get length of " LUA_QS) |
