lua/ldblib.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 23 Jun 2017 17:28:03 -0400
changeset 58 1390348facc7
parent 0 d7ee4e2ed49d
permissions -rw-r--r--
Command line tool that decrypts an OPVault keychain and dumps it to stdout. To compile: gcc -o opvault opvault.c cJSON.c -lcrypto Usage: ./opvault </path/to/mykeychain.opvault> <password> This is just a proof of concept; I'll be recycling this into proper OPVault support in 1pass later and deleting this tool. This uses OpenSSL's libcrypto for the math instead of all the homegrown crypto this project is otherwise using. I'll probably migrate the rest in this direction, too, since this wasn't as bad as I expected to use and gets you all the package-manager mojo of automatic bug fixes and security patches and shared code, etc. cJSON parses JSON in C. That is from https://github.com/DaveGamble/cJSON An example OPVault keychain from AgileBits is available here: https://cache.agilebits.com/security-kb/
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     1
/*
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     2
** $Id: ldblib.c,v 1.132.1.1 2013/04/12 18:48:47 roberto Exp $
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     3
** Interface from Lua to its debug API
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     4
** See Copyright Notice in lua.h
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     5
*/
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     6
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     7
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     8
#include <stdio.h>
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     9
#include <stdlib.h>
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    10
#include <string.h>
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    11
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    12
#define ldblib_c
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    13
#define LUA_LIB
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    14
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    15
#include "lua.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    16
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    17
#include "lauxlib.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    18
#include "lualib.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    19
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    20
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    21
#define HOOKKEY		"_HKEY"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    22
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    23
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    24
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    25
static int db_getregistry (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    26
  lua_pushvalue(L, LUA_REGISTRYINDEX);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    27
  return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    28
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    29
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    30
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    31
static int db_getmetatable (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    32
  luaL_checkany(L, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    33
  if (!lua_getmetatable(L, 1)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    34
    lua_pushnil(L);  /* no metatable */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    35
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    36
  return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    37
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    38
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    39
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    40
static int db_setmetatable (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    41
  int t = lua_type(L, 2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    42
  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    43
                    "nil or table expected");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    44
  lua_settop(L, 2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    45
  lua_setmetatable(L, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    46
  return 1;  /* return 1st argument */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    47
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    48
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    49
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    50
static int db_getuservalue (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    51
  if (lua_type(L, 1) != LUA_TUSERDATA)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    52
    lua_pushnil(L);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    53
  else
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    54
    lua_getuservalue(L, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    55
  return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    56
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    57
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    58
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    59
static int db_setuservalue (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    60
  if (lua_type(L, 1) == LUA_TLIGHTUSERDATA)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    61
    luaL_argerror(L, 1, "full userdata expected, got light userdata");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    62
  luaL_checktype(L, 1, LUA_TUSERDATA);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    63
  if (!lua_isnoneornil(L, 2))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    64
    luaL_checktype(L, 2, LUA_TTABLE);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    65
  lua_settop(L, 2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    66
  lua_setuservalue(L, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    67
  return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    68
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    69
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    70
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    71
static void settabss (lua_State *L, const char *i, const char *v) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    72
  lua_pushstring(L, v);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    73
  lua_setfield(L, -2, i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    74
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    75
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    76
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    77
static void settabsi (lua_State *L, const char *i, int v) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    78
  lua_pushinteger(L, v);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    79
  lua_setfield(L, -2, i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    80
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    81
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    82
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    83
static void settabsb (lua_State *L, const char *i, int v) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    84
  lua_pushboolean(L, v);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    85
  lua_setfield(L, -2, i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    86
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    87
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    88
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    89
static lua_State *getthread (lua_State *L, int *arg) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    90
  if (lua_isthread(L, 1)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    91
    *arg = 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    92
    return lua_tothread(L, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    93
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    94
  else {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    95
    *arg = 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    96
    return L;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    97
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    98
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    99
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   100
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   101
static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   102
  if (L == L1) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   103
    lua_pushvalue(L, -2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   104
    lua_remove(L, -3);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   105
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   106
  else
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   107
    lua_xmove(L1, L, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   108
  lua_setfield(L, -2, fname);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   109
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   110
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   111
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   112
static int db_getinfo (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   113
  lua_Debug ar;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   114
  int arg;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   115
  lua_State *L1 = getthread(L, &arg);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   116
  const char *options = luaL_optstring(L, arg+2, "flnStu");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   117
  if (lua_isnumber(L, arg+1)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   118
    if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   119
      lua_pushnil(L);  /* level out of range */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   120
      return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   121
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   122
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   123
  else if (lua_isfunction(L, arg+1)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   124
    lua_pushfstring(L, ">%s", options);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   125
    options = lua_tostring(L, -1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   126
    lua_pushvalue(L, arg+1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   127
    lua_xmove(L, L1, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   128
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   129
  else
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   130
    return luaL_argerror(L, arg+1, "function or level expected");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   131
  if (!lua_getinfo(L1, options, &ar))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   132
    return luaL_argerror(L, arg+2, "invalid option");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   133
  lua_createtable(L, 0, 2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   134
  if (strchr(options, 'S')) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   135
    settabss(L, "source", ar.source);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   136
    settabss(L, "short_src", ar.short_src);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   137
    settabsi(L, "linedefined", ar.linedefined);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   138
    settabsi(L, "lastlinedefined", ar.lastlinedefined);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   139
    settabss(L, "what", ar.what);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   140
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   141
  if (strchr(options, 'l'))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   142
    settabsi(L, "currentline", ar.currentline);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   143
  if (strchr(options, 'u')) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   144
    settabsi(L, "nups", ar.nups);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   145
    settabsi(L, "nparams", ar.nparams);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   146
    settabsb(L, "isvararg", ar.isvararg);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   147
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   148
  if (strchr(options, 'n')) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   149
    settabss(L, "name", ar.name);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   150
    settabss(L, "namewhat", ar.namewhat);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   151
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   152
  if (strchr(options, 't'))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   153
    settabsb(L, "istailcall", ar.istailcall);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   154
  if (strchr(options, 'L'))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   155
    treatstackoption(L, L1, "activelines");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   156
  if (strchr(options, 'f'))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   157
    treatstackoption(L, L1, "func");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   158
  return 1;  /* return table */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   159
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   160
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   161
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   162
static int db_getlocal (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   163
  int arg;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   164
  lua_State *L1 = getthread(L, &arg);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   165
  lua_Debug ar;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   166
  const char *name;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   167
  int nvar = luaL_checkint(L, arg+2);  /* local-variable index */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   168
  if (lua_isfunction(L, arg + 1)) {  /* function argument? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   169
    lua_pushvalue(L, arg + 1);  /* push function */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   170
    lua_pushstring(L, lua_getlocal(L, NULL, nvar));  /* push local name */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   171
    return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   172
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   173
  else {  /* stack-level argument */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   174
    if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   175
      return luaL_argerror(L, arg+1, "level out of range");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   176
    name = lua_getlocal(L1, &ar, nvar);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   177
    if (name) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   178
      lua_xmove(L1, L, 1);  /* push local value */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   179
      lua_pushstring(L, name);  /* push name */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   180
      lua_pushvalue(L, -2);  /* re-order */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   181
      return 2;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   182
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   183
    else {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   184
      lua_pushnil(L);  /* no name (nor value) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   185
      return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   186
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   187
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   188
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   189
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   190
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   191
static int db_setlocal (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   192
  int arg;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   193
  lua_State *L1 = getthread(L, &arg);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   194
  lua_Debug ar;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   195
  if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   196
    return luaL_argerror(L, arg+1, "level out of range");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   197
  luaL_checkany(L, arg+3);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   198
  lua_settop(L, arg+3);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   199
  lua_xmove(L, L1, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   200
  lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   201
  return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   202
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   203
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   204
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   205
static int auxupvalue (lua_State *L, int get) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   206
  const char *name;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   207
  int n = luaL_checkint(L, 2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   208
  luaL_checktype(L, 1, LUA_TFUNCTION);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   209
  name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   210
  if (name == NULL) return 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   211
  lua_pushstring(L, name);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   212
  lua_insert(L, -(get+1));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   213
  return get + 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   214
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   215
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   216
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   217
static int db_getupvalue (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   218
  return auxupvalue(L, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   219
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   220
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   221
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   222
static int db_setupvalue (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   223
  luaL_checkany(L, 3);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   224
  return auxupvalue(L, 0);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   225
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   226
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   227
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   228
static int checkupval (lua_State *L, int argf, int argnup) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   229
  lua_Debug ar;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   230
  int nup = luaL_checkint(L, argnup);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   231
  luaL_checktype(L, argf, LUA_TFUNCTION);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   232
  lua_pushvalue(L, argf);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   233
  lua_getinfo(L, ">u", &ar);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   234
  luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   235
  return nup;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   236
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   237
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   238
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   239
static int db_upvalueid (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   240
  int n = checkupval(L, 1, 2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   241
  lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   242
  return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   243
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   244
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   245
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   246
static int db_upvaluejoin (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   247
  int n1 = checkupval(L, 1, 2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   248
  int n2 = checkupval(L, 3, 4);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   249
  luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   250
  luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   251
  lua_upvaluejoin(L, 1, n1, 3, n2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   252
  return 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   253
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   254
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   255
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   256
#define gethooktable(L)	luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   257
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   258
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   259
static void hookf (lua_State *L, lua_Debug *ar) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   260
  static const char *const hooknames[] =
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   261
    {"call", "return", "line", "count", "tail call"};
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   262
  gethooktable(L);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   263
  lua_pushthread(L);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   264
  lua_rawget(L, -2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   265
  if (lua_isfunction(L, -1)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   266
    lua_pushstring(L, hooknames[(int)ar->event]);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   267
    if (ar->currentline >= 0)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   268
      lua_pushinteger(L, ar->currentline);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   269
    else lua_pushnil(L);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   270
    lua_assert(lua_getinfo(L, "lS", ar));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   271
    lua_call(L, 2, 0);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   272
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   273
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   274
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   275
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   276
static int makemask (const char *smask, int count) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   277
  int mask = 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   278
  if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   279
  if (strchr(smask, 'r')) mask |= LUA_MASKRET;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   280
  if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   281
  if (count > 0) mask |= LUA_MASKCOUNT;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   282
  return mask;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   283
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   284
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   285
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   286
static char *unmakemask (int mask, char *smask) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   287
  int i = 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   288
  if (mask & LUA_MASKCALL) smask[i++] = 'c';
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   289
  if (mask & LUA_MASKRET) smask[i++] = 'r';
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   290
  if (mask & LUA_MASKLINE) smask[i++] = 'l';
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   291
  smask[i] = '\0';
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   292
  return smask;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   293
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   294
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   295
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   296
static int db_sethook (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   297
  int arg, mask, count;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   298
  lua_Hook func;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   299
  lua_State *L1 = getthread(L, &arg);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   300
  if (lua_isnoneornil(L, arg+1)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   301
    lua_settop(L, arg+1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   302
    func = NULL; mask = 0; count = 0;  /* turn off hooks */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   303
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   304
  else {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   305
    const char *smask = luaL_checkstring(L, arg+2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   306
    luaL_checktype(L, arg+1, LUA_TFUNCTION);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   307
    count = luaL_optint(L, arg+3, 0);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   308
    func = hookf; mask = makemask(smask, count);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   309
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   310
  if (gethooktable(L) == 0) {  /* creating hook table? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   311
    lua_pushstring(L, "k");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   312
    lua_setfield(L, -2, "__mode");  /** hooktable.__mode = "k" */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   313
    lua_pushvalue(L, -1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   314
    lua_setmetatable(L, -2);  /* setmetatable(hooktable) = hooktable */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   315
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   316
  lua_pushthread(L1); lua_xmove(L1, L, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   317
  lua_pushvalue(L, arg+1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   318
  lua_rawset(L, -3);  /* set new hook */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   319
  lua_sethook(L1, func, mask, count);  /* set hooks */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   320
  return 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   321
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   322
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   323
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   324
static int db_gethook (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   325
  int arg;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   326
  lua_State *L1 = getthread(L, &arg);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   327
  char buff[5];
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   328
  int mask = lua_gethookmask(L1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   329
  lua_Hook hook = lua_gethook(L1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   330
  if (hook != NULL && hook != hookf)  /* external hook? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   331
    lua_pushliteral(L, "external hook");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   332
  else {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   333
    gethooktable(L);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   334
    lua_pushthread(L1); lua_xmove(L1, L, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   335
    lua_rawget(L, -2);   /* get hook */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   336
    lua_remove(L, -2);  /* remove hook table */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   337
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   338
  lua_pushstring(L, unmakemask(mask, buff));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   339
  lua_pushinteger(L, lua_gethookcount(L1));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   340
  return 3;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   341
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   342
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   343
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   344
static int db_debug (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   345
  for (;;) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   346
    char buffer[250];
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   347
    luai_writestringerror("%s", "lua_debug> ");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   348
    if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   349
        strcmp(buffer, "cont\n") == 0)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   350
      return 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   351
    if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   352
        lua_pcall(L, 0, 0, 0))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   353
      luai_writestringerror("%s\n", lua_tostring(L, -1));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   354
    lua_settop(L, 0);  /* remove eventual returns */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   355
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   356
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   357
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   358
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   359
static int db_traceback (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   360
  int arg;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   361
  lua_State *L1 = getthread(L, &arg);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   362
  const char *msg = lua_tostring(L, arg + 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   363
  if (msg == NULL && !lua_isnoneornil(L, arg + 1))  /* non-string 'msg'? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   364
    lua_pushvalue(L, arg + 1);  /* return it untouched */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   365
  else {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   366
    int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   367
    luaL_traceback(L, L1, msg, level);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   368
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   369
  return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   370
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   371
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   372
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   373
static const luaL_Reg dblib[] = {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   374
  {"debug", db_debug},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   375
  {"getuservalue", db_getuservalue},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   376
  {"gethook", db_gethook},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   377
  {"getinfo", db_getinfo},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   378
  {"getlocal", db_getlocal},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   379
  {"getregistry", db_getregistry},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   380
  {"getmetatable", db_getmetatable},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   381
  {"getupvalue", db_getupvalue},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   382
  {"upvaluejoin", db_upvaluejoin},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   383
  {"upvalueid", db_upvalueid},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   384
  {"setuservalue", db_setuservalue},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   385
  {"sethook", db_sethook},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   386
  {"setlocal", db_setlocal},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   387
  {"setmetatable", db_setmetatable},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   388
  {"setupvalue", db_setupvalue},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   389
  {"traceback", db_traceback},
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   390
  {NULL, NULL}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   391
};
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   392
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   393
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   394
LUAMOD_API int luaopen_debug (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   395
  luaL_newlib(L, dblib);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   396
  return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   397
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   398