summaryrefslogtreecommitdiffstats
path: root/src/lib-lua/dlua-script-private.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib-lua/dlua-script-private.h264
1 files changed, 264 insertions, 0 deletions
diff --git a/src/lib-lua/dlua-script-private.h b/src/lib-lua/dlua-script-private.h
new file mode 100644
index 0000000..e6c8273
--- /dev/null
+++ b/src/lib-lua/dlua-script-private.h
@@ -0,0 +1,264 @@
+#ifndef LUA_SCRIPT_PRIVATE_H
+#define LUA_SCRIPT_PRIVATE_H 1
+
+#include "dlua-script.h"
+#include "lualib.h"
+#include "lauxlib.h"
+#include "dlua-compat.h"
+
+/* consistency helpers */
+#define lua_isstring(L, n) (lua_isstring((L), (n)) == 1)
+#define lua_isnumber(L, n) (lua_isnumber((L), (n)) == 1)
+#define lua_toboolean(L, n) (lua_toboolean((L), (n)) == 1)
+#define lua_pushboolean(L, b) lua_pushboolean((L), (b) ? 1 : 0)
+#define lua_isinteger(L, n) (lua_isinteger((L), (n)) == 1)
+
+#define DLUA_TABLE_STRING(n, val) { .name = (n),\
+ .type = DLUA_TABLE_VALUE_STRING, .v.s = (val) }
+#define DLUA_TABLE_INTEGER(n, val) { .name = (n), \
+ .type = DLUA_TABLE_VALUE_INTEGER, .v.i = (val) }
+#define DLUA_TABLE_ENUM(n) { .name = #n, \
+ .type = DLUA_TABLE_VALUE_INTEGER, .v.i = (n) }
+#define DLUA_TABLE_DOUBLE(n, val) { .name = (n), \
+ .type = DLUA_TABLE_VALUE_DOUBLE, .v.d = (val) }
+#define DLUA_TABLE_BOOLEAN(n, val) { .name = (n), \
+ .type = DLUA_TABLE_VALUE_BOOLEAN, .v.b = (val) }
+#define DLUA_TABLE_NULL(n, s) { .name = (n), \
+ .type = DLUA_TABLE_VALUE_NULL }
+#define DLUA_TABLE_END { .name = NULL }
+
+#define DLUA_REQUIRE_ARGS_IN(L, x, y) \
+ STMT_START { \
+ if (lua_gettop(L) < (x) || lua_gettop(L) > (y)) { \
+ return luaL_error((L), "expected %d to %d arguments, got %d", \
+ (x), (y), lua_gettop(L)); \
+ } \
+ } STMT_END
+#define DLUA_REQUIRE_ARGS(L, x) \
+ STMT_START { \
+ if (lua_gettop(L) != (x)) { \
+ return luaL_error((L), "expected %d arguments, got %d", \
+ (x), lua_gettop(L)); \
+ } \
+ } STMT_END
+
+struct dlua_script {
+ struct dlua_script *prev,*next;
+ pool_t pool;
+
+ lua_State *L; /* base lua context */
+
+ struct event *event;
+ const char *filename;
+ struct istream *in;
+ ssize_t last_read;
+
+ int ref;
+ bool init:1;
+};
+
+enum dlua_table_value_type {
+ DLUA_TABLE_VALUE_STRING = 0,
+ DLUA_TABLE_VALUE_INTEGER,
+ DLUA_TABLE_VALUE_DOUBLE,
+ DLUA_TABLE_VALUE_BOOLEAN,
+ DLUA_TABLE_VALUE_NULL
+};
+
+struct dlua_table_values {
+ const char *name;
+ enum dlua_table_value_type type;
+ union {
+ const char *s;
+ ptrdiff_t i;
+ double d;
+ bool b;
+ } v;
+};
+
+typedef void dlua_pcall_yieldable_callback_t(lua_State *L, void *context, int status);
+
+extern struct event_category event_category_lua;
+
+/* assorted wrappers for lua_foo(), but operating on a struct dlua_script */
+void dlua_register(struct dlua_script *script, const char *name,
+ lua_CFunction f);
+
+/* Get dlua_script from lua_State */
+struct dlua_script *dlua_script_from_state(lua_State *L);
+
+/* register 'dovecot' global */
+void dlua_dovecot_register(struct dlua_script *script);
+
+/* push 'dovecot' global on top of stack */
+void dlua_get_dovecot(lua_State *L);
+
+/* register 'http' methods to 'dovecot' */
+void dlua_dovecot_http_register(struct dlua_script *script);
+
+/* assign values to table on idx */
+void dlua_set_members(lua_State *L, const struct dlua_table_values *values, int idx);
+
+/* push event to top of stack */
+void dlua_push_event(lua_State *L, struct event *event);
+
+/* get event from given stack position */
+struct event *dlua_check_event(lua_State *L, int arg);
+
+/* improved lua_pushfstring, can handle full C format support */
+const char *dlua_push_vfstring(lua_State *L, const char *fmt, va_list argp) ATTR_FORMAT(2, 0);
+const char *dlua_push_fstring(lua_State *L, const char *fmt, ...) ATTR_FORMAT(2, 3);
+
+/* improved luaL_error, can handle full C format support */
+int dluaL_error(lua_State *L, const char *fmt, ...) ATTR_FORMAT(2, 3);
+#define luaL_error(...) dluaL_error(__VA_ARGS__)
+
+/*
+ * Returns field from a Lua table
+ *
+ * There are different variants of these that allow for different key types
+ * and different value types. In general, the function name scheme is:
+ *
+ * dlua_table_get_<return type>_by_<key type>
+ *
+ * The _by_{str,int} variants use the supplied field value as the table key.
+ *
+ * The _by_thread variants use the current thread's thread object as the
+ * table key.
+ *
+ * Returns:
+ * -1 = incompatible value type
+ * 0 = nil or not found
+ * 1 = value found
+ */
+int dlua_table_get_luainteger_by_str(lua_State *L, int idx, const char *field, lua_Integer *value_r);
+int dlua_table_get_int_by_str(lua_State *L, int idx, const char *field, int *value_r);
+int dlua_table_get_intmax_by_str(lua_State *L, int idx, const char *field, intmax_t *value_r);
+int dlua_table_get_uint_by_str(lua_State *L, int idx, const char *field, unsigned int *value_r);
+int dlua_table_get_uintmax_by_str(lua_State *L, int idx, const char *field, uintmax_t *value_r);
+int dlua_table_get_number_by_str(lua_State *L, int idx, const char *field, lua_Number *value_r);
+int dlua_table_get_bool_by_str(lua_State *L, int idx, const char *field, bool *value_r);
+int dlua_table_get_string_by_str(lua_State *L, int idx, const char *field, const char **value_r);
+int dlua_table_get_data_by_str(lua_State *L, int idx, const char *field, const unsigned char **value_r, size_t *len_r);
+
+int dlua_table_get_luainteger_by_int(lua_State *L, int idx, lua_Integer field, lua_Integer *value_r);
+int dlua_table_get_int_by_int(lua_State *L, int idx, lua_Integer field, int *value_r);
+int dlua_table_get_intmax_by_int(lua_State *L, int idx, lua_Integer field, intmax_t *value_r);
+int dlua_table_get_uint_by_int(lua_State *L, int idx, lua_Integer field, unsigned int *value_r);
+int dlua_table_get_uintmax_by_int(lua_State *L, int idx, lua_Integer field, uintmax_t *value_r);
+int dlua_table_get_number_by_int(lua_State *L, int idx, lua_Integer field, lua_Number *value_r);
+int dlua_table_get_bool_by_int(lua_State *L, int idx, lua_Integer field, bool *value_r);
+int dlua_table_get_string_by_int(lua_State *L, int idx, lua_Integer field, const char **value_r);
+int dlua_table_get_data_by_int(lua_State *L, int idx, lua_Integer field, const unsigned char **value_r, size_t *len_r);
+
+int dlua_table_get_luainteger_by_thread(lua_State *L, int idx, lua_Integer *value_r);
+int dlua_table_get_int_by_thread(lua_State *L, int idx, int *value_r);
+int dlua_table_get_intmax_by_thread(lua_State *L, int idx, intmax_t *value_r);
+int dlua_table_get_uint_by_thread(lua_State *L, int idx, unsigned int *value_r);
+int dlua_table_get_uintmax_by_thread(lua_State *L, int idx, uintmax_t *value_r);
+int dlua_table_get_number_by_thread(lua_State *L, int idx, lua_Number *value_r);
+int dlua_table_get_bool_by_thread(lua_State *L, int idx, bool *value_r);
+int dlua_table_get_string_by_thread(lua_State *L, int idx, const char **value_r);
+int dlua_table_get_data_by_thread(lua_State *L, int idx, const unsigned char **value_r, size_t *len_r);
+
+/*
+ * Pushes onto the stack the value t[k], where t is the value at the given
+ * index and k is field argument. Unlike lua_gettable(), this function
+ * checks the type of the retrieved value against the passed in type.
+ * [-1,+0..1,e]
+ *
+ * There are different variants of these that allow for different key types.
+ * In general, the function name scheme is:
+ *
+ * dlua_table_get_by_<key type>
+ *
+ * The _by_{str,int} variants use the supplied field value as the table key.
+ *
+ * The _by_thread variants use the current thread's thread object as the
+ * table key.
+ *
+ * Returns:
+ * -1 = incompatible value type (nothing is pushed)
+ * 0 = nil or not found (nothing is pushed)
+ * 1 = value found (retrieved value is pushed to the top of the stack)
+ */
+int dlua_table_get_by_str(lua_State *L, int idx, int type, const char *field);
+int dlua_table_get_by_int(lua_State *L, int idx, int type, lua_Integer field);
+int dlua_table_get_by_thread(lua_State *L, int idx, int type);
+
+/* call a function in a script.
+
+ **NOTE**: This function works differently than lua_pcall:
+
+ return value:
+ -1 = error
+ 0+ = number of result(s)
+
+*/
+int dlua_pcall(lua_State *L, const char *func_name, int nargs, int nresults,
+ const char **error_r);
+
+/* dumps current stack as i_debug lines */
+void dlua_dump_stack(lua_State *L);
+
+/* Create new thread and keep track of it. */
+lua_State *dlua_script_new_thread(struct dlua_script *script);
+
+/* Close thread. */
+void dlua_script_close_thread(struct dlua_script *script, lua_State **_L);
+
+#ifdef DLUA_WITH_YIELDS
+/*
+ * Call a function with nargs in a way that supports yielding.
+ *
+ * When the specified function returns, the callback will be called with the
+ * supplied context pointer and a status integer indicating whether an error
+ * occurred (-1) or whether execution completed successfully (0+). In the
+ * case of a successful completion, the status will indicate the number of
+ * results returned by the function. On failure, the top of the stack
+ * contains the error object.
+ *
+ * Returns:
+ * -1 = if function name refers to a non-function type
+ * 0 = function called, callback will be called in the future
+ */
+int dlua_pcall_yieldable(lua_State *L, const char *func_name, int nargs,
+ dlua_pcall_yieldable_callback_t *callback,
+ void *context, const char **error_r);
+#define dlua_pcall_yieldable(L, func_name, nargs, callback, context, error_r) \
+ dlua_pcall_yieldable(L, TRUE ? func_name : \
+ CALLBACK_TYPECHECK(callback, void (*)(lua_State *, typeof(context), int)), \
+ nargs, (dlua_pcall_yieldable_callback_t *)callback, context, error_r)
+/*
+ * Resume yielded function execution.
+ *
+ * The nargs argument indicates how many items from the top of the stack
+ * should be "returned" by the yield.
+ *
+ * This function is to be called from other API callbacks to resume
+ * execution of the Lua script. For example, if a Lua script invokes a
+ * function to perform I/O, the function would start the async I/O and yield
+ * from the script. Eventually, the I/O completion callback executes, which
+ * would call dlua_pcall_yieldable_resume() to continue executing the Lua
+ * script with the supplied arguments.
+ *
+ * Note: The actual execution doesn't resume immediately. Rather, it is
+ * scheduled to start in the near future via a timeout.
+ */
+void dlua_pcall_yieldable_resume(lua_State *L, int nargs);
+#endif
+
+/* initialize/free script's thread table */
+void dlua_init_thread_table(struct dlua_script *script);
+void dlua_free_thread_table(struct dlua_script *script);
+
+/* thread local storage (TLS) getters & setters */
+void dlua_tls_set_ptr(lua_State *L, const char *name, void *ptr);
+void *dlua_tls_get_ptr(lua_State *L, const char *name);
+void dlua_tls_set_int(lua_State *L, const char *name, lua_Integer i);
+lua_Integer dlua_tls_get_int(lua_State *L, const char *name);
+
+/* free a thread local storage (TLS) value */
+void dlua_tls_clear(lua_State *L, const char *name);
+
+#endif