terom@143: #include "lua_func.h" terom@143: #include "error.h" terom@143: terom@143: #include terom@143: terom@143: /** terom@143: * Pushes onto the stack the value at t[i] terom@143: */ terom@143: static void lua_getindex (lua_State *L, int t, int i) terom@143: { terom@143: lua_pushinteger(L, i); terom@143: lua_gettable(L, t); terom@143: } terom@143: terom@143: /** terom@143: * Pushes onto the stack either: terom@143: * * the value at t[name] terom@143: * * the value at t[index] terom@143: * terom@143: * Returns the new index, or 0, if neither could be found terom@143: */ terom@143: static int lua_arg_lookup (lua_State *L, int t, const char *name, int index) terom@143: { terom@143: // try name terom@143: lua_getfield(L, t, name); terom@143: terom@143: if (!lua_isnil(L, -1)) terom@143: return lua_gettop(L); terom@143: else terom@143: lua_pop(L, 1); terom@143: terom@143: // try index terom@143: lua_getindex(L, t, index); terom@143: terom@143: if (!lua_isnil(L, -1)) terom@143: return lua_gettop(L); terom@143: terom@143: else terom@143: lua_pop(L, 1); terom@143: terom@143: // not found terom@143: return 0; terom@143: } terom@143: terom@143: static const char *_lua_arg_string (lua_State *L, int index, const char *name, const char *def) terom@143: { terom@143: const char *value; terom@143: terom@143: // use default? terom@143: if (lua_isnoneornil(L, index) && def != (const char *) LUA_ARG_REQUIRED) terom@143: return def; terom@143: terom@143: // value given? terom@143: if ((value = lua_tostring(L, index))) terom@143: return value; terom@143: terom@143: // error terom@143: luaL_error(L, "missing value for required string argument <%d:%s>", index, name); return NULL; terom@143: } terom@143: terom@143: static bool _lua_arg_bool (lua_State *L, int index, const char *name, int def) terom@143: { terom@143: (void) name; terom@143: terom@143: // use default? terom@143: if (lua_isnoneornil(L, index) && def != LUA_ARG_REQUIRED) terom@143: return def; terom@143: terom@143: // value given terom@143: return lua_toboolean(L, index); terom@143: } terom@143: terom@201: static long _lua_arg_int (lua_State *L, int index, const char *name, long def) terom@201: { terom@201: (void) name; terom@201: terom@201: // use default? terom@201: if (lua_isnoneornil(L, index) && def != LUA_ARG_REQUIRED) terom@201: return def; terom@201: terom@201: // conver to integer terom@201: // XXX: check compatibility? terom@201: return lua_tointeger(L, index); terom@201: } terom@201: terom@199: static void * _lua_arg_obj (lua_State *L, int index, const struct lua_type *type, bool optional) terom@199: { terom@199: // not given? terom@199: if (!lua_isnoneornil(L, index)) terom@199: return lua_type_get(L, type, index); terom@199: terom@199: if (optional) terom@199: return NULL; terom@199: terom@199: luaL_error(L, "missing value for required object argument <%d:%s>", index, type->name); terom@199: return NULL; terom@199: } terom@199: terom@143: /** terom@143: * Look up the arg index to use for the given index/name. terom@143: * terom@143: * If no value is found for the corresponding index, returns zero. terom@143: */ terom@143: static int lua_arg_index (lua_State *L, int nargs, int index, const char *name) terom@143: { terom@143: // lookup from table? terom@199: if (nargs == 2 && lua_istable(L, 2) && name) { terom@199: // push the value from the named field onto the stack terom@143: lua_getfield(L, 2, name); terom@143: terom@143: // no named field? terom@143: if (lua_isnil(L, -1)) { terom@143: lua_pop(L, 1); terom@143: terom@143: lua_getindex(L, 2, index - 1); terom@143: } terom@143: terom@143: // no index field? terom@143: if (lua_isnil(L, -1)) { terom@143: lua_pop(L, 1); terom@143: terom@143: return 0; terom@143: } terom@143: terom@143: // found either a named or indexed arg terom@143: return lua_gettop(L); terom@143: terom@143: } else if (index <= nargs) { terom@143: // use the same index terom@143: return index; terom@143: terom@143: } else { terom@143: // no index terom@143: return 0; terom@143: } terom@143: } terom@143: terom@143: const char *lua_arg_string (lua_State *L, int nargs, int index, const char *name, const char *def) terom@143: { terom@143: return _lua_arg_string(L, lua_arg_index(L, nargs, index, name), name, def); terom@143: } terom@143: terom@143: bool lua_arg_bool (lua_State *L, int nargs, int index, const char *name, int def) terom@143: { terom@143: return _lua_arg_bool(L, lua_arg_index(L, nargs, index, name), name, def); terom@143: } terom@143: terom@201: void* lua_arg_obj (lua_State *L, int nargs, int index, const struct lua_type *type, bool optional) terom@199: { terom@199: return _lua_arg_obj(L, lua_arg_index(L, nargs, index, NULL), type, optional); terom@199: } terom@199: terom@201: long lua_arg_int (lua_State *L, int nargs, int index, const char *name, long def) terom@201: { terom@201: return _lua_arg_int(L, lua_arg_index(L, nargs, index, name), name, def); terom@201: } terom@201: terom@143: void lua_args_parse (lua_State *L, const struct lua_func *func, void **obj_ptr, ...) terom@143: { terom@143: int argidx = 1, argtbl = 0, idx; terom@143: const struct lua_func_arg *arg; terom@143: va_list vargs; terom@143: terom@143: // first, the obj argument terom@145: if (func->type) terom@145: *obj_ptr = lua_type_get(L, func->type, argidx++); terom@143: terom@143: // were we given a table of arguments? terom@143: if (lua_istable(L, argidx)) terom@143: argtbl = argidx++; terom@143: terom@143: // parse the args terom@143: va_start(vargs, obj_ptr); terom@143: terom@143: for (arg = func->args, idx = 1; arg->name && arg->type; arg++, idx++) { terom@143: int index; terom@143: terom@143: // map index terom@143: if (!argtbl) terom@143: // direct terom@143: index = argidx++; terom@143: terom@143: else terom@143: // lookup from table terom@143: index = lua_arg_lookup(L, argtbl, arg->name, idx); terom@143: terom@143: // apply terom@143: switch (arg->type) { terom@143: case LUA_ARG_STRING: terom@143: *va_arg(vargs, const char **) = _lua_arg_string(L, index, arg->name, arg->def.string); terom@143: break; terom@143: terom@143: case LUA_ARG_BOOL: terom@143: *va_arg(vargs, bool *) = _lua_arg_bool(L, index, arg->name, arg->def.boolean); terom@143: break; terom@201: terom@201: case LUA_ARG_INT: terom@201: *va_arg(vargs, long *) = _lua_arg_int(L, index, arg->name, arg->def.integer); terom@201: break; terom@143: terom@143: default: terom@143: NOT_REACHED(); terom@143: }; terom@143: } terom@143: terom@143: va_end(vargs); terom@143: }