aboutsummaryrefslogtreecommitdiff
path: root/src/lua/log.c
blob: d02775c2fe41c175f473cda2f16839d08a819826 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <assert.h>
#include <string.h>

#include "api.h"
#include "../any_log.h"

static int lua_log_format(lua_State *state, any_log_level_t level) {
    const char *value = luaL_checkstring(state, 1);

    lua_getglobal(state, "debug");
    lua_getfield(state, -1, "getinfo");

    // Ignore the first frame (lua_log_format itself)
    lua_pushnumber(state, 2);
    // S: source, l: currentline, n: name
    lua_pushstring(state, "Sln");

    const char *source = "x", *func = "y";
    char buffer[4096] = { 0 };

    if (lua_pcall(state, 2, 1, 0) == LUA_OK) {

        lua_getfield(state, -1, "short_src");
        const char *shortsrc = lua_tostring(state, -1);

        lua_getfield(state, -2, "currentline");
        int line = lua_tointeger(state, -1);

        if (!strncmp(shortsrc, "[string ", 8)) {
            int length = strlen(shortsrc);
            snprintf(buffer, sizeof(buffer), "lua %.*s", length - 9, shortsrc + 8);
        } else {
            snprintf(buffer, sizeof(buffer), "lua %s:%d", shortsrc, line);
        }

        source = buffer;

        lua_getfield(state, -3, "name");
        const char *name = lua_tostring(state, -1);

        func = name == NULL
             ? "..."
             : name;
    }

    lua_pop(state, 3);
    any_log_format(level, source, func, "%s", value);
    return 0;
}

static int lua_log_log(lua_State *state) {
    const char *level = luaL_checkstring(state, 1);
    lua_pop(state, 1);
    any_log_level_t l = any_log_level_from_string(level);
    assert(l > ANY_LOG_ALL);
    return lua_log_format(state, l);
}

static int lua_log_panic(lua_State *state) {
    return lua_log_format(state, ANY_LOG_PANIC);
}

static int lua_log_error(lua_State *state) {
    return lua_log_format(state, ANY_LOG_ERROR);
}

static int lua_log_warn(lua_State *state) {
    return lua_log_format(state, ANY_LOG_WARN);
}

static int lua_log_info(lua_State *state) {
    return lua_log_format(state, ANY_LOG_INFO);
}

static int lua_log_debug(lua_State *state) {
    return lua_log_format(state, ANY_LOG_DEBUG);
}

static int lua_log_trace(lua_State *state) {
    return lua_log_format(state, ANY_LOG_TRACE);
}

int lua_log_library(lua_State *state)
{
    static const luaL_Reg library[] = {
        { "log",   lua_log_log },
        { "panic", lua_log_panic },
        { "error", lua_log_error },
        { "warn",  lua_log_warn },
        { "info",  lua_log_info },
        { "debug", lua_log_debug },
        { "trace", lua_log_trace },
        { NULL, NULL },
    };
    luaL_newlib(state, library);
    return 1;
}