Ejemplo n.º 1
0
void
signal_object_emit(lua_State *L, signal_t *signals,
        const gchar *name, gint nargs) {

    signal_array_t *sigfuncs = signal_lookup(signals, name, FALSE);
    if(sigfuncs) {
        gint nbfunc = sigfuncs->len;
        luaL_checkstack(L, lua_gettop(L) + nbfunc + nargs + 1,
                "too much signal");
        /* Push all functions and then execute, because this list can change
         * while executing funcs. */
        for(gint i = 0; i < nbfunc; i++) {
            luaH_object_push(L, sigfuncs->pdata[i]);
        }

        for(gint i = 0; i < nbfunc; i++) {
            /* push all args */
            for(gint j = 0; j < nargs; j++)
                lua_pushvalue(L, - nargs - nbfunc + i);
            /* push first function */
            lua_pushvalue(L, - nargs - nbfunc + i);
            /* remove this first function */
            lua_remove(L, - nargs - nbfunc - 1 + i);
            luaH_dofunction(L, nargs, 0);
        }
    }
    /* remove args */
    lua_pop(L, nargs);
}
Ejemplo n.º 2
0
/* Emit a signal to an object.
 * `oud` is the object index on the stack.
 * `name` is the name of the signal.
 * `nargs` is the number of arguments to pass to the called functions. */
gint
luaH_object_emit_signal(lua_State *L, gint oud,
        const gchar *name, gint nargs, gint nret) {
    gint ret, top, bot = lua_gettop(L) - nargs + 1;
    gint oud_abs = luaH_absindex(L, oud);
    lua_object_t *obj = lua_touserdata(L, oud);
    if(!obj)
        luaL_error(L, "trying to emit signal on non-object");

    debug("emitting \"%s\" on %p with %d args and %d nret", name, obj, nargs, nret);

    signal_array_t *sigfuncs = signal_lookup(obj->signals, name, FALSE);
    if(sigfuncs) {
        guint nbfunc = sigfuncs->len;
        luaL_checkstack(L, lua_gettop(L) + nbfunc + nargs + 2, "too much signal");
        /* Push all functions and then execute, because this list can change
         * while executing funcs. */
        for(guint i = 0; i < nbfunc; i++)
            luaH_object_push_item(L, oud_abs, sigfuncs->pdata[i]);

        for(guint i = 0; i < nbfunc; i++) {
            /* push object */
            lua_pushvalue(L, oud_abs);
            /* push all args */
            for(gint j = 0; j < nargs; j++)
                lua_pushvalue(L, - nargs - nbfunc - 1 + i);
            /* push first function */
            lua_pushvalue(L, - nargs - nbfunc - 1 + i);
            /* remove this first function */
            lua_remove(L, - nargs - nbfunc - 2 + i);
            top = lua_gettop(L) - 2 - nargs;
            luaH_dofunction(L, nargs + 1, LUA_MULTRET);
            ret = lua_gettop(L) - top;

            /* Note that only if nret && ret will the signal execution stop */
            if (ret) {
                /* Adjust the number of results to match nret (including 0) */
                if (nret != LUA_MULTRET && ret != nret) {
                    /* Pad with nils */
                    for (; ret < nret; ret++)
                        lua_pushnil(L);
                    /* Or truncate stack */
                    if (ret > nret) {
                        lua_pop(L, ret - nret);
                        ret = nret;
                    }
                }

                /* Remove all signal functions and args from the stack */
                for (gint i = bot; i < top; i++)
                    lua_remove(L, bot);
                /* Return the number of returned arguments */
                return ret;
            }
        }
    }
    lua_pop(L, nargs);
    return 0;
}
Ejemplo n.º 3
0
/* Remove all signals of a given name to an object.
 * `oud` is the object index on the stack.
 * `name` is the name of the signal.
 */
void
luaH_object_remove_signals(lua_State *L, gint oud, const gchar *name) {
    lua_object_t *obj = lua_touserdata(L, oud);
    signal_array_t *sigfuncs = signal_lookup(obj->signals, name);
    if (!sigfuncs)
        return;
    for (guint i = 0; i < sigfuncs->len; i++) {
        gpointer ref = g_ptr_array_index(sigfuncs, i);
        luaH_object_unref_item(L, oud, ref);
    }
    signals_remove(obj->signals, name);
}
Ejemplo n.º 4
0
/* Emit a signal to an object.
 * `oud` is the object index on the stack.
 * `name` is the name of the signal.
 * `nargs` is the number of arguments to pass to the called functions.
 * `nret` is the number of return values this function pushes onto the stack.
 * A positive number means that any missing values will be padded with nil
 * and any superfluous values will be removed.
 * LUA_MULTRET means that any number of values is returned without any
 * adjustment.
 * 0 means that all return values are removed and that ALL handler functions are
 * executed.
 * Returns the number of return values pushed onto the stack. */
