/* ** Join the ktables from p1 and p2 the ktable for the new pattern at the ** top of the stack, reusing them when possible. */ static void joinktables (lua_State *L, int p1, TTree *t2, int p2) { int n1, n2; lua_getuservalue(L, p1); /* get ktables */ lua_getuservalue(L, p2); n1 = ktablelen(L, -2); n2 = ktablelen(L, -1); if (n1 == 0 && n2 == 0) /* are both tables empty? */ lua_pop(L, 2); /* nothing to be done; pop tables */ else if (n2 == 0 || lp_equal(L, -2, -1)) { /* 2nd table empty or equal? */ lua_pop(L, 1); /* pop 2nd table */ lua_setuservalue(L, -2); /* set 1st ktable into new pattern */ } else if (n1 == 0) { /* first table is empty? */ lua_setuservalue(L, -3); /* set 2nd table into new pattern */ lua_pop(L, 1); /* pop 1st table */ } else { lua_createtable(L, n1 + n2, 0); /* create ktable for new pattern */ /* stack: new p; ktable p1; ktable p2; new ktable */ concattable(L, -3, -1); /* from p1 into new ktable */ concattable(L, -2, -1); /* from p2 into new ktable */ lua_setuservalue(L, -4); /* new ktable becomes 'p' environment */ lua_pop(L, 2); /* pop other ktables */ correctkeys(t2, n1); /* correction for indices from p2 */ } }
/* ** merge 'ktable' from 'stree' at stack index 'idx' into 'ktable' ** from tree at the top of the stack, and correct corresponding ** tree. */ static void mergektable (lua_State *L, int idx, TTree *stree) { int n; lua_getuservalue(L, -1); /* get ktables */ lua_getuservalue(L, idx); n = concattable(L, -1, -2); lua_pop(L, 2); /* remove both ktables */ correctkeys(stree, n); }
static int lmount(lua_State *L) { struct sprite *s = self(L); const char * name = luaL_checkstring(L,2); int index = sprite_child(s, name); if (index < 0) { return luaL_error(L, "No child name %s", name); } lua_getuservalue(L, 1); struct sprite * child = (struct sprite *)lua_touserdata(L, 3); lua_rawgeti(L, -1, index+1); if (lua_isnil(L, -1)) { lua_pop(L, 1); } else { struct sprite * c = lua_touserdata(L, -1); if (c == child) { // mount not change return 0; } if (!c->multimount) { // try to remove parent ref lua_getuservalue(L, -1); if (lua_istable(L, -1)) { lua_pushnil(L); lua_rawseti(L, -2, 0); } lua_pop(L, 2); } else { lua_pop(L, 1); } } if (child == NULL) { sprite_mount(s, index, NULL); lua_pushnil(L); lua_rawseti(L, -2, index+1); } else { if (child->parent) { unlink_parent(L, child, 3); } sprite_mount(s, index, child); lua_pushvalue(L, 3); lua_rawseti(L, -2, index+1); if (!child->multimount) { // multimount has no parent // set child's new parent ref_parent(L, 3, 1); } } return 0; }
/* Lazily creates the uservalue if it doesn't exist. */ static void lupb_getuservalue(lua_State *L, int index) { lua_getuservalue(L, index); if (lua_isnil(L, -1)) { /* Lazily create and set userval. */ lua_pop(L, 1); /* nil. */ lua_pushvalue(L, index); /* userdata copy. */ lua_newtable(L); lua_setuservalue(L, -2); lua_pop(L, 1); /* userdata copy. */ lua_getuservalue(L, index); } assert(!lua_isnil(L, -1)); }
static int test_uservalue (lua_State *L) { void *udata = lua_newuserdata(L, 1); int ui = lua_gettop(L); lua_getuservalue(L, ui); lua_newtable(L); lua_setuservalue(L, ui); lua_getuservalue(L, ui); lua_pushnil(L); lua_setuservalue(L, ui); lua_getuservalue(L, ui); (void)udata; return 3; }
void luaT_getfenv52(lua_State *L, int iIndex) { int iType = lua_type(L, iIndex); switch(iType) { case LUA_TUSERDATA: lua_getuservalue(L, iIndex); break; case LUA_TFUNCTION: if(lua_iscfunction(L, iIndex)) { // Our convention: upvalue at #1 is environment if(lua_getupvalue(L, iIndex, 1) == nullptr) lua_pushglobaltable(L); } else { // Language convention: upvalue called _ENV is environment const char* sUpName = nullptr; for(int i = 1; (sUpName = lua_getupvalue(L, iIndex, i)) ; ++i) { if(std::strcmp(sUpName, "_ENV") == 0) return; else lua_pop(L, 1); } lua_pushglobaltable(L); } break; default: luaL_error(L, "Unable to get environment of a %s in 5.2", lua_typename(L, iType)); break; } }
static int sfuserdata_mtgc(lua_State *l) { lua_settop(l, 1); //[u] assert(lua_type(l, -1) == LUA_TUSERDATA); //clear the function lua_getuservalue(l, 1); //[ut] lua_getfield(l, -1, "dbud"); //[utu] struct dbuserdata *uddb = (struct dbuserdata *)lua_touserdata(l, 3); assert(uddb != NULL); assert(uddb->db != NULL); lua_pop(l, 1); //[ut] lua_getfield(l, -1, "name"); //[uts] sqlite3_create_function(uddb->db, lua_tostring(l, -1), -1, SQLITE_ANY, NULL, NULL, NULL, NULL); struct sfuserdata *ud = (struct sfuserdata *)lua_touserdata(l, 1); if(ud->funcref != -1) { luaL_unref(l, LUA_REGISTRYINDEX, ud->funcref); } return 0; }
static int Lnewindex(lua_State *L) { int nret; /* upvalue: seti, seth */ /* order: * - lut * - accessor * - normaltable * - uservalue */ if (!lua_isnone(L, lua_upvalueindex(1)) && (nret = call_lut(L, lua_upvalueindex(1), 3)) >= 0) return nret; if (!lua_isnone(L, lua_upvalueindex(2)) && (nret = call_accessor(L, lua_upvalueindex(2), 3)) >= 0) return nret; if (!lua_isuserdata(L, 1)) { lua_settop(L, 3); lua_rawset(L, 1); return 0; } lua_getuservalue(L, 1); if (lua_isnil(L, -1)) { lua_pop(L, 1); lua_newtable(L); lua_pushvalue(L, -1); lua_setuservalue(L, 1); } lua_pushvalue(L, 2); lua_pushvalue(L, 3); lua_rawset(L, -3); return 0; }
static int lua_update_metadata(lua_State*L) { dt_lib_module_t *self = lua_touserdata(L, 1); int32_t imgid = lua_tointeger(L,2); dt_lua_module_entry_push(L,"lib",self->plugin_name); lua_getuservalue(L,-1); lua_getfield(L,4,"callbacks"); lua_getfield(L,4,"values"); lua_pushnil(L); while(lua_next(L, 5) != 0) { lua_pushvalue(L,-1); luaA_push(L,dt_lua_image_t,&imgid); lua_call(L,1,1); lua_pushvalue(L,7); lua_pushvalue(L,9); lua_settable(L,6); lua_pop(L, 2); } lua_pushcfunction(L,lua_update_widgets); dt_lua_gtk_wrap(L); lua_pushlightuserdata(L,self); lua_call(L,1,0); return 0; }
static int container_numindex(lua_State*L) { lua_container container; luaA_to(L,lua_container,&container,1); GList * children = gtk_container_get_children(GTK_CONTAINER(container->widget)); int index = lua_tointeger(L,2) -1; if(lua_gettop(L) >2) { int length = g_list_length(children); if(!lua_isnil(L,3) && index == length) { lua_widget widget; luaA_to(L, lua_widget,&widget,3), gtk_container_add(GTK_CONTAINER(container->widget),widget->widget); } else if(lua_isnil(L,3) && index < length) { GtkWidget *searched_widget = g_list_nth_data(children,index); gtk_container_remove(GTK_CONTAINER(container->widget),searched_widget); } else { luaL_error(L,"Incorrect index or value when setting the child of a container"); } g_list_free(children); return 0; } else { GtkWidget *searched_widget = g_list_nth_data(children,index); g_list_free(children); lua_getuservalue(L,1); lua_pushlightuserdata(L,searched_widget); lua_gettable(L,-2); return 1; } }
/* to_cdata returns the struct cdata* and pushes the user value onto the * stack. If the index is not a ctype then ct is set to the zero value such * that ct->type is INVALID_TYPE, a nil is pushed, and NULL is returned. */ void* to_cdata(lua_State* L, int idx, struct ctype* ct) { struct cdata* cd; memset(ct, 0, sizeof(struct ctype)); if (!lua_isuserdata(L, idx) || !lua_getmetatable(L, idx)) { lua_pushnil(L); return NULL; } if (!equals_upval(L, -1, &cdata_mt_key)) { lua_pop(L, 1); /* mt */ lua_pushnil(L); return NULL; } lua_pop(L, 1); /* mt */ cd = (struct cdata*) lua_touserdata(L, idx); *ct = cd->type; lua_getuservalue(L, idx); if (ct->is_reference) { return *(void**) (cd+1); } else if (ct->pointers && !ct->is_array) { return *(void**) (cd+1); } else { return cd + 1; } }
static int lua_register_selection(lua_State *L) { lua_settop(L,3); dt_lib_module_t *self = lua_touserdata(L, lua_upvalueindex(1)); dt_lua_module_entry_push(L,"lib",self->plugin_name); lua_getuservalue(L,-1); const char* key = luaL_checkstring(L,1); luaL_checktype(L,2,LUA_TFUNCTION); lua_getfield(L,-1,"callbacks"); lua_pushstring(L,key); lua_pushvalue(L,2); lua_settable(L,-3); GtkWidget* button = gtk_button_new_with_label(key); const char * tooltip = lua_tostring(L,3); if(tooltip) { gtk_widget_set_tooltip_text(button, tooltip); } gtk_grid_attach_next_to(GTK_GRID(self->widget), button, NULL, GTK_POS_BOTTOM, 2, 1); lua_callback_data * data = malloc(sizeof(lua_callback_data)); data->key = strdup(key); data->self = self; g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(lua_button_clicked), data); gtk_widget_show_all(self->widget); return 0; }
static int lua__map_get_units(lua_State *L) { imap * map = CHECK_AOI_MAP(L, 1); (void)map; lua_getuservalue(L, 1); return 1; }
/* lpty_getenviron * * return the environment the child process is executed in * * Arguments: * L Lua State * * Lua Stack: * 1 lpty userdata * * Lua Returns: * +1 a table containing the current environment for the child process */ static int lpty_getenviron(lua_State *L) { /* lPty *pty = lpty_checkLPty(L, 1); */ char *c = NULL, **e = environ, *p; size_t buflen = 64; char *buf = malloc(buflen); lua_getuservalue(L, 1); lua_rawgeti(L, 2, 1); lua_remove(L, -2); if (lua_isnil(L, -1)) { lua_pop(L, 1); lua_newtable(L); while ((c = *e++)) { if (strlen(c) >= buflen) { buflen += strlen(c); buf = realloc(buf, buflen); } strcpy(buf, c); p = strchr(buf, '='); *p = 0; ++p; lua_pushstring(L, (const char*) buf); lua_pushstring(L, (const char*) p); lua_rawset(L, -3); } } free(buf); return 1; }
static int db_getuservalue (lua_State *L) { if (lua_type(L, 1) != LUA_TUSERDATA) lua_pushnil(L); else lua_getuservalue(L, 1); return 1; }
static int lua__map_unit_del_byid(lua_State *L) { iunit * unit = NULL; imap * map = CHECK_AOI_MAP(L, 1); iid id = (iid)luaL_checkinteger(L, 2); lua_settop(L, 2); lua_getuservalue(L, 1); lua_pushinteger(L, (lua_Integer)id); lua_rawget(L, -2); if (lua_isnoneornil(L, -1)) { DLOG("%s,id=%" PRId64 " not found\n", __FUNCTION__, id); return 0; } unit = CHECK_AOI_UNIT(L, -1); imapremoveunit(map, unit); lua_pushinteger(L, (lua_Integer)id); lua_pushnil(L); lua_rawset(L, 3); DLOG("%s,id=%" PRId64 " removed\n", __FUNCTION__, id); /* fprintf(stderr, "%s,id=%" PRId64 " removed\n", __FUNCTION__, id); */ return 0; }
static int lua_create_job(lua_State *L) { const char * message = luaL_checkstring(L, 1); gboolean has_progress_bar = lua_toboolean(L, 2); int cancellable = FALSE; if(!lua_isnoneornil(L,3)) { luaL_checktype(L, 3, LUA_TFUNCTION); cancellable = TRUE; } dt_lua_unlock(false); dt_progress_t *progress = dt_control_progress_create(darktable.control, has_progress_bar, message); if(cancellable) { dt_control_progress_make_cancellable(darktable.control, progress, lua_job_cancelled, progress); } dt_lua_lock(); luaA_push(L, dt_lua_backgroundjob_t, &progress); if(cancellable) { lua_getuservalue(L, -1); lua_pushvalue(L, 3); lua_setfield(L, -2, "cancel_callback"); lua_pop(L, 1); } return 1; }
static void start_element(void* ud, const char* name, const char** atts) { P("start element %s", name); lxp* lxpp = (lxp*) ud; lua_State* L = lxpp->L; STACK_DUMP(); lua_getuservalue(L, 1); lua_pushvalue(L, -1); iterate_table(L, 4); STACK_DUMP(); //lua_getfield(L, -1, "startElement"); lua_pushstring(L, "startElement"); STACK_DUMP(); lua_gettable(L, -2); lua_pushvalue(L, 1); lua_pushstring(L, name); lua_newtable(L); for(;*atts;atts+=2) { lua_pushstring(L, *(atts+1)); lua_setfield(L, -2, *atts); } STACK_DUMP(); lua_pcall(L, 3, 0, 0); STACK_DUMP(); P("start element done"); }
/* Store at ubox * It stores, creating the corresponding table if needed, * the pair key/value in the corresponding ubox table */ static void storeatubox (lua_State* L, int lo) { #ifdef LUA_VERSION_NUM // lua_getfenv(L, lo); lua_getuservalue(L, lo); if (lua_rawequal(L, -1, TOLUA_NOPEER)) { lua_pop(L, 1); lua_newtable(L); lua_pushvalue(L, -1); // lua_setfenv(L, lo); /* stack: k,v,table */ lua_setuservalue(L, lo); /* stack: k,v,table */ }; lua_insert(L, -3); lua_settable(L, -3); /* on lua 5.1, we trade the "tolua_peers" lookup for a settable call */ lua_pop(L, 1); #else /* stack: key value (to be stored) */ lua_pushstring(L,"tolua_peers"); lua_rawget(L,LUA_REGISTRYINDEX); /* stack: k v ubox */ lua_pushvalue(L,lo); lua_rawget(L,-2); /* stack: k v ubox ubox[u] */ if (!lua_istable(L,-1)) { lua_pop(L,1); /* stack: k v ubox */ lua_newtable(L); /* stack: k v ubox table */ lua_pushvalue(L,1); lua_pushvalue(L,-2); /* stack: k v ubox table u table */ lua_rawset(L,-4); /* stack: k v ubox ubox[u]=table */ } lua_insert(L,-4); /* put table before k */ lua_pop(L,1); /* pop ubox */ lua_rawset(L,-3); /* store at table */ lua_pop(L,1); /* pop ubox[u] */ #endif }
static int lmount(lua_State *L) { struct sprite *s = self(L); const char * name = luaL_checkstring(L,2); int index = sprite_child(s, name); if (index < 0) { return luaL_error(L, "No child name %s", name); } lua_getuservalue(L, 1); struct sprite * child = (struct sprite *)lua_touserdata(L, 3); if (child == NULL) { sprite_mount(s, index, NULL); lua_pushnil(L); lua_rawseti(L, -2, index+1); } else { if (child->parent) { struct sprite* p = child->parent; sprite_mount(p, index, NULL); //return luaL_error(L, "Can't mount sprite %p twice,pre parent:%p: %s", child,child->parent,child->name); } sprite_mount(s, index, child); lua_pushvalue(L, 3); lua_rawseti(L, -2, index+1); } return 0; }
void dt_lua_widget_get_callback(lua_State *L,int index,const char* name) { luaL_argcheck(L, dt_lua_isa(L, index, lua_widget), index, "lua_widget expected"); lua_getuservalue(L,index); lua_getfield(L,-1,name); lua_remove(L,-2); }
/* returns the value as a ctype, pushes the user value onto the stack */ void check_ctype(lua_State* L, int idx, struct ctype* ct) { if (lua_isstring(L, idx)) { struct parser P; P.line = 1; P.prev = P.next = lua_tostring(L, idx); P.align_mask = DEFAULT_ALIGN_MASK; parse_type(L, &P, ct); parse_argument(L, &P, -1, ct, NULL, NULL); lua_remove(L, -2); /* remove the user value from parse_type */ } else if (lua_getmetatable(L, idx)) { if (!equals_upval(L, -1, &ctype_mt_key) && !equals_upval(L, -1, &cdata_mt_key)) { goto err; } lua_pop(L, 1); /* pop the metatable */ *ct = *(struct ctype*) lua_touserdata(L, idx); lua_getuservalue(L, idx); } else { goto err; } return; err: luaL_error(L, "expected cdata, ctype or string for arg #%d", idx); }
void dt_lua_widget_set_callback(lua_State *L,int index,const char* name) { luaL_argcheck(L, dt_lua_isa(L, index, lua_widget), index, "lua_widget expected"); luaL_checktype(L,-1,LUA_TFUNCTION); lua_getuservalue(L,index); lua_pushvalue(L,-2); lua_setfield(L,-2,name); lua_pop(L,2); }
static int job_canceled(lua_State *L) { lua_getuservalue(L, 1); lua_getfield(L, -1, "cancel_callback"); lua_pushvalue(L, -3); lua_call(L,1,0); lua_pop(L, 2); return 0; }
static void unlink_parent(lua_State *L, struct sprite * child, int idx) { lua_getuservalue(L, idx); // reftable lua_rawgeti(L, -1, 0); // reftable parent struct sprite * parent = lua_touserdata(L, -1); if (parent == NULL) { luaL_error(L, "No parent object"); } int index = sprite_child_ptr(parent, child); if (index < 0) { luaL_error(L, "Invalid child object"); } lua_getuservalue(L, -1); // reftable parent parentref lua_pushnil(L); lua_rawseti(L, -2, index+1); lua_pop(L, 3); sprite_mount(parent, index, NULL); }
static void fetch_parent(lua_State *L, int index) { lua_getuservalue(L, 1); lua_rawgeti(L, -1, index+1); // A child may not exist, but the name is valid. (empty dummy child) if (!lua_isnil(L, -1)) { ref_parent(L, lua_gettop(L), 1); } }
static int lgetparent(lua_State *L) { struct sprite *s = self(L); if (s->parent == NULL) return 0; lua_getuservalue(L, 1); lua_rawgeti(L, -1, 0); return 1; }
int luaT_lua_getenv(lua_State *L) { if(!lua_isfunction(L, 1) && !lua_isuserdata(L, 1)) luaL_typerror(L, 1, "function or userdata"); lua_getuservalue(L, 1); if (lua_isnil(L, -1)) lua_newtable(L); return 1; }
static void get_reftable(lua_State *L, int index) { lua_getuservalue(L, index); if (lua_isnil(L, -1)) { lua_pop(L, 1); lua_createtable(L, 0, 1); lua_pushvalue(L, -1); lua_setuservalue(L, index); } }
static int lgettext(lua_State *L) { struct sprite *s = self(L); if (s->type != TYPE_LABEL) { return luaL_error(L, "Only label can get text"); } lua_settop(L,2); lua_getuservalue(L, 1); return 1; }