gint
luaH_object_emit_signal(lua_State *L, gint oud,
        const gchar *name, gint nargs, gint nret) {
    gint ret, top, bot = lua_gettop(L) - nargs + 1;
    gint oud_abs = luaH_absindex(L, oud);
    lua_object_t *obj = lua_touserdata(L, oud);

    gchar *origin = luaH_callerinfo(L);
    debug("emit " ANSI_COLOR_BLUE "\"%s\"" ANSI_COLOR_RESET
            " on %p from "
            ANSI_COLOR_GREEN "%s" ANSI_COLOR_RESET " (%d args, %d nret)",
            name, obj, origin ? origin : "<GTK>", nargs, nret);
    g_free(origin);

    if(!obj)
        return luaL_error(L, "trying to emit " ANSI_COLOR_BLUE "\"%s\"" ANSI_COLOR_RESET " on non-object", name);

    signal_array_t *sigfuncs = signal_lookup(obj->signals, name);
    if (sigfuncs) {
        guint nbfunc = sigfuncs->len;
        luaL_checkstack(L, lua_gettop(L) + nbfunc + nargs + 2,
                "too many signal handlers; need a new implementation!");
        /* Push all functions and then execute, because this list can change
         * while executing funcs. */
        for (guint i = 0; i < nbfunc; i++)
            luaH_object_push_item(L, oud_abs, sigfuncs->pdata[i]);

        for (guint i = 0; i < nbfunc; i++) {
            /* push object */
            lua_pushvalue(L, oud_abs);
            /* push all args */
            for (gint j = 0; j < nargs; j++)
                lua_pushvalue(L, - nargs - nbfunc - 1 + i);
            /* push first function */
            lua_pushvalue(L, - nargs - nbfunc - 1 + i);
            /* remove this first function */
            lua_remove(L, - nargs - nbfunc - 2 + i);
            top = lua_gettop(L) - 2 - nargs;
            luaH_dofunction(L, nargs + 1, LUA_MULTRET);
            ret = lua_gettop(L) - top;

            /* Signal execution stops when:
             *  - there's an expected number of return values (>0 or LUA_MULTRET)
             *  - at least one return value (ret)
             *  - the first return value is non-nil
             */
            if (nret && ret && !lua_isnil(L, -ret)) {
                /* Adjust the number of results to match nret (including 0) */
                if (nret != LUA_MULTRET && ret != nret) {
                    /* Pad with nils */
                    for (; ret < nret; ret++)
                        lua_pushnil(L);
                    /* Or truncate stack */
                    if (ret > nret) {
                        lua_pop(L, ret - nret);
                        ret = nret;
                    }
                }
                /* Remove all signal functions and args from the stack */
                for (gint i = bot; i <= top; i++)
                    lua_remove(L, bot);
                /* Return the number of returned arguments */
                return ret;
            } else if (nret == 0) {
                /* ignore all return values */
                lua_pop(L, ret);
            }
        }
    }
    lua_pop(L, nargs);
    return 0;
}
Ejemplo n.º 5
0
/* Similar to signal_object_emit(), but allows you to choose the signal array
 * by name. */
gint
signal_array_emit(lua_State *L, signal_t *signals,
        const gchar *array_name, const gchar *name, gint nargs, gint nret) {

    signal_array_t *sigfuncs = signal_lookup(signals, array_name);

    gchar *origin = luaH_callerinfo(L);
    debug("emit " ANSI_COLOR_BLUE "\"%s\"" ANSI_COLOR_RESET
            " on %p from "
            ANSI_COLOR_GREEN "%s" ANSI_COLOR_RESET " (%d args, %d nret)",
            name, signals, origin ? origin : "<GTK>", nargs, nret);
    g_free(origin);

    if (sigfuncs) {
        gint nbfunc = sigfuncs->len;
        luaL_checkstack(L, lua_gettop(L) + nbfunc + nargs + 1,
                "too many signal handlers; need a new implementation!");
        /* Push all functions and then execute, because this list can change
         * while executing funcs. */
        for (gint i = 0; i < nbfunc; i++) {
            luaH_object_push(L, sigfuncs->pdata[i]);
        }

        for (gint i = 0; i < nbfunc; i++) {
            gint stacksize = lua_gettop(L);
            /* push all args */
            for (gint j = 0; j < nargs; j++)
                lua_pushvalue(L, - nargs - nbfunc + i);
            /* push first function */
            lua_pushvalue(L, - nargs - nbfunc + i);
            /* remove this first function */
            lua_remove(L, - nargs - nbfunc - 1 + i);
            luaH_dofunction(L, nargs, LUA_MULTRET);
            gint ret = lua_gettop(L) - stacksize + 1;

            /* Signal execution stops when:
             *  - there's an expected number of return values (>0 or LUA_MULTRET)
             *  - at least one return value (ret)
             *  - the first return value is non-nil
             */
            if (nret && ret && !lua_isnil(L, -ret)) {
                /* remove all args and functions */
                for (gint j = 0; j < nargs + nbfunc - i - 1; j++) {
                    lua_remove(L, - ret - 1);
                }

                /* Adjust the number of results to match nret */
                if (nret != LUA_MULTRET && ret != nret) {
                    /* Pad with nils */
                    for (; ret < nret; ret++)
                        lua_pushnil(L);
                    /* Or truncate stack */
                    if (ret > nret) {
                        lua_pop(L, ret - nret);
                        ret = nret;
                    }
                }

                /* Return the number of returned arguments */
                return ret;
            } else if (nret == 0) {
                /* ignore all return values */
                lua_pop(L, ret);
            }
        }
    }
    /* remove args */
    lua_pop(L, nargs);
    return 0;
}