From 5f4b111d064ebc19e88760ddeb2ff9ceb649b0b1 Mon Sep 17 00:00:00 2001 From: JailDoctor Date: Sat, 25 Sep 2021 19:13:55 +0200 Subject: [PATCH] first commit --- .gitignore | 0 .vscode/launch.json | 29 + .vscode/settings.json | 8 + .vscode/tasks.json | 32 + font.xlsx | Bin 0 -> 32143 bytes game.lua | 38 + lua.cpp | 637 ++++++++++++++ lua.h | 7 + lua/lapi.c | 1455 ++++++++++++++++++++++++++++++ lua/lapi.h | 49 ++ lua/lauxlib.c | 1105 +++++++++++++++++++++++ lua/lauxlib.h | 293 ++++++ lua/lbaselib.c | 528 +++++++++++ lua/lcode.c | 1814 ++++++++++++++++++++++++++++++++++++++ lua/lcode.h | 104 +++ lua/lcorolib.c | 210 +++++ lua/lctype.c | 64 ++ lua/lctype.h | 101 +++ lua/ldblib.c | 483 ++++++++++ lua/ldebug.c | 877 ++++++++++++++++++ lua/ldebug.h | 63 ++ lua/ldo.c | 963 ++++++++++++++++++++ lua/ldo.h | 79 ++ lua/ldump.c | 226 +++++ lua/lfunc.c | 294 +++++++ lua/lfunc.h | 64 ++ lua/lgc.c | 1728 ++++++++++++++++++++++++++++++++++++ lua/lgc.h | 189 ++++ lua/linit.c | 65 ++ lua/liolib.c | 828 +++++++++++++++++ lua/ljumptab.h | 112 +++ lua/llex.c | 581 ++++++++++++ lua/llex.h | 91 ++ lua/llimits.h | 353 ++++++++ lua/lmathlib.c | 764 ++++++++++++++++ lua/lmem.c | 201 +++++ lua/lmem.h | 93 ++ lua/loadlib.c | 762 ++++++++++++++++ lua/lobject.c | 592 +++++++++++++ lua/lobject.h | 800 +++++++++++++++++ lua/lopcodes.c | 104 +++ lua/lopcodes.h | 392 +++++++++ lua/lopnames.h | 103 +++ lua/loslib.c | 430 +++++++++ lua/lparser.c | 1956 +++++++++++++++++++++++++++++++++++++++++ lua/lparser.h | 171 ++++ lua/lprefix.h | 45 + lua/lstate.c | 439 +++++++++ lua/lstate.h | 404 +++++++++ lua/lstring.c | 273 ++++++ lua/lstring.h | 57 ++ lua/lstrlib.c | 1817 ++++++++++++++++++++++++++++++++++++++ lua/ltable.c | 971 ++++++++++++++++++++ lua/ltable.h | 66 ++ lua/ltablib.c | 429 +++++++++ lua/ltm.c | 271 ++++++ lua/ltm.h | 103 +++ lua/lua.h | 518 +++++++++++ lua/lua.hpp | 9 + lua/luaconf.h | 790 +++++++++++++++++ lua/lualib.h | 52 ++ lua/lundump.c | 333 +++++++ lua/lundump.h | 36 + lua/lutf8lib.c | 289 ++++++ lua/lvm.c | 1836 ++++++++++++++++++++++++++++++++++++++ lua/lvm.h | 136 +++ lua/lzio.c | 68 ++ lua/lzio.h | 66 ++ main.cpp | 27 + mini.cpp | 678 ++++++++++++++ mini.exe | Bin 0 -> 1193216 bytes mini.h | 205 +++++ sprites.aseprite | Bin 0 -> 718 bytes sprites.bmp | Bin 0 -> 8310 bytes sweetie-16.pal | 19 + 75 files changed, 29775 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 font.xlsx create mode 100644 game.lua create mode 100644 lua.cpp create mode 100644 lua.h create mode 100644 lua/lapi.c create mode 100644 lua/lapi.h create mode 100644 lua/lauxlib.c create mode 100644 lua/lauxlib.h create mode 100644 lua/lbaselib.c create mode 100644 lua/lcode.c create mode 100644 lua/lcode.h create mode 100644 lua/lcorolib.c create mode 100644 lua/lctype.c create mode 100644 lua/lctype.h create mode 100644 lua/ldblib.c create mode 100644 lua/ldebug.c create mode 100644 lua/ldebug.h create mode 100644 lua/ldo.c create mode 100644 lua/ldo.h create mode 100644 lua/ldump.c create mode 100644 lua/lfunc.c create mode 100644 lua/lfunc.h create mode 100644 lua/lgc.c create mode 100644 lua/lgc.h create mode 100644 lua/linit.c create mode 100644 lua/liolib.c create mode 100644 lua/ljumptab.h create mode 100644 lua/llex.c create mode 100644 lua/llex.h create mode 100644 lua/llimits.h create mode 100644 lua/lmathlib.c create mode 100644 lua/lmem.c create mode 100644 lua/lmem.h create mode 100644 lua/loadlib.c create mode 100644 lua/lobject.c create mode 100644 lua/lobject.h create mode 100644 lua/lopcodes.c create mode 100644 lua/lopcodes.h create mode 100644 lua/lopnames.h create mode 100644 lua/loslib.c create mode 100644 lua/lparser.c create mode 100644 lua/lparser.h create mode 100644 lua/lprefix.h create mode 100644 lua/lstate.c create mode 100644 lua/lstate.h create mode 100644 lua/lstring.c create mode 100644 lua/lstring.h create mode 100644 lua/lstrlib.c create mode 100644 lua/ltable.c create mode 100644 lua/ltable.h create mode 100644 lua/ltablib.c create mode 100644 lua/ltm.c create mode 100644 lua/ltm.h create mode 100644 lua/lua.h create mode 100644 lua/lua.hpp create mode 100644 lua/luaconf.h create mode 100644 lua/lualib.h create mode 100644 lua/lundump.c create mode 100644 lua/lundump.h create mode 100644 lua/lutf8lib.c create mode 100644 lua/lvm.c create mode 100644 lua/lvm.h create mode 100644 lua/lzio.c create mode 100644 lua/lzio.h create mode 100644 main.cpp create mode 100644 mini.cpp create mode 100644 mini.exe create mode 100644 mini.h create mode 100644 sprites.aseprite create mode 100644 sprites.bmp create mode 100644 sweetie-16.pal diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e66abde --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "g++.exe - Compilar y depurar el archivo activo", + "type": "cppdbg", + "request": "launch", + "program": "${fileDirname}\\mini.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin\\gdb.exe", + "setupCommands": [ + { + "description": "Habilitar la impresión con sangría para gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "C/C++: g++.exe compilar archivo activo" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..bd284c1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "files.associations": { + "cmath": "cpp", + "*.tcc": "cpp", + "cinttypes": "cpp", + "cstdlib": "cpp" + } +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..2d3ceec --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,32 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: g++.exe compilar archivo activo", + "command": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin\\g++.exe", + "args": [ + "-g", + "*.cpp", + "./lua/*.c", + "-lmingw32", + "-lSDL2main", + "-lSDL2", + //"-mwindows", + "-o", + "${fileDirname}\\mini.exe" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "compilador: \"C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin\\g++.exe\"" + } + ] +} \ No newline at end of file diff --git a/font.xlsx b/font.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b9029e482d1b37c81f2b4f0cab7ad7e553eee6d8 GIT binary patch literal 32143 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 literal 0 HcmV?d00001 diff --git a/game.lua b/game.lua new file mode 100644 index 0000000..d410ca0 --- /dev/null +++ b/game.lua @@ -0,0 +1,38 @@ +x = 0 + +function text(str, x, y, color) + palt(0, false) + print(str, x-1, y-1, 0) + print(str, x , y-1, 0) + print(str, x+1, y-1, 0) + print(str, x-1, y , 0) + print(str, x+1, y , 0) + print(str, x-1, y+1, 0) + print(str, x , y+1, 0) + print(str, x+1, y+1, 0) + palt() + print(str, x, y, color) +end + +function _update() + cls(1) + camera(x, 0) + if btn(KEY_LEFT) then x = x + 1 end + if btn(KEY_RIGHT) then x = x - 1 end + map(0, 0, 0, 0, 16, 16) + rectfill(10, 10, 114, 40, 12) + palt(0, false) palt(9, true) + rect(10, 10, 114, 40, 0) + spr(16, 18, 40, 1, 1, true) + sspr(24, 0, 16, 16, 10, 50, 16, 16, false, false) + palt() + + text("HOLA, ESTA ES LA PRIMERA", 14, 15, 5) + text("DEMO DEL NOU E INCREIBLE", 14, 23, 5) + text("JAIL'S ADVENTURE 2!", 14, 31, 5) + circfill(64, 64, 20) + sset(9, 9, 6) + --ovalfill(30,10,100,100,8) + tline(10, 50, 10, 91, 1.125, 1, 0.0, 1.0/32.0) + line(10, 101, 41, 101, 9) +end diff --git a/lua.cpp b/lua.cpp new file mode 100644 index 0000000..007236f --- /dev/null +++ b/lua.cpp @@ -0,0 +1,637 @@ +#include "lua.h" +#include "lua/lua.hpp" +#include "mini.h" + +extern "C" { + static int cpp_cls(lua_State *L) { + uint8_t color = luaL_optinteger(L, 1, 0); + cls(color); + return 0; + } + + static int cpp_color(lua_State *L) { + uint8_t col = luaL_optinteger(L, 1, 6); + color(col); + return 0; + } + + static int cpp_pal(lua_State *L) { + int numargs = lua_gettop(L); + switch (numargs) { + case 0: pal(); return 0; + case 1: luaL_error(L, "not enough arguments"); return 0; + } + uint8_t c0 = luaL_checkinteger(L, 1); + uint8_t c1 = luaL_checkinteger(L, 2); + uint8_t p = luaL_optinteger(L, 1, 0); + pal(c0, c1, p); + return 0; + } + + static int cpp_palt(lua_State *L) { + int numargs = lua_gettop(L); + switch (numargs) { + case 0: palt(); return 0; + case 1: uint16_t bits = luaL_checkinteger(L, 1); palt(bits); return 0; + } + uint8_t col = luaL_checkinteger(L, 1); + bool t = lua_toboolean(L, 2); + palt(col, t); + return 0; + } + + static int cpp_pset(lua_State *L) { + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + if (lua_gettop(L) > 2) { + uint8_t color = luaL_checkinteger(L, 3); + pset(x, y, color); + } else { + pset(x, y); + } + return 0; + } + + static int cpp_pget(lua_State *L) { + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + lua_pushinteger(L, pget(x, y)); + return 1; + } + + static int cpp_line(lua_State *L) { + int x0 = luaL_checkinteger(L, 1); + int y0 = luaL_checkinteger(L, 2); + int x1 = luaL_checkinteger(L, 3); + int y1 = luaL_checkinteger(L, 4); + if (lua_gettop(L) > 4) { + uint8_t color = luaL_checkinteger(L, 5); + line(x0, y0, x1, y1, color); + } else { + line(x0, y0, x1, y1); + } + return 0; + } + + static int cpp_hline(lua_State *L) { + int x0 = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + int x1 = luaL_checkinteger(L, 3); + if (lua_gettop(L) > 3) { + uint8_t color = luaL_checkinteger(L, 4); + hline(x0, y, x1, color); + } else { + hline(x0, y, x1); + } + return 0; + } + + static int cpp_vline(lua_State *L) { + int x = luaL_checkinteger(L, 1); + int y0 = luaL_checkinteger(L, 2); + int y1 = luaL_checkinteger(L, 3); + if (lua_gettop(L) > 3) { + uint8_t color = luaL_checkinteger(L, 4); + vline(x, y0, y1, color); + } else { + vline(x, y0, y1); + } + return 0; + } + + static int cpp_rect(lua_State *L) { + int x0 = luaL_checkinteger(L, 1); + int y0 = luaL_checkinteger(L, 2); + int x1 = luaL_checkinteger(L, 3); + int y1 = luaL_checkinteger(L, 4); + if (lua_gettop(L) > 4) { + uint8_t color = luaL_checkinteger(L, 5); + rect(x0, y0, x1, y1, color); + } else { + rect(x0, y0, x1, y1); + } + return 0; + } + + static int cpp_rectfill(lua_State *L) { + int x0 = luaL_checkinteger(L, 1); + int y0 = luaL_checkinteger(L, 2); + int x1 = luaL_checkinteger(L, 3); + int y1 = luaL_checkinteger(L, 4); + if (lua_gettop(L) > 4) { + uint8_t color = luaL_checkinteger(L, 5); + rectfill(x0, y0, x1, y1, color); + } else { + rectfill(x0, y0, x1, y1); + } + return 0; + } + + static int cpp_fillp(lua_State *L) { + uint16_t pat = luaL_checkinteger(L, 1); + bool transparent = lua_toboolean(L, 2); + fillp(pat, transparent); + return 0; + } + + static int cpp_print(lua_State *L) { + const char* str = luaL_checkstring(L, 1); + int x = luaL_checkinteger(L, 2); + int y = luaL_checkinteger(L, 3); + if (lua_gettop(L) > 3) { + uint8_t color = luaL_checkinteger(L, 4); + print(str, x, y, color); + } else { + print(str, x, y); + } + return 0; + } + + static int cpp_clip(lua_State *L) { + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + int w = luaL_checkinteger(L, 3); + int h = luaL_checkinteger(L, 4); + clip(x, y, w, h); + return 0; + } + + static int cpp_camera(lua_State *L) { + int x = luaL_checknumber(L, 1); + int y = luaL_checknumber(L, 2); + camera(x, y); + return 0; + } + + static int cpp_circ(lua_State *L) { + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + int r = luaL_optinteger(L, 3, 4); + if (lua_gettop(L) > 3) { + uint8_t color = luaL_checkinteger(L, 4); + circ(x, y, r, color); + } else { + circ(x, y, r); + } + return 0; + } + + static int cpp_circfill(lua_State *L) { + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + int r = luaL_optinteger(L, 3, 4); + if (lua_gettop(L) > 3) { + uint8_t color = luaL_checkinteger(L, 4); + circfill(x, y, r, color); + } else { + circfill(x, y, r); + } + return 0; + } + + static int cpp_oval(lua_State *L) { + int x0 = luaL_checkinteger(L, 1); + int y0 = luaL_checkinteger(L, 2); + int x1 = luaL_checkinteger(L, 3); + int y1 = luaL_checkinteger(L, 4); + if (lua_gettop(L) > 4) { + uint8_t color = luaL_checkinteger(L, 5); + oval(x0, y0, x1, y1, color); + } else { + oval(x0, y0, x1, y1); + } + return 0; + } + + static int cpp_ovalfill(lua_State *L) { + int x0 = luaL_checkinteger(L, 1); + int y0 = luaL_checkinteger(L, 2); + int x1 = luaL_checkinteger(L, 3); + int y1 = luaL_checkinteger(L, 4); + if (lua_gettop(L) > 4) { + uint8_t color = luaL_checkinteger(L, 5); + ovalfill(x0, y0, x1, y1, color); + } else { + ovalfill(x0, y0, x1, y1); + } + return 0; + } + + static int cpp_sset(lua_State *L) { + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + if (lua_gettop(L) > 2) { + uint8_t color = luaL_checkinteger(L, 3); + sset(x, y, color); + } else { + sset(x, y); + } + return 0; + } + + static int cpp_sget(lua_State *L) { + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + lua_pushinteger(L, sget(x, y)); + return 1; + } + + static int cpp_spr(lua_State *L) { + uint8_t n = luaL_checkinteger(L, 1); + int x = luaL_checkinteger(L, 2); + int y = luaL_checkinteger(L, 3); + float w = luaL_optnumber(L, 4, 1.0f); + float h = luaL_optnumber(L, 5, 1.0f); + bool flip_x = lua_toboolean(L, 6); + bool flip_y = lua_toboolean(L, 7); + spr(n, x, y, w, h, flip_x, flip_y); + return 0; + } + + static int cpp_sspr(lua_State *L) { + int sx = luaL_checkinteger(L, 1); + int sy = luaL_checkinteger(L, 2); + int sw = luaL_checkinteger(L, 3); + int sh = luaL_checkinteger(L, 4); + int dx = luaL_checkinteger(L, 5); + int dy = luaL_checkinteger(L, 6); + int dw = luaL_optinteger(L, 7, 0); + int dh = luaL_optinteger(L, 8, 0); + bool flip_x = lua_toboolean(L, 9); + bool flip_y = lua_toboolean(L, 10); + sspr(sx, sy, sw, sh, dx, dy, dw, dh, flip_x, flip_y); + return 0; + } + + static int cpp_tline(lua_State *L) { + int x0 = luaL_checkinteger(L, 1); + int y0 = luaL_checkinteger(L, 2); + int x1 = luaL_checkinteger(L, 3); + int y1 = luaL_checkinteger(L, 4); + float mx = luaL_checknumber(L, 5); + float my = luaL_checknumber(L, 6); + float mdx = luaL_optnumber(L, 7, 0.125f); + float mdy = luaL_optnumber(L, 8, 0.0f); + tline(x0, y0, x1, y1, mx, my, mdx, mdy); + return 0; + } + + static int cpp_thline(lua_State *L) { + int x0 = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + int x1 = luaL_checkinteger(L, 3); + float mx = luaL_checknumber(L, 4); + float my = luaL_checknumber(L, 5); + float mdx = luaL_optnumber(L, 6, 0.125f); + float mdy = luaL_optnumber(L, 7, 0.0f); + thline(x0, y, x1, mx, my, mdx, mdy); + return 0; + } + + static int cpp_tvline(lua_State *L) { + int x = luaL_checkinteger(L, 1); + int y0 = luaL_checkinteger(L, 2); + int y1 = luaL_checkinteger(L, 3); + float mx = luaL_checknumber(L, 4); + float my = luaL_checknumber(L, 5); + float mdx = luaL_optnumber(L, 6, 0.0f); + float mdy = luaL_optnumber(L, 7, 0.125f); + tvline(x, y0, y1, mx, my, mdx, mdy); + return 0; + } + + static int cpp_mset(lua_State *L) { + int celx = luaL_checkinteger(L, 1); + int cely = luaL_checkinteger(L, 2); + uint8_t snum = luaL_checkinteger(L, 3); + mset(celx, cely, snum); + return 0; + } + + static int cpp_mget(lua_State *L) { + int celx = luaL_checkinteger(L, 1); + int cely = luaL_checkinteger(L, 2); + lua_pushinteger(L, mget(celx, cely)); + return 1; + } + + static int cpp_map(lua_State *L) { + uint8_t celx = luaL_checkinteger(L, 1); + uint8_t cely = luaL_checkinteger(L, 2); + int sx = luaL_checkinteger(L, 3); + int sy = luaL_checkinteger(L, 4); + uint8_t celw = luaL_checkinteger(L, 5); + uint8_t celh = luaL_checkinteger(L, 6); + uint8_t layer = luaL_optinteger(L, 7, 0); + map(celx, cely, sx, sy, celw, celh, layer); + return 0; + } + + static int cpp_btn(lua_State *L) { + uint8_t i = luaL_checkinteger(L, 1); + lua_pushboolean(L, btn(i)); + return 1; + } + + static int cpp_btnp(lua_State *L) { + uint8_t i = luaL_checkinteger(L, 1); + lua_pushboolean(L, btnp(i)); + return 1; + } + + static int cpp_time(lua_State *L) { + lua_pushnumber(L, time()); + return 1; + } + + static int cpp_abs(lua_State *L) { + float x = luaL_checknumber(L, 1); + lua_pushnumber(L, abs(x)); + return 1; + } + static int cpp_ceil(lua_State *L) { + float x = luaL_checknumber(L, 1); + lua_pushnumber(L, ceil(x)); + return 1; + } + static int cpp_flr(lua_State *L) { + float x = luaL_checknumber(L, 1); + lua_pushnumber(L, flr(x)); + return 1; + } + static int cpp_sgn(lua_State *L) { + float x = luaL_checknumber(L, 1); + lua_pushnumber(L, sgn(x)); + return 1; + } + static int cpp_sin(lua_State *L) { + float x = luaL_checknumber(L, 1); + lua_pushnumber(L, sin(x)); + return 1; + } + static int cpp_cos(lua_State *L) { + float x = luaL_checknumber(L, 1); + lua_pushnumber(L, cos(x)); + return 1; + } + static int cpp_atan2(lua_State *L) { + float dx = luaL_checknumber(L, 1); + float dy = luaL_checknumber(L, 2); + lua_pushnumber(L, atan2(dx, dy)); + return 1; + } + static int cpp_sqrt(lua_State *L) { + float x = luaL_checknumber(L, 1); + lua_pushnumber(L, sqrt(x)); + return 1; + } + static int cpp_max(lua_State *L) { + float x = luaL_checknumber(L, 1); + float y = luaL_checknumber(L, 2); + lua_pushnumber(L, max(x, y)); + return 1; + } + static int cpp_mid(lua_State *L) { + float x = luaL_checknumber(L, 1); + float y = luaL_checknumber(L, 2); + float z = luaL_checknumber(L, 3); + lua_pushnumber(L, mid(x, y, z)); + return 1; + } + static int cpp_min(lua_State *L) { + float x = luaL_checknumber(L, 1); + float y = luaL_checknumber(L, 2); + lua_pushnumber(L, min(x, y)); + return 1; + } + static int cpp_rnd(lua_State *L) { + int x = luaL_checkinteger(L, 1); + lua_pushinteger(L, rnd(x)); + return 1; + } + static int cpp_srand(lua_State *L) { + int x = luaL_checkinteger(L, 1); + srand(x); + return 0; + } + +} + +lua_State *L; +bool is_playing = false; +bool init_exists = false; +bool update_exists = false; + +bool lua_is_playing() { + return is_playing; +} + +void lua_init() { + L = luaL_newstate(); + + if (luaL_loadfile(L, "game.lua")) { + debug("error loading game"); + debug(lua_tostring(L, -1)); + lua_pop(L,1); + return; + } + + lua_pushcfunction(L,cpp_cls); lua_setglobal(L, "cls"); + lua_pushcfunction(L,cpp_color); lua_setglobal(L, "color"); + lua_pushcfunction(L,cpp_pal); lua_setglobal(L, "pal"); + lua_pushcfunction(L,cpp_palt); lua_setglobal(L, "palt"); + lua_pushcfunction(L,cpp_pset); lua_setglobal(L, "pset"); + lua_pushcfunction(L,cpp_pget); lua_setglobal(L, "pget"); + lua_pushcfunction(L,cpp_line); lua_setglobal(L, "line"); + lua_pushcfunction(L,cpp_hline); lua_setglobal(L, "hline"); + lua_pushcfunction(L,cpp_vline); lua_setglobal(L, "vline"); + lua_pushcfunction(L,cpp_rect); lua_setglobal(L, "rect"); + lua_pushcfunction(L,cpp_rectfill); lua_setglobal(L, "rectfill"); + lua_pushcfunction(L,cpp_fillp); lua_setglobal(L, "fillp"); + lua_pushcfunction(L,cpp_print); lua_setglobal(L, "print"); + lua_pushcfunction(L,cpp_clip); lua_setglobal(L, "clip"); + lua_pushcfunction(L,cpp_camera); lua_setglobal(L, "camera"); + lua_pushcfunction(L,cpp_circ); lua_setglobal(L, "circ"); + lua_pushcfunction(L,cpp_circfill); lua_setglobal(L, "circfill"); + lua_pushcfunction(L,cpp_oval); lua_setglobal(L, "oval"); + lua_pushcfunction(L,cpp_ovalfill); lua_setglobal(L, "ovalfill"); + lua_pushcfunction(L,cpp_sset); lua_setglobal(L, "sset"); + lua_pushcfunction(L,cpp_sget); lua_setglobal(L, "sget"); + lua_pushcfunction(L,cpp_spr); lua_setglobal(L, "spr"); + lua_pushcfunction(L,cpp_sspr); lua_setglobal(L, "sspr"); + lua_pushcfunction(L,cpp_tline); lua_setglobal(L, "tline"); + lua_pushcfunction(L,cpp_thline); lua_setglobal(L, "thline"); + lua_pushcfunction(L,cpp_tvline); lua_setglobal(L, "tvline"); + lua_pushcfunction(L,cpp_mget); lua_setglobal(L, "mget"); + lua_pushcfunction(L,cpp_mset); lua_setglobal(L, "mset"); + lua_pushcfunction(L,cpp_map); lua_setglobal(L, "map"); + lua_pushcfunction(L,cpp_btn); lua_setglobal(L, "btn"); + lua_pushcfunction(L,cpp_btnp); lua_setglobal(L, "btnp"); + lua_pushcfunction(L,cpp_time); lua_setglobal(L, "time"); + lua_pushcfunction(L,cpp_abs); lua_setglobal(L, "abs"); + lua_pushcfunction(L,cpp_ceil); lua_setglobal(L, "ceil"); + lua_pushcfunction(L,cpp_flr); lua_setglobal(L, "flr"); + lua_pushcfunction(L,cpp_sgn); lua_setglobal(L, "sgn"); + lua_pushcfunction(L,cpp_sin); lua_setglobal(L, "sin"); + lua_pushcfunction(L,cpp_cos); lua_setglobal(L, "cos"); + lua_pushcfunction(L,cpp_atan2); lua_setglobal(L, "atan2"); + lua_pushcfunction(L,cpp_sqrt); lua_setglobal(L, "sqrt"); + lua_pushcfunction(L,cpp_max); lua_setglobal(L, "max"); + lua_pushcfunction(L,cpp_mid); lua_setglobal(L, "mid"); + lua_pushcfunction(L,cpp_min); lua_setglobal(L, "min"); + lua_pushcfunction(L,cpp_rnd); lua_setglobal(L, "rnd"); + lua_pushcfunction(L,cpp_srand); lua_setglobal(L, "srand"); + + lua_pushinteger(L, 0); lua_setglobal(L, "KEY_UNKNOWN"); + lua_pushinteger(L, 4); lua_setglobal(L, "KEY_A"); + lua_pushinteger(L, 5); lua_setglobal(L, "KEY_B"); + lua_pushinteger(L, 6); lua_setglobal(L, "KEY_C"); + lua_pushinteger(L, 7); lua_setglobal(L, "KEY_D"); + lua_pushinteger(L, 8); lua_setglobal(L, "KEY_E"); + lua_pushinteger(L, 9); lua_setglobal(L, "KEY_F"); + lua_pushinteger(L, 10); lua_setglobal(L, "KEY_G"); + lua_pushinteger(L, 11); lua_setglobal(L, "KEY_H"); + lua_pushinteger(L, 12); lua_setglobal(L, "KEY_I"); + lua_pushinteger(L, 13); lua_setglobal(L, "KEY_J"); + lua_pushinteger(L, 14); lua_setglobal(L, "KEY_K"); + lua_pushinteger(L, 15); lua_setglobal(L, "KEY_L"); + lua_pushinteger(L, 16); lua_setglobal(L, "KEY_M"); + lua_pushinteger(L, 17); lua_setglobal(L, "KEY_N"); + lua_pushinteger(L, 18); lua_setglobal(L, "KEY_O"); + lua_pushinteger(L, 19); lua_setglobal(L, "KEY_P"); + lua_pushinteger(L, 20); lua_setglobal(L, "KEY_Q"); + lua_pushinteger(L, 21); lua_setglobal(L, "KEY_R"); + lua_pushinteger(L, 22); lua_setglobal(L, "KEY_S"); + lua_pushinteger(L, 23); lua_setglobal(L, "KEY_T"); + lua_pushinteger(L, 24); lua_setglobal(L, "KEY_U"); + lua_pushinteger(L, 25); lua_setglobal(L, "KEY_V"); + lua_pushinteger(L, 26); lua_setglobal(L, "KEY_W"); + lua_pushinteger(L, 27); lua_setglobal(L, "KEY_X"); + lua_pushinteger(L, 28); lua_setglobal(L, "KEY_Y"); + lua_pushinteger(L, 29); lua_setglobal(L, "KEY_Z"); + lua_pushinteger(L, 30); lua_setglobal(L, "KEY_1"); + lua_pushinteger(L, 31); lua_setglobal(L, "KEY_2"); + lua_pushinteger(L, 32); lua_setglobal(L, "KEY_3"); + lua_pushinteger(L, 33); lua_setglobal(L, "KEY_4"); + lua_pushinteger(L, 34); lua_setglobal(L, "KEY_5"); + lua_pushinteger(L, 35); lua_setglobal(L, "KEY_6"); + lua_pushinteger(L, 36); lua_setglobal(L, "KEY_7"); + lua_pushinteger(L, 37); lua_setglobal(L, "KEY_8"); + lua_pushinteger(L, 38); lua_setglobal(L, "KEY_9"); + lua_pushinteger(L, 39); lua_setglobal(L, "KEY_0"); + lua_pushinteger(L, 40); lua_setglobal(L, "KEY_RETURN"); + lua_pushinteger(L, 41); lua_setglobal(L, "KEY_ESCAPE"); + lua_pushinteger(L, 42); lua_setglobal(L, "KEY_BACKSPACE"); + lua_pushinteger(L, 43); lua_setglobal(L, "KEY_TAB"); + lua_pushinteger(L, 44); lua_setglobal(L, "KEY_SPACE"); + lua_pushinteger(L, 45); lua_setglobal(L, "KEY_MINUS"); + lua_pushinteger(L, 46); lua_setglobal(L, "KEY_EQUALS"); + lua_pushinteger(L, 47); lua_setglobal(L, "KEY_LEFTBRACKET"); + lua_pushinteger(L, 48); lua_setglobal(L, "KEY_RIGHTBRACKET"); + lua_pushinteger(L, 49); lua_setglobal(L, "KEY_BACKSLASH"); + lua_pushinteger(L, 50); lua_setglobal(L, "KEY_NONUSHASH"); + lua_pushinteger(L, 51); lua_setglobal(L, "KEY_SEMICOLON"); + lua_pushinteger(L, 52); lua_setglobal(L, "KEY_APOSTROPHE"); + lua_pushinteger(L, 53); lua_setglobal(L, "KEY_GRAVE"); + lua_pushinteger(L, 54); lua_setglobal(L, "KEY_COMMA"); + lua_pushinteger(L, 55); lua_setglobal(L, "KEY_PERIOD"); + lua_pushinteger(L, 56); lua_setglobal(L, "KEY_SLASH"); + lua_pushinteger(L, 57); lua_setglobal(L, "KEY_CAPSLOCK"); + lua_pushinteger(L, 58); lua_setglobal(L, "KEY_F1"); + lua_pushinteger(L, 59); lua_setglobal(L, "KEY_F2"); + lua_pushinteger(L, 60); lua_setglobal(L, "KEY_F3"); + lua_pushinteger(L, 61); lua_setglobal(L, "KEY_F4"); + lua_pushinteger(L, 62); lua_setglobal(L, "KEY_F5"); + lua_pushinteger(L, 63); lua_setglobal(L, "KEY_F6"); + lua_pushinteger(L, 64); lua_setglobal(L, "KEY_F7"); + lua_pushinteger(L, 65); lua_setglobal(L, "KEY_F8"); + lua_pushinteger(L, 66); lua_setglobal(L, "KEY_F9"); + lua_pushinteger(L, 67); lua_setglobal(L, "KEY_F10"); + lua_pushinteger(L, 68); lua_setglobal(L, "KEY_F11"); + lua_pushinteger(L, 69); lua_setglobal(L, "KEY_F12"); + lua_pushinteger(L, 70); lua_setglobal(L, "KEY_PRINTSCREEN"); + lua_pushinteger(L, 71); lua_setglobal(L, "KEY_SCROLLLOCK"); + lua_pushinteger(L, 72); lua_setglobal(L, "KEY_PAUSE"); + lua_pushinteger(L, 73); lua_setglobal(L, "KEY_INSERT"); + lua_pushinteger(L, 74); lua_setglobal(L, "KEY_HOME"); + lua_pushinteger(L, 75); lua_setglobal(L, "KEY_PAGEUP"); + lua_pushinteger(L, 76); lua_setglobal(L, "KEY_DELETE"); + lua_pushinteger(L, 77); lua_setglobal(L, "KEY_END"); + lua_pushinteger(L, 78); lua_setglobal(L, "KEY_PAGEDOWN"); + lua_pushinteger(L, 79); lua_setglobal(L, "KEY_RIGHT"); + lua_pushinteger(L, 80); lua_setglobal(L, "KEY_LEFT"); + lua_pushinteger(L, 81); lua_setglobal(L, "KEY_DOWN"); + lua_pushinteger(L, 82); lua_setglobal(L, "KEY_UP"); + lua_pushinteger(L, 83); lua_setglobal(L, "KEY_NUMLOCKCLEAR"); + lua_pushinteger(L, 84); lua_setglobal(L, "KEY_KP_DIVIDE"); + lua_pushinteger(L, 85); lua_setglobal(L, "KEY_KP_MULTIPLY"); + lua_pushinteger(L, 86); lua_setglobal(L, "KEY_KP_MINUS"); + lua_pushinteger(L, 87); lua_setglobal(L, "KEY_KP_PLUS"); + lua_pushinteger(L, 88); lua_setglobal(L, "KEY_KP_ENTER"); + lua_pushinteger(L, 89); lua_setglobal(L, "KEY_KP_1"); + lua_pushinteger(L, 90); lua_setglobal(L, "KEY_KP_2"); + lua_pushinteger(L, 91); lua_setglobal(L, "KEY_KP_3"); + lua_pushinteger(L, 92); lua_setglobal(L, "KEY_KP_4"); + lua_pushinteger(L, 93); lua_setglobal(L, "KEY_KP_5"); + lua_pushinteger(L, 94); lua_setglobal(L, "KEY_KP_6"); + lua_pushinteger(L, 95); lua_setglobal(L, "KEY_KP_7"); + lua_pushinteger(L, 96); lua_setglobal(L, "KEY_KP_8"); + lua_pushinteger(L, 97); lua_setglobal(L, "KEY_KP_9"); + lua_pushinteger(L, 98); lua_setglobal(L, "KEY_KP_0"); + lua_pushinteger(L, 99); lua_setglobal(L, "KEY_KP_PERIOD"); + lua_pushinteger(L, 100); lua_setglobal(L, "KEY_NONUSBACKSLASH"); + lua_pushinteger(L, 101); lua_setglobal(L, "KEY_APPLICATION"); + lua_pushinteger(L, 224); lua_setglobal(L, "KEY_LCTRL"); + lua_pushinteger(L, 225); lua_setglobal(L, "KEY_LSHIFT"); + lua_pushinteger(L, 226); lua_setglobal(L, "KEY_LALT"); + lua_pushinteger(L, 227); lua_setglobal(L, "KEY_LGUI"); + lua_pushinteger(L, 228); lua_setglobal(L, "KEY_RCTRL"); + lua_pushinteger(L, 229); lua_setglobal(L, "KEY_RSHIFT"); + lua_pushinteger(L, 230); lua_setglobal(L, "KEY_RALT"); + lua_pushinteger(L, 231); lua_setglobal(L, "KEY_RGUI"); + + if (lua_pcall(L,0, LUA_MULTRET, 0)) { + debug("runtime error"); + debug(lua_tostring(L, -1)); + lua_pop(L,1); + return; + } + + lua_getglobal(L, "_init"); + if (lua_isfunction(L,-1)) init_exists = true; + lua_pop(L,1); + + lua_getglobal(L, "_update"); + if (lua_isfunction(L,-1)) update_exists = true; + lua_pop(L,1); + + is_playing = true; +} + +void lua_call_init() { + if (!init_exists) return; + lua_getglobal(L, "_init"); + if (lua_pcall(L, 0, 0, 0)) { + debug("runtime error"); + debug(lua_tostring(L, -1)); + lua_pop(L,1); + is_playing = false; + } +} + +void lua_call_update() { + if (!update_exists) return; + lua_getglobal(L, "_update"); + if (lua_pcall(L, 0, 0, 0)) { + debug("runtime error"); + debug(lua_tostring(L, -1)); + lua_pop(L,1); + is_playing = false; + } +} + +void lua_quit() { + if (!is_playing) return; + is_playing = false; + lua_close(L); +} diff --git a/lua.h b/lua.h new file mode 100644 index 0000000..f991050 --- /dev/null +++ b/lua.h @@ -0,0 +1,7 @@ +#pragma once + +bool lua_is_playing(); +void lua_init(); +void lua_call_init(); +void lua_call_update(); +void lua_quit(); diff --git a/lua/lapi.c b/lua/lapi.c new file mode 100644 index 0000000..f8f70cd --- /dev/null +++ b/lua/lapi.c @@ -0,0 +1,1455 @@ +/* +** $Id: lapi.c $ +** Lua API +** See Copyright Notice in lua.h +*/ + +#define lapi_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" + + + +const char lua_ident[] = + "$LuaVersion: " LUA_COPYRIGHT " $" + "$LuaAuthors: " LUA_AUTHORS " $"; + + + +/* +** Test for a valid index (one that is not the 'nilvalue'). +** '!ttisnil(o)' implies 'o != &G(L)->nilvalue', so it is not needed. +** However, it covers the most common cases in a faster way. +*/ +#define isvalid(L, o) (!ttisnil(o) || o != &G(L)->nilvalue) + + +/* test for pseudo index */ +#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) + +/* test for upvalue */ +#define isupvalue(i) ((i) < LUA_REGISTRYINDEX) + + +static TValue *index2value (lua_State *L, int idx) { + CallInfo *ci = L->ci; + if (idx > 0) { + StkId o = ci->func + idx; + api_check(L, idx <= L->ci->top - (ci->func + 1), "unacceptable index"); + if (o >= L->top) return &G(L)->nilvalue; + else return s2v(o); + } + else if (!ispseudo(idx)) { /* negative index */ + api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + return s2v(L->top + idx); + } + else if (idx == LUA_REGISTRYINDEX) + return &G(L)->l_registry; + else { /* upvalues */ + idx = LUA_REGISTRYINDEX - idx; + api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); + if (ttislcf(s2v(ci->func))) /* light C function? */ + return &G(L)->nilvalue; /* it has no upvalues */ + else { + CClosure *func = clCvalue(s2v(ci->func)); + return (idx <= func->nupvalues) ? &func->upvalue[idx-1] + : &G(L)->nilvalue; + } + } +} + + +static StkId index2stack (lua_State *L, int idx) { + CallInfo *ci = L->ci; + if (idx > 0) { + StkId o = ci->func + idx; + api_check(L, o < L->top, "unacceptable index"); + return o; + } + else { /* non-positive index */ + api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + api_check(L, !ispseudo(idx), "invalid index"); + return L->top + idx; + } +} + + +LUA_API int lua_checkstack (lua_State *L, int n) { + int res; + CallInfo *ci; + lua_lock(L); + ci = L->ci; + api_check(L, n >= 0, "negative 'n'"); + if (L->stack_last - L->top > n) /* stack large enough? */ + res = 1; /* yes; check is OK */ + else { /* no; need to grow stack */ + int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; + if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ + res = 0; /* no */ + else /* try to grow stack */ + res = luaD_growstack(L, n, 0); + } + if (res && ci->top < L->top + n) + ci->top = L->top + n; /* adjust frame top */ + lua_unlock(L); + return res; +} + + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { + int i; + if (from == to) return; + lua_lock(to); + api_checknelems(from, n); + api_check(from, G(from) == G(to), "moving among independent states"); + api_check(from, to->ci->top - to->top >= n, "stack overflow"); + from->top -= n; + for (i = 0; i < n; i++) { + setobjs2s(to, to->top, from->top + i); + to->top++; /* stack already checked by previous 'api_check' */ + } + lua_unlock(to); +} + + +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { + lua_CFunction old; + lua_lock(L); + old = G(L)->panic; + G(L)->panic = panicf; + lua_unlock(L); + return old; +} + + +LUA_API lua_Number lua_version (lua_State *L) { + UNUSED(L); + return LUA_VERSION_NUM; +} + + + +/* +** basic stack manipulation +*/ + + +/* +** convert an acceptable stack index into an absolute index +*/ +LUA_API int lua_absindex (lua_State *L, int idx) { + return (idx > 0 || ispseudo(idx)) + ? idx + : cast_int(L->top - L->ci->func) + idx; +} + + +LUA_API int lua_gettop (lua_State *L) { + return cast_int(L->top - (L->ci->func + 1)); +} + + +LUA_API void lua_settop (lua_State *L, int idx) { + CallInfo *ci; + StkId func, newtop; + ptrdiff_t diff; /* difference for new top */ + lua_lock(L); + ci = L->ci; + func = ci->func; + if (idx >= 0) { + api_check(L, idx <= ci->top - (func + 1), "new top too large"); + diff = ((func + 1) + idx) - L->top; + for (; diff > 0; diff--) + setnilvalue(s2v(L->top++)); /* clear new slots */ + } + else { + api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); + diff = idx + 1; /* will "subtract" index (as it is negative) */ + } + api_check(L, L->tbclist < L->top, "previous pop of an unclosed slot"); + newtop = L->top + diff; + if (diff < 0 && L->tbclist >= newtop) { + lua_assert(hastocloseCfunc(ci->nresults)); + luaF_close(L, newtop, CLOSEKTOP, 0); + } + L->top = newtop; /* correct top only after closing any upvalue */ + lua_unlock(L); +} + + +LUA_API void lua_closeslot (lua_State *L, int idx) { + StkId level; + lua_lock(L); + level = index2stack(L, idx); + api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist == level, + "no variable to close at given level"); + luaF_close(L, level, CLOSEKTOP, 0); + level = index2stack(L, idx); /* stack may be moved */ + setnilvalue(s2v(level)); + lua_unlock(L); +} + + +/* +** Reverse the stack segment from 'from' to 'to' +** (auxiliary to 'lua_rotate') +** Note that we move(copy) only the value inside the stack. +** (We do not move additional fields that may exist.) +*/ +static void reverse (lua_State *L, StkId from, StkId to) { + for (; from < to; from++, to--) { + TValue temp; + setobj(L, &temp, s2v(from)); + setobjs2s(L, from, to); + setobj2s(L, to, &temp); + } +} + + +/* +** Let x = AB, where A is a prefix of length 'n'. Then, +** rotate x n == BA. But BA == (A^r . B^r)^r. +*/ +LUA_API void lua_rotate (lua_State *L, int idx, int n) { + StkId p, t, m; + lua_lock(L); + t = L->top - 1; /* end of stack segment being rotated */ + p = index2stack(L, idx); /* start of segment */ + api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); + m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ + reverse(L, p, m); /* reverse the prefix with length 'n' */ + reverse(L, m + 1, t); /* reverse the suffix */ + reverse(L, p, t); /* reverse the entire segment */ + lua_unlock(L); +} + + +LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { + TValue *fr, *to; + lua_lock(L); + fr = index2value(L, fromidx); + to = index2value(L, toidx); + api_check(L, isvalid(L, to), "invalid index"); + setobj(L, to, fr); + if (isupvalue(toidx)) /* function upvalue? */ + luaC_barrier(L, clCvalue(s2v(L->ci->func)), fr); + /* LUA_REGISTRYINDEX does not need gc barrier + (collector revisits it before finishing collection) */ + lua_unlock(L); +} + + +LUA_API void lua_pushvalue (lua_State *L, int idx) { + lua_lock(L); + setobj2s(L, L->top, index2value(L, idx)); + api_incr_top(L); + lua_unlock(L); +} + + + +/* +** access functions (stack -> C) +*/ + + +LUA_API int lua_type (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return (isvalid(L, o) ? ttype(o) : LUA_TNONE); +} + + +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + api_check(L, LUA_TNONE <= t && t < LUA_NUMTYPES, "invalid type"); + return ttypename(t); +} + + +LUA_API int lua_iscfunction (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return (ttislcf(o) || (ttisCclosure(o))); +} + + +LUA_API int lua_isinteger (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return ttisinteger(o); +} + + +LUA_API int lua_isnumber (lua_State *L, int idx) { + lua_Number n; + const TValue *o = index2value(L, idx); + return tonumber(o, &n); +} + + +LUA_API int lua_isstring (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return (ttisstring(o) || cvt2str(o)); +} + + +LUA_API int lua_isuserdata (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return (ttisfulluserdata(o) || ttislightuserdata(o)); +} + + +LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { + const TValue *o1 = index2value(L, index1); + const TValue *o2 = index2value(L, index2); + return (isvalid(L, o1) && isvalid(L, o2)) ? luaV_rawequalobj(o1, o2) : 0; +} + + +LUA_API void lua_arith (lua_State *L, int op) { + lua_lock(L); + if (op != LUA_OPUNM && op != LUA_OPBNOT) + api_checknelems(L, 2); /* all other operations expect two operands */ + else { /* for unary operations, add fake 2nd operand */ + api_checknelems(L, 1); + setobjs2s(L, L->top, L->top - 1); + api_incr_top(L); + } + /* first operand at top - 2, second at top - 1; result go to top - 2 */ + luaO_arith(L, op, s2v(L->top - 2), s2v(L->top - 1), L->top - 2); + L->top--; /* remove second operand */ + lua_unlock(L); +} + + +LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { + const TValue *o1; + const TValue *o2; + int i = 0; + lua_lock(L); /* may call tag method */ + o1 = index2value(L, index1); + o2 = index2value(L, index2); + if (isvalid(L, o1) && isvalid(L, o2)) { + switch (op) { + case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; + case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; + case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; + default: api_check(L, 0, "invalid option"); + } + } + lua_unlock(L); + return i; +} + + +LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { + size_t sz = luaO_str2num(s, s2v(L->top)); + if (sz != 0) + api_incr_top(L); + return sz; +} + + +LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) { + lua_Number n = 0; + const TValue *o = index2value(L, idx); + int isnum = tonumber(o, &n); + if (pisnum) + *pisnum = isnum; + return n; +} + + +LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) { + lua_Integer res = 0; + const TValue *o = index2value(L, idx); + int isnum = tointeger(o, &res); + if (pisnum) + *pisnum = isnum; + return res; +} + + +LUA_API int lua_toboolean (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return !l_isfalse(o); +} + + +LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { + TValue *o; + lua_lock(L); + o = index2value(L, idx); + if (!ttisstring(o)) { + if (!cvt2str(o)) { /* not convertible? */ + if (len != NULL) *len = 0; + lua_unlock(L); + return NULL; + } + luaO_tostring(L, o); + luaC_checkGC(L); + o = index2value(L, idx); /* previous call may reallocate the stack */ + } + if (len != NULL) + *len = vslen(o); + lua_unlock(L); + return svalue(o); +} + + +LUA_API lua_Unsigned lua_rawlen (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + switch (ttypetag(o)) { + case LUA_VSHRSTR: return tsvalue(o)->shrlen; + case LUA_VLNGSTR: return tsvalue(o)->u.lnglen; + case LUA_VUSERDATA: return uvalue(o)->len; + case LUA_VTABLE: return luaH_getn(hvalue(o)); + default: return 0; + } +} + + +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + if (ttislcf(o)) return fvalue(o); + else if (ttisCclosure(o)) + return clCvalue(o)->f; + else return NULL; /* not a C function */ +} + + +static void *touserdata (const TValue *o) { + switch (ttype(o)) { + case LUA_TUSERDATA: return getudatamem(uvalue(o)); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } +} + + +LUA_API void *lua_touserdata (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return touserdata(o); +} + + +LUA_API lua_State *lua_tothread (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return (!ttisthread(o)) ? NULL : thvalue(o); +} + + +/* +** Returns a pointer to the internal representation of an object. +** Note that ANSI C does not allow the conversion of a pointer to +** function to a 'void*', so the conversion here goes through +** a 'size_t'. (As the returned pointer is only informative, this +** conversion should not be a problem.) +*/ +LUA_API const void *lua_topointer (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + switch (ttypetag(o)) { + case LUA_VLCF: return cast_voidp(cast_sizet(fvalue(o))); + case LUA_VUSERDATA: case LUA_VLIGHTUSERDATA: + return touserdata(o); + default: { + if (iscollectable(o)) + return gcvalue(o); + else + return NULL; + } + } +} + + + +/* +** push functions (C -> stack) +*/ + + +LUA_API void lua_pushnil (lua_State *L) { + lua_lock(L); + setnilvalue(s2v(L->top)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { + lua_lock(L); + setfltvalue(s2v(L->top), n); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { + lua_lock(L); + setivalue(s2v(L->top), n); + api_incr_top(L); + lua_unlock(L); +} + + +/* +** Pushes on the stack a string with given length. Avoid using 's' when +** 'len' == 0 (as 's' can be NULL in that case), due to later use of +** 'memcmp' and 'memcpy'. +*/ +LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { + TString *ts; + lua_lock(L); + ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); + setsvalue2s(L, L->top, ts); + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return getstr(ts); +} + + +LUA_API const char *lua_pushstring (lua_State *L, const char *s) { + lua_lock(L); + if (s == NULL) + setnilvalue(s2v(L->top)); + else { + TString *ts; + ts = luaS_new(L, s); + setsvalue2s(L, L->top, ts); + s = getstr(ts); /* internal copy's address */ + } + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return s; +} + + +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, + va_list argp) { + const char *ret; + lua_lock(L); + ret = luaO_pushvfstring(L, fmt, argp); + luaC_checkGC(L); + lua_unlock(L); + return ret; +} + + +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { + const char *ret; + va_list argp; + lua_lock(L); + va_start(argp, fmt); + ret = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + luaC_checkGC(L); + lua_unlock(L); + return ret; +} + + +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { + lua_lock(L); + if (n == 0) { + setfvalue(s2v(L->top), fn); + api_incr_top(L); + } + else { + CClosure *cl; + api_checknelems(L, n); + api_check(L, n <= MAXUPVAL, "upvalue index too large"); + cl = luaF_newCclosure(L, n); + cl->f = fn; + L->top -= n; + while (n--) { + setobj2n(L, &cl->upvalue[n], s2v(L->top + n)); + /* does not need barrier because closure is white */ + lua_assert(iswhite(cl)); + } + setclCvalue(L, s2v(L->top), cl); + api_incr_top(L); + luaC_checkGC(L); + } + lua_unlock(L); +} + + +LUA_API void lua_pushboolean (lua_State *L, int b) { + lua_lock(L); + if (b) + setbtvalue(s2v(L->top)); + else + setbfvalue(s2v(L->top)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { + lua_lock(L); + setpvalue(s2v(L->top), p); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_pushthread (lua_State *L) { + lua_lock(L); + setthvalue(L, s2v(L->top), L); + api_incr_top(L); + lua_unlock(L); + return (G(L)->mainthread == L); +} + + + +/* +** get functions (Lua -> stack) +*/ + + +static int auxgetstr (lua_State *L, const TValue *t, const char *k) { + const TValue *slot; + TString *str = luaS_new(L, k); + if (luaV_fastget(L, t, str, slot, luaH_getstr)) { + setobj2s(L, L->top, slot); + api_incr_top(L); + } + else { + setsvalue2s(L, L->top, str); + api_incr_top(L); + luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot); + } + lua_unlock(L); + return ttype(s2v(L->top - 1)); +} + + +/* +** Get the global table in the registry. Since all predefined +** indices in the registry were inserted right when the registry +** was created and never removed, they must always be in the array +** part of the registry. +*/ +#define getGtable(L) \ + (&hvalue(&G(L)->l_registry)->array[LUA_RIDX_GLOBALS - 1]) + + +LUA_API int lua_getglobal (lua_State *L, const char *name) { + const TValue *G; + lua_lock(L); + G = getGtable(L); + return auxgetstr(L, G, name); +} + + +LUA_API int lua_gettable (lua_State *L, int idx) { + const TValue *slot; + TValue *t; + lua_lock(L); + t = index2value(L, idx); + if (luaV_fastget(L, t, s2v(L->top - 1), slot, luaH_get)) { + setobj2s(L, L->top - 1, slot); + } + else + luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot); + lua_unlock(L); + return ttype(s2v(L->top - 1)); +} + + +LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { + lua_lock(L); + return auxgetstr(L, index2value(L, idx), k); +} + + +LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { + TValue *t; + const TValue *slot; + lua_lock(L); + t = index2value(L, idx); + if (luaV_fastgeti(L, t, n, slot)) { + setobj2s(L, L->top, slot); + } + else { + TValue aux; + setivalue(&aux, n); + luaV_finishget(L, t, &aux, L->top, slot); + } + api_incr_top(L); + lua_unlock(L); + return ttype(s2v(L->top - 1)); +} + + +static int finishrawget (lua_State *L, const TValue *val) { + if (isempty(val)) /* avoid copying empty items to the stack */ + setnilvalue(s2v(L->top)); + else + setobj2s(L, L->top, val); + api_incr_top(L); + lua_unlock(L); + return ttype(s2v(L->top - 1)); +} + + +static Table *gettable (lua_State *L, int idx) { + TValue *t = index2value(L, idx); + api_check(L, ttistable(t), "table expected"); + return hvalue(t); +} + + +LUA_API int lua_rawget (lua_State *L, int idx) { + Table *t; + const TValue *val; + lua_lock(L); + api_checknelems(L, 1); + t = gettable(L, idx); + val = luaH_get(t, s2v(L->top - 1)); + L->top--; /* remove key */ + return finishrawget(L, val); +} + + +LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { + Table *t; + lua_lock(L); + t = gettable(L, idx); + return finishrawget(L, luaH_getint(t, n)); +} + + +LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { + Table *t; + TValue k; + lua_lock(L); + t = gettable(L, idx); + setpvalue(&k, cast_voidp(p)); + return finishrawget(L, luaH_get(t, &k)); +} + + +LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { + Table *t; + lua_lock(L); + t = luaH_new(L); + sethvalue2s(L, L->top, t); + api_incr_top(L); + if (narray > 0 || nrec > 0) + luaH_resize(L, t, narray, nrec); + luaC_checkGC(L); + lua_unlock(L); +} + + +LUA_API int lua_getmetatable (lua_State *L, int objindex) { + const TValue *obj; + Table *mt; + int res = 0; + lua_lock(L); + obj = index2value(L, objindex); + switch (ttype(obj)) { + case LUA_TTABLE: + mt = hvalue(obj)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(obj)->metatable; + break; + default: + mt = G(L)->mt[ttype(obj)]; + break; + } + if (mt != NULL) { + sethvalue2s(L, L->top, mt); + api_incr_top(L); + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) { + TValue *o; + int t; + lua_lock(L); + o = index2value(L, idx); + api_check(L, ttisfulluserdata(o), "full userdata expected"); + if (n <= 0 || n > uvalue(o)->nuvalue) { + setnilvalue(s2v(L->top)); + t = LUA_TNONE; + } + else { + setobj2s(L, L->top, &uvalue(o)->uv[n - 1].uv); + t = ttype(s2v(L->top)); + } + api_incr_top(L); + lua_unlock(L); + return t; +} + + +/* +** set functions (stack -> Lua) +*/ + +/* +** t[k] = value at the top of the stack (where 'k' is a string) +*/ +static void auxsetstr (lua_State *L, const TValue *t, const char *k) { + const TValue *slot; + TString *str = luaS_new(L, k); + api_checknelems(L, 1); + if (luaV_fastget(L, t, str, slot, luaH_getstr)) { + luaV_finishfastset(L, t, slot, s2v(L->top - 1)); + L->top--; /* pop value */ + } + else { + setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ + api_incr_top(L); + luaV_finishset(L, t, s2v(L->top - 1), s2v(L->top - 2), slot); + L->top -= 2; /* pop value and key */ + } + lua_unlock(L); /* lock done by caller */ +} + + +LUA_API void lua_setglobal (lua_State *L, const char *name) { + const TValue *G; + lua_lock(L); /* unlock done in 'auxsetstr' */ + G = getGtable(L); + auxsetstr(L, G, name); +} + + +LUA_API void lua_settable (lua_State *L, int idx) { + TValue *t; + const TValue *slot; + lua_lock(L); + api_checknelems(L, 2); + t = index2value(L, idx); + if (luaV_fastget(L, t, s2v(L->top - 2), slot, luaH_get)) { + luaV_finishfastset(L, t, slot, s2v(L->top - 1)); + } + else + luaV_finishset(L, t, s2v(L->top - 2), s2v(L->top - 1), slot); + L->top -= 2; /* pop index and value */ + lua_unlock(L); +} + + +LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { + lua_lock(L); /* unlock done in 'auxsetstr' */ + auxsetstr(L, index2value(L, idx), k); +} + + +LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { + TValue *t; + const TValue *slot; + lua_lock(L); + api_checknelems(L, 1); + t = index2value(L, idx); + if (luaV_fastgeti(L, t, n, slot)) { + luaV_finishfastset(L, t, slot, s2v(L->top - 1)); + } + else { + TValue aux; + setivalue(&aux, n); + luaV_finishset(L, t, &aux, s2v(L->top - 1), slot); + } + L->top--; /* pop value */ + lua_unlock(L); +} + + +static void aux_rawset (lua_State *L, int idx, TValue *key, int n) { + Table *t; + lua_lock(L); + api_checknelems(L, n); + t = gettable(L, idx); + luaH_set(L, t, key, s2v(L->top - 1)); + invalidateTMcache(t); + luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); + L->top -= n; + lua_unlock(L); +} + + +LUA_API void lua_rawset (lua_State *L, int idx) { + aux_rawset(L, idx, s2v(L->top - 2), 2); +} + + +LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { + TValue k; + setpvalue(&k, cast_voidp(p)); + aux_rawset(L, idx, &k, 1); +} + + +LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { + Table *t; + lua_lock(L); + api_checknelems(L, 1); + t = gettable(L, idx); + luaH_setint(L, t, n, s2v(L->top - 1)); + luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); + L->top--; + lua_unlock(L); +} + + +LUA_API int lua_setmetatable (lua_State *L, int objindex) { + TValue *obj; + Table *mt; + lua_lock(L); + api_checknelems(L, 1); + obj = index2value(L, objindex); + if (ttisnil(s2v(L->top - 1))) + mt = NULL; + else { + api_check(L, ttistable(s2v(L->top - 1)), "table expected"); + mt = hvalue(s2v(L->top - 1)); + } + switch (ttype(obj)) { + case LUA_TTABLE: { + hvalue(obj)->metatable = mt; + if (mt) { + luaC_objbarrier(L, gcvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } + break; + } + case LUA_TUSERDATA: { + uvalue(obj)->metatable = mt; + if (mt) { + luaC_objbarrier(L, uvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } + break; + } + default: { + G(L)->mt[ttype(obj)] = mt; + break; + } + } + L->top--; + lua_unlock(L); + return 1; +} + + +LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { + TValue *o; + int res; + lua_lock(L); + api_checknelems(L, 1); + o = index2value(L, idx); + api_check(L, ttisfulluserdata(o), "full userdata expected"); + if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue))) + res = 0; /* 'n' not in [1, uvalue(o)->nuvalue] */ + else { + setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top - 1)); + luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); + res = 1; + } + L->top--; + lua_unlock(L); + return res; +} + + +/* +** 'load' and 'call' functions (run Lua code) +*/ + + +#define checkresults(L,na,nr) \ + api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ + "results from function overflow current stack size") + + +LUA_API void lua_callk (lua_State *L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k) { + StkId func; + lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); + api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); + func = L->top - (nargs+1); + if (k != NULL && yieldable(L)) { /* need to prepare continuation? */ + L->ci->u.c.k = k; /* save continuation */ + L->ci->u.c.ctx = ctx; /* save context */ + luaD_call(L, func, nresults); /* do the call */ + } + else /* no continuation or no yieldable */ + luaD_callnoyield(L, func, nresults); /* just do the call */ + adjustresults(L, nresults); + lua_unlock(L); +} + + + +/* +** Execute a protected call. +*/ +struct CallS { /* data to 'f_call' */ + StkId func; + int nresults; +}; + + +static void f_call (lua_State *L, void *ud) { + struct CallS *c = cast(struct CallS *, ud); + luaD_callnoyield(L, c->func, c->nresults); +} + + + +LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k) { + struct CallS c; + int status; + ptrdiff_t func; + lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); + api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); + if (errfunc == 0) + func = 0; + else { + StkId o = index2stack(L, errfunc); + api_check(L, ttisfunction(s2v(o)), "error handler must be a function"); + func = savestack(L, o); + } + c.func = L->top - (nargs+1); /* function to be called */ + if (k == NULL || !yieldable(L)) { /* no continuation or no yieldable? */ + c.nresults = nresults; /* do a 'conventional' protected call */ + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + } + else { /* prepare continuation (call is already protected by 'resume') */ + CallInfo *ci = L->ci; + ci->u.c.k = k; /* save continuation */ + ci->u.c.ctx = ctx; /* save context */ + /* save information for error recovery */ + ci->u2.funcidx = cast_int(savestack(L, c.func)); + ci->u.c.old_errfunc = L->errfunc; + L->errfunc = func; + setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ + ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ + luaD_call(L, c.func, nresults); /* do the call */ + ci->callstatus &= ~CIST_YPCALL; + L->errfunc = ci->u.c.old_errfunc; + status = LUA_OK; /* if it is here, there were no errors */ + } + adjustresults(L, nresults); + lua_unlock(L); + return status; +} + + +LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, + const char *chunkname, const char *mode) { + ZIO z; + int status; + lua_lock(L); + if (!chunkname) chunkname = "?"; + luaZ_init(L, &z, reader, data); + status = luaD_protectedparser(L, &z, chunkname, mode); + if (status == LUA_OK) { /* no errors? */ + LClosure *f = clLvalue(s2v(L->top - 1)); /* get newly created function */ + if (f->nupvalues >= 1) { /* does it have an upvalue? */ + /* get global table from registry */ + const TValue *gt = getGtable(L); + /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ + setobj(L, f->upvals[0]->v, gt); + luaC_barrier(L, f->upvals[0], gt); + } + } + lua_unlock(L); + return status; +} + + +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { + int status; + TValue *o; + lua_lock(L); + api_checknelems(L, 1); + o = s2v(L->top - 1); + if (isLfunction(o)) + status = luaU_dump(L, getproto(o), writer, data, strip); + else + status = 1; + lua_unlock(L); + return status; +} + + +LUA_API int lua_status (lua_State *L) { + return L->status; +} + + +/* +** Garbage-collection function +*/ +LUA_API int lua_gc (lua_State *L, int what, ...) { + va_list argp; + int res = 0; + global_State *g; + lua_lock(L); + g = G(L); + va_start(argp, what); + switch (what) { + case LUA_GCSTOP: { + g->gcrunning = 0; + break; + } + case LUA_GCRESTART: { + luaE_setdebt(g, 0); + g->gcrunning = 1; + break; + } + case LUA_GCCOLLECT: { + luaC_fullgc(L, 0); + break; + } + case LUA_GCCOUNT: { + /* GC values are expressed in Kbytes: #bytes/2^10 */ + res = cast_int(gettotalbytes(g) >> 10); + break; + } + case LUA_GCCOUNTB: { + res = cast_int(gettotalbytes(g) & 0x3ff); + break; + } + case LUA_GCSTEP: { + int data = va_arg(argp, int); + l_mem debt = 1; /* =1 to signal that it did an actual step */ + lu_byte oldrunning = g->gcrunning; + g->gcrunning = 1; /* allow GC to run */ + if (data == 0) { + luaE_setdebt(g, 0); /* do a basic step */ + luaC_step(L); + } + else { /* add 'data' to total debt */ + debt = cast(l_mem, data) * 1024 + g->GCdebt; + luaE_setdebt(g, debt); + luaC_checkGC(L); + } + g->gcrunning = oldrunning; /* restore previous state */ + if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ + res = 1; /* signal it */ + break; + } + case LUA_GCSETPAUSE: { + int data = va_arg(argp, int); + res = getgcparam(g->gcpause); + setgcparam(g->gcpause, data); + break; + } + case LUA_GCSETSTEPMUL: { + int data = va_arg(argp, int); + res = getgcparam(g->gcstepmul); + setgcparam(g->gcstepmul, data); + break; + } + case LUA_GCISRUNNING: { + res = g->gcrunning; + break; + } + case LUA_GCGEN: { + int minormul = va_arg(argp, int); + int majormul = va_arg(argp, int); + res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; + if (minormul != 0) + g->genminormul = minormul; + if (majormul != 0) + setgcparam(g->genmajormul, majormul); + luaC_changemode(L, KGC_GEN); + break; + } + case LUA_GCINC: { + int pause = va_arg(argp, int); + int stepmul = va_arg(argp, int); + int stepsize = va_arg(argp, int); + res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; + if (pause != 0) + setgcparam(g->gcpause, pause); + if (stepmul != 0) + setgcparam(g->gcstepmul, stepmul); + if (stepsize != 0) + g->gcstepsize = stepsize; + luaC_changemode(L, KGC_INC); + break; + } + default: res = -1; /* invalid option */ + } + va_end(argp); + lua_unlock(L); + return res; +} + + + +/* +** miscellaneous functions +*/ + + +LUA_API int lua_error (lua_State *L) { + TValue *errobj; + lua_lock(L); + errobj = s2v(L->top - 1); + api_checknelems(L, 1); + /* error object is the memory error message? */ + if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg)) + luaM_error(L); /* raise a memory error */ + else + luaG_errormsg(L); /* raise a regular error */ + /* code unreachable; will unlock when control actually leaves the kernel */ + return 0; /* to avoid warnings */ +} + + +LUA_API int lua_next (lua_State *L, int idx) { + Table *t; + int more; + lua_lock(L); + api_checknelems(L, 1); + t = gettable(L, idx); + more = luaH_next(L, t, L->top - 1); + if (more) { + api_incr_top(L); + } + else /* no more elements */ + L->top -= 1; /* remove key */ + lua_unlock(L); + return more; +} + + +LUA_API void lua_toclose (lua_State *L, int idx) { + int nresults; + StkId o; + lua_lock(L); + o = index2stack(L, idx); + nresults = L->ci->nresults; + api_check(L, L->tbclist < o, "given index below or equal a marked one"); + luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */ + if (!hastocloseCfunc(nresults)) /* function not marked yet? */ + L->ci->nresults = codeNresults(nresults); /* mark it */ + lua_assert(hastocloseCfunc(L->ci->nresults)); + lua_unlock(L); +} + + +LUA_API void lua_concat (lua_State *L, int n) { + lua_lock(L); + api_checknelems(L, n); + if (n > 0) + luaV_concat(L, n); + else { /* nothing to concatenate */ + setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); /* push empty string */ + api_incr_top(L); + } + luaC_checkGC(L); + lua_unlock(L); +} + + +LUA_API void lua_len (lua_State *L, int idx) { + TValue *t; + lua_lock(L); + t = index2value(L, idx); + luaV_objlen(L, L->top, t); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { + lua_Alloc f; + lua_lock(L); + if (ud) *ud = G(L)->ud; + f = G(L)->frealloc; + lua_unlock(L); + return f; +} + + +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { + lua_lock(L); + G(L)->ud = ud; + G(L)->frealloc = f; + lua_unlock(L); +} + + +void lua_setwarnf (lua_State *L, lua_WarnFunction f, void *ud) { + lua_lock(L); + G(L)->ud_warn = ud; + G(L)->warnf = f; + lua_unlock(L); +} + + +void lua_warning (lua_State *L, const char *msg, int tocont) { + lua_lock(L); + luaE_warning(L, msg, tocont); + lua_unlock(L); +} + + + +LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) { + Udata *u; + lua_lock(L); + api_check(L, 0 <= nuvalue && nuvalue < USHRT_MAX, "invalid value"); + u = luaS_newudata(L, size, nuvalue); + setuvalue(L, s2v(L->top), u); + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return getudatamem(u); +} + + + +static const char *aux_upvalue (TValue *fi, int n, TValue **val, + GCObject **owner) { + switch (ttypetag(fi)) { + case LUA_VCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + if (!(cast_uint(n) - 1u < cast_uint(f->nupvalues))) + return NULL; /* 'n' not in [1, f->nupvalues] */ + *val = &f->upvalue[n-1]; + if (owner) *owner = obj2gco(f); + return ""; + } + case LUA_VLCL: { /* Lua closure */ + LClosure *f = clLvalue(fi); + TString *name; + Proto *p = f->p; + if (!(cast_uint(n) - 1u < cast_uint(p->sizeupvalues))) + return NULL; /* 'n' not in [1, p->sizeupvalues] */ + *val = f->upvals[n-1]->v; + if (owner) *owner = obj2gco(f->upvals[n - 1]); + name = p->upvalues[n-1].name; + return (name == NULL) ? "(no name)" : getstr(name); + } + default: return NULL; /* not a closure */ + } +} + + +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val = NULL; /* to avoid warnings */ + lua_lock(L); + name = aux_upvalue(index2value(L, funcindex), n, &val, NULL); + if (name) { + setobj2s(L, L->top, val); + api_incr_top(L); + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val = NULL; /* to avoid warnings */ + GCObject *owner = NULL; /* to avoid warnings */ + TValue *fi; + lua_lock(L); + fi = index2value(L, funcindex); + api_checknelems(L, 1); + name = aux_upvalue(fi, n, &val, &owner); + if (name) { + L->top--; + setobj(L, val, s2v(L->top)); + luaC_barrier(L, owner, val); + } + lua_unlock(L); + return name; +} + + +static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { + static const UpVal *const nullup = NULL; + LClosure *f; + TValue *fi = index2value(L, fidx); + api_check(L, ttisLclosure(fi), "Lua function expected"); + f = clLvalue(fi); + if (pf) *pf = f; + if (1 <= n && n <= f->p->sizeupvalues) + return &f->upvals[n - 1]; /* get its upvalue pointer */ + else + return (UpVal**)&nullup; +} + + +LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { + TValue *fi = index2value(L, fidx); + switch (ttypetag(fi)) { + case LUA_VLCL: { /* lua closure */ + return *getupvalref(L, fidx, n, NULL); + } + case LUA_VCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + if (1 <= n && n <= f->nupvalues) + return &f->upvalue[n - 1]; + /* else */ + } /* FALLTHROUGH */ + case LUA_VLCF: + return NULL; /* light C functions have no upvalues */ + default: { + api_check(L, 0, "function expected"); + return NULL; + } + } +} + + +LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, + int fidx2, int n2) { + LClosure *f1; + UpVal **up1 = getupvalref(L, fidx1, n1, &f1); + UpVal **up2 = getupvalref(L, fidx2, n2, NULL); + api_check(L, *up1 != NULL && *up2 != NULL, "invalid upvalue index"); + *up1 = *up2; + luaC_objbarrier(L, f1, *up1); +} + + diff --git a/lua/lapi.h b/lua/lapi.h new file mode 100644 index 0000000..9e99cc4 --- /dev/null +++ b/lua/lapi.h @@ -0,0 +1,49 @@ +/* +** $Id: lapi.h $ +** Auxiliary functions from Lua API +** See Copyright Notice in lua.h +*/ + +#ifndef lapi_h +#define lapi_h + + +#include "llimits.h" +#include "lstate.h" + + +/* Increments 'L->top', checking for stack overflows */ +#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ + "stack overflow");} + + +/* +** If a call returns too many multiple returns, the callee may not have +** stack space to accommodate all results. In this case, this macro +** increases its stack space ('L->ci->top'). +*/ +#define adjustresults(L,nres) \ + { if ((nres) <= LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } + + +/* Ensure the stack has at least 'n' elements */ +#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ + "not enough elements in the stack") + + +/* +** To reduce the overhead of returning from C functions, the presence of +** to-be-closed variables in these functions is coded in the CallInfo's +** field 'nresults', in a way that functions with no to-be-closed variables +** with zero, one, or "all" wanted results have no overhead. Functions +** with other number of wanted results, as well as functions with +** variables to be closed, have an extra check. +*/ + +#define hastocloseCfunc(n) ((n) < LUA_MULTRET) + +/* Map [-1, inf) (range of 'nresults') into (-inf, -2] */ +#define codeNresults(n) (-(n) - 3) +#define decodeNresults(n) (-(n) - 3) + +#endif diff --git a/lua/lauxlib.c b/lua/lauxlib.c new file mode 100644 index 0000000..94835ef --- /dev/null +++ b/lua/lauxlib.c @@ -0,0 +1,1105 @@ +/* +** $Id: lauxlib.c $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + +#define lauxlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include +#include + + +/* +** This file uses only the official API of Lua. +** Any function declared here could be written as an application function. +*/ + +#include "lua.h" + +#include "lauxlib.h" + + +#if !defined(MAX_SIZET) +/* maximum value for size_t */ +#define MAX_SIZET ((size_t)(~(size_t)0)) +#endif + + +/* +** {====================================================== +** Traceback +** ======================================================= +*/ + + +#define LEVELS1 10 /* size of the first part of the stack */ +#define LEVELS2 11 /* size of the second part of the stack */ + + + +/* +** Search for 'objidx' in table at index -1. ('objidx' must be an +** absolute index.) Return 1 + string at top if it found a good name. +*/ +static int findfield (lua_State *L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) { /* try recursively */ + /* stack: lib_name, lib_table, field_name (top) */ + lua_pushliteral(L, "."); /* place '.' between the two names */ + lua_replace(L, -3); /* (in the slot occupied by table) */ + lua_concat(L, 3); /* lib_name.field_name */ + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + + +/* +** Search for a name for a function in all loaded modules +*/ +static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + if (findfield(L, top + 1, 2)) { + const char *name = lua_tostring(L, -1); + if (strncmp(name, LUA_GNAME ".", 3) == 0) { /* name start with '_G.'? */ + lua_pushstring(L, name + 3); /* push name without prefix */ + lua_remove(L, -2); /* remove original name */ + } + lua_copy(L, -1, top + 1); /* copy name to proper place */ + lua_settop(L, top + 1); /* remove table "loaded" and name copy */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + + +static void pushfuncname (lua_State *L, lua_Debug *ar) { + if (pushglobalfuncname(L, ar)) { /* try first a global name */ + lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else if (*ar->namewhat != '\0') /* is there a name from code? */ + lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */ + else if (*ar->what == 'm') /* main? */ + lua_pushliteral(L, "main chunk"); + else if (*ar->what != 'C') /* for Lua functions, use */ + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); + else /* nothing left... */ + lua_pushliteral(L, "?"); +} + + +static int lastlevel (lua_State *L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } + /* do a binary search */ + while (li < le) { + int m = (li + le)/2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; +} + + +LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, + const char *msg, int level) { + luaL_Buffer b; + lua_Debug ar; + int last = lastlevel(L1); + int limit2show = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; + luaL_buffinit(L, &b); + if (msg) { + luaL_addstring(&b, msg); + luaL_addchar(&b, '\n'); + } + luaL_addstring(&b, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (limit2show-- == 0) { /* too many levels? */ + int n = last - level - LEVELS2 + 1; /* number of levels to skip */ + lua_pushfstring(L, "\n\t...\t(skipping %d levels)", n); + luaL_addvalue(&b); /* add warning about skip */ + level += n; /* and skip to last levels */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + if (ar.currentline <= 0) + lua_pushfstring(L, "\n\t%s: in ", ar.short_src); + else + lua_pushfstring(L, "\n\t%s:%d: in ", ar.short_src, ar.currentline); + luaL_addvalue(&b); + pushfuncname(L, &ar); + luaL_addvalue(&b); + if (ar.istailcall) + luaL_addstring(&b, "\n\t(...tail calls...)"); + } + } + luaL_pushresult(&b); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Error-report functions +** ======================================================= +*/ + +LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { + lua_Debug ar; + if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ + return luaL_error(L, "bad argument #%d (%s)", arg, extramsg); + lua_getinfo(L, "n", &ar); + if (strcmp(ar.namewhat, "method") == 0) { + arg--; /* do not count 'self' */ + if (arg == 0) /* error is in the self argument itself? */ + return luaL_error(L, "calling '%s' on bad self (%s)", + ar.name, extramsg); + } + if (ar.name == NULL) + ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; + return luaL_error(L, "bad argument #%d to '%s' (%s)", + arg, ar.name, extramsg); +} + + +LUALIB_API int luaL_typeerror (lua_State *L, int arg, const char *tname) { + const char *msg; + const char *typearg; /* name for the type of the actual argument */ + if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING) + typearg = lua_tostring(L, -1); /* use the given type name */ + else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA) + typearg = "light userdata"; /* special name for messages */ + else + typearg = luaL_typename(L, arg); /* standard name */ + msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg); + return luaL_argerror(L, arg, msg); +} + + +static void tag_error (lua_State *L, int arg, int tag) { + luaL_typeerror(L, arg, lua_typename(L, tag)); +} + + +/* +** The use of 'lua_pushfstring' ensures this function does not +** need reserved stack space when called. +*/ +LUALIB_API void luaL_where (lua_State *L, int level) { + lua_Debug ar; + if (lua_getstack(L, level, &ar)) { /* check function at level */ + lua_getinfo(L, "Sl", &ar); /* get info about it */ + if (ar.currentline > 0) { /* is there info? */ + lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); + return; + } + } + lua_pushfstring(L, ""); /* else, no information available... */ +} + + +/* +** Again, the use of 'lua_pushvfstring' ensures this function does +** not need reserved stack space when called. (At worst, it generates +** an error with "stack overflow" instead of the given message.) +*/ +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); +} + + +LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { + int en = errno; /* calls to Lua API may change this value */ + if (stat) { + lua_pushboolean(L, 1); + return 1; + } + else { + luaL_pushfail(L); + if (fname) + lua_pushfstring(L, "%s: %s", fname, strerror(en)); + else + lua_pushstring(L, strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +#if !defined(l_inspectstat) /* { */ + +#if defined(LUA_USE_POSIX) + +#include + +/* +** use appropriate macros to interpret 'pclose' return status +*/ +#define l_inspectstat(stat,what) \ + if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ + else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } + +#else + +#define l_inspectstat(stat,what) /* no op */ + +#endif + +#endif /* } */ + + +LUALIB_API int luaL_execresult (lua_State *L, int stat) { + if (stat != 0 && errno != 0) /* error with an 'errno'? */ + return luaL_fileresult(L, 0, NULL); + else { + const char *what = "exit"; /* type of termination */ + l_inspectstat(stat, what); /* interpret result */ + if (*what == 'e' && stat == 0) /* successful termination? */ + lua_pushboolean(L, 1); + else + luaL_pushfail(L); + lua_pushstring(L, what); + lua_pushinteger(L, stat); + return 3; /* return true/fail,what,code */ + } +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Userdata's metatable manipulation +** ======================================================= +*/ + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */ + return 0; /* leave previous value on top, but return 0 */ + lua_pop(L, 1); + lua_createtable(L, 0, 2); /* create metatable */ + lua_pushstring(L, tname); + lua_setfield(L, -2, "__name"); /* metatable.__name = tname */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ + return 1; +} + + +LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + + +LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { + void *p = lua_touserdata(L, ud); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ + luaL_getmetatable(L, tname); /* get correct metatable */ + if (!lua_rawequal(L, -1, -2)) /* not the same? */ + p = NULL; /* value is a userdata with wrong metatable */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + return NULL; /* value is not a userdata with a metatable */ +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + void *p = luaL_testudata(L, ud, tname); + luaL_argexpected(L, p != NULL, ud, tname); + return p; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Argument check functions +** ======================================================= +*/ + +LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def, + const char *const lst[]) { + const char *name = (def) ? luaL_optstring(L, arg, def) : + luaL_checkstring(L, arg); + int i; + for (i=0; lst[i]; i++) + if (strcmp(lst[i], name) == 0) + return i; + return luaL_argerror(L, arg, + lua_pushfstring(L, "invalid option '%s'", name)); +} + + +/* +** Ensures the stack has at least 'space' extra slots, raising an error +** if it cannot fulfill the request. (The error handling needs a few +** extra slots to format the error message. In case of an error without +** this extra space, Lua will generate the same 'stack overflow' error, +** but without 'msg'.) +*/ +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { + if (l_unlikely(!lua_checkstack(L, space))) { + if (msg) + luaL_error(L, "stack overflow (%s)", msg); + else + luaL_error(L, "stack overflow"); + } +} + + +LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) { + if (l_unlikely(lua_type(L, arg) != t)) + tag_error(L, arg, t); +} + + +LUALIB_API void luaL_checkany (lua_State *L, int arg) { + if (l_unlikely(lua_type(L, arg) == LUA_TNONE)) + luaL_argerror(L, arg, "value expected"); +} + + +LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) { + const char *s = lua_tolstring(L, arg, len); + if (l_unlikely(!s)) tag_error(L, arg, LUA_TSTRING); + return s; +} + + +LUALIB_API const char *luaL_optlstring (lua_State *L, int arg, + const char *def, size_t *len) { + if (lua_isnoneornil(L, arg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_checklstring(L, arg, len); +} + + +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) { + int isnum; + lua_Number d = lua_tonumberx(L, arg, &isnum); + if (l_unlikely(!isnum)) + tag_error(L, arg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) { + return luaL_opt(L, luaL_checknumber, arg, def); +} + + +static void interror (lua_State *L, int arg) { + if (lua_isnumber(L, arg)) + luaL_argerror(L, arg, "number has no integer representation"); + else + tag_error(L, arg, LUA_TNUMBER); +} + + +LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { + int isnum; + lua_Integer d = lua_tointegerx(L, arg, &isnum); + if (l_unlikely(!isnum)) { + interror(L, arg); + } + return d; +} + + +LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, + lua_Integer def) { + return luaL_opt(L, luaL_checkinteger, arg, def); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +/* userdata to box arbitrary data */ +typedef struct UBox { + void *box; + size_t bsize; +} UBox; + + +static void *resizebox (lua_State *L, int idx, size_t newsize) { + void *ud; + lua_Alloc allocf = lua_getallocf(L, &ud); + UBox *box = (UBox *)lua_touserdata(L, idx); + void *temp = allocf(ud, box->box, box->bsize, newsize); + if (l_unlikely(temp == NULL && newsize > 0)) { /* allocation error? */ + lua_pushliteral(L, "not enough memory"); + lua_error(L); /* raise a memory error */ + } + box->box = temp; + box->bsize = newsize; + return temp; +} + + +static int boxgc (lua_State *L) { + resizebox(L, 1, 0); + return 0; +} + + +static const luaL_Reg boxmt[] = { /* box metamethods */ + {"__gc", boxgc}, + {"__close", boxgc}, + {NULL, NULL} +}; + + +static void newbox (lua_State *L) { + UBox *box = (UBox *)lua_newuserdatauv(L, sizeof(UBox), 0); + box->box = NULL; + box->bsize = 0; + if (luaL_newmetatable(L, "_UBOX*")) /* creating metatable? */ + luaL_setfuncs(L, boxmt, 0); /* set its metamethods */ + lua_setmetatable(L, -2); +} + + +/* +** check whether buffer is using a userdata on the stack as a temporary +** buffer +*/ +#define buffonstack(B) ((B)->b != (B)->init.b) + + +/* +** Whenever buffer is accessed, slot 'idx' must either be a box (which +** cannot be NULL) or it is a placeholder for the buffer. +*/ +#define checkbufferlevel(B,idx) \ + lua_assert(buffonstack(B) ? lua_touserdata(B->L, idx) != NULL \ + : lua_touserdata(B->L, idx) == (void*)B) + + +/* +** Compute new size for buffer 'B', enough to accommodate extra 'sz' +** bytes. +*/ +static size_t newbuffsize (luaL_Buffer *B, size_t sz) { + size_t newsize = B->size * 2; /* double buffer size */ + if (l_unlikely(MAX_SIZET - sz < B->n)) /* overflow in (B->n + sz)? */ + return luaL_error(B->L, "buffer too large"); + if (newsize < B->n + sz) /* double is not big enough? */ + newsize = B->n + sz; + return newsize; +} + + +/* +** Returns a pointer to a free area with at least 'sz' bytes in buffer +** 'B'. 'boxidx' is the relative position in the stack where is the +** buffer's box or its placeholder. +*/ +static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) { + checkbufferlevel(B, boxidx); + if (B->size - B->n >= sz) /* enough space? */ + return B->b + B->n; + else { + lua_State *L = B->L; + char *newbuff; + size_t newsize = newbuffsize(B, sz); + /* create larger buffer */ + if (buffonstack(B)) /* buffer already has a box? */ + newbuff = (char *)resizebox(L, boxidx, newsize); /* resize it */ + else { /* no box yet */ + lua_remove(L, boxidx); /* remove placeholder */ + newbox(L); /* create a new box */ + lua_insert(L, boxidx); /* move box to its intended position */ + lua_toclose(L, boxidx); + newbuff = (char *)resizebox(L, boxidx, newsize); + memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ + } + B->b = newbuff; + B->size = newsize; + return newbuff + B->n; + } +} + +/* +** returns a pointer to a free area with at least 'sz' bytes +*/ +LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { + return prepbuffsize(B, sz, -1); +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */ + char *b = prepbuffsize(B, l, -1); + memcpy(b, s, l * sizeof(char)); + luaL_addsize(B, l); + } +} + + +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { + luaL_addlstring(B, s, strlen(s)); +} + + +LUALIB_API void luaL_pushresult (luaL_Buffer *B) { + lua_State *L = B->L; + checkbufferlevel(B, -1); + lua_pushlstring(L, B->b, B->n); + if (buffonstack(B)) + lua_closeslot(L, -2); /* close the box */ + lua_remove(L, -2); /* remove box or placeholder from the stack */ +} + + +LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { + luaL_addsize(B, sz); + luaL_pushresult(B); +} + + +/* +** 'luaL_addvalue' is the only function in the Buffer system where the +** box (if existent) is not on the top of the stack. So, instead of +** calling 'luaL_addlstring', it replicates the code using -2 as the +** last argument to 'prepbuffsize', signaling that the box is (or will +** be) bellow the string being added to the buffer. (Box creation can +** trigger an emergency GC, so we should not remove the string from the +** stack before we have the space guaranteed.) +*/ +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t len; + const char *s = lua_tolstring(L, -1, &len); + char *b = prepbuffsize(B, len, -2); + memcpy(b, s, len * sizeof(char)); + luaL_addsize(B, len); + lua_pop(L, 1); /* pop string */ +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->b = B->init.b; + B->n = 0; + B->size = LUAL_BUFFERSIZE; + lua_pushlightuserdata(L, (void*)B); /* push placeholder */ +} + + +LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { + luaL_buffinit(L, B); + return prepbuffsize(B, sz, -1); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Reference system +** ======================================================= +*/ + +/* index of free-list header (after the predefined values) */ +#define freelist (LUA_RIDX_LAST + 1) + +/* +** The previously freed references form a linked list: +** t[freelist] is the index of a first free index, or zero if list is +** empty; t[t[freelist]] is the index of the second element; etc. +*/ +LUALIB_API int luaL_ref (lua_State *L, int t) { + int ref; + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* remove from stack */ + return LUA_REFNIL; /* 'nil' has a unique fixed reference */ + } + t = lua_absindex(L, t); + if (lua_rawgeti(L, t, freelist) == LUA_TNIL) { /* first access? */ + ref = 0; /* list is empty */ + lua_pushinteger(L, 0); /* initialize as an empty list */ + lua_rawseti(L, t, freelist); /* ref = t[freelist] = 0 */ + } + else { /* already initialized */ + lua_assert(lua_isinteger(L, -1)); + ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ + } + lua_pop(L, 1); /* remove element from stack */ + if (ref != 0) { /* any free element? */ + lua_rawgeti(L, t, ref); /* remove it from list */ + lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ + } + else /* no free elements */ + ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ + lua_rawseti(L, t, ref); + return ref; +} + + +LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { + if (ref >= 0) { + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); + lua_assert(lua_isinteger(L, -1)); + lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ + lua_pushinteger(L, ref); + lua_rawseti(L, t, freelist); /* t[freelist] = ref */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + int n; /* number of pre-read characters */ + FILE *f; /* file being read */ + char buff[BUFSIZ]; /* area for reading file */ +} LoadF; + + +static const char *getF (lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; /* not used */ + if (lf->n > 0) { /* are there pre-read characters to be read? */ + *size = lf->n; /* return them (chars already in buffer) */ + lf->n = 0; /* no more pre-read characters */ + } + else { /* read a block from file */ + /* 'fread' can return > 0 *and* set the EOF flag. If next call to + 'getF' called 'fread', it might still wait for user input. + The next check avoids this problem. */ + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ + } + return lf->buff; +} + + +static int errfile (lua_State *L, const char *what, int fnameindex) { + const char *serr = strerror(errno); + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + + +static int skipBOM (LoadF *lf) { + const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ + int c; + lf->n = 0; + do { + c = getc(lf->f); + if (c == EOF || c != *(const unsigned char *)p++) return c; + lf->buff[lf->n++] = c; /* to be read by the parser */ + } while (*p != '\0'); + lf->n = 0; /* prefix matched; discard it */ + return getc(lf->f); /* return next character */ +} + + +/* +** reads the first character of file 'f' and skips an optional BOM mark +** in its beginning plus its first line if it starts with '#'. Returns +** true if it skipped the first line. In any case, '*cp' has the +** first "valid" character of the file (after the optional BOM and +** a first-line comment). +*/ +static int skipcomment (LoadF *lf, int *cp) { + int c = *cp = skipBOM(lf); + if (c == '#') { /* first line is a comment (Unix exec. file)? */ + do { /* skip first line */ + c = getc(lf->f); + } while (c != EOF && c != '\n'); + *cp = getc(lf->f); /* skip end-of-line, if present */ + return 1; /* there was a comment */ + } + else return 0; /* no comment */ +} + + +LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, + const char *mode) { + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); + lf.f = fopen(filename, "r"); + if (lf.f == NULL) return errfile(L, "open", fnameindex); + } + if (skipcomment(&lf, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ + if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + skipcomment(&lf, &c); /* re-read initial portion */ + } + if (c != EOF) + lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ + status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); + readstatus = ferror(lf.f); + if (filename) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ + return errfile(L, "read", fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + + +typedef struct LoadS { + const char *s; + size_t size; +} LoadS; + + +static const char *getS (lua_State *L, void *ud, size_t *size) { + LoadS *ls = (LoadS *)ud; + (void)L; /* not used */ + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, + const char *name, const char *mode) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name, mode); +} + + +LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { + return luaL_loadbuffer(L, s, strlen(s), s); +} + +/* }====================================================== */ + + + +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return LUA_TNIL; + else { + int tt; + lua_pushstring(L, event); + tt = lua_rawget(L, -2); + if (tt == LUA_TNIL) /* is metafield nil? */ + lua_pop(L, 2); /* remove metatable and metafield */ + else + lua_remove(L, -2); /* remove only metatable */ + return tt; /* return metafield type */ + } +} + + +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + obj = lua_absindex(L, obj); + if (luaL_getmetafield(L, obj, event) == LUA_TNIL) /* no metafield? */ + return 0; + lua_pushvalue(L, obj); + lua_call(L, 1, 1); + return 1; +} + + +LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) { + lua_Integer l; + int isnum; + lua_len(L, idx); + l = lua_tointegerx(L, -1, &isnum); + if (l_unlikely(!isnum)) + luaL_error(L, "object length is not an integer"); + lua_pop(L, 1); /* remove object */ + return l; +} + + +LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { + if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */ + if (!lua_isstring(L, -1)) + luaL_error(L, "'__tostring' must return a string"); + } + else { + switch (lua_type(L, idx)) { + case LUA_TNUMBER: { + if (lua_isinteger(L, idx)) + lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx)); + else + lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx)); + break; + } + case LUA_TSTRING: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: { + int tt = luaL_getmetafield(L, idx, "__name"); /* try name */ + const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : + luaL_typename(L, idx); + lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx)); + if (tt != LUA_TNIL) + lua_remove(L, -2); /* remove '__name' */ + break; + } + } + } + return lua_tolstring(L, -1, len); +} + + +/* +** set functions from list 'l' into table at top - 'nup'; each +** function gets the 'nup' elements at the top as upvalues. +** Returns with only the table at the stack. +*/ +LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkstack(L, nup, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + if (l->func == NULL) /* place holder? */ + lua_pushboolean(L, 0); + else { + int i; + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -nup); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + } + lua_setfield(L, -(nup + 2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + + +/* +** ensure that stack[idx][fname] has a table and push that table +** into the stack +*/ +LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { + if (lua_getfield(L, idx, fname) == LUA_TTABLE) + return 1; /* table already there */ + else { + lua_pop(L, 1); /* remove previous result */ + idx = lua_absindex(L, idx); + lua_newtable(L); + lua_pushvalue(L, -1); /* copy to be left at top */ + lua_setfield(L, idx, fname); /* assign new table to field */ + return 0; /* false, because did not find table there */ + } +} + + +/* +** Stripped-down 'require': After checking "loaded" table, calls 'openf' +** to open a module, registers the result in 'package.loaded' table and, +** if 'glb' is true, also registers the result in the global table. +** Leaves resulting module on the top. +*/ +LUALIB_API void luaL_requiref (lua_State *L, const char *modname, + lua_CFunction openf, int glb) { + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_getfield(L, -1, modname); /* LOADED[modname] */ + if (!lua_toboolean(L, -1)) { /* package not already loaded? */ + lua_pop(L, 1); /* remove field */ + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); /* argument to open function */ + lua_call(L, 1, 1); /* call 'openf' to open module */ + lua_pushvalue(L, -1); /* make copy of module (call result) */ + lua_setfield(L, -3, modname); /* LOADED[modname] = module */ + } + lua_remove(L, -2); /* remove LOADED table */ + if (glb) { + lua_pushvalue(L, -1); /* copy of module */ + lua_setglobal(L, modname); /* _G[modname] = module */ + } +} + + +LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s, + const char *p, const char *r) { + const char *wild; + size_t l = strlen(p); + while ((wild = strstr(s, p)) != NULL) { + luaL_addlstring(b, s, wild - s); /* push prefix */ + luaL_addstring(b, r); /* push replacement in place of pattern */ + s = wild + l; /* continue after 'p' */ + } + luaL_addstring(b, s); /* push last suffix */ +} + + +LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, + const char *p, const char *r) { + luaL_Buffer b; + luaL_buffinit(L, &b); + luaL_addgsub(&b, s, p, r); + luaL_pushresult(&b); + return lua_tostring(L, -1); +} + + +static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { + (void)ud; (void)osize; /* not used */ + if (nsize == 0) { + free(ptr); + return NULL; + } + else + return realloc(ptr, nsize); +} + + +static int panic (lua_State *L) { + const char *msg = lua_tostring(L, -1); + if (msg == NULL) msg = "error object is not a string"; + lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", + msg); + return 0; /* return to Lua to abort */ +} + + +/* +** Warning functions: +** warnfoff: warning system is off +** warnfon: ready to start a new message +** warnfcont: previous message is to be continued +*/ +static void warnfoff (void *ud, const char *message, int tocont); +static void warnfon (void *ud, const char *message, int tocont); +static void warnfcont (void *ud, const char *message, int tocont); + + +/* +** Check whether message is a control message. If so, execute the +** control or ignore it if unknown. +*/ +static int checkcontrol (lua_State *L, const char *message, int tocont) { + if (tocont || *(message++) != '@') /* not a control message? */ + return 0; + else { + if (strcmp(message, "off") == 0) + lua_setwarnf(L, warnfoff, L); /* turn warnings off */ + else if (strcmp(message, "on") == 0) + lua_setwarnf(L, warnfon, L); /* turn warnings on */ + return 1; /* it was a control message */ + } +} + + +static void warnfoff (void *ud, const char *message, int tocont) { + checkcontrol((lua_State *)ud, message, tocont); +} + + +/* +** Writes the message and handle 'tocont', finishing the message +** if needed and setting the next warn function. +*/ +static void warnfcont (void *ud, const char *message, int tocont) { + lua_State *L = (lua_State *)ud; + lua_writestringerror("%s", message); /* write message */ + if (tocont) /* not the last part? */ + lua_setwarnf(L, warnfcont, L); /* to be continued */ + else { /* last part */ + lua_writestringerror("%s", "\n"); /* finish message with end-of-line */ + lua_setwarnf(L, warnfon, L); /* next call is a new message */ + } +} + + +static void warnfon (void *ud, const char *message, int tocont) { + if (checkcontrol((lua_State *)ud, message, tocont)) /* control message? */ + return; /* nothing else to be done */ + lua_writestringerror("%s", "Lua warning: "); /* start a new warning */ + warnfcont(ud, message, tocont); /* finish processing */ +} + + +LUALIB_API lua_State *luaL_newstate (void) { + lua_State *L = lua_newstate(l_alloc, NULL); + if (l_likely(L)) { + lua_atpanic(L, &panic); + lua_setwarnf(L, warnfoff, L); /* default is warnings off */ + } + return L; +} + + +LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { + lua_Number v = lua_version(L); + if (sz != LUAL_NUMSIZES) /* check numeric types */ + luaL_error(L, "core and library have incompatible numeric types"); + else if (v != ver) + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", + (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)v); +} + diff --git a/lua/lauxlib.h b/lua/lauxlib.h new file mode 100644 index 0000000..72f70e7 --- /dev/null +++ b/lua/lauxlib.h @@ -0,0 +1,293 @@ +/* +** $Id: lauxlib.h $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "luaconf.h" +#include "lua.h" + + +/* global table */ +#define LUA_GNAME "_G" + + +typedef struct luaL_Buffer luaL_Buffer; + + +/* extra error code for 'luaL_loadfilex' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +/* key, in the registry, for table of loaded modules */ +#define LUA_LOADED_TABLE "_LOADED" + + +/* key, in the registry, for table of preloaded loaders */ +#define LUA_PRELOAD_TABLE "_PRELOAD" + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + +#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) + +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); +#define luaL_checkversion(L) \ + luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) + +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); +LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); +LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int arg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); +LUALIB_API int (luaL_execresult) (lua_State *L, int stat); + + +/* predefined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + +LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); + +LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s, + const char *p, const char *r); +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, + const char *p, const char *r); + +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); + +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); + +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); + +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) \ + (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#define luaL_argcheck(L, cond,arg,extramsg) \ + ((void)(luai_likely(cond) || luaL_argerror(L, (arg), (extramsg)))) + +#define luaL_argexpected(L,cond,arg,tname) \ + ((void)(luai_likely(cond) || luaL_typeerror(L, (arg), (tname)))) + +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + +/* push the value used to represent failure/error */ +#define luaL_pushfail(L) lua_pushnil(L) + + +/* +** Internal assertions for in-house debugging +*/ +#if !defined(lua_assert) + +#if defined LUAI_ASSERT + #include + #define lua_assert(c) assert(c) +#else + #define lua_assert(c) ((void)0) +#endif + +#endif + + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +struct luaL_Buffer { + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ + lua_State *L; + union { + LUAI_MAXALIGN; /* ensure maximum alignment for buffer */ + char b[LUAL_BUFFERSIZE]; /* initial buffer */ + } init; +}; + + +#define luaL_bufflen(bf) ((bf)->n) +#define luaL_buffaddr(bf) ((bf)->b) + + +#define luaL_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) + +#define luaL_addsize(B,s) ((B)->n += (s)) + +#define luaL_buffsub(B,s) ((B)->n -= (s)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); +LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); + +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +/* }====================================================== */ + + + +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + +/* +** {================================================================== +** "Abstraction Layer" for basic report of messages and errors +** =================================================================== +*/ + +/* print a string */ +#if !defined(lua_writestring) +#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#endif + +/* print a newline and flush the output */ +#if !defined(lua_writeline) +#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) +#endif + +/* print an error message */ +#if !defined(lua_writestringerror) +#define lua_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) +#endif + +/* }================================================================== */ + + +/* +** {============================================================ +** Compatibility with deprecated conversions +** ============================================================= +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) +#define luaL_optunsigned(L,a,d) \ + ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) + +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) + +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#endif +/* }============================================================ */ + + + +#endif + + diff --git a/lua/lbaselib.c b/lua/lbaselib.c new file mode 100644 index 0000000..83ad306 --- /dev/null +++ b/lua/lbaselib.c @@ -0,0 +1,528 @@ +/* +** $Id: lbaselib.c $ +** Basic library +** See Copyright Notice in lua.h +*/ + +#define lbaselib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static int luaB_print (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + for (i = 1; i <= n; i++) { /* for each argument */ + size_t l; + const char *s = luaL_tolstring(L, i, &l); /* convert it to string */ + if (i > 1) /* not the first element? */ + lua_writestring("\t", 1); /* add a tab before it */ + lua_writestring(s, l); /* print it */ + lua_pop(L, 1); /* pop result */ + } + lua_writeline(); + return 0; +} + + +/* +** Creates a warning with all given arguments. +** Check first for errors; otherwise an error may interrupt +** the composition of a warning, leaving it unfinished. +*/ +static int luaB_warn (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + luaL_checkstring(L, 1); /* at least one argument */ + for (i = 2; i <= n; i++) + luaL_checkstring(L, i); /* make sure all arguments are strings */ + for (i = 1; i < n; i++) /* compose warning */ + lua_warning(L, lua_tostring(L, i), 1); + lua_warning(L, lua_tostring(L, n), 0); /* close warning */ + return 0; +} + + +#define SPACECHARS " \f\n\r\t\v" + +static const char *b_str2int (const char *s, int base, lua_Integer *pn) { + lua_Unsigned n = 0; + int neg = 0; + s += strspn(s, SPACECHARS); /* skip initial spaces */ + if (*s == '-') { s++; neg = 1; } /* handle sign */ + else if (*s == '+') s++; + if (!isalnum((unsigned char)*s)) /* no digit? */ + return NULL; + do { + int digit = (isdigit((unsigned char)*s)) ? *s - '0' + : (toupper((unsigned char)*s) - 'A') + 10; + if (digit >= base) return NULL; /* invalid numeral */ + n = n * base + digit; + s++; + } while (isalnum((unsigned char)*s)); + s += strspn(s, SPACECHARS); /* skip trailing spaces */ + *pn = (lua_Integer)((neg) ? (0u - n) : n); + return s; +} + + +static int luaB_tonumber (lua_State *L) { + if (lua_isnoneornil(L, 2)) { /* standard conversion? */ + if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */ + lua_settop(L, 1); /* yes; return it */ + return 1; + } + else { + size_t l; + const char *s = lua_tolstring(L, 1, &l); + if (s != NULL && lua_stringtonumber(L, s) == l + 1) + return 1; /* successful conversion to number */ + /* else not a number */ + luaL_checkany(L, 1); /* (but there must be some parameter) */ + } + } + else { + size_t l; + const char *s; + lua_Integer n = 0; /* to avoid warnings */ + lua_Integer base = luaL_checkinteger(L, 2); + luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */ + s = lua_tolstring(L, 1, &l); + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + if (b_str2int(s, (int)base, &n) == s + l) { + lua_pushinteger(L, n); + return 1; + } /* else not a number */ + } /* else not a number */ + luaL_pushfail(L); /* not a number */ + return 1; +} + + +static int luaB_error (lua_State *L) { + int level = (int)luaL_optinteger(L, 2, 1); + lua_settop(L, 1); + if (lua_type(L, 1) == LUA_TSTRING && level > 0) { + luaL_where(L, level); /* add extra information */ + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); +} + + +static int luaB_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); + return 1; /* no metatable */ + } + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ +} + + +static int luaB_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table"); + if (l_unlikely(luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL)) + return luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; +} + + +static int luaB_rawequal (lua_State *L) { + luaL_checkany(L, 1); + luaL_checkany(L, 2); + lua_pushboolean(L, lua_rawequal(L, 1, 2)); + return 1; +} + + +static int luaB_rawlen (lua_State *L) { + int t = lua_type(L, 1); + luaL_argexpected(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, + "table or string"); + lua_pushinteger(L, lua_rawlen(L, 1)); + return 1; +} + + +static int luaB_rawget (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_rawget(L, 1); + return 1; +} + +static int luaB_rawset (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_settop(L, 3); + lua_rawset(L, 1); + return 1; +} + + +static int pushmode (lua_State *L, int oldmode) { + lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental" + : "generational"); + return 1; +} + + +static int luaB_collectgarbage (lua_State *L) { + static const char *const opts[] = {"stop", "restart", "collect", + "count", "step", "setpause", "setstepmul", + "isrunning", "generational", "incremental", NULL}; + static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, + LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; + int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; + switch (o) { + case LUA_GCCOUNT: { + int k = lua_gc(L, o); + int b = lua_gc(L, LUA_GCCOUNTB); + lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024)); + return 1; + } + case LUA_GCSTEP: { + int step = (int)luaL_optinteger(L, 2, 0); + int res = lua_gc(L, o, step); + lua_pushboolean(L, res); + return 1; + } + case LUA_GCSETPAUSE: + case LUA_GCSETSTEPMUL: { + int p = (int)luaL_optinteger(L, 2, 0); + int previous = lua_gc(L, o, p); + lua_pushinteger(L, previous); + return 1; + } + case LUA_GCISRUNNING: { + int res = lua_gc(L, o); + lua_pushboolean(L, res); + return 1; + } + case LUA_GCGEN: { + int minormul = (int)luaL_optinteger(L, 2, 0); + int majormul = (int)luaL_optinteger(L, 3, 0); + return pushmode(L, lua_gc(L, o, minormul, majormul)); + } + case LUA_GCINC: { + int pause = (int)luaL_optinteger(L, 2, 0); + int stepmul = (int)luaL_optinteger(L, 3, 0); + int stepsize = (int)luaL_optinteger(L, 4, 0); + return pushmode(L, lua_gc(L, o, pause, stepmul, stepsize)); + } + default: { + int res = lua_gc(L, o); + lua_pushinteger(L, res); + return 1; + } + } +} + + +static int luaB_type (lua_State *L) { + int t = lua_type(L, 1); + luaL_argcheck(L, t != LUA_TNONE, 1, "value expected"); + lua_pushstring(L, lua_typename(L, t)); + return 1; +} + + +static int luaB_next (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + + +static int luaB_pairs (lua_State *L) { + luaL_checkany(L, 1); + if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */ + lua_pushcfunction(L, luaB_next); /* will return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushnil(L); /* and initial value */ + } + else { + lua_pushvalue(L, 1); /* argument 'self' to metamethod */ + lua_call(L, 1, 3); /* get 3 values from metamethod */ + } + return 3; +} + + +/* +** Traversal function for 'ipairs' +*/ +static int ipairsaux (lua_State *L) { + lua_Integer i = luaL_checkinteger(L, 2) + 1; + lua_pushinteger(L, i); + return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2; +} + + +/* +** 'ipairs' function. Returns 'ipairsaux', given "table", 0. +** (The given "table" may not be a table.) +*/ +static int luaB_ipairs (lua_State *L) { + luaL_checkany(L, 1); + lua_pushcfunction(L, ipairsaux); /* iteration function */ + lua_pushvalue(L, 1); /* state */ + lua_pushinteger(L, 0); /* initial value */ + return 3; +} + + +static int load_aux (lua_State *L, int status, int envidx) { + if (l_likely(status == LUA_OK)) { + if (envidx != 0) { /* 'env' parameter? */ + lua_pushvalue(L, envidx); /* environment for loaded function */ + if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ + lua_pop(L, 1); /* remove 'env' if not used by previous call */ + } + return 1; + } + else { /* error (message is on top of the stack) */ + luaL_pushfail(L); + lua_insert(L, -2); /* put before error message */ + return 2; /* return fail plus error message */ + } +} + + +static int luaB_loadfile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + const char *mode = luaL_optstring(L, 2, NULL); + int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ + int status = luaL_loadfilex(L, fname, mode); + return load_aux(L, status, env); +} + + +/* +** {====================================================== +** Generic Read function +** ======================================================= +*/ + + +/* +** reserved slot, above all arguments, to hold a copy of the returned +** string to avoid it being collected while parsed. 'load' has four +** optional arguments (chunk, source name, mode, and environment). +*/ +#define RESERVEDSLOT 5 + + +/* +** Reader for generic 'load' function: 'lua_load' uses the +** stack for internal stuff, so the reader cannot change the +** stack top. Instead, it keeps its resulting string in a +** reserved slot inside the stack. +*/ +static const char *generic_reader (lua_State *L, void *ud, size_t *size) { + (void)(ud); /* not used */ + luaL_checkstack(L, 2, "too many nested functions"); + lua_pushvalue(L, 1); /* get function */ + lua_call(L, 0, 1); /* call it */ + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* pop result */ + *size = 0; + return NULL; + } + else if (l_unlikely(!lua_isstring(L, -1))) + luaL_error(L, "reader function must return a string"); + lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ + return lua_tolstring(L, RESERVEDSLOT, size); +} + + +static int luaB_load (lua_State *L) { + int status; + size_t l; + const char *s = lua_tolstring(L, 1, &l); + const char *mode = luaL_optstring(L, 3, "bt"); + int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ + if (s != NULL) { /* loading a string? */ + const char *chunkname = luaL_optstring(L, 2, s); + status = luaL_loadbufferx(L, s, l, chunkname, mode); + } + else { /* loading from a reader function */ + const char *chunkname = luaL_optstring(L, 2, "=(load)"); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, RESERVEDSLOT); /* create reserved slot */ + status = lua_load(L, generic_reader, NULL, chunkname, mode); + } + return load_aux(L, status, env); +} + +/* }====================================================== */ + + +static int dofilecont (lua_State *L, int d1, lua_KContext d2) { + (void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */ + return lua_gettop(L) - 1; +} + + +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + lua_settop(L, 1); + if (l_unlikely(luaL_loadfile(L, fname) != LUA_OK)) + return lua_error(L); + lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); + return dofilecont(L, 0, 0); +} + + +static int luaB_assert (lua_State *L) { + if (l_likely(lua_toboolean(L, 1))) /* condition is true? */ + return lua_gettop(L); /* return all arguments */ + else { /* error */ + luaL_checkany(L, 1); /* there must be a condition */ + lua_remove(L, 1); /* remove it */ + lua_pushliteral(L, "assertion failed!"); /* default message */ + lua_settop(L, 1); /* leave only message (default if no other one) */ + return luaB_error(L); /* call 'error' */ + } +} + + +static int luaB_select (lua_State *L) { + int n = lua_gettop(L); + if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { + lua_pushinteger(L, n-1); + return 1; + } + else { + lua_Integer i = luaL_checkinteger(L, 1); + if (i < 0) i = n + i; + else if (i > n) i = n; + luaL_argcheck(L, 1 <= i, 1, "index out of range"); + return n - (int)i; + } +} + + +/* +** Continuation function for 'pcall' and 'xpcall'. Both functions +** already pushed a 'true' before doing the call, so in case of success +** 'finishpcall' only has to return everything in the stack minus +** 'extra' values (where 'extra' is exactly the number of items to be +** ignored). +*/ +static int finishpcall (lua_State *L, int status, lua_KContext extra) { + if (l_unlikely(status != LUA_OK && status != LUA_YIELD)) { /* error? */ + lua_pushboolean(L, 0); /* first result (false) */ + lua_pushvalue(L, -2); /* error message */ + return 2; /* return false, msg */ + } + else + return lua_gettop(L) - (int)extra; /* return all results */ +} + + +static int luaB_pcall (lua_State *L) { + int status; + luaL_checkany(L, 1); + lua_pushboolean(L, 1); /* first result if no errors */ + lua_insert(L, 1); /* put it in place */ + status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall); + return finishpcall(L, status, 0); +} + + +/* +** Do a protected call with error handling. After 'lua_rotate', the +** stack will have ; so, the function passes +** 2 to 'finishpcall' to skip the 2 first values when returning results. +*/ +static int luaB_xpcall (lua_State *L) { + int status; + int n = lua_gettop(L); + luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */ + lua_pushboolean(L, 1); /* first result */ + lua_pushvalue(L, 1); /* function */ + lua_rotate(L, 3, 2); /* move them below function's arguments */ + status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall); + return finishpcall(L, status, 2); +} + + +static int luaB_tostring (lua_State *L) { + luaL_checkany(L, 1); + luaL_tolstring(L, 1, NULL); + return 1; +} + + +static const luaL_Reg base_funcs[] = { + {"assert", luaB_assert}, + {"collectgarbage", luaB_collectgarbage}, + {"dofile", luaB_dofile}, + {"error", luaB_error}, + {"getmetatable", luaB_getmetatable}, + {"ipairs", luaB_ipairs}, + {"loadfile", luaB_loadfile}, + {"load", luaB_load}, + {"next", luaB_next}, + {"pairs", luaB_pairs}, + {"pcall", luaB_pcall}, + {"print", luaB_print}, + {"warn", luaB_warn}, + {"rawequal", luaB_rawequal}, + {"rawlen", luaB_rawlen}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"select", luaB_select}, + {"setmetatable", luaB_setmetatable}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"xpcall", luaB_xpcall}, + /* placeholders */ + {LUA_GNAME, NULL}, + {"_VERSION", NULL}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_base (lua_State *L) { + /* open lib into global table */ + lua_pushglobaltable(L); + luaL_setfuncs(L, base_funcs, 0); + /* set global _G */ + lua_pushvalue(L, -1); + lua_setfield(L, -2, LUA_GNAME); + /* set global _VERSION */ + lua_pushliteral(L, LUA_VERSION); + lua_setfield(L, -2, "_VERSION"); + return 1; +} + diff --git a/lua/lcode.c b/lua/lcode.c new file mode 100644 index 0000000..80d975c --- /dev/null +++ b/lua/lcode.c @@ -0,0 +1,1814 @@ +/* +** $Id: lcode.c $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#define lcode_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstring.h" +#include "ltable.h" +#include "lvm.h" + + +/* Maximum number of registers in a Lua function (must fit in 8 bits) */ +#define MAXREGS 255 + + +#define hasjumps(e) ((e)->t != (e)->f) + + +static int codesJ (FuncState *fs, OpCode o, int sj, int k); + + + +/* semantic error */ +l_noret luaK_semerror (LexState *ls, const char *msg) { + ls->t.token = 0; /* remove "near " from final message */ + luaX_syntaxerror(ls, msg); +} + + +/* +** If expression is a numeric constant, fills 'v' with its value +** and returns 1. Otherwise, returns 0. +*/ +static int tonumeral (const expdesc *e, TValue *v) { + if (hasjumps(e)) + return 0; /* not a numeral */ + switch (e->k) { + case VKINT: + if (v) setivalue(v, e->u.ival); + return 1; + case VKFLT: + if (v) setfltvalue(v, e->u.nval); + return 1; + default: return 0; + } +} + + +/* +** Get the constant value from a constant expression +*/ +static TValue *const2val (FuncState *fs, const expdesc *e) { + lua_assert(e->k == VCONST); + return &fs->ls->dyd->actvar.arr[e->u.info].k; +} + + +/* +** If expression is a constant, fills 'v' with its value +** and returns 1. Otherwise, returns 0. +*/ +int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v) { + if (hasjumps(e)) + return 0; /* not a constant */ + switch (e->k) { + case VFALSE: + setbfvalue(v); + return 1; + case VTRUE: + setbtvalue(v); + return 1; + case VNIL: + setnilvalue(v); + return 1; + case VKSTR: { + setsvalue(fs->ls->L, v, e->u.strval); + return 1; + } + case VCONST: { + setobj(fs->ls->L, v, const2val(fs, e)); + return 1; + } + default: return tonumeral(e, v); + } +} + + +/* +** Return the previous instruction of the current code. If there +** may be a jump target between the current instruction and the +** previous one, return an invalid instruction (to avoid wrong +** optimizations). +*/ +static Instruction *previousinstruction (FuncState *fs) { + static const Instruction invalidinstruction = ~(Instruction)0; + if (fs->pc > fs->lasttarget) + return &fs->f->code[fs->pc - 1]; /* previous instruction */ + else + return cast(Instruction*, &invalidinstruction); +} + + +/* +** Create a OP_LOADNIL instruction, but try to optimize: if the previous +** instruction is also OP_LOADNIL and ranges are compatible, adjust +** range of previous instruction instead of emitting a new one. (For +** instance, 'local a; local b' will generate a single opcode.) +*/ +void luaK_nil (FuncState *fs, int from, int n) { + int l = from + n - 1; /* last register to set nil */ + Instruction *previous = previousinstruction(fs); + if (GET_OPCODE(*previous) == OP_LOADNIL) { /* previous is LOADNIL? */ + int pfrom = GETARG_A(*previous); /* get previous range */ + int pl = pfrom + GETARG_B(*previous); + if ((pfrom <= from && from <= pl + 1) || + (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ + if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ + if (pl > l) l = pl; /* l = max(l, pl) */ + SETARG_A(*previous, from); + SETARG_B(*previous, l - from); + return; + } /* else go through */ + } + luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ +} + + +/* +** Gets the destination address of a jump instruction. Used to traverse +** a list of jumps. +*/ +static int getjump (FuncState *fs, int pc) { + int offset = GETARG_sJ(fs->f->code[pc]); + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc+1)+offset; /* turn offset into absolute position */ +} + + +/* +** Fix jump instruction at position 'pc' to jump to 'dest'. +** (Jump addresses are relative in Lua) +*/ +static void fixjump (FuncState *fs, int pc, int dest) { + Instruction *jmp = &fs->f->code[pc]; + int offset = dest - (pc + 1); + lua_assert(dest != NO_JUMP); + if (!(-OFFSET_sJ <= offset && offset <= MAXARG_sJ - OFFSET_sJ)) + luaX_syntaxerror(fs->ls, "control structure too long"); + lua_assert(GET_OPCODE(*jmp) == OP_JMP); + SETARG_sJ(*jmp, offset); +} + + +/* +** Concatenate jump-list 'l2' into jump-list 'l1' +*/ +void luaK_concat (FuncState *fs, int *l1, int l2) { + if (l2 == NO_JUMP) return; /* nothing to concatenate? */ + else if (*l1 == NO_JUMP) /* no original list? */ + *l1 = l2; /* 'l1' points to 'l2' */ + else { + int list = *l1; + int next; + while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + fixjump(fs, list, l2); /* last element links to 'l2' */ + } +} + + +/* +** Create a jump instruction and return its position, so its destination +** can be fixed later (with 'fixjump'). +*/ +int luaK_jump (FuncState *fs) { + return codesJ(fs, OP_JMP, NO_JUMP, 0); +} + + +/* +** Code a 'return' instruction +*/ +void luaK_ret (FuncState *fs, int first, int nret) { + OpCode op; + switch (nret) { + case 0: op = OP_RETURN0; break; + case 1: op = OP_RETURN1; break; + default: op = OP_RETURN; break; + } + luaK_codeABC(fs, op, first, nret + 1, 0); +} + + +/* +** Code a "conditional jump", that is, a test or comparison opcode +** followed by a jump. Return jump position. +*/ +static int condjump (FuncState *fs, OpCode op, int A, int B, int C, int k) { + luaK_codeABCk(fs, op, A, B, C, k); + return luaK_jump(fs); +} + + +/* +** returns current 'pc' and marks it as a jump target (to avoid wrong +** optimizations with consecutive instructions not in the same basic block). +*/ +int luaK_getlabel (FuncState *fs) { + fs->lasttarget = fs->pc; + return fs->pc; +} + + +/* +** Returns the position of the instruction "controlling" a given +** jump (that is, its condition), or the jump itself if it is +** unconditional. +*/ +static Instruction *getjumpcontrol (FuncState *fs, int pc) { + Instruction *pi = &fs->f->code[pc]; + if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) + return pi-1; + else + return pi; +} + + +/* +** Patch destination register for a TESTSET instruction. +** If instruction in position 'node' is not a TESTSET, return 0 ("fails"). +** Otherwise, if 'reg' is not 'NO_REG', set it as the destination +** register. Otherwise, change instruction to a simple 'TEST' (produces +** no register value) +*/ +static int patchtestreg (FuncState *fs, int node, int reg) { + Instruction *i = getjumpcontrol(fs, node); + if (GET_OPCODE(*i) != OP_TESTSET) + return 0; /* cannot patch other instructions */ + if (reg != NO_REG && reg != GETARG_B(*i)) + SETARG_A(*i, reg); + else { + /* no register to put value or register already has the value; + change instruction to simple test */ + *i = CREATE_ABCk(OP_TEST, GETARG_B(*i), 0, 0, GETARG_k(*i)); + } + return 1; +} + + +/* +** Traverse a list of tests ensuring no one produces a value +*/ +static void removevalues (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) + patchtestreg(fs, list, NO_REG); +} + + +/* +** Traverse a list of tests, patching their destination address and +** registers: tests producing values jump to 'vtarget' (and put their +** values in 'reg'), other tests jump to 'dtarget'. +*/ +static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, + int dtarget) { + while (list != NO_JUMP) { + int next = getjump(fs, list); + if (patchtestreg(fs, list, reg)) + fixjump(fs, list, vtarget); + else + fixjump(fs, list, dtarget); /* jump to default target */ + list = next; + } +} + + +/* +** Path all jumps in 'list' to jump to 'target'. +** (The assert means that we cannot fix a jump to a forward address +** because we only know addresses once code is generated.) +*/ +void luaK_patchlist (FuncState *fs, int list, int target) { + lua_assert(target <= fs->pc); + patchlistaux(fs, list, target, NO_REG, target); +} + + +void luaK_patchtohere (FuncState *fs, int list) { + int hr = luaK_getlabel(fs); /* mark "here" as a jump target */ + luaK_patchlist(fs, list, hr); +} + + +/* limit for difference between lines in relative line info. */ +#define LIMLINEDIFF 0x80 + + +/* +** Save line info for a new instruction. If difference from last line +** does not fit in a byte, of after that many instructions, save a new +** absolute line info; (in that case, the special value 'ABSLINEINFO' +** in 'lineinfo' signals the existence of this absolute information.) +** Otherwise, store the difference from last line in 'lineinfo'. +*/ +static void savelineinfo (FuncState *fs, Proto *f, int line) { + int linedif = line - fs->previousline; + int pc = fs->pc - 1; /* last instruction coded */ + if (abs(linedif) >= LIMLINEDIFF || fs->iwthabs++ >= MAXIWTHABS) { + luaM_growvector(fs->ls->L, f->abslineinfo, fs->nabslineinfo, + f->sizeabslineinfo, AbsLineInfo, MAX_INT, "lines"); + f->abslineinfo[fs->nabslineinfo].pc = pc; + f->abslineinfo[fs->nabslineinfo++].line = line; + linedif = ABSLINEINFO; /* signal that there is absolute information */ + fs->iwthabs = 1; /* restart counter */ + } + luaM_growvector(fs->ls->L, f->lineinfo, pc, f->sizelineinfo, ls_byte, + MAX_INT, "opcodes"); + f->lineinfo[pc] = linedif; + fs->previousline = line; /* last line saved */ +} + + +/* +** Remove line information from the last instruction. +** If line information for that instruction is absolute, set 'iwthabs' +** above its max to force the new (replacing) instruction to have +** absolute line info, too. +*/ +static void removelastlineinfo (FuncState *fs) { + Proto *f = fs->f; + int pc = fs->pc - 1; /* last instruction coded */ + if (f->lineinfo[pc] != ABSLINEINFO) { /* relative line info? */ + fs->previousline -= f->lineinfo[pc]; /* correct last line saved */ + fs->iwthabs--; /* undo previous increment */ + } + else { /* absolute line information */ + lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == pc); + fs->nabslineinfo--; /* remove it */ + fs->iwthabs = MAXIWTHABS + 1; /* force next line info to be absolute */ + } +} + + +/* +** Remove the last instruction created, correcting line information +** accordingly. +*/ +static void removelastinstruction (FuncState *fs) { + removelastlineinfo(fs); + fs->pc--; +} + + +/* +** Emit instruction 'i', checking for array sizes and saving also its +** line information. Return 'i' position. +*/ +int luaK_code (FuncState *fs, Instruction i) { + Proto *f = fs->f; + /* put new instruction in code array */ + luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "opcodes"); + f->code[fs->pc++] = i; + savelineinfo(fs, f, fs->ls->lastline); + return fs->pc - 1; /* index of new instruction */ +} + + +/* +** Format and emit an 'iABC' instruction. (Assertions check consistency +** of parameters versus opcode.) +*/ +int luaK_codeABCk (FuncState *fs, OpCode o, int a, int b, int c, int k) { + lua_assert(getOpMode(o) == iABC); + lua_assert(a <= MAXARG_A && b <= MAXARG_B && + c <= MAXARG_C && (k & ~1) == 0); + return luaK_code(fs, CREATE_ABCk(o, a, b, c, k)); +} + + +/* +** Format and emit an 'iABx' instruction. +*/ +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { + lua_assert(getOpMode(o) == iABx); + lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); + return luaK_code(fs, CREATE_ABx(o, a, bc)); +} + + +/* +** Format and emit an 'iAsBx' instruction. +*/ +int luaK_codeAsBx (FuncState *fs, OpCode o, int a, int bc) { + unsigned int b = bc + OFFSET_sBx; + lua_assert(getOpMode(o) == iAsBx); + lua_assert(a <= MAXARG_A && b <= MAXARG_Bx); + return luaK_code(fs, CREATE_ABx(o, a, b)); +} + + +/* +** Format and emit an 'isJ' instruction. +*/ +static int codesJ (FuncState *fs, OpCode o, int sj, int k) { + unsigned int j = sj + OFFSET_sJ; + lua_assert(getOpMode(o) == isJ); + lua_assert(j <= MAXARG_sJ && (k & ~1) == 0); + return luaK_code(fs, CREATE_sJ(o, j, k)); +} + + +/* +** Emit an "extra argument" instruction (format 'iAx') +*/ +static int codeextraarg (FuncState *fs, int a) { + lua_assert(a <= MAXARG_Ax); + return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); +} + + +/* +** Emit a "load constant" instruction, using either 'OP_LOADK' +** (if constant index 'k' fits in 18 bits) or an 'OP_LOADKX' +** instruction with "extra argument". +*/ +static int luaK_codek (FuncState *fs, int reg, int k) { + if (k <= MAXARG_Bx) + return luaK_codeABx(fs, OP_LOADK, reg, k); + else { + int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); + codeextraarg(fs, k); + return p; + } +} + + +/* +** Check register-stack level, keeping track of its maximum size +** in field 'maxstacksize' +*/ +void luaK_checkstack (FuncState *fs, int n) { + int newstack = fs->freereg + n; + if (newstack > fs->f->maxstacksize) { + if (newstack >= MAXREGS) + luaX_syntaxerror(fs->ls, + "function or expression needs too many registers"); + fs->f->maxstacksize = cast_byte(newstack); + } +} + + +/* +** Reserve 'n' registers in register stack +*/ +void luaK_reserveregs (FuncState *fs, int n) { + luaK_checkstack(fs, n); + fs->freereg += n; +} + + +/* +** Free register 'reg', if it is neither a constant index nor +** a local variable. +) +*/ +static void freereg (FuncState *fs, int reg) { + if (reg >= luaY_nvarstack(fs)) { + fs->freereg--; + lua_assert(reg == fs->freereg); + } +} + + +/* +** Free two registers in proper order +*/ +static void freeregs (FuncState *fs, int r1, int r2) { + if (r1 > r2) { + freereg(fs, r1); + freereg(fs, r2); + } + else { + freereg(fs, r2); + freereg(fs, r1); + } +} + + +/* +** Free register used by expression 'e' (if any) +*/ +static void freeexp (FuncState *fs, expdesc *e) { + if (e->k == VNONRELOC) + freereg(fs, e->u.info); +} + + +/* +** Free registers used by expressions 'e1' and 'e2' (if any) in proper +** order. +*/ +static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { + int r1 = (e1->k == VNONRELOC) ? e1->u.info : -1; + int r2 = (e2->k == VNONRELOC) ? e2->u.info : -1; + freeregs(fs, r1, r2); +} + + +/* +** Add constant 'v' to prototype's list of constants (field 'k'). +** Use scanner's table to cache position of constants in constant list +** and try to reuse constants. Because some values should not be used +** as keys (nil cannot be a key, integer keys can collapse with float +** keys), the caller must provide a useful 'key' for indexing the cache. +** Note that all functions share the same table, so entering or exiting +** a function can make some indices wrong. +*/ +static int addk (FuncState *fs, TValue *key, TValue *v) { + TValue val; + lua_State *L = fs->ls->L; + Proto *f = fs->f; + const TValue *idx = luaH_get(fs->ls->h, key); /* query scanner table */ + int k, oldsize; + if (ttisinteger(idx)) { /* is there an index there? */ + k = cast_int(ivalue(idx)); + /* correct value? (warning: must distinguish floats from integers!) */ + if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) && + luaV_rawequalobj(&f->k[k], v)) + return k; /* reuse index */ + } + /* constant not found; create a new entry */ + oldsize = f->sizek; + k = fs->nk; + /* numerical value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setivalue(&val, k); + luaH_finishset(L, fs->ls->h, key, idx, &val); + luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[k], v); + fs->nk++; + luaC_barrier(L, f, v); + return k; +} + + +/* +** Add a string to list of constants and return its index. +*/ +static int stringK (FuncState *fs, TString *s) { + TValue o; + setsvalue(fs->ls->L, &o, s); + return addk(fs, &o, &o); /* use string itself as key */ +} + + +/* +** Add an integer to list of constants and return its index. +** Integers use userdata as keys to avoid collision with floats with +** same value; conversion to 'void*' is used only for hashing, so there +** are no "precision" problems. +*/ +static int luaK_intK (FuncState *fs, lua_Integer n) { + TValue k, o; + setpvalue(&k, cast_voidp(cast_sizet(n))); + setivalue(&o, n); + return addk(fs, &k, &o); +} + +/* +** Add a float to list of constants and return its index. +*/ +static int luaK_numberK (FuncState *fs, lua_Number r) { + TValue o; + setfltvalue(&o, r); + return addk(fs, &o, &o); /* use number itself as key */ +} + + +/* +** Add a false to list of constants and return its index. +*/ +static int boolF (FuncState *fs) { + TValue o; + setbfvalue(&o); + return addk(fs, &o, &o); /* use boolean itself as key */ +} + + +/* +** Add a true to list of constants and return its index. +*/ +static int boolT (FuncState *fs) { + TValue o; + setbtvalue(&o); + return addk(fs, &o, &o); /* use boolean itself as key */ +} + + +/* +** Add nil to list of constants and return its index. +*/ +static int nilK (FuncState *fs) { + TValue k, v; + setnilvalue(&v); + /* cannot use nil as key; instead use table itself to represent nil */ + sethvalue(fs->ls->L, &k, fs->ls->h); + return addk(fs, &k, &v); +} + + +/* +** Check whether 'i' can be stored in an 'sC' operand. Equivalent to +** (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) but without risk of +** overflows in the hidden addition inside 'int2sC'. +*/ +static int fitsC (lua_Integer i) { + return (l_castS2U(i) + OFFSET_sC <= cast_uint(MAXARG_C)); +} + + +/* +** Check whether 'i' can be stored in an 'sBx' operand. +*/ +static int fitsBx (lua_Integer i) { + return (-OFFSET_sBx <= i && i <= MAXARG_Bx - OFFSET_sBx); +} + + +void luaK_int (FuncState *fs, int reg, lua_Integer i) { + if (fitsBx(i)) + luaK_codeAsBx(fs, OP_LOADI, reg, cast_int(i)); + else + luaK_codek(fs, reg, luaK_intK(fs, i)); +} + + +static void luaK_float (FuncState *fs, int reg, lua_Number f) { + lua_Integer fi; + if (luaV_flttointeger(f, &fi, F2Ieq) && fitsBx(fi)) + luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi)); + else + luaK_codek(fs, reg, luaK_numberK(fs, f)); +} + + +/* +** Convert a constant in 'v' into an expression description 'e' +*/ +static void const2exp (TValue *v, expdesc *e) { + switch (ttypetag(v)) { + case LUA_VNUMINT: + e->k = VKINT; e->u.ival = ivalue(v); + break; + case LUA_VNUMFLT: + e->k = VKFLT; e->u.nval = fltvalue(v); + break; + case LUA_VFALSE: + e->k = VFALSE; + break; + case LUA_VTRUE: + e->k = VTRUE; + break; + case LUA_VNIL: + e->k = VNIL; + break; + case LUA_VSHRSTR: case LUA_VLNGSTR: + e->k = VKSTR; e->u.strval = tsvalue(v); + break; + default: lua_assert(0); + } +} + + +/* +** Fix an expression to return the number of results 'nresults'. +** 'e' must be a multi-ret expression (function call or vararg). +*/ +void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { + Instruction *pc = &getinstruction(fs, e); + if (e->k == VCALL) /* expression is an open function call? */ + SETARG_C(*pc, nresults + 1); + else { + lua_assert(e->k == VVARARG); + SETARG_C(*pc, nresults + 1); + SETARG_A(*pc, fs->freereg); + luaK_reserveregs(fs, 1); + } +} + + +/* +** Convert a VKSTR to a VK +*/ +static void str2K (FuncState *fs, expdesc *e) { + lua_assert(e->k == VKSTR); + e->u.info = stringK(fs, e->u.strval); + e->k = VK; +} + + +/* +** Fix an expression to return one result. +** If expression is not a multi-ret expression (function call or +** vararg), it already returns one result, so nothing needs to be done. +** Function calls become VNONRELOC expressions (as its result comes +** fixed in the base register of the call), while vararg expressions +** become VRELOC (as OP_VARARG puts its results where it wants). +** (Calls are created returning one result, so that does not need +** to be fixed.) +*/ +void luaK_setoneret (FuncState *fs, expdesc *e) { + if (e->k == VCALL) { /* expression is an open function call? */ + /* already returns 1 value */ + lua_assert(GETARG_C(getinstruction(fs, e)) == 2); + e->k = VNONRELOC; /* result has fixed position */ + e->u.info = GETARG_A(getinstruction(fs, e)); + } + else if (e->k == VVARARG) { + SETARG_C(getinstruction(fs, e), 2); + e->k = VRELOC; /* can relocate its simple result */ + } +} + + +/* +** Ensure that expression 'e' is not a variable (nor a ). +** (Expression still may have jump lists.) +*/ +void luaK_dischargevars (FuncState *fs, expdesc *e) { + switch (e->k) { + case VCONST: { + const2exp(const2val(fs, e), e); + break; + } + case VLOCAL: { /* already in a register */ + e->u.info = e->u.var.ridx; + e->k = VNONRELOC; /* becomes a non-relocatable value */ + break; + } + case VUPVAL: { /* move value to some (pending) register */ + e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); + e->k = VRELOC; + break; + } + case VINDEXUP: { + e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOC; + break; + } + case VINDEXI: { + freereg(fs, e->u.ind.t); + e->u.info = luaK_codeABC(fs, OP_GETI, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOC; + break; + } + case VINDEXSTR: { + freereg(fs, e->u.ind.t); + e->u.info = luaK_codeABC(fs, OP_GETFIELD, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOC; + break; + } + case VINDEXED: { + freeregs(fs, e->u.ind.t, e->u.ind.idx); + e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOC; + break; + } + case VVARARG: case VCALL: { + luaK_setoneret(fs, e); + break; + } + default: break; /* there is one value available (somewhere) */ + } +} + + +/* +** Ensure expression value is in register 'reg', making 'e' a +** non-relocatable expression. +** (Expression still may have jump lists.) +*/ +static void discharge2reg (FuncState *fs, expdesc *e, int reg) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: { + luaK_nil(fs, reg, 1); + break; + } + case VFALSE: { + luaK_codeABC(fs, OP_LOADFALSE, reg, 0, 0); + break; + } + case VTRUE: { + luaK_codeABC(fs, OP_LOADTRUE, reg, 0, 0); + break; + } + case VKSTR: { + str2K(fs, e); + } /* FALLTHROUGH */ + case VK: { + luaK_codek(fs, reg, e->u.info); + break; + } + case VKFLT: { + luaK_float(fs, reg, e->u.nval); + break; + } + case VKINT: { + luaK_int(fs, reg, e->u.ival); + break; + } + case VRELOC: { + Instruction *pc = &getinstruction(fs, e); + SETARG_A(*pc, reg); /* instruction will put result in 'reg' */ + break; + } + case VNONRELOC: { + if (reg != e->u.info) + luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); + break; + } + default: { + lua_assert(e->k == VJMP); + return; /* nothing to do... */ + } + } + e->u.info = reg; + e->k = VNONRELOC; +} + + +/* +** Ensure expression value is in a register, making 'e' a +** non-relocatable expression. +** (Expression still may have jump lists.) +*/ +static void discharge2anyreg (FuncState *fs, expdesc *e) { + if (e->k != VNONRELOC) { /* no fixed register yet? */ + luaK_reserveregs(fs, 1); /* get a register */ + discharge2reg(fs, e, fs->freereg-1); /* put value there */ + } +} + + +static int code_loadbool (FuncState *fs, int A, OpCode op) { + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_codeABC(fs, op, A, 0, 0); +} + + +/* +** check whether list has any jump that do not produce a value +** or produce an inverted value +*/ +static int need_value (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + Instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TESTSET) return 1; + } + return 0; /* not found */ +} + + +/* +** Ensures final expression result (which includes results from its +** jump lists) is in register 'reg'. +** If expression has jumps, need to patch these jumps either to +** its final position or to "load" instructions (for those tests +** that do not produce values). +*/ +static void exp2reg (FuncState *fs, expdesc *e, int reg) { + discharge2reg(fs, e, reg); + if (e->k == VJMP) /* expression itself is a test? */ + luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ + if (hasjumps(e)) { + int final; /* position after whole expression */ + int p_f = NO_JUMP; /* position of an eventual LOAD false */ + int p_t = NO_JUMP; /* position of an eventual LOAD true */ + if (need_value(fs, e->t) || need_value(fs, e->f)) { + int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); + p_f = code_loadbool(fs, reg, OP_LFALSESKIP); /* skip next inst. */ + p_t = code_loadbool(fs, reg, OP_LOADTRUE); + /* jump around these booleans if 'e' is not a test */ + luaK_patchtohere(fs, fj); + } + final = luaK_getlabel(fs); + patchlistaux(fs, e->f, final, reg, p_f); + patchlistaux(fs, e->t, final, reg, p_t); + } + e->f = e->t = NO_JUMP; + e->u.info = reg; + e->k = VNONRELOC; +} + + +/* +** Ensures final expression result is in next available register. +*/ +void luaK_exp2nextreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + freeexp(fs, e); + luaK_reserveregs(fs, 1); + exp2reg(fs, e, fs->freereg - 1); +} + + +/* +** Ensures final expression result is in some (any) register +** and return that register. +*/ +int luaK_exp2anyreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + if (e->k == VNONRELOC) { /* expression already has a register? */ + if (!hasjumps(e)) /* no jumps? */ + return e->u.info; /* result is already in a register */ + if (e->u.info >= luaY_nvarstack(fs)) { /* reg. is not a local? */ + exp2reg(fs, e, e->u.info); /* put final result in it */ + return e->u.info; + } + /* else expression has jumps and cannot change its register + to hold the jump values, because it is a local variable. + Go through to the default case. */ + } + luaK_exp2nextreg(fs, e); /* default: use next available register */ + return e->u.info; +} + + +/* +** Ensures final expression result is either in a register +** or in an upvalue. +*/ +void luaK_exp2anyregup (FuncState *fs, expdesc *e) { + if (e->k != VUPVAL || hasjumps(e)) + luaK_exp2anyreg(fs, e); +} + + +/* +** Ensures final expression result is either in a register +** or it is a constant. +*/ +void luaK_exp2val (FuncState *fs, expdesc *e) { + if (hasjumps(e)) + luaK_exp2anyreg(fs, e); + else + luaK_dischargevars(fs, e); +} + + +/* +** Try to make 'e' a K expression with an index in the range of R/K +** indices. Return true iff succeeded. +*/ +static int luaK_exp2K (FuncState *fs, expdesc *e) { + if (!hasjumps(e)) { + int info; + switch (e->k) { /* move constants to 'k' */ + case VTRUE: info = boolT(fs); break; + case VFALSE: info = boolF(fs); break; + case VNIL: info = nilK(fs); break; + case VKINT: info = luaK_intK(fs, e->u.ival); break; + case VKFLT: info = luaK_numberK(fs, e->u.nval); break; + case VKSTR: info = stringK(fs, e->u.strval); break; + case VK: info = e->u.info; break; + default: return 0; /* not a constant */ + } + if (info <= MAXINDEXRK) { /* does constant fit in 'argC'? */ + e->k = VK; /* make expression a 'K' expression */ + e->u.info = info; + return 1; + } + } + /* else, expression doesn't fit; leave it unchanged */ + return 0; +} + + +/* +** Ensures final expression result is in a valid R/K index +** (that is, it is either in a register or in 'k' with an index +** in the range of R/K indices). +** Returns 1 iff expression is K. +*/ +int luaK_exp2RK (FuncState *fs, expdesc *e) { + if (luaK_exp2K(fs, e)) + return 1; + else { /* not a constant in the right range: put it in a register */ + luaK_exp2anyreg(fs, e); + return 0; + } +} + + +static void codeABRK (FuncState *fs, OpCode o, int a, int b, + expdesc *ec) { + int k = luaK_exp2RK(fs, ec); + luaK_codeABCk(fs, o, a, b, ec->u.info, k); +} + + +/* +** Generate code to store result of expression 'ex' into variable 'var'. +*/ +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { + switch (var->k) { + case VLOCAL: { + freeexp(fs, ex); + exp2reg(fs, ex, var->u.var.ridx); /* compute 'ex' into proper place */ + return; + } + case VUPVAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); + break; + } + case VINDEXUP: { + codeABRK(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, ex); + break; + } + case VINDEXI: { + codeABRK(fs, OP_SETI, var->u.ind.t, var->u.ind.idx, ex); + break; + } + case VINDEXSTR: { + codeABRK(fs, OP_SETFIELD, var->u.ind.t, var->u.ind.idx, ex); + break; + } + case VINDEXED: { + codeABRK(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, ex); + break; + } + default: lua_assert(0); /* invalid var kind to store */ + } + freeexp(fs, ex); +} + + +/* +** Emit SELF instruction (convert expression 'e' into 'e:key(e,'). +*/ +void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { + int ereg; + luaK_exp2anyreg(fs, e); + ereg = e->u.info; /* register where 'e' was placed */ + freeexp(fs, e); + e->u.info = fs->freereg; /* base register for op_self */ + e->k = VNONRELOC; /* self expression has a fixed register */ + luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ + codeABRK(fs, OP_SELF, e->u.info, ereg, key); + freeexp(fs, key); +} + + +/* +** Negate condition 'e' (where 'e' is a comparison). +*/ +static void negatecondition (FuncState *fs, expdesc *e) { + Instruction *pc = getjumpcontrol(fs, e->u.info); + lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && + GET_OPCODE(*pc) != OP_TEST); + SETARG_k(*pc, (GETARG_k(*pc) ^ 1)); +} + + +/* +** Emit instruction to jump if 'e' is 'cond' (that is, if 'cond' +** is true, code will jump if 'e' is true.) Return jump position. +** Optimize when 'e' is 'not' something, inverting the condition +** and removing the 'not'. +*/ +static int jumponcond (FuncState *fs, expdesc *e, int cond) { + if (e->k == VRELOC) { + Instruction ie = getinstruction(fs, e); + if (GET_OPCODE(ie) == OP_NOT) { + removelastinstruction(fs); /* remove previous OP_NOT */ + return condjump(fs, OP_TEST, GETARG_B(ie), 0, 0, !cond); + } + /* else go through */ + } + discharge2anyreg(fs, e); + freeexp(fs, e); + return condjump(fs, OP_TESTSET, NO_REG, e->u.info, 0, cond); +} + + +/* +** Emit code to go through if 'e' is true, jump otherwise. +*/ +void luaK_goiftrue (FuncState *fs, expdesc *e) { + int pc; /* pc of new jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VJMP: { /* condition? */ + negatecondition(fs, e); /* jump when it is false */ + pc = e->u.info; /* save jump position */ + break; + } + case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } + default: { + pc = jumponcond(fs, e, 0); /* jump when false */ + break; + } + } + luaK_concat(fs, &e->f, pc); /* insert new jump in false list */ + luaK_patchtohere(fs, e->t); /* true list jumps to here (to go through) */ + e->t = NO_JUMP; +} + + +/* +** Emit code to go through if 'e' is false, jump otherwise. +*/ +void luaK_goiffalse (FuncState *fs, expdesc *e) { + int pc; /* pc of new jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VJMP: { + pc = e->u.info; /* already jump if true */ + break; + } + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ + break; + } + default: { + pc = jumponcond(fs, e, 1); /* jump if true */ + break; + } + } + luaK_concat(fs, &e->t, pc); /* insert new jump in 't' list */ + luaK_patchtohere(fs, e->f); /* false list jumps to here (to go through) */ + e->f = NO_JUMP; +} + + +/* +** Code 'not e', doing constant folding. +*/ +static void codenot (FuncState *fs, expdesc *e) { + switch (e->k) { + case VNIL: case VFALSE: { + e->k = VTRUE; /* true == not nil == not false */ + break; + } + case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: { + e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ + break; + } + case VJMP: { + negatecondition(fs, e); + break; + } + case VRELOC: + case VNONRELOC: { + discharge2anyreg(fs, e); + freeexp(fs, e); + e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); + e->k = VRELOC; + break; + } + default: lua_assert(0); /* cannot happen */ + } + /* interchange true and false lists */ + { int temp = e->f; e->f = e->t; e->t = temp; } + removevalues(fs, e->f); /* values are useless when negated */ + removevalues(fs, e->t); +} + + +/* +** Check whether expression 'e' is a small literal string +*/ +static int isKstr (FuncState *fs, expdesc *e) { + return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B && + ttisshrstring(&fs->f->k[e->u.info])); +} + +/* +** Check whether expression 'e' is a literal integer. +*/ +int luaK_isKint (expdesc *e) { + return (e->k == VKINT && !hasjumps(e)); +} + + +/* +** Check whether expression 'e' is a literal integer in +** proper range to fit in register C +*/ +static int isCint (expdesc *e) { + return luaK_isKint(e) && (l_castS2U(e->u.ival) <= l_castS2U(MAXARG_C)); +} + + +/* +** Check whether expression 'e' is a literal integer in +** proper range to fit in register sC +*/ +static int isSCint (expdesc *e) { + return luaK_isKint(e) && fitsC(e->u.ival); +} + + +/* +** Check whether expression 'e' is a literal integer or float in +** proper range to fit in a register (sB or sC). +*/ +static int isSCnumber (expdesc *e, int *pi, int *isfloat) { + lua_Integer i; + if (e->k == VKINT) + i = e->u.ival; + else if (e->k == VKFLT && luaV_flttointeger(e->u.nval, &i, F2Ieq)) + *isfloat = 1; + else + return 0; /* not a number */ + if (!hasjumps(e) && fitsC(i)) { + *pi = int2sC(cast_int(i)); + return 1; + } + else + return 0; +} + + +/* +** Create expression 't[k]'. 't' must have its final result already in a +** register or upvalue. Upvalues can only be indexed by literal strings. +** Keys can be literal strings in the constant table or arbitrary +** values in registers. +*/ +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + if (k->k == VKSTR) + str2K(fs, k); + lua_assert(!hasjumps(t) && + (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL)); + if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ + luaK_exp2anyreg(fs, t); /* put it in a register */ + if (t->k == VUPVAL) { + t->u.ind.t = t->u.info; /* upvalue index */ + t->u.ind.idx = k->u.info; /* literal string */ + t->k = VINDEXUP; + } + else { + /* register index of the table */ + t->u.ind.t = (t->k == VLOCAL) ? t->u.var.ridx: t->u.info; + if (isKstr(fs, k)) { + t->u.ind.idx = k->u.info; /* literal string */ + t->k = VINDEXSTR; + } + else if (isCint(k)) { + t->u.ind.idx = cast_int(k->u.ival); /* int. constant in proper range */ + t->k = VINDEXI; + } + else { + t->u.ind.idx = luaK_exp2anyreg(fs, k); /* register */ + t->k = VINDEXED; + } + } +} + + +/* +** Return false if folding can raise an error. +** Bitwise operations need operands convertible to integers; division +** operations cannot have 0 as divisor. +*/ +static int validop (int op, TValue *v1, TValue *v2) { + switch (op) { + case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: + case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ + lua_Integer i; + return (luaV_tointegerns(v1, &i, LUA_FLOORN2I) && + luaV_tointegerns(v2, &i, LUA_FLOORN2I)); + } + case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ + return (nvalue(v2) != 0); + default: return 1; /* everything else is valid */ + } +} + + +/* +** Try to "constant-fold" an operation; return 1 iff successful. +** (In this case, 'e1' has the final result.) +*/ +static int constfolding (FuncState *fs, int op, expdesc *e1, + const expdesc *e2) { + TValue v1, v2, res; + if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) + return 0; /* non-numeric operands or not safe to fold */ + luaO_rawarith(fs->ls->L, op, &v1, &v2, &res); /* does operation */ + if (ttisinteger(&res)) { + e1->k = VKINT; + e1->u.ival = ivalue(&res); + } + else { /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */ + lua_Number n = fltvalue(&res); + if (luai_numisnan(n) || n == 0) + return 0; + e1->k = VKFLT; + e1->u.nval = n; + } + return 1; +} + + +/* +** Emit code for unary expressions that "produce values" +** (everything but 'not'). +** Expression to produce final result will be encoded in 'e'. +*/ +static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { + int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */ + freeexp(fs, e); + e->u.info = luaK_codeABC(fs, op, 0, r, 0); /* generate opcode */ + e->k = VRELOC; /* all those operations are relocatable */ + luaK_fixline(fs, line); +} + + +/* +** Emit code for binary expressions that "produce values" +** (everything but logical operators 'and'/'or' and comparison +** operators). +** Expression to produce final result will be encoded in 'e1'. +*/ +static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, + OpCode op, int v2, int flip, int line, + OpCode mmop, TMS event) { + int v1 = luaK_exp2anyreg(fs, e1); + int pc = luaK_codeABCk(fs, op, 0, v1, v2, 0); + freeexps(fs, e1, e2); + e1->u.info = pc; + e1->k = VRELOC; /* all those operations are relocatable */ + luaK_fixline(fs, line); + luaK_codeABCk(fs, mmop, v1, v2, event, flip); /* to call metamethod */ + luaK_fixline(fs, line); +} + + +/* +** Emit code for binary expressions that "produce values" over +** two registers. +*/ +static void codebinexpval (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int line) { + int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ + lua_assert(OP_ADD <= op && op <= OP_SHR); + finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, + cast(TMS, (op - OP_ADD) + TM_ADD)); +} + + +/* +** Code binary operators with immediate operands. +*/ +static void codebini (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int flip, int line, + TMS event) { + int v2 = int2sC(cast_int(e2->u.ival)); /* immediate operand */ + lua_assert(e2->k == VKINT); + finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINI, event); +} + + +/* Try to code a binary operator negating its second operand. +** For the metamethod, 2nd operand must keep its original value. +*/ +static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2, + OpCode op, int line, TMS event) { + if (!luaK_isKint(e2)) + return 0; /* not an integer constant */ + else { + lua_Integer i2 = e2->u.ival; + if (!(fitsC(i2) && fitsC(-i2))) + return 0; /* not in the proper range */ + else { /* operating a small integer constant */ + int v2 = cast_int(i2); + finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event); + /* correct metamethod argument */ + SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2)); + return 1; /* successfully coded */ + } + } +} + + +static void swapexps (expdesc *e1, expdesc *e2) { + expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ +} + + +/* +** Code arithmetic operators ('+', '-', ...). If second operand is a +** constant in the proper range, use variant opcodes with K operands. +*/ +static void codearith (FuncState *fs, BinOpr opr, + expdesc *e1, expdesc *e2, int flip, int line) { + TMS event = cast(TMS, opr + TM_ADD); + if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */ + int v2 = e2->u.info; /* K index */ + OpCode op = cast(OpCode, opr + OP_ADDK); + finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event); + } + else { /* 'e2' is neither an immediate nor a K operand */ + OpCode op = cast(OpCode, opr + OP_ADD); + if (flip) + swapexps(e1, e2); /* back to original order */ + codebinexpval(fs, op, e1, e2, line); /* use standard operators */ + } +} + + +/* +** Code commutative operators ('+', '*'). If first operand is a +** numeric constant, change order of operands to try to use an +** immediate or K operator. +*/ +static void codecommutative (FuncState *fs, BinOpr op, + expdesc *e1, expdesc *e2, int line) { + int flip = 0; + if (tonumeral(e1, NULL)) { /* is first operand a numeric constant? */ + swapexps(e1, e2); /* change order */ + flip = 1; + } + if (op == OPR_ADD && isSCint(e2)) /* immediate operand? */ + codebini(fs, cast(OpCode, OP_ADDI), e1, e2, flip, line, TM_ADD); + else + codearith(fs, op, e1, e2, flip, line); +} + + +/* +** Code bitwise operations; they are all associative, so the function +** tries to put an integer constant as the 2nd operand (a K operand). +*/ +static void codebitwise (FuncState *fs, BinOpr opr, + expdesc *e1, expdesc *e2, int line) { + int flip = 0; + int v2; + OpCode op; + if (e1->k == VKINT && luaK_exp2RK(fs, e1)) { + swapexps(e1, e2); /* 'e2' will be the constant operand */ + flip = 1; + } + else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */ + op = cast(OpCode, opr + OP_ADD); + codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ + return; + } + v2 = e2->u.info; /* index in K array */ + op = cast(OpCode, opr + OP_ADDK); + lua_assert(ttisinteger(&fs->f->k[v2])); + finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, + cast(TMS, opr + TM_ADD)); +} + + +/* +** Emit code for order comparisons. When using an immediate operand, +** 'isfloat' tells whether the original value was a float. +*/ +static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { + int r1, r2; + int im; + int isfloat = 0; + if (isSCnumber(e2, &im, &isfloat)) { + /* use immediate operand */ + r1 = luaK_exp2anyreg(fs, e1); + r2 = im; + op = cast(OpCode, (op - OP_LT) + OP_LTI); + } + else if (isSCnumber(e1, &im, &isfloat)) { + /* transform (A < B) to (B > A) and (A <= B) to (B >= A) */ + r1 = luaK_exp2anyreg(fs, e2); + r2 = im; + op = (op == OP_LT) ? OP_GTI : OP_GEI; + } + else { /* regular case, compare two registers */ + r1 = luaK_exp2anyreg(fs, e1); + r2 = luaK_exp2anyreg(fs, e2); + } + freeexps(fs, e1, e2); + e1->u.info = condjump(fs, op, r1, r2, isfloat, 1); + e1->k = VJMP; +} + + +/* +** Emit code for equality comparisons ('==', '~='). +** 'e1' was already put as RK by 'luaK_infix'. +*/ +static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { + int r1, r2; + int im; + int isfloat = 0; /* not needed here, but kept for symmetry */ + OpCode op; + if (e1->k != VNONRELOC) { + lua_assert(e1->k == VK || e1->k == VKINT || e1->k == VKFLT); + swapexps(e1, e2); + } + r1 = luaK_exp2anyreg(fs, e1); /* 1st expression must be in register */ + if (isSCnumber(e2, &im, &isfloat)) { + op = OP_EQI; + r2 = im; /* immediate operand */ + } + else if (luaK_exp2RK(fs, e2)) { /* 1st expression is constant? */ + op = OP_EQK; + r2 = e2->u.info; /* constant index */ + } + else { + op = OP_EQ; /* will compare two registers */ + r2 = luaK_exp2anyreg(fs, e2); + } + freeexps(fs, e1, e2); + e1->u.info = condjump(fs, op, r1, r2, isfloat, (opr == OPR_EQ)); + e1->k = VJMP; +} + + +/* +** Apply prefix operation 'op' to expression 'e'. +*/ +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { + static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; + luaK_dischargevars(fs, e); + switch (op) { + case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ + if (constfolding(fs, op + LUA_OPUNM, e, &ef)) + break; + /* else */ /* FALLTHROUGH */ + case OPR_LEN: + codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); + break; + case OPR_NOT: codenot(fs, e); break; + default: lua_assert(0); + } +} + + +/* +** Process 1st operand 'v' of binary operation 'op' before reading +** 2nd operand. +*/ +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { + luaK_dischargevars(fs, v); + switch (op) { + case OPR_AND: { + luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */ + break; + } + case OPR_OR: { + luaK_goiffalse(fs, v); /* go ahead only if 'v' is false */ + break; + } + case OPR_CONCAT: { + luaK_exp2nextreg(fs, v); /* operand must be on the stack */ + break; + } + case OPR_ADD: case OPR_SUB: + case OPR_MUL: case OPR_DIV: case OPR_IDIV: + case OPR_MOD: case OPR_POW: + case OPR_BAND: case OPR_BOR: case OPR_BXOR: + case OPR_SHL: case OPR_SHR: { + if (!tonumeral(v, NULL)) + luaK_exp2anyreg(fs, v); + /* else keep numeral, which may be folded with 2nd operand */ + break; + } + case OPR_EQ: case OPR_NE: { + if (!tonumeral(v, NULL)) + luaK_exp2RK(fs, v); + /* else keep numeral, which may be an immediate operand */ + break; + } + case OPR_LT: case OPR_LE: + case OPR_GT: case OPR_GE: { + int dummy, dummy2; + if (!isSCnumber(v, &dummy, &dummy2)) + luaK_exp2anyreg(fs, v); + /* else keep numeral, which may be an immediate operand */ + break; + } + default: lua_assert(0); + } +} + +/* +** Create code for '(e1 .. e2)'. +** For '(e1 .. e2.1 .. e2.2)' (which is '(e1 .. (e2.1 .. e2.2))', +** because concatenation is right associative), merge both CONCATs. +*/ +static void codeconcat (FuncState *fs, expdesc *e1, expdesc *e2, int line) { + Instruction *ie2 = previousinstruction(fs); + if (GET_OPCODE(*ie2) == OP_CONCAT) { /* is 'e2' a concatenation? */ + int n = GETARG_B(*ie2); /* # of elements concatenated in 'e2' */ + lua_assert(e1->u.info + 1 == GETARG_A(*ie2)); + freeexp(fs, e2); + SETARG_A(*ie2, e1->u.info); /* correct first element ('e1') */ + SETARG_B(*ie2, n + 1); /* will concatenate one more element */ + } + else { /* 'e2' is not a concatenation */ + luaK_codeABC(fs, OP_CONCAT, e1->u.info, 2, 0); /* new concat opcode */ + freeexp(fs, e2); + luaK_fixline(fs, line); + } +} + + +/* +** Finalize code for binary operation, after reading 2nd operand. +*/ +void luaK_posfix (FuncState *fs, BinOpr opr, + expdesc *e1, expdesc *e2, int line) { + luaK_dischargevars(fs, e2); + if (foldbinop(opr) && constfolding(fs, opr + LUA_OPADD, e1, e2)) + return; /* done by folding */ + switch (opr) { + case OPR_AND: { + lua_assert(e1->t == NO_JUMP); /* list closed by 'luaK_infix' */ + luaK_concat(fs, &e2->f, e1->f); + *e1 = *e2; + break; + } + case OPR_OR: { + lua_assert(e1->f == NO_JUMP); /* list closed by 'luaK_infix' */ + luaK_concat(fs, &e2->t, e1->t); + *e1 = *e2; + break; + } + case OPR_CONCAT: { /* e1 .. e2 */ + luaK_exp2nextreg(fs, e2); + codeconcat(fs, e1, e2, line); + break; + } + case OPR_ADD: case OPR_MUL: { + codecommutative(fs, opr, e1, e2, line); + break; + } + case OPR_SUB: { + if (finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB)) + break; /* coded as (r1 + -I) */ + /* ELSE */ + } /* FALLTHROUGH */ + case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: { + codearith(fs, opr, e1, e2, 0, line); + break; + } + case OPR_BAND: case OPR_BOR: case OPR_BXOR: { + codebitwise(fs, opr, e1, e2, line); + break; + } + case OPR_SHL: { + if (isSCint(e1)) { + swapexps(e1, e2); + codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); /* I << r2 */ + } + else if (finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL)) { + /* coded as (r1 >> -I) */; + } + else /* regular case (two registers) */ + codebinexpval(fs, OP_SHL, e1, e2, line); + break; + } + case OPR_SHR: { + if (isSCint(e2)) + codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */ + else /* regular case (two registers) */ + codebinexpval(fs, OP_SHR, e1, e2, line); + break; + } + case OPR_EQ: case OPR_NE: { + codeeq(fs, opr, e1, e2); + break; + } + case OPR_LT: case OPR_LE: { + OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); + codeorder(fs, op, e1, e2); + break; + } + case OPR_GT: case OPR_GE: { + /* '(a > b)' <=> '(b < a)'; '(a >= b)' <=> '(b <= a)' */ + OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); + swapexps(e1, e2); + codeorder(fs, op, e1, e2); + break; + } + default: lua_assert(0); + } +} + + +/* +** Change line information associated with current position, by removing +** previous info and adding it again with new line. +*/ +void luaK_fixline (FuncState *fs, int line) { + removelastlineinfo(fs); + savelineinfo(fs, fs->f, line); +} + + +void luaK_settablesize (FuncState *fs, int pc, int ra, int asize, int hsize) { + Instruction *inst = &fs->f->code[pc]; + int rb = (hsize != 0) ? luaO_ceillog2(hsize) + 1 : 0; /* hash size */ + int extra = asize / (MAXARG_C + 1); /* higher bits of array size */ + int rc = asize % (MAXARG_C + 1); /* lower bits of array size */ + int k = (extra > 0); /* true iff needs extra argument */ + *inst = CREATE_ABCk(OP_NEWTABLE, ra, rb, rc, k); + *(inst + 1) = CREATE_Ax(OP_EXTRAARG, extra); +} + + +/* +** Emit a SETLIST instruction. +** 'base' is register that keeps table; +** 'nelems' is #table plus those to be stored now; +** 'tostore' is number of values (in registers 'base + 1',...) to add to +** table (or LUA_MULTRET to add up to stack top). +*/ +void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { + lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); + if (tostore == LUA_MULTRET) + tostore = 0; + if (nelems <= MAXARG_C) + luaK_codeABC(fs, OP_SETLIST, base, tostore, nelems); + else { + int extra = nelems / (MAXARG_C + 1); + nelems %= (MAXARG_C + 1); + luaK_codeABCk(fs, OP_SETLIST, base, tostore, nelems, 1); + codeextraarg(fs, extra); + } + fs->freereg = base + 1; /* free registers with list values */ +} + + +/* +** return the final target of a jump (skipping jumps to jumps) +*/ +static int finaltarget (Instruction *code, int i) { + int count; + for (count = 0; count < 100; count++) { /* avoid infinite loops */ + Instruction pc = code[i]; + if (GET_OPCODE(pc) != OP_JMP) + break; + else + i += GETARG_sJ(pc) + 1; + } + return i; +} + + +/* +** Do a final pass over the code of a function, doing small peephole +** optimizations and adjustments. +*/ +void luaK_finish (FuncState *fs) { + int i; + Proto *p = fs->f; + for (i = 0; i < fs->pc; i++) { + Instruction *pc = &p->code[i]; + lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc)); + switch (GET_OPCODE(*pc)) { + case OP_RETURN0: case OP_RETURN1: { + if (!(fs->needclose || p->is_vararg)) + break; /* no extra work */ + /* else use OP_RETURN to do the extra work */ + SET_OPCODE(*pc, OP_RETURN); + } /* FALLTHROUGH */ + case OP_RETURN: case OP_TAILCALL: { + if (fs->needclose) + SETARG_k(*pc, 1); /* signal that it needs to close */ + if (p->is_vararg) + SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */ + break; + } + case OP_JMP: { + int target = finaltarget(p->code, i); + fixjump(fs, i, target); + break; + } + default: break; + } + } +} diff --git a/lua/lcode.h b/lua/lcode.h new file mode 100644 index 0000000..3265824 --- /dev/null +++ b/lua/lcode.h @@ -0,0 +1,104 @@ +/* +** $Id: lcode.h $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lcode_h +#define lcode_h + +#include "llex.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" + + +/* +** Marks the end of a patch list. It is an invalid value both as an absolute +** address, and as a list link (would link an element to itself). +*/ +#define NO_JUMP (-1) + + +/* +** grep "ORDER OPR" if you change these enums (ORDER OP) +*/ +typedef enum BinOpr { + /* arithmetic operators */ + OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW, + OPR_DIV, OPR_IDIV, + /* bitwise operators */ + OPR_BAND, OPR_BOR, OPR_BXOR, + OPR_SHL, OPR_SHR, + /* string operator */ + OPR_CONCAT, + /* comparison operators */ + OPR_EQ, OPR_LT, OPR_LE, + OPR_NE, OPR_GT, OPR_GE, + /* logical operators */ + OPR_AND, OPR_OR, + OPR_NOBINOPR +} BinOpr; + + +/* true if operation is foldable (that is, it is arithmetic or bitwise) */ +#define foldbinop(op) ((op) <= OPR_SHR) + + +#define luaK_codeABC(fs,o,a,b,c) luaK_codeABCk(fs,o,a,b,c,0) + + +typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; + + +/* get (pointer to) instruction of given 'expdesc' */ +#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info]) + + +#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) + +#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) + +LUAI_FUNC int luaK_code (FuncState *fs, Instruction i); +LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); +LUAI_FUNC int luaK_codeAsBx (FuncState *fs, OpCode o, int A, int Bx); +LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A, + int B, int C, int k); +LUAI_FUNC int luaK_isKint (expdesc *e); +LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v); +LUAI_FUNC void luaK_fixline (FuncState *fs, int line); +LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); +LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); +LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); +LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n); +LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); +LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); +LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); +LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); +LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_jump (FuncState *fs); +LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); +LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); +LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); +LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); +LUAI_FUNC int luaK_getlabel (FuncState *fs); +LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); +LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); +LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, + expdesc *v2, int line); +LUAI_FUNC void luaK_settablesize (FuncState *fs, int pc, + int ra, int asize, int hsize); +LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); +LUAI_FUNC void luaK_finish (FuncState *fs); +LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg); + + +#endif diff --git a/lua/lcorolib.c b/lua/lcorolib.c new file mode 100644 index 0000000..fedbebe --- /dev/null +++ b/lua/lcorolib.c @@ -0,0 +1,210 @@ +/* +** $Id: lcorolib.c $ +** Coroutine Library +** See Copyright Notice in lua.h +*/ + +#define lcorolib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static lua_State *getco (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argexpected(L, co, 1, "thread"); + return co; +} + + +/* +** Resumes a coroutine. Returns the number of results for non-error +** cases or -1 for errors. +*/ +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status, nres; + if (l_unlikely(!lua_checkstack(co, narg))) { + lua_pushliteral(L, "too many arguments to resume"); + return -1; /* error flag */ + } + lua_xmove(L, co, narg); + status = lua_resume(co, L, narg, &nres); + if (l_likely(status == LUA_OK || status == LUA_YIELD)) { + if (l_unlikely(!lua_checkstack(L, nres + 1))) { + lua_pop(co, nres); /* remove results anyway */ + lua_pushliteral(L, "too many results to resume"); + return -1; /* error flag */ + } + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } +} + + +static int luaB_coresume (lua_State *L) { + lua_State *co = getco(L); + int r; + r = auxresume(L, co, lua_gettop(L) - 1); + if (l_unlikely(r < 0)) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + 'resume' returns */ + } +} + + +static int luaB_auxwrap (lua_State *L) { + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (l_unlikely(r < 0)) { /* error? */ + int stat = lua_status(co); + if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */ + stat = lua_resetthread(co); /* close its tbc variables */ + lua_assert(stat != LUA_OK); + lua_xmove(co, L, 1); /* copy error message */ + } + if (stat != LUA_ERRMEM && /* not a memory error and ... */ + lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */ + luaL_where(L, 1); /* add extra info, if available */ + lua_insert(L, -2); + lua_concat(L, 2); + } + return lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL; + luaL_checktype(L, 1, LUA_TFUNCTION); + NL = lua_newthread(L); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; +} + + +static int luaB_cowrap (lua_State *L) { + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; +} + + +static int luaB_yield (lua_State *L) { + return lua_yield(L, lua_gettop(L)); +} + + +#define COS_RUN 0 +#define COS_DEAD 1 +#define COS_YIELD 2 +#define COS_NORM 3 + + +static const char *const statname[] = + {"running", "dead", "suspended", "normal"}; + + +static int auxstatus (lua_State *L, lua_State *co) { + if (L == co) return COS_RUN; + else { + switch (lua_status(co)) { + case LUA_YIELD: + return COS_YIELD; + case LUA_OK: { + lua_Debug ar; + if (lua_getstack(co, 0, &ar)) /* does it have frames? */ + return COS_NORM; /* it is running */ + else if (lua_gettop(co) == 0) + return COS_DEAD; + else + return COS_YIELD; /* initial state */ + } + default: /* some error occurred */ + return COS_DEAD; + } + } +} + + +static int luaB_costatus (lua_State *L) { + lua_State *co = getco(L); + lua_pushstring(L, statname[auxstatus(L, co)]); + return 1; +} + + +static int luaB_yieldable (lua_State *L) { + lua_State *co = lua_isnone(L, 1) ? L : getco(L); + lua_pushboolean(L, lua_isyieldable(co)); + return 1; +} + + +static int luaB_corunning (lua_State *L) { + int ismain = lua_pushthread(L); + lua_pushboolean(L, ismain); + return 2; +} + + +static int luaB_close (lua_State *L) { + lua_State *co = getco(L); + int status = auxstatus(L, co); + switch (status) { + case COS_DEAD: case COS_YIELD: { + status = lua_resetthread(co); + if (status == LUA_OK) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushboolean(L, 0); + lua_xmove(co, L, 1); /* copy error message */ + return 2; + } + } + default: /* normal or running coroutine */ + return luaL_error(L, "cannot close a %s coroutine", statname[status]); + } +} + + +static const luaL_Reg co_funcs[] = { + {"create", luaB_cocreate}, + {"resume", luaB_coresume}, + {"running", luaB_corunning}, + {"status", luaB_costatus}, + {"wrap", luaB_cowrap}, + {"yield", luaB_yield}, + {"isyieldable", luaB_yieldable}, + {"close", luaB_close}, + {NULL, NULL} +}; + + + +LUAMOD_API int luaopen_coroutine (lua_State *L) { + luaL_newlib(L, co_funcs); + return 1; +} + diff --git a/lua/lctype.c b/lua/lctype.c new file mode 100644 index 0000000..9542280 --- /dev/null +++ b/lua/lctype.c @@ -0,0 +1,64 @@ +/* +** $Id: lctype.c $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#define lctype_c +#define LUA_CORE + +#include "lprefix.h" + + +#include "lctype.h" + +#if !LUA_USE_CTYPE /* { */ + +#include + + +#if defined (LUA_UCID) /* accept UniCode IDentifiers? */ +/* consider all non-ascii codepoints to be alphabetic */ +#define NONA 0x01 +#else +#define NONA 0x00 /* default */ +#endif + + +LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { + 0x00, /* EOZ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ + 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 8. */ + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 9. */ + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* a. */ + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* b. */ + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, + 0x00, 0x00, NONA, NONA, NONA, NONA, NONA, NONA, /* c. */ + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* d. */ + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* e. */ + NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, + NONA, NONA, NONA, NONA, NONA, 0x00, 0x00, 0x00, /* f. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +#endif /* } */ diff --git a/lua/lctype.h b/lua/lctype.h new file mode 100644 index 0000000..864e190 --- /dev/null +++ b/lua/lctype.h @@ -0,0 +1,101 @@ +/* +** $Id: lctype.h $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lctype_h +#define lctype_h + +#include "lua.h" + + +/* +** WARNING: the functions defined here do not necessarily correspond +** to the similar functions in the standard C ctype.h. They are +** optimized for the specific needs of Lua. +*/ + +#if !defined(LUA_USE_CTYPE) + +#if 'A' == 65 && '0' == 48 +/* ASCII case: can use its own tables; faster and fixed */ +#define LUA_USE_CTYPE 0 +#else +/* must use standard C ctype */ +#define LUA_USE_CTYPE 1 +#endif + +#endif + + +#if !LUA_USE_CTYPE /* { */ + +#include + +#include "llimits.h" + + +#define ALPHABIT 0 +#define DIGITBIT 1 +#define PRINTBIT 2 +#define SPACEBIT 3 +#define XDIGITBIT 4 + + +#define MASK(B) (1 << (B)) + + +/* +** add 1 to char to allow index -1 (EOZ) +*/ +#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) + +/* +** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' +*/ +#define lislalpha(c) testprop(c, MASK(ALPHABIT)) +#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) +#define lisdigit(c) testprop(c, MASK(DIGITBIT)) +#define lisspace(c) testprop(c, MASK(SPACEBIT)) +#define lisprint(c) testprop(c, MASK(PRINTBIT)) +#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) + + +/* +** In ASCII, this 'ltolower' is correct for alphabetic characters and +** for '.'. That is enough for Lua needs. ('check_exp' ensures that +** the character either is an upper-case letter or is unchanged by +** the transformation, which holds for lower-case letters and '.'.) +*/ +#define ltolower(c) \ + check_exp(('A' <= (c) && (c) <= 'Z') || (c) == ((c) | ('A' ^ 'a')), \ + (c) | ('A' ^ 'a')) + + +/* one entry for each character and for -1 (EOZ) */ +LUAI_DDEC(const lu_byte luai_ctype_[UCHAR_MAX + 2];) + + +#else /* }{ */ + +/* +** use standard C ctypes +*/ + +#include + + +#define lislalpha(c) (isalpha(c) || (c) == '_') +#define lislalnum(c) (isalnum(c) || (c) == '_') +#define lisdigit(c) (isdigit(c)) +#define lisspace(c) (isspace(c)) +#define lisprint(c) (isprint(c)) +#define lisxdigit(c) (isxdigit(c)) + +#define ltolower(c) (tolower(c)) + +#endif /* } */ + +#endif + diff --git a/lua/ldblib.c b/lua/ldblib.c new file mode 100644 index 0000000..6dcbaa9 --- /dev/null +++ b/lua/ldblib.c @@ -0,0 +1,483 @@ +/* +** $Id: ldblib.c $ +** Interface from Lua to its debug API +** See Copyright Notice in lua.h +*/ + +#define ldblib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** The hook table at registry[HOOKKEY] maps threads to their current +** hook function. +*/ +static const char *const HOOKKEY = "_HOOKKEY"; + + +/* +** If L1 != L, L1 can be in any state, and therefore there are no +** guarantees about its stack space; any push in L1 must be +** checked. +*/ +static void checkstack (lua_State *L, lua_State *L1, int n) { + if (l_unlikely(L != L1 && !lua_checkstack(L1, n))) + luaL_error(L, "stack overflow"); +} + + +static int db_getregistry (lua_State *L) { + lua_pushvalue(L, LUA_REGISTRYINDEX); + return 1; +} + + +static int db_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); /* no metatable */ + } + return 1; +} + + +static int db_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; /* return 1st argument */ +} + + +static int db_getuservalue (lua_State *L) { + int n = (int)luaL_optinteger(L, 2, 1); + if (lua_type(L, 1) != LUA_TUSERDATA) + luaL_pushfail(L); + else if (lua_getiuservalue(L, 1, n) != LUA_TNONE) { + lua_pushboolean(L, 1); + return 2; + } + return 1; +} + + +static int db_setuservalue (lua_State *L) { + int n = (int)luaL_optinteger(L, 3, 1); + luaL_checktype(L, 1, LUA_TUSERDATA); + luaL_checkany(L, 2); + lua_settop(L, 2); + if (!lua_setiuservalue(L, 1, n)) + luaL_pushfail(L); + return 1; +} + + +/* +** Auxiliary function used by several library functions: check for +** an optional thread as function's first argument and set 'arg' with +** 1 if this argument is present (so that functions can skip it to +** access their other arguments) +*/ +static lua_State *getthread (lua_State *L, int *arg) { + if (lua_isthread(L, 1)) { + *arg = 1; + return lua_tothread(L, 1); + } + else { + *arg = 0; + return L; /* function will operate over current thread */ + } +} + + +/* +** Variations of 'lua_settable', used by 'db_getinfo' to put results +** from 'lua_getinfo' into result table. Key is always a string; +** value can be a string, an int, or a boolean. +*/ +static void settabss (lua_State *L, const char *k, const char *v) { + lua_pushstring(L, v); + lua_setfield(L, -2, k); +} + +static void settabsi (lua_State *L, const char *k, int v) { + lua_pushinteger(L, v); + lua_setfield(L, -2, k); +} + +static void settabsb (lua_State *L, const char *k, int v) { + lua_pushboolean(L, v); + lua_setfield(L, -2, k); +} + + +/* +** In function 'db_getinfo', the call to 'lua_getinfo' may push +** results on the stack; later it creates the result table to put +** these objects. Function 'treatstackoption' puts the result from +** 'lua_getinfo' on top of the result table so that it can call +** 'lua_setfield'. +*/ +static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { + if (L == L1) + lua_rotate(L, -2, 1); /* exchange object and table */ + else + lua_xmove(L1, L, 1); /* move object to the "main" stack */ + lua_setfield(L, -2, fname); /* put object into table */ +} + + +/* +** Calls 'lua_getinfo' and collects all results in a new table. +** L1 needs stack space for an optional input (function) plus +** two optional outputs (function and line table) from function +** 'lua_getinfo'. +*/ +static int db_getinfo (lua_State *L) { + lua_Debug ar; + int arg; + lua_State *L1 = getthread(L, &arg); + const char *options = luaL_optstring(L, arg+2, "flnSrtu"); + checkstack(L, L1, 3); + luaL_argcheck(L, options[0] != '>', arg + 2, "invalid option '>'"); + if (lua_isfunction(L, arg + 1)) { /* info about a function? */ + options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ + lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ + lua_xmove(L, L1, 1); + } + else { /* stack level */ + if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) { + luaL_pushfail(L); /* level out of range */ + return 1; + } + } + if (!lua_getinfo(L1, options, &ar)) + return luaL_argerror(L, arg+2, "invalid option"); + lua_newtable(L); /* table to collect results */ + if (strchr(options, 'S')) { + lua_pushlstring(L, ar.source, ar.srclen); + lua_setfield(L, -2, "source"); + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabsi(L, "lastlinedefined", ar.lastlinedefined); + settabss(L, "what", ar.what); + } + if (strchr(options, 'l')) + settabsi(L, "currentline", ar.currentline); + if (strchr(options, 'u')) { + settabsi(L, "nups", ar.nups); + settabsi(L, "nparams", ar.nparams); + settabsb(L, "isvararg", ar.isvararg); + } + if (strchr(options, 'n')) { + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + } + if (strchr(options, 'r')) { + settabsi(L, "ftransfer", ar.ftransfer); + settabsi(L, "ntransfer", ar.ntransfer); + } + if (strchr(options, 't')) + settabsb(L, "istailcall", ar.istailcall); + if (strchr(options, 'L')) + treatstackoption(L, L1, "activelines"); + if (strchr(options, 'f')) + treatstackoption(L, L1, "func"); + return 1; /* return table */ +} + + +static int db_getlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */ + if (lua_isfunction(L, arg + 1)) { /* function argument? */ + lua_pushvalue(L, arg + 1); /* push function */ + lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ + return 1; /* return only name (there is no value) */ + } + else { /* stack-level argument */ + lua_Debug ar; + const char *name; + int level = (int)luaL_checkinteger(L, arg + 1); + if (l_unlikely(!lua_getstack(L1, level, &ar))) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + checkstack(L, L1, 1); + name = lua_getlocal(L1, &ar, nvar); + if (name) { + lua_xmove(L1, L, 1); /* move local value */ + lua_pushstring(L, name); /* push name */ + lua_rotate(L, -2, 1); /* re-order */ + return 2; + } + else { + luaL_pushfail(L); /* no name (nor value) */ + return 1; + } + } +} + + +static int db_setlocal (lua_State *L) { + int arg; + const char *name; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + int level = (int)luaL_checkinteger(L, arg + 1); + int nvar = (int)luaL_checkinteger(L, arg + 2); + if (l_unlikely(!lua_getstack(L1, level, &ar))) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + luaL_checkany(L, arg+3); + lua_settop(L, arg+3); + checkstack(L, L1, 1); + lua_xmove(L, L1, 1); + name = lua_setlocal(L1, &ar, nvar); + if (name == NULL) + lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */ + lua_pushstring(L, name); + return 1; +} + + +/* +** get (if 'get' is true) or set an upvalue from a closure +*/ +static int auxupvalue (lua_State *L, int get) { + const char *name; + int n = (int)luaL_checkinteger(L, 2); /* upvalue index */ + luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */ + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); /* no-op if get is false */ + return get + 1; +} + + +static int db_getupvalue (lua_State *L) { + return auxupvalue(L, 1); +} + + +static int db_setupvalue (lua_State *L) { + luaL_checkany(L, 3); + return auxupvalue(L, 0); +} + + +/* +** Check whether a given upvalue from a given closure exists and +** returns its index +*/ +static void *checkupval (lua_State *L, int argf, int argnup, int *pnup) { + void *id; + int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ + luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ + id = lua_upvalueid(L, argf, nup); + if (pnup) { + luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index"); + *pnup = nup; + } + return id; +} + + +static int db_upvalueid (lua_State *L) { + void *id = checkupval(L, 1, 2, NULL); + if (id != NULL) + lua_pushlightuserdata(L, id); + else + luaL_pushfail(L); + return 1; +} + + +static int db_upvaluejoin (lua_State *L) { + int n1, n2; + checkupval(L, 1, 2, &n1); + checkupval(L, 3, 4, &n2); + luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); + luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); + lua_upvaluejoin(L, 1, n1, 3, n2); + return 0; +} + + +/* +** Call hook function registered at hook table for the current +** thread (if there is one) +*/ +static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail call"}; + lua_getfield(L, LUA_REGISTRYINDEX, HOOKKEY); + lua_pushthread(L); + if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */ + lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */ + if (ar->currentline >= 0) + lua_pushinteger(L, ar->currentline); /* push current line */ + else lua_pushnil(L); + lua_assert(lua_getinfo(L, "lS", ar)); + lua_call(L, 2, 0); /* call hook function */ + } +} + + +/* +** Convert a string mask (for 'sethook') into a bit mask +*/ +static int makemask (const char *smask, int count) { + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + return mask; +} + + +/* +** Convert a bit mask (for 'gethook') into a string mask +*/ +static char *unmakemask (int mask, char *smask) { + int i = 0; + if (mask & LUA_MASKCALL) smask[i++] = 'c'; + if (mask & LUA_MASKRET) smask[i++] = 'r'; + if (mask & LUA_MASKLINE) smask[i++] = 'l'; + smask[i] = '\0'; + return smask; +} + + +static int db_sethook (lua_State *L) { + int arg, mask, count; + lua_Hook func; + lua_State *L1 = getthread(L, &arg); + if (lua_isnoneornil(L, arg+1)) { /* no hook? */ + lua_settop(L, arg+1); + func = NULL; mask = 0; count = 0; /* turn off hooks */ + } + else { + const char *smask = luaL_checkstring(L, arg+2); + luaL_checktype(L, arg+1, LUA_TFUNCTION); + count = (int)luaL_optinteger(L, arg + 3, 0); + func = hookf; mask = makemask(smask, count); + } + if (!luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)) { + /* table just created; initialize it */ + lua_pushliteral(L, "k"); + lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ + lua_pushvalue(L, -1); + lua_setmetatable(L, -2); /* metatable(hooktable) = hooktable */ + } + checkstack(L, L1, 1); + lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */ + lua_pushvalue(L, arg + 1); /* value (hook function) */ + lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */ + lua_sethook(L1, func, mask, count); + return 0; +} + + +static int db_gethook (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + char buff[5]; + int mask = lua_gethookmask(L1); + lua_Hook hook = lua_gethook(L1); + if (hook == NULL) { /* no hook? */ + luaL_pushfail(L); + return 1; + } + else if (hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else { /* hook table must exist */ + lua_getfield(L, LUA_REGISTRYINDEX, HOOKKEY); + checkstack(L, L1, 1); + lua_pushthread(L1); lua_xmove(L1, L, 1); + lua_rawget(L, -2); /* 1st result = hooktable[L1] */ + lua_remove(L, -2); /* remove hook table */ + } + lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */ + lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */ + return 3; +} + + +static int db_debug (lua_State *L) { + for (;;) { + char buffer[250]; + lua_writestringerror("%s", "lua_debug> "); + if (fgets(buffer, sizeof(buffer), stdin) == NULL || + strcmp(buffer, "cont\n") == 0) + return 0; + if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || + lua_pcall(L, 0, 0, 0)) + lua_writestringerror("%s\n", luaL_tolstring(L, -1, NULL)); + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +static int db_traceback (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + const char *msg = lua_tostring(L, arg + 1); + if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ + lua_pushvalue(L, arg + 1); /* return it untouched */ + else { + int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0); + luaL_traceback(L, L1, msg, level); + } + return 1; +} + + +static int db_setcstacklimit (lua_State *L) { + int limit = (int)luaL_checkinteger(L, 1); + int res = lua_setcstacklimit(L, limit); + lua_pushinteger(L, res); + return 1; +} + + +static const luaL_Reg dblib[] = { + {"debug", db_debug}, + {"getuservalue", db_getuservalue}, + {"gethook", db_gethook}, + {"getinfo", db_getinfo}, + {"getlocal", db_getlocal}, + {"getregistry", db_getregistry}, + {"getmetatable", db_getmetatable}, + {"getupvalue", db_getupvalue}, + {"upvaluejoin", db_upvaluejoin}, + {"upvalueid", db_upvalueid}, + {"setuservalue", db_setuservalue}, + {"sethook", db_sethook}, + {"setlocal", db_setlocal}, + {"setmetatable", db_setmetatable}, + {"setupvalue", db_setupvalue}, + {"traceback", db_traceback}, + {"setcstacklimit", db_setcstacklimit}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_debug (lua_State *L) { + luaL_newlib(L, dblib); + return 1; +} + diff --git a/lua/ldebug.c b/lua/ldebug.c new file mode 100644 index 0000000..1feaab2 --- /dev/null +++ b/lua/ldebug.c @@ -0,0 +1,877 @@ +/* +** $Id: ldebug.c $ +** Debug Interface +** See Copyright Notice in lua.h +*/ + +#define ldebug_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lapi.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL) + + +static const char *funcnamefromcode (lua_State *L, CallInfo *ci, + const char **name); + + +static int currentpc (CallInfo *ci) { + lua_assert(isLua(ci)); + return pcRel(ci->u.l.savedpc, ci_func(ci)->p); +} + + +/* +** Get a "base line" to find the line corresponding to an instruction. +** Base lines are regularly placed at MAXIWTHABS intervals, so usually +** an integer division gets the right place. When the source file has +** large sequences of empty/comment lines, it may need extra entries, +** so the original estimate needs a correction. +** If the original estimate is -1, the initial 'if' ensures that the +** 'while' will run at least once. +** The assertion that the estimate is a lower bound for the correct base +** is valid as long as the debug info has been generated with the same +** value for MAXIWTHABS or smaller. (Previous releases use a little +** smaller value.) +*/ +static int getbaseline (const Proto *f, int pc, int *basepc) { + if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) { + *basepc = -1; /* start from the beginning */ + return f->linedefined; + } + else { + int i = cast_uint(pc) / MAXIWTHABS - 1; /* get an estimate */ + /* estimate must be a lower bond of the correct base */ + lua_assert(i < 0 || + (i < f->sizeabslineinfo && f->abslineinfo[i].pc <= pc)); + while (i + 1 < f->sizeabslineinfo && pc >= f->abslineinfo[i + 1].pc) + i++; /* low estimate; adjust it */ + *basepc = f->abslineinfo[i].pc; + return f->abslineinfo[i].line; + } +} + + +/* +** Get the line corresponding to instruction 'pc' in function 'f'; +** first gets a base line and from there does the increments until +** the desired instruction. +*/ +int luaG_getfuncline (const Proto *f, int pc) { + if (f->lineinfo == NULL) /* no debug information? */ + return -1; + else { + int basepc; + int baseline = getbaseline(f, pc, &basepc); + while (basepc++ < pc) { /* walk until given instruction */ + lua_assert(f->lineinfo[basepc] != ABSLINEINFO); + baseline += f->lineinfo[basepc]; /* correct line */ + } + return baseline; + } +} + + +static int getcurrentline (CallInfo *ci) { + return luaG_getfuncline(ci_func(ci)->p, currentpc(ci)); +} + + +/* +** Set 'trap' for all active Lua frames. +** This function can be called during a signal, under "reasonable" +** assumptions. A new 'ci' is completely linked in the list before it +** becomes part of the "active" list, and we assume that pointers are +** atomic; see comment in next function. +** (A compiler doing interprocedural optimizations could, theoretically, +** reorder memory writes in such a way that the list could be +** temporarily broken while inserting a new element. We simply assume it +** has no good reasons to do that.) +*/ +static void settraps (CallInfo *ci) { + for (; ci != NULL; ci = ci->previous) + if (isLua(ci)) + ci->u.l.trap = 1; +} + + +/* +** This function can be called during a signal, under "reasonable" +** assumptions. +** Fields 'basehookcount' and 'hookcount' (set by 'resethookcount') +** are for debug only, and it is no problem if they get arbitrary +** values (causes at most one wrong hook call). 'hookmask' is an atomic +** value. We assume that pointers are atomic too (e.g., gcc ensures that +** for all platforms where it runs). Moreover, 'hook' is always checked +** before being called (see 'luaD_hook'). +*/ +LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { + if (func == NULL || mask == 0) { /* turn off hooks? */ + mask = 0; + func = NULL; + } + L->hook = func; + L->basehookcount = count; + resethookcount(L); + L->hookmask = cast_byte(mask); + if (mask) + settraps(L->ci); /* to trace inside 'luaV_execute' */ +} + + +LUA_API lua_Hook lua_gethook (lua_State *L) { + return L->hook; +} + + +LUA_API int lua_gethookmask (lua_State *L) { + return L->hookmask; +} + + +LUA_API int lua_gethookcount (lua_State *L) { + return L->basehookcount; +} + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { + int status; + CallInfo *ci; + if (level < 0) return 0; /* invalid (negative) level */ + lua_lock(L); + for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) + level--; + if (level == 0 && ci != &L->base_ci) { /* level found? */ + status = 1; + ar->i_ci = ci; + } + else status = 0; /* no such level */ + lua_unlock(L); + return status; +} + + +static const char *upvalname (const Proto *p, int uv) { + TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); + if (s == NULL) return "?"; + else return getstr(s); +} + + +static const char *findvararg (CallInfo *ci, int n, StkId *pos) { + if (clLvalue(s2v(ci->func))->p->is_vararg) { + int nextra = ci->u.l.nextraargs; + if (n >= -nextra) { /* 'n' is negative */ + *pos = ci->func - nextra - (n + 1); + return "(vararg)"; /* generic name for any vararg */ + } + } + return NULL; /* no such vararg */ +} + + +const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { + StkId base = ci->func + 1; + const char *name = NULL; + if (isLua(ci)) { + if (n < 0) /* access to vararg values? */ + return findvararg(ci, n, pos); + else + name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); + } + if (name == NULL) { /* no 'standard' name? */ + StkId limit = (ci == L->ci) ? L->top : ci->next->func; + if (limit - base >= n && n > 0) { /* is 'n' inside 'ci' stack? */ + /* generic name for any valid slot */ + name = isLua(ci) ? "(temporary)" : "(C temporary)"; + } + else + return NULL; /* no name */ + } + if (pos) + *pos = base + (n - 1); + return name; +} + + +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { + const char *name; + lua_lock(L); + if (ar == NULL) { /* information about non-active function? */ + if (!isLfunction(s2v(L->top - 1))) /* not a Lua function? */ + name = NULL; + else /* consider live variables at function start (parameters) */ + name = luaF_getlocalname(clLvalue(s2v(L->top - 1))->p, n, 0); + } + else { /* active function; get information through 'ar' */ + StkId pos = NULL; /* to avoid warnings */ + name = luaG_findlocal(L, ar->i_ci, n, &pos); + if (name) { + setobjs2s(L, L->top, pos); + api_incr_top(L); + } + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + StkId pos = NULL; /* to avoid warnings */ + const char *name; + lua_lock(L); + name = luaG_findlocal(L, ar->i_ci, n, &pos); + if (name) { + setobjs2s(L, pos, L->top - 1); + L->top--; /* pop value */ + } + lua_unlock(L); + return name; +} + + +static void funcinfo (lua_Debug *ar, Closure *cl) { + if (noLuaClosure(cl)) { + ar->source = "=[C]"; + ar->srclen = LL("=[C]"); + ar->linedefined = -1; + ar->lastlinedefined = -1; + ar->what = "C"; + } + else { + const Proto *p = cl->l.p; + if (p->source) { + ar->source = getstr(p->source); + ar->srclen = tsslen(p->source); + } + else { + ar->source = "=?"; + ar->srclen = LL("=?"); + } + ar->linedefined = p->linedefined; + ar->lastlinedefined = p->lastlinedefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } + luaO_chunkid(ar->short_src, ar->source, ar->srclen); +} + + +static int nextline (const Proto *p, int currentline, int pc) { + if (p->lineinfo[pc] != ABSLINEINFO) + return currentline + p->lineinfo[pc]; + else + return luaG_getfuncline(p, pc); +} + + +static void collectvalidlines (lua_State *L, Closure *f) { + if (noLuaClosure(f)) { + setnilvalue(s2v(L->top)); + api_incr_top(L); + } + else { + int i; + TValue v; + const Proto *p = f->l.p; + int currentline = p->linedefined; + Table *t = luaH_new(L); /* new table to store active lines */ + sethvalue2s(L, L->top, t); /* push it on stack */ + api_incr_top(L); + setbtvalue(&v); /* boolean 'true' to be the value of all indices */ + for (i = 0; i < p->sizelineinfo; i++) { /* for all instructions */ + currentline = nextline(p, currentline, i); /* get its line */ + luaH_setint(L, t, currentline, &v); /* table[line] = true */ + } + } +} + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { + if (ci == NULL) /* no 'ci'? */ + return NULL; /* no info */ + else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */ + *name = "__gc"; + return "metamethod"; /* report it as such */ + } + /* calling function is a known Lua function? */ + else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) + return funcnamefromcode(L, ci->previous, name); + else return NULL; /* no way to find a name */ +} + + +static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, + Closure *f, CallInfo *ci) { + int status = 1; + for (; *what; what++) { + switch (*what) { + case 'S': { + funcinfo(ar, f); + break; + } + case 'l': { + ar->currentline = (ci && isLua(ci)) ? getcurrentline(ci) : -1; + break; + } + case 'u': { + ar->nups = (f == NULL) ? 0 : f->c.nupvalues; + if (noLuaClosure(f)) { + ar->isvararg = 1; + ar->nparams = 0; + } + else { + ar->isvararg = f->l.p->is_vararg; + ar->nparams = f->l.p->numparams; + } + break; + } + case 't': { + ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; + break; + } + case 'n': { + ar->namewhat = getfuncname(L, ci, &ar->name); + if (ar->namewhat == NULL) { + ar->namewhat = ""; /* not found */ + ar->name = NULL; + } + break; + } + case 'r': { + if (ci == NULL || !(ci->callstatus & CIST_TRAN)) + ar->ftransfer = ar->ntransfer = 0; + else { + ar->ftransfer = ci->u2.transferinfo.ftransfer; + ar->ntransfer = ci->u2.transferinfo.ntransfer; + } + break; + } + case 'L': + case 'f': /* handled by lua_getinfo */ + break; + default: status = 0; /* invalid option */ + } + } + return status; +} + + +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { + int status; + Closure *cl; + CallInfo *ci; + TValue *func; + lua_lock(L); + if (*what == '>') { + ci = NULL; + func = s2v(L->top - 1); + api_check(L, ttisfunction(func), "function expected"); + what++; /* skip the '>' */ + L->top--; /* pop function */ + } + else { + ci = ar->i_ci; + func = s2v(ci->func); + lua_assert(ttisfunction(func)); + } + cl = ttisclosure(func) ? clvalue(func) : NULL; + status = auxgetinfo(L, what, ar, cl, ci); + if (strchr(what, 'f')) { + setobj2s(L, L->top, func); + api_incr_top(L); + } + if (strchr(what, 'L')) + collectvalidlines(L, cl); + lua_unlock(L); + return status; +} + + +/* +** {====================================================== +** Symbolic Execution +** ======================================================= +*/ + +static const char *getobjname (const Proto *p, int lastpc, int reg, + const char **name); + + +/* +** Find a "name" for the constant 'c'. +*/ +static void kname (const Proto *p, int c, const char **name) { + TValue *kvalue = &p->k[c]; + *name = (ttisstring(kvalue)) ? svalue(kvalue) : "?"; +} + + +/* +** Find a "name" for the register 'c'. +*/ +static void rname (const Proto *p, int pc, int c, const char **name) { + const char *what = getobjname(p, pc, c, name); /* search for 'c' */ + if (!(what && *what == 'c')) /* did not find a constant name? */ + *name = "?"; +} + + +/* +** Find a "name" for a 'C' value in an RK instruction. +*/ +static void rkname (const Proto *p, int pc, Instruction i, const char **name) { + int c = GETARG_C(i); /* key index */ + if (GETARG_k(i)) /* is 'c' a constant? */ + kname(p, c, name); + else /* 'c' is a register */ + rname(p, pc, c, name); +} + + +static int filterpc (int pc, int jmptarget) { + if (pc < jmptarget) /* is code conditional (inside a jump)? */ + return -1; /* cannot know who sets that register */ + else return pc; /* current position sets that register */ +} + + +/* +** Try to find last instruction before 'lastpc' that modified register 'reg'. +*/ +static int findsetreg (const Proto *p, int lastpc, int reg) { + int pc; + int setreg = -1; /* keep last instruction that changed 'reg' */ + int jmptarget = 0; /* any code before this address is conditional */ + if (testMMMode(GET_OPCODE(p->code[lastpc]))) + lastpc--; /* previous instruction was not actually executed */ + for (pc = 0; pc < lastpc; pc++) { + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + int a = GETARG_A(i); + int change; /* true if current instruction changed 'reg' */ + switch (op) { + case OP_LOADNIL: { /* set registers from 'a' to 'a+b' */ + int b = GETARG_B(i); + change = (a <= reg && reg <= a + b); + break; + } + case OP_TFORCALL: { /* affect all regs above its base */ + change = (reg >= a + 2); + break; + } + case OP_CALL: + case OP_TAILCALL: { /* affect all registers above base */ + change = (reg >= a); + break; + } + case OP_JMP: { /* doesn't change registers, but changes 'jmptarget' */ + int b = GETARG_sJ(i); + int dest = pc + 1 + b; + /* jump does not skip 'lastpc' and is larger than current one? */ + if (dest <= lastpc && dest > jmptarget) + jmptarget = dest; /* update 'jmptarget' */ + change = 0; + break; + } + default: /* any instruction that sets A */ + change = (testAMode(op) && reg == a); + break; + } + if (change) + setreg = filterpc(pc, jmptarget); + } + return setreg; +} + + +/* +** Check whether table being indexed by instruction 'i' is the +** environment '_ENV' +*/ +static const char *gxf (const Proto *p, int pc, Instruction i, int isup) { + int t = GETARG_B(i); /* table index */ + const char *name; /* name of indexed variable */ + if (isup) /* is an upvalue? */ + name = upvalname(p, t); + else + getobjname(p, pc, t, &name); + return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field"; +} + + +static const char *getobjname (const Proto *p, int lastpc, int reg, + const char **name) { + int pc; + *name = luaF_getlocalname(p, reg + 1, lastpc); + if (*name) /* is a local? */ + return "local"; + /* else try symbolic execution */ + pc = findsetreg(p, lastpc, reg); + if (pc != -1) { /* could find instruction? */ + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + switch (op) { + case OP_MOVE: { + int b = GETARG_B(i); /* move from 'b' to 'a' */ + if (b < GETARG_A(i)) + return getobjname(p, pc, b, name); /* get name for 'b' */ + break; + } + case OP_GETTABUP: { + int k = GETARG_C(i); /* key index */ + kname(p, k, name); + return gxf(p, pc, i, 1); + } + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + rname(p, pc, k, name); + return gxf(p, pc, i, 0); + } + case OP_GETI: { + *name = "integer index"; + return "field"; + } + case OP_GETFIELD: { + int k = GETARG_C(i); /* key index */ + kname(p, k, name); + return gxf(p, pc, i, 0); + } + case OP_GETUPVAL: { + *name = upvalname(p, GETARG_B(i)); + return "upvalue"; + } + case OP_LOADK: + case OP_LOADKX: { + int b = (op == OP_LOADK) ? GETARG_Bx(i) + : GETARG_Ax(p->code[pc + 1]); + if (ttisstring(&p->k[b])) { + *name = svalue(&p->k[b]); + return "constant"; + } + break; + } + case OP_SELF: { + rkname(p, pc, i, name); + return "method"; + } + default: break; /* go through to return NULL */ + } + } + return NULL; /* could not find reasonable name */ +} + + +/* +** Try to find a name for a function based on the code that called it. +** (Only works when function was called by a Lua function.) +** Returns what the name is (e.g., "for iterator", "method", +** "metamethod") and sets '*name' to point to the name. +*/ +static const char *funcnamefromcode (lua_State *L, CallInfo *ci, + const char **name) { + TMS tm = (TMS)0; /* (initial value avoids warnings) */ + const Proto *p = ci_func(ci)->p; /* calling function */ + int pc = currentpc(ci); /* calling instruction index */ + Instruction i = p->code[pc]; /* calling instruction */ + if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ + *name = "?"; + return "hook"; + } + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: + return getobjname(p, pc, GETARG_A(i), name); /* get function name */ + case OP_TFORCALL: { /* for iterator */ + *name = "for iterator"; + return "for iterator"; + } + /* other instructions can do calls through metamethods */ + case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: + case OP_GETI: case OP_GETFIELD: + tm = TM_INDEX; + break; + case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD: + tm = TM_NEWINDEX; + break; + case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: { + tm = cast(TMS, GETARG_C(i)); + break; + } + case OP_UNM: tm = TM_UNM; break; + case OP_BNOT: tm = TM_BNOT; break; + case OP_LEN: tm = TM_LEN; break; + case OP_CONCAT: tm = TM_CONCAT; break; + case OP_EQ: tm = TM_EQ; break; + /* no cases for OP_EQI and OP_EQK, as they don't call metamethods */ + case OP_LT: case OP_LTI: case OP_GTI: tm = TM_LT; break; + case OP_LE: case OP_LEI: case OP_GEI: tm = TM_LE; break; + case OP_CLOSE: case OP_RETURN: tm = TM_CLOSE; break; + default: + return NULL; /* cannot find a reasonable name */ + } + *name = getstr(G(L)->tmname[tm]) + 2; + return "metamethod"; +} + +/* }====================================================== */ + + + +/* +** Check whether pointer 'o' points to some value in the stack +** frame of the current function. Because 'o' may not point to a +** value in this stack, we cannot compare it with the region +** boundaries (undefined behaviour in ISO C). +*/ +static int isinstack (CallInfo *ci, const TValue *o) { + StkId pos; + for (pos = ci->func + 1; pos < ci->top; pos++) { + if (o == s2v(pos)) + return 1; + } + return 0; /* not found */ +} + + +/* +** Checks whether value 'o' came from an upvalue. (That can only happen +** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on +** upvalues.) +*/ +static const char *getupvalname (CallInfo *ci, const TValue *o, + const char **name) { + LClosure *c = ci_func(ci); + int i; + for (i = 0; i < c->nupvalues; i++) { + if (c->upvals[i]->v == o) { + *name = upvalname(c->p, i); + return "upvalue"; + } + } + return NULL; +} + + +static const char *varinfo (lua_State *L, const TValue *o) { + const char *name = NULL; /* to avoid warnings */ + CallInfo *ci = L->ci; + const char *kind = NULL; + if (isLua(ci)) { + kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ + if (!kind && isinstack(ci, o)) /* no? try a register */ + kind = getobjname(ci_func(ci)->p, currentpc(ci), + cast_int(cast(StkId, o) - (ci->func + 1)), &name); + } + return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : ""; +} + + +l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + const char *t = luaT_objtypename(L, o); + luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o)); +} + + +l_noret luaG_callerror (lua_State *L, const TValue *o) { + CallInfo *ci = L->ci; + const char *name = NULL; /* to avoid warnings */ + const char *what = (isLua(ci)) ? funcnamefromcode(L, ci, &name) : NULL; + if (what != NULL) { + const char *t = luaT_objtypename(L, o); + luaG_runerror(L, "%s '%s' is not callable (a %s value)", what, name, t); + } + else + luaG_typeerror(L, o, "call"); +} + + +l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) { + luaG_runerror(L, "bad 'for' %s (number expected, got %s)", + what, luaT_objtypename(L, o)); +} + + +l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { + if (ttisstring(p1) || cvt2str(p1)) p1 = p2; + luaG_typeerror(L, p1, "concatenate"); +} + + +l_noret luaG_opinterror (lua_State *L, const TValue *p1, + const TValue *p2, const char *msg) { + if (!ttisnumber(p1)) /* first operand is wrong? */ + p2 = p1; /* now second is wrong */ + luaG_typeerror(L, p2, msg); +} + + +/* +** Error when both values are convertible to numbers, but not to integers +*/ +l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { + lua_Integer temp; + if (!luaV_tointegerns(p1, &temp, LUA_FLOORN2I)) + p2 = p1; + luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); +} + + +l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { + const char *t1 = luaT_objtypename(L, p1); + const char *t2 = luaT_objtypename(L, p2); + if (strcmp(t1, t2) == 0) + luaG_runerror(L, "attempt to compare two %s values", t1); + else + luaG_runerror(L, "attempt to compare %s with %s", t1, t2); +} + + +/* add src:line information to 'msg' */ +const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, + int line) { + char buff[LUA_IDSIZE]; + if (src) + luaO_chunkid(buff, getstr(src), tsslen(src)); + else { /* no source available; use "?" instead */ + buff[0] = '?'; buff[1] = '\0'; + } + return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); +} + + +l_noret luaG_errormsg (lua_State *L) { + if (L->errfunc != 0) { /* is there an error handling function? */ + StkId errfunc = restorestack(L, L->errfunc); + lua_assert(ttisfunction(s2v(errfunc))); + setobjs2s(L, L->top, L->top - 1); /* move argument */ + setobjs2s(L, L->top - 1, errfunc); /* push function */ + L->top++; /* assume EXTRA_STACK */ + luaD_callnoyield(L, L->top - 2, 1); /* call it */ + } + luaD_throw(L, LUA_ERRRUN); +} + + +l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { + CallInfo *ci = L->ci; + const char *msg; + va_list argp; + luaC_checkGC(L); /* error message uses memory */ + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); /* format message */ + va_end(argp); + if (isLua(ci)) /* if Lua function, add source:line information */ + luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci)); + luaG_errormsg(L); +} + + +/* +** Check whether new instruction 'newpc' is in a different line from +** previous instruction 'oldpc'. More often than not, 'newpc' is only +** one or a few instructions after 'oldpc' (it must be after, see +** caller), so try to avoid calling 'luaG_getfuncline'. If they are +** too far apart, there is a good chance of a ABSLINEINFO in the way, +** so it goes directly to 'luaG_getfuncline'. +*/ +static int changedline (const Proto *p, int oldpc, int newpc) { + if (p->lineinfo == NULL) /* no debug information? */ + return 0; + if (newpc - oldpc < MAXIWTHABS / 2) { /* not too far apart? */ + int delta = 0; /* line diference */ + int pc = oldpc; + for (;;) { + int lineinfo = p->lineinfo[++pc]; + if (lineinfo == ABSLINEINFO) + break; /* cannot compute delta; fall through */ + delta += lineinfo; + if (pc == newpc) + return (delta != 0); /* delta computed successfully */ + } + } + /* either instructions are too far apart or there is an absolute line + info in the way; compute line difference explicitly */ + return (luaG_getfuncline(p, oldpc) != luaG_getfuncline(p, newpc)); +} + + +/* +** Traces the execution of a Lua function. Called before the execution +** of each opcode, when debug is on. 'L->oldpc' stores the last +** instruction traced, to detect line changes. When entering a new +** function, 'npci' will be zero and will test as a new line whatever +** the value of 'oldpc'. Some exceptional conditions may return to +** a function without setting 'oldpc'. In that case, 'oldpc' may be +** invalid; if so, use zero as a valid value. (A wrong but valid 'oldpc' +** at most causes an extra call to a line hook.) +** This function is not "Protected" when called, so it should correct +** 'L->top' before calling anything that can run the GC. +*/ +int luaG_traceexec (lua_State *L, const Instruction *pc) { + CallInfo *ci = L->ci; + lu_byte mask = L->hookmask; + const Proto *p = ci_func(ci)->p; + int counthook; + if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */ + ci->u.l.trap = 0; /* don't need to stop again */ + return 0; /* turn off 'trap' */ + } + pc++; /* reference is always next instruction */ + ci->u.l.savedpc = pc; /* save 'pc' */ + counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); + if (counthook) + resethookcount(L); /* reset count */ + else if (!(mask & LUA_MASKLINE)) + return 1; /* no line hook and count != 0; nothing to be done now */ + if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ + ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ + return 1; /* do not call hook again (VM yielded, so it did not move) */ + } + if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */ + L->top = ci->top; /* correct top */ + if (counthook) + luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */ + if (mask & LUA_MASKLINE) { + /* 'L->oldpc' may be invalid; use zero in this case */ + int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0; + int npci = pcRel(pc, p); + if (npci <= oldpc || /* call hook when jump back (loop), */ + changedline(p, oldpc, npci)) { /* or when enter new line */ + int newline = luaG_getfuncline(p, npci); + luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */ + } + L->oldpc = npci; /* 'pc' of last call to line hook */ + } + if (L->status == LUA_YIELD) { /* did hook yield? */ + if (counthook) + L->hookcount = 1; /* undo decrement to zero */ + ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ + ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ + luaD_throw(L, LUA_YIELD); + } + return 1; /* keep 'trap' on */ +} + diff --git a/lua/ldebug.h b/lua/ldebug.h new file mode 100644 index 0000000..974960e --- /dev/null +++ b/lua/ldebug.h @@ -0,0 +1,63 @@ +/* +** $Id: ldebug.h $ +** Auxiliary functions from Debug Interface module +** See Copyright Notice in lua.h +*/ + +#ifndef ldebug_h +#define ldebug_h + + +#include "lstate.h" + + +#define pcRel(pc, p) (cast_int((pc) - (p)->code) - 1) + + +/* Active Lua function (given call info) */ +#define ci_func(ci) (clLvalue(s2v((ci)->func))) + + +#define resethookcount(L) (L->hookcount = L->basehookcount) + +/* +** mark for entries in 'lineinfo' array that has absolute information in +** 'abslineinfo' array +*/ +#define ABSLINEINFO (-0x80) + + +/* +** MAXimum number of successive Instructions WiTHout ABSolute line +** information. (A power of two allows fast divisions.) +*/ +#if !defined(MAXIWTHABS) +#define MAXIWTHABS 128 +#endif + + +LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc); +LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, + StkId *pos); +LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, + const char *opname); +LUAI_FUNC l_noret luaG_callerror (lua_State *L, const TValue *o); +LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o, + const char *what); +LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, + const TValue *p2, + const char *msg); +LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg, + TString *src, int line); +LUAI_FUNC l_noret luaG_errormsg (lua_State *L); +LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); + + +#endif diff --git a/lua/ldo.c b/lua/ldo.c new file mode 100644 index 0000000..7135079 --- /dev/null +++ b/lua/ldo.c @@ -0,0 +1,963 @@ +/* +** $Id: ldo.c $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#define ldo_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" +#include "lzio.h" + + + +#define errorstatus(s) ((s) > LUA_YIELD) + + +/* +** {====================================================== +** Error-recovery functions +** ======================================================= +*/ + +/* +** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By +** default, Lua handles errors with exceptions when compiling as +** C++ code, with _longjmp/_setjmp when asked to use them, and with +** longjmp/setjmp otherwise. +*/ +#if !defined(LUAI_THROW) /* { */ + +#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) /* { */ + +/* C++ exceptions */ +#define LUAI_THROW(L,c) throw(c) +#define LUAI_TRY(L,c,a) \ + try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy variable */ + +#elif defined(LUA_USE_POSIX) /* }{ */ + +/* in POSIX, try _longjmp/_setjmp (more efficient) */ +#define LUAI_THROW(L,c) _longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#else /* }{ */ + +/* ISO C handling with long jumps */ +#define LUAI_THROW(L,c) longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#endif /* } */ + +#endif /* } */ + + + +/* chain list of long jump buffers */ +struct lua_longjmp { + struct lua_longjmp *previous; + luai_jmpbuf b; + volatile int status; /* error code */ +}; + + +void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { + switch (errcode) { + case LUA_ERRMEM: { /* memory error? */ + setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ + break; + } + case LUA_ERRERR: { + setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); + break; + } + case LUA_OK: { /* special case only for closing upvalues */ + setnilvalue(s2v(oldtop)); /* no error message */ + break; + } + default: { + lua_assert(errorstatus(errcode)); /* real error */ + setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + break; + } + } + L->top = oldtop + 1; +} + + +l_noret luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { /* thread has an error handler? */ + L->errorJmp->status = errcode; /* set status */ + LUAI_THROW(L, L->errorJmp); /* jump to it */ + } + else { /* thread has no error handler */ + global_State *g = G(L); + errcode = luaE_resetthread(L, errcode); /* close all upvalues */ + if (g->mainthread->errorJmp) { /* main thread has a handler? */ + setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ + luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ + } + else { /* no handler at all; abort */ + if (g->panic) { /* panic function? */ + lua_unlock(L); + g->panic(L); /* call panic function (last chance to jump out) */ + } + abort(); + } + } +} + + +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + l_uint32 oldnCcalls = L->nCcalls; + struct lua_longjmp lj; + lj.status = LUA_OK; + lj.previous = L->errorJmp; /* chain new error handler */ + L->errorJmp = &lj; + LUAI_TRY(L, &lj, + (*f)(L, ud); + ); + L->errorJmp = lj.previous; /* restore old error handler */ + L->nCcalls = oldnCcalls; + return lj.status; +} + +/* }====================================================== */ + + +/* +** {================================================================== +** Stack reallocation +** =================================================================== +*/ +static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { + CallInfo *ci; + UpVal *up; + L->top = (L->top - oldstack) + newstack; + L->tbclist = (L->tbclist - oldstack) + newstack; + for (up = L->openupval; up != NULL; up = up->u.open.next) + up->v = s2v((uplevel(up) - oldstack) + newstack); + for (ci = L->ci; ci != NULL; ci = ci->previous) { + ci->top = (ci->top - oldstack) + newstack; + ci->func = (ci->func - oldstack) + newstack; + if (isLua(ci)) + ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ + } +} + + +/* some space for error handling */ +#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) + + +/* +** Reallocate the stack to a new size, correcting all pointers into +** it. (There are pointers to a stack from its upvalues, from its list +** of call infos, plus a few individual pointers.) The reallocation is +** done in two steps (allocation + free) because the correction must be +** done while both addresses (the old stack and the new one) are valid. +** (In ISO C, any pointer use after the pointer has been deallocated is +** undefined behavior.) +** In case of allocation error, raise an error or return false according +** to 'raiseerror'. +*/ +int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { + int oldsize = stacksize(L); + int i; + StkId newstack = luaM_reallocvector(L, NULL, 0, + newsize + EXTRA_STACK, StackValue); + lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); + if (l_unlikely(newstack == NULL)) { /* reallocation failed? */ + if (raiseerror) + luaM_error(L); + else return 0; /* do not raise an error */ + } + /* number of elements to be copied to the new stack */ + i = ((oldsize <= newsize) ? oldsize : newsize) + EXTRA_STACK; + memcpy(newstack, L->stack, i * sizeof(StackValue)); + for (; i < newsize + EXTRA_STACK; i++) + setnilvalue(s2v(newstack + i)); /* erase new segment */ + correctstack(L, L->stack, newstack); + luaM_freearray(L, L->stack, oldsize + EXTRA_STACK); + L->stack = newstack; + L->stack_last = L->stack + newsize; + return 1; +} + + +/* +** Try to grow the stack by at least 'n' elements. when 'raiseerror' +** is true, raises any error; otherwise, return 0 in case of errors. +*/ +int luaD_growstack (lua_State *L, int n, int raiseerror) { + int size = stacksize(L); + if (l_unlikely(size > LUAI_MAXSTACK)) { + /* if stack is larger than maximum, thread is already using the + extra space reserved for errors, that is, thread is handling + a stack error; cannot grow further than that. */ + lua_assert(stacksize(L) == ERRORSTACKSIZE); + if (raiseerror) + luaD_throw(L, LUA_ERRERR); /* error inside message handler */ + return 0; /* if not 'raiseerror', just signal it */ + } + else { + int newsize = 2 * size; /* tentative new size */ + int needed = cast_int(L->top - L->stack) + n; + if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */ + newsize = LUAI_MAXSTACK; + if (newsize < needed) /* but must respect what was asked for */ + newsize = needed; + if (l_likely(newsize <= LUAI_MAXSTACK)) + return luaD_reallocstack(L, newsize, raiseerror); + else { /* stack overflow */ + /* add extra size to be able to handle the error message */ + luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); + if (raiseerror) + luaG_runerror(L, "stack overflow"); + return 0; + } + } +} + + +static int stackinuse (lua_State *L) { + CallInfo *ci; + int res; + StkId lim = L->top; + for (ci = L->ci; ci != NULL; ci = ci->previous) { + if (lim < ci->top) lim = ci->top; + } + lua_assert(lim <= L->stack_last); + res = cast_int(lim - L->stack) + 1; /* part of stack in use */ + if (res < LUA_MINSTACK) + res = LUA_MINSTACK; /* ensure a minimum size */ + return res; +} + + +/* +** If stack size is more than 3 times the current use, reduce that size +** to twice the current use. (So, the final stack size is at most 2/3 the +** previous size, and half of its entries are empty.) +** As a particular case, if stack was handling a stack overflow and now +** it is not, 'max' (limited by LUAI_MAXSTACK) will be smaller than +** stacksize (equal to ERRORSTACKSIZE in this case), and so the stack +** will be reduced to a "regular" size. +*/ +void luaD_shrinkstack (lua_State *L) { + int inuse = stackinuse(L); + int nsize = inuse * 2; /* proposed new size */ + int max = inuse * 3; /* maximum "reasonable" size */ + if (max > LUAI_MAXSTACK) { + max = LUAI_MAXSTACK; /* respect stack limit */ + if (nsize > LUAI_MAXSTACK) + nsize = LUAI_MAXSTACK; + } + /* if thread is currently not handling a stack overflow and its + size is larger than maximum "reasonable" size, shrink it */ + if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) + luaD_reallocstack(L, nsize, 0); /* ok if that fails */ + else /* don't change stack */ + condmovestack(L,{},{}); /* (change only for debugging) */ + luaE_shrinkCI(L); /* shrink CI list */ +} + + +void luaD_inctop (lua_State *L) { + luaD_checkstack(L, 1); + L->top++; +} + +/* }================================================================== */ + + +/* +** Call a hook for the given event. Make sure there is a hook to be +** called. (Both 'L->hook' and 'L->hookmask', which trigger this +** function, can be changed asynchronously by signals.) +*/ +void luaD_hook (lua_State *L, int event, int line, + int ftransfer, int ntransfer) { + lua_Hook hook = L->hook; + if (hook && L->allowhook) { /* make sure there is a hook */ + int mask = CIST_HOOKED; + CallInfo *ci = L->ci; + ptrdiff_t top = savestack(L, L->top); /* preserve original 'top' */ + ptrdiff_t ci_top = savestack(L, ci->top); /* idem for 'ci->top' */ + lua_Debug ar; + ar.event = event; + ar.currentline = line; + ar.i_ci = ci; + if (ntransfer != 0) { + mask |= CIST_TRAN; /* 'ci' has transfer information */ + ci->u2.transferinfo.ftransfer = ftransfer; + ci->u2.transferinfo.ntransfer = ntransfer; + } + if (isLua(ci) && L->top < ci->top) + L->top = ci->top; /* protect entire activation register */ + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + if (ci->top < L->top + LUA_MINSTACK) + ci->top = L->top + LUA_MINSTACK; + L->allowhook = 0; /* cannot call hooks inside a hook */ + ci->callstatus |= mask; + lua_unlock(L); + (*hook)(L, &ar); + lua_lock(L); + lua_assert(!L->allowhook); + L->allowhook = 1; + ci->top = restorestack(L, ci_top); + L->top = restorestack(L, top); + ci->callstatus &= ~mask; + } +} + + +/* +** Executes a call hook for Lua functions. This function is called +** whenever 'hookmask' is not zero, so it checks whether call hooks are +** active. +*/ +void luaD_hookcall (lua_State *L, CallInfo *ci) { + L->oldpc = 0; /* set 'oldpc' for new function */ + if (L->hookmask & LUA_MASKCALL) { /* is call hook on? */ + int event = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL + : LUA_HOOKCALL; + Proto *p = ci_func(ci)->p; + ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ + luaD_hook(L, event, -1, 1, p->numparams); + ci->u.l.savedpc--; /* correct 'pc' */ + } +} + + +/* +** Executes a return hook for Lua and C functions and sets/corrects +** 'oldpc'. (Note that this correction is needed by the line hook, so it +** is done even when return hooks are off.) +*/ +static void rethook (lua_State *L, CallInfo *ci, int nres) { + if (L->hookmask & LUA_MASKRET) { /* is return hook on? */ + StkId firstres = L->top - nres; /* index of first result */ + int delta = 0; /* correction for vararg functions */ + int ftransfer; + if (isLua(ci)) { + Proto *p = ci_func(ci)->p; + if (p->is_vararg) + delta = ci->u.l.nextraargs + p->numparams + 1; + } + ci->func += delta; /* if vararg, back to virtual 'func' */ + ftransfer = cast(unsigned short, firstres - ci->func); + luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */ + ci->func -= delta; + } + if (isLua(ci = ci->previous)) + L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* set 'oldpc' */ +} + + +/* +** Check whether 'func' has a '__call' metafield. If so, put it in the +** stack, below original 'func', so that 'luaD_precall' can call it. Raise +** an error if there is no '__call' metafield. +*/ +void luaD_tryfuncTM (lua_State *L, StkId func) { + const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); + StkId p; + if (l_unlikely(ttisnil(tm))) + luaG_callerror(L, s2v(func)); /* nothing to call */ + for (p = L->top; p > func; p--) /* open space for metamethod */ + setobjs2s(L, p, p-1); + L->top++; /* stack space pre-allocated by the caller */ + setobj2s(L, func, tm); /* metamethod is the new function to be called */ +} + + +/* +** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'. +** Handle most typical cases (zero results for commands, one result for +** expressions, multiple results for tail calls/single parameters) +** separated. +*/ +static void moveresults (lua_State *L, StkId res, int nres, int wanted) { + StkId firstresult; + int i; + switch (wanted) { /* handle typical cases separately */ + case 0: /* no values needed */ + L->top = res; + return; + case 1: /* one value needed */ + if (nres == 0) /* no results? */ + setnilvalue(s2v(res)); /* adjust with nil */ + else /* at least one result */ + setobjs2s(L, res, L->top - nres); /* move it to proper place */ + L->top = res + 1; + return; + case LUA_MULTRET: + wanted = nres; /* we want all results */ + break; + default: /* two/more results and/or to-be-closed variables */ + if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ + ptrdiff_t savedres = savestack(L, res); + L->ci->callstatus |= CIST_CLSRET; /* in case of yields */ + L->ci->u2.nres = nres; + luaF_close(L, res, CLOSEKTOP, 1); + L->ci->callstatus &= ~CIST_CLSRET; + if (L->hookmask) /* if needed, call hook after '__close's */ + rethook(L, L->ci, nres); + res = restorestack(L, savedres); /* close and hook can move stack */ + wanted = decodeNresults(wanted); + if (wanted == LUA_MULTRET) + wanted = nres; /* we want all results */ + } + break; + } + /* generic case */ + firstresult = L->top - nres; /* index of first result */ + if (nres > wanted) /* extra results? */ + nres = wanted; /* don't need them */ + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstresult + i); + for (; i < wanted; i++) /* complete wanted number of results */ + setnilvalue(s2v(res + i)); + L->top = res + wanted; /* top points after the last result */ +} + + +/* +** Finishes a function call: calls hook if necessary, moves current +** number of results to proper place, and returns to previous call +** info. If function has to close variables, hook must be called after +** that. +*/ +void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { + int wanted = ci->nresults; + if (l_unlikely(L->hookmask && !hastocloseCfunc(wanted))) + rethook(L, ci, nres); + /* move results to proper place */ + moveresults(L, ci->func, nres, wanted); + /* function cannot be in any of these cases when returning */ + lua_assert(!(ci->callstatus & + (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET))); + L->ci = ci->previous; /* back to caller (after closing variables) */ +} + + + +#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) + + +/* +** Prepare a function for a tail call, building its call info on top +** of the current call info. 'narg1' is the number of arguments plus 1 +** (so that it includes the function itself). +*/ +void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { + Proto *p = clLvalue(s2v(func))->p; + int fsize = p->maxstacksize; /* frame size */ + int nfixparams = p->numparams; + int i; + for (i = 0; i < narg1; i++) /* move down function and arguments */ + setobjs2s(L, ci->func + i, func + i); + checkstackGC(L, fsize); + func = ci->func; /* moved-down function */ + for (; narg1 <= nfixparams; narg1++) + setnilvalue(s2v(func + narg1)); /* complete missing arguments */ + ci->top = func + 1 + fsize; /* top for new function */ + lua_assert(ci->top <= L->stack_last); + ci->u.l.savedpc = p->code; /* starting point */ + ci->callstatus |= CIST_TAIL; + L->top = func + narg1; /* set top */ +} + + +/* +** Prepares the call to a function (C or Lua). For C functions, also do +** the call. The function to be called is at '*func'. The arguments +** are on the stack, right after the function. Returns the CallInfo +** to be executed, if it was a Lua function. Otherwise (a C function) +** returns NULL, with all the results on the stack, starting at the +** original function position. +*/ +CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { + lua_CFunction f; + retry: + switch (ttypetag(s2v(func))) { + case LUA_VCCL: /* C closure */ + f = clCvalue(s2v(func))->f; + goto Cfunc; + case LUA_VLCF: /* light C function */ + f = fvalue(s2v(func)); + Cfunc: { + int n; /* number of returns */ + CallInfo *ci; + checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ + L->ci = ci = next_ci(L); + ci->nresults = nresults; + ci->callstatus = CIST_C; + ci->top = L->top + LUA_MINSTACK; + ci->func = func; + lua_assert(ci->top <= L->stack_last); + if (l_unlikely(L->hookmask & LUA_MASKCALL)) { + int narg = cast_int(L->top - func) - 1; + luaD_hook(L, LUA_HOOKCALL, -1, 1, narg); + } + lua_unlock(L); + n = (*f)(L); /* do the actual call */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, ci, n); + return NULL; + } + case LUA_VLCL: { /* Lua function */ + CallInfo *ci; + Proto *p = clLvalue(s2v(func))->p; + int narg = cast_int(L->top - func) - 1; /* number of real arguments */ + int nfixparams = p->numparams; + int fsize = p->maxstacksize; /* frame size */ + checkstackGCp(L, fsize, func); + L->ci = ci = next_ci(L); + ci->nresults = nresults; + ci->u.l.savedpc = p->code; /* starting point */ + ci->top = func + 1 + fsize; + ci->func = func; + L->ci = ci; + for (; narg < nfixparams; narg++) + setnilvalue(s2v(L->top++)); /* complete missing arguments */ + lua_assert(ci->top <= L->stack_last); + return ci; + } + default: { /* not a function */ + checkstackGCp(L, 1, func); /* space for metamethod */ + luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ + goto retry; /* try again with metamethod */ + } + } +} + + +/* +** Call a function (C or Lua) through C. 'inc' can be 1 (increment +** number of recursive invocations in the C stack) or nyci (the same +** plus increment number of non-yieldable calls). +*/ +static void ccall (lua_State *L, StkId func, int nResults, int inc) { + CallInfo *ci; + L->nCcalls += inc; + if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) + luaE_checkcstack(L); + if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ + ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ + luaV_execute(L, ci); /* call it */ + } + L->nCcalls -= inc; +} + + +/* +** External interface for 'ccall' +*/ +void luaD_call (lua_State *L, StkId func, int nResults) { + ccall(L, func, nResults, 1); +} + + +/* +** Similar to 'luaD_call', but does not allow yields during the call. +*/ +void luaD_callnoyield (lua_State *L, StkId func, int nResults) { + ccall(L, func, nResults, nyci); +} + + +/* +** Finish the job of 'lua_pcallk' after it was interrupted by an yield. +** (The caller, 'finishCcall', does the final call to 'adjustresults'.) +** The main job is to complete the 'luaD_pcall' called by 'lua_pcallk'. +** If a '__close' method yields here, eventually control will be back +** to 'finishCcall' (when that '__close' method finally returns) and +** 'finishpcallk' will run again and close any still pending '__close' +** methods. Similarly, if a '__close' method errs, 'precover' calls +** 'unroll' which calls ''finishCcall' and we are back here again, to +** close any pending '__close' methods. +** Note that, up to the call to 'luaF_close', the corresponding +** 'CallInfo' is not modified, so that this repeated run works like the +** first one (except that it has at least one less '__close' to do). In +** particular, field CIST_RECST preserves the error status across these +** multiple runs, changing only if there is a new error. +*/ +static int finishpcallk (lua_State *L, CallInfo *ci) { + int status = getcistrecst(ci); /* get original status */ + if (l_likely(status == LUA_OK)) /* no error? */ + status = LUA_YIELD; /* was interrupted by an yield */ + else { /* error */ + StkId func = restorestack(L, ci->u2.funcidx); + L->allowhook = getoah(ci->callstatus); /* restore 'allowhook' */ + luaF_close(L, func, status, 1); /* can yield or raise an error */ + func = restorestack(L, ci->u2.funcidx); /* stack may be moved */ + luaD_seterrorobj(L, status, func); + luaD_shrinkstack(L); /* restore stack size in case of overflow */ + setcistrecst(ci, LUA_OK); /* clear original status */ + } + ci->callstatus &= ~CIST_YPCALL; + L->errfunc = ci->u.c.old_errfunc; + /* if it is here, there were errors or yields; unlike 'lua_pcallk', + do not change status */ + return status; +} + + +/* +** Completes the execution of a C function interrupted by an yield. +** The interruption must have happened while the function was either +** closing its tbc variables in 'moveresults' or executing +** 'lua_callk'/'lua_pcallk'. In the first case, it just redoes +** 'luaD_poscall'. In the second case, the call to 'finishpcallk' +** finishes the interrupted execution of 'lua_pcallk'. After that, it +** calls the continuation of the interrupted function and finally it +** completes the job of the 'luaD_call' that called the function. In +** the call to 'adjustresults', we do not know the number of results +** of the function called by 'lua_callk'/'lua_pcallk', so we are +** conservative and use LUA_MULTRET (always adjust). +*/ +static void finishCcall (lua_State *L, CallInfo *ci) { + int n; /* actual number of results from C function */ + if (ci->callstatus & CIST_CLSRET) { /* was returning? */ + lua_assert(hastocloseCfunc(ci->nresults)); + n = ci->u2.nres; /* just redo 'luaD_poscall' */ + /* don't need to reset CIST_CLSRET, as it will be set again anyway */ + } + else { + int status = LUA_YIELD; /* default if there were no errors */ + /* must have a continuation and must be able to call it */ + lua_assert(ci->u.c.k != NULL && yieldable(L)); + if (ci->callstatus & CIST_YPCALL) /* was inside a 'lua_pcallk'? */ + status = finishpcallk(L, ci); /* finish it */ + adjustresults(L, LUA_MULTRET); /* finish 'lua_callk' */ + lua_unlock(L); + n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation */ + lua_lock(L); + api_checknelems(L, n); + } + luaD_poscall(L, ci, n); /* finish 'luaD_call' */ +} + + +/* +** Executes "full continuation" (everything in the stack) of a +** previously interrupted coroutine until the stack is empty (or another +** interruption long-jumps out of the loop). +*/ +static void unroll (lua_State *L, void *ud) { + CallInfo *ci; + UNUSED(ud); + while ((ci = L->ci) != &L->base_ci) { /* something in the stack */ + if (!isLua(ci)) /* C function? */ + finishCcall(L, ci); /* complete its execution */ + else { /* Lua function */ + luaV_finishOp(L); /* finish interrupted instruction */ + luaV_execute(L, ci); /* execute down to higher C 'boundary' */ + } + } +} + + +/* +** Try to find a suspended protected call (a "recover point") for the +** given thread. +*/ +static CallInfo *findpcall (lua_State *L) { + CallInfo *ci; + for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ + if (ci->callstatus & CIST_YPCALL) + return ci; + } + return NULL; /* no pending pcall */ +} + + +/* +** Signal an error in the call to 'lua_resume', not in the execution +** of the coroutine itself. (Such errors should not be handled by any +** coroutine error handler and should not kill the coroutine.) +*/ +static int resume_error (lua_State *L, const char *msg, int narg) { + L->top -= narg; /* remove args from the stack */ + setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ + api_incr_top(L); + lua_unlock(L); + return LUA_ERRRUN; +} + + +/* +** Do the work for 'lua_resume' in protected mode. Most of the work +** depends on the status of the coroutine: initial state, suspended +** inside a hook, or regularly suspended (optionally with a continuation +** function), plus erroneous cases: non-suspended coroutine or dead +** coroutine. +*/ +static void resume (lua_State *L, void *ud) { + int n = *(cast(int*, ud)); /* number of arguments */ + StkId firstArg = L->top - n; /* first argument */ + CallInfo *ci = L->ci; + if (L->status == LUA_OK) /* starting a coroutine? */ + ccall(L, firstArg - 1, LUA_MULTRET, 1); /* just call its body */ + else { /* resuming from previous yield */ + lua_assert(L->status == LUA_YIELD); + L->status = LUA_OK; /* mark that it is running (again) */ + luaE_incCstack(L); /* control the C stack */ + if (isLua(ci)) { /* yielded inside a hook? */ + L->top = firstArg; /* discard arguments */ + luaV_execute(L, ci); /* just continue running Lua code */ + } + else { /* 'common' yield */ + if (ci->u.c.k != NULL) { /* does it have a continuation function? */ + lua_unlock(L); + n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ + lua_lock(L); + api_checknelems(L, n); + } + luaD_poscall(L, ci, n); /* finish 'luaD_call' */ + } + unroll(L, NULL); /* run continuation */ + } +} + + +/* +** Unrolls a coroutine in protected mode while there are recoverable +** errors, that is, errors inside a protected call. (Any error +** interrupts 'unroll', and this loop protects it again so it can +** continue.) Stops with a normal end (status == LUA_OK), an yield +** (status == LUA_YIELD), or an unprotected error ('findpcall' doesn't +** find a recover point). +*/ +static int precover (lua_State *L, int status) { + CallInfo *ci; + while (errorstatus(status) && (ci = findpcall(L)) != NULL) { + L->ci = ci; /* go down to recovery functions */ + setcistrecst(ci, status); /* status to finish 'pcall' */ + status = luaD_rawrunprotected(L, unroll, NULL); + } + return status; +} + + +LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, + int *nresults) { + int status; + lua_lock(L); + if (L->status == LUA_OK) { /* may be starting a coroutine */ + if (L->ci != &L->base_ci) /* not in base level? */ + return resume_error(L, "cannot resume non-suspended coroutine", nargs); + else if (L->top - (L->ci->func + 1) == nargs) /* no function? */ + return resume_error(L, "cannot resume dead coroutine", nargs); + } + else if (L->status != LUA_YIELD) /* ended with errors? */ + return resume_error(L, "cannot resume dead coroutine", nargs); + L->nCcalls = (from) ? getCcalls(from) : 0; + luai_userstateresume(L, nargs); + api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); + status = luaD_rawrunprotected(L, resume, &nargs); + /* continue running after recoverable errors */ + status = precover(L, status); + if (l_likely(!errorstatus(status))) + lua_assert(status == L->status); /* normal end or yield */ + else { /* unrecoverable error */ + L->status = cast_byte(status); /* mark thread as 'dead' */ + luaD_seterrorobj(L, status, L->top); /* push error message */ + L->ci->top = L->top; + } + *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield + : cast_int(L->top - (L->ci->func + 1)); + lua_unlock(L); + return status; +} + + +LUA_API int lua_isyieldable (lua_State *L) { + return yieldable(L); +} + + +LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, + lua_KFunction k) { + CallInfo *ci; + luai_userstateyield(L, nresults); + lua_lock(L); + ci = L->ci; + api_checknelems(L, nresults); + if (l_unlikely(!yieldable(L))) { + if (L != G(L)->mainthread) + luaG_runerror(L, "attempt to yield across a C-call boundary"); + else + luaG_runerror(L, "attempt to yield from outside a coroutine"); + } + L->status = LUA_YIELD; + ci->u2.nyield = nresults; /* save number of results */ + if (isLua(ci)) { /* inside a hook? */ + lua_assert(!isLuacode(ci)); + api_check(L, nresults == 0, "hooks cannot yield values"); + api_check(L, k == NULL, "hooks cannot continue after yielding"); + } + else { + if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ + ci->u.c.ctx = ctx; /* save context */ + luaD_throw(L, LUA_YIELD); + } + lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ + lua_unlock(L); + return 0; /* return to 'luaD_hook' */ +} + + +/* +** Auxiliary structure to call 'luaF_close' in protected mode. +*/ +struct CloseP { + StkId level; + int status; +}; + + +/* +** Auxiliary function to call 'luaF_close' in protected mode. +*/ +static void closepaux (lua_State *L, void *ud) { + struct CloseP *pcl = cast(struct CloseP *, ud); + luaF_close(L, pcl->level, pcl->status, 0); +} + + +/* +** Calls 'luaF_close' in protected mode. Return the original status +** or, in case of errors, the new status. +*/ +int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status) { + CallInfo *old_ci = L->ci; + lu_byte old_allowhooks = L->allowhook; + for (;;) { /* keep closing upvalues until no more errors */ + struct CloseP pcl; + pcl.level = restorestack(L, level); pcl.status = status; + status = luaD_rawrunprotected(L, &closepaux, &pcl); + if (l_likely(status == LUA_OK)) /* no more errors? */ + return pcl.status; + else { /* an error occurred; restore saved state and repeat */ + L->ci = old_ci; + L->allowhook = old_allowhooks; + } + } +} + + +/* +** Call the C function 'func' in protected mode, restoring basic +** thread information ('allowhook', etc.) and in particular +** its stack level in case of errors. +*/ +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t old_top, ptrdiff_t ef) { + int status; + CallInfo *old_ci = L->ci; + lu_byte old_allowhooks = L->allowhook; + ptrdiff_t old_errfunc = L->errfunc; + L->errfunc = ef; + status = luaD_rawrunprotected(L, func, u); + if (l_unlikely(status != LUA_OK)) { /* an error occurred? */ + L->ci = old_ci; + L->allowhook = old_allowhooks; + status = luaD_closeprotected(L, old_top, status); + luaD_seterrorobj(L, status, restorestack(L, old_top)); + luaD_shrinkstack(L); /* restore stack size in case of overflow */ + } + L->errfunc = old_errfunc; + return status; +} + + + +/* +** Execute a protected parser. +*/ +struct SParser { /* data to 'f_parser' */ + ZIO *z; + Mbuffer buff; /* dynamic structure used by the scanner */ + Dyndata dyd; /* dynamic structures used by the parser */ + const char *mode; + const char *name; +}; + + +static void checkmode (lua_State *L, const char *mode, const char *x) { + if (mode && strchr(mode, x[0]) == NULL) { + luaO_pushfstring(L, + "attempt to load a %s chunk (mode is '%s')", x, mode); + luaD_throw(L, LUA_ERRSYNTAX); + } +} + + +static void f_parser (lua_State *L, void *ud) { + LClosure *cl; + struct SParser *p = cast(struct SParser *, ud); + int c = zgetc(p->z); /* read first character */ + if (c == LUA_SIGNATURE[0]) { + checkmode(L, p->mode, "binary"); + cl = luaU_undump(L, p->z, p->name); + } + else { + checkmode(L, p->mode, "text"); + cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); + } + lua_assert(cl->nupvalues == cl->p->sizeupvalues); + luaF_initupvals(L, cl); +} + + +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode) { + struct SParser p; + int status; + incnny(L); /* cannot yield during parsing */ + p.z = z; p.name = name; p.mode = mode; + p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; + p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; + p.dyd.label.arr = NULL; p.dyd.label.size = 0; + luaZ_initbuffer(L, &p.buff); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + luaZ_freebuffer(L, &p.buff); + luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); + luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); + luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); + decnny(L); + return status; +} + + diff --git a/lua/ldo.h b/lua/ldo.h new file mode 100644 index 0000000..6bf0ed8 --- /dev/null +++ b/lua/ldo.h @@ -0,0 +1,79 @@ +/* +** $Id: ldo.h $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#ifndef ldo_h +#define ldo_h + + +#include "lobject.h" +#include "lstate.h" +#include "lzio.h" + + +/* +** Macro to check stack size and grow stack if needed. Parameters +** 'pre'/'pos' allow the macro to preserve a pointer into the +** stack across reallocations, doing the work only when needed. +** It also allows the running of one GC step when the stack is +** reallocated. +** 'condmovestack' is used in heavy tests to force a stack reallocation +** at every check. +*/ +#define luaD_checkstackaux(L,n,pre,pos) \ + if (l_unlikely(L->stack_last - L->top <= (n))) \ + { pre; luaD_growstack(L, n, 1); pos; } \ + else { condmovestack(L,pre,pos); } + +/* In general, 'pre'/'pos' are empty (nothing to save) */ +#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0) + + + +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((StkId)((char *)L->stack + (n))) + + +/* macro to check stack size, preserving 'p' */ +#define checkstackGCp(L,n,p) \ + luaD_checkstackaux(L, n, \ + ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ + luaC_checkGC(L), /* stack grow uses memory */ \ + p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ + + +/* macro to check stack size and GC */ +#define checkstackGC(L,fsize) \ + luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0) + + +/* type of protected functions, to be ran by 'runprotected' */ +typedef void (*Pfunc) (lua_State *L, void *ud); + +LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); +LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode); +LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, + int fTransfer, int nTransfer); +LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); +LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n); +LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); +LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); +LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); +LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func); +LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status); +LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t oldtop, ptrdiff_t ef); +LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, int nres); +LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror); +LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); +LUAI_FUNC void luaD_shrinkstack (lua_State *L); +LUAI_FUNC void luaD_inctop (lua_State *L); + +LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); +LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); + +#endif + diff --git a/lua/ldump.c b/lua/ldump.c new file mode 100644 index 0000000..f848b66 --- /dev/null +++ b/lua/ldump.c @@ -0,0 +1,226 @@ +/* +** $Id: ldump.c $ +** save precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#define ldump_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lundump.h" + + +typedef struct { + lua_State *L; + lua_Writer writer; + void *data; + int strip; + int status; +} DumpState; + + +/* +** All high-level dumps go through dumpVector; you can change it to +** change the endianness of the result +*/ +#define dumpVector(D,v,n) dumpBlock(D,v,(n)*sizeof((v)[0])) + +#define dumpLiteral(D, s) dumpBlock(D,s,sizeof(s) - sizeof(char)) + + +static void dumpBlock (DumpState *D, const void *b, size_t size) { + if (D->status == 0 && size > 0) { + lua_unlock(D->L); + D->status = (*D->writer)(D->L, b, size, D->data); + lua_lock(D->L); + } +} + + +#define dumpVar(D,x) dumpVector(D,&x,1) + + +static void dumpByte (DumpState *D, int y) { + lu_byte x = (lu_byte)y; + dumpVar(D, x); +} + + +/* dumpInt Buff Size */ +#define DIBS ((sizeof(size_t) * 8 / 7) + 1) + +static void dumpSize (DumpState *D, size_t x) { + lu_byte buff[DIBS]; + int n = 0; + do { + buff[DIBS - (++n)] = x & 0x7f; /* fill buffer in reverse order */ + x >>= 7; + } while (x != 0); + buff[DIBS - 1] |= 0x80; /* mark last byte */ + dumpVector(D, buff + DIBS - n, n); +} + + +static void dumpInt (DumpState *D, int x) { + dumpSize(D, x); +} + + +static void dumpNumber (DumpState *D, lua_Number x) { + dumpVar(D, x); +} + + +static void dumpInteger (DumpState *D, lua_Integer x) { + dumpVar(D, x); +} + + +static void dumpString (DumpState *D, const TString *s) { + if (s == NULL) + dumpSize(D, 0); + else { + size_t size = tsslen(s); + const char *str = getstr(s); + dumpSize(D, size + 1); + dumpVector(D, str, size); + } +} + + +static void dumpCode (DumpState *D, const Proto *f) { + dumpInt(D, f->sizecode); + dumpVector(D, f->code, f->sizecode); +} + + +static void dumpFunction(DumpState *D, const Proto *f, TString *psource); + +static void dumpConstants (DumpState *D, const Proto *f) { + int i; + int n = f->sizek; + dumpInt(D, n); + for (i = 0; i < n; i++) { + const TValue *o = &f->k[i]; + int tt = ttypetag(o); + dumpByte(D, tt); + switch (tt) { + case LUA_VNUMFLT: + dumpNumber(D, fltvalue(o)); + break; + case LUA_VNUMINT: + dumpInteger(D, ivalue(o)); + break; + case LUA_VSHRSTR: + case LUA_VLNGSTR: + dumpString(D, tsvalue(o)); + break; + default: + lua_assert(tt == LUA_VNIL || tt == LUA_VFALSE || tt == LUA_VTRUE); + } + } +} + + +static void dumpProtos (DumpState *D, const Proto *f) { + int i; + int n = f->sizep; + dumpInt(D, n); + for (i = 0; i < n; i++) + dumpFunction(D, f->p[i], f->source); +} + + +static void dumpUpvalues (DumpState *D, const Proto *f) { + int i, n = f->sizeupvalues; + dumpInt(D, n); + for (i = 0; i < n; i++) { + dumpByte(D, f->upvalues[i].instack); + dumpByte(D, f->upvalues[i].idx); + dumpByte(D, f->upvalues[i].kind); + } +} + + +static void dumpDebug (DumpState *D, const Proto *f) { + int i, n; + n = (D->strip) ? 0 : f->sizelineinfo; + dumpInt(D, n); + dumpVector(D, f->lineinfo, n); + n = (D->strip) ? 0 : f->sizeabslineinfo; + dumpInt(D, n); + for (i = 0; i < n; i++) { + dumpInt(D, f->abslineinfo[i].pc); + dumpInt(D, f->abslineinfo[i].line); + } + n = (D->strip) ? 0 : f->sizelocvars; + dumpInt(D, n); + for (i = 0; i < n; i++) { + dumpString(D, f->locvars[i].varname); + dumpInt(D, f->locvars[i].startpc); + dumpInt(D, f->locvars[i].endpc); + } + n = (D->strip) ? 0 : f->sizeupvalues; + dumpInt(D, n); + for (i = 0; i < n; i++) + dumpString(D, f->upvalues[i].name); +} + + +static void dumpFunction (DumpState *D, const Proto *f, TString *psource) { + if (D->strip || f->source == psource) + dumpString(D, NULL); /* no debug info or same source as its parent */ + else + dumpString(D, f->source); + dumpInt(D, f->linedefined); + dumpInt(D, f->lastlinedefined); + dumpByte(D, f->numparams); + dumpByte(D, f->is_vararg); + dumpByte(D, f->maxstacksize); + dumpCode(D, f); + dumpConstants(D, f); + dumpUpvalues(D, f); + dumpProtos(D, f); + dumpDebug(D, f); +} + + +static void dumpHeader (DumpState *D) { + dumpLiteral(D, LUA_SIGNATURE); + dumpByte(D, LUAC_VERSION); + dumpByte(D, LUAC_FORMAT); + dumpLiteral(D, LUAC_DATA); + dumpByte(D, sizeof(Instruction)); + dumpByte(D, sizeof(lua_Integer)); + dumpByte(D, sizeof(lua_Number)); + dumpInteger(D, LUAC_INT); + dumpNumber(D, LUAC_NUM); +} + + +/* +** dump Lua function as precompiled chunk +*/ +int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, + int strip) { + DumpState D; + D.L = L; + D.writer = w; + D.data = data; + D.strip = strip; + D.status = 0; + dumpHeader(&D); + dumpByte(&D, f->sizeupvalues); + dumpFunction(&D, f, NULL); + return D.status; +} + diff --git a/lua/lfunc.c b/lua/lfunc.c new file mode 100644 index 0000000..f5889a2 --- /dev/null +++ b/lua/lfunc.c @@ -0,0 +1,294 @@ +/* +** $Id: lfunc.c $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#define lfunc_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +CClosure *luaF_newCclosure (lua_State *L, int nupvals) { + GCObject *o = luaC_newobj(L, LUA_VCCL, sizeCclosure(nupvals)); + CClosure *c = gco2ccl(o); + c->nupvalues = cast_byte(nupvals); + return c; +} + + +LClosure *luaF_newLclosure (lua_State *L, int nupvals) { + GCObject *o = luaC_newobj(L, LUA_VLCL, sizeLclosure(nupvals)); + LClosure *c = gco2lcl(o); + c->p = NULL; + c->nupvalues = cast_byte(nupvals); + while (nupvals--) c->upvals[nupvals] = NULL; + return c; +} + + +/* +** fill a closure with new closed upvalues +*/ +void luaF_initupvals (lua_State *L, LClosure *cl) { + int i; + for (i = 0; i < cl->nupvalues; i++) { + GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); + UpVal *uv = gco2upv(o); + uv->v = &uv->u.value; /* make it closed */ + setnilvalue(uv->v); + cl->upvals[i] = uv; + luaC_objbarrier(L, cl, uv); + } +} + + +/* +** Create a new upvalue at the given level, and link it to the list of +** open upvalues of 'L' after entry 'prev'. +**/ +static UpVal *newupval (lua_State *L, int tbc, StkId level, UpVal **prev) { + GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); + UpVal *uv = gco2upv(o); + UpVal *next = *prev; + uv->v = s2v(level); /* current value lives in the stack */ + uv->tbc = tbc; + uv->u.open.next = next; /* link it to list of open upvalues */ + uv->u.open.previous = prev; + if (next) + next->u.open.previous = &uv->u.open.next; + *prev = uv; + if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ + L->twups = G(L)->twups; /* link it to the list */ + G(L)->twups = L; + } + return uv; +} + + +/* +** Find and reuse, or create if it does not exist, an upvalue +** at the given level. +*/ +UpVal *luaF_findupval (lua_State *L, StkId level) { + UpVal **pp = &L->openupval; + UpVal *p; + lua_assert(isintwups(L) || L->openupval == NULL); + while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */ + lua_assert(!isdead(G(L), p)); + if (uplevel(p) == level) /* corresponding upvalue? */ + return p; /* return it */ + pp = &p->u.open.next; + } + /* not found: create a new upvalue after 'pp' */ + return newupval(L, 0, level, pp); +} + + +/* +** Call closing method for object 'obj' with error message 'err'. The +** boolean 'yy' controls whether the call is yieldable. +** (This function assumes EXTRA_STACK.) +*/ +static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { + StkId top = L->top; + const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); + setobj2s(L, top, tm); /* will call metamethod... */ + setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ + setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ + L->top = top + 3; /* add function and arguments */ + if (yy) + luaD_call(L, top, 0); + else + luaD_callnoyield(L, top, 0); +} + + +/* +** Check whether object at given level has a close metamethod and raise +** an error if not. +*/ +static void checkclosemth (lua_State *L, StkId level) { + const TValue *tm = luaT_gettmbyobj(L, s2v(level), TM_CLOSE); + if (ttisnil(tm)) { /* no metamethod? */ + int idx = cast_int(level - L->ci->func); /* variable index */ + const char *vname = luaG_findlocal(L, L->ci, idx, NULL); + if (vname == NULL) vname = "?"; + luaG_runerror(L, "variable '%s' got a non-closable value", vname); + } +} + + +/* +** Prepare and call a closing method. +** If status is CLOSEKTOP, the call to the closing method will be pushed +** at the top of the stack. Otherwise, values can be pushed right after +** the 'level' of the upvalue being closed, as everything after that +** won't be used again. +*/ +static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) { + TValue *uv = s2v(level); /* value being closed */ + TValue *errobj; + if (status == CLOSEKTOP) + errobj = &G(L)->nilvalue; /* error object is nil */ + else { /* 'luaD_seterrorobj' will set top to level + 2 */ + errobj = s2v(level + 1); /* error object goes after 'uv' */ + luaD_seterrorobj(L, status, level + 1); /* set error object */ + } + callclosemethod(L, uv, errobj, yy); +} + + +/* +** Maximum value for deltas in 'tbclist', dependent on the type +** of delta. (This macro assumes that an 'L' is in scope where it +** is used.) +*/ +#define MAXDELTA \ + ((256ul << ((sizeof(L->stack->tbclist.delta) - 1) * 8)) - 1) + + +/* +** Insert a variable in the list of to-be-closed variables. +*/ +void luaF_newtbcupval (lua_State *L, StkId level) { + lua_assert(level > L->tbclist); + if (l_isfalse(s2v(level))) + return; /* false doesn't need to be closed */ + checkclosemth(L, level); /* value must have a close method */ + while (cast_uint(level - L->tbclist) > MAXDELTA) { + L->tbclist += MAXDELTA; /* create a dummy node at maximum delta */ + L->tbclist->tbclist.delta = 0; + } + level->tbclist.delta = cast(unsigned short, level - L->tbclist); + L->tbclist = level; +} + + +void luaF_unlinkupval (UpVal *uv) { + lua_assert(upisopen(uv)); + *uv->u.open.previous = uv->u.open.next; + if (uv->u.open.next) + uv->u.open.next->u.open.previous = uv->u.open.previous; +} + + +/* +** Close all upvalues up to the given stack level. +*/ +void luaF_closeupval (lua_State *L, StkId level) { + UpVal *uv; + StkId upl; /* stack index pointed by 'uv' */ + while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) { + TValue *slot = &uv->u.value; /* new position for value */ + lua_assert(uplevel(uv) < L->top); + luaF_unlinkupval(uv); /* remove upvalue from 'openupval' list */ + setobj(L, slot, uv->v); /* move value to upvalue slot */ + uv->v = slot; /* now current value lives here */ + if (!iswhite(uv)) { /* neither white nor dead? */ + nw2black(uv); /* closed upvalues cannot be gray */ + luaC_barrier(L, uv, slot); + } + } +} + + +/* +** Remove firt element from the tbclist plus its dummy nodes. +*/ +static void poptbclist (lua_State *L) { + StkId tbc = L->tbclist; + lua_assert(tbc->tbclist.delta > 0); /* first element cannot be dummy */ + tbc -= tbc->tbclist.delta; + while (tbc > L->stack && tbc->tbclist.delta == 0) + tbc -= MAXDELTA; /* remove dummy nodes */ + L->tbclist = tbc; +} + + +/* +** Close all upvalues and to-be-closed variables up to the given stack +** level. +*/ +void luaF_close (lua_State *L, StkId level, int status, int yy) { + ptrdiff_t levelrel = savestack(L, level); + luaF_closeupval(L, level); /* first, close the upvalues */ + while (L->tbclist >= level) { /* traverse tbc's down to that level */ + StkId tbc = L->tbclist; /* get variable index */ + poptbclist(L); /* remove it from list */ + prepcallclosemth(L, tbc, status, yy); /* close variable */ + level = restorestack(L, levelrel); + } +} + + +Proto *luaF_newproto (lua_State *L) { + GCObject *o = luaC_newobj(L, LUA_VPROTO, sizeof(Proto)); + Proto *f = gco2p(o); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->sizecode = 0; + f->lineinfo = NULL; + f->sizelineinfo = 0; + f->abslineinfo = NULL; + f->sizeabslineinfo = 0; + f->upvalues = NULL; + f->sizeupvalues = 0; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->locvars = NULL; + f->sizelocvars = 0; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + + +void luaF_freeproto (lua_State *L, Proto *f) { + luaM_freearray(L, f->code, f->sizecode); + luaM_freearray(L, f->p, f->sizep); + luaM_freearray(L, f->k, f->sizek); + luaM_freearray(L, f->lineinfo, f->sizelineinfo); + luaM_freearray(L, f->abslineinfo, f->sizeabslineinfo); + luaM_freearray(L, f->locvars, f->sizelocvars); + luaM_freearray(L, f->upvalues, f->sizeupvalues); + luaM_free(L, f); +} + + +/* +** Look for n-th local variable at line 'line' in function 'func'. +** Returns NULL if not found. +*/ +const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { + int i; + for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { + if (pc < f->locvars[i].endpc) { /* is variable active? */ + local_number--; + if (local_number == 0) + return getstr(f->locvars[i].varname); + } + } + return NULL; /* not found */ +} + diff --git a/lua/lfunc.h b/lua/lfunc.h new file mode 100644 index 0000000..dc1cebc --- /dev/null +++ b/lua/lfunc.h @@ -0,0 +1,64 @@ +/* +** $Id: lfunc.h $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#ifndef lfunc_h +#define lfunc_h + + +#include "lobject.h" + + +#define sizeCclosure(n) (cast_int(offsetof(CClosure, upvalue)) + \ + cast_int(sizeof(TValue)) * (n)) + +#define sizeLclosure(n) (cast_int(offsetof(LClosure, upvals)) + \ + cast_int(sizeof(TValue *)) * (n)) + + +/* test whether thread is in 'twups' list */ +#define isintwups(L) (L->twups != L) + + +/* +** maximum number of upvalues in a closure (both C and Lua). (Value +** must fit in a VM register.) +*/ +#define MAXUPVAL 255 + + +#define upisopen(up) ((up)->v != &(up)->u.value) + + +#define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v)) + + +/* +** maximum number of misses before giving up the cache of closures +** in prototypes +*/ +#define MAXMISS 10 + + + +/* special status to close upvalues preserving the top of the stack */ +#define CLOSEKTOP (-1) + + +LUAI_FUNC Proto *luaF_newproto (lua_State *L); +LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nupvals); +LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nupvals); +LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); +LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); +LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); +LUAI_FUNC void luaF_closeupval (lua_State *L, StkId level); +LUAI_FUNC void luaF_close (lua_State *L, StkId level, int status, int yy); +LUAI_FUNC void luaF_unlinkupval (UpVal *uv); +LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); +LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, + int pc); + + +#endif diff --git a/lua/lgc.c b/lua/lgc.c new file mode 100644 index 0000000..b360eed --- /dev/null +++ b/lua/lgc.c @@ -0,0 +1,1728 @@ +/* +** $Id: lgc.c $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#define lgc_c +#define LUA_CORE + +#include "lprefix.h" + +#include +#include + + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +/* +** Maximum number of elements to sweep in each single step. +** (Large enough to dissipate fixed overheads but small enough +** to allow small steps for the collector.) +*/ +#define GCSWEEPMAX 100 + +/* +** Maximum number of finalizers to call in each single step. +*/ +#define GCFINMAX 10 + + +/* +** Cost of calling one finalizer. +*/ +#define GCFINALIZECOST 50 + + +/* +** The equivalent, in bytes, of one unit of "work" (visiting a slot, +** sweeping an object, etc.) +*/ +#define WORK2MEM sizeof(TValue) + + +/* +** macro to adjust 'pause': 'pause' is actually used like +** 'pause / PAUSEADJ' (value chosen by tests) +*/ +#define PAUSEADJ 100 + + +/* mask with all color bits */ +#define maskcolors (bitmask(BLACKBIT) | WHITEBITS) + +/* mask with all GC bits */ +#define maskgcbits (maskcolors | AGEBITS) + + +/* macro to erase all color bits then set only the current white bit */ +#define makewhite(g,x) \ + (x->marked = cast_byte((x->marked & ~maskcolors) | luaC_white(g))) + +/* make an object gray (neither white nor black) */ +#define set2gray(x) resetbits(x->marked, maskcolors) + + +/* make an object black (coming from any color) */ +#define set2black(x) \ + (x->marked = cast_byte((x->marked & ~WHITEBITS) | bitmask(BLACKBIT))) + + +#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) + +#define keyiswhite(n) (keyiscollectable(n) && iswhite(gckey(n))) + + +/* +** Protected access to objects in values +*/ +#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL) + + +#define markvalue(g,o) { checkliveness(g->mainthread,o); \ + if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } + +#define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); } + +#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); } + +/* +** mark an object that can be NULL (either because it is really optional, +** or it was stripped as debug info, or inside an uncompleted structure) +*/ +#define markobjectN(g,t) { if (t) markobject(g,t); } + +static void reallymarkobject (global_State *g, GCObject *o); +static lu_mem atomic (lua_State *L); +static void entersweep (lua_State *L); + + +/* +** {====================================================== +** Generic functions +** ======================================================= +*/ + + +/* +** one after last element in a hash array +*/ +#define gnodelast(h) gnode(h, cast_sizet(sizenode(h))) + + +static GCObject **getgclist (GCObject *o) { + switch (o->tt) { + case LUA_VTABLE: return &gco2t(o)->gclist; + case LUA_VLCL: return &gco2lcl(o)->gclist; + case LUA_VCCL: return &gco2ccl(o)->gclist; + case LUA_VTHREAD: return &gco2th(o)->gclist; + case LUA_VPROTO: return &gco2p(o)->gclist; + case LUA_VUSERDATA: { + Udata *u = gco2u(o); + lua_assert(u->nuvalue > 0); + return &u->gclist; + } + default: lua_assert(0); return 0; + } +} + + +/* +** Link a collectable object 'o' with a known type into the list 'p'. +** (Must be a macro to access the 'gclist' field in different types.) +*/ +#define linkgclist(o,p) linkgclist_(obj2gco(o), &(o)->gclist, &(p)) + +static void linkgclist_ (GCObject *o, GCObject **pnext, GCObject **list) { + lua_assert(!isgray(o)); /* cannot be in a gray list */ + *pnext = *list; + *list = o; + set2gray(o); /* now it is */ +} + + +/* +** Link a generic collectable object 'o' into the list 'p'. +*/ +#define linkobjgclist(o,p) linkgclist_(obj2gco(o), getgclist(o), &(p)) + + + +/* +** Clear keys for empty entries in tables. If entry is empty, mark its +** entry as dead. This allows the collection of the key, but keeps its +** entry in the table: its removal could break a chain and could break +** a table traversal. Other places never manipulate dead keys, because +** its associated empty value is enough to signal that the entry is +** logically empty. +*/ +static void clearkey (Node *n) { + lua_assert(isempty(gval(n))); + if (keyiscollectable(n)) + setdeadkey(n); /* unused key; remove it */ +} + + +/* +** tells whether a key or value can be cleared from a weak +** table. Non-collectable objects are never removed from weak +** tables. Strings behave as 'values', so are never removed too. for +** other objects: if really collected, cannot keep them; for objects +** being finalized, keep them in keys, but not in values +*/ +static int iscleared (global_State *g, const GCObject *o) { + if (o == NULL) return 0; /* non-collectable value */ + else if (novariant(o->tt) == LUA_TSTRING) { + markobject(g, o); /* strings are 'values', so are never weak */ + return 0; + } + else return iswhite(o); +} + + +/* +** Barrier that moves collector forward, that is, marks the white object +** 'v' being pointed by the black object 'o'. In the generational +** mode, 'v' must also become old, if 'o' is old; however, it cannot +** be changed directly to OLD, because it may still point to non-old +** objects. So, it is marked as OLD0. In the next cycle it will become +** OLD1, and in the next it will finally become OLD (regular old). By +** then, any object it points to will also be old. If called in the +** incremental sweep phase, it clears the black object to white (sweep +** it) to avoid other barrier calls for this same object. (That cannot +** be done is generational mode, as its sweep does not distinguish +** whites from deads.) +*/ +void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { + global_State *g = G(L); + lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); + if (keepinvariant(g)) { /* must keep invariant? */ + reallymarkobject(g, v); /* restore invariant */ + if (isold(o)) { + lua_assert(!isold(v)); /* white object could not be old */ + setage(v, G_OLD0); /* restore generational invariant */ + } + } + else { /* sweep phase */ + lua_assert(issweepphase(g)); + if (g->gckind == KGC_INC) /* incremental mode? */ + makewhite(g, o); /* mark 'o' as white to avoid other barriers */ + } +} + + +/* +** barrier that moves collector backward, that is, mark the black object +** pointing to a white object as gray again. +*/ +void luaC_barrierback_ (lua_State *L, GCObject *o) { + global_State *g = G(L); + lua_assert(isblack(o) && !isdead(g, o)); + lua_assert((g->gckind == KGC_GEN) == (isold(o) && getage(o) != G_TOUCHED1)); + if (getage(o) == G_TOUCHED2) /* already in gray list? */ + set2gray(o); /* make it gray to become touched1 */ + else /* link it in 'grayagain' and paint it gray */ + linkobjgclist(o, g->grayagain); + if (isold(o)) /* generational mode? */ + setage(o, G_TOUCHED1); /* touched in current cycle */ +} + + +void luaC_fix (lua_State *L, GCObject *o) { + global_State *g = G(L); + lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ + set2gray(o); /* they will be gray forever */ + setage(o, G_OLD); /* and old forever */ + g->allgc = o->next; /* remove object from 'allgc' list */ + o->next = g->fixedgc; /* link it to 'fixedgc' list */ + g->fixedgc = o; +} + + +/* +** create a new collectable object (with given type and size) and link +** it to 'allgc' list. +*/ +GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { + global_State *g = G(L); + GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); + o->marked = luaC_white(g); + o->tt = tt; + o->next = g->allgc; + g->allgc = o; + return o; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Mark functions +** ======================================================= +*/ + + +/* +** Mark an object. Userdata with no user values, strings, and closed +** upvalues are visited and turned black here. Open upvalues are +** already indirectly linked through their respective threads in the +** 'twups' list, so they don't go to the gray list; nevertheless, they +** are kept gray to avoid barriers, as their values will be revisited +** by the thread or by 'remarkupvals'. Other objects are added to the +** gray list to be visited (and turned black) later. Both userdata and +** upvalues can call this function recursively, but this recursion goes +** for at most two levels: An upvalue cannot refer to another upvalue +** (only closures can), and a userdata's metatable must be a table. +*/ +static void reallymarkobject (global_State *g, GCObject *o) { + switch (o->tt) { + case LUA_VSHRSTR: + case LUA_VLNGSTR: { + set2black(o); /* nothing to visit */ + break; + } + case LUA_VUPVAL: { + UpVal *uv = gco2upv(o); + if (upisopen(uv)) + set2gray(uv); /* open upvalues are kept gray */ + else + set2black(uv); /* closed upvalues are visited here */ + markvalue(g, uv->v); /* mark its content */ + break; + } + case LUA_VUSERDATA: { + Udata *u = gco2u(o); + if (u->nuvalue == 0) { /* no user values? */ + markobjectN(g, u->metatable); /* mark its metatable */ + set2black(u); /* nothing else to mark */ + break; + } + /* else... */ + } /* FALLTHROUGH */ + case LUA_VLCL: case LUA_VCCL: case LUA_VTABLE: + case LUA_VTHREAD: case LUA_VPROTO: { + linkobjgclist(o, g->gray); /* to be visited later */ + break; + } + default: lua_assert(0); break; + } +} + + +/* +** mark metamethods for basic types +*/ +static void markmt (global_State *g) { + int i; + for (i=0; i < LUA_NUMTAGS; i++) + markobjectN(g, g->mt[i]); +} + + +/* +** mark all objects in list of being-finalized +*/ +static lu_mem markbeingfnz (global_State *g) { + GCObject *o; + lu_mem count = 0; + for (o = g->tobefnz; o != NULL; o = o->next) { + count++; + markobject(g, o); + } + return count; +} + + +/* +** For each non-marked thread, simulates a barrier between each open +** upvalue and its value. (If the thread is collected, the value will be +** assigned to the upvalue, but then it can be too late for the barrier +** to act. The "barrier" does not need to check colors: A non-marked +** thread must be young; upvalues cannot be older than their threads; so +** any visited upvalue must be young too.) Also removes the thread from +** the list, as it was already visited. Removes also threads with no +** upvalues, as they have nothing to be checked. (If the thread gets an +** upvalue later, it will be linked in the list again.) +*/ +static int remarkupvals (global_State *g) { + lua_State *thread; + lua_State **p = &g->twups; + int work = 0; /* estimate of how much work was done here */ + while ((thread = *p) != NULL) { + work++; + if (!iswhite(thread) && thread->openupval != NULL) + p = &thread->twups; /* keep marked thread with upvalues in the list */ + else { /* thread is not marked or without upvalues */ + UpVal *uv; + lua_assert(!isold(thread) || thread->openupval == NULL); + *p = thread->twups; /* remove thread from the list */ + thread->twups = thread; /* mark that it is out of list */ + for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { + lua_assert(getage(uv) <= getage(thread)); + work++; + if (!iswhite(uv)) { /* upvalue already visited? */ + lua_assert(upisopen(uv) && isgray(uv)); + markvalue(g, uv->v); /* mark its value */ + } + } + } + } + return work; +} + + +static void cleargraylists (global_State *g) { + g->gray = g->grayagain = NULL; + g->weak = g->allweak = g->ephemeron = NULL; +} + + +/* +** mark root set and reset all gray lists, to start a new collection +*/ +static void restartcollection (global_State *g) { + cleargraylists(g); + markobject(g, g->mainthread); + markvalue(g, &g->l_registry); + markmt(g); + markbeingfnz(g); /* mark any finalizing object left from previous cycle */ +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Traverse functions +** ======================================================= +*/ + + +/* +** Check whether object 'o' should be kept in the 'grayagain' list for +** post-processing by 'correctgraylist'. (It could put all old objects +** in the list and leave all the work to 'correctgraylist', but it is +** more efficient to avoid adding elements that will be removed.) Only +** TOUCHED1 objects need to be in the list. TOUCHED2 doesn't need to go +** back to a gray list, but then it must become OLD. (That is what +** 'correctgraylist' does when it finds a TOUCHED2 object.) +*/ +static void genlink (global_State *g, GCObject *o) { + lua_assert(isblack(o)); + if (getage(o) == G_TOUCHED1) { /* touched in this cycle? */ + linkobjgclist(o, g->grayagain); /* link it back in 'grayagain' */ + } /* everything else do not need to be linked back */ + else if (getage(o) == G_TOUCHED2) + changeage(o, G_TOUCHED2, G_OLD); /* advance age */ +} + + +/* +** Traverse a table with weak values and link it to proper list. During +** propagate phase, keep it in 'grayagain' list, to be revisited in the +** atomic phase. In the atomic phase, if table has any white value, +** put it in 'weak' list, to be cleared. +*/ +static void traverseweakvalue (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + /* if there is array part, assume it may have white values (it is not + worth traversing it now just to check) */ + int hasclears = (h->alimit > 0); + for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ + if (isempty(gval(n))) /* entry is empty? */ + clearkey(n); /* clear its key */ + else { + lua_assert(!keyisnil(n)); + markkey(g, n); + if (!hasclears && iscleared(g, gcvalueN(gval(n)))) /* a white value? */ + hasclears = 1; /* table will have to be cleared */ + } + } + if (g->gcstate == GCSatomic && hasclears) + linkgclist(h, g->weak); /* has to be cleared later */ + else + linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ +} + + +/* +** Traverse an ephemeron table and link it to proper list. Returns true +** iff any object was marked during this traversal (which implies that +** convergence has to continue). During propagation phase, keep table +** in 'grayagain' list, to be visited again in the atomic phase. In +** the atomic phase, if table has any white->white entry, it has to +** be revisited during ephemeron convergence (as that key may turn +** black). Otherwise, if it has any white key, table has to be cleared +** (in the atomic phase). In generational mode, some tables +** must be kept in some gray list for post-processing; this is done +** by 'genlink'. +*/ +static int traverseephemeron (global_State *g, Table *h, int inv) { + int marked = 0; /* true if an object is marked in this traversal */ + int hasclears = 0; /* true if table has white keys */ + int hasww = 0; /* true if table has entry "white-key -> white-value" */ + unsigned int i; + unsigned int asize = luaH_realasize(h); + unsigned int nsize = sizenode(h); + /* traverse array part */ + for (i = 0; i < asize; i++) { + if (valiswhite(&h->array[i])) { + marked = 1; + reallymarkobject(g, gcvalue(&h->array[i])); + } + } + /* traverse hash part; if 'inv', traverse descending + (see 'convergeephemerons') */ + for (i = 0; i < nsize; i++) { + Node *n = inv ? gnode(h, nsize - 1 - i) : gnode(h, i); + if (isempty(gval(n))) /* entry is empty? */ + clearkey(n); /* clear its key */ + else if (iscleared(g, gckeyN(n))) { /* key is not marked (yet)? */ + hasclears = 1; /* table must be cleared */ + if (valiswhite(gval(n))) /* value not marked yet? */ + hasww = 1; /* white-white entry */ + } + else if (valiswhite(gval(n))) { /* value not marked yet? */ + marked = 1; + reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ + } + } + /* link table into proper list */ + if (g->gcstate == GCSpropagate) + linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ + else if (hasww) /* table has white->white entries? */ + linkgclist(h, g->ephemeron); /* have to propagate again */ + else if (hasclears) /* table has white keys? */ + linkgclist(h, g->allweak); /* may have to clean white keys */ + else + genlink(g, obj2gco(h)); /* check whether collector still needs to see it */ + return marked; +} + + +static void traversestrongtable (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + unsigned int i; + unsigned int asize = luaH_realasize(h); + for (i = 0; i < asize; i++) /* traverse array part */ + markvalue(g, &h->array[i]); + for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ + if (isempty(gval(n))) /* entry is empty? */ + clearkey(n); /* clear its key */ + else { + lua_assert(!keyisnil(n)); + markkey(g, n); + markvalue(g, gval(n)); + } + } + genlink(g, obj2gco(h)); +} + + +static lu_mem traversetable (global_State *g, Table *h) { + const char *weakkey, *weakvalue; + const TValue *mode = gfasttm(g, h->metatable, TM_MODE); + markobjectN(g, h->metatable); + if (mode && ttisstring(mode) && /* is there a weak mode? */ + (cast_void(weakkey = strchr(svalue(mode), 'k')), + cast_void(weakvalue = strchr(svalue(mode), 'v')), + (weakkey || weakvalue))) { /* is really weak? */ + if (!weakkey) /* strong keys? */ + traverseweakvalue(g, h); + else if (!weakvalue) /* strong values? */ + traverseephemeron(g, h, 0); + else /* all weak */ + linkgclist(h, g->allweak); /* nothing to traverse now */ + } + else /* not weak */ + traversestrongtable(g, h); + return 1 + h->alimit + 2 * allocsizenode(h); +} + + +static int traverseudata (global_State *g, Udata *u) { + int i; + markobjectN(g, u->metatable); /* mark its metatable */ + for (i = 0; i < u->nuvalue; i++) + markvalue(g, &u->uv[i].uv); + genlink(g, obj2gco(u)); + return 1 + u->nuvalue; +} + + +/* +** Traverse a prototype. (While a prototype is being build, its +** arrays can be larger than needed; the extra slots are filled with +** NULL, so the use of 'markobjectN') +*/ +static int traverseproto (global_State *g, Proto *f) { + int i; + markobjectN(g, f->source); + for (i = 0; i < f->sizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ + markobjectN(g, f->upvalues[i].name); + for (i = 0; i < f->sizep; i++) /* mark nested protos */ + markobjectN(g, f->p[i]); + for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ + markobjectN(g, f->locvars[i].varname); + return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars; +} + + +static int traverseCclosure (global_State *g, CClosure *cl) { + int i; + for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ + markvalue(g, &cl->upvalue[i]); + return 1 + cl->nupvalues; +} + +/* +** Traverse a Lua closure, marking its prototype and its upvalues. +** (Both can be NULL while closure is being created.) +*/ +static int traverseLclosure (global_State *g, LClosure *cl) { + int i; + markobjectN(g, cl->p); /* mark its prototype */ + for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ + UpVal *uv = cl->upvals[i]; + markobjectN(g, uv); /* mark upvalue */ + } + return 1 + cl->nupvalues; +} + + +/* +** Traverse a thread, marking the elements in the stack up to its top +** and cleaning the rest of the stack in the final traversal. That +** ensures that the entire stack have valid (non-dead) objects. +** Threads have no barriers. In gen. mode, old threads must be visited +** at every cycle, because they might point to young objects. In inc. +** mode, the thread can still be modified before the end of the cycle, +** and therefore it must be visited again in the atomic phase. To ensure +** these visits, threads must return to a gray list if they are not new +** (which can only happen in generational mode) or if the traverse is in +** the propagate phase (which can only happen in incremental mode). +*/ +static int traversethread (global_State *g, lua_State *th) { + UpVal *uv; + StkId o = th->stack; + if (isold(th) || g->gcstate == GCSpropagate) + linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ + if (o == NULL) + return 1; /* stack not completely built yet */ + lua_assert(g->gcstate == GCSatomic || + th->openupval == NULL || isintwups(th)); + for (; o < th->top; o++) /* mark live elements in the stack */ + markvalue(g, s2v(o)); + for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) + markobject(g, uv); /* open upvalues cannot be collected */ + if (g->gcstate == GCSatomic) { /* final traversal? */ + for (; o < th->stack_last + EXTRA_STACK; o++) + setnilvalue(s2v(o)); /* clear dead stack slice */ + /* 'remarkupvals' may have removed thread from 'twups' list */ + if (!isintwups(th) && th->openupval != NULL) { + th->twups = g->twups; /* link it back to the list */ + g->twups = th; + } + } + else if (!g->gcemergency) + luaD_shrinkstack(th); /* do not change stack in emergency cycle */ + return 1 + stacksize(th); +} + + +/* +** traverse one gray object, turning it to black. +*/ +static lu_mem propagatemark (global_State *g) { + GCObject *o = g->gray; + nw2black(o); + g->gray = *getgclist(o); /* remove from 'gray' list */ + switch (o->tt) { + case LUA_VTABLE: return traversetable(g, gco2t(o)); + case LUA_VUSERDATA: return traverseudata(g, gco2u(o)); + case LUA_VLCL: return traverseLclosure(g, gco2lcl(o)); + case LUA_VCCL: return traverseCclosure(g, gco2ccl(o)); + case LUA_VPROTO: return traverseproto(g, gco2p(o)); + case LUA_VTHREAD: return traversethread(g, gco2th(o)); + default: lua_assert(0); return 0; + } +} + + +static lu_mem propagateall (global_State *g) { + lu_mem tot = 0; + while (g->gray) + tot += propagatemark(g); + return tot; +} + + +/* +** Traverse all ephemeron tables propagating marks from keys to values. +** Repeat until it converges, that is, nothing new is marked. 'dir' +** inverts the direction of the traversals, trying to speed up +** convergence on chains in the same table. +** +*/ +static void convergeephemerons (global_State *g) { + int changed; + int dir = 0; + do { + GCObject *w; + GCObject *next = g->ephemeron; /* get ephemeron list */ + g->ephemeron = NULL; /* tables may return to this list when traversed */ + changed = 0; + while ((w = next) != NULL) { /* for each ephemeron table */ + Table *h = gco2t(w); + next = h->gclist; /* list is rebuilt during loop */ + nw2black(h); /* out of the list (for now) */ + if (traverseephemeron(g, h, dir)) { /* marked some value? */ + propagateall(g); /* propagate changes */ + changed = 1; /* will have to revisit all ephemeron tables */ + } + } + dir = !dir; /* invert direction next time */ + } while (changed); /* repeat until no more changes */ +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Sweep Functions +** ======================================================= +*/ + + +/* +** clear entries with unmarked keys from all weaktables in list 'l' +*/ +static void clearbykeys (global_State *g, GCObject *l) { + for (; l; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *limit = gnodelast(h); + Node *n; + for (n = gnode(h, 0); n < limit; n++) { + if (iscleared(g, gckeyN(n))) /* unmarked key? */ + setempty(gval(n)); /* remove entry */ + if (isempty(gval(n))) /* is entry empty? */ + clearkey(n); /* clear its key */ + } + } +} + + +/* +** clear entries with unmarked values from all weaktables in list 'l' up +** to element 'f' +*/ +static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + unsigned int i; + unsigned int asize = luaH_realasize(h); + for (i = 0; i < asize; i++) { + TValue *o = &h->array[i]; + if (iscleared(g, gcvalueN(o))) /* value was collected? */ + setempty(o); /* remove entry */ + } + for (n = gnode(h, 0); n < limit; n++) { + if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */ + setempty(gval(n)); /* remove entry */ + if (isempty(gval(n))) /* is entry empty? */ + clearkey(n); /* clear its key */ + } + } +} + + +static void freeupval (lua_State *L, UpVal *uv) { + if (upisopen(uv)) + luaF_unlinkupval(uv); + luaM_free(L, uv); +} + + +static void freeobj (lua_State *L, GCObject *o) { + switch (o->tt) { + case LUA_VPROTO: + luaF_freeproto(L, gco2p(o)); + break; + case LUA_VUPVAL: + freeupval(L, gco2upv(o)); + break; + case LUA_VLCL: { + LClosure *cl = gco2lcl(o); + luaM_freemem(L, cl, sizeLclosure(cl->nupvalues)); + break; + } + case LUA_VCCL: { + CClosure *cl = gco2ccl(o); + luaM_freemem(L, cl, sizeCclosure(cl->nupvalues)); + break; + } + case LUA_VTABLE: + luaH_free(L, gco2t(o)); + break; + case LUA_VTHREAD: + luaE_freethread(L, gco2th(o)); + break; + case LUA_VUSERDATA: { + Udata *u = gco2u(o); + luaM_freemem(L, o, sizeudata(u->nuvalue, u->len)); + break; + } + case LUA_VSHRSTR: { + TString *ts = gco2ts(o); + luaS_remove(L, ts); /* remove it from hash table */ + luaM_freemem(L, ts, sizelstring(ts->shrlen)); + break; + } + case LUA_VLNGSTR: { + TString *ts = gco2ts(o); + luaM_freemem(L, ts, sizelstring(ts->u.lnglen)); + break; + } + default: lua_assert(0); + } +} + + +/* +** sweep at most 'countin' elements from a list of GCObjects erasing dead +** objects, where a dead object is one marked with the old (non current) +** white; change all non-dead objects back to white, preparing for next +** collection cycle. Return where to continue the traversal or NULL if +** list is finished. ('*countout' gets the number of elements traversed.) +*/ +static GCObject **sweeplist (lua_State *L, GCObject **p, int countin, + int *countout) { + global_State *g = G(L); + int ow = otherwhite(g); + int i; + int white = luaC_white(g); /* current white */ + for (i = 0; *p != NULL && i < countin; i++) { + GCObject *curr = *p; + int marked = curr->marked; + if (isdeadm(ow, marked)) { /* is 'curr' dead? */ + *p = curr->next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + else { /* change mark to 'white' */ + curr->marked = cast_byte((marked & ~maskgcbits) | white); + p = &curr->next; /* go to next element */ + } + } + if (countout) + *countout = i; /* number of elements traversed */ + return (*p == NULL) ? NULL : p; +} + + +/* +** sweep a list until a live object (or end of list) +*/ +static GCObject **sweeptolive (lua_State *L, GCObject **p) { + GCObject **old = p; + do { + p = sweeplist(L, p, 1, NULL); + } while (p == old); + return p; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Finalization +** ======================================================= +*/ + +/* +** If possible, shrink string table. +*/ +static void checkSizes (lua_State *L, global_State *g) { + if (!g->gcemergency) { + if (g->strt.nuse < g->strt.size / 4) { /* string table too big? */ + l_mem olddebt = g->GCdebt; + luaS_resize(L, g->strt.size / 2); + g->GCestimate += g->GCdebt - olddebt; /* correct estimate */ + } + } +} + + +/* +** Get the next udata to be finalized from the 'tobefnz' list, and +** link it back into the 'allgc' list. +*/ +static GCObject *udata2finalize (global_State *g) { + GCObject *o = g->tobefnz; /* get first element */ + lua_assert(tofinalize(o)); + g->tobefnz = o->next; /* remove it from 'tobefnz' list */ + o->next = g->allgc; /* return it to 'allgc' list */ + g->allgc = o; + resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ + if (issweepphase(g)) + makewhite(g, o); /* "sweep" object */ + else if (getage(o) == G_OLD1) + g->firstold1 = o; /* it is the first OLD1 object in the list */ + return o; +} + + +static void dothecall (lua_State *L, void *ud) { + UNUSED(ud); + luaD_callnoyield(L, L->top - 2, 0); +} + + +static void GCTM (lua_State *L) { + global_State *g = G(L); + const TValue *tm; + TValue v; + lua_assert(!g->gcemergency); + setgcovalue(L, &v, udata2finalize(g)); + tm = luaT_gettmbyobj(L, &v, TM_GC); + if (!notm(tm)) { /* is there a finalizer? */ + int status; + lu_byte oldah = L->allowhook; + int running = g->gcrunning; + L->allowhook = 0; /* stop debug hooks during GC metamethod */ + g->gcrunning = 0; /* avoid GC steps */ + setobj2s(L, L->top++, tm); /* push finalizer... */ + setobj2s(L, L->top++, &v); /* ... and its argument */ + L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ + status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); + L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ + L->allowhook = oldah; /* restore hooks */ + g->gcrunning = running; /* restore state */ + if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */ + luaE_warnerror(L, "__gc metamethod"); + L->top--; /* pops error object */ + } + } +} + + +/* +** Call a few finalizers +*/ +static int runafewfinalizers (lua_State *L, int n) { + global_State *g = G(L); + int i; + for (i = 0; i < n && g->tobefnz; i++) + GCTM(L); /* call one finalizer */ + return i; +} + + +/* +** call all pending finalizers +*/ +static void callallpendingfinalizers (lua_State *L) { + global_State *g = G(L); + while (g->tobefnz) + GCTM(L); +} + + +/* +** find last 'next' field in list 'p' list (to add elements in its end) +*/ +static GCObject **findlast (GCObject **p) { + while (*p != NULL) + p = &(*p)->next; + return p; +} + + +/* +** Move all unreachable objects (or 'all' objects) that need +** finalization from list 'finobj' to list 'tobefnz' (to be finalized). +** (Note that objects after 'finobjold1' cannot be white, so they +** don't need to be traversed. In incremental mode, 'finobjold1' is NULL, +** so the whole list is traversed.) +*/ +static void separatetobefnz (global_State *g, int all) { + GCObject *curr; + GCObject **p = &g->finobj; + GCObject **lastnext = findlast(&g->tobefnz); + while ((curr = *p) != g->finobjold1) { /* traverse all finalizable objects */ + lua_assert(tofinalize(curr)); + if (!(iswhite(curr) || all)) /* not being collected? */ + p = &curr->next; /* don't bother with it */ + else { + if (curr == g->finobjsur) /* removing 'finobjsur'? */ + g->finobjsur = curr->next; /* correct it */ + *p = curr->next; /* remove 'curr' from 'finobj' list */ + curr->next = *lastnext; /* link at the end of 'tobefnz' list */ + *lastnext = curr; + lastnext = &curr->next; + } + } +} + + +/* +** If pointer 'p' points to 'o', move it to the next element. +*/ +static void checkpointer (GCObject **p, GCObject *o) { + if (o == *p) + *p = o->next; +} + + +/* +** Correct pointers to objects inside 'allgc' list when +** object 'o' is being removed from the list. +*/ +static void correctpointers (global_State *g, GCObject *o) { + checkpointer(&g->survival, o); + checkpointer(&g->old1, o); + checkpointer(&g->reallyold, o); + checkpointer(&g->firstold1, o); +} + + +/* +** if object 'o' has a finalizer, remove it from 'allgc' list (must +** search the list to find it) and link it in 'finobj' list. +*/ +void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { + global_State *g = G(L); + if (tofinalize(o) || /* obj. is already marked... */ + gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ + return; /* nothing to be done */ + else { /* move 'o' to 'finobj' list */ + GCObject **p; + if (issweepphase(g)) { + makewhite(g, o); /* "sweep" object 'o' */ + if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ + g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */ + } + else + correctpointers(g, o); + /* search for pointer pointing to 'o' */ + for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } + *p = o->next; /* remove 'o' from 'allgc' list */ + o->next = g->finobj; /* link it in 'finobj' list */ + g->finobj = o; + l_setbit(o->marked, FINALIZEDBIT); /* mark it as such */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Generational Collector +** ======================================================= +*/ + +static void setpause (global_State *g); + + +/* +** Sweep a list of objects to enter generational mode. Deletes dead +** objects and turns the non dead to old. All non-dead threads---which +** are now old---must be in a gray list. Everything else is not in a +** gray list. Open upvalues are also kept gray. +*/ +static void sweep2old (lua_State *L, GCObject **p) { + GCObject *curr; + global_State *g = G(L); + while ((curr = *p) != NULL) { + if (iswhite(curr)) { /* is 'curr' dead? */ + lua_assert(isdead(g, curr)); + *p = curr->next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + else { /* all surviving objects become old */ + setage(curr, G_OLD); + if (curr->tt == LUA_VTHREAD) { /* threads must be watched */ + lua_State *th = gco2th(curr); + linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ + } + else if (curr->tt == LUA_VUPVAL && upisopen(gco2upv(curr))) + set2gray(curr); /* open upvalues are always gray */ + else /* everything else is black */ + nw2black(curr); + p = &curr->next; /* go to next element */ + } + } +} + + +/* +** Sweep for generational mode. Delete dead objects. (Because the +** collection is not incremental, there are no "new white" objects +** during the sweep. So, any white object must be dead.) For +** non-dead objects, advance their ages and clear the color of +** new objects. (Old objects keep their colors.) +** The ages of G_TOUCHED1 and G_TOUCHED2 objects cannot be advanced +** here, because these old-generation objects are usually not swept +** here. They will all be advanced in 'correctgraylist'. That function +** will also remove objects turned white here from any gray list. +*/ +static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, + GCObject *limit, GCObject **pfirstold1) { + static const lu_byte nextage[] = { + G_SURVIVAL, /* from G_NEW */ + G_OLD1, /* from G_SURVIVAL */ + G_OLD1, /* from G_OLD0 */ + G_OLD, /* from G_OLD1 */ + G_OLD, /* from G_OLD (do not change) */ + G_TOUCHED1, /* from G_TOUCHED1 (do not change) */ + G_TOUCHED2 /* from G_TOUCHED2 (do not change) */ + }; + int white = luaC_white(g); + GCObject *curr; + while ((curr = *p) != limit) { + if (iswhite(curr)) { /* is 'curr' dead? */ + lua_assert(!isold(curr) && isdead(g, curr)); + *p = curr->next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + else { /* correct mark and age */ + if (getage(curr) == G_NEW) { /* new objects go back to white */ + int marked = curr->marked & ~maskgcbits; /* erase GC bits */ + curr->marked = cast_byte(marked | G_SURVIVAL | white); + } + else { /* all other objects will be old, and so keep their color */ + setage(curr, nextage[getage(curr)]); + if (getage(curr) == G_OLD1 && *pfirstold1 == NULL) + *pfirstold1 = curr; /* first OLD1 object in the list */ + } + p = &curr->next; /* go to next element */ + } + } + return p; +} + + +/* +** Traverse a list making all its elements white and clearing their +** age. In incremental mode, all objects are 'new' all the time, +** except for fixed strings (which are always old). +*/ +static void whitelist (global_State *g, GCObject *p) { + int white = luaC_white(g); + for (; p != NULL; p = p->next) + p->marked = cast_byte((p->marked & ~maskgcbits) | white); +} + + +/* +** Correct a list of gray objects. Return pointer to where rest of the +** list should be linked. +** Because this correction is done after sweeping, young objects might +** be turned white and still be in the list. They are only removed. +** 'TOUCHED1' objects are advanced to 'TOUCHED2' and remain on the list; +** Non-white threads also remain on the list; 'TOUCHED2' objects become +** regular old; they and anything else are removed from the list. +*/ +static GCObject **correctgraylist (GCObject **p) { + GCObject *curr; + while ((curr = *p) != NULL) { + GCObject **next = getgclist(curr); + if (iswhite(curr)) + goto remove; /* remove all white objects */ + else if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ + lua_assert(isgray(curr)); + nw2black(curr); /* make it black, for next barrier */ + changeage(curr, G_TOUCHED1, G_TOUCHED2); + goto remain; /* keep it in the list and go to next element */ + } + else if (curr->tt == LUA_VTHREAD) { + lua_assert(isgray(curr)); + goto remain; /* keep non-white threads on the list */ + } + else { /* everything else is removed */ + lua_assert(isold(curr)); /* young objects should be white here */ + if (getage(curr) == G_TOUCHED2) /* advance from TOUCHED2... */ + changeage(curr, G_TOUCHED2, G_OLD); /* ... to OLD */ + nw2black(curr); /* make object black (to be removed) */ + goto remove; + } + remove: *p = *next; continue; + remain: p = next; continue; + } + return p; +} + + +/* +** Correct all gray lists, coalescing them into 'grayagain'. +*/ +static void correctgraylists (global_State *g) { + GCObject **list = correctgraylist(&g->grayagain); + *list = g->weak; g->weak = NULL; + list = correctgraylist(list); + *list = g->allweak; g->allweak = NULL; + list = correctgraylist(list); + *list = g->ephemeron; g->ephemeron = NULL; + correctgraylist(list); +} + + +/* +** Mark black 'OLD1' objects when starting a new young collection. +** Gray objects are already in some gray list, and so will be visited +** in the atomic step. +*/ +static void markold (global_State *g, GCObject *from, GCObject *to) { + GCObject *p; + for (p = from; p != to; p = p->next) { + if (getage(p) == G_OLD1) { + lua_assert(!iswhite(p)); + changeage(p, G_OLD1, G_OLD); /* now they are old */ + if (isblack(p)) + reallymarkobject(g, p); + } + } +} + + +/* +** Finish a young-generation collection. +*/ +static void finishgencycle (lua_State *L, global_State *g) { + correctgraylists(g); + checkSizes(L, g); + g->gcstate = GCSpropagate; /* skip restart */ + if (!g->gcemergency) + callallpendingfinalizers(L); +} + + +/* +** Does a young collection. First, mark 'OLD1' objects. Then does the +** atomic step. Then, sweep all lists and advance pointers. Finally, +** finish the collection. +*/ +static void youngcollection (lua_State *L, global_State *g) { + GCObject **psurvival; /* to point to first non-dead survival object */ + GCObject *dummy; /* dummy out parameter to 'sweepgen' */ + lua_assert(g->gcstate == GCSpropagate); + if (g->firstold1) { /* are there regular OLD1 objects? */ + markold(g, g->firstold1, g->reallyold); /* mark them */ + g->firstold1 = NULL; /* no more OLD1 objects (for now) */ + } + markold(g, g->finobj, g->finobjrold); + markold(g, g->tobefnz, NULL); + atomic(L); + + /* sweep nursery and get a pointer to its last live element */ + g->gcstate = GCSswpallgc; + psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1); + /* sweep 'survival' */ + sweepgen(L, g, psurvival, g->old1, &g->firstold1); + g->reallyold = g->old1; + g->old1 = *psurvival; /* 'survival' survivals are old now */ + g->survival = g->allgc; /* all news are survivals */ + + /* repeat for 'finobj' lists */ + dummy = NULL; /* no 'firstold1' optimization for 'finobj' lists */ + psurvival = sweepgen(L, g, &g->finobj, g->finobjsur, &dummy); + /* sweep 'survival' */ + sweepgen(L, g, psurvival, g->finobjold1, &dummy); + g->finobjrold = g->finobjold1; + g->finobjold1 = *psurvival; /* 'survival' survivals are old now */ + g->finobjsur = g->finobj; /* all news are survivals */ + + sweepgen(L, g, &g->tobefnz, NULL, &dummy); + finishgencycle(L, g); +} + + +/* +** Clears all gray lists, sweeps objects, and prepare sublists to enter +** generational mode. The sweeps remove dead objects and turn all +** surviving objects to old. Threads go back to 'grayagain'; everything +** else is turned black (not in any gray list). +*/ +static void atomic2gen (lua_State *L, global_State *g) { + cleargraylists(g); + /* sweep all elements making them old */ + g->gcstate = GCSswpallgc; + sweep2old(L, &g->allgc); + /* everything alive now is old */ + g->reallyold = g->old1 = g->survival = g->allgc; + g->firstold1 = NULL; /* there are no OLD1 objects anywhere */ + + /* repeat for 'finobj' lists */ + sweep2old(L, &g->finobj); + g->finobjrold = g->finobjold1 = g->finobjsur = g->finobj; + + sweep2old(L, &g->tobefnz); + + g->gckind = KGC_GEN; + g->lastatomic = 0; + g->GCestimate = gettotalbytes(g); /* base for memory control */ + finishgencycle(L, g); +} + + +/* +** Enter generational mode. Must go until the end of an atomic cycle +** to ensure that all objects are correctly marked and weak tables +** are cleared. Then, turn all objects into old and finishes the +** collection. +*/ +static lu_mem entergen (lua_State *L, global_State *g) { + lu_mem numobjs; + luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ + luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ + numobjs = atomic(L); /* propagates all and then do the atomic stuff */ + atomic2gen(L, g); + return numobjs; +} + + +/* +** Enter incremental mode. Turn all objects white, make all +** intermediate lists point to NULL (to avoid invalid pointers), +** and go to the pause state. +*/ +static void enterinc (global_State *g) { + whitelist(g, g->allgc); + g->reallyold = g->old1 = g->survival = NULL; + whitelist(g, g->finobj); + whitelist(g, g->tobefnz); + g->finobjrold = g->finobjold1 = g->finobjsur = NULL; + g->gcstate = GCSpause; + g->gckind = KGC_INC; + g->lastatomic = 0; +} + + +/* +** Change collector mode to 'newmode'. +*/ +void luaC_changemode (lua_State *L, int newmode) { + global_State *g = G(L); + if (newmode != g->gckind) { + if (newmode == KGC_GEN) /* entering generational mode? */ + entergen(L, g); + else + enterinc(g); /* entering incremental mode */ + } + g->lastatomic = 0; +} + + +/* +** Does a full collection in generational mode. +*/ +static lu_mem fullgen (lua_State *L, global_State *g) { + enterinc(g); + return entergen(L, g); +} + + +/* +** Set debt for the next minor collection, which will happen when +** memory grows 'genminormul'%. +*/ +static void setminordebt (global_State *g) { + luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); +} + + +/* +** Does a major collection after last collection was a "bad collection". +** +** When the program is building a big structure, it allocates lots of +** memory but generates very little garbage. In those scenarios, +** the generational mode just wastes time doing small collections, and +** major collections are frequently what we call a "bad collection", a +** collection that frees too few objects. To avoid the cost of switching +** between generational mode and the incremental mode needed for full +** (major) collections, the collector tries to stay in incremental mode +** after a bad collection, and to switch back to generational mode only +** after a "good" collection (one that traverses less than 9/8 objects +** of the previous one). +** The collector must choose whether to stay in incremental mode or to +** switch back to generational mode before sweeping. At this point, it +** does not know the real memory in use, so it cannot use memory to +** decide whether to return to generational mode. Instead, it uses the +** number of objects traversed (returned by 'atomic') as a proxy. The +** field 'g->lastatomic' keeps this count from the last collection. +** ('g->lastatomic != 0' also means that the last collection was bad.) +*/ +static void stepgenfull (lua_State *L, global_State *g) { + lu_mem newatomic; /* count of traversed objects */ + lu_mem lastatomic = g->lastatomic; /* count from last collection */ + if (g->gckind == KGC_GEN) /* still in generational mode? */ + enterinc(g); /* enter incremental mode */ + luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ + newatomic = atomic(L); /* mark everybody */ + if (newatomic < lastatomic + (lastatomic >> 3)) { /* good collection? */ + atomic2gen(L, g); /* return to generational mode */ + setminordebt(g); + } + else { /* another bad collection; stay in incremental mode */ + g->GCestimate = gettotalbytes(g); /* first estimate */; + entersweep(L); + luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ + setpause(g); + g->lastatomic = newatomic; + } +} + + +/* +** Does a generational "step". +** Usually, this means doing a minor collection and setting the debt to +** make another collection when memory grows 'genminormul'% larger. +** +** However, there are exceptions. If memory grows 'genmajormul'% +** larger than it was at the end of the last major collection (kept +** in 'g->GCestimate'), the function does a major collection. At the +** end, it checks whether the major collection was able to free a +** decent amount of memory (at least half the growth in memory since +** previous major collection). If so, the collector keeps its state, +** and the next collection will probably be minor again. Otherwise, +** we have what we call a "bad collection". In that case, set the field +** 'g->lastatomic' to signal that fact, so that the next collection will +** go to 'stepgenfull'. +** +** 'GCdebt <= 0' means an explicit call to GC step with "size" zero; +** in that case, do a minor collection. +*/ +static void genstep (lua_State *L, global_State *g) { + if (g->lastatomic != 0) /* last collection was a bad one? */ + stepgenfull(L, g); /* do a full step */ + else { + lu_mem majorbase = g->GCestimate; /* memory after last major collection */ + lu_mem majorinc = (majorbase / 100) * getgcparam(g->genmajormul); + if (g->GCdebt > 0 && gettotalbytes(g) > majorbase + majorinc) { + lu_mem numobjs = fullgen(L, g); /* do a major collection */ + if (gettotalbytes(g) < majorbase + (majorinc / 2)) { + /* collected at least half of memory growth since last major + collection; keep doing minor collections */ + setminordebt(g); + } + else { /* bad collection */ + g->lastatomic = numobjs; /* signal that last collection was bad */ + setpause(g); /* do a long wait for next (major) collection */ + } + } + else { /* regular case; do a minor collection */ + youngcollection(L, g); + setminordebt(g); + g->GCestimate = majorbase; /* preserve base value */ + } + } + lua_assert(isdecGCmodegen(g)); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** GC control +** ======================================================= +*/ + + +/* +** Set the "time" to wait before starting a new GC cycle; cycle will +** start when memory use hits the threshold of ('estimate' * pause / +** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, +** because Lua cannot even start with less than PAUSEADJ bytes). +*/ +static void setpause (global_State *g) { + l_mem threshold, debt; + int pause = getgcparam(g->gcpause); + l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ + lua_assert(estimate > 0); + threshold = (pause < MAX_LMEM / estimate) /* overflow? */ + ? estimate * pause /* no overflow */ + : MAX_LMEM; /* overflow; truncate to maximum */ + debt = gettotalbytes(g) - threshold; + if (debt > 0) debt = 0; + luaE_setdebt(g, debt); +} + + +/* +** Enter first sweep phase. +** The call to 'sweeptolive' makes the pointer point to an object +** inside the list (instead of to the header), so that the real sweep do +** not need to skip objects created between "now" and the start of the +** real sweep. +*/ +static void entersweep (lua_State *L) { + global_State *g = G(L); + g->gcstate = GCSswpallgc; + lua_assert(g->sweepgc == NULL); + g->sweepgc = sweeptolive(L, &g->allgc); +} + + +/* +** Delete all objects in list 'p' until (but not including) object +** 'limit'. +*/ +static void deletelist (lua_State *L, GCObject *p, GCObject *limit) { + while (p != limit) { + GCObject *next = p->next; + freeobj(L, p); + p = next; + } +} + + +/* +** Call all finalizers of the objects in the given Lua state, and +** then free all objects, except for the main thread. +*/ +void luaC_freeallobjects (lua_State *L) { + global_State *g = G(L); + luaC_changemode(L, KGC_INC); + separatetobefnz(g, 1); /* separate all objects with finalizers */ + lua_assert(g->finobj == NULL); + callallpendingfinalizers(L); + deletelist(L, g->allgc, obj2gco(g->mainthread)); + deletelist(L, g->finobj, NULL); + deletelist(L, g->fixedgc, NULL); /* collect fixed objects */ + lua_assert(g->strt.nuse == 0); +} + + +static lu_mem atomic (lua_State *L) { + global_State *g = G(L); + lu_mem work = 0; + GCObject *origweak, *origall; + GCObject *grayagain = g->grayagain; /* save original list */ + g->grayagain = NULL; + lua_assert(g->ephemeron == NULL && g->weak == NULL); + lua_assert(!iswhite(g->mainthread)); + g->gcstate = GCSatomic; + markobject(g, L); /* mark running thread */ + /* registry and global metatables may be changed by API */ + markvalue(g, &g->l_registry); + markmt(g); /* mark global metatables */ + work += propagateall(g); /* empties 'gray' list */ + /* remark occasional upvalues of (maybe) dead threads */ + work += remarkupvals(g); + work += propagateall(g); /* propagate changes */ + g->gray = grayagain; + work += propagateall(g); /* traverse 'grayagain' list */ + convergeephemerons(g); + /* at this point, all strongly accessible objects are marked. */ + /* Clear values from weak tables, before checking finalizers */ + clearbyvalues(g, g->weak, NULL); + clearbyvalues(g, g->allweak, NULL); + origweak = g->weak; origall = g->allweak; + separatetobefnz(g, 0); /* separate objects to be finalized */ + work += markbeingfnz(g); /* mark objects that will be finalized */ + work += propagateall(g); /* remark, to propagate 'resurrection' */ + convergeephemerons(g); + /* at this point, all resurrected objects are marked. */ + /* remove dead objects from weak tables */ + clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron tables */ + clearbykeys(g, g->allweak); /* clear keys from all 'allweak' tables */ + /* clear values from resurrected weak tables */ + clearbyvalues(g, g->weak, origweak); + clearbyvalues(g, g->allweak, origall); + luaS_clearcache(g); + g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ + lua_assert(g->gray == NULL); + return work; /* estimate of slots marked by 'atomic' */ +} + + +static int sweepstep (lua_State *L, global_State *g, + int nextstate, GCObject **nextlist) { + if (g->sweepgc) { + l_mem olddebt = g->GCdebt; + int count; + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX, &count); + g->GCestimate += g->GCdebt - olddebt; /* update estimate */ + return count; + } + else { /* enter next state */ + g->gcstate = nextstate; + g->sweepgc = nextlist; + return 0; /* no work done */ + } +} + + +static lu_mem singlestep (lua_State *L) { + global_State *g = G(L); + lu_mem work; + lua_assert(!g->gcstopem); /* collector is not reentrant */ + g->gcstopem = 1; /* no emergency collections while collecting */ + switch (g->gcstate) { + case GCSpause: { + restartcollection(g); + g->gcstate = GCSpropagate; + work = 1; + break; + } + case GCSpropagate: { + if (g->gray == NULL) { /* no more gray objects? */ + g->gcstate = GCSenteratomic; /* finish propagate phase */ + work = 0; + } + else + work = propagatemark(g); /* traverse one gray object */ + break; + } + case GCSenteratomic: { + work = atomic(L); /* work is what was traversed by 'atomic' */ + entersweep(L); + g->GCestimate = gettotalbytes(g); /* first estimate */; + break; + } + case GCSswpallgc: { /* sweep "regular" objects */ + work = sweepstep(L, g, GCSswpfinobj, &g->finobj); + break; + } + case GCSswpfinobj: { /* sweep objects with finalizers */ + work = sweepstep(L, g, GCSswptobefnz, &g->tobefnz); + break; + } + case GCSswptobefnz: { /* sweep objects to be finalized */ + work = sweepstep(L, g, GCSswpend, NULL); + break; + } + case GCSswpend: { /* finish sweeps */ + checkSizes(L, g); + g->gcstate = GCScallfin; + work = 0; + break; + } + case GCScallfin: { /* call remaining finalizers */ + if (g->tobefnz && !g->gcemergency) { + g->gcstopem = 0; /* ok collections during finalizers */ + work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST; + } + else { /* emergency mode or no more finalizers */ + g->gcstate = GCSpause; /* finish collection */ + work = 0; + } + break; + } + default: lua_assert(0); return 0; + } + g->gcstopem = 0; + return work; +} + + +/* +** advances the garbage collector until it reaches a state allowed +** by 'statemask' +*/ +void luaC_runtilstate (lua_State *L, int statesmask) { + global_State *g = G(L); + while (!testbit(statesmask, g->gcstate)) + singlestep(L); +} + + +/* +** Performs a basic incremental step. The debt and step size are +** converted from bytes to "units of work"; then the function loops +** running single steps until adding that many units of work or +** finishing a cycle (pause state). Finally, it sets the debt that +** controls when next step will be performed. +*/ +static void incstep (lua_State *L, global_State *g) { + int stepmul = (getgcparam(g->gcstepmul) | 1); /* avoid division by 0 */ + l_mem debt = (g->GCdebt / WORK2MEM) * stepmul; + l_mem stepsize = (g->gcstepsize <= log2maxs(l_mem)) + ? ((cast(l_mem, 1) << g->gcstepsize) / WORK2MEM) * stepmul + : MAX_LMEM; /* overflow; keep maximum value */ + do { /* repeat until pause or enough "credit" (negative debt) */ + lu_mem work = singlestep(L); /* perform one single step */ + debt -= work; + } while (debt > -stepsize && g->gcstate != GCSpause); + if (g->gcstate == GCSpause) + setpause(g); /* pause until next cycle */ + else { + debt = (debt / stepmul) * WORK2MEM; /* convert 'work units' to bytes */ + luaE_setdebt(g, debt); + } +} + +/* +** performs a basic GC step if collector is running +*/ +void luaC_step (lua_State *L) { + global_State *g = G(L); + lua_assert(!g->gcemergency); + if (g->gcrunning) { /* running? */ + if(isdecGCmodegen(g)) + genstep(L, g); + else + incstep(L, g); + } +} + + +/* +** Perform a full collection in incremental mode. +** Before running the collection, check 'keepinvariant'; if it is true, +** there may be some objects marked as black, so the collector has +** to sweep all objects to turn them back to white (as white has not +** changed, nothing will be collected). +*/ +static void fullinc (lua_State *L, global_State *g) { + if (keepinvariant(g)) /* black objects? */ + entersweep(L); /* sweep everything to turn them back to white */ + /* finish any pending sweep phase to start a new cycle */ + luaC_runtilstate(L, bitmask(GCSpause)); + luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ + /* estimate must be correct after a full GC cycle */ + lua_assert(g->GCestimate == gettotalbytes(g)); + luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ + setpause(g); +} + + +/* +** Performs a full GC cycle; if 'isemergency', set a flag to avoid +** some operations which could change the interpreter state in some +** unexpected ways (running finalizers and shrinking some structures). +*/ +void luaC_fullgc (lua_State *L, int isemergency) { + global_State *g = G(L); + lua_assert(!g->gcemergency); + g->gcemergency = isemergency; /* set flag */ + if (g->gckind == KGC_INC) + fullinc(L, g); + else + fullgen(L, g); + g->gcemergency = 0; +} + +/* }====================================================== */ + + diff --git a/lua/lgc.h b/lua/lgc.h new file mode 100644 index 0000000..073e2a4 --- /dev/null +++ b/lua/lgc.h @@ -0,0 +1,189 @@ +/* +** $Id: lgc.h $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#ifndef lgc_h +#define lgc_h + + +#include "lobject.h" +#include "lstate.h" + +/* +** Collectable objects may have one of three colors: white, which means +** the object is not marked; gray, which means the object is marked, but +** its references may be not marked; and black, which means that the +** object and all its references are marked. The main invariant of the +** garbage collector, while marking objects, is that a black object can +** never point to a white one. Moreover, any gray object must be in a +** "gray list" (gray, grayagain, weak, allweak, ephemeron) so that it +** can be visited again before finishing the collection cycle. (Open +** upvalues are an exception to this rule.) These lists have no meaning +** when the invariant is not being enforced (e.g., sweep phase). +*/ + + +/* +** Possible states of the Garbage Collector +*/ +#define GCSpropagate 0 +#define GCSenteratomic 1 +#define GCSatomic 2 +#define GCSswpallgc 3 +#define GCSswpfinobj 4 +#define GCSswptobefnz 5 +#define GCSswpend 6 +#define GCScallfin 7 +#define GCSpause 8 + + +#define issweepphase(g) \ + (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) + + +/* +** macro to tell when main invariant (white objects cannot point to black +** ones) must be kept. During a collection, the sweep +** phase may break the invariant, as objects turned white may point to +** still-black objects. The invariant is restored when sweep ends and +** all objects are white again. +*/ + +#define keepinvariant(g) ((g)->gcstate <= GCSatomic) + + +/* +** some useful bit tricks +*/ +#define resetbits(x,m) ((x) &= cast_byte(~(m))) +#define setbits(x,m) ((x) |= (m)) +#define testbits(x,m) ((x) & (m)) +#define bitmask(b) (1<<(b)) +#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) +#define l_setbit(x,b) setbits(x, bitmask(b)) +#define resetbit(x,b) resetbits(x, bitmask(b)) +#define testbit(x,b) testbits(x, bitmask(b)) + + +/* +** Layout for bit use in 'marked' field. First three bits are +** used for object "age" in generational mode. Last bit is used +** by tests. +*/ +#define WHITE0BIT 3 /* object is white (type 0) */ +#define WHITE1BIT 4 /* object is white (type 1) */ +#define BLACKBIT 5 /* object is black */ +#define FINALIZEDBIT 6 /* object has been marked for finalization */ + +#define TESTBIT 7 + + + +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) + + +#define iswhite(x) testbits((x)->marked, WHITEBITS) +#define isblack(x) testbit((x)->marked, BLACKBIT) +#define isgray(x) /* neither white nor black */ \ + (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) + +#define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) + +#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) +#define isdeadm(ow,m) ((m) & (ow)) +#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) + +#define changewhite(x) ((x)->marked ^= WHITEBITS) +#define nw2black(x) \ + check_exp(!iswhite(x), l_setbit((x)->marked, BLACKBIT)) + +#define luaC_white(g) cast_byte((g)->currentwhite & WHITEBITS) + + +/* object age in generational mode */ +#define G_NEW 0 /* created in current cycle */ +#define G_SURVIVAL 1 /* created in previous cycle */ +#define G_OLD0 2 /* marked old by frw. barrier in this cycle */ +#define G_OLD1 3 /* first full cycle as old */ +#define G_OLD 4 /* really old object (not to be visited) */ +#define G_TOUCHED1 5 /* old object touched this cycle */ +#define G_TOUCHED2 6 /* old object touched in previous cycle */ + +#define AGEBITS 7 /* all age bits (111) */ + +#define getage(o) ((o)->marked & AGEBITS) +#define setage(o,a) ((o)->marked = cast_byte(((o)->marked & (~AGEBITS)) | a)) +#define isold(o) (getage(o) > G_SURVIVAL) + +#define changeage(o,f,t) \ + check_exp(getage(o) == (f), (o)->marked ^= ((f)^(t))) + + +/* Default Values for GC parameters */ +#define LUAI_GENMAJORMUL 100 +#define LUAI_GENMINORMUL 20 + +/* wait memory to double before starting new cycle */ +#define LUAI_GCPAUSE 200 + +/* +** some gc parameters are stored divided by 4 to allow a maximum value +** up to 1023 in a 'lu_byte'. +*/ +#define getgcparam(p) ((p) * 4) +#define setgcparam(p,v) ((p) = (v) / 4) + +#define LUAI_GCMUL 100 + +/* how much to allocate before next GC step (log2) */ +#define LUAI_GCSTEPSIZE 13 /* 8 KB */ + + +/* +** Check whether the declared GC mode is generational. While in +** generational mode, the collector can go temporarily to incremental +** mode to improve performance. This is signaled by 'g->lastatomic != 0'. +*/ +#define isdecGCmodegen(g) (g->gckind == KGC_GEN || g->lastatomic != 0) + +/* +** Does one step of collection when debt becomes positive. 'pre'/'pos' +** allows some adjustments to be done only when needed. macro +** 'condchangemem' is used only for heavy tests (forcing a full +** GC cycle on every opportunity) +*/ +#define luaC_condGC(L,pre,pos) \ + { if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \ + condchangemem(L,pre,pos); } + +/* more often than not, 'pre'/'pos' are empty */ +#define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0) + + +#define luaC_barrier(L,p,v) ( \ + (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ + luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0)) + +#define luaC_barrierback(L,p,v) ( \ + (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ + luaC_barrierback_(L,p) : cast_void(0)) + +#define luaC_objbarrier(L,p,o) ( \ + (isblack(p) && iswhite(o)) ? \ + luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) + +LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); +LUAI_FUNC void luaC_freeallobjects (lua_State *L); +LUAI_FUNC void luaC_step (lua_State *L); +LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); +LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); +LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); +LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); +LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); +LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); +LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); + + +#endif diff --git a/lua/linit.c b/lua/linit.c new file mode 100644 index 0000000..69808f8 --- /dev/null +++ b/lua/linit.c @@ -0,0 +1,65 @@ +/* +** $Id: linit.c $ +** Initialization of libraries for lua.c and other clients +** See Copyright Notice in lua.h +*/ + + +#define linit_c +#define LUA_LIB + +/* +** If you embed Lua in your program and need to open the standard +** libraries, call luaL_openlibs in your program. If you need a +** different set of libraries, copy this file to your project and edit +** it to suit your needs. +** +** You can also *preload* libraries, so that a later 'require' can +** open the library, which is already linked to the application. +** For that, do the following code: +** +** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); +** lua_pushcfunction(L, luaopen_modname); +** lua_setfield(L, -2, modname); +** lua_pop(L, 1); // remove PRELOAD table +*/ + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lualib.h" +#include "lauxlib.h" + + +/* +** these libs are loaded by lua.c and are readily available to any Lua +** program +*/ +static const luaL_Reg loadedlibs[] = { + {LUA_GNAME, luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_COLIBNAME, luaopen_coroutine}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_UTF8LIBNAME, luaopen_utf8}, + {LUA_DBLIBNAME, luaopen_debug}, + {NULL, NULL} +}; + + +LUALIB_API void luaL_openlibs (lua_State *L) { + const luaL_Reg *lib; + /* "require" functions from 'loadedlibs' and set results to global table */ + for (lib = loadedlibs; lib->func; lib++) { + luaL_requiref(L, lib->name, lib->func, 1); + lua_pop(L, 1); /* remove lib */ + } +} + diff --git a/lua/liolib.c b/lua/liolib.c new file mode 100644 index 0000000..b08397d --- /dev/null +++ b/lua/liolib.c @@ -0,0 +1,828 @@ +/* +** $Id: liolib.c $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + +#define liolib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + + +/* +** Change this macro to accept other modes for 'fopen' besides +** the standard ones. +*/ +#if !defined(l_checkmode) + +/* accepted extensions to 'mode' in 'fopen' */ +#if !defined(L_MODEEXT) +#define L_MODEEXT "b" +#endif + +/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */ +static int l_checkmode (const char *mode) { + return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && + (*mode != '+' || ((void)(++mode), 1)) && /* skip if char is '+' */ + (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */ +} + +#endif + +/* +** {====================================================== +** l_popen spawns a new process connected to the current +** one through the file streams. +** ======================================================= +*/ + +#if !defined(l_popen) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#define l_popen(L,c,m) (fflush(NULL), popen(c,m)) +#define l_pclose(L,file) (pclose(file)) + +#elif defined(LUA_USE_WINDOWS) /* }{ */ + +#define l_popen(L,c,m) (_popen(c,m)) +#define l_pclose(L,file) (_pclose(file)) + +#if !defined(l_checkmodep) +/* Windows accepts "[rw][bt]?" as valid modes */ +#define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && \ + (m[1] == '\0' || ((m[1] == 'b' || m[1] == 't') && m[2] == '\0'))) +#endif + +#else /* }{ */ + +/* ISO C definitions */ +#define l_popen(L,c,m) \ + ((void)c, (void)m, \ + luaL_error(L, "'popen' not supported"), \ + (FILE*)0) +#define l_pclose(L,file) ((void)L, (void)file, -1) + +#endif /* } */ + +#endif /* } */ + + +#if !defined(l_checkmodep) +/* By default, Lua accepts only "r" or "w" as valid modes */ +#define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && m[1] == '\0') +#endif + +/* }====================================================== */ + + +#if !defined(l_getc) /* { */ + +#if defined(LUA_USE_POSIX) +#define l_getc(f) getc_unlocked(f) +#define l_lockfile(f) flockfile(f) +#define l_unlockfile(f) funlockfile(f) +#else +#define l_getc(f) getc(f) +#define l_lockfile(f) ((void)0) +#define l_unlockfile(f) ((void)0) +#endif + +#endif /* } */ + + +/* +** {====================================================== +** l_fseek: configuration for longer offsets +** ======================================================= +*/ + +#if !defined(l_fseek) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#include + +#define l_fseek(f,o,w) fseeko(f,o,w) +#define l_ftell(f) ftello(f) +#define l_seeknum off_t + +#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \ + && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */ + +/* Windows (but not DDK) and Visual C++ 2005 or higher */ +#define l_fseek(f,o,w) _fseeki64(f,o,w) +#define l_ftell(f) _ftelli64(f) +#define l_seeknum __int64 + +#else /* }{ */ + +/* ISO C definitions */ +#define l_fseek(f,o,w) fseek(f,o,w) +#define l_ftell(f) ftell(f) +#define l_seeknum long + +#endif /* } */ + +#endif /* } */ + +/* }====================================================== */ + + + +#define IO_PREFIX "_IO_" +#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1) +#define IO_INPUT (IO_PREFIX "input") +#define IO_OUTPUT (IO_PREFIX "output") + + +typedef luaL_Stream LStream; + + +#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + +#define isclosed(p) ((p)->closef == NULL) + + +static int io_type (lua_State *L) { + LStream *p; + luaL_checkany(L, 1); + p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); + if (p == NULL) + luaL_pushfail(L); /* not a file */ + else if (isclosed(p)) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static int f_tostring (lua_State *L) { + LStream *p = tolstream(L); + if (isclosed(p)) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", p->f); + return 1; +} + + +static FILE *tofile (lua_State *L) { + LStream *p = tolstream(L); + if (l_unlikely(isclosed(p))) + luaL_error(L, "attempt to use a closed file"); + lua_assert(p->f); + return p->f; +} + + +/* +** When creating file handles, always creates a 'closed' file handle +** before opening the actual file; so, if there is a memory error, the +** handle is in a consistent state. +*/ +static LStream *newprefile (lua_State *L) { + LStream *p = (LStream *)lua_newuserdatauv(L, sizeof(LStream), 0); + p->closef = NULL; /* mark file handle as 'closed' */ + luaL_setmetatable(L, LUA_FILEHANDLE); + return p; +} + + +/* +** Calls the 'close' function from a file handle. The 'volatile' avoids +** a bug in some versions of the Clang compiler (e.g., clang 3.0 for +** 32 bits). +*/ +static int aux_close (lua_State *L) { + LStream *p = tolstream(L); + volatile lua_CFunction cf = p->closef; + p->closef = NULL; /* mark stream as closed */ + return (*cf)(L); /* close it */ +} + + +static int f_close (lua_State *L) { + tofile(L); /* make sure argument is an open stream */ + return aux_close(L); +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) /* no argument? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use default output */ + return f_close(L); +} + + +static int f_gc (lua_State *L) { + LStream *p = tolstream(L); + if (!isclosed(p) && p->f != NULL) + aux_close(L); /* ignore closed and incompletely open files */ + return 0; +} + + +/* +** function to close regular files +*/ +static int io_fclose (lua_State *L) { + LStream *p = tolstream(L); + int res = fclose(p->f); + return luaL_fileresult(L, (res == 0), NULL); +} + + +static LStream *newfile (lua_State *L) { + LStream *p = newprefile(L); + p->f = NULL; + p->closef = &io_fclose; + return p; +} + + +static void opencheck (lua_State *L, const char *fname, const char *mode) { + LStream *p = newfile(L); + p->f = fopen(fname, mode); + if (l_unlikely(p->f == NULL)) + luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno)); +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + LStream *p = newfile(L); + const char *md = mode; /* to traverse/check mode */ + luaL_argcheck(L, l_checkmode(md), 2, "invalid mode"); + p->f = fopen(filename, mode); + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; +} + + +/* +** function to close 'popen' files +*/ +static int io_pclose (lua_State *L) { + LStream *p = tolstream(L); + errno = 0; + return luaL_execresult(L, l_pclose(L, p->f)); +} + + +static int io_popen (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + LStream *p = newprefile(L); + luaL_argcheck(L, l_checkmodep(mode), 2, "invalid mode"); + p->f = l_popen(L, filename, mode); + p->closef = &io_pclose; + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; +} + + +static int io_tmpfile (lua_State *L) { + LStream *p = newfile(L); + p->f = tmpfile(); + return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, const char *findex) { + LStream *p; + lua_getfield(L, LUA_REGISTRYINDEX, findex); + p = (LStream *)lua_touserdata(L, -1); + if (l_unlikely(isclosed(p))) + luaL_error(L, "default %s file is closed", findex + IOPREF_LEN); + return p->f; +} + + +static int g_iofile (lua_State *L, const char *f, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + if (filename) + opencheck(L, filename, mode); + else { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_setfield(L, LUA_REGISTRYINDEX, f); + } + /* return current value */ + lua_getfield(L, LUA_REGISTRYINDEX, f); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +/* +** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit +** in the limit for upvalues of a closure) +*/ +#define MAXARGLINE 250 + +/* +** Auxiliary function to create the iteration function for 'lines'. +** The iteration function is a closure over 'io_readline', with +** the following upvalues: +** 1) The file being read (first value in the stack) +** 2) the number of arguments to read +** 3) a boolean, true iff file has to be closed when finished ('toclose') +** *) a variable number of format arguments (rest of the stack) +*/ +static void aux_lines (lua_State *L, int toclose) { + int n = lua_gettop(L) - 1; /* number of arguments to read */ + luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); + lua_pushvalue(L, 1); /* file */ + lua_pushinteger(L, n); /* number of arguments to read */ + lua_pushboolean(L, toclose); /* close/not close file when finished */ + lua_rotate(L, 2, 3); /* move the three values to their positions */ + lua_pushcclosure(L, io_readline, 3 + n); +} + + +static int f_lines (lua_State *L) { + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 0); + return 1; +} + + +/* +** Return an iteration function for 'io.lines'. If file has to be +** closed, also returns the file itself as a second result (to be +** closed as the state at the exit of a generic for). +*/ +static int io_lines (lua_State *L) { + int toclose; + if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ + if (lua_isnil(L, 1)) { /* no file name? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ + lua_replace(L, 1); /* put it at index 1 */ + tofile(L); /* check that it's a valid file handle */ + toclose = 0; /* do not close it after iteration */ + } + else { /* open a new file */ + const char *filename = luaL_checkstring(L, 1); + opencheck(L, filename, "r"); + lua_replace(L, 1); /* put file at index 1 */ + toclose = 1; /* close it after iteration */ + } + aux_lines(L, toclose); /* push iteration function */ + if (toclose) { + lua_pushnil(L); /* state */ + lua_pushnil(L); /* control */ + lua_pushvalue(L, 1); /* file is the to-be-closed variable (4th result) */ + return 4; + } + else + return 1; +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + +/* maximum length of a numeral */ +#if !defined (L_MAXLENNUM) +#define L_MAXLENNUM 200 +#endif + + +/* auxiliary structure used by 'read_number' */ +typedef struct { + FILE *f; /* file being read */ + int c; /* current character (look ahead) */ + int n; /* number of elements in buffer 'buff' */ + char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */ +} RN; + + +/* +** Add current char to buffer (if not out of space) and read next one +*/ +static int nextc (RN *rn) { + if (l_unlikely(rn->n >= L_MAXLENNUM)) { /* buffer overflow? */ + rn->buff[0] = '\0'; /* invalidate result */ + return 0; /* fail */ + } + else { + rn->buff[rn->n++] = rn->c; /* save current char */ + rn->c = l_getc(rn->f); /* read next one */ + return 1; + } +} + + +/* +** Accept current char if it is in 'set' (of size 2) +*/ +static int test2 (RN *rn, const char *set) { + if (rn->c == set[0] || rn->c == set[1]) + return nextc(rn); + else return 0; +} + + +/* +** Read a sequence of (hex)digits +*/ +static int readdigits (RN *rn, int hex) { + int count = 0; + while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn)) + count++; + return count; +} + + +/* +** Read a number: first reads a valid prefix of a numeral into a buffer. +** Then it calls 'lua_stringtonumber' to check whether the format is +** correct and to convert it to a Lua number. +*/ +static int read_number (lua_State *L, FILE *f) { + RN rn; + int count = 0; + int hex = 0; + char decp[2]; + rn.f = f; rn.n = 0; + decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */ + decp[1] = '.'; /* always accept a dot */ + l_lockfile(rn.f); + do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ + test2(&rn, "-+"); /* optional sign */ + if (test2(&rn, "00")) { + if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ + else count = 1; /* count initial '0' as a valid digit */ + } + count += readdigits(&rn, hex); /* integral part */ + if (test2(&rn, decp)) /* decimal point? */ + count += readdigits(&rn, hex); /* fractional part */ + if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */ + test2(&rn, "-+"); /* exponent sign */ + readdigits(&rn, 0); /* exponent digits */ + } + ungetc(rn.c, rn.f); /* unread look-ahead char */ + l_unlockfile(rn.f); + rn.buff[rn.n] = '\0'; /* finish string */ + if (l_likely(lua_stringtonumber(L, rn.buff))) + return 1; /* ok, it is a valid number */ + else { /* invalid format */ + lua_pushnil(L); /* "result" to be removed */ + return 0; /* read fails */ + } +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); /* no-op when c == EOF */ + lua_pushliteral(L, ""); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f, int chop) { + luaL_Buffer b; + int c; + luaL_buffinit(L, &b); + do { /* may need to read several chunks to get whole line */ + char *buff = luaL_prepbuffer(&b); /* preallocate buffer space */ + int i = 0; + l_lockfile(f); /* no memory errors can happen inside the lock */ + while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n') + buff[i++] = c; /* read up to end of line or buffer limit */ + l_unlockfile(f); + luaL_addsize(&b, i); + } while (c != EOF && c != '\n'); /* repeat until end of line */ + if (!chop && c == '\n') /* want a newline and have one? */ + luaL_addchar(&b, c); /* add ending newline to result */ + luaL_pushresult(&b); /* close buffer */ + /* return ok if read something (either a newline or something else) */ + return (c == '\n' || lua_rawlen(L, -1) > 0); +} + + +static void read_all (lua_State *L, FILE *f) { + size_t nr; + luaL_Buffer b; + luaL_buffinit(L, &b); + do { /* read file in chunks of LUAL_BUFFERSIZE bytes */ + char *p = luaL_prepbuffer(&b); + nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f); + luaL_addsize(&b, nr); + } while (nr == LUAL_BUFFERSIZE); + luaL_pushresult(&b); /* close buffer */ +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t nr; /* number of chars actually read */ + char *p; + luaL_Buffer b; + luaL_buffinit(L, &b); + p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ + nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ + luaL_addsize(&b, nr); + luaL_pushresult(&b); /* close buffer */ + return (nr > 0); /* true iff read something */ +} + + +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int n, success; + clearerr(f); + if (nargs == 0) { /* no arguments? */ + success = read_line(L, f, 1); + n = first + 1; /* to return 1 result */ + } + else { + /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); + success = 1; + for (n = first; nargs-- && success; n++) { + if (lua_type(L, n) == LUA_TNUMBER) { + size_t l = (size_t)luaL_checkinteger(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else { + const char *p = luaL_checkstring(L, n); + if (*p == '*') p++; /* skip optional '*' (for compatibility) */ + switch (*p) { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f, 1); + break; + case 'L': /* line with end-of-line */ + success = read_line(L, f, 0); + break; + case 'a': /* file */ + read_all(L, f); /* read entire file */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (ferror(f)) + return luaL_fileresult(L, 0, NULL); + if (!success) { + lua_pop(L, 1); /* remove last result */ + luaL_pushfail(L); /* push nil instead */ + } + return n - first; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L), 2); +} + + +/* +** Iteration function for 'lines'. +*/ +static int io_readline (lua_State *L) { + LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); + int i; + int n = (int)lua_tointeger(L, lua_upvalueindex(2)); + if (isclosed(p)) /* file is already closed? */ + return luaL_error(L, "file is already closed"); + lua_settop(L , 1); + luaL_checkstack(L, n, "too many arguments"); + for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ + lua_pushvalue(L, lua_upvalueindex(3 + i)); + n = g_read(L, p->f, 2); /* 'n' is number of results */ + lua_assert(n > 0); /* should return at least a nil */ + if (lua_toboolean(L, -n)) /* read at least one value? */ + return n; /* return them */ + else { /* first result is false: EOF or error */ + if (n > 1) { /* is there error information? */ + /* 2nd result is error message */ + return luaL_error(L, "%s", lua_tostring(L, -n + 1)); + } + if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ + lua_settop(L, 0); /* clear stack */ + lua_pushvalue(L, lua_upvalueindex(1)); /* push file at index 1 */ + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - arg; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + int len = lua_isinteger(L, arg) + ? fprintf(f, LUA_INTEGER_FMT, + (LUAI_UACINT)lua_tointeger(L, arg)) + : fprintf(f, LUA_NUMBER_FMT, + (LUAI_UACNUMBER)lua_tonumber(L, arg)); + status = status && (len > 0); + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + if (l_likely(status)) + return 1; /* file handle already on stack top */ + else return luaL_fileresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + FILE *f = tofile(L); + lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ + return g_write(L, f, 2); +} + + +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, "cur", modenames); + lua_Integer p3 = luaL_optinteger(L, 3, 0); + l_seeknum offset = (l_seeknum)p3; + luaL_argcheck(L, (lua_Integer)offset == p3, 3, + "not an integer in proper range"); + op = l_fseek(f, offset, mode[op]); + if (l_unlikely(op)) + return luaL_fileresult(L, 0, NULL); /* error */ + else { + lua_pushinteger(L, (lua_Integer)l_ftell(f)); + return 1; + } +} + + +static int f_setvbuf (lua_State *L) { + static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; + static const char *const modenames[] = {"no", "full", "line", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); + lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], (size_t)sz); + return luaL_fileresult(L, res == 0, NULL); +} + + + +static int io_flush (lua_State *L) { + return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); +} + + +/* +** functions for 'io' library +*/ +static const luaL_Reg iolib[] = { + {"close", io_close}, + {"flush", io_flush}, + {"input", io_input}, + {"lines", io_lines}, + {"open", io_open}, + {"output", io_output}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +/* +** methods for file handles +*/ +static const luaL_Reg meth[] = { + {"read", f_read}, + {"write", f_write}, + {"lines", f_lines}, + {"flush", f_flush}, + {"seek", f_seek}, + {"close", f_close}, + {"setvbuf", f_setvbuf}, + {NULL, NULL} +}; + + +/* +** metamethods for file handles +*/ +static const luaL_Reg metameth[] = { + {"__index", NULL}, /* place holder */ + {"__gc", f_gc}, + {"__close", f_gc}, + {"__tostring", f_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, LUA_FILEHANDLE); /* metatable for file handles */ + luaL_setfuncs(L, metameth, 0); /* add metamethods to new metatable */ + luaL_newlibtable(L, meth); /* create method table */ + luaL_setfuncs(L, meth, 0); /* add file methods to method table */ + lua_setfield(L, -2, "__index"); /* metatable.__index = method table */ + lua_pop(L, 1); /* pop metatable */ +} + + +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + LStream *p = tolstream(L); + p->closef = &io_noclose; /* keep file opened */ + luaL_pushfail(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; +} + + +static void createstdfile (lua_State *L, FILE *f, const char *k, + const char *fname) { + LStream *p = newprefile(L); + p->f = f; + p->closef = &io_noclose; + if (k != NULL) { + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ + } + lua_setfield(L, -2, fname); /* add file to module */ +} + + +LUAMOD_API int luaopen_io (lua_State *L) { + luaL_newlib(L, iolib); /* new module */ + createmeta(L); + /* create (and set) default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, NULL, "stderr"); + return 1; +} + diff --git a/lua/ljumptab.h b/lua/ljumptab.h new file mode 100644 index 0000000..8306f25 --- /dev/null +++ b/lua/ljumptab.h @@ -0,0 +1,112 @@ +/* +** $Id: ljumptab.h $ +** Jump Table for the Lua interpreter +** See Copyright Notice in lua.h +*/ + + +#undef vmdispatch +#undef vmcase +#undef vmbreak + +#define vmdispatch(x) goto *disptab[x]; + +#define vmcase(l) L_##l: + +#define vmbreak vmfetch(); vmdispatch(GET_OPCODE(i)); + + +static const void *const disptab[NUM_OPCODES] = { + +#if 0 +** you can update the following list with this command: +** +** sed -n '/^OP_/\!d; s/OP_/\&\&L_OP_/ ; s/,.*/,/ ; s/\/.*// ; p' lopcodes.h +** +#endif + +&&L_OP_MOVE, +&&L_OP_LOADI, +&&L_OP_LOADF, +&&L_OP_LOADK, +&&L_OP_LOADKX, +&&L_OP_LOADFALSE, +&&L_OP_LFALSESKIP, +&&L_OP_LOADTRUE, +&&L_OP_LOADNIL, +&&L_OP_GETUPVAL, +&&L_OP_SETUPVAL, +&&L_OP_GETTABUP, +&&L_OP_GETTABLE, +&&L_OP_GETI, +&&L_OP_GETFIELD, +&&L_OP_SETTABUP, +&&L_OP_SETTABLE, +&&L_OP_SETI, +&&L_OP_SETFIELD, +&&L_OP_NEWTABLE, +&&L_OP_SELF, +&&L_OP_ADDI, +&&L_OP_ADDK, +&&L_OP_SUBK, +&&L_OP_MULK, +&&L_OP_MODK, +&&L_OP_POWK, +&&L_OP_DIVK, +&&L_OP_IDIVK, +&&L_OP_BANDK, +&&L_OP_BORK, +&&L_OP_BXORK, +&&L_OP_SHRI, +&&L_OP_SHLI, +&&L_OP_ADD, +&&L_OP_SUB, +&&L_OP_MUL, +&&L_OP_MOD, +&&L_OP_POW, +&&L_OP_DIV, +&&L_OP_IDIV, +&&L_OP_BAND, +&&L_OP_BOR, +&&L_OP_BXOR, +&&L_OP_SHL, +&&L_OP_SHR, +&&L_OP_MMBIN, +&&L_OP_MMBINI, +&&L_OP_MMBINK, +&&L_OP_UNM, +&&L_OP_BNOT, +&&L_OP_NOT, +&&L_OP_LEN, +&&L_OP_CONCAT, +&&L_OP_CLOSE, +&&L_OP_TBC, +&&L_OP_JMP, +&&L_OP_EQ, +&&L_OP_LT, +&&L_OP_LE, +&&L_OP_EQK, +&&L_OP_EQI, +&&L_OP_LTI, +&&L_OP_LEI, +&&L_OP_GTI, +&&L_OP_GEI, +&&L_OP_TEST, +&&L_OP_TESTSET, +&&L_OP_CALL, +&&L_OP_TAILCALL, +&&L_OP_RETURN, +&&L_OP_RETURN0, +&&L_OP_RETURN1, +&&L_OP_FORLOOP, +&&L_OP_FORPREP, +&&L_OP_TFORPREP, +&&L_OP_TFORCALL, +&&L_OP_TFORLOOP, +&&L_OP_SETLIST, +&&L_OP_CLOSURE, +&&L_OP_VARARG, +&&L_OP_VARARGPREP, +&&L_OP_EXTRAARG + +}; diff --git a/lua/llex.c b/lua/llex.c new file mode 100644 index 0000000..e991517 --- /dev/null +++ b/lua/llex.c @@ -0,0 +1,581 @@ +/* +** $Id: llex.c $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#define llex_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include + +#include "lua.h" + +#include "lctype.h" +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "llex.h" +#include "lobject.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lzio.h" + + + +#define next(ls) (ls->current = zgetc(ls->z)) + + + +#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') + + +/* ORDER RESERVED */ +static const char *const luaX_tokens [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "goto", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "//", "..", "...", "==", ">=", "<=", "~=", + "<<", ">>", "::", "", + "", "", "", "" +}; + + +#define save_and_next(ls) (save(ls, ls->current), next(ls)) + + +static l_noret lexerror (LexState *ls, const char *msg, int token); + + +static void save (LexState *ls, int c) { + Mbuffer *b = ls->buff; + if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { + size_t newsize; + if (luaZ_sizebuffer(b) >= MAX_SIZE/2) + lexerror(ls, "lexical element too long", 0); + newsize = luaZ_sizebuffer(b) * 2; + luaZ_resizebuffer(ls->L, b, newsize); + } + b->buffer[luaZ_bufflen(b)++] = cast_char(c); +} + + +void luaX_init (lua_State *L) { + int i; + TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */ + luaC_fix(L, obj2gco(e)); /* never collect this name */ + for (i=0; iextra = cast_byte(i+1); /* reserved word */ + } +} + + +const char *luaX_token2str (LexState *ls, int token) { + if (token < FIRST_RESERVED) { /* single-byte symbols? */ + if (lisprint(token)) + return luaO_pushfstring(ls->L, "'%c'", token); + else /* control character */ + return luaO_pushfstring(ls->L, "'<\\%d>'", token); + } + else { + const char *s = luaX_tokens[token - FIRST_RESERVED]; + if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ + return luaO_pushfstring(ls->L, "'%s'", s); + else /* names, strings, and numerals */ + return s; + } +} + + +static const char *txtToken (LexState *ls, int token) { + switch (token) { + case TK_NAME: case TK_STRING: + case TK_FLT: case TK_INT: + save(ls, '\0'); + return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff)); + default: + return luaX_token2str(ls, token); + } +} + + +static l_noret lexerror (LexState *ls, const char *msg, int token) { + msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber); + if (token) + luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); + luaD_throw(ls->L, LUA_ERRSYNTAX); +} + + +l_noret luaX_syntaxerror (LexState *ls, const char *msg) { + lexerror(ls, msg, ls->t.token); +} + + +/* +** Creates a new string and anchors it in scanner's table so that it +** will not be collected until the end of the compilation; by that time +** it should be anchored somewhere. It also internalizes long strings, +** ensuring there is only one copy of each unique string. The table +** here is used as a set: the string enters as the key, while its value +** is irrelevant. We use the string itself as the value only because it +** is a TValue readly available. Later, the code generation can change +** this value. +*/ +TString *luaX_newstring (LexState *ls, const char *str, size_t l) { + lua_State *L = ls->L; + TString *ts = luaS_newlstr(L, str, l); /* create new string */ + const TValue *o = luaH_getstr(ls->h, ts); + if (!ttisnil(o)) /* string already present? */ + ts = keystrval(nodefromval(o)); /* get saved copy */ + else { /* not in use yet */ + TValue *stv = s2v(L->top++); /* reserve stack space for string */ + setsvalue(L, stv, ts); /* temporarily anchor the string */ + luaH_finishset(L, ls->h, stv, o, stv); /* t[string] = string */ + /* table is not a metatable, so it does not need to invalidate cache */ + luaC_checkGC(L); + L->top--; /* remove string from stack */ + } + return ts; +} + + +/* +** increment line number and skips newline sequence (any of +** \n, \r, \n\r, or \r\n) +*/ +static void inclinenumber (LexState *ls) { + int old = ls->current; + lua_assert(currIsNewline(ls)); + next(ls); /* skip '\n' or '\r' */ + if (currIsNewline(ls) && ls->current != old) + next(ls); /* skip '\n\r' or '\r\n' */ + if (++ls->linenumber >= MAX_INT) + lexerror(ls, "chunk has too many lines", 0); +} + + +void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, + int firstchar) { + ls->t.token = 0; + ls->L = L; + ls->current = firstchar; + ls->lookahead.token = TK_EOS; /* no look-ahead token */ + ls->z = z; + ls->fs = NULL; + ls->linenumber = 1; + ls->lastline = 1; + ls->source = source; + ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */ + luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ +} + + + +/* +** ======================================================= +** LEXICAL ANALYZER +** ======================================================= +*/ + + +static int check_next1 (LexState *ls, int c) { + if (ls->current == c) { + next(ls); + return 1; + } + else return 0; +} + + +/* +** Check whether current char is in set 'set' (with two chars) and +** saves it +*/ +static int check_next2 (LexState *ls, const char *set) { + lua_assert(set[2] == '\0'); + if (ls->current == set[0] || ls->current == set[1]) { + save_and_next(ls); + return 1; + } + else return 0; +} + + +/* LUA_NUMBER */ +/* +** This function is quite liberal in what it accepts, as 'luaO_str2num' +** will reject ill-formed numerals. Roughly, it accepts the following +** pattern: +** +** %d(%x|%.|([Ee][+-]?))* | 0[Xx](%x|%.|([Pp][+-]?))* +** +** The only tricky part is to accept [+-] only after a valid exponent +** mark, to avoid reading '3-4' or '0xe+1' as a single number. +** +** The caller might have already read an initial dot. +*/ +static int read_numeral (LexState *ls, SemInfo *seminfo) { + TValue obj; + const char *expo = "Ee"; + int first = ls->current; + lua_assert(lisdigit(ls->current)); + save_and_next(ls); + if (first == '0' && check_next2(ls, "xX")) /* hexadecimal? */ + expo = "Pp"; + for (;;) { + if (check_next2(ls, expo)) /* exponent mark? */ + check_next2(ls, "-+"); /* optional exponent sign */ + else if (lisxdigit(ls->current) || ls->current == '.') /* '%x|%.' */ + save_and_next(ls); + else break; + } + if (lislalpha(ls->current)) /* is numeral touching a letter? */ + save_and_next(ls); /* force an error */ + save(ls, '\0'); + if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */ + lexerror(ls, "malformed number", TK_FLT); + if (ttisinteger(&obj)) { + seminfo->i = ivalue(&obj); + return TK_INT; + } + else { + lua_assert(ttisfloat(&obj)); + seminfo->r = fltvalue(&obj); + return TK_FLT; + } +} + + +/* +** read a sequence '[=*[' or ']=*]', leaving the last bracket. If +** sequence is well formed, return its number of '='s + 2; otherwise, +** return 1 if it is a single bracket (no '='s and no 2nd bracket); +** otherwise (an unfinished '[==...') return 0. +*/ +static size_t skip_sep (LexState *ls) { + size_t count = 0; + int s = ls->current; + lua_assert(s == '[' || s == ']'); + save_and_next(ls); + while (ls->current == '=') { + save_and_next(ls); + count++; + } + return (ls->current == s) ? count + 2 + : (count == 0) ? 1 + : 0; +} + + +static void read_long_string (LexState *ls, SemInfo *seminfo, size_t sep) { + int line = ls->linenumber; /* initial line (for error message) */ + save_and_next(ls); /* skip 2nd '[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) { + switch (ls->current) { + case EOZ: { /* error */ + const char *what = (seminfo ? "string" : "comment"); + const char *msg = luaO_pushfstring(ls->L, + "unfinished long %s (starting at line %d)", what, line); + lexerror(ls, msg, TK_EOS); + break; /* to avoid warnings */ + } + case ']': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd ']' */ + goto endloop; + } + break; + } + case '\n': case '\r': { + save(ls, '\n'); + inclinenumber(ls); + if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ + break; + } + default: { + if (seminfo) save_and_next(ls); + else next(ls); + } + } + } endloop: + if (seminfo) + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + sep, + luaZ_bufflen(ls->buff) - 2 * sep); +} + + +static void esccheck (LexState *ls, int c, const char *msg) { + if (!c) { + if (ls->current != EOZ) + save_and_next(ls); /* add current to buffer for error message */ + lexerror(ls, msg, TK_STRING); + } +} + + +static int gethexa (LexState *ls) { + save_and_next(ls); + esccheck (ls, lisxdigit(ls->current), "hexadecimal digit expected"); + return luaO_hexavalue(ls->current); +} + + +static int readhexaesc (LexState *ls) { + int r = gethexa(ls); + r = (r << 4) + gethexa(ls); + luaZ_buffremove(ls->buff, 2); /* remove saved chars from buffer */ + return r; +} + + +static unsigned long readutf8esc (LexState *ls) { + unsigned long r; + int i = 4; /* chars to be removed: '\', 'u', '{', and first digit */ + save_and_next(ls); /* skip 'u' */ + esccheck(ls, ls->current == '{', "missing '{'"); + r = gethexa(ls); /* must have at least one digit */ + while (cast_void(save_and_next(ls)), lisxdigit(ls->current)) { + i++; + esccheck(ls, r <= (0x7FFFFFFFu >> 4), "UTF-8 value too large"); + r = (r << 4) + luaO_hexavalue(ls->current); + } + esccheck(ls, ls->current == '}', "missing '}'"); + next(ls); /* skip '}' */ + luaZ_buffremove(ls->buff, i); /* remove saved chars from buffer */ + return r; +} + + +static void utf8esc (LexState *ls) { + char buff[UTF8BUFFSZ]; + int n = luaO_utf8esc(buff, readutf8esc(ls)); + for (; n > 0; n--) /* add 'buff' to string */ + save(ls, buff[UTF8BUFFSZ - n]); +} + + +static int readdecesc (LexState *ls) { + int i; + int r = 0; /* result accumulator */ + for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ + r = 10*r + ls->current - '0'; + save_and_next(ls); + } + esccheck(ls, r <= UCHAR_MAX, "decimal escape too large"); + luaZ_buffremove(ls->buff, i); /* remove read digits from buffer */ + return r; +} + + +static void read_string (LexState *ls, int del, SemInfo *seminfo) { + save_and_next(ls); /* keep delimiter (for error messages) */ + while (ls->current != del) { + switch (ls->current) { + case EOZ: + lexerror(ls, "unfinished string", TK_EOS); + break; /* to avoid warnings */ + case '\n': + case '\r': + lexerror(ls, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': { /* escape sequences */ + int c; /* final character to be saved */ + save_and_next(ls); /* keep '\\' for error messages */ + switch (ls->current) { + case 'a': c = '\a'; goto read_save; + case 'b': c = '\b'; goto read_save; + case 'f': c = '\f'; goto read_save; + case 'n': c = '\n'; goto read_save; + case 'r': c = '\r'; goto read_save; + case 't': c = '\t'; goto read_save; + case 'v': c = '\v'; goto read_save; + case 'x': c = readhexaesc(ls); goto read_save; + case 'u': utf8esc(ls); goto no_save; + case '\n': case '\r': + inclinenumber(ls); c = '\n'; goto only_save; + case '\\': case '\"': case '\'': + c = ls->current; goto read_save; + case EOZ: goto no_save; /* will raise an error next loop */ + case 'z': { /* zap following span of spaces */ + luaZ_buffremove(ls->buff, 1); /* remove '\\' */ + next(ls); /* skip the 'z' */ + while (lisspace(ls->current)) { + if (currIsNewline(ls)) inclinenumber(ls); + else next(ls); + } + goto no_save; + } + default: { + esccheck(ls, lisdigit(ls->current), "invalid escape sequence"); + c = readdecesc(ls); /* digital escape '\ddd' */ + goto only_save; + } + } + read_save: + next(ls); + /* go through */ + only_save: + luaZ_buffremove(ls->buff, 1); /* remove '\\' */ + save(ls, c); + /* go through */ + no_save: break; + } + default: + save_and_next(ls); + } + } + save_and_next(ls); /* skip delimiter */ + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, + luaZ_bufflen(ls->buff) - 2); +} + + +static int llex (LexState *ls, SemInfo *seminfo) { + luaZ_resetbuffer(ls->buff); + for (;;) { + switch (ls->current) { + case '\n': case '\r': { /* line breaks */ + inclinenumber(ls); + break; + } + case ' ': case '\f': case '\t': case '\v': { /* spaces */ + next(ls); + break; + } + case '-': { /* '-' or '--' (comment) */ + next(ls); + if (ls->current != '-') return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') { /* long comment? */ + size_t sep = skip_sep(ls); + luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ + if (sep >= 2) { + read_long_string(ls, NULL, sep); /* skip long comment */ + luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ + break; + } + } + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); /* skip until end of line (or end of file) */ + break; + } + case '[': { /* long string or simply '[' */ + size_t sep = skip_sep(ls); + if (sep >= 2) { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } + else if (sep == 0) /* '[=...' missing second bracket? */ + lexerror(ls, "invalid long string delimiter", TK_STRING); + return '['; + } + case '=': { + next(ls); + if (check_next1(ls, '=')) return TK_EQ; /* '==' */ + else return '='; + } + case '<': { + next(ls); + if (check_next1(ls, '=')) return TK_LE; /* '<=' */ + else if (check_next1(ls, '<')) return TK_SHL; /* '<<' */ + else return '<'; + } + case '>': { + next(ls); + if (check_next1(ls, '=')) return TK_GE; /* '>=' */ + else if (check_next1(ls, '>')) return TK_SHR; /* '>>' */ + else return '>'; + } + case '/': { + next(ls); + if (check_next1(ls, '/')) return TK_IDIV; /* '//' */ + else return '/'; + } + case '~': { + next(ls); + if (check_next1(ls, '=')) return TK_NE; /* '~=' */ + else return '~'; + } + case ':': { + next(ls); + if (check_next1(ls, ':')) return TK_DBCOLON; /* '::' */ + else return ':'; + } + case '"': case '\'': { /* short literal strings */ + read_string(ls, ls->current, seminfo); + return TK_STRING; + } + case '.': { /* '.', '..', '...', or number */ + save_and_next(ls); + if (check_next1(ls, '.')) { + if (check_next1(ls, '.')) + return TK_DOTS; /* '...' */ + else return TK_CONCAT; /* '..' */ + } + else if (!lisdigit(ls->current)) return '.'; + else return read_numeral(ls, seminfo); + } + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + return read_numeral(ls, seminfo); + } + case EOZ: { + return TK_EOS; + } + default: { + if (lislalpha(ls->current)) { /* identifier or reserved word? */ + TString *ts; + do { + save_and_next(ls); + } while (lislalnum(ls->current)); + ts = luaX_newstring(ls, luaZ_buffer(ls->buff), + luaZ_bufflen(ls->buff)); + seminfo->ts = ts; + if (isreserved(ts)) /* reserved word? */ + return ts->extra - 1 + FIRST_RESERVED; + else { + return TK_NAME; + } + } + else { /* single-char tokens ('+', '*', '%', '{', '}', ...) */ + int c = ls->current; + next(ls); + return c; + } + } + } + } +} + + +void luaX_next (LexState *ls) { + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ +} + + +int luaX_lookahead (LexState *ls) { + lua_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); + return ls->lookahead.token; +} + diff --git a/lua/llex.h b/lua/llex.h new file mode 100644 index 0000000..389d2f8 --- /dev/null +++ b/lua/llex.h @@ -0,0 +1,91 @@ +/* +** $Id: llex.h $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#ifndef llex_h +#define llex_h + +#include + +#include "lobject.h" +#include "lzio.h" + + +/* +** Single-char tokens (terminal symbols) are represented by their own +** numeric code. Other tokens start at the following value. +*/ +#define FIRST_RESERVED (UCHAR_MAX + 1) + + +#if !defined(LUA_ENV) +#define LUA_ENV "_ENV" +#endif + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER RESERVED" +*/ +enum RESERVED { + /* terminal symbols denoted by reserved words */ + TK_AND = FIRST_RESERVED, TK_BREAK, + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, + TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, + TK_SHL, TK_SHR, + TK_DBCOLON, TK_EOS, + TK_FLT, TK_INT, TK_NAME, TK_STRING +}; + +/* number of reserved words */ +#define NUM_RESERVED (cast_int(TK_WHILE-FIRST_RESERVED + 1)) + + +typedef union { + lua_Number r; + lua_Integer i; + TString *ts; +} SemInfo; /* semantics information */ + + +typedef struct Token { + int token; + SemInfo seminfo; +} Token; + + +/* state of the lexer plus state of the parser when shared by all + functions */ +typedef struct LexState { + int current; /* current character (charint) */ + int linenumber; /* input line counter */ + int lastline; /* line of last token 'consumed' */ + Token t; /* current token */ + Token lookahead; /* look ahead token */ + struct FuncState *fs; /* current function (parser) */ + struct lua_State *L; + ZIO *z; /* input stream */ + Mbuffer *buff; /* buffer for tokens */ + Table *h; /* to avoid collection/reuse strings */ + struct Dyndata *dyd; /* dynamic structures used by the parser */ + TString *source; /* current source name */ + TString *envn; /* environment variable name */ +} LexState; + + +LUAI_FUNC void luaX_init (lua_State *L); +LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, + TString *source, int firstchar); +LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); +LUAI_FUNC void luaX_next (LexState *ls); +LUAI_FUNC int luaX_lookahead (LexState *ls); +LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); +LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); + + +#endif diff --git a/lua/llimits.h b/lua/llimits.h new file mode 100644 index 0000000..025f1c8 --- /dev/null +++ b/lua/llimits.h @@ -0,0 +1,353 @@ +/* +** $Id: llimits.h $ +** Limits, basic types, and some other 'installation-dependent' definitions +** See Copyright Notice in lua.h +*/ + +#ifndef llimits_h +#define llimits_h + + +#include +#include + + +#include "lua.h" + + +/* +** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count +** the total memory used by Lua (in bytes). Usually, 'size_t' and +** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. +*/ +#if defined(LUAI_MEM) /* { external definitions? */ +typedef LUAI_UMEM lu_mem; +typedef LUAI_MEM l_mem; +#elif LUAI_IS32INT /* }{ */ +typedef size_t lu_mem; +typedef ptrdiff_t l_mem; +#else /* 16-bit ints */ /* }{ */ +typedef unsigned long lu_mem; +typedef long l_mem; +#endif /* } */ + + +/* chars used as small naturals (so that 'char' is reserved for characters) */ +typedef unsigned char lu_byte; +typedef signed char ls_byte; + + +/* maximum value for size_t */ +#define MAX_SIZET ((size_t)(~(size_t)0)) + +/* maximum size visible for Lua (must be representable in a lua_Integer) */ +#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \ + : (size_t)(LUA_MAXINTEGER)) + + +#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)) + +#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1)) + + +#define MAX_INT INT_MAX /* maximum value of an int */ + + +/* +** floor of the log2 of the maximum signed value for integral type 't'. +** (That is, maximum 'n' such that '2^n' fits in the given signed type.) +*/ +#define log2maxs(t) (sizeof(t) * 8 - 2) + + +/* +** test whether an unsigned value is a power of 2 (or zero) +*/ +#define ispow2(x) (((x) & ((x) - 1)) == 0) + + +/* number of chars of a literal string without the ending \0 */ +#define LL(x) (sizeof(x)/sizeof(char) - 1) + + +/* +** conversion of pointer to unsigned integer: +** this is for hashing only; there is no problem if the integer +** cannot hold the whole pointer value +*/ +#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX)) + + + +/* types of 'usual argument conversions' for lua_Number and lua_Integer */ +typedef LUAI_UACNUMBER l_uacNumber; +typedef LUAI_UACINT l_uacInt; + + +/* +** Internal assertions for in-house debugging +*/ +#if defined LUAI_ASSERT +#undef NDEBUG +#include +#define lua_assert(c) assert(c) +#endif + +#if defined(lua_assert) +#define check_exp(c,e) (lua_assert(c), (e)) +/* to avoid problems with conditions too long */ +#define lua_longassert(c) ((c) ? (void)0 : lua_assert(0)) +#else +#define lua_assert(c) ((void)0) +#define check_exp(c,e) (e) +#define lua_longassert(c) ((void)0) +#endif + +/* +** assertion for checking API calls +*/ +#if !defined(luai_apicheck) +#define luai_apicheck(l,e) ((void)l, lua_assert(e)) +#endif + +#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) + + +/* macro to avoid warnings about unused variables */ +#if !defined(UNUSED) +#define UNUSED(x) ((void)(x)) +#endif + + +/* type casts (a macro highlights casts in the code) */ +#define cast(t, exp) ((t)(exp)) + +#define cast_void(i) cast(void, (i)) +#define cast_voidp(i) cast(void *, (i)) +#define cast_num(i) cast(lua_Number, (i)) +#define cast_int(i) cast(int, (i)) +#define cast_uint(i) cast(unsigned int, (i)) +#define cast_byte(i) cast(lu_byte, (i)) +#define cast_uchar(i) cast(unsigned char, (i)) +#define cast_char(i) cast(char, (i)) +#define cast_charp(i) cast(char *, (i)) +#define cast_sizet(i) cast(size_t, (i)) + + +/* cast a signed lua_Integer to lua_Unsigned */ +#if !defined(l_castS2U) +#define l_castS2U(i) ((lua_Unsigned)(i)) +#endif + +/* +** cast a lua_Unsigned to a signed lua_Integer; this cast is +** not strict ISO C, but two-complement architectures should +** work fine. +*/ +#if !defined(l_castU2S) +#define l_castU2S(i) ((lua_Integer)(i)) +#endif + + +/* +** non-return type +*/ +#if !defined(l_noret) + +#if defined(__GNUC__) +#define l_noret void __attribute__((noreturn)) +#elif defined(_MSC_VER) && _MSC_VER >= 1200 +#define l_noret void __declspec(noreturn) +#else +#define l_noret void +#endif + +#endif + + +/* +** type for virtual-machine instructions; +** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +*/ +#if LUAI_IS32INT +typedef unsigned int l_uint32; +#else +typedef unsigned long l_uint32; +#endif + +typedef l_uint32 Instruction; + + + +/* +** Maximum length for short strings, that is, strings that are +** internalized. (Cannot be smaller than reserved words or tags for +** metamethods, as these strings must be internalized; +** #("function") = 8, #("__newindex") = 10.) +*/ +#if !defined(LUAI_MAXSHORTLEN) +#define LUAI_MAXSHORTLEN 40 +#endif + + +/* +** Initial size for the string table (must be power of 2). +** The Lua core alone registers ~50 strings (reserved words + +** metaevent keys + a few others). Libraries would typically add +** a few dozens more. +*/ +#if !defined(MINSTRTABSIZE) +#define MINSTRTABSIZE 128 +#endif + + +/* +** Size of cache for strings in the API. 'N' is the number of +** sets (better be a prime) and "M" is the size of each set (M == 1 +** makes a direct cache.) +*/ +#if !defined(STRCACHE_N) +#define STRCACHE_N 53 +#define STRCACHE_M 2 +#endif + + +/* minimum size for string buffer */ +#if !defined(LUA_MINBUFFER) +#define LUA_MINBUFFER 32 +#endif + + +/* +** Maximum depth for nested C calls, syntactical nested non-terminals, +** and other features implemented through recursion in C. (Value must +** fit in a 16-bit unsigned integer. It must also be compatible with +** the size of the C stack.) +*/ +#if !defined(LUAI_MAXCCALLS) +#define LUAI_MAXCCALLS 200 +#endif + + +/* +** macros that are executed whenever program enters the Lua core +** ('lua_lock') and leaves the core ('lua_unlock') +*/ +#if !defined(lua_lock) +#define lua_lock(L) ((void) 0) +#define lua_unlock(L) ((void) 0) +#endif + +/* +** macro executed during Lua functions at points where the +** function can yield. +*/ +#if !defined(luai_threadyield) +#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} +#endif + + +/* +** these macros allow user-specific actions when a thread is +** created/deleted/resumed/yielded. +*/ +#if !defined(luai_userstateopen) +#define luai_userstateopen(L) ((void)L) +#endif + +#if !defined(luai_userstateclose) +#define luai_userstateclose(L) ((void)L) +#endif + +#if !defined(luai_userstatethread) +#define luai_userstatethread(L,L1) ((void)L) +#endif + +#if !defined(luai_userstatefree) +#define luai_userstatefree(L,L1) ((void)L) +#endif + +#if !defined(luai_userstateresume) +#define luai_userstateresume(L,n) ((void)L) +#endif + +#if !defined(luai_userstateyield) +#define luai_userstateyield(L,n) ((void)L) +#endif + + + +/* +** The luai_num* macros define the primitive operations over numbers. +*/ + +/* floor division (defined as 'floor(a/b)') */ +#if !defined(luai_numidiv) +#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b))) +#endif + +/* float division */ +#if !defined(luai_numdiv) +#define luai_numdiv(L,a,b) ((a)/(b)) +#endif + +/* +** modulo: defined as 'a - floor(a/b)*b'; the direct computation +** using this definition has several problems with rounding errors, +** so it is better to use 'fmod'. 'fmod' gives the result of +** 'a - trunc(a/b)*b', and therefore must be corrected when +** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a +** non-integer negative result: non-integer result is equivalent to +** a non-zero remainder 'm'; negative result is equivalent to 'a' and +** 'b' with different signs, or 'm' and 'b' with different signs +** (as the result 'm' of 'fmod' has the same sign of 'a'). +*/ +#if !defined(luai_nummod) +#define luai_nummod(L,a,b,m) \ + { (void)L; (m) = l_mathop(fmod)(a,b); \ + if (((m) > 0) ? (b) < 0 : ((m) < 0 && (b) > 0)) (m) += (b); } +#endif + +/* exponentiation */ +#if !defined(luai_numpow) +#define luai_numpow(L,a,b) \ + ((void)L, (b == 2) ? (a)*(a) : l_mathop(pow)(a,b)) +#endif + +/* the others are quite standard operations */ +#if !defined(luai_numadd) +#define luai_numadd(L,a,b) ((a)+(b)) +#define luai_numsub(L,a,b) ((a)-(b)) +#define luai_nummul(L,a,b) ((a)*(b)) +#define luai_numunm(L,a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(a,b) ((a)<(b)) +#define luai_numle(a,b) ((a)<=(b)) +#define luai_numgt(a,b) ((a)>(b)) +#define luai_numge(a,b) ((a)>=(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) +#endif + + + + + +/* +** macro to control inclusion of some hard tests on stack reallocation +*/ +#if !defined(HARDSTACKTESTS) +#define condmovestack(L,pre,pos) ((void)0) +#else +/* realloc stack keeping its size */ +#define condmovestack(L,pre,pos) \ + { int sz_ = stacksize(L); pre; luaD_reallocstack((L), sz_, 0); pos; } +#endif + +#if !defined(HARDMEMTESTS) +#define condchangemem(L,pre,pos) ((void)0) +#else +#define condchangemem(L,pre,pos) \ + { if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } } +#endif + +#endif diff --git a/lua/lmathlib.c b/lua/lmathlib.c new file mode 100644 index 0000000..5f5983a --- /dev/null +++ b/lua/lmathlib.c @@ -0,0 +1,764 @@ +/* +** $Id: lmathlib.c $ +** Standard mathematical library +** See Copyright Notice in lua.h +*/ + +#define lmathlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#undef PI +#define PI (l_mathop(3.141592653589793238462643383279502884)) + + +static int math_abs (lua_State *L) { + if (lua_isinteger(L, 1)) { + lua_Integer n = lua_tointeger(L, 1); + if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n); + lua_pushinteger(L, n); + } + else + lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_Number y = luaL_checknumber(L, 1); + lua_Number x = luaL_optnumber(L, 2, 1); + lua_pushnumber(L, l_mathop(atan2)(y, x)); + return 1; +} + + +static int math_toint (lua_State *L) { + int valid; + lua_Integer n = lua_tointegerx(L, 1, &valid); + if (l_likely(valid)) + lua_pushinteger(L, n); + else { + luaL_checkany(L, 1); + luaL_pushfail(L); /* value is not convertible to integer */ + } + return 1; +} + + +static void pushnumint (lua_State *L, lua_Number d) { + lua_Integer n; + if (lua_numbertointeger(d, &n)) /* does 'd' fit in an integer? */ + lua_pushinteger(L, n); /* result is integer */ + else + lua_pushnumber(L, d); /* result is float */ +} + + +static int math_floor (lua_State *L) { + if (lua_isinteger(L, 1)) + lua_settop(L, 1); /* integer is its own floor */ + else { + lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1)); + pushnumint(L, d); + } + return 1; +} + + +static int math_ceil (lua_State *L) { + if (lua_isinteger(L, 1)) + lua_settop(L, 1); /* integer is its own ceil */ + else { + lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1)); + pushnumint(L, d); + } + return 1; +} + + +static int math_fmod (lua_State *L) { + if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) { + lua_Integer d = lua_tointeger(L, 2); + if ((lua_Unsigned)d + 1u <= 1u) { /* special cases: -1 or 0 */ + luaL_argcheck(L, d != 0, 2, "zero"); + lua_pushinteger(L, 0); /* avoid overflow with 0x80000... / -1 */ + } + else + lua_pushinteger(L, lua_tointeger(L, 1) % d); + } + else + lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), + luaL_checknumber(L, 2))); + return 1; +} + + +/* +** next function does not use 'modf', avoiding problems with 'double*' +** (which is not compatible with 'float*') when lua_Number is not +** 'double'. +*/ +static int math_modf (lua_State *L) { + if (lua_isinteger(L ,1)) { + lua_settop(L, 1); /* number is its own integer part */ + lua_pushnumber(L, 0); /* no fractional part */ + } + else { + lua_Number n = luaL_checknumber(L, 1); + /* integer part (rounds toward zero) */ + lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n); + pushnumint(L, ip); + /* fractional part (test needed for inf/-inf) */ + lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip)); + } + return 2; +} + + +static int math_sqrt (lua_State *L) { + lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); + return 1; +} + + +static int math_ult (lua_State *L) { + lua_Integer a = luaL_checkinteger(L, 1); + lua_Integer b = luaL_checkinteger(L, 2); + lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b); + return 1; +} + +static int math_log (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + lua_Number res; + if (lua_isnoneornil(L, 2)) + res = l_mathop(log)(x); + else { + lua_Number base = luaL_checknumber(L, 2); +#if !defined(LUA_USE_C89) + if (base == l_mathop(2.0)) + res = l_mathop(log2)(x); + else +#endif + if (base == l_mathop(10.0)) + res = l_mathop(log10)(x); + else + res = l_mathop(log)(x)/l_mathop(log)(base); + } + lua_pushnumber(L, res); + return 1; +} + +static int math_exp (lua_State *L) { + lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_deg (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI)); + return 1; +} + +static int math_rad (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0))); + return 1; +} + + +static int math_min (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int imin = 1; /* index of current minimum value */ + int i; + luaL_argcheck(L, n >= 1, 1, "value expected"); + for (i = 2; i <= n; i++) { + if (lua_compare(L, i, imin, LUA_OPLT)) + imin = i; + } + lua_pushvalue(L, imin); + return 1; +} + + +static int math_max (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int imax = 1; /* index of current maximum value */ + int i; + luaL_argcheck(L, n >= 1, 1, "value expected"); + for (i = 2; i <= n; i++) { + if (lua_compare(L, imax, i, LUA_OPLT)) + imax = i; + } + lua_pushvalue(L, imax); + return 1; +} + + +static int math_type (lua_State *L) { + if (lua_type(L, 1) == LUA_TNUMBER) + lua_pushstring(L, (lua_isinteger(L, 1)) ? "integer" : "float"); + else { + luaL_checkany(L, 1); + luaL_pushfail(L); + } + return 1; +} + + + +/* +** {================================================================== +** Pseudo-Random Number Generator based on 'xoshiro256**'. +** =================================================================== +*/ + +/* number of binary digits in the mantissa of a float */ +#define FIGS l_floatatt(MANT_DIG) + +#if FIGS > 64 +/* there are only 64 random bits; use them all */ +#undef FIGS +#define FIGS 64 +#endif + + +/* +** LUA_RAND32 forces the use of 32-bit integers in the implementation +** of the PRN generator (mainly for testing). +*/ +#if !defined(LUA_RAND32) && !defined(Rand64) + +/* try to find an integer type with at least 64 bits */ + +#if (ULONG_MAX >> 31 >> 31) >= 3 + +/* 'long' has at least 64 bits */ +#define Rand64 unsigned long + +#elif !defined(LUA_USE_C89) && defined(LLONG_MAX) + +/* there is a 'long long' type (which must have at least 64 bits) */ +#define Rand64 unsigned long long + +#elif (LUA_MAXUNSIGNED >> 31 >> 31) >= 3 + +/* 'lua_Integer' has at least 64 bits */ +#define Rand64 lua_Unsigned + +#endif + +#endif + + +#if defined(Rand64) /* { */ + +/* +** Standard implementation, using 64-bit integers. +** If 'Rand64' has more than 64 bits, the extra bits do not interfere +** with the 64 initial bits, except in a right shift. Moreover, the +** final result has to discard the extra bits. +*/ + +/* avoid using extra bits when needed */ +#define trim64(x) ((x) & 0xffffffffffffffffu) + + +/* rotate left 'x' by 'n' bits */ +static Rand64 rotl (Rand64 x, int n) { + return (x << n) | (trim64(x) >> (64 - n)); +} + +static Rand64 nextrand (Rand64 *state) { + Rand64 state0 = state[0]; + Rand64 state1 = state[1]; + Rand64 state2 = state[2] ^ state0; + Rand64 state3 = state[3] ^ state1; + Rand64 res = rotl(state1 * 5, 7) * 9; + state[0] = state0 ^ state3; + state[1] = state1 ^ state2; + state[2] = state2 ^ (state1 << 17); + state[3] = rotl(state3, 45); + return res; +} + + +/* must take care to not shift stuff by more than 63 slots */ + + +/* +** Convert bits from a random integer into a float in the +** interval [0,1), getting the higher FIG bits from the +** random unsigned integer and converting that to a float. +*/ + +/* must throw out the extra (64 - FIGS) bits */ +#define shift64_FIG (64 - FIGS) + +/* to scale to [0, 1), multiply by scaleFIG = 2^(-FIGS) */ +#define scaleFIG (l_mathop(0.5) / ((Rand64)1 << (FIGS - 1))) + +static lua_Number I2d (Rand64 x) { + return (lua_Number)(trim64(x) >> shift64_FIG) * scaleFIG; +} + +/* convert a 'Rand64' to a 'lua_Unsigned' */ +#define I2UInt(x) ((lua_Unsigned)trim64(x)) + +/* convert a 'lua_Unsigned' to a 'Rand64' */ +#define Int2I(x) ((Rand64)(x)) + + +#else /* no 'Rand64' }{ */ + +/* get an integer with at least 32 bits */ +#if LUAI_IS32INT +typedef unsigned int lu_int32; +#else +typedef unsigned long lu_int32; +#endif + + +/* +** Use two 32-bit integers to represent a 64-bit quantity. +*/ +typedef struct Rand64 { + lu_int32 h; /* higher half */ + lu_int32 l; /* lower half */ +} Rand64; + + +/* +** If 'lu_int32' has more than 32 bits, the extra bits do not interfere +** with the 32 initial bits, except in a right shift and comparisons. +** Moreover, the final result has to discard the extra bits. +*/ + +/* avoid using extra bits when needed */ +#define trim32(x) ((x) & 0xffffffffu) + + +/* +** basic operations on 'Rand64' values +*/ + +/* build a new Rand64 value */ +static Rand64 packI (lu_int32 h, lu_int32 l) { + Rand64 result; + result.h = h; + result.l = l; + return result; +} + +/* return i << n */ +static Rand64 Ishl (Rand64 i, int n) { + lua_assert(n > 0 && n < 32); + return packI((i.h << n) | (trim32(i.l) >> (32 - n)), i.l << n); +} + +/* i1 ^= i2 */ +static void Ixor (Rand64 *i1, Rand64 i2) { + i1->h ^= i2.h; + i1->l ^= i2.l; +} + +/* return i1 + i2 */ +static Rand64 Iadd (Rand64 i1, Rand64 i2) { + Rand64 result = packI(i1.h + i2.h, i1.l + i2.l); + if (trim32(result.l) < trim32(i1.l)) /* carry? */ + result.h++; + return result; +} + +/* return i * 5 */ +static Rand64 times5 (Rand64 i) { + return Iadd(Ishl(i, 2), i); /* i * 5 == (i << 2) + i */ +} + +/* return i * 9 */ +static Rand64 times9 (Rand64 i) { + return Iadd(Ishl(i, 3), i); /* i * 9 == (i << 3) + i */ +} + +/* return 'i' rotated left 'n' bits */ +static Rand64 rotl (Rand64 i, int n) { + lua_assert(n > 0 && n < 32); + return packI((i.h << n) | (trim32(i.l) >> (32 - n)), + (trim32(i.h) >> (32 - n)) | (i.l << n)); +} + +/* for offsets larger than 32, rotate right by 64 - offset */ +static Rand64 rotl1 (Rand64 i, int n) { + lua_assert(n > 32 && n < 64); + n = 64 - n; + return packI((trim32(i.h) >> n) | (i.l << (32 - n)), + (i.h << (32 - n)) | (trim32(i.l) >> n)); +} + +/* +** implementation of 'xoshiro256**' algorithm on 'Rand64' values +*/ +static Rand64 nextrand (Rand64 *state) { + Rand64 res = times9(rotl(times5(state[1]), 7)); + Rand64 t = Ishl(state[1], 17); + Ixor(&state[2], state[0]); + Ixor(&state[3], state[1]); + Ixor(&state[1], state[2]); + Ixor(&state[0], state[3]); + Ixor(&state[2], t); + state[3] = rotl1(state[3], 45); + return res; +} + + +/* +** Converts a 'Rand64' into a float. +*/ + +/* an unsigned 1 with proper type */ +#define UONE ((lu_int32)1) + + +#if FIGS <= 32 + +/* 2^(-FIGS) */ +#define scaleFIG (l_mathop(0.5) / (UONE << (FIGS - 1))) + +/* +** get up to 32 bits from higher half, shifting right to +** throw out the extra bits. +*/ +static lua_Number I2d (Rand64 x) { + lua_Number h = (lua_Number)(trim32(x.h) >> (32 - FIGS)); + return h * scaleFIG; +} + +#else /* 32 < FIGS <= 64 */ + +/* must take care to not shift stuff by more than 31 slots */ + +/* 2^(-FIGS) = 1.0 / 2^30 / 2^3 / 2^(FIGS-33) */ +#define scaleFIG \ + ((lua_Number)1.0 / (UONE << 30) / 8.0 / (UONE << (FIGS - 33))) + +/* +** use FIGS - 32 bits from lower half, throwing out the other +** (32 - (FIGS - 32)) = (64 - FIGS) bits +*/ +#define shiftLOW (64 - FIGS) + +/* +** higher 32 bits go after those (FIGS - 32) bits: shiftHI = 2^(FIGS - 32) +*/ +#define shiftHI ((lua_Number)(UONE << (FIGS - 33)) * 2.0) + + +static lua_Number I2d (Rand64 x) { + lua_Number h = (lua_Number)trim32(x.h) * shiftHI; + lua_Number l = (lua_Number)(trim32(x.l) >> shiftLOW); + return (h + l) * scaleFIG; +} + +#endif + + +/* convert a 'Rand64' to a 'lua_Unsigned' */ +static lua_Unsigned I2UInt (Rand64 x) { + return ((lua_Unsigned)trim32(x.h) << 31 << 1) | (lua_Unsigned)trim32(x.l); +} + +/* convert a 'lua_Unsigned' to a 'Rand64' */ +static Rand64 Int2I (lua_Unsigned n) { + return packI((lu_int32)(n >> 31 >> 1), (lu_int32)n); +} + +#endif /* } */ + + +/* +** A state uses four 'Rand64' values. +*/ +typedef struct { + Rand64 s[4]; +} RanState; + + +/* +** Project the random integer 'ran' into the interval [0, n]. +** Because 'ran' has 2^B possible values, the projection can only be +** uniform when the size of the interval is a power of 2 (exact +** division). Otherwise, to get a uniform projection into [0, n], we +** first compute 'lim', the smallest Mersenne number not smaller than +** 'n'. We then project 'ran' into the interval [0, lim]. If the result +** is inside [0, n], we are done. Otherwise, we try with another 'ran', +** until we have a result inside the interval. +*/ +static lua_Unsigned project (lua_Unsigned ran, lua_Unsigned n, + RanState *state) { + if ((n & (n + 1)) == 0) /* is 'n + 1' a power of 2? */ + return ran & n; /* no bias */ + else { + lua_Unsigned lim = n; + /* compute the smallest (2^b - 1) not smaller than 'n' */ + lim |= (lim >> 1); + lim |= (lim >> 2); + lim |= (lim >> 4); + lim |= (lim >> 8); + lim |= (lim >> 16); +#if (LUA_MAXUNSIGNED >> 31) >= 3 + lim |= (lim >> 32); /* integer type has more than 32 bits */ +#endif + lua_assert((lim & (lim + 1)) == 0 /* 'lim + 1' is a power of 2, */ + && lim >= n /* not smaller than 'n', */ + && (lim >> 1) < n); /* and it is the smallest one */ + while ((ran &= lim) > n) /* project 'ran' into [0..lim] */ + ran = I2UInt(nextrand(state->s)); /* not inside [0..n]? try again */ + return ran; + } +} + + +static int math_random (lua_State *L) { + lua_Integer low, up; + lua_Unsigned p; + RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1)); + Rand64 rv = nextrand(state->s); /* next pseudo-random value */ + switch (lua_gettop(L)) { /* check number of arguments */ + case 0: { /* no arguments */ + lua_pushnumber(L, I2d(rv)); /* float between 0 and 1 */ + return 1; + } + case 1: { /* only upper limit */ + low = 1; + up = luaL_checkinteger(L, 1); + if (up == 0) { /* single 0 as argument? */ + lua_pushinteger(L, I2UInt(rv)); /* full random integer */ + return 1; + } + break; + } + case 2: { /* lower and upper limits */ + low = luaL_checkinteger(L, 1); + up = luaL_checkinteger(L, 2); + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + /* random integer in the interval [low, up] */ + luaL_argcheck(L, low <= up, 1, "interval is empty"); + /* project random integer into the interval [0, up - low] */ + p = project(I2UInt(rv), (lua_Unsigned)up - (lua_Unsigned)low, state); + lua_pushinteger(L, p + (lua_Unsigned)low); + return 1; +} + + +static void setseed (lua_State *L, Rand64 *state, + lua_Unsigned n1, lua_Unsigned n2) { + int i; + state[0] = Int2I(n1); + state[1] = Int2I(0xff); /* avoid a zero state */ + state[2] = Int2I(n2); + state[3] = Int2I(0); + for (i = 0; i < 16; i++) + nextrand(state); /* discard initial values to "spread" seed */ + lua_pushinteger(L, n1); + lua_pushinteger(L, n2); +} + + +/* +** Set a "random" seed. To get some randomness, use the current time +** and the address of 'L' (in case the machine does address space layout +** randomization). +*/ +static void randseed (lua_State *L, RanState *state) { + lua_Unsigned seed1 = (lua_Unsigned)time(NULL); + lua_Unsigned seed2 = (lua_Unsigned)(size_t)L; + setseed(L, state->s, seed1, seed2); +} + + +static int math_randomseed (lua_State *L) { + RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1)); + if (lua_isnone(L, 1)) { + randseed(L, state); + } + else { + lua_Integer n1 = luaL_checkinteger(L, 1); + lua_Integer n2 = luaL_optinteger(L, 2, 0); + setseed(L, state->s, n1, n2); + } + return 2; /* return seeds */ +} + + +static const luaL_Reg randfuncs[] = { + {"random", math_random}, + {"randomseed", math_randomseed}, + {NULL, NULL} +}; + + +/* +** Register the random functions and initialize their state. +*/ +static void setrandfunc (lua_State *L) { + RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0); + randseed(L, state); /* initialize with a "random" seed */ + lua_pop(L, 2); /* remove pushed seeds */ + luaL_setfuncs(L, randfuncs, 1); +} + +/* }================================================================== */ + + +/* +** {================================================================== +** Deprecated functions (for compatibility only) +** =================================================================== +*/ +#if defined(LUA_COMPAT_MATHLIB) + +static int math_cosh (lua_State *L) { + lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sinh (lua_State *L) { + lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tanh (lua_State *L) { + lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + lua_Number y = luaL_checknumber(L, 2); + lua_pushnumber(L, l_mathop(pow)(x, y)); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); + lua_pushinteger(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + int ep = (int)luaL_checkinteger(L, 2); + lua_pushnumber(L, l_mathop(ldexp)(x, ep)); + return 1; +} + +static int math_log10 (lua_State *L) { + lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); + return 1; +} + +#endif +/* }================================================================== */ + + + +static const luaL_Reg mathlib[] = { + {"abs", math_abs}, + {"acos", math_acos}, + {"asin", math_asin}, + {"atan", math_atan}, + {"ceil", math_ceil}, + {"cos", math_cos}, + {"deg", math_deg}, + {"exp", math_exp}, + {"tointeger", math_toint}, + {"floor", math_floor}, + {"fmod", math_fmod}, + {"ult", math_ult}, + {"log", math_log}, + {"max", math_max}, + {"min", math_min}, + {"modf", math_modf}, + {"rad", math_rad}, + {"sin", math_sin}, + {"sqrt", math_sqrt}, + {"tan", math_tan}, + {"type", math_type}, +#if defined(LUA_COMPAT_MATHLIB) + {"atan2", math_atan}, + {"cosh", math_cosh}, + {"sinh", math_sinh}, + {"tanh", math_tanh}, + {"pow", math_pow}, + {"frexp", math_frexp}, + {"ldexp", math_ldexp}, + {"log10", math_log10}, +#endif + /* placeholders */ + {"random", NULL}, + {"randomseed", NULL}, + {"pi", NULL}, + {"huge", NULL}, + {"maxinteger", NULL}, + {"mininteger", NULL}, + {NULL, NULL} +}; + + +/* +** Open math library +*/ +LUAMOD_API int luaopen_math (lua_State *L) { + luaL_newlib(L, mathlib); + lua_pushnumber(L, PI); + lua_setfield(L, -2, "pi"); + lua_pushnumber(L, (lua_Number)HUGE_VAL); + lua_setfield(L, -2, "huge"); + lua_pushinteger(L, LUA_MAXINTEGER); + lua_setfield(L, -2, "maxinteger"); + lua_pushinteger(L, LUA_MININTEGER); + lua_setfield(L, -2, "mininteger"); + setrandfunc(L); + return 1; +} + diff --git a/lua/lmem.c b/lua/lmem.c new file mode 100644 index 0000000..9029d58 --- /dev/null +++ b/lua/lmem.c @@ -0,0 +1,201 @@ +/* +** $Id: lmem.c $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#define lmem_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + +#if defined(EMERGENCYGCTESTS) +/* +** First allocation will fail whenever not building initial state. +** (This fail will trigger 'tryagain' and a full GC cycle at every +** allocation.) +*/ +static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { + if (completestate(g) && ns > 0) /* frees never fail */ + return NULL; /* fail */ + else /* normal allocation */ + return (*g->frealloc)(g->ud, block, os, ns); +} +#else +#define firsttry(g,block,os,ns) ((*g->frealloc)(g->ud, block, os, ns)) +#endif + + + + + +/* +** About the realloc function: +** void *frealloc (void *ud, void *ptr, size_t osize, size_t nsize); +** ('osize' is the old size, 'nsize' is the new size) +** +** - frealloc(ud, p, x, 0) frees the block 'p' and returns NULL. +** Particularly, frealloc(ud, NULL, 0, 0) does nothing, +** which is equivalent to free(NULL) in ISO C. +** +** - frealloc(ud, NULL, x, s) creates a new block of size 's' +** (no matter 'x'). Returns NULL if it cannot create the new block. +** +** - otherwise, frealloc(ud, b, x, y) reallocates the block 'b' from +** size 'x' to size 'y'. Returns NULL if it cannot reallocate the +** block to the new size. +*/ + + + + +/* +** {================================================================== +** Functions to allocate/deallocate arrays for the Parser +** =================================================================== +*/ + +/* +** Minimum size for arrays during parsing, to avoid overhead of +** reallocating to size 1, then 2, and then 4. All these arrays +** will be reallocated to exact sizes or erased when parsing ends. +*/ +#define MINSIZEARRAY 4 + + +void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize, + int size_elems, int limit, const char *what) { + void *newblock; + int size = *psize; + if (nelems + 1 <= size) /* does one extra element still fit? */ + return block; /* nothing to be done */ + if (size >= limit / 2) { /* cannot double it? */ + if (l_unlikely(size >= limit)) /* cannot grow even a little? */ + luaG_runerror(L, "too many %s (limit is %d)", what, limit); + size = limit; /* still have at least one free place */ + } + else { + size *= 2; + if (size < MINSIZEARRAY) + size = MINSIZEARRAY; /* minimum size */ + } + lua_assert(nelems + 1 <= size && size <= limit); + /* 'limit' ensures that multiplication will not overflow */ + newblock = luaM_saferealloc_(L, block, cast_sizet(*psize) * size_elems, + cast_sizet(size) * size_elems); + *psize = size; /* update only when everything else is OK */ + return newblock; +} + + +/* +** In prototypes, the size of the array is also its number of +** elements (to save memory). So, if it cannot shrink an array +** to its number of elements, the only option is to raise an +** error. +*/ +void *luaM_shrinkvector_ (lua_State *L, void *block, int *size, + int final_n, int size_elem) { + void *newblock; + size_t oldsize = cast_sizet((*size) * size_elem); + size_t newsize = cast_sizet(final_n * size_elem); + lua_assert(newsize <= oldsize); + newblock = luaM_saferealloc_(L, block, oldsize, newsize); + *size = final_n; + return newblock; +} + +/* }================================================================== */ + + +l_noret luaM_toobig (lua_State *L) { + luaG_runerror(L, "memory allocation error: block too big"); +} + + +/* +** Free memory +*/ +void luaM_free_ (lua_State *L, void *block, size_t osize) { + global_State *g = G(L); + lua_assert((osize == 0) == (block == NULL)); + (*g->frealloc)(g->ud, block, osize, 0); + g->GCdebt -= osize; +} + + +/* +** In case of allocation fail, this function will do an emergency +** collection to free some memory and then try the allocation again. +** The GC should not be called while state is not fully built, as the +** collector is not yet fully initialized. Also, it should not be called +** when 'gcstopem' is true, because then the interpreter is in the +** middle of a collection step. +*/ +static void *tryagain (lua_State *L, void *block, + size_t osize, size_t nsize) { + global_State *g = G(L); + if (completestate(g) && !g->gcstopem) { + luaC_fullgc(L, 1); /* try to free some memory... */ + return (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + } + else return NULL; /* cannot free any memory without a full state */ +} + + +/* +** Generic allocation routine. +*/ +void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { + void *newblock; + global_State *g = G(L); + lua_assert((osize == 0) == (block == NULL)); + newblock = firsttry(g, block, osize, nsize); + if (l_unlikely(newblock == NULL && nsize > 0)) { + newblock = tryagain(L, block, osize, nsize); + if (newblock == NULL) /* still no memory? */ + return NULL; /* do not update 'GCdebt' */ + } + lua_assert((nsize == 0) == (newblock == NULL)); + g->GCdebt = (g->GCdebt + nsize) - osize; + return newblock; +} + + +void *luaM_saferealloc_ (lua_State *L, void *block, size_t osize, + size_t nsize) { + void *newblock = luaM_realloc_(L, block, osize, nsize); + if (l_unlikely(newblock == NULL && nsize > 0)) /* allocation failed? */ + luaM_error(L); + return newblock; +} + + +void *luaM_malloc_ (lua_State *L, size_t size, int tag) { + if (size == 0) + return NULL; /* that's all */ + else { + global_State *g = G(L); + void *newblock = firsttry(g, NULL, tag, size); + if (l_unlikely(newblock == NULL)) { + newblock = tryagain(L, NULL, tag, size); + if (newblock == NULL) + luaM_error(L); + } + g->GCdebt += size; + return newblock; + } +} diff --git a/lua/lmem.h b/lua/lmem.h new file mode 100644 index 0000000..8c75a44 --- /dev/null +++ b/lua/lmem.h @@ -0,0 +1,93 @@ +/* +** $Id: lmem.h $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#ifndef lmem_h +#define lmem_h + + +#include + +#include "llimits.h" +#include "lua.h" + + +#define luaM_error(L) luaD_throw(L, LUA_ERRMEM) + + +/* +** This macro tests whether it is safe to multiply 'n' by the size of +** type 't' without overflows. Because 'e' is always constant, it avoids +** the runtime division MAX_SIZET/(e). +** (The macro is somewhat complex to avoid warnings: The 'sizeof' +** comparison avoids a runtime comparison when overflow cannot occur. +** The compiler should be able to optimize the real test by itself, but +** when it does it, it may give a warning about "comparison is always +** false due to limited range of data type"; the +1 tricks the compiler, +** avoiding this warning but also this optimization.) +*/ +#define luaM_testsize(n,e) \ + (sizeof(n) >= sizeof(size_t) && cast_sizet((n)) + 1 > MAX_SIZET/(e)) + +#define luaM_checksize(L,n,e) \ + (luaM_testsize(n,e) ? luaM_toobig(L) : cast_void(0)) + + +/* +** Computes the minimum between 'n' and 'MAX_SIZET/sizeof(t)', so that +** the result is not larger than 'n' and cannot overflow a 'size_t' +** when multiplied by the size of type 't'. (Assumes that 'n' is an +** 'int' or 'unsigned int' and that 'int' is not larger than 'size_t'.) +*/ +#define luaM_limitN(n,t) \ + ((cast_sizet(n) <= MAX_SIZET/sizeof(t)) ? (n) : \ + cast_uint((MAX_SIZET/sizeof(t)))) + + +/* +** Arrays of chars do not need any test +*/ +#define luaM_reallocvchar(L,b,on,n) \ + cast_charp(luaM_saferealloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char))) + +#define luaM_freemem(L, b, s) luaM_free_(L, (b), (s)) +#define luaM_free(L, b) luaM_free_(L, (b), sizeof(*(b))) +#define luaM_freearray(L, b, n) luaM_free_(L, (b), (n)*sizeof(*(b))) + +#define luaM_new(L,t) cast(t*, luaM_malloc_(L, sizeof(t), 0)) +#define luaM_newvector(L,n,t) cast(t*, luaM_malloc_(L, (n)*sizeof(t), 0)) +#define luaM_newvectorchecked(L,n,t) \ + (luaM_checksize(L,n,sizeof(t)), luaM_newvector(L,n,t)) + +#define luaM_newobject(L,tag,s) luaM_malloc_(L, (s), tag) + +#define luaM_growvector(L,v,nelems,size,t,limit,e) \ + ((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \ + luaM_limitN(limit,t),e))) + +#define luaM_reallocvector(L, v,oldn,n,t) \ + (cast(t *, luaM_realloc_(L, v, cast_sizet(oldn) * sizeof(t), \ + cast_sizet(n) * sizeof(t)))) + +#define luaM_shrinkvector(L,v,size,fs,t) \ + ((v)=cast(t *, luaM_shrinkvector_(L, v, &(size), fs, sizeof(t)))) + +LUAI_FUNC l_noret luaM_toobig (lua_State *L); + +/* not to be called directly */ +LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, + size_t size); +LUAI_FUNC void *luaM_saferealloc_ (lua_State *L, void *block, size_t oldsize, + size_t size); +LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize); +LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems, + int *size, int size_elem, int limit, + const char *what); +LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem, + int final_n, int size_elem); +LUAI_FUNC void *luaM_malloc_ (lua_State *L, size_t size, int tag); + +#endif + diff --git a/lua/loadlib.c b/lua/loadlib.c new file mode 100644 index 0000000..6f9fa37 --- /dev/null +++ b/lua/loadlib.c @@ -0,0 +1,762 @@ +/* +** $Id: loadlib.c $ +** Dynamic library loader for Lua +** See Copyright Notice in lua.h +** +** This module contains an implementation of loadlib for Unix systems +** that have dlfcn, an implementation for Windows, and a stub for other +** systems. +*/ + +#define loadlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** LUA_IGMARK is a mark to ignore all before it when building the +** luaopen_ function name. +*/ +#if !defined (LUA_IGMARK) +#define LUA_IGMARK "-" +#endif + + +/* +** LUA_CSUBSEP is the character that replaces dots in submodule names +** when searching for a C loader. +** LUA_LSUBSEP is the character that replaces dots in submodule names +** when searching for a Lua loader. +*/ +#if !defined(LUA_CSUBSEP) +#define LUA_CSUBSEP LUA_DIRSEP +#endif + +#if !defined(LUA_LSUBSEP) +#define LUA_LSUBSEP LUA_DIRSEP +#endif + + +/* prefix for open functions in C libraries */ +#define LUA_POF "luaopen_" + +/* separator for open functions in C libraries */ +#define LUA_OFSEP "_" + + +/* +** key for table in the registry that keeps handles +** for all loaded C libraries +*/ +static const char *const CLIBS = "_CLIBS"; + +#define LIB_FAIL "open" + + +#define setprogdir(L) ((void)0) + + +/* +** Special type equivalent to '(void*)' for functions in gcc +** (to suppress warnings when converting function pointers) +*/ +typedef void (*voidf)(void); + + +/* +** system-dependent functions +*/ + +/* +** unload library 'lib' +*/ +static void lsys_unloadlib (void *lib); + +/* +** load C library in file 'path'. If 'seeglb', load with all names in +** the library global. +** Returns the library; in case of error, returns NULL plus an +** error string in the stack. +*/ +static void *lsys_load (lua_State *L, const char *path, int seeglb); + +/* +** Try to find a function named 'sym' in library 'lib'. +** Returns the function; in case of error, returns NULL plus an +** error string in the stack. +*/ +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym); + + + + +#if defined(LUA_USE_DLOPEN) /* { */ +/* +** {======================================================================== +** This is an implementation of loadlib based on the dlfcn interface. +** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, +** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least +** as an emulation layer on top of native functions. +** ========================================================================= +*/ + +#include + +/* +** Macro to convert pointer-to-void* to pointer-to-function. This cast +** is undefined according to ISO C, but POSIX assumes that it works. +** (The '__extension__' in gnu compilers is only to avoid warnings.) +*/ +#if defined(__GNUC__) +#define cast_func(p) (__extension__ (lua_CFunction)(p)) +#else +#define cast_func(p) ((lua_CFunction)(p)) +#endif + + +static void lsys_unloadlib (void *lib) { + dlclose(lib); +} + + +static void *lsys_load (lua_State *L, const char *path, int seeglb) { + void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); + if (l_unlikely(lib == NULL)) + lua_pushstring(L, dlerror()); + return lib; +} + + +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = cast_func(dlsym(lib, sym)); + if (l_unlikely(f == NULL)) + lua_pushstring(L, dlerror()); + return f; +} + +/* }====================================================== */ + + + +#elif defined(LUA_DL_DLL) /* }{ */ +/* +** {====================================================================== +** This is an implementation of loadlib for Windows using native functions. +** ======================================================================= +*/ + +#include + + +/* +** optional flags for LoadLibraryEx +*/ +#if !defined(LUA_LLE_FLAGS) +#define LUA_LLE_FLAGS 0 +#endif + + +#undef setprogdir + + +/* +** Replace in the path (on the top of the stack) any occurrence +** of LUA_EXEC_DIR with the executable's path. +*/ +static void setprogdir (lua_State *L) { + char buff[MAX_PATH + 1]; + char *lb; + DWORD nsize = sizeof(buff)/sizeof(char); + DWORD n = GetModuleFileNameA(NULL, buff, nsize); /* get exec. name */ + if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) + luaL_error(L, "unable to get ModuleFileName"); + else { + *lb = '\0'; /* cut name on the last '\\' to get the path */ + luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); + lua_remove(L, -2); /* remove original string */ + } +} + + + + +static void pusherror (lua_State *L) { + int error = GetLastError(); + char buffer[128]; + if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) + lua_pushstring(L, buffer); + else + lua_pushfstring(L, "system error %d\n", error); +} + +static void lsys_unloadlib (void *lib) { + FreeLibrary((HMODULE)lib); +} + + +static void *lsys_load (lua_State *L, const char *path, int seeglb) { + HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); + (void)(seeglb); /* not used: symbols are 'global' by default */ + if (lib == NULL) pusherror(L); + return lib; +} + + +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)(voidf)GetProcAddress((HMODULE)lib, sym); + if (f == NULL) pusherror(L); + return f; +} + +/* }====================================================== */ + + +#else /* }{ */ +/* +** {====================================================== +** Fallback for other systems +** ======================================================= +*/ + +#undef LIB_FAIL +#define LIB_FAIL "absent" + + +#define DLMSG "dynamic libraries not enabled; check your Lua installation" + + +static void lsys_unloadlib (void *lib) { + (void)(lib); /* not used */ +} + + +static void *lsys_load (lua_State *L, const char *path, int seeglb) { + (void)(path); (void)(seeglb); /* not used */ + lua_pushliteral(L, DLMSG); + return NULL; +} + + +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { + (void)(lib); (void)(sym); /* not used */ + lua_pushliteral(L, DLMSG); + return NULL; +} + +/* }====================================================== */ +#endif /* } */ + + +/* +** {================================================================== +** Set Paths +** =================================================================== +*/ + +/* +** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment +** variables that Lua check to set its paths. +*/ +#if !defined(LUA_PATH_VAR) +#define LUA_PATH_VAR "LUA_PATH" +#endif + +#if !defined(LUA_CPATH_VAR) +#define LUA_CPATH_VAR "LUA_CPATH" +#endif + + + +/* +** return registry.LUA_NOENV as a boolean +*/ +static int noenv (lua_State *L) { + int b; + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + b = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + return b; +} + + +/* +** Set a path +*/ +static void setpath (lua_State *L, const char *fieldname, + const char *envname, + const char *dft) { + const char *dftmark; + const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX); + const char *path = getenv(nver); /* try versioned name */ + if (path == NULL) /* no versioned environment variable? */ + path = getenv(envname); /* try unversioned name */ + if (path == NULL || noenv(L)) /* no environment variable? */ + lua_pushstring(L, dft); /* use default */ + else if ((dftmark = strstr(path, LUA_PATH_SEP LUA_PATH_SEP)) == NULL) + lua_pushstring(L, path); /* nothing to change */ + else { /* path contains a ";;": insert default path in its place */ + size_t len = strlen(path); + luaL_Buffer b; + luaL_buffinit(L, &b); + if (path < dftmark) { /* is there a prefix before ';;'? */ + luaL_addlstring(&b, path, dftmark - path); /* add it */ + luaL_addchar(&b, *LUA_PATH_SEP); + } + luaL_addstring(&b, dft); /* add default */ + if (dftmark < path + len - 2) { /* is there a suffix after ';;'? */ + luaL_addchar(&b, *LUA_PATH_SEP); + luaL_addlstring(&b, dftmark + 2, (path + len - 2) - dftmark); + } + luaL_pushresult(&b); + } + setprogdir(L); + lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */ + lua_pop(L, 1); /* pop versioned variable name ('nver') */ +} + +/* }================================================================== */ + + +/* +** return registry.CLIBS[path] +*/ +static void *checkclib (lua_State *L, const char *path) { + void *plib; + lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); + lua_getfield(L, -1, path); + plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ + lua_pop(L, 2); /* pop CLIBS table and 'plib' */ + return plib; +} + + +/* +** registry.CLIBS[path] = plib -- for queries +** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries +*/ +static void addtoclib (lua_State *L, const char *path, void *plib) { + lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); + lua_pushlightuserdata(L, plib); + lua_pushvalue(L, -1); + lua_setfield(L, -3, path); /* CLIBS[path] = plib */ + lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ + lua_pop(L, 1); /* pop CLIBS table */ +} + + +/* +** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib +** handles in list CLIBS +*/ +static int gctm (lua_State *L) { + lua_Integer n = luaL_len(L, 1); + for (; n >= 1; n--) { /* for each handle, in reverse order */ + lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ + lsys_unloadlib(lua_touserdata(L, -1)); + lua_pop(L, 1); /* pop handle */ + } + return 0; +} + + + +/* error codes for 'lookforfunc' */ +#define ERRLIB 1 +#define ERRFUNC 2 + +/* +** Look for a C function named 'sym' in a dynamically loaded library +** 'path'. +** First, check whether the library is already loaded; if not, try +** to load it. +** Then, if 'sym' is '*', return true (as library has been loaded). +** Otherwise, look for symbol 'sym' in the library and push a +** C function with that symbol. +** Return 0 and 'true' or a function in the stack; in case of +** errors, return an error code and an error message in the stack. +*/ +static int lookforfunc (lua_State *L, const char *path, const char *sym) { + void *reg = checkclib(L, path); /* check loaded C libraries */ + if (reg == NULL) { /* must load library? */ + reg = lsys_load(L, path, *sym == '*'); /* global symbols if 'sym'=='*' */ + if (reg == NULL) return ERRLIB; /* unable to load library */ + addtoclib(L, path, reg); + } + if (*sym == '*') { /* loading only library (no function)? */ + lua_pushboolean(L, 1); /* return 'true' */ + return 0; /* no errors */ + } + else { + lua_CFunction f = lsys_sym(L, reg, sym); + if (f == NULL) + return ERRFUNC; /* unable to find function */ + lua_pushcfunction(L, f); /* else create new function */ + return 0; /* no errors */ + } +} + + +static int ll_loadlib (lua_State *L) { + const char *path = luaL_checkstring(L, 1); + const char *init = luaL_checkstring(L, 2); + int stat = lookforfunc(L, path, init); + if (l_likely(stat == 0)) /* no errors? */ + return 1; /* return the loaded function */ + else { /* error; error message is on stack top */ + luaL_pushfail(L); + lua_insert(L, -2); + lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); + return 3; /* return fail, error message, and where */ + } +} + + + +/* +** {====================================================== +** 'require' function +** ======================================================= +*/ + + +static int readable (const char *filename) { + FILE *f = fopen(filename, "r"); /* try to open file */ + if (f == NULL) return 0; /* open failed */ + fclose(f); + return 1; +} + + +/* +** Get the next name in '*path' = 'name1;name2;name3;...', changing +** the ending ';' to '\0' to create a zero-terminated string. Return +** NULL when list ends. +*/ +static const char *getnextfilename (char **path, char *end) { + char *sep; + char *name = *path; + if (name == end) + return NULL; /* no more names */ + else if (*name == '\0') { /* from previous iteration? */ + *name = *LUA_PATH_SEP; /* restore separator */ + name++; /* skip it */ + } + sep = strchr(name, *LUA_PATH_SEP); /* find next separator */ + if (sep == NULL) /* separator not found? */ + sep = end; /* name goes until the end */ + *sep = '\0'; /* finish file name */ + *path = sep; /* will start next search from here */ + return name; +} + + +/* +** Given a path such as ";blabla.so;blublu.so", pushes the string +** +** no file 'blabla.so' +** no file 'blublu.so' +*/ +static void pusherrornotfound (lua_State *L, const char *path) { + luaL_Buffer b; + luaL_buffinit(L, &b); + luaL_addstring(&b, "no file '"); + luaL_addgsub(&b, path, LUA_PATH_SEP, "'\n\tno file '"); + luaL_addstring(&b, "'"); + luaL_pushresult(&b); +} + + +static const char *searchpath (lua_State *L, const char *name, + const char *path, + const char *sep, + const char *dirsep) { + luaL_Buffer buff; + char *pathname; /* path with name inserted */ + char *endpathname; /* its end */ + const char *filename; + /* separator is non-empty and appears in 'name'? */ + if (*sep != '\0' && strchr(name, *sep) != NULL) + name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ + luaL_buffinit(L, &buff); + /* add path to the buffer, replacing marks ('?') with the file name */ + luaL_addgsub(&buff, path, LUA_PATH_MARK, name); + luaL_addchar(&buff, '\0'); + pathname = luaL_buffaddr(&buff); /* writable list of file names */ + endpathname = pathname + luaL_bufflen(&buff) - 1; + while ((filename = getnextfilename(&pathname, endpathname)) != NULL) { + if (readable(filename)) /* does file exist and is readable? */ + return lua_pushstring(L, filename); /* save and return name */ + } + luaL_pushresult(&buff); /* push path to create error message */ + pusherrornotfound(L, lua_tostring(L, -1)); /* create error message */ + return NULL; /* not found */ +} + + +static int ll_searchpath (lua_State *L) { + const char *f = searchpath(L, luaL_checkstring(L, 1), + luaL_checkstring(L, 2), + luaL_optstring(L, 3, "."), + luaL_optstring(L, 4, LUA_DIRSEP)); + if (f != NULL) return 1; + else { /* error message is on top of the stack */ + luaL_pushfail(L); + lua_insert(L, -2); + return 2; /* return fail + error message */ + } +} + + +static const char *findfile (lua_State *L, const char *name, + const char *pname, + const char *dirsep) { + const char *path; + lua_getfield(L, lua_upvalueindex(1), pname); + path = lua_tostring(L, -1); + if (l_unlikely(path == NULL)) + luaL_error(L, "'package.%s' must be a string", pname); + return searchpath(L, name, path, ".", dirsep); +} + + +static int checkload (lua_State *L, int stat, const char *filename) { + if (l_likely(stat)) { /* module loaded successfully? */ + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; /* return open function and file name */ + } + else + return luaL_error(L, "error loading module '%s' from file '%s':\n\t%s", + lua_tostring(L, 1), filename, lua_tostring(L, -1)); +} + + +static int searcher_Lua (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + filename = findfile(L, name, "path", LUA_LSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); +} + + +/* +** Try to find a load function for module 'modname' at file 'filename'. +** First, change '.' to '_' in 'modname'; then, if 'modname' has +** the form X-Y (that is, it has an "ignore mark"), build a function +** name "luaopen_X" and look for it. (For compatibility, if that +** fails, it also tries "luaopen_Y".) If there is no ignore mark, +** look for a function named "luaopen_modname". +*/ +static int loadfunc (lua_State *L, const char *filename, const char *modname) { + const char *openfunc; + const char *mark; + modname = luaL_gsub(L, modname, ".", LUA_OFSEP); + mark = strchr(modname, *LUA_IGMARK); + if (mark) { + int stat; + openfunc = lua_pushlstring(L, modname, mark - modname); + openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc); + stat = lookforfunc(L, filename, openfunc); + if (stat != ERRFUNC) return stat; + modname = mark + 1; /* else go ahead and try old-style name */ + } + openfunc = lua_pushfstring(L, LUA_POF"%s", modname); + return lookforfunc(L, filename, openfunc); +} + + +static int searcher_C (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (loadfunc(L, filename, name) == 0), filename); +} + + +static int searcher_Croot (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + const char *p = strchr(name, '.'); + int stat; + if (p == NULL) return 0; /* is root */ + lua_pushlstring(L, name, p - name); + filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* root not found */ + if ((stat = loadfunc(L, filename, name)) != 0) { + if (stat != ERRFUNC) + return checkload(L, 0, filename); /* real error */ + else { /* open function not found */ + lua_pushfstring(L, "no module '%s' in file '%s'", name, filename); + return 1; + } + } + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; +} + + +static int searcher_preload (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + if (lua_getfield(L, -1, name) == LUA_TNIL) { /* not found? */ + lua_pushfstring(L, "no field package.preload['%s']", name); + return 1; + } + else { + lua_pushliteral(L, ":preload:"); + return 2; + } +} + + +static void findloader (lua_State *L, const char *name) { + int i; + luaL_Buffer msg; /* to build error message */ + /* push 'package.searchers' to index 3 in the stack */ + if (l_unlikely(lua_getfield(L, lua_upvalueindex(1), "searchers") + != LUA_TTABLE)) + luaL_error(L, "'package.searchers' must be a table"); + luaL_buffinit(L, &msg); + /* iterate over available searchers to find a loader */ + for (i = 1; ; i++) { + luaL_addstring(&msg, "\n\t"); /* error-message prefix */ + if (l_unlikely(lua_rawgeti(L, 3, i) == LUA_TNIL)) { /* no more searchers? */ + lua_pop(L, 1); /* remove nil */ + luaL_buffsub(&msg, 2); /* remove prefix */ + luaL_pushresult(&msg); /* create error message */ + luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1)); + } + lua_pushstring(L, name); + lua_call(L, 1, 2); /* call it */ + if (lua_isfunction(L, -2)) /* did it find a loader? */ + return; /* module loader found */ + else if (lua_isstring(L, -2)) { /* searcher returned error message? */ + lua_pop(L, 1); /* remove extra return */ + luaL_addvalue(&msg); /* concatenate error message */ + } + else { /* no error message */ + lua_pop(L, 2); /* remove both returns */ + luaL_buffsub(&msg, 2); /* remove prefix */ + } + } +} + + +static int ll_require (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_settop(L, 1); /* LOADED table will be at index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_getfield(L, 2, name); /* LOADED[name] */ + if (lua_toboolean(L, -1)) /* is it there? */ + return 1; /* package is already loaded */ + /* else must load package */ + lua_pop(L, 1); /* remove 'getfield' result */ + findloader(L, name); + lua_rotate(L, -2, 1); /* function <-> loader data */ + lua_pushvalue(L, 1); /* name is 1st argument to module loader */ + lua_pushvalue(L, -3); /* loader data is 2nd argument */ + /* stack: ...; loader data; loader function; mod. name; loader data */ + lua_call(L, 2, 1); /* run loader to load module */ + /* stack: ...; loader data; result from loader */ + if (!lua_isnil(L, -1)) /* non-nil return? */ + lua_setfield(L, 2, name); /* LOADED[name] = returned value */ + else + lua_pop(L, 1); /* pop nil */ + if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ + lua_pushboolean(L, 1); /* use true as result */ + lua_copy(L, -1, -2); /* replace loader result */ + lua_setfield(L, 2, name); /* LOADED[name] = true */ + } + lua_rotate(L, -2, 1); /* loader data <-> module result */ + return 2; /* return module result and loader data */ +} + +/* }====================================================== */ + + + + +static const luaL_Reg pk_funcs[] = { + {"loadlib", ll_loadlib}, + {"searchpath", ll_searchpath}, + /* placeholders */ + {"preload", NULL}, + {"cpath", NULL}, + {"path", NULL}, + {"searchers", NULL}, + {"loaded", NULL}, + {NULL, NULL} +}; + + +static const luaL_Reg ll_funcs[] = { + {"require", ll_require}, + {NULL, NULL} +}; + + +static void createsearcherstable (lua_State *L) { + static const lua_CFunction searchers[] = + {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; + int i; + /* create 'searchers' table */ + lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); + /* fill it with predefined searchers */ + for (i=0; searchers[i] != NULL; i++) { + lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ + lua_pushcclosure(L, searchers[i], 1); + lua_rawseti(L, -2, i+1); + } + lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ +} + + +/* +** create table CLIBS to keep track of loaded C libraries, +** setting a finalizer to close all libraries when closing state. +*/ +static void createclibstable (lua_State *L) { + luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */ + lua_createtable(L, 0, 1); /* create metatable for CLIBS */ + lua_pushcfunction(L, gctm); + lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ + lua_setmetatable(L, -2); +} + + +LUAMOD_API int luaopen_package (lua_State *L) { + createclibstable(L); + luaL_newlib(L, pk_funcs); /* create 'package' table */ + createsearcherstable(L); + /* set paths */ + setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT); + setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT); + /* store config information */ + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" + LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); + lua_setfield(L, -2, "config"); + /* set field 'loaded' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_setfield(L, -2, "loaded"); + /* set field 'preload' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + lua_setfield(L, -2, "preload"); + lua_pushglobaltable(L); + lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ + luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ + lua_pop(L, 1); /* pop global table */ + return 1; /* return 'package' table */ +} + diff --git a/lua/lobject.c b/lua/lobject.c new file mode 100644 index 0000000..0e504be --- /dev/null +++ b/lua/lobject.c @@ -0,0 +1,592 @@ +/* +** $Id: lobject.c $ +** Some generic functions over Lua objects +** See Copyright Notice in lua.h +*/ + +#define lobject_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lctype.h" +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "lvm.h" + + +/* +** Computes ceil(log2(x)) +*/ +int luaO_ceillog2 (unsigned int x) { + static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }; + int l = 0; + x--; + while (x >= 256) { l += 8; x >>= 8; } + return l + log_2[x]; +} + + +static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, + lua_Integer v2) { + switch (op) { + case LUA_OPADD: return intop(+, v1, v2); + case LUA_OPSUB:return intop(-, v1, v2); + case LUA_OPMUL:return intop(*, v1, v2); + case LUA_OPMOD: return luaV_mod(L, v1, v2); + case LUA_OPIDIV: return luaV_idiv(L, v1, v2); + case LUA_OPBAND: return intop(&, v1, v2); + case LUA_OPBOR: return intop(|, v1, v2); + case LUA_OPBXOR: return intop(^, v1, v2); + case LUA_OPSHL: return luaV_shiftl(v1, v2); + case LUA_OPSHR: return luaV_shiftl(v1, -v2); + case LUA_OPUNM: return intop(-, 0, v1); + case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); + default: lua_assert(0); return 0; + } +} + + +static lua_Number numarith (lua_State *L, int op, lua_Number v1, + lua_Number v2) { + switch (op) { + case LUA_OPADD: return luai_numadd(L, v1, v2); + case LUA_OPSUB: return luai_numsub(L, v1, v2); + case LUA_OPMUL: return luai_nummul(L, v1, v2); + case LUA_OPDIV: return luai_numdiv(L, v1, v2); + case LUA_OPPOW: return luai_numpow(L, v1, v2); + case LUA_OPIDIV: return luai_numidiv(L, v1, v2); + case LUA_OPUNM: return luai_numunm(L, v1); + case LUA_OPMOD: return luaV_modf(L, v1, v2); + default: lua_assert(0); return 0; + } +} + + +int luaO_rawarith (lua_State *L, int op, const TValue *p1, const TValue *p2, + TValue *res) { + switch (op) { + case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: + case LUA_OPSHL: case LUA_OPSHR: + case LUA_OPBNOT: { /* operate only on integers */ + lua_Integer i1; lua_Integer i2; + if (tointegerns(p1, &i1) && tointegerns(p2, &i2)) { + setivalue(res, intarith(L, op, i1, i2)); + return 1; + } + else return 0; /* fail */ + } + case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */ + lua_Number n1; lua_Number n2; + if (tonumberns(p1, n1) && tonumberns(p2, n2)) { + setfltvalue(res, numarith(L, op, n1, n2)); + return 1; + } + else return 0; /* fail */ + } + default: { /* other operations */ + lua_Number n1; lua_Number n2; + if (ttisinteger(p1) && ttisinteger(p2)) { + setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); + return 1; + } + else if (tonumberns(p1, n1) && tonumberns(p2, n2)) { + setfltvalue(res, numarith(L, op, n1, n2)); + return 1; + } + else return 0; /* fail */ + } + } +} + + +void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, + StkId res) { + if (!luaO_rawarith(L, op, p1, p2, s2v(res))) { + /* could not perform raw operation; try metamethod */ + luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD)); + } +} + + +int luaO_hexavalue (int c) { + if (lisdigit(c)) return c - '0'; + else return (ltolower(c) - 'a') + 10; +} + + +static int isneg (const char **s) { + if (**s == '-') { (*s)++; return 1; } + else if (**s == '+') (*s)++; + return 0; +} + + + +/* +** {================================================================== +** Lua's implementation for 'lua_strx2number' +** =================================================================== +*/ + +#if !defined(lua_strx2number) + +/* maximum number of significant digits to read (to avoid overflows + even with single floats) */ +#define MAXSIGDIG 30 + +/* +** convert a hexadecimal numeric string to a number, following +** C99 specification for 'strtod' +*/ +static lua_Number lua_strx2number (const char *s, char **endptr) { + int dot = lua_getlocaledecpoint(); + lua_Number r = 0.0; /* result (accumulator) */ + int sigdig = 0; /* number of significant digits */ + int nosigdig = 0; /* number of non-significant digits */ + int e = 0; /* exponent correction */ + int neg; /* 1 if number is negative */ + int hasdot = 0; /* true after seen a dot */ + *endptr = cast_charp(s); /* nothing is valid yet */ + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); /* check sign */ + if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ + return 0.0; /* invalid format (no '0x') */ + for (s += 2; ; s++) { /* skip '0x' and read numeral */ + if (*s == dot) { + if (hasdot) break; /* second dot? stop loop */ + else hasdot = 1; + } + else if (lisxdigit(cast_uchar(*s))) { + if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */ + nosigdig++; + else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ + r = (r * cast_num(16.0)) + luaO_hexavalue(*s); + else e++; /* too many digits; ignore, but still count for exponent */ + if (hasdot) e--; /* decimal digit? correct exponent */ + } + else break; /* neither a dot nor a digit */ + } + if (nosigdig + sigdig == 0) /* no digits? */ + return 0.0; /* invalid format */ + *endptr = cast_charp(s); /* valid up to here */ + e *= 4; /* each digit multiplies/divides value by 2^4 */ + if (*s == 'p' || *s == 'P') { /* exponent part? */ + int exp1 = 0; /* exponent value */ + int neg1; /* exponent sign */ + s++; /* skip 'p' */ + neg1 = isneg(&s); /* sign */ + if (!lisdigit(cast_uchar(*s))) + return 0.0; /* invalid; must have at least one digit */ + while (lisdigit(cast_uchar(*s))) /* read exponent */ + exp1 = exp1 * 10 + *(s++) - '0'; + if (neg1) exp1 = -exp1; + e += exp1; + *endptr = cast_charp(s); /* valid up to here */ + } + if (neg) r = -r; + return l_mathop(ldexp)(r, e); +} + +#endif +/* }====================================================== */ + + +/* maximum length of a numeral to be converted to a number */ +#if !defined (L_MAXLENNUM) +#define L_MAXLENNUM 200 +#endif + +/* +** Convert string 's' to a Lua number (put in 'result'). Return NULL on +** fail or the address of the ending '\0' on success. ('mode' == 'x') +** means a hexadecimal numeral. +*/ +static const char *l_str2dloc (const char *s, lua_Number *result, int mode) { + char *endptr; + *result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */ + : lua_str2number(s, &endptr); + if (endptr == s) return NULL; /* nothing recognized? */ + while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */ + return (*endptr == '\0') ? endptr : NULL; /* OK iff no trailing chars */ +} + + +/* +** Convert string 's' to a Lua number (put in 'result') handling the +** current locale. +** This function accepts both the current locale or a dot as the radix +** mark. If the conversion fails, it may mean number has a dot but +** locale accepts something else. In that case, the code copies 's' +** to a buffer (because 's' is read-only), changes the dot to the +** current locale radix mark, and tries to convert again. +** The variable 'mode' checks for special characters in the string: +** - 'n' means 'inf' or 'nan' (which should be rejected) +** - 'x' means a hexadecimal numeral +** - '.' just optimizes the search for the common case (no special chars) +*/ +static const char *l_str2d (const char *s, lua_Number *result) { + const char *endptr; + const char *pmode = strpbrk(s, ".xXnN"); /* look for special chars */ + int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0; + if (mode == 'n') /* reject 'inf' and 'nan' */ + return NULL; + endptr = l_str2dloc(s, result, mode); /* try to convert */ + if (endptr == NULL) { /* failed? may be a different locale */ + char buff[L_MAXLENNUM + 1]; + const char *pdot = strchr(s, '.'); + if (pdot == NULL || strlen(s) > L_MAXLENNUM) + return NULL; /* string too long or no dot; fail */ + strcpy(buff, s); /* copy string to buffer */ + buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */ + endptr = l_str2dloc(buff, result, mode); /* try again */ + if (endptr != NULL) + endptr = s + (endptr - buff); /* make relative to 's' */ + } + return endptr; +} + + +#define MAXBY10 cast(lua_Unsigned, LUA_MAXINTEGER / 10) +#define MAXLASTD cast_int(LUA_MAXINTEGER % 10) + +static const char *l_str2int (const char *s, lua_Integer *result) { + lua_Unsigned a = 0; + int empty = 1; + int neg; + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); + if (s[0] == '0' && + (s[1] == 'x' || s[1] == 'X')) { /* hex? */ + s += 2; /* skip '0x' */ + for (; lisxdigit(cast_uchar(*s)); s++) { + a = a * 16 + luaO_hexavalue(*s); + empty = 0; + } + } + else { /* decimal */ + for (; lisdigit(cast_uchar(*s)); s++) { + int d = *s - '0'; + if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */ + return NULL; /* do not accept it (as integer) */ + a = a * 10 + d; + empty = 0; + } + } + while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */ + if (empty || *s != '\0') return NULL; /* something wrong in the numeral */ + else { + *result = l_castU2S((neg) ? 0u - a : a); + return s; + } +} + + +size_t luaO_str2num (const char *s, TValue *o) { + lua_Integer i; lua_Number n; + const char *e; + if ((e = l_str2int(s, &i)) != NULL) { /* try as an integer */ + setivalue(o, i); + } + else if ((e = l_str2d(s, &n)) != NULL) { /* else try as a float */ + setfltvalue(o, n); + } + else + return 0; /* conversion failed */ + return (e - s) + 1; /* success; return string size */ +} + + +int luaO_utf8esc (char *buff, unsigned long x) { + int n = 1; /* number of bytes put in buffer (backwards) */ + lua_assert(x <= 0x7FFFFFFFu); + if (x < 0x80) /* ascii? */ + buff[UTF8BUFFSZ - 1] = cast_char(x); + else { /* need continuation bytes */ + unsigned int mfb = 0x3f; /* maximum that fits in first byte */ + do { /* add continuation bytes */ + buff[UTF8BUFFSZ - (n++)] = cast_char(0x80 | (x & 0x3f)); + x >>= 6; /* remove added bits */ + mfb >>= 1; /* now there is one less bit available in first byte */ + } while (x > mfb); /* still needs continuation byte? */ + buff[UTF8BUFFSZ - n] = cast_char((~mfb << 1) | x); /* add first byte */ + } + return n; +} + + +/* +** Maximum length of the conversion of a number to a string. Must be +** enough to accommodate both LUA_INTEGER_FMT and LUA_NUMBER_FMT. +** (For a long long int, this is 19 digits plus a sign and a final '\0', +** adding to 21. For a long double, it can go to a sign, 33 digits, +** the dot, an exponent letter, an exponent sign, 5 exponent digits, +** and a final '\0', adding to 43.) +*/ +#define MAXNUMBER2STR 44 + + +/* +** Convert a number object to a string, adding it to a buffer +*/ +static int tostringbuff (TValue *obj, char *buff) { + int len; + lua_assert(ttisnumber(obj)); + if (ttisinteger(obj)) + len = lua_integer2str(buff, MAXNUMBER2STR, ivalue(obj)); + else { + len = lua_number2str(buff, MAXNUMBER2STR, fltvalue(obj)); + if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ + buff[len++] = lua_getlocaledecpoint(); + buff[len++] = '0'; /* adds '.0' to result */ + } + } + return len; +} + + +/* +** Convert a number object to a Lua string, replacing the value at 'obj' +*/ +void luaO_tostring (lua_State *L, TValue *obj) { + char buff[MAXNUMBER2STR]; + int len = tostringbuff(obj, buff); + setsvalue(L, obj, luaS_newlstr(L, buff, len)); +} + + + + +/* +** {================================================================== +** 'luaO_pushvfstring' +** =================================================================== +*/ + +/* size for buffer space used by 'luaO_pushvfstring' */ +#define BUFVFS 200 + +/* buffer used by 'luaO_pushvfstring' */ +typedef struct BuffFS { + lua_State *L; + int pushed; /* number of string pieces already on the stack */ + int blen; /* length of partial string in 'space' */ + char space[BUFVFS]; /* holds last part of the result */ +} BuffFS; + + +/* +** Push given string to the stack, as part of the buffer, and +** join the partial strings in the stack into one. +*/ +static void pushstr (BuffFS *buff, const char *str, size_t l) { + lua_State *L = buff->L; + setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); + L->top++; /* may use one extra slot */ + buff->pushed++; + luaV_concat(L, buff->pushed); /* join partial results into one */ + buff->pushed = 1; +} + + +/* +** empty the buffer space into the stack +*/ +static void clearbuff (BuffFS *buff) { + pushstr(buff, buff->space, buff->blen); /* push buffer contents */ + buff->blen = 0; /* space now is empty */ +} + + +/* +** Get a space of size 'sz' in the buffer. If buffer has not enough +** space, empty it. 'sz' must fit in an empty buffer. +*/ +static char *getbuff (BuffFS *buff, int sz) { + lua_assert(buff->blen <= BUFVFS); lua_assert(sz <= BUFVFS); + if (sz > BUFVFS - buff->blen) /* not enough space? */ + clearbuff(buff); + return buff->space + buff->blen; +} + + +#define addsize(b,sz) ((b)->blen += (sz)) + + +/* +** Add 'str' to the buffer. If string is larger than the buffer space, +** push the string directly to the stack. +*/ +static void addstr2buff (BuffFS *buff, const char *str, size_t slen) { + if (slen <= BUFVFS) { /* does string fit into buffer? */ + char *bf = getbuff(buff, cast_int(slen)); + memcpy(bf, str, slen); /* add string to buffer */ + addsize(buff, cast_int(slen)); + } + else { /* string larger than buffer */ + clearbuff(buff); /* string comes after buffer's content */ + pushstr(buff, str, slen); /* push string */ + } +} + + +/* +** Add a number to the buffer. +*/ +static void addnum2buff (BuffFS *buff, TValue *num) { + char *numbuff = getbuff(buff, MAXNUMBER2STR); + int len = tostringbuff(num, numbuff); /* format number into 'numbuff' */ + addsize(buff, len); +} + + +/* +** this function handles only '%d', '%c', '%f', '%p', '%s', and '%%' + conventional formats, plus Lua-specific '%I' and '%U' +*/ +const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { + BuffFS buff; /* holds last part of the result */ + const char *e; /* points to next '%' */ + buff.pushed = buff.blen = 0; + buff.L = L; + while ((e = strchr(fmt, '%')) != NULL) { + addstr2buff(&buff, fmt, e - fmt); /* add 'fmt' up to '%' */ + switch (*(e + 1)) { /* conversion specifier */ + case 's': { /* zero-terminated string */ + const char *s = va_arg(argp, char *); + if (s == NULL) s = "(null)"; + addstr2buff(&buff, s, strlen(s)); + break; + } + case 'c': { /* an 'int' as a character */ + char c = cast_uchar(va_arg(argp, int)); + addstr2buff(&buff, &c, sizeof(char)); + break; + } + case 'd': { /* an 'int' */ + TValue num; + setivalue(&num, va_arg(argp, int)); + addnum2buff(&buff, &num); + break; + } + case 'I': { /* a 'lua_Integer' */ + TValue num; + setivalue(&num, cast(lua_Integer, va_arg(argp, l_uacInt))); + addnum2buff(&buff, &num); + break; + } + case 'f': { /* a 'lua_Number' */ + TValue num; + setfltvalue(&num, cast_num(va_arg(argp, l_uacNumber))); + addnum2buff(&buff, &num); + break; + } + case 'p': { /* a pointer */ + const int sz = 3 * sizeof(void*) + 8; /* enough space for '%p' */ + char *bf = getbuff(&buff, sz); + void *p = va_arg(argp, void *); + int len = lua_pointer2str(bf, sz, p); + addsize(&buff, len); + break; + } + case 'U': { /* a 'long' as a UTF-8 sequence */ + char bf[UTF8BUFFSZ]; + int len = luaO_utf8esc(bf, va_arg(argp, long)); + addstr2buff(&buff, bf + UTF8BUFFSZ - len, len); + break; + } + case '%': { + addstr2buff(&buff, "%", 1); + break; + } + default: { + luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'", + *(e + 1)); + } + } + fmt = e + 2; /* skip '%' and the specifier */ + } + addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */ + clearbuff(&buff); /* empty buffer into the stack */ + lua_assert(buff.pushed == 1); + return svalue(s2v(L->top - 1)); +} + + +const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { + const char *msg; + va_list argp; + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + return msg; +} + +/* }================================================================== */ + + +#define RETS "..." +#define PRE "[string \"" +#define POS "\"]" + +#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) + +void luaO_chunkid (char *out, const char *source, size_t srclen) { + size_t bufflen = LUA_IDSIZE; /* free space in buffer */ + if (*source == '=') { /* 'literal' source */ + if (srclen <= bufflen) /* small enough? */ + memcpy(out, source + 1, srclen * sizeof(char)); + else { /* truncate it */ + addstr(out, source + 1, bufflen - 1); + *out = '\0'; + } + } + else if (*source == '@') { /* file name */ + if (srclen <= bufflen) /* small enough? */ + memcpy(out, source + 1, srclen * sizeof(char)); + else { /* add '...' before rest of name */ + addstr(out, RETS, LL(RETS)); + bufflen -= LL(RETS); + memcpy(out, source + 1 + srclen - bufflen, bufflen * sizeof(char)); + } + } + else { /* string; format as [string "source"] */ + const char *nl = strchr(source, '\n'); /* find first new line (if any) */ + addstr(out, PRE, LL(PRE)); /* add prefix */ + bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ + if (srclen < bufflen && nl == NULL) { /* small one-line source? */ + addstr(out, source, srclen); /* keep it */ + } + else { + if (nl != NULL) srclen = nl - source; /* stop at first newline */ + if (srclen > bufflen) srclen = bufflen; + addstr(out, source, srclen); + addstr(out, RETS, LL(RETS)); + } + memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); + } +} + diff --git a/lua/lobject.h b/lua/lobject.h new file mode 100644 index 0000000..950bebb --- /dev/null +++ b/lua/lobject.h @@ -0,0 +1,800 @@ +/* +** $Id: lobject.h $ +** Type definitions for Lua objects +** See Copyright Notice in lua.h +*/ + + +#ifndef lobject_h +#define lobject_h + + +#include + + +#include "llimits.h" +#include "lua.h" + + +/* +** Extra types for collectable non-values +*/ +#define LUA_TUPVAL LUA_NUMTYPES /* upvalues */ +#define LUA_TPROTO (LUA_NUMTYPES+1) /* function prototypes */ +#define LUA_TDEADKEY (LUA_NUMTYPES+2) /* removed keys in tables */ + + + +/* +** number of all possible types (including LUA_TNONE but excluding DEADKEY) +*/ +#define LUA_TOTALTYPES (LUA_TPROTO + 2) + + +/* +** tags for Tagged Values have the following use of bits: +** bits 0-3: actual tag (a LUA_T* constant) +** bits 4-5: variant bits +** bit 6: whether value is collectable +*/ + +/* add variant bits to a type */ +#define makevariant(t,v) ((t) | ((v) << 4)) + + + +/* +** Union of all Lua values +*/ +typedef union Value { + struct GCObject *gc; /* collectable objects */ + void *p; /* light userdata */ + lua_CFunction f; /* light C functions */ + lua_Integer i; /* integer numbers */ + lua_Number n; /* float numbers */ +} Value; + + +/* +** Tagged Values. This is the basic representation of values in Lua: +** an actual value plus a tag with its type. +*/ + +#define TValuefields Value value_; lu_byte tt_ + +typedef struct TValue { + TValuefields; +} TValue; + + +#define val_(o) ((o)->value_) +#define valraw(o) (&val_(o)) + + +/* raw type tag of a TValue */ +#define rawtt(o) ((o)->tt_) + +/* tag with no variants (bits 0-3) */ +#define novariant(t) ((t) & 0x0F) + +/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ +#define withvariant(t) ((t) & 0x3F) +#define ttypetag(o) withvariant(rawtt(o)) + +/* type of a TValue */ +#define ttype(o) (novariant(rawtt(o))) + + +/* Macros to test type */ +#define checktag(o,t) (rawtt(o) == (t)) +#define checktype(o,t) (ttype(o) == (t)) + + +/* Macros for internal tests */ + +/* collectable object has the same tag as the original value */ +#define righttt(obj) (ttypetag(obj) == gcvalue(obj)->tt) + +/* +** Any value being manipulated by the program either is non +** collectable, or the collectable object has the right tag +** and it is not dead. The option 'L == NULL' allows other +** macros using this one to be used where L is not available. +*/ +#define checkliveness(L,obj) \ + ((void)L, lua_longassert(!iscollectable(obj) || \ + (righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj)))))) + + +/* Macros to set values */ + +/* set a value's tag */ +#define settt_(o,t) ((o)->tt_=(t)) + + +/* main macro to copy values (from 'obj1' to 'obj2') */ +#define setobj(L,obj1,obj2) \ + { TValue *io1=(obj1); const TValue *io2=(obj2); \ + io1->value_ = io2->value_; settt_(io1, io2->tt_); \ + checkliveness(L,io1); lua_assert(!isnonstrictnil(io1)); } + +/* +** Different types of assignments, according to source and destination. +** (They are mostly equal now, but may be different in the future.) +*/ + +/* from stack to stack */ +#define setobjs2s(L,o1,o2) setobj(L,s2v(o1),s2v(o2)) +/* to stack (not from same stack) */ +#define setobj2s(L,o1,o2) setobj(L,s2v(o1),o2) +/* from table to same table */ +#define setobjt2t setobj +/* to new object */ +#define setobj2n setobj +/* to table */ +#define setobj2t setobj + + +/* +** Entries in a Lua stack. Field 'tbclist' forms a list of all +** to-be-closed variables active in this stack. Dummy entries are +** used when the distance between two tbc variables does not fit +** in an unsigned short. They are represented by delta==0, and +** their real delta is always the maximum value that fits in +** that field. +*/ +typedef union StackValue { + TValue val; + struct { + TValuefields; + unsigned short delta; + } tbclist; +} StackValue; + + +/* index to stack elements */ +typedef StackValue *StkId; + +/* convert a 'StackValue' to a 'TValue' */ +#define s2v(o) (&(o)->val) + + + +/* +** {================================================================== +** Nil +** =================================================================== +*/ + +/* Standard nil */ +#define LUA_VNIL makevariant(LUA_TNIL, 0) + +/* Empty slot (which might be different from a slot containing nil) */ +#define LUA_VEMPTY makevariant(LUA_TNIL, 1) + +/* Value returned for a key not found in a table (absent key) */ +#define LUA_VABSTKEY makevariant(LUA_TNIL, 2) + + +/* macro to test for (any kind of) nil */ +#define ttisnil(v) checktype((v), LUA_TNIL) + + +/* macro to test for a standard nil */ +#define ttisstrictnil(o) checktag((o), LUA_VNIL) + + +#define setnilvalue(obj) settt_(obj, LUA_VNIL) + + +#define isabstkey(v) checktag((v), LUA_VABSTKEY) + + +/* +** macro to detect non-standard nils (used only in assertions) +*/ +#define isnonstrictnil(v) (ttisnil(v) && !ttisstrictnil(v)) + + +/* +** By default, entries with any kind of nil are considered empty. +** (In any definition, values associated with absent keys must also +** be accepted as empty.) +*/ +#define isempty(v) ttisnil(v) + + +/* macro defining a value corresponding to an absent key */ +#define ABSTKEYCONSTANT {NULL}, LUA_VABSTKEY + + +/* mark an entry as empty */ +#define setempty(v) settt_(v, LUA_VEMPTY) + + + +/* }================================================================== */ + + +/* +** {================================================================== +** Booleans +** =================================================================== +*/ + + +#define LUA_VFALSE makevariant(LUA_TBOOLEAN, 0) +#define LUA_VTRUE makevariant(LUA_TBOOLEAN, 1) + +#define ttisboolean(o) checktype((o), LUA_TBOOLEAN) +#define ttisfalse(o) checktag((o), LUA_VFALSE) +#define ttistrue(o) checktag((o), LUA_VTRUE) + + +#define l_isfalse(o) (ttisfalse(o) || ttisnil(o)) + + +#define setbfvalue(obj) settt_(obj, LUA_VFALSE) +#define setbtvalue(obj) settt_(obj, LUA_VTRUE) + +/* }================================================================== */ + + +/* +** {================================================================== +** Threads +** =================================================================== +*/ + +#define LUA_VTHREAD makevariant(LUA_TTHREAD, 0) + +#define ttisthread(o) checktag((o), ctb(LUA_VTHREAD)) + +#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc)) + +#define setthvalue(L,obj,x) \ + { TValue *io = (obj); lua_State *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VTHREAD)); \ + checkliveness(L,io); } + +#define setthvalue2s(L,o,t) setthvalue(L,s2v(o),t) + +/* }================================================================== */ + + +/* +** {================================================================== +** Collectable Objects +** =================================================================== +*/ + +/* +** Common Header for all collectable objects (in macro form, to be +** included in other objects) +*/ +#define CommonHeader struct GCObject *next; lu_byte tt; lu_byte marked + + +/* Common type for all collectable objects */ +typedef struct GCObject { + CommonHeader; +} GCObject; + + +/* Bit mark for collectable types */ +#define BIT_ISCOLLECTABLE (1 << 6) + +#define iscollectable(o) (rawtt(o) & BIT_ISCOLLECTABLE) + +/* mark a tag as collectable */ +#define ctb(t) ((t) | BIT_ISCOLLECTABLE) + +#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) + +#define gcvalueraw(v) ((v).gc) + +#define setgcovalue(L,obj,x) \ + { TValue *io = (obj); GCObject *i_g=(x); \ + val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); } + +/* }================================================================== */ + + +/* +** {================================================================== +** Numbers +** =================================================================== +*/ + +/* Variant tags for numbers */ +#define LUA_VNUMINT makevariant(LUA_TNUMBER, 0) /* integer numbers */ +#define LUA_VNUMFLT makevariant(LUA_TNUMBER, 1) /* float numbers */ + +#define ttisnumber(o) checktype((o), LUA_TNUMBER) +#define ttisfloat(o) checktag((o), LUA_VNUMFLT) +#define ttisinteger(o) checktag((o), LUA_VNUMINT) + +#define nvalue(o) check_exp(ttisnumber(o), \ + (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o))) +#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n) +#define ivalue(o) check_exp(ttisinteger(o), val_(o).i) + +#define fltvalueraw(v) ((v).n) +#define ivalueraw(v) ((v).i) + +#define setfltvalue(obj,x) \ + { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_VNUMFLT); } + +#define chgfltvalue(obj,x) \ + { TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); } + +#define setivalue(obj,x) \ + { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_VNUMINT); } + +#define chgivalue(obj,x) \ + { TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); } + +/* }================================================================== */ + + +/* +** {================================================================== +** Strings +** =================================================================== +*/ + +/* Variant tags for strings */ +#define LUA_VSHRSTR makevariant(LUA_TSTRING, 0) /* short strings */ +#define LUA_VLNGSTR makevariant(LUA_TSTRING, 1) /* long strings */ + +#define ttisstring(o) checktype((o), LUA_TSTRING) +#define ttisshrstring(o) checktag((o), ctb(LUA_VSHRSTR)) +#define ttislngstring(o) checktag((o), ctb(LUA_VLNGSTR)) + +#define tsvalueraw(v) (gco2ts((v).gc)) + +#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc)) + +#define setsvalue(L,obj,x) \ + { TValue *io = (obj); TString *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \ + checkliveness(L,io); } + +/* set a string to the stack */ +#define setsvalue2s(L,o,s) setsvalue(L,s2v(o),s) + +/* set a string to a new object */ +#define setsvalue2n setsvalue + + +/* +** Header for a string value. +*/ +typedef struct TString { + CommonHeader; + lu_byte extra; /* reserved words for short strings; "has hash" for longs */ + lu_byte shrlen; /* length for short strings */ + unsigned int hash; + union { + size_t lnglen; /* length for long strings */ + struct TString *hnext; /* linked list for hash table */ + } u; + char contents[1]; +} TString; + + + +/* +** Get the actual string (array of bytes) from a 'TString'. +*/ +#define getstr(ts) ((ts)->contents) + + +/* get the actual string (array of bytes) from a Lua value */ +#define svalue(o) getstr(tsvalue(o)) + +/* get string length from 'TString *s' */ +#define tsslen(s) ((s)->tt == LUA_VSHRSTR ? (s)->shrlen : (s)->u.lnglen) + +/* get string length from 'TValue *o' */ +#define vslen(o) tsslen(tsvalue(o)) + +/* }================================================================== */ + + +/* +** {================================================================== +** Userdata +** =================================================================== +*/ + + +/* +** Light userdata should be a variant of userdata, but for compatibility +** reasons they are also different types. +*/ +#define LUA_VLIGHTUSERDATA makevariant(LUA_TLIGHTUSERDATA, 0) + +#define LUA_VUSERDATA makevariant(LUA_TUSERDATA, 0) + +#define ttislightuserdata(o) checktag((o), LUA_VLIGHTUSERDATA) +#define ttisfulluserdata(o) checktag((o), ctb(LUA_VUSERDATA)) + +#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) +#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc)) + +#define pvalueraw(v) ((v).p) + +#define setpvalue(obj,x) \ + { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_VLIGHTUSERDATA); } + +#define setuvalue(L,obj,x) \ + { TValue *io = (obj); Udata *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VUSERDATA)); \ + checkliveness(L,io); } + + +/* Ensures that addresses after this type are always fully aligned. */ +typedef union UValue { + TValue uv; + LUAI_MAXALIGN; /* ensures maximum alignment for udata bytes */ +} UValue; + + +/* +** Header for userdata with user values; +** memory area follows the end of this structure. +*/ +typedef struct Udata { + CommonHeader; + unsigned short nuvalue; /* number of user values */ + size_t len; /* number of bytes */ + struct Table *metatable; + GCObject *gclist; + UValue uv[1]; /* user values */ +} Udata; + + +/* +** Header for userdata with no user values. These userdata do not need +** to be gray during GC, and therefore do not need a 'gclist' field. +** To simplify, the code always use 'Udata' for both kinds of userdata, +** making sure it never accesses 'gclist' on userdata with no user values. +** This structure here is used only to compute the correct size for +** this representation. (The 'bindata' field in its end ensures correct +** alignment for binary data following this header.) +*/ +typedef struct Udata0 { + CommonHeader; + unsigned short nuvalue; /* number of user values */ + size_t len; /* number of bytes */ + struct Table *metatable; + union {LUAI_MAXALIGN;} bindata; +} Udata0; + + +/* compute the offset of the memory area of a userdata */ +#define udatamemoffset(nuv) \ + ((nuv) == 0 ? offsetof(Udata0, bindata) \ + : offsetof(Udata, uv) + (sizeof(UValue) * (nuv))) + +/* get the address of the memory block inside 'Udata' */ +#define getudatamem(u) (cast_charp(u) + udatamemoffset((u)->nuvalue)) + +/* compute the size of a userdata */ +#define sizeudata(nuv,nb) (udatamemoffset(nuv) + (nb)) + +/* }================================================================== */ + + +/* +** {================================================================== +** Prototypes +** =================================================================== +*/ + +#define LUA_VPROTO makevariant(LUA_TPROTO, 0) + + +/* +** Description of an upvalue for function prototypes +*/ +typedef struct Upvaldesc { + TString *name; /* upvalue name (for debug information) */ + lu_byte instack; /* whether it is in stack (register) */ + lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ + lu_byte kind; /* kind of corresponding variable */ +} Upvaldesc; + + +/* +** Description of a local variable for function prototypes +** (used for debug information) +*/ +typedef struct LocVar { + TString *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} LocVar; + + +/* +** Associates the absolute line source for a given instruction ('pc'). +** The array 'lineinfo' gives, for each instruction, the difference in +** lines from the previous instruction. When that difference does not +** fit into a byte, Lua saves the absolute line for that instruction. +** (Lua also saves the absolute line periodically, to speed up the +** computation of a line number: we can use binary search in the +** absolute-line array, but we must traverse the 'lineinfo' array +** linearly to compute a line.) +*/ +typedef struct AbsLineInfo { + int pc; + int line; +} AbsLineInfo; + +/* +** Function Prototypes +*/ +typedef struct Proto { + CommonHeader; + lu_byte numparams; /* number of fixed (named) parameters */ + lu_byte is_vararg; + lu_byte maxstacksize; /* number of registers needed by this function */ + int sizeupvalues; /* size of 'upvalues' */ + int sizek; /* size of 'k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of 'p' */ + int sizelocvars; + int sizeabslineinfo; /* size of 'abslineinfo' */ + int linedefined; /* debug information */ + int lastlinedefined; /* debug information */ + TValue *k; /* constants used by the function */ + Instruction *code; /* opcodes */ + struct Proto **p; /* functions defined inside the function */ + Upvaldesc *upvalues; /* upvalue information */ + ls_byte *lineinfo; /* information about source lines (debug information) */ + AbsLineInfo *abslineinfo; /* idem */ + LocVar *locvars; /* information about local variables (debug information) */ + TString *source; /* used for debug information */ + GCObject *gclist; +} Proto; + +/* }================================================================== */ + + +/* +** {================================================================== +** Functions +** =================================================================== +*/ + +#define LUA_VUPVAL makevariant(LUA_TUPVAL, 0) + + +/* Variant tags for functions */ +#define LUA_VLCL makevariant(LUA_TFUNCTION, 0) /* Lua closure */ +#define LUA_VLCF makevariant(LUA_TFUNCTION, 1) /* light C function */ +#define LUA_VCCL makevariant(LUA_TFUNCTION, 2) /* C closure */ + +#define ttisfunction(o) checktype(o, LUA_TFUNCTION) +#define ttisLclosure(o) checktag((o), ctb(LUA_VLCL)) +#define ttislcf(o) checktag((o), LUA_VLCF) +#define ttisCclosure(o) checktag((o), ctb(LUA_VCCL)) +#define ttisclosure(o) (ttisLclosure(o) || ttisCclosure(o)) + + +#define isLfunction(o) ttisLclosure(o) + +#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc)) +#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc)) +#define fvalue(o) check_exp(ttislcf(o), val_(o).f) +#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc)) + +#define fvalueraw(v) ((v).f) + +#define setclLvalue(L,obj,x) \ + { TValue *io = (obj); LClosure *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VLCL)); \ + checkliveness(L,io); } + +#define setclLvalue2s(L,o,cl) setclLvalue(L,s2v(o),cl) + +#define setfvalue(obj,x) \ + { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_VLCF); } + +#define setclCvalue(L,obj,x) \ + { TValue *io = (obj); CClosure *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VCCL)); \ + checkliveness(L,io); } + + +/* +** Upvalues for Lua closures +*/ +typedef struct UpVal { + CommonHeader; + lu_byte tbc; /* true if it represents a to-be-closed variable */ + TValue *v; /* points to stack or to its own value */ + union { + struct { /* (when open) */ + struct UpVal *next; /* linked list */ + struct UpVal **previous; + } open; + TValue value; /* the value (when closed) */ + } u; +} UpVal; + + + +#define ClosureHeader \ + CommonHeader; lu_byte nupvalues; GCObject *gclist + +typedef struct CClosure { + ClosureHeader; + lua_CFunction f; + TValue upvalue[1]; /* list of upvalues */ +} CClosure; + + +typedef struct LClosure { + ClosureHeader; + struct Proto *p; + UpVal *upvals[1]; /* list of upvalues */ +} LClosure; + + +typedef union Closure { + CClosure c; + LClosure l; +} Closure; + + +#define getproto(o) (clLvalue(o)->p) + +/* }================================================================== */ + + +/* +** {================================================================== +** Tables +** =================================================================== +*/ + +#define LUA_VTABLE makevariant(LUA_TTABLE, 0) + +#define ttistable(o) checktag((o), ctb(LUA_VTABLE)) + +#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc)) + +#define sethvalue(L,obj,x) \ + { TValue *io = (obj); Table *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VTABLE)); \ + checkliveness(L,io); } + +#define sethvalue2s(L,o,h) sethvalue(L,s2v(o),h) + + +/* +** Nodes for Hash tables: A pack of two TValue's (key-value pairs) +** plus a 'next' field to link colliding entries. The distribution +** of the key's fields ('key_tt' and 'key_val') not forming a proper +** 'TValue' allows for a smaller size for 'Node' both in 4-byte +** and 8-byte alignments. +*/ +typedef union Node { + struct NodeKey { + TValuefields; /* fields for value */ + lu_byte key_tt; /* key type */ + int next; /* for chaining */ + Value key_val; /* key value */ + } u; + TValue i_val; /* direct access to node's value as a proper 'TValue' */ +} Node; + + +/* copy a value into a key */ +#define setnodekey(L,node,obj) \ + { Node *n_=(node); const TValue *io_=(obj); \ + n_->u.key_val = io_->value_; n_->u.key_tt = io_->tt_; \ + checkliveness(L,io_); } + + +/* copy a value from a key */ +#define getnodekey(L,obj,node) \ + { TValue *io_=(obj); const Node *n_=(node); \ + io_->value_ = n_->u.key_val; io_->tt_ = n_->u.key_tt; \ + checkliveness(L,io_); } + + +/* +** About 'alimit': if 'isrealasize(t)' is true, then 'alimit' is the +** real size of 'array'. Otherwise, the real size of 'array' is the +** smallest power of two not smaller than 'alimit' (or zero iff 'alimit' +** is zero); 'alimit' is then used as a hint for #t. +*/ + +#define BITRAS (1 << 7) +#define isrealasize(t) (!((t)->flags & BITRAS)) +#define setrealasize(t) ((t)->flags &= cast_byte(~BITRAS)) +#define setnorealasize(t) ((t)->flags |= BITRAS) + + +typedef struct Table { + CommonHeader; + lu_byte flags; /* 1<

u.key_tt) +#define keyval(node) ((node)->u.key_val) + +#define keyisnil(node) (keytt(node) == LUA_TNIL) +#define keyisinteger(node) (keytt(node) == LUA_VNUMINT) +#define keyival(node) (keyval(node).i) +#define keyisshrstr(node) (keytt(node) == ctb(LUA_VSHRSTR)) +#define keystrval(node) (gco2ts(keyval(node).gc)) + +#define setnilkey(node) (keytt(node) = LUA_TNIL) + +#define keyiscollectable(n) (keytt(n) & BIT_ISCOLLECTABLE) + +#define gckey(n) (keyval(n).gc) +#define gckeyN(n) (keyiscollectable(n) ? gckey(n) : NULL) + + +/* +** Dead keys in tables have the tag DEADKEY but keep their original +** gcvalue. This distinguishes them from regular keys but allows them to +** be found when searched in a special way. ('next' needs that to find +** keys removed from a table during a traversal.) +*/ +#define setdeadkey(node) (keytt(node) = LUA_TDEADKEY) +#define keyisdead(node) (keytt(node) == LUA_TDEADKEY) + +/* }================================================================== */ + + + +/* +** 'module' operation for hashing (size is always a power of 2) +*/ +#define lmod(s,size) \ + (check_exp((size&(size-1))==0, (cast_int((s) & ((size)-1))))) + + +#define twoto(x) (1<<(x)) +#define sizenode(t) (twoto((t)->lsizenode)) + + +/* size of buffer for 'luaO_utf8esc' function */ +#define UTF8BUFFSZ 8 + +LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x); +LUAI_FUNC int luaO_ceillog2 (unsigned int x); +LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1, + const TValue *p2, TValue *res); +LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, + const TValue *p2, StkId res); +LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); +LUAI_FUNC int luaO_hexavalue (int c); +LUAI_FUNC void luaO_tostring (lua_State *L, TValue *obj); +LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, + va_list argp); +LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); +LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen); + + +#endif + diff --git a/lua/lopcodes.c b/lua/lopcodes.c new file mode 100644 index 0000000..c67aa22 --- /dev/null +++ b/lua/lopcodes.c @@ -0,0 +1,104 @@ +/* +** $Id: lopcodes.c $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#define lopcodes_c +#define LUA_CORE + +#include "lprefix.h" + + +#include "lopcodes.h" + + +/* ORDER OP */ + +LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { +/* MM OT IT T A mode opcode */ + opmode(0, 0, 0, 0, 1, iABC) /* OP_MOVE */ + ,opmode(0, 0, 0, 0, 1, iAsBx) /* OP_LOADI */ + ,opmode(0, 0, 0, 0, 1, iAsBx) /* OP_LOADF */ + ,opmode(0, 0, 0, 0, 1, iABx) /* OP_LOADK */ + ,opmode(0, 0, 0, 0, 1, iABx) /* OP_LOADKX */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADFALSE */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LFALSESKIP */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADTRUE */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADNIL */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETUPVAL */ + ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETUPVAL */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETTABUP */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETI */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETFIELD */ + ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABUP */ + ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABLE */ + ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETI */ + ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETFIELD */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_NEWTABLE */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SELF */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDI */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDK */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUBK */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MULK */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MODK */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_POWK */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIVK */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIVK */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BANDK */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BORK */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXORK */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHRI */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHLI */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADD */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUB */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MUL */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MOD */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_POW */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIV */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIV */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BAND */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BOR */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXOR */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHL */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHR */ + ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBIN */ + ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINI*/ + ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINK*/ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_UNM */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BNOT */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_NOT */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LEN */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_CONCAT */ + ,opmode(0, 0, 0, 0, 0, iABC) /* OP_CLOSE */ + ,opmode(0, 0, 0, 0, 0, iABC) /* OP_TBC */ + ,opmode(0, 0, 0, 0, 0, isJ) /* OP_JMP */ + ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQ */ + ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LT */ + ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LE */ + ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQK */ + ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQI */ + ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LTI */ + ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LEI */ + ,opmode(0, 0, 0, 1, 0, iABC) /* OP_GTI */ + ,opmode(0, 0, 0, 1, 0, iABC) /* OP_GEI */ + ,opmode(0, 0, 0, 1, 0, iABC) /* OP_TEST */ + ,opmode(0, 0, 0, 1, 1, iABC) /* OP_TESTSET */ + ,opmode(0, 1, 1, 0, 1, iABC) /* OP_CALL */ + ,opmode(0, 1, 1, 0, 1, iABC) /* OP_TAILCALL */ + ,opmode(0, 0, 1, 0, 0, iABC) /* OP_RETURN */ + ,opmode(0, 0, 0, 0, 0, iABC) /* OP_RETURN0 */ + ,opmode(0, 0, 0, 0, 0, iABC) /* OP_RETURN1 */ + ,opmode(0, 0, 0, 0, 1, iABx) /* OP_FORLOOP */ + ,opmode(0, 0, 0, 0, 1, iABx) /* OP_FORPREP */ + ,opmode(0, 0, 0, 0, 0, iABx) /* OP_TFORPREP */ + ,opmode(0, 0, 0, 0, 0, iABC) /* OP_TFORCALL */ + ,opmode(0, 0, 0, 0, 1, iABx) /* OP_TFORLOOP */ + ,opmode(0, 0, 1, 0, 0, iABC) /* OP_SETLIST */ + ,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */ + ,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */ + ,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */ + ,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */ +}; + diff --git a/lua/lopcodes.h b/lua/lopcodes.h new file mode 100644 index 0000000..d6a47e5 --- /dev/null +++ b/lua/lopcodes.h @@ -0,0 +1,392 @@ +/* +** $Id: lopcodes.h $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lopcodes_h +#define lopcodes_h + +#include "llimits.h" + + +/*=========================================================================== + We assume that instructions are unsigned 32-bit integers. + All instructions have an opcode in the first 7 bits. + Instructions can have the following formats: + + 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 + 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +iABC C(8) | B(8) |k| A(8) | Op(7) | +iABx Bx(17) | A(8) | Op(7) | +iAsBx sBx (signed)(17) | A(8) | Op(7) | +iAx Ax(25) | Op(7) | +isJ sJ(25) | Op(7) | + + A signed argument is represented in excess K: the represented value is + the written unsigned value minus K, where K is half the maximum for the + corresponding unsigned argument. +===========================================================================*/ + + +enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */ + + +/* +** size and position of opcode arguments. +*/ +#define SIZE_C 8 +#define SIZE_B 8 +#define SIZE_Bx (SIZE_C + SIZE_B + 1) +#define SIZE_A 8 +#define SIZE_Ax (SIZE_Bx + SIZE_A) +#define SIZE_sJ (SIZE_Bx + SIZE_A) + +#define SIZE_OP 7 + +#define POS_OP 0 + +#define POS_A (POS_OP + SIZE_OP) +#define POS_k (POS_A + SIZE_A) +#define POS_B (POS_k + 1) +#define POS_C (POS_B + SIZE_B) + +#define POS_Bx POS_k + +#define POS_Ax POS_A + +#define POS_sJ POS_A + + +/* +** limits for opcode arguments. +** we use (signed) 'int' to manipulate most arguments, +** so they must fit in ints. +*/ + +/* Check whether type 'int' has at least 'b' bits ('b' < 32) */ +#define L_INTHASBITS(b) ((UINT_MAX >> ((b) - 1)) >= 1) + + +#if L_INTHASBITS(SIZE_Bx) +#define MAXARG_Bx ((1<>1) /* 'sBx' is signed */ + + +#if L_INTHASBITS(SIZE_Ax) +#define MAXARG_Ax ((1<> 1) + + +#define MAXARG_A ((1<> 1) + +#define int2sC(i) ((i) + OFFSET_sC) +#define sC2int(i) ((i) - OFFSET_sC) + + +/* creates a mask with 'n' 1 bits at position 'p' */ +#define MASK1(n,p) ((~((~(Instruction)0)<<(n)))<<(p)) + +/* creates a mask with 'n' 0 bits at position 'p' */ +#define MASK0(n,p) (~MASK1(n,p)) + +/* +** the following macros help to manipulate instructions +*/ + +#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0))) +#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ + ((cast(Instruction, o)<>(pos)) & MASK1(size,0))) +#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ + ((cast(Instruction, v)<> sC */ +OP_SHLI,/* A B sC R[A] := sC << R[B] */ + +OP_ADD,/* A B C R[A] := R[B] + R[C] */ +OP_SUB,/* A B C R[A] := R[B] - R[C] */ +OP_MUL,/* A B C R[A] := R[B] * R[C] */ +OP_MOD,/* A B C R[A] := R[B] % R[C] */ +OP_POW,/* A B C R[A] := R[B] ^ R[C] */ +OP_DIV,/* A B C R[A] := R[B] / R[C] */ +OP_IDIV,/* A B C R[A] := R[B] // R[C] */ + +OP_BAND,/* A B C R[A] := R[B] & R[C] */ +OP_BOR,/* A B C R[A] := R[B] | R[C] */ +OP_BXOR,/* A B C R[A] := R[B] ~ R[C] */ +OP_SHL,/* A B C R[A] := R[B] << R[C] */ +OP_SHR,/* A B C R[A] := R[B] >> R[C] */ + +OP_MMBIN,/* A B C call C metamethod over R[A] and R[B] */ +OP_MMBINI,/* A sB C k call C metamethod over R[A] and sB */ +OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */ + +OP_UNM,/* A B R[A] := -R[B] */ +OP_BNOT,/* A B R[A] := ~R[B] */ +OP_NOT,/* A B R[A] := not R[B] */ +OP_LEN,/* A B R[A] := #R[B] (length operator) */ + +OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */ + +OP_CLOSE,/* A close all upvalues >= R[A] */ +OP_TBC,/* A mark variable A "to be closed" */ +OP_JMP,/* sJ pc += sJ */ +OP_EQ,/* A B k if ((R[A] == R[B]) ~= k) then pc++ */ +OP_LT,/* A B k if ((R[A] < R[B]) ~= k) then pc++ */ +OP_LE,/* A B k if ((R[A] <= R[B]) ~= k) then pc++ */ + +OP_EQK,/* A B k if ((R[A] == K[B]) ~= k) then pc++ */ +OP_EQI,/* A sB k if ((R[A] == sB) ~= k) then pc++ */ +OP_LTI,/* A sB k if ((R[A] < sB) ~= k) then pc++ */ +OP_LEI,/* A sB k if ((R[A] <= sB) ~= k) then pc++ */ +OP_GTI,/* A sB k if ((R[A] > sB) ~= k) then pc++ */ +OP_GEI,/* A sB k if ((R[A] >= sB) ~= k) then pc++ */ + +OP_TEST,/* A k if (not R[A] == k) then pc++ */ +OP_TESTSET,/* A B k if (not R[B] == k) then pc++ else R[A] := R[B] */ + +OP_CALL,/* A B C R[A], ... ,R[A+C-2] := R[A](R[A+1], ... ,R[A+B-1]) */ +OP_TAILCALL,/* A B C k return R[A](R[A+1], ... ,R[A+B-1]) */ + +OP_RETURN,/* A B C k return R[A], ... ,R[A+B-2] (see note) */ +OP_RETURN0,/* return */ +OP_RETURN1,/* A return R[A] */ + +OP_FORLOOP,/* A Bx update counters; if loop continues then pc-=Bx; */ +OP_FORPREP,/* A Bx ; + if not to run then pc+=Bx+1; */ + +OP_TFORPREP,/* A Bx create upvalue for R[A + 3]; pc+=Bx */ +OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */ +OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */ + +OP_SETLIST,/* A B C k R[A][C+i] := R[A+i], 1 <= i <= B */ + +OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */ + +OP_VARARG,/* A C R[A], R[A+1], ..., R[A+C-2] = vararg */ + +OP_VARARGPREP,/*A (adjust vararg parameters) */ + +OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ +} OpCode; + + +#define NUM_OPCODES ((int)(OP_EXTRAARG) + 1) + + + +/*=========================================================================== + Notes: + (*) In OP_CALL, if (B == 0) then B = top - A. If (C == 0), then + 'top' is set to last_result+1, so next open instruction (OP_CALL, + OP_RETURN*, OP_SETLIST) may use 'top'. + + (*) In OP_VARARG, if (C == 0) then use actual number of varargs and + set top (like in OP_CALL with C == 0). + + (*) In OP_RETURN, if (B == 0) then return up to 'top'. + + (*) In OP_LOADKX and OP_NEWTABLE, the next instruction is always + OP_EXTRAARG. + + (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if k, then + real C = EXTRAARG _ C (the bits of EXTRAARG concatenated with the + bits of C). + + (*) In OP_NEWTABLE, B is log2 of the hash size (which is always a + power of 2) plus 1, or zero for size zero. If not k, the array size + is C. Otherwise, the array size is EXTRAARG _ C. + + (*) For comparisons, k specifies what condition the test should accept + (true or false). + + (*) In OP_MMBINI/OP_MMBINK, k means the arguments were flipped + (the constant is the first operand). + + (*) All 'skips' (pc++) assume that next instruction is a jump. + + (*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the + function builds upvalues, which may need to be closed. C > 0 means + the function is vararg, so that its 'func' must be corrected before + returning; in this case, (C - 1) is its number of fixed parameters. + + (*) In comparisons with an immediate operand, C signals whether the + original operand was a float. (It must be corrected in case of + metamethods.) + +===========================================================================*/ + + +/* +** masks for instruction properties. The format is: +** bits 0-2: op mode +** bit 3: instruction set register A +** bit 4: operator is a test (next instruction must be a jump) +** bit 5: instruction uses 'L->top' set by previous instruction (when B == 0) +** bit 6: instruction sets 'L->top' for next instruction (when C == 0) +** bit 7: instruction is an MM instruction (call a metamethod) +*/ + +LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];) + +#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 7)) +#define testAMode(m) (luaP_opmodes[m] & (1 << 3)) +#define testTMode(m) (luaP_opmodes[m] & (1 << 4)) +#define testITMode(m) (luaP_opmodes[m] & (1 << 5)) +#define testOTMode(m) (luaP_opmodes[m] & (1 << 6)) +#define testMMMode(m) (luaP_opmodes[m] & (1 << 7)) + +/* "out top" (set top for next instruction) */ +#define isOT(i) \ + ((testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0) || \ + GET_OPCODE(i) == OP_TAILCALL) + +/* "in top" (uses top from previous instruction) */ +#define isIT(i) (testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0) + +#define opmode(mm,ot,it,t,a,m) \ + (((mm) << 7) | ((ot) << 6) | ((it) << 5) | ((t) << 4) | ((a) << 3) | (m)) + + +/* number of list items to accumulate before a SETLIST instruction */ +#define LFIELDS_PER_FLUSH 50 + +#endif diff --git a/lua/lopnames.h b/lua/lopnames.h new file mode 100644 index 0000000..965cec9 --- /dev/null +++ b/lua/lopnames.h @@ -0,0 +1,103 @@ +/* +** $Id: lopnames.h $ +** Opcode names +** See Copyright Notice in lua.h +*/ + +#if !defined(lopnames_h) +#define lopnames_h + +#include + + +/* ORDER OP */ + +static const char *const opnames[] = { + "MOVE", + "LOADI", + "LOADF", + "LOADK", + "LOADKX", + "LOADFALSE", + "LFALSESKIP", + "LOADTRUE", + "LOADNIL", + "GETUPVAL", + "SETUPVAL", + "GETTABUP", + "GETTABLE", + "GETI", + "GETFIELD", + "SETTABUP", + "SETTABLE", + "SETI", + "SETFIELD", + "NEWTABLE", + "SELF", + "ADDI", + "ADDK", + "SUBK", + "MULK", + "MODK", + "POWK", + "DIVK", + "IDIVK", + "BANDK", + "BORK", + "BXORK", + "SHRI", + "SHLI", + "ADD", + "SUB", + "MUL", + "MOD", + "POW", + "DIV", + "IDIV", + "BAND", + "BOR", + "BXOR", + "SHL", + "SHR", + "MMBIN", + "MMBINI", + "MMBINK", + "UNM", + "BNOT", + "NOT", + "LEN", + "CONCAT", + "CLOSE", + "TBC", + "JMP", + "EQ", + "LT", + "LE", + "EQK", + "EQI", + "LTI", + "LEI", + "GTI", + "GEI", + "TEST", + "TESTSET", + "CALL", + "TAILCALL", + "RETURN", + "RETURN0", + "RETURN1", + "FORLOOP", + "FORPREP", + "TFORPREP", + "TFORCALL", + "TFORLOOP", + "SETLIST", + "CLOSURE", + "VARARG", + "VARARGPREP", + "EXTRAARG", + NULL +}; + +#endif + diff --git a/lua/loslib.c b/lua/loslib.c new file mode 100644 index 0000000..3e20d62 --- /dev/null +++ b/lua/loslib.c @@ -0,0 +1,430 @@ +/* +** $Id: loslib.c $ +** Standard Operating System library +** See Copyright Notice in lua.h +*/ + +#define loslib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** {================================================================== +** List of valid conversion specifiers for the 'strftime' function; +** options are grouped by length; group of length 2 start with '||'. +** =================================================================== +*/ +#if !defined(LUA_STRFTIMEOPTIONS) /* { */ + +/* options for ANSI C 89 (only 1-char options) */ +#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%" + +/* options for ISO C 99 and POSIX */ +#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ + "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ + +/* options for Windows */ +#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \ + "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ + +#if defined(LUA_USE_WINDOWS) +#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN +#elif defined(LUA_USE_C89) +#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89 +#else /* C99 specification */ +#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99 +#endif + +#endif /* } */ +/* }================================================================== */ + + +/* +** {================================================================== +** Configuration for time-related stuff +** =================================================================== +*/ + +/* +** type to represent time_t in Lua +*/ +#if !defined(LUA_NUMTIME) /* { */ + +#define l_timet lua_Integer +#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) +#define l_gettime(L,arg) luaL_checkinteger(L, arg) + +#else /* }{ */ + +#define l_timet lua_Number +#define l_pushtime(L,t) lua_pushnumber(L,(lua_Number)(t)) +#define l_gettime(L,arg) luaL_checknumber(L, arg) + +#endif /* } */ + + +#if !defined(l_gmtime) /* { */ +/* +** By default, Lua uses gmtime/localtime, except when POSIX is available, +** where it uses gmtime_r/localtime_r +*/ + +#if defined(LUA_USE_POSIX) /* { */ + +#define l_gmtime(t,r) gmtime_r(t,r) +#define l_localtime(t,r) localtime_r(t,r) + +#else /* }{ */ + +/* ISO C definitions */ +#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t)) +#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t)) + +#endif /* } */ + +#endif /* } */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Configuration for 'tmpnam': +** By default, Lua uses tmpnam except when POSIX is available, where +** it uses mkstemp. +** =================================================================== +*/ +#if !defined(lua_tmpnam) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#include + +#define LUA_TMPNAMBUFSIZE 32 + +#if !defined(LUA_TMPNAMTEMPLATE) +#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX" +#endif + +#define lua_tmpnam(b,e) { \ + strcpy(b, LUA_TMPNAMTEMPLATE); \ + e = mkstemp(b); \ + if (e != -1) close(e); \ + e = (e == -1); } + +#else /* }{ */ + +/* ISO C definitions */ +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } + +#endif /* } */ + +#endif /* } */ +/* }================================================================== */ + + + +static int os_execute (lua_State *L) { + const char *cmd = luaL_optstring(L, 1, NULL); + int stat; + errno = 0; + stat = system(cmd); + if (cmd != NULL) + return luaL_execresult(L, stat); + else { + lua_pushboolean(L, stat); /* true if there is a shell */ + return 1; + } +} + + +static int os_remove (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + return luaL_fileresult(L, remove(filename) == 0, filename); +} + + +static int os_rename (lua_State *L) { + const char *fromname = luaL_checkstring(L, 1); + const char *toname = luaL_checkstring(L, 2); + return luaL_fileresult(L, rename(fromname, toname) == 0, NULL); +} + + +static int os_tmpname (lua_State *L) { + char buff[LUA_TMPNAMBUFSIZE]; + int err; + lua_tmpnam(buff, err); + if (l_unlikely(err)) + return luaL_error(L, "unable to generate a unique filename"); + lua_pushstring(L, buff); + return 1; +} + + +static int os_getenv (lua_State *L) { + lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ + return 1; +} + + +static int os_clock (lua_State *L) { + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + return 1; +} + + +/* +** {====================================================== +** Time/Date operations +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, +** wday=%w+1, yday=%j, isdst=? } +** ======================================================= +*/ + +/* +** About the overflow check: an overflow cannot occur when time +** is represented by a lua_Integer, because either lua_Integer is +** large enough to represent all int fields or it is not large enough +** to represent a time that cause a field to overflow. However, if +** times are represented as doubles and lua_Integer is int, then the +** time 0x1.e1853b0d184f6p+55 would cause an overflow when adding 1900 +** to compute the year. +*/ +static void setfield (lua_State *L, const char *key, int value, int delta) { + #if (defined(LUA_NUMTIME) && LUA_MAXINTEGER <= INT_MAX) + if (l_unlikely(value > LUA_MAXINTEGER - delta)) + luaL_error(L, "field '%s' is out-of-bound", key); + #endif + lua_pushinteger(L, (lua_Integer)value + delta); + lua_setfield(L, -2, key); +} + + +static void setboolfield (lua_State *L, const char *key, int value) { + if (value < 0) /* undefined? */ + return; /* does not set field */ + lua_pushboolean(L, value); + lua_setfield(L, -2, key); +} + + +/* +** Set all fields from structure 'tm' in the table on top of the stack +*/ +static void setallfields (lua_State *L, struct tm *stm) { + setfield(L, "year", stm->tm_year, 1900); + setfield(L, "month", stm->tm_mon, 1); + setfield(L, "day", stm->tm_mday, 0); + setfield(L, "hour", stm->tm_hour, 0); + setfield(L, "min", stm->tm_min, 0); + setfield(L, "sec", stm->tm_sec, 0); + setfield(L, "yday", stm->tm_yday, 1); + setfield(L, "wday", stm->tm_wday, 1); + setboolfield(L, "isdst", stm->tm_isdst); +} + + +static int getboolfield (lua_State *L, const char *key) { + int res; + res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); + lua_pop(L, 1); + return res; +} + + +static int getfield (lua_State *L, const char *key, int d, int delta) { + int isnum; + int t = lua_getfield(L, -1, key); /* get field and its type */ + lua_Integer res = lua_tointegerx(L, -1, &isnum); + if (!isnum) { /* field is not an integer? */ + if (l_unlikely(t != LUA_TNIL)) /* some other value? */ + return luaL_error(L, "field '%s' is not an integer", key); + else if (l_unlikely(d < 0)) /* absent field; no default? */ + return luaL_error(L, "field '%s' missing in date table", key); + res = d; + } + else { + /* unsigned avoids overflow when lua_Integer has 32 bits */ + if (!(res >= 0 ? (lua_Unsigned)res <= (lua_Unsigned)INT_MAX + delta + : (lua_Integer)INT_MIN + delta <= res)) + return luaL_error(L, "field '%s' is out-of-bound", key); + res -= delta; + } + lua_pop(L, 1); + return (int)res; +} + + +static const char *checkoption (lua_State *L, const char *conv, + ptrdiff_t convlen, char *buff) { + const char *option = LUA_STRFTIMEOPTIONS; + int oplen = 1; /* length of options being checked */ + for (; *option != '\0' && oplen <= convlen; option += oplen) { + if (*option == '|') /* next block? */ + oplen++; /* will check options with next length (+1) */ + else if (memcmp(conv, option, oplen) == 0) { /* match? */ + memcpy(buff, conv, oplen); /* copy valid option to buffer */ + buff[oplen] = '\0'; + return conv + oplen; /* return next item */ + } + } + luaL_argerror(L, 1, + lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); + return conv; /* to avoid warnings */ +} + + +static time_t l_checktime (lua_State *L, int arg) { + l_timet t = l_gettime(L, arg); + luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds"); + return (time_t)t; +} + + +/* maximum size for an individual 'strftime' item */ +#define SIZETIMEFMT 250 + + +static int os_date (lua_State *L) { + size_t slen; + const char *s = luaL_optlstring(L, 1, "%c", &slen); + time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); + const char *se = s + slen; /* 's' end */ + struct tm tmr, *stm; + if (*s == '!') { /* UTC? */ + stm = l_gmtime(&t, &tmr); + s++; /* skip '!' */ + } + else + stm = l_localtime(&t, &tmr); + if (stm == NULL) /* invalid date? */ + return luaL_error(L, + "date result cannot be represented in this installation"); + if (strcmp(s, "*t") == 0) { + lua_createtable(L, 0, 9); /* 9 = number of fields */ + setallfields(L, stm); + } + else { + char cc[4]; /* buffer for individual conversion specifiers */ + luaL_Buffer b; + cc[0] = '%'; + luaL_buffinit(L, &b); + while (s < se) { + if (*s != '%') /* not a conversion specifier? */ + luaL_addchar(&b, *s++); + else { + size_t reslen; + char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); + s++; /* skip '%' */ + s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */ + reslen = strftime(buff, SIZETIMEFMT, cc, stm); + luaL_addsize(&b, reslen); + } + } + luaL_pushresult(&b); + } + return 1; +} + + +static int os_time (lua_State *L) { + time_t t; + if (lua_isnoneornil(L, 1)) /* called without args? */ + t = time(NULL); /* get current time */ + else { + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_year = getfield(L, "year", -1, 1900); + ts.tm_mon = getfield(L, "month", -1, 1); + ts.tm_mday = getfield(L, "day", -1, 0); + ts.tm_hour = getfield(L, "hour", 12, 0); + ts.tm_min = getfield(L, "min", 0, 0); + ts.tm_sec = getfield(L, "sec", 0, 0); + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + setallfields(L, &ts); /* update fields with normalized values */ + } + if (t != (time_t)(l_timet)t || t == (time_t)(-1)) + return luaL_error(L, + "time result cannot be represented in this installation"); + l_pushtime(L, t); + return 1; +} + + +static int os_difftime (lua_State *L) { + time_t t1 = l_checktime(L, 1); + time_t t2 = l_checktime(L, 2); + lua_pushnumber(L, (lua_Number)difftime(t1, t2)); + return 1; +} + +/* }====================================================== */ + + +static int os_setlocale (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + const char *l = luaL_optstring(L, 1, NULL); + int op = luaL_checkoption(L, 2, "all", catnames); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; +} + + +static int os_exit (lua_State *L) { + int status; + if (lua_isboolean(L, 1)) + status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); + else + status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS); + if (lua_toboolean(L, 2)) + lua_close(L); + if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ + return 0; +} + + +static const luaL_Reg syslib[] = { + {"clock", os_clock}, + {"date", os_date}, + {"difftime", os_difftime}, + {"execute", os_execute}, + {"exit", os_exit}, + {"getenv", os_getenv}, + {"remove", os_remove}, + {"rename", os_rename}, + {"setlocale", os_setlocale}, + {"time", os_time}, + {"tmpname", os_tmpname}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +LUAMOD_API int luaopen_os (lua_State *L) { + luaL_newlib(L, syslib); + return 1; +} + diff --git a/lua/lparser.c b/lua/lparser.c new file mode 100644 index 0000000..284ef1f --- /dev/null +++ b/lua/lparser.c @@ -0,0 +1,1956 @@ +/* +** $Id: lparser.c $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + +#define lparser_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" + + + +/* maximum number of local variables per function (must be smaller + than 250, due to the bytecode format) */ +#define MAXVARS 200 + + +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) + + +/* because all strings are unified by the scanner, the parser + can use pointer equality for string equality */ +#define eqstr(a,b) ((a) == (b)) + + +/* +** nodes for block list (list of active blocks) +*/ +typedef struct BlockCnt { + struct BlockCnt *previous; /* chain */ + int firstlabel; /* index of first label in this block */ + int firstgoto; /* index of first pending goto in this block */ + lu_byte nactvar; /* # active locals outside the block */ + lu_byte upval; /* true if some variable in the block is an upvalue */ + lu_byte isloop; /* true if 'block' is a loop */ + lu_byte insidetbc; /* true if inside the scope of a to-be-closed var. */ +} BlockCnt; + + + +/* +** prototypes for recursive non-terminal functions +*/ +static void statement (LexState *ls); +static void expr (LexState *ls, expdesc *v); + + +static l_noret error_expected (LexState *ls, int token) { + luaX_syntaxerror(ls, + luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); +} + + +static l_noret errorlimit (FuncState *fs, int limit, const char *what) { + lua_State *L = fs->ls->L; + const char *msg; + int line = fs->f->linedefined; + const char *where = (line == 0) + ? "main function" + : luaO_pushfstring(L, "function at line %d", line); + msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", + what, limit, where); + luaX_syntaxerror(fs->ls, msg); +} + + +static void checklimit (FuncState *fs, int v, int l, const char *what) { + if (v > l) errorlimit(fs, l, what); +} + + +/* +** Test whether next token is 'c'; if so, skip it. +*/ +static int testnext (LexState *ls, int c) { + if (ls->t.token == c) { + luaX_next(ls); + return 1; + } + else return 0; +} + + +/* +** Check that next token is 'c'. +*/ +static void check (LexState *ls, int c) { + if (ls->t.token != c) + error_expected(ls, c); +} + + +/* +** Check that next token is 'c' and skip it. +*/ +static void checknext (LexState *ls, int c) { + check(ls, c); + luaX_next(ls); +} + + +#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } + + +/* +** Check that next token is 'what' and skip it. In case of error, +** raise an error that the expected 'what' should match a 'who' +** in line 'where' (if that is not the current line). +*/ +static void check_match (LexState *ls, int what, int who, int where) { + if (l_unlikely(!testnext(ls, what))) { + if (where == ls->linenumber) /* all in the same line? */ + error_expected(ls, what); /* do not need a complex message */ + else { + luaX_syntaxerror(ls, luaO_pushfstring(ls->L, + "%s expected (to close %s at line %d)", + luaX_token2str(ls, what), luaX_token2str(ls, who), where)); + } + } +} + + +static TString *str_checkname (LexState *ls) { + TString *ts; + check(ls, TK_NAME); + ts = ls->t.seminfo.ts; + luaX_next(ls); + return ts; +} + + +static void init_exp (expdesc *e, expkind k, int i) { + e->f = e->t = NO_JUMP; + e->k = k; + e->u.info = i; +} + + +static void codestring (expdesc *e, TString *s) { + e->f = e->t = NO_JUMP; + e->k = VKSTR; + e->u.strval = s; +} + + +static void codename (LexState *ls, expdesc *e) { + codestring(e, str_checkname(ls)); +} + + +/* +** Register a new local variable in the active 'Proto' (for debug +** information). +*/ +static int registerlocalvar (LexState *ls, FuncState *fs, TString *varname) { + Proto *f = fs->f; + int oldsize = f->sizelocvars; + luaM_growvector(ls->L, f->locvars, fs->ndebugvars, f->sizelocvars, + LocVar, SHRT_MAX, "local variables"); + while (oldsize < f->sizelocvars) + f->locvars[oldsize++].varname = NULL; + f->locvars[fs->ndebugvars].varname = varname; + f->locvars[fs->ndebugvars].startpc = fs->pc; + luaC_objbarrier(ls->L, f, varname); + return fs->ndebugvars++; +} + + +/* +** Create a new local variable with the given 'name'. Return its index +** in the function. +*/ +static int new_localvar (LexState *ls, TString *name) { + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Dyndata *dyd = ls->dyd; + Vardesc *var; + checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, + MAXVARS, "local variables"); + luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, + dyd->actvar.size, Vardesc, USHRT_MAX, "local variables"); + var = &dyd->actvar.arr[dyd->actvar.n++]; + var->vd.kind = VDKREG; /* default */ + var->vd.name = name; + return dyd->actvar.n - 1 - fs->firstlocal; +} + +#define new_localvarliteral(ls,v) \ + new_localvar(ls, \ + luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1)); + + + +/* +** Return the "variable description" (Vardesc) of a given variable. +** (Unless noted otherwise, all variables are referred to by their +** compiler indices.) +*/ +static Vardesc *getlocalvardesc (FuncState *fs, int vidx) { + return &fs->ls->dyd->actvar.arr[fs->firstlocal + vidx]; +} + + +/* +** Convert 'nvar', a compiler index level, to its corresponding +** register. For that, search for the highest variable below that level +** that is in a register and uses its register index ('ridx') plus one. +*/ +static int reglevel (FuncState *fs, int nvar) { + while (nvar-- > 0) { + Vardesc *vd = getlocalvardesc(fs, nvar); /* get previous variable */ + if (vd->vd.kind != RDKCTC) /* is in a register? */ + return vd->vd.ridx + 1; + } + return 0; /* no variables in registers */ +} + + +/* +** Return the number of variables in the register stack for the given +** function. +*/ +int luaY_nvarstack (FuncState *fs) { + return reglevel(fs, fs->nactvar); +} + + +/* +** Get the debug-information entry for current variable 'vidx'. +*/ +static LocVar *localdebuginfo (FuncState *fs, int vidx) { + Vardesc *vd = getlocalvardesc(fs, vidx); + if (vd->vd.kind == RDKCTC) + return NULL; /* no debug info. for constants */ + else { + int idx = vd->vd.pidx; + lua_assert(idx < fs->ndebugvars); + return &fs->f->locvars[idx]; + } +} + + +/* +** Create an expression representing variable 'vidx' +*/ +static void init_var (FuncState *fs, expdesc *e, int vidx) { + e->f = e->t = NO_JUMP; + e->k = VLOCAL; + e->u.var.vidx = vidx; + e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx; +} + + +/* +** Raises an error if variable described by 'e' is read only +*/ +static void check_readonly (LexState *ls, expdesc *e) { + FuncState *fs = ls->fs; + TString *varname = NULL; /* to be set if variable is const */ + switch (e->k) { + case VCONST: { + varname = ls->dyd->actvar.arr[e->u.info].vd.name; + break; + } + case VLOCAL: { + Vardesc *vardesc = getlocalvardesc(fs, e->u.var.vidx); + if (vardesc->vd.kind != VDKREG) /* not a regular variable? */ + varname = vardesc->vd.name; + break; + } + case VUPVAL: { + Upvaldesc *up = &fs->f->upvalues[e->u.info]; + if (up->kind != VDKREG) + varname = up->name; + break; + } + default: + return; /* other cases cannot be read-only */ + } + if (varname) { + const char *msg = luaO_pushfstring(ls->L, + "attempt to assign to const variable '%s'", getstr(varname)); + luaK_semerror(ls, msg); /* error */ + } +} + + +/* +** Start the scope for the last 'nvars' created variables. +*/ +static void adjustlocalvars (LexState *ls, int nvars) { + FuncState *fs = ls->fs; + int reglevel = luaY_nvarstack(fs); + int i; + for (i = 0; i < nvars; i++) { + int vidx = fs->nactvar++; + Vardesc *var = getlocalvardesc(fs, vidx); + var->vd.ridx = reglevel++; + var->vd.pidx = registerlocalvar(ls, fs, var->vd.name); + } +} + + +/* +** Close the scope for all variables up to level 'tolevel'. +** (debug info.) +*/ +static void removevars (FuncState *fs, int tolevel) { + fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); + while (fs->nactvar > tolevel) { + LocVar *var = localdebuginfo(fs, --fs->nactvar); + if (var) /* does it have debug information? */ + var->endpc = fs->pc; + } +} + + +/* +** Search the upvalues of the function 'fs' for one +** with the given 'name'. +*/ +static int searchupvalue (FuncState *fs, TString *name) { + int i; + Upvaldesc *up = fs->f->upvalues; + for (i = 0; i < fs->nups; i++) { + if (eqstr(up[i].name, name)) return i; + } + return -1; /* not found */ +} + + +static Upvaldesc *allocupvalue (FuncState *fs) { + Proto *f = fs->f; + int oldsize = f->sizeupvalues; + checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); + luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, + Upvaldesc, MAXUPVAL, "upvalues"); + while (oldsize < f->sizeupvalues) + f->upvalues[oldsize++].name = NULL; + return &f->upvalues[fs->nups++]; +} + + +static int newupvalue (FuncState *fs, TString *name, expdesc *v) { + Upvaldesc *up = allocupvalue(fs); + FuncState *prev = fs->prev; + if (v->k == VLOCAL) { + up->instack = 1; + up->idx = v->u.var.ridx; + up->kind = getlocalvardesc(prev, v->u.var.vidx)->vd.kind; + lua_assert(eqstr(name, getlocalvardesc(prev, v->u.var.vidx)->vd.name)); + } + else { + up->instack = 0; + up->idx = cast_byte(v->u.info); + up->kind = prev->f->upvalues[v->u.info].kind; + lua_assert(eqstr(name, prev->f->upvalues[v->u.info].name)); + } + up->name = name; + luaC_objbarrier(fs->ls->L, fs->f, name); + return fs->nups - 1; +} + + +/* +** Look for an active local variable with the name 'n' in the +** function 'fs'. If found, initialize 'var' with it and return +** its expression kind; otherwise return -1. +*/ +static int searchvar (FuncState *fs, TString *n, expdesc *var) { + int i; + for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { + Vardesc *vd = getlocalvardesc(fs, i); + if (eqstr(n, vd->vd.name)) { /* found? */ + if (vd->vd.kind == RDKCTC) /* compile-time constant? */ + init_exp(var, VCONST, fs->firstlocal + i); + else /* real variable */ + init_var(fs, var, i); + return var->k; + } + } + return -1; /* not found */ +} + + +/* +** Mark block where variable at given level was defined +** (to emit close instructions later). +*/ +static void markupval (FuncState *fs, int level) { + BlockCnt *bl = fs->bl; + while (bl->nactvar > level) + bl = bl->previous; + bl->upval = 1; + fs->needclose = 1; +} + + +/* +** Find a variable with the given name 'n'. If it is an upvalue, add +** this upvalue into all intermediate functions. If it is a global, set +** 'var' as 'void' as a flag. +*/ +static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { + if (fs == NULL) /* no more levels? */ + init_exp(var, VVOID, 0); /* default is global */ + else { + int v = searchvar(fs, n, var); /* look up locals at current level */ + if (v >= 0) { /* found? */ + if (v == VLOCAL && !base) + markupval(fs, var->u.var.vidx); /* local will be used as an upval */ + } + else { /* not found as local at current level; try upvalues */ + int idx = searchupvalue(fs, n); /* try existing upvalues */ + if (idx < 0) { /* not found? */ + singlevaraux(fs->prev, n, var, 0); /* try upper levels */ + if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */ + idx = newupvalue(fs, n, var); /* will be a new upvalue */ + else /* it is a global or a constant */ + return; /* don't need to do anything at this level */ + } + init_exp(var, VUPVAL, idx); /* new or old upvalue */ + } + } +} + + +/* +** Find a variable with the given name 'n', handling global variables +** too. +*/ +static void singlevar (LexState *ls, expdesc *var) { + TString *varname = str_checkname(ls); + FuncState *fs = ls->fs; + singlevaraux(fs, varname, var, 1); + if (var->k == VVOID) { /* global name? */ + expdesc key; + singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ + lua_assert(var->k != VVOID); /* this one must exist */ + codestring(&key, varname); /* key is variable name */ + luaK_indexed(fs, var, &key); /* env[varname] */ + } +} + + +/* +** Adjust the number of results from an expression list 'e' with 'nexps' +** expressions to 'nvars' values. +*/ +static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { + FuncState *fs = ls->fs; + int needed = nvars - nexps; /* extra values needed */ + if (hasmultret(e->k)) { /* last expression has multiple returns? */ + int extra = needed + 1; /* discount last expression itself */ + if (extra < 0) + extra = 0; + luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ + } + else { + if (e->k != VVOID) /* at least one expression? */ + luaK_exp2nextreg(fs, e); /* close last expression */ + if (needed > 0) /* missing values? */ + luaK_nil(fs, fs->freereg, needed); /* complete with nils */ + } + if (needed > 0) + luaK_reserveregs(fs, needed); /* registers for extra values */ + else /* adding 'needed' is actually a subtraction */ + fs->freereg += needed; /* remove extra values */ +} + + +#define enterlevel(ls) luaE_incCstack(ls->L) + + +#define leavelevel(ls) ((ls)->L->nCcalls--) + + +/* +** Generates an error that a goto jumps into the scope of some +** local variable. +*/ +static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { + const char *varname = getstr(getlocalvardesc(ls->fs, gt->nactvar)->vd.name); + const char *msg = " at line %d jumps into the scope of local '%s'"; + msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname); + luaK_semerror(ls, msg); /* raise the error */ +} + + +/* +** Solves the goto at index 'g' to given 'label' and removes it +** from the list of pending goto's. +** If it jumps into the scope of some variable, raises an error. +*/ +static void solvegoto (LexState *ls, int g, Labeldesc *label) { + int i; + Labellist *gl = &ls->dyd->gt; /* list of goto's */ + Labeldesc *gt = &gl->arr[g]; /* goto to be resolved */ + lua_assert(eqstr(gt->name, label->name)); + if (l_unlikely(gt->nactvar < label->nactvar)) /* enter some scope? */ + jumpscopeerror(ls, gt); + luaK_patchlist(ls->fs, gt->pc, label->pc); + for (i = g; i < gl->n - 1; i++) /* remove goto from pending list */ + gl->arr[i] = gl->arr[i + 1]; + gl->n--; +} + + +/* +** Search for an active label with the given name. +*/ +static Labeldesc *findlabel (LexState *ls, TString *name) { + int i; + Dyndata *dyd = ls->dyd; + /* check labels in current function for a match */ + for (i = ls->fs->firstlabel; i < dyd->label.n; i++) { + Labeldesc *lb = &dyd->label.arr[i]; + if (eqstr(lb->name, name)) /* correct label? */ + return lb; + } + return NULL; /* label not found */ +} + + +/* +** Adds a new label/goto in the corresponding list. +*/ +static int newlabelentry (LexState *ls, Labellist *l, TString *name, + int line, int pc) { + int n = l->n; + luaM_growvector(ls->L, l->arr, n, l->size, + Labeldesc, SHRT_MAX, "labels/gotos"); + l->arr[n].name = name; + l->arr[n].line = line; + l->arr[n].nactvar = ls->fs->nactvar; + l->arr[n].close = 0; + l->arr[n].pc = pc; + l->n = n + 1; + return n; +} + + +static int newgotoentry (LexState *ls, TString *name, int line, int pc) { + return newlabelentry(ls, &ls->dyd->gt, name, line, pc); +} + + +/* +** Solves forward jumps. Check whether new label 'lb' matches any +** pending gotos in current block and solves them. Return true +** if any of the goto's need to close upvalues. +*/ +static int solvegotos (LexState *ls, Labeldesc *lb) { + Labellist *gl = &ls->dyd->gt; + int i = ls->fs->bl->firstgoto; + int needsclose = 0; + while (i < gl->n) { + if (eqstr(gl->arr[i].name, lb->name)) { + needsclose |= gl->arr[i].close; + solvegoto(ls, i, lb); /* will remove 'i' from the list */ + } + else + i++; + } + return needsclose; +} + + +/* +** Create a new label with the given 'name' at the given 'line'. +** 'last' tells whether label is the last non-op statement in its +** block. Solves all pending goto's to this new label and adds +** a close instruction if necessary. +** Returns true iff it added a close instruction. +*/ +static int createlabel (LexState *ls, TString *name, int line, + int last) { + FuncState *fs = ls->fs; + Labellist *ll = &ls->dyd->label; + int l = newlabelentry(ls, ll, name, line, luaK_getlabel(fs)); + if (last) { /* label is last no-op statement in the block? */ + /* assume that locals are already out of scope */ + ll->arr[l].nactvar = fs->bl->nactvar; + } + if (solvegotos(ls, &ll->arr[l])) { /* need close? */ + luaK_codeABC(fs, OP_CLOSE, luaY_nvarstack(fs), 0, 0); + return 1; + } + return 0; +} + + +/* +** Adjust pending gotos to outer level of a block. +*/ +static void movegotosout (FuncState *fs, BlockCnt *bl) { + int i; + Labellist *gl = &fs->ls->dyd->gt; + /* correct pending gotos to current block */ + for (i = bl->firstgoto; i < gl->n; i++) { /* for each pending goto */ + Labeldesc *gt = &gl->arr[i]; + /* leaving a variable scope? */ + if (reglevel(fs, gt->nactvar) > reglevel(fs, bl->nactvar)) + gt->close |= bl->upval; /* jump may need a close */ + gt->nactvar = bl->nactvar; /* update goto level */ + } +} + + +static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { + bl->isloop = isloop; + bl->nactvar = fs->nactvar; + bl->firstlabel = fs->ls->dyd->label.n; + bl->firstgoto = fs->ls->dyd->gt.n; + bl->upval = 0; + bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); + bl->previous = fs->bl; + fs->bl = bl; + lua_assert(fs->freereg == luaY_nvarstack(fs)); +} + + +/* +** generates an error for an undefined 'goto'. +*/ +static l_noret undefgoto (LexState *ls, Labeldesc *gt) { + const char *msg; + if (eqstr(gt->name, luaS_newliteral(ls->L, "break"))) { + msg = "break outside loop at line %d"; + msg = luaO_pushfstring(ls->L, msg, gt->line); + } + else { + msg = "no visible label '%s' for at line %d"; + msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); + } + luaK_semerror(ls, msg); +} + + +static void leaveblock (FuncState *fs) { + BlockCnt *bl = fs->bl; + LexState *ls = fs->ls; + int hasclose = 0; + int stklevel = reglevel(fs, bl->nactvar); /* level outside the block */ + if (bl->isloop) /* fix pending breaks? */ + hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); + if (!hasclose && bl->previous && bl->upval) + luaK_codeABC(fs, OP_CLOSE, stklevel, 0, 0); + fs->bl = bl->previous; + removevars(fs, bl->nactvar); + lua_assert(bl->nactvar == fs->nactvar); + fs->freereg = stklevel; /* free registers */ + ls->dyd->label.n = bl->firstlabel; /* remove local labels */ + if (bl->previous) /* inner block? */ + movegotosout(fs, bl); /* update pending gotos to outer block */ + else { + if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ + undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ + } +} + + +/* +** adds a new prototype into list of prototypes +*/ +static Proto *addprototype (LexState *ls) { + Proto *clp; + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; /* prototype of current function */ + if (fs->np >= f->sizep) { + int oldsize = f->sizep; + luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); + while (oldsize < f->sizep) + f->p[oldsize++] = NULL; + } + f->p[fs->np++] = clp = luaF_newproto(L); + luaC_objbarrier(L, f, clp); + return clp; +} + + +/* +** codes instruction to create new closure in parent function. +** The OP_CLOSURE instruction uses the last available register, +** so that, if it invokes the GC, the GC knows which registers +** are in use at that time. + +*/ +static void codeclosure (LexState *ls, expdesc *v) { + FuncState *fs = ls->fs->prev; + init_exp(v, VRELOC, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); + luaK_exp2nextreg(fs, v); /* fix it at the last register */ +} + + +static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { + Proto *f = fs->f; + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + ls->fs = fs; + fs->pc = 0; + fs->previousline = f->linedefined; + fs->iwthabs = 0; + fs->lasttarget = 0; + fs->freereg = 0; + fs->nk = 0; + fs->nabslineinfo = 0; + fs->np = 0; + fs->nups = 0; + fs->ndebugvars = 0; + fs->nactvar = 0; + fs->needclose = 0; + fs->firstlocal = ls->dyd->actvar.n; + fs->firstlabel = ls->dyd->label.n; + fs->bl = NULL; + f->source = ls->source; + luaC_objbarrier(ls->L, f, f->source); + f->maxstacksize = 2; /* registers 0/1 are always valid */ + enterblock(fs, bl, 0); +} + + +static void close_func (LexState *ls) { + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; + luaK_ret(fs, luaY_nvarstack(fs), 0); /* final return */ + leaveblock(fs); + lua_assert(fs->bl == NULL); + luaK_finish(fs); + luaM_shrinkvector(L, f->code, f->sizecode, fs->pc, Instruction); + luaM_shrinkvector(L, f->lineinfo, f->sizelineinfo, fs->pc, ls_byte); + luaM_shrinkvector(L, f->abslineinfo, f->sizeabslineinfo, + fs->nabslineinfo, AbsLineInfo); + luaM_shrinkvector(L, f->k, f->sizek, fs->nk, TValue); + luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *); + luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar); + luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); + ls->fs = fs->prev; + luaC_checkGC(L); +} + + + +/*============================================================*/ +/* GRAMMAR RULES */ +/*============================================================*/ + + +/* +** check whether current token is in the follow set of a block. +** 'until' closes syntactical blocks, but do not close scope, +** so it is handled in separate. +*/ +static int block_follow (LexState *ls, int withuntil) { + switch (ls->t.token) { + case TK_ELSE: case TK_ELSEIF: + case TK_END: case TK_EOS: + return 1; + case TK_UNTIL: return withuntil; + default: return 0; + } +} + + +static void statlist (LexState *ls) { + /* statlist -> { stat [';'] } */ + while (!block_follow(ls, 1)) { + if (ls->t.token == TK_RETURN) { + statement(ls); + return; /* 'return' must be last statement */ + } + statement(ls); + } +} + + +static void fieldsel (LexState *ls, expdesc *v) { + /* fieldsel -> ['.' | ':'] NAME */ + FuncState *fs = ls->fs; + expdesc key; + luaK_exp2anyregup(fs, v); + luaX_next(ls); /* skip the dot or colon */ + codename(ls, &key); + luaK_indexed(fs, v, &key); +} + + +static void yindex (LexState *ls, expdesc *v) { + /* index -> '[' expr ']' */ + luaX_next(ls); /* skip the '[' */ + expr(ls, v); + luaK_exp2val(ls->fs, v); + checknext(ls, ']'); +} + + +/* +** {====================================================================== +** Rules for Constructors +** ======================================================================= +*/ + + +typedef struct ConsControl { + expdesc v; /* last list item read */ + expdesc *t; /* table descriptor */ + int nh; /* total number of 'record' elements */ + int na; /* number of array elements already stored */ + int tostore; /* number of array elements pending to be stored */ +} ConsControl; + + +static void recfield (LexState *ls, ConsControl *cc) { + /* recfield -> (NAME | '['exp']') = exp */ + FuncState *fs = ls->fs; + int reg = ls->fs->freereg; + expdesc tab, key, val; + if (ls->t.token == TK_NAME) { + checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + codename(ls, &key); + } + else /* ls->t.token == '[' */ + yindex(ls, &key); + cc->nh++; + checknext(ls, '='); + tab = *cc->t; + luaK_indexed(fs, &tab, &key); + expr(ls, &val); + luaK_storevar(fs, &tab, &val); + fs->freereg = reg; /* free registers */ +} + + +static void closelistfield (FuncState *fs, ConsControl *cc) { + if (cc->v.k == VVOID) return; /* there is no list item */ + luaK_exp2nextreg(fs, &cc->v); + cc->v.k = VVOID; + if (cc->tostore == LFIELDS_PER_FLUSH) { + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ + cc->na += cc->tostore; + cc->tostore = 0; /* no more items pending */ + } +} + + +static void lastlistfield (FuncState *fs, ConsControl *cc) { + if (cc->tostore == 0) return; + if (hasmultret(cc->v.k)) { + luaK_setmultret(fs, &cc->v); + luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); + cc->na--; /* do not count last expression (unknown number of elements) */ + } + else { + if (cc->v.k != VVOID) + luaK_exp2nextreg(fs, &cc->v); + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); + } + cc->na += cc->tostore; +} + + +static void listfield (LexState *ls, ConsControl *cc) { + /* listfield -> exp */ + expr(ls, &cc->v); + cc->tostore++; +} + + +static void field (LexState *ls, ConsControl *cc) { + /* field -> listfield | recfield */ + switch(ls->t.token) { + case TK_NAME: { /* may be 'listfield' or 'recfield' */ + if (luaX_lookahead(ls) != '=') /* expression? */ + listfield(ls, cc); + else + recfield(ls, cc); + break; + } + case '[': { + recfield(ls, cc); + break; + } + default: { + listfield(ls, cc); + break; + } + } +} + + +static void constructor (LexState *ls, expdesc *t) { + /* constructor -> '{' [ field { sep field } [sep] ] '}' + sep -> ',' | ';' */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); + ConsControl cc; + luaK_code(fs, 0); /* space for extra arg. */ + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + init_exp(t, VNONRELOC, fs->freereg); /* table will be at stack top */ + luaK_reserveregs(fs, 1); + init_exp(&cc.v, VVOID, 0); /* no value (yet) */ + checknext(ls, '{'); + do { + lua_assert(cc.v.k == VVOID || cc.tostore > 0); + if (ls->t.token == '}') break; + closelistfield(fs, &cc); + field(ls, &cc); + } while (testnext(ls, ',') || testnext(ls, ';')); + check_match(ls, '}', '{', line); + lastlistfield(fs, &cc); + luaK_settablesize(fs, pc, t->u.info, cc.na, cc.nh); +} + +/* }====================================================================== */ + + +static void setvararg (FuncState *fs, int nparams) { + fs->f->is_vararg = 1; + luaK_codeABC(fs, OP_VARARGPREP, nparams, 0, 0); +} + + +static void parlist (LexState *ls) { + /* parlist -> [ {NAME ','} (NAME | '...') ] */ + FuncState *fs = ls->fs; + Proto *f = fs->f; + int nparams = 0; + int isvararg = 0; + if (ls->t.token != ')') { /* is 'parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_NAME: { + new_localvar(ls, str_checkname(ls)); + nparams++; + break; + } + case TK_DOTS: { + luaX_next(ls); + isvararg = 1; + break; + } + default: luaX_syntaxerror(ls, " or '...' expected"); + } + } while (!isvararg && testnext(ls, ',')); + } + adjustlocalvars(ls, nparams); + f->numparams = cast_byte(fs->nactvar); + if (isvararg) + setvararg(fs, f->numparams); /* declared vararg */ + luaK_reserveregs(fs, fs->nactvar); /* reserve registers for parameters */ +} + + +static void body (LexState *ls, expdesc *e, int ismethod, int line) { + /* body -> '(' parlist ')' block END */ + FuncState new_fs; + BlockCnt bl; + new_fs.f = addprototype(ls); + new_fs.f->linedefined = line; + open_func(ls, &new_fs, &bl); + checknext(ls, '('); + if (ismethod) { + new_localvarliteral(ls, "self"); /* create 'self' parameter */ + adjustlocalvars(ls, 1); + } + parlist(ls); + checknext(ls, ')'); + statlist(ls); + new_fs.f->lastlinedefined = ls->linenumber; + check_match(ls, TK_END, TK_FUNCTION, line); + codeclosure(ls, e); + close_func(ls); +} + + +static int explist (LexState *ls, expdesc *v) { + /* explist -> expr { ',' expr } */ + int n = 1; /* at least one expression */ + expr(ls, v); + while (testnext(ls, ',')) { + luaK_exp2nextreg(ls->fs, v); + expr(ls, v); + n++; + } + return n; +} + + +static void funcargs (LexState *ls, expdesc *f, int line) { + FuncState *fs = ls->fs; + expdesc args; + int base, nparams; + switch (ls->t.token) { + case '(': { /* funcargs -> '(' [ explist ] ')' */ + luaX_next(ls); + if (ls->t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + explist(ls, &args); + if (hasmultret(args.k)) + luaK_setmultret(fs, &args); + } + check_match(ls, ')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + codestring(&args, ls->t.seminfo.ts); + luaX_next(ls); /* must use 'seminfo' before 'next' */ + break; + } + default: { + luaX_syntaxerror(ls, "function arguments expected"); + } + } + lua_assert(f->k == VNONRELOC); + base = f->u.info; /* base register for call */ + if (hasmultret(args.k)) + nparams = LUA_MULTRET; /* open call */ + else { + if (args.k != VVOID) + luaK_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base+1); + } + init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); + luaK_fixline(fs, line); + fs->freereg = base+1; /* call remove function and arguments and leaves + (unless changed) one result */ +} + + + + +/* +** {====================================================================== +** Expression parsing +** ======================================================================= +*/ + + +static void primaryexp (LexState *ls, expdesc *v) { + /* primaryexp -> NAME | '(' expr ')' */ + switch (ls->t.token) { + case '(': { + int line = ls->linenumber; + luaX_next(ls); + expr(ls, v); + check_match(ls, ')', '(', line); + luaK_dischargevars(ls->fs, v); + return; + } + case TK_NAME: { + singlevar(ls, v); + return; + } + default: { + luaX_syntaxerror(ls, "unexpected symbol"); + } + } +} + + +static void suffixedexp (LexState *ls, expdesc *v) { + /* suffixedexp -> + primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + primaryexp(ls, v); + for (;;) { + switch (ls->t.token) { + case '.': { /* fieldsel */ + fieldsel(ls, v); + break; + } + case '[': { /* '[' exp ']' */ + expdesc key; + luaK_exp2anyregup(fs, v); + yindex(ls, &key); + luaK_indexed(fs, v, &key); + break; + } + case ':': { /* ':' NAME funcargs */ + expdesc key; + luaX_next(ls); + codename(ls, &key); + luaK_self(fs, v, &key); + funcargs(ls, v, line); + break; + } + case '(': case TK_STRING: case '{': { /* funcargs */ + luaK_exp2nextreg(fs, v); + funcargs(ls, v, line); + break; + } + default: return; + } + } +} + + +static void simpleexp (LexState *ls, expdesc *v) { + /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... | + constructor | FUNCTION body | suffixedexp */ + switch (ls->t.token) { + case TK_FLT: { + init_exp(v, VKFLT, 0); + v->u.nval = ls->t.seminfo.r; + break; + } + case TK_INT: { + init_exp(v, VKINT, 0); + v->u.ival = ls->t.seminfo.i; + break; + } + case TK_STRING: { + codestring(v, ls->t.seminfo.ts); + break; + } + case TK_NIL: { + init_exp(v, VNIL, 0); + break; + } + case TK_TRUE: { + init_exp(v, VTRUE, 0); + break; + } + case TK_FALSE: { + init_exp(v, VFALSE, 0); + break; + } + case TK_DOTS: { /* vararg */ + FuncState *fs = ls->fs; + check_condition(ls, fs->f->is_vararg, + "cannot use '...' outside a vararg function"); + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 0, 1)); + break; + } + case '{': { /* constructor */ + constructor(ls, v); + return; + } + case TK_FUNCTION: { + luaX_next(ls); + body(ls, v, 0, ls->linenumber); + return; + } + default: { + suffixedexp(ls, v); + return; + } + } + luaX_next(ls); +} + + +static UnOpr getunopr (int op) { + switch (op) { + case TK_NOT: return OPR_NOT; + case '-': return OPR_MINUS; + case '~': return OPR_BNOT; + case '#': return OPR_LEN; + default: return OPR_NOUNOPR; + } +} + + +static BinOpr getbinopr (int op) { + switch (op) { + case '+': return OPR_ADD; + case '-': return OPR_SUB; + case '*': return OPR_MUL; + case '%': return OPR_MOD; + case '^': return OPR_POW; + case '/': return OPR_DIV; + case TK_IDIV: return OPR_IDIV; + case '&': return OPR_BAND; + case '|': return OPR_BOR; + case '~': return OPR_BXOR; + case TK_SHL: return OPR_SHL; + case TK_SHR: return OPR_SHR; + case TK_CONCAT: return OPR_CONCAT; + case TK_NE: return OPR_NE; + case TK_EQ: return OPR_EQ; + case '<': return OPR_LT; + case TK_LE: return OPR_LE; + case '>': return OPR_GT; + case TK_GE: return OPR_GE; + case TK_AND: return OPR_AND; + case TK_OR: return OPR_OR; + default: return OPR_NOBINOPR; + } +} + + +/* +** Priority table for binary operators. +*/ +static const struct { + lu_byte left; /* left priority for each binary operator */ + lu_byte right; /* right priority */ +} priority[] = { /* ORDER OPR */ + {10, 10}, {10, 10}, /* '+' '-' */ + {11, 11}, {11, 11}, /* '*' '%' */ + {14, 13}, /* '^' (right associative) */ + {11, 11}, {11, 11}, /* '/' '//' */ + {6, 6}, {4, 4}, {5, 5}, /* '&' '|' '~' */ + {7, 7}, {7, 7}, /* '<<' '>>' */ + {9, 8}, /* '..' (right associative) */ + {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ + {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ + {2, 2}, {1, 1} /* and, or */ +}; + +#define UNARY_PRIORITY 12 /* priority for unary operators */ + + +/* +** subexpr -> (simpleexp | unop subexpr) { binop subexpr } +** where 'binop' is any binary operator with a priority higher than 'limit' +*/ +static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { + BinOpr op; + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) { /* prefix (unary) operator? */ + int line = ls->linenumber; + luaX_next(ls); /* skip operator */ + subexpr(ls, v, UNARY_PRIORITY); + luaK_prefix(ls->fs, uop, v, line); + } + else simpleexp(ls, v); + /* expand while operators have priorities higher than 'limit' */ + op = getbinopr(ls->t.token); + while (op != OPR_NOBINOPR && priority[op].left > limit) { + expdesc v2; + BinOpr nextop; + int line = ls->linenumber; + luaX_next(ls); /* skip operator */ + luaK_infix(ls->fs, op, v); + /* read sub-expression with higher priority */ + nextop = subexpr(ls, &v2, priority[op].right); + luaK_posfix(ls->fs, op, v, &v2, line); + op = nextop; + } + leavelevel(ls); + return op; /* return first untreated operator */ +} + + +static void expr (LexState *ls, expdesc *v) { + subexpr(ls, v, 0); +} + +/* }==================================================================== */ + + + +/* +** {====================================================================== +** Rules for Statements +** ======================================================================= +*/ + + +static void block (LexState *ls) { + /* block -> statlist */ + FuncState *fs = ls->fs; + BlockCnt bl; + enterblock(fs, &bl, 0); + statlist(ls); + leaveblock(fs); +} + + +/* +** structure to chain all variables in the left-hand side of an +** assignment +*/ +struct LHS_assign { + struct LHS_assign *prev; + expdesc v; /* variable (global, local, upvalue, or indexed) */ +}; + + +/* +** check whether, in an assignment to an upvalue/local variable, the +** upvalue/local variable is begin used in a previous assignment to a +** table. If so, save original upvalue/local value in a safe place and +** use this safe copy in the previous assignment. +*/ +static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { + FuncState *fs = ls->fs; + int extra = fs->freereg; /* eventual position to save local variable */ + int conflict = 0; + for (; lh; lh = lh->prev) { /* check all previous assignments */ + if (vkisindexed(lh->v.k)) { /* assignment to table field? */ + if (lh->v.k == VINDEXUP) { /* is table an upvalue? */ + if (v->k == VUPVAL && lh->v.u.ind.t == v->u.info) { + conflict = 1; /* table is the upvalue being assigned now */ + lh->v.k = VINDEXSTR; + lh->v.u.ind.t = extra; /* assignment will use safe copy */ + } + } + else { /* table is a register */ + if (v->k == VLOCAL && lh->v.u.ind.t == v->u.var.ridx) { + conflict = 1; /* table is the local being assigned now */ + lh->v.u.ind.t = extra; /* assignment will use safe copy */ + } + /* is index the local being assigned? */ + if (lh->v.k == VINDEXED && v->k == VLOCAL && + lh->v.u.ind.idx == v->u.var.ridx) { + conflict = 1; + lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ + } + } + } + } + if (conflict) { + /* copy upvalue/local value to a temporary (in position 'extra') */ + if (v->k == VLOCAL) + luaK_codeABC(fs, OP_MOVE, extra, v->u.var.ridx, 0); + else + luaK_codeABC(fs, OP_GETUPVAL, extra, v->u.info, 0); + luaK_reserveregs(fs, 1); + } +} + +/* +** Parse and compile a multiple assignment. The first "variable" +** (a 'suffixedexp') was already read by the caller. +** +** assignment -> suffixedexp restassign +** restassign -> ',' suffixedexp restassign | '=' explist +*/ +static void restassign (LexState *ls, struct LHS_assign *lh, int nvars) { + expdesc e; + check_condition(ls, vkisvar(lh->v.k), "syntax error"); + check_readonly(ls, &lh->v); + if (testnext(ls, ',')) { /* restassign -> ',' suffixedexp restassign */ + struct LHS_assign nv; + nv.prev = lh; + suffixedexp(ls, &nv.v); + if (!vkisindexed(nv.v.k)) + check_conflict(ls, lh, &nv.v); + enterlevel(ls); /* control recursion depth */ + restassign(ls, &nv, nvars+1); + leavelevel(ls); + } + else { /* restassign -> '=' explist */ + int nexps; + checknext(ls, '='); + nexps = explist(ls, &e); + if (nexps != nvars) + adjust_assign(ls, nvars, nexps, &e); + else { + luaK_setoneret(ls->fs, &e); /* close last expression */ + luaK_storevar(ls->fs, &lh->v, &e); + return; /* avoid default */ + } + } + init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ + luaK_storevar(ls->fs, &lh->v, &e); +} + + +static int cond (LexState *ls) { + /* cond -> exp */ + expdesc v; + expr(ls, &v); /* read condition */ + if (v.k == VNIL) v.k = VFALSE; /* 'falses' are all equal here */ + luaK_goiftrue(ls->fs, &v); + return v.f; +} + + +static void gotostat (LexState *ls) { + FuncState *fs = ls->fs; + int line = ls->linenumber; + TString *name = str_checkname(ls); /* label's name */ + Labeldesc *lb = findlabel(ls, name); + if (lb == NULL) /* no label? */ + /* forward jump; will be resolved when the label is declared */ + newgotoentry(ls, name, line, luaK_jump(fs)); + else { /* found a label */ + /* backward jump; will be resolved here */ + int lblevel = reglevel(fs, lb->nactvar); /* label level */ + if (luaY_nvarstack(fs) > lblevel) /* leaving the scope of a variable? */ + luaK_codeABC(fs, OP_CLOSE, lblevel, 0, 0); + /* create jump and link it to the label */ + luaK_patchlist(fs, luaK_jump(fs), lb->pc); + } +} + + +/* +** Break statement. Semantically equivalent to "goto break". +*/ +static void breakstat (LexState *ls) { + int line = ls->linenumber; + luaX_next(ls); /* skip break */ + newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, luaK_jump(ls->fs)); +} + + +/* +** Check whether there is already a label with the given 'name'. +*/ +static void checkrepeated (LexState *ls, TString *name) { + Labeldesc *lb = findlabel(ls, name); + if (l_unlikely(lb != NULL)) { /* already defined? */ + const char *msg = "label '%s' already defined on line %d"; + msg = luaO_pushfstring(ls->L, msg, getstr(name), lb->line); + luaK_semerror(ls, msg); /* error */ + } +} + + +static void labelstat (LexState *ls, TString *name, int line) { + /* label -> '::' NAME '::' */ + checknext(ls, TK_DBCOLON); /* skip double colon */ + while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) + statement(ls); /* skip other no-op statements */ + checkrepeated(ls, name); /* check for repeated labels */ + createlabel(ls, name, line, block_follow(ls, 0)); +} + + +static void whilestat (LexState *ls, int line) { + /* whilestat -> WHILE cond DO block END */ + FuncState *fs = ls->fs; + int whileinit; + int condexit; + BlockCnt bl; + luaX_next(ls); /* skip WHILE */ + whileinit = luaK_getlabel(fs); + condexit = cond(ls); + enterblock(fs, &bl, 1); + checknext(ls, TK_DO); + block(ls); + luaK_jumpto(fs, whileinit); + check_match(ls, TK_END, TK_WHILE, line); + leaveblock(fs); + luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ +} + + +static void repeatstat (LexState *ls, int line) { + /* repeatstat -> REPEAT block UNTIL cond */ + int condexit; + FuncState *fs = ls->fs; + int repeat_init = luaK_getlabel(fs); + BlockCnt bl1, bl2; + enterblock(fs, &bl1, 1); /* loop block */ + enterblock(fs, &bl2, 0); /* scope block */ + luaX_next(ls); /* skip REPEAT */ + statlist(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + condexit = cond(ls); /* read condition (inside scope block) */ + leaveblock(fs); /* finish scope */ + if (bl2.upval) { /* upvalues? */ + int exit = luaK_jump(fs); /* normal exit must jump over fix */ + luaK_patchtohere(fs, condexit); /* repetition must close upvalues */ + luaK_codeABC(fs, OP_CLOSE, reglevel(fs, bl2.nactvar), 0, 0); + condexit = luaK_jump(fs); /* repeat after closing upvalues */ + luaK_patchtohere(fs, exit); /* normal exit comes to here */ + } + luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ + leaveblock(fs); /* finish loop */ +} + + +/* +** Read an expression and generate code to put its results in next +** stack slot. +** +*/ +static void exp1 (LexState *ls) { + expdesc e; + expr(ls, &e); + luaK_exp2nextreg(ls->fs, &e); + lua_assert(e.k == VNONRELOC); +} + + +/* +** Fix for instruction at position 'pc' to jump to 'dest'. +** (Jump addresses are relative in Lua). 'back' true means +** a back jump. +*/ +static void fixforjump (FuncState *fs, int pc, int dest, int back) { + Instruction *jmp = &fs->f->code[pc]; + int offset = dest - (pc + 1); + if (back) + offset = -offset; + if (l_unlikely(offset > MAXARG_Bx)) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_Bx(*jmp, offset); +} + + +/* +** Generate code for a 'for' loop. +*/ +static void forbody (LexState *ls, int base, int line, int nvars, int isgen) { + /* forbody -> DO block */ + static const OpCode forprep[2] = {OP_FORPREP, OP_TFORPREP}; + static const OpCode forloop[2] = {OP_FORLOOP, OP_TFORLOOP}; + BlockCnt bl; + FuncState *fs = ls->fs; + int prep, endfor; + checknext(ls, TK_DO); + prep = luaK_codeABx(fs, forprep[isgen], base, 0); + enterblock(fs, &bl, 0); /* scope for declared variables */ + adjustlocalvars(ls, nvars); + luaK_reserveregs(fs, nvars); + block(ls); + leaveblock(fs); /* end of scope for declared variables */ + fixforjump(fs, prep, luaK_getlabel(fs), 0); + if (isgen) { /* generic for? */ + luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); + luaK_fixline(fs, line); + } + endfor = luaK_codeABx(fs, forloop[isgen], base, 0); + fixforjump(fs, endfor, prep + 1, 1); + luaK_fixline(fs, line); +} + + +static void fornum (LexState *ls, TString *varname, int line) { + /* fornum -> NAME = exp,exp[,exp] forbody */ + FuncState *fs = ls->fs; + int base = fs->freereg; + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for state)"); + new_localvar(ls, varname); + checknext(ls, '='); + exp1(ls); /* initial value */ + checknext(ls, ','); + exp1(ls); /* limit */ + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ + luaK_int(fs, fs->freereg, 1); + luaK_reserveregs(fs, 1); + } + adjustlocalvars(ls, 3); /* control variables */ + forbody(ls, base, line, 1, 0); +} + + +static void forlist (LexState *ls, TString *indexname) { + /* forlist -> NAME {,NAME} IN explist forbody */ + FuncState *fs = ls->fs; + expdesc e; + int nvars = 5; /* gen, state, control, toclose, 'indexname' */ + int line; + int base = fs->freereg; + /* create control variables */ + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for state)"); + /* create declared variables */ + new_localvar(ls, indexname); + while (testnext(ls, ',')) { + new_localvar(ls, str_checkname(ls)); + nvars++; + } + checknext(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, 4, explist(ls, &e), &e); + adjustlocalvars(ls, 4); /* control variables */ + markupval(fs, fs->nactvar); /* last control var. must be closed */ + luaK_checkstack(fs, 3); /* extra space to call generator */ + forbody(ls, base, line, nvars - 4, 1); +} + + +static void forstat (LexState *ls, int line) { + /* forstat -> FOR (fornum | forlist) END */ + FuncState *fs = ls->fs; + TString *varname; + BlockCnt bl; + enterblock(fs, &bl, 1); /* scope for loop and control variables */ + luaX_next(ls); /* skip 'for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) { + case '=': fornum(ls, varname, line); break; + case ',': case TK_IN: forlist(ls, varname); break; + default: luaX_syntaxerror(ls, "'=' or 'in' expected"); + } + check_match(ls, TK_END, TK_FOR, line); + leaveblock(fs); /* loop scope ('break' jumps to this point) */ +} + + +static void test_then_block (LexState *ls, int *escapelist) { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + BlockCnt bl; + FuncState *fs = ls->fs; + expdesc v; + int jf; /* instruction to skip 'then' code (if condition is false) */ + luaX_next(ls); /* skip IF or ELSEIF */ + expr(ls, &v); /* read condition */ + checknext(ls, TK_THEN); + if (ls->t.token == TK_BREAK) { /* 'if x then break' ? */ + int line = ls->linenumber; + luaK_goiffalse(ls->fs, &v); /* will jump if condition is true */ + luaX_next(ls); /* skip 'break' */ + enterblock(fs, &bl, 0); /* must enter block before 'goto' */ + newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t); + while (testnext(ls, ';')) {} /* skip semicolons */ + if (block_follow(ls, 0)) { /* jump is the entire block? */ + leaveblock(fs); + return; /* and that is it */ + } + else /* must skip over 'then' part if condition is false */ + jf = luaK_jump(fs); + } + else { /* regular case (not a break) */ + luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ + enterblock(fs, &bl, 0); + jf = v.f; + } + statlist(ls); /* 'then' part */ + leaveblock(fs); + if (ls->t.token == TK_ELSE || + ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ + luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ + luaK_patchtohere(fs, jf); +} + + +static void ifstat (LexState *ls, int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + FuncState *fs = ls->fs; + int escapelist = NO_JUMP; /* exit list for finished parts */ + test_then_block(ls, &escapelist); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) + test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ + if (testnext(ls, TK_ELSE)) + block(ls); /* 'else' part */ + check_match(ls, TK_END, TK_IF, line); + luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ +} + + +static void localfunc (LexState *ls) { + expdesc b; + FuncState *fs = ls->fs; + int fvar = fs->nactvar; /* function's variable index */ + new_localvar(ls, str_checkname(ls)); /* new local variable */ + adjustlocalvars(ls, 1); /* enter its scope */ + body(ls, &b, 0, ls->linenumber); /* function created in next register */ + /* debug information will only see the variable after this point! */ + localdebuginfo(fs, fvar)->startpc = fs->pc; +} + + +static int getlocalattribute (LexState *ls) { + /* ATTRIB -> ['<' Name '>'] */ + if (testnext(ls, '<')) { + const char *attr = getstr(str_checkname(ls)); + checknext(ls, '>'); + if (strcmp(attr, "const") == 0) + return RDKCONST; /* read-only variable */ + else if (strcmp(attr, "close") == 0) + return RDKTOCLOSE; /* to-be-closed variable */ + else + luaK_semerror(ls, + luaO_pushfstring(ls->L, "unknown attribute '%s'", attr)); + } + return VDKREG; /* regular variable */ +} + + +static void checktoclose (LexState *ls, int level) { + if (level != -1) { /* is there a to-be-closed variable? */ + FuncState *fs = ls->fs; + markupval(fs, level + 1); + fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */ + luaK_codeABC(fs, OP_TBC, reglevel(fs, level), 0, 0); + } +} + + +static void localstat (LexState *ls) { + /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */ + FuncState *fs = ls->fs; + int toclose = -1; /* index of to-be-closed variable (if any) */ + Vardesc *var; /* last variable */ + int vidx, kind; /* index and kind of last variable */ + int nvars = 0; + int nexps; + expdesc e; + do { + vidx = new_localvar(ls, str_checkname(ls)); + kind = getlocalattribute(ls); + getlocalvardesc(fs, vidx)->vd.kind = kind; + if (kind == RDKTOCLOSE) { /* to-be-closed? */ + if (toclose != -1) /* one already present? */ + luaK_semerror(ls, "multiple to-be-closed variables in local list"); + toclose = fs->nactvar + nvars; + } + nvars++; + } while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist(ls, &e); + else { + e.k = VVOID; + nexps = 0; + } + var = getlocalvardesc(fs, vidx); /* get last variable */ + if (nvars == nexps && /* no adjustments? */ + var->vd.kind == RDKCONST && /* last variable is const? */ + luaK_exp2const(fs, &e, &var->k)) { /* compile-time constant? */ + var->vd.kind = RDKCTC; /* variable is a compile-time constant */ + adjustlocalvars(ls, nvars - 1); /* exclude last variable */ + fs->nactvar++; /* but count it */ + } + else { + adjust_assign(ls, nvars, nexps, &e); + adjustlocalvars(ls, nvars); + } + checktoclose(ls, toclose); +} + + +static int funcname (LexState *ls, expdesc *v) { + /* funcname -> NAME {fieldsel} [':' NAME] */ + int ismethod = 0; + singlevar(ls, v); + while (ls->t.token == '.') + fieldsel(ls, v); + if (ls->t.token == ':') { + ismethod = 1; + fieldsel(ls, v); + } + return ismethod; +} + + +static void funcstat (LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + int ismethod; + expdesc v, b; + luaX_next(ls); /* skip FUNCTION */ + ismethod = funcname(ls, &v); + body(ls, &b, ismethod, line); + luaK_storevar(ls->fs, &v, &b); + luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ +} + + +static void exprstat (LexState *ls) { + /* stat -> func | assignment */ + FuncState *fs = ls->fs; + struct LHS_assign v; + suffixedexp(ls, &v.v); + if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ + v.prev = NULL; + restassign(ls, &v, 1); + } + else { /* stat -> func */ + Instruction *inst; + check_condition(ls, v.v.k == VCALL, "syntax error"); + inst = &getinstruction(fs, &v.v); + SETARG_C(*inst, 1); /* call statement uses no results */ + } +} + + +static void retstat (LexState *ls) { + /* stat -> RETURN [explist] [';'] */ + FuncState *fs = ls->fs; + expdesc e; + int nret; /* number of values being returned */ + int first = luaY_nvarstack(fs); /* first slot to be returned */ + if (block_follow(ls, 1) || ls->t.token == ';') + nret = 0; /* return no values */ + else { + nret = explist(ls, &e); /* optional return values */ + if (hasmultret(e.k)) { + luaK_setmultret(fs, &e); + if (e.k == VCALL && nret == 1 && !fs->bl->insidetbc) { /* tail call? */ + SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getinstruction(fs,&e)) == luaY_nvarstack(fs)); + } + nret = LUA_MULTRET; /* return all values */ + } + else { + if (nret == 1) /* only one single value? */ + first = luaK_exp2anyreg(fs, &e); /* can use original slot */ + else { /* values must go to the top of the stack */ + luaK_exp2nextreg(fs, &e); + lua_assert(nret == fs->freereg - first); + } + } + } + luaK_ret(fs, first, nret); + testnext(ls, ';'); /* skip optional semicolon */ +} + + +static void statement (LexState *ls) { + int line = ls->linenumber; /* may be needed for error messages */ + enterlevel(ls); + switch (ls->t.token) { + case ';': { /* stat -> ';' (empty statement) */ + luaX_next(ls); /* skip ';' */ + break; + } + case TK_IF: { /* stat -> ifstat */ + ifstat(ls, line); + break; + } + case TK_WHILE: { /* stat -> whilestat */ + whilestat(ls, line); + break; + } + case TK_DO: { /* stat -> DO block END */ + luaX_next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + break; + } + case TK_FOR: { /* stat -> forstat */ + forstat(ls, line); + break; + } + case TK_REPEAT: { /* stat -> repeatstat */ + repeatstat(ls, line); + break; + } + case TK_FUNCTION: { /* stat -> funcstat */ + funcstat(ls, line); + break; + } + case TK_LOCAL: { /* stat -> localstat */ + luaX_next(ls); /* skip LOCAL */ + if (testnext(ls, TK_FUNCTION)) /* local function? */ + localfunc(ls); + else + localstat(ls); + break; + } + case TK_DBCOLON: { /* stat -> label */ + luaX_next(ls); /* skip double colon */ + labelstat(ls, str_checkname(ls), line); + break; + } + case TK_RETURN: { /* stat -> retstat */ + luaX_next(ls); /* skip RETURN */ + retstat(ls); + break; + } + case TK_BREAK: { /* stat -> breakstat */ + breakstat(ls); + break; + } + case TK_GOTO: { /* stat -> 'goto' NAME */ + luaX_next(ls); /* skip 'goto' */ + gotostat(ls); + break; + } + default: { /* stat -> func | assignment */ + exprstat(ls); + break; + } + } + lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && + ls->fs->freereg >= luaY_nvarstack(ls->fs)); + ls->fs->freereg = luaY_nvarstack(ls->fs); /* free registers */ + leavelevel(ls); +} + +/* }====================================================================== */ + + +/* +** compiles the main function, which is a regular vararg function with an +** upvalue named LUA_ENV +*/ +static void mainfunc (LexState *ls, FuncState *fs) { + BlockCnt bl; + Upvaldesc *env; + open_func(ls, fs, &bl); + setvararg(fs, 0); /* main function is always declared vararg */ + env = allocupvalue(fs); /* ...set environment upvalue */ + env->instack = 1; + env->idx = 0; + env->kind = VDKREG; + env->name = ls->envn; + luaC_objbarrier(ls->L, fs->f, env->name); + luaX_next(ls); /* read first token */ + statlist(ls); /* parse main body */ + check(ls, TK_EOS); + close_func(ls); +} + + +LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar) { + LexState lexstate; + FuncState funcstate; + LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ + setclLvalue2s(L, L->top, cl); /* anchor it (to avoid being collected) */ + luaD_inctop(L); + lexstate.h = luaH_new(L); /* create table for scanner */ + sethvalue2s(L, L->top, lexstate.h); /* anchor it */ + luaD_inctop(L); + funcstate.f = cl->p = luaF_newproto(L); + luaC_objbarrier(L, cl, cl->p); + funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ + luaC_objbarrier(L, funcstate.f, funcstate.f->source); + lexstate.buff = buff; + lexstate.dyd = dyd; + dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; + luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); + mainfunc(&lexstate, &funcstate); + lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); + /* all scopes should be correctly finished */ + lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); + L->top--; /* remove scanner's table */ + return cl; /* closure is on the stack, too */ +} + diff --git a/lua/lparser.h b/lua/lparser.h new file mode 100644 index 0000000..5e4500f --- /dev/null +++ b/lua/lparser.h @@ -0,0 +1,171 @@ +/* +** $Id: lparser.h $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + +#ifndef lparser_h +#define lparser_h + +#include "llimits.h" +#include "lobject.h" +#include "lzio.h" + + +/* +** Expression and variable descriptor. +** Code generation for variables and expressions can be delayed to allow +** optimizations; An 'expdesc' structure describes a potentially-delayed +** variable/expression. It has a description of its "main" value plus a +** list of conditional jumps that can also produce its value (generated +** by short-circuit operators 'and'/'or'). +*/ + +/* kinds of variables/expressions */ +typedef enum { + VVOID, /* when 'expdesc' describes the last expression of a list, + this kind means an empty list (so, no expression) */ + VNIL, /* constant nil */ + VTRUE, /* constant true */ + VFALSE, /* constant false */ + VK, /* constant in 'k'; info = index of constant in 'k' */ + VKFLT, /* floating constant; nval = numerical float value */ + VKINT, /* integer constant; ival = numerical integer value */ + VKSTR, /* string constant; strval = TString address; + (string is fixed by the lexer) */ + VNONRELOC, /* expression has its value in a fixed register; + info = result register */ + VLOCAL, /* local variable; var.ridx = register index; + var.vidx = relative index in 'actvar.arr' */ + VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ + VCONST, /* compile-time variable; + info = absolute index in 'actvar.arr' */ + VINDEXED, /* indexed variable; + ind.t = table register; + ind.idx = key's R index */ + VINDEXUP, /* indexed upvalue; + ind.t = table upvalue; + ind.idx = key's K index */ + VINDEXI, /* indexed variable with constant integer; + ind.t = table register; + ind.idx = key's value */ + VINDEXSTR, /* indexed variable with literal string; + ind.t = table register; + ind.idx = key's K index */ + VJMP, /* expression is a test/comparison; + info = pc of corresponding jump instruction */ + VRELOC, /* expression can put result in any register; + info = instruction pc */ + VCALL, /* expression is a function call; info = instruction pc */ + VVARARG /* vararg expression; info = instruction pc */ +} expkind; + + +#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXSTR) +#define vkisindexed(k) (VINDEXED <= (k) && (k) <= VINDEXSTR) + + +typedef struct expdesc { + expkind k; + union { + lua_Integer ival; /* for VKINT */ + lua_Number nval; /* for VKFLT */ + TString *strval; /* for VKSTR */ + int info; /* for generic use */ + struct { /* for indexed variables */ + short idx; /* index (R or "long" K) */ + lu_byte t; /* table (register or upvalue) */ + } ind; + struct { /* for local variables */ + lu_byte ridx; /* register holding the variable */ + unsigned short vidx; /* compiler index (in 'actvar.arr') */ + } var; + } u; + int t; /* patch list of 'exit when true' */ + int f; /* patch list of 'exit when false' */ +} expdesc; + + +/* kinds of variables */ +#define VDKREG 0 /* regular */ +#define RDKCONST 1 /* constant */ +#define RDKTOCLOSE 2 /* to-be-closed */ +#define RDKCTC 3 /* compile-time constant */ + +/* description of an active local variable */ +typedef union Vardesc { + struct { + TValuefields; /* constant value (if it is a compile-time constant) */ + lu_byte kind; + lu_byte ridx; /* register holding the variable */ + short pidx; /* index of the variable in the Proto's 'locvars' array */ + TString *name; /* variable name */ + } vd; + TValue k; /* constant value (if any) */ +} Vardesc; + + + +/* description of pending goto statements and label statements */ +typedef struct Labeldesc { + TString *name; /* label identifier */ + int pc; /* position in code */ + int line; /* line where it appeared */ + lu_byte nactvar; /* number of active variables in that position */ + lu_byte close; /* goto that escapes upvalues */ +} Labeldesc; + + +/* list of labels or gotos */ +typedef struct Labellist { + Labeldesc *arr; /* array */ + int n; /* number of entries in use */ + int size; /* array size */ +} Labellist; + + +/* dynamic structures used by the parser */ +typedef struct Dyndata { + struct { /* list of all active local variables */ + Vardesc *arr; + int n; + int size; + } actvar; + Labellist gt; /* list of pending gotos */ + Labellist label; /* list of active labels */ +} Dyndata; + + +/* control of blocks */ +struct BlockCnt; /* defined in lparser.c */ + + +/* state needed to generate code for a given function */ +typedef struct FuncState { + Proto *f; /* current function header */ + struct FuncState *prev; /* enclosing function */ + struct LexState *ls; /* lexical state */ + struct BlockCnt *bl; /* chain of current blocks */ + int pc; /* next position to code (equivalent to 'ncode') */ + int lasttarget; /* 'label' of last 'jump label' */ + int previousline; /* last line that was saved in 'lineinfo' */ + int nk; /* number of elements in 'k' */ + int np; /* number of elements in 'p' */ + int nabslineinfo; /* number of elements in 'abslineinfo' */ + int firstlocal; /* index of first local var (in Dyndata array) */ + int firstlabel; /* index of first label (in 'dyd->label->arr') */ + short ndebugvars; /* number of elements in 'f->locvars' */ + lu_byte nactvar; /* number of active local variables */ + lu_byte nups; /* number of upvalues */ + lu_byte freereg; /* first free register */ + lu_byte iwthabs; /* instructions issued since last absolute line info */ + lu_byte needclose; /* function needs to close upvalues when returning */ +} FuncState; + + +LUAI_FUNC int luaY_nvarstack (FuncState *fs); +LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar); + + +#endif diff --git a/lua/lprefix.h b/lua/lprefix.h new file mode 100644 index 0000000..484f2ad --- /dev/null +++ b/lua/lprefix.h @@ -0,0 +1,45 @@ +/* +** $Id: lprefix.h $ +** Definitions for Lua code that must come before any other header file +** See Copyright Notice in lua.h +*/ + +#ifndef lprefix_h +#define lprefix_h + + +/* +** Allows POSIX/XSI stuff +*/ +#if !defined(LUA_USE_C89) /* { */ + +#if !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE 600 +#elif _XOPEN_SOURCE == 0 +#undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */ +#endif + +/* +** Allows manipulation of large files in gcc and some other compilers +*/ +#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS) +#define _LARGEFILE_SOURCE 1 +#define _FILE_OFFSET_BITS 64 +#endif + +#endif /* } */ + + +/* +** Windows stuff +*/ +#if defined(_WIN32) /* { */ + +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */ +#endif + +#endif /* } */ + +#endif + diff --git a/lua/lstate.c b/lua/lstate.c new file mode 100644 index 0000000..c5e3b43 --- /dev/null +++ b/lua/lstate.c @@ -0,0 +1,439 @@ +/* +** $Id: lstate.c $ +** Global State +** See Copyright Notice in lua.h +*/ + +#define lstate_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + + +/* +** thread state + extra space +*/ +typedef struct LX { + lu_byte extra_[LUA_EXTRASPACE]; + lua_State l; +} LX; + + +/* +** Main thread combines a thread state and the global state +*/ +typedef struct LG { + LX l; + global_State g; +} LG; + + + +#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) + + +/* +** A macro to create a "random" seed when a state is created; +** the seed is used to randomize string hashes. +*/ +#if !defined(luai_makeseed) + +#include + +/* +** Compute an initial seed with some level of randomness. +** Rely on Address Space Layout Randomization (if present) and +** current time. +*/ +#define addbuff(b,p,e) \ + { size_t t = cast_sizet(e); \ + memcpy(b + p, &t, sizeof(t)); p += sizeof(t); } + +static unsigned int luai_makeseed (lua_State *L) { + char buff[3 * sizeof(size_t)]; + unsigned int h = cast_uint(time(NULL)); + int p = 0; + addbuff(buff, p, L); /* heap variable */ + addbuff(buff, p, &h); /* local variable */ + addbuff(buff, p, &lua_newstate); /* public function */ + lua_assert(p == sizeof(buff)); + return luaS_hash(buff, p, h); +} + +#endif + + +/* +** set GCdebt to a new value keeping the value (totalbytes + GCdebt) +** invariant (and avoiding underflows in 'totalbytes') +*/ +void luaE_setdebt (global_State *g, l_mem debt) { + l_mem tb = gettotalbytes(g); + lua_assert(tb > 0); + if (debt < tb - MAX_LMEM) + debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */ + g->totalbytes = tb - debt; + g->GCdebt = debt; +} + + +LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) { + UNUSED(L); UNUSED(limit); + return LUAI_MAXCCALLS; /* warning?? */ +} + + +CallInfo *luaE_extendCI (lua_State *L) { + CallInfo *ci; + lua_assert(L->ci->next == NULL); + ci = luaM_new(L, CallInfo); + lua_assert(L->ci->next == NULL); + L->ci->next = ci; + ci->previous = L->ci; + ci->next = NULL; + ci->u.l.trap = 0; + L->nci++; + return ci; +} + + +/* +** free all CallInfo structures not in use by a thread +*/ +void luaE_freeCI (lua_State *L) { + CallInfo *ci = L->ci; + CallInfo *next = ci->next; + ci->next = NULL; + while ((ci = next) != NULL) { + next = ci->next; + luaM_free(L, ci); + L->nci--; + } +} + + +/* +** free half of the CallInfo structures not in use by a thread, +** keeping the first one. +*/ +void luaE_shrinkCI (lua_State *L) { + CallInfo *ci = L->ci->next; /* first free CallInfo */ + CallInfo *next; + if (ci == NULL) + return; /* no extra elements */ + while ((next = ci->next) != NULL) { /* two extra elements? */ + CallInfo *next2 = next->next; /* next's next */ + ci->next = next2; /* remove next from the list */ + L->nci--; + luaM_free(L, next); /* free next */ + if (next2 == NULL) + break; /* no more elements */ + else { + next2->previous = ci; + ci = next2; /* continue */ + } + } +} + + +/* +** Called when 'getCcalls(L)' larger or equal to LUAI_MAXCCALLS. +** If equal, raises an overflow error. If value is larger than +** LUAI_MAXCCALLS (which means it is handling an overflow) but +** not much larger, does not report an error (to allow overflow +** handling to work). +*/ +void luaE_checkcstack (lua_State *L) { + if (getCcalls(L) == LUAI_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11)) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ +} + + +LUAI_FUNC void luaE_incCstack (lua_State *L) { + L->nCcalls++; + if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) + luaE_checkcstack(L); +} + + +static void stack_init (lua_State *L1, lua_State *L) { + int i; CallInfo *ci; + /* initialize stack array */ + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); + L1->tbclist = L1->stack; + for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) + setnilvalue(s2v(L1->stack + i)); /* erase new stack */ + L1->top = L1->stack; + L1->stack_last = L1->stack + BASIC_STACK_SIZE; + /* initialize first ci */ + ci = &L1->base_ci; + ci->next = ci->previous = NULL; + ci->callstatus = CIST_C; + ci->func = L1->top; + ci->u.c.k = NULL; + ci->nresults = 0; + setnilvalue(s2v(L1->top)); /* 'function' entry for this 'ci' */ + L1->top++; + ci->top = L1->top + LUA_MINSTACK; + L1->ci = ci; +} + + +static void freestack (lua_State *L) { + if (L->stack == NULL) + return; /* stack not completely built yet */ + L->ci = &L->base_ci; /* free the entire 'ci' list */ + luaE_freeCI(L); + lua_assert(L->nci == 0); + luaM_freearray(L, L->stack, stacksize(L) + EXTRA_STACK); /* free stack */ +} + + +/* +** Create registry table and its predefined values +*/ +static void init_registry (lua_State *L, global_State *g) { + /* create registry */ + Table *registry = luaH_new(L); + sethvalue(L, &g->l_registry, registry); + luaH_resize(L, registry, LUA_RIDX_LAST, 0); + /* registry[LUA_RIDX_MAINTHREAD] = L */ + setthvalue(L, ®istry->array[LUA_RIDX_MAINTHREAD - 1], L); + /* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */ + sethvalue(L, ®istry->array[LUA_RIDX_GLOBALS - 1], luaH_new(L)); +} + + +/* +** open parts of the state that may cause memory-allocation errors. +*/ +static void f_luaopen (lua_State *L, void *ud) { + global_State *g = G(L); + UNUSED(ud); + stack_init(L, L); /* init stack */ + init_registry(L, g); + luaS_init(L); + luaT_init(L); + luaX_init(L); + g->gcrunning = 1; /* allow gc */ + setnilvalue(&g->nilvalue); /* now state is complete */ + luai_userstateopen(L); +} + + +/* +** preinitialize a thread with consistent values without allocating +** any memory (to avoid errors) +*/ +static void preinit_thread (lua_State *L, global_State *g) { + G(L) = g; + L->stack = NULL; + L->ci = NULL; + L->nci = 0; + L->twups = L; /* thread has no upvalues */ + L->nCcalls = 0; + L->errorJmp = NULL; + L->hook = NULL; + L->hookmask = 0; + L->basehookcount = 0; + L->allowhook = 1; + resethookcount(L); + L->openupval = NULL; + L->status = LUA_OK; + L->errfunc = 0; + L->oldpc = 0; +} + + +static void close_state (lua_State *L) { + global_State *g = G(L); + if (!completestate(g)) /* closing a partially built state? */ + luaC_freeallobjects(L); /* jucst collect its objects */ + else { /* closing a fully built state */ + luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */ + luaC_freeallobjects(L); /* collect all objects */ + luai_userstateclose(L); + } + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); + freestack(L); + lua_assert(gettotalbytes(g) == sizeof(LG)); + (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ +} + + +LUA_API lua_State *lua_newthread (lua_State *L) { + global_State *g; + lua_State *L1; + lua_lock(L); + g = G(L); + luaC_checkGC(L); + /* create new thread */ + L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; + L1->marked = luaC_white(g); + L1->tt = LUA_VTHREAD; + /* link it on list 'allgc' */ + L1->next = g->allgc; + g->allgc = obj2gco(L1); + /* anchor it on L stack */ + setthvalue2s(L, L->top, L1); + api_incr_top(L); + preinit_thread(L1, g); + L1->hookmask = L->hookmask; + L1->basehookcount = L->basehookcount; + L1->hook = L->hook; + resethookcount(L1); + /* initialize L1 extra space */ + memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread), + LUA_EXTRASPACE); + luai_userstatethread(L, L1); + stack_init(L1, L); /* init stack */ + lua_unlock(L); + return L1; +} + + +void luaE_freethread (lua_State *L, lua_State *L1) { + LX *l = fromstate(L1); + luaF_closeupval(L1, L1->stack); /* close all upvalues */ + lua_assert(L1->openupval == NULL); + luai_userstatefree(L, L1); + freestack(L1); + luaM_free(L, l); +} + + +int luaE_resetthread (lua_State *L, int status) { + CallInfo *ci = L->ci = &L->base_ci; /* unwind CallInfo list */ + setnilvalue(s2v(L->stack)); /* 'function' entry for basic 'ci' */ + ci->func = L->stack; + ci->callstatus = CIST_C; + if (status == LUA_YIELD) + status = LUA_OK; + status = luaD_closeprotected(L, 1, status); + if (status != LUA_OK) /* errors? */ + luaD_seterrorobj(L, status, L->stack + 1); + else + L->top = L->stack + 1; + ci->top = L->top + LUA_MINSTACK; + L->status = cast_byte(status); + luaD_reallocstack(L, cast_int(ci->top - L->stack), 0); + return status; +} + + +LUA_API int lua_resetthread (lua_State *L) { + int status; + lua_lock(L); + status = luaE_resetthread(L, L->status); + lua_unlock(L); + return status; +} + + +LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { + int i; + lua_State *L; + global_State *g; + LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); + if (l == NULL) return NULL; + L = &l->l.l; + g = &l->g; + L->tt = LUA_VTHREAD; + g->currentwhite = bitmask(WHITE0BIT); + L->marked = luaC_white(g); + preinit_thread(L, g); + g->allgc = obj2gco(L); /* by now, only object is the main thread */ + L->next = NULL; + incnny(L); /* main thread is always non yieldable */ + g->frealloc = f; + g->ud = ud; + g->warnf = NULL; + g->ud_warn = NULL; + g->mainthread = L; + g->seed = luai_makeseed(L); + g->gcrunning = 0; /* no GC while building state */ + g->strt.size = g->strt.nuse = 0; + g->strt.hash = NULL; + setnilvalue(&g->l_registry); + g->panic = NULL; + g->gcstate = GCSpause; + g->gckind = KGC_INC; + g->gcstopem = 0; + g->gcemergency = 0; + g->finobj = g->tobefnz = g->fixedgc = NULL; + g->firstold1 = g->survival = g->old1 = g->reallyold = NULL; + g->finobjsur = g->finobjold1 = g->finobjrold = NULL; + g->sweepgc = NULL; + g->gray = g->grayagain = NULL; + g->weak = g->ephemeron = g->allweak = NULL; + g->twups = NULL; + g->totalbytes = sizeof(LG); + g->GCdebt = 0; + g->lastatomic = 0; + setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ + setgcparam(g->gcpause, LUAI_GCPAUSE); + setgcparam(g->gcstepmul, LUAI_GCMUL); + g->gcstepsize = LUAI_GCSTEPSIZE; + setgcparam(g->genmajormul, LUAI_GENMAJORMUL); + g->genminormul = LUAI_GENMINORMUL; + for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { + /* memory allocation error: free partial state */ + close_state(L); + L = NULL; + } + return L; +} + + +LUA_API void lua_close (lua_State *L) { + lua_lock(L); + L = G(L)->mainthread; /* only the main thread can be closed */ + close_state(L); +} + + +void luaE_warning (lua_State *L, const char *msg, int tocont) { + lua_WarnFunction wf = G(L)->warnf; + if (wf != NULL) + wf(G(L)->ud_warn, msg, tocont); +} + + +/* +** Generate a warning from an error message +*/ +void luaE_warnerror (lua_State *L, const char *where) { + TValue *errobj = s2v(L->top - 1); /* error object */ + const char *msg = (ttisstring(errobj)) + ? svalue(errobj) + : "error object is not a string"; + /* produce warning "error in %s (%s)" (where, msg) */ + luaE_warning(L, "error in ", 1); + luaE_warning(L, where, 1); + luaE_warning(L, " (", 1); + luaE_warning(L, msg, 1); + luaE_warning(L, ")", 0); +} + diff --git a/lua/lstate.h b/lua/lstate.h new file mode 100644 index 0000000..c1283bb --- /dev/null +++ b/lua/lstate.h @@ -0,0 +1,404 @@ +/* +** $Id: lstate.h $ +** Global State +** See Copyright Notice in lua.h +*/ + +#ifndef lstate_h +#define lstate_h + +#include "lua.h" + +#include "lobject.h" +#include "ltm.h" +#include "lzio.h" + + +/* +** Some notes about garbage-collected objects: All objects in Lua must +** be kept somehow accessible until being freed, so all objects always +** belong to one (and only one) of these lists, using field 'next' of +** the 'CommonHeader' for the link: +** +** 'allgc': all objects not marked for finalization; +** 'finobj': all objects marked for finalization; +** 'tobefnz': all objects ready to be finalized; +** 'fixedgc': all objects that are not to be collected (currently +** only small strings, such as reserved words). +** +** For the generational collector, some of these lists have marks for +** generations. Each mark points to the first element in the list for +** that particular generation; that generation goes until the next mark. +** +** 'allgc' -> 'survival': new objects; +** 'survival' -> 'old': objects that survived one collection; +** 'old1' -> 'reallyold': objects that became old in last collection; +** 'reallyold' -> NULL: objects old for more than one cycle. +** +** 'finobj' -> 'finobjsur': new objects marked for finalization; +** 'finobjsur' -> 'finobjold1': survived """"; +** 'finobjold1' -> 'finobjrold': just old """"; +** 'finobjrold' -> NULL: really old """". +** +** All lists can contain elements older than their main ages, due +** to 'luaC_checkfinalizer' and 'udata2finalize', which move +** objects between the normal lists and the "marked for finalization" +** lists. Moreover, barriers can age young objects in young lists as +** OLD0, which then become OLD1. However, a list never contains +** elements younger than their main ages. +** +** The generational collector also uses a pointer 'firstold1', which +** points to the first OLD1 object in the list. It is used to optimize +** 'markold'. (Potentially OLD1 objects can be anywhere between 'allgc' +** and 'reallyold', but often the list has no OLD1 objects or they are +** after 'old1'.) Note the difference between it and 'old1': +** 'firstold1': no OLD1 objects before this point; there can be all +** ages after it. +** 'old1': no objects younger than OLD1 after this point. +*/ + +/* +** Moreover, there is another set of lists that control gray objects. +** These lists are linked by fields 'gclist'. (All objects that +** can become gray have such a field. The field is not the same +** in all objects, but it always has this name.) Any gray object +** must belong to one of these lists, and all objects in these lists +** must be gray (with two exceptions explained below): +** +** 'gray': regular gray objects, still waiting to be visited. +** 'grayagain': objects that must be revisited at the atomic phase. +** That includes +** - black objects got in a write barrier; +** - all kinds of weak tables during propagation phase; +** - all threads. +** 'weak': tables with weak values to be cleared; +** 'ephemeron': ephemeron tables with white->white entries; +** 'allweak': tables with weak keys and/or weak values to be cleared. +** +** The exceptions to that "gray rule" are: +** - TOUCHED2 objects in generational mode stay in a gray list (because +** they must be visited again at the end of the cycle), but they are +** marked black because assignments to them must activate barriers (to +** move them back to TOUCHED1). +** - Open upvales are kept gray to avoid barriers, but they stay out +** of gray lists. (They don't even have a 'gclist' field.) +*/ + + + +/* +** About 'nCcalls': This count has two parts: the lower 16 bits counts +** the number of recursive invocations in the C stack; the higher +** 16 bits counts the number of non-yieldable calls in the stack. +** (They are together so that we can change and save both with one +** instruction.) +*/ + + +/* true if this thread does not have non-yieldable calls in the stack */ +#define yieldable(L) (((L)->nCcalls & 0xffff0000) == 0) + +/* real number of C calls */ +#define getCcalls(L) ((L)->nCcalls & 0xffff) + + +/* Increment the number of non-yieldable calls */ +#define incnny(L) ((L)->nCcalls += 0x10000) + +/* Decrement the number of non-yieldable calls */ +#define decnny(L) ((L)->nCcalls -= 0x10000) + +/* Non-yieldable call increment */ +#define nyci (0x10000 | 1) + + + + +struct lua_longjmp; /* defined in ldo.c */ + + +/* +** Atomic type (relative to signals) to better ensure that 'lua_sethook' +** is thread safe +*/ +#if !defined(l_signalT) +#include +#define l_signalT sig_atomic_t +#endif + + +/* +** Extra stack space to handle TM calls and some other extras. This +** space is not included in 'stack_last'. It is used only to avoid stack +** checks, either because the element will be promptly popped or because +** there will be a stack check soon after the push. Function frames +** never use this extra space, so it does not need to be kept clean. +*/ +#define EXTRA_STACK 5 + + +#define BASIC_STACK_SIZE (2*LUA_MINSTACK) + +#define stacksize(th) cast_int((th)->stack_last - (th)->stack) + + +/* kinds of Garbage Collection */ +#define KGC_INC 0 /* incremental gc */ +#define KGC_GEN 1 /* generational gc */ + + +typedef struct stringtable { + TString **hash; + int nuse; /* number of elements */ + int size; +} stringtable; + + +/* +** Information about a call. +** About union 'u': +** - field 'l' is used only for Lua functions; +** - field 'c' is used only for C functions. +** About union 'u2': +** - field 'funcidx' is used only by C functions while doing a +** protected call; +** - field 'nyield' is used only while a function is "doing" an +** yield (from the yield until the next resume); +** - field 'nres' is used only while closing tbc variables when +** returning from a C function; +** - field 'transferinfo' is used only during call/returnhooks, +** before the function starts or after it ends. +*/ +typedef struct CallInfo { + StkId func; /* function index in the stack */ + StkId top; /* top for this function */ + struct CallInfo *previous, *next; /* dynamic call link */ + union { + struct { /* only for Lua functions */ + const Instruction *savedpc; + volatile l_signalT trap; + int nextraargs; /* # of extra arguments in vararg functions */ + } l; + struct { /* only for C functions */ + lua_KFunction k; /* continuation in case of yields */ + ptrdiff_t old_errfunc; + lua_KContext ctx; /* context info. in case of yields */ + } c; + } u; + union { + int funcidx; /* called-function index */ + int nyield; /* number of values yielded */ + int nres; /* number of values returned */ + struct { /* info about transferred values (for call/return hooks) */ + unsigned short ftransfer; /* offset of first value transferred */ + unsigned short ntransfer; /* number of values transferred */ + } transferinfo; + } u2; + short nresults; /* expected number of results from this function */ + unsigned short callstatus; +} CallInfo; + + +/* +** Bits in CallInfo status +*/ +#define CIST_OAH (1<<0) /* original value of 'allowhook' */ +#define CIST_C (1<<1) /* call is running a C function */ +#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */ +#define CIST_HOOKED (1<<3) /* call is running a debug hook */ +#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */ +#define CIST_TAIL (1<<5) /* call was tail called */ +#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ +#define CIST_FIN (1<<7) /* call is running a finalizer */ +#define CIST_TRAN (1<<8) /* 'ci' has transfer information */ +#define CIST_CLSRET (1<<9) /* function is closing tbc variables */ +/* Bits 10-12 are used for CIST_RECST (see below) */ +#define CIST_RECST 10 +#if defined(LUA_COMPAT_LT_LE) +#define CIST_LEQ (1<<13) /* using __lt for __le */ +#endif + + +/* +** Field CIST_RECST stores the "recover status", used to keep the error +** status while closing to-be-closed variables in coroutines, so that +** Lua can correctly resume after an yield from a __close method called +** because of an error. (Three bits are enough for error status.) +*/ +#define getcistrecst(ci) (((ci)->callstatus >> CIST_RECST) & 7) +#define setcistrecst(ci,st) \ + check_exp(((st) & 7) == (st), /* status must fit in three bits */ \ + ((ci)->callstatus = ((ci)->callstatus & ~(7 << CIST_RECST)) \ + | ((st) << CIST_RECST))) + + +/* active function is a Lua function */ +#define isLua(ci) (!((ci)->callstatus & CIST_C)) + +/* call is running Lua code (not a hook) */ +#define isLuacode(ci) (!((ci)->callstatus & (CIST_C | CIST_HOOKED))) + +/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */ +#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) +#define getoah(st) ((st) & CIST_OAH) + + +/* +** 'global state', shared by all threads of this state +*/ +typedef struct global_State { + lua_Alloc frealloc; /* function to reallocate memory */ + void *ud; /* auxiliary data to 'frealloc' */ + l_mem totalbytes; /* number of bytes currently allocated - GCdebt */ + l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ + lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ + lu_mem lastatomic; /* see function 'genstep' in file 'lgc.c' */ + stringtable strt; /* hash table for strings */ + TValue l_registry; + TValue nilvalue; /* a nil value */ + unsigned int seed; /* randomized seed for hashes */ + lu_byte currentwhite; + lu_byte gcstate; /* state of garbage collector */ + lu_byte gckind; /* kind of GC running */ + lu_byte gcstopem; /* stops emergency collections */ + lu_byte genminormul; /* control for minor generational collections */ + lu_byte genmajormul; /* control for major generational collections */ + lu_byte gcrunning; /* true if GC is running */ + lu_byte gcemergency; /* true if this is an emergency collection */ + lu_byte gcpause; /* size of pause between successive GCs */ + lu_byte gcstepmul; /* GC "speed" */ + lu_byte gcstepsize; /* (log2 of) GC granularity */ + GCObject *allgc; /* list of all collectable objects */ + GCObject **sweepgc; /* current position of sweep in list */ + GCObject *finobj; /* list of collectable objects with finalizers */ + GCObject *gray; /* list of gray objects */ + GCObject *grayagain; /* list of objects to be traversed atomically */ + GCObject *weak; /* list of tables with weak values */ + GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ + GCObject *allweak; /* list of all-weak tables */ + GCObject *tobefnz; /* list of userdata to be GC */ + GCObject *fixedgc; /* list of objects not to be collected */ + /* fields for generational collector */ + GCObject *survival; /* start of objects that survived one GC cycle */ + GCObject *old1; /* start of old1 objects */ + GCObject *reallyold; /* objects more than one cycle old ("really old") */ + GCObject *firstold1; /* first OLD1 object in the list (if any) */ + GCObject *finobjsur; /* list of survival objects with finalizers */ + GCObject *finobjold1; /* list of old1 objects with finalizers */ + GCObject *finobjrold; /* list of really old objects with finalizers */ + struct lua_State *twups; /* list of threads with open upvalues */ + lua_CFunction panic; /* to be called in unprotected errors */ + struct lua_State *mainthread; + TString *memerrmsg; /* message for memory-allocation errors */ + TString *tmname[TM_N]; /* array with tag-method names */ + struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ + TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ + lua_WarnFunction warnf; /* warning function */ + void *ud_warn; /* auxiliary data to 'warnf' */ +} global_State; + + +/* +** 'per thread' state +*/ +struct lua_State { + CommonHeader; + lu_byte status; + lu_byte allowhook; + unsigned short nci; /* number of items in 'ci' list */ + StkId top; /* first free slot in the stack */ + global_State *l_G; + CallInfo *ci; /* call info for current function */ + StkId stack_last; /* end of stack (last element + 1) */ + StkId stack; /* stack base */ + UpVal *openupval; /* list of open upvalues in this stack */ + StkId tbclist; /* list of to-be-closed variables */ + GCObject *gclist; + struct lua_State *twups; /* list of threads with open upvalues */ + struct lua_longjmp *errorJmp; /* current error recover point */ + CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ + volatile lua_Hook hook; + ptrdiff_t errfunc; /* current error handling function (stack index) */ + l_uint32 nCcalls; /* number of nested (non-yieldable | C) calls */ + int oldpc; /* last pc traced */ + int basehookcount; + int hookcount; + volatile l_signalT hookmask; +}; + + +#define G(L) (L->l_G) + +/* +** 'g->nilvalue' being a nil value flags that the state was completely +** build. +*/ +#define completestate(g) ttisnil(&g->nilvalue) + + +/* +** Union of all collectable objects (only for conversions) +** ISO C99, 6.5.2.3 p.5: +** "if a union contains several structures that share a common initial +** sequence [...], and if the union object currently contains one +** of these structures, it is permitted to inspect the common initial +** part of any of them anywhere that a declaration of the complete type +** of the union is visible." +*/ +union GCUnion { + GCObject gc; /* common header */ + struct TString ts; + struct Udata u; + union Closure cl; + struct Table h; + struct Proto p; + struct lua_State th; /* thread */ + struct UpVal upv; +}; + + +/* +** ISO C99, 6.7.2.1 p.14: +** "A pointer to a union object, suitably converted, points to each of +** its members [...], and vice versa." +*/ +#define cast_u(o) cast(union GCUnion *, (o)) + +/* macros to convert a GCObject into a specific value */ +#define gco2ts(o) \ + check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts)) +#define gco2u(o) check_exp((o)->tt == LUA_VUSERDATA, &((cast_u(o))->u)) +#define gco2lcl(o) check_exp((o)->tt == LUA_VLCL, &((cast_u(o))->cl.l)) +#define gco2ccl(o) check_exp((o)->tt == LUA_VCCL, &((cast_u(o))->cl.c)) +#define gco2cl(o) \ + check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl)) +#define gco2t(o) check_exp((o)->tt == LUA_VTABLE, &((cast_u(o))->h)) +#define gco2p(o) check_exp((o)->tt == LUA_VPROTO, &((cast_u(o))->p)) +#define gco2th(o) check_exp((o)->tt == LUA_VTHREAD, &((cast_u(o))->th)) +#define gco2upv(o) check_exp((o)->tt == LUA_VUPVAL, &((cast_u(o))->upv)) + + +/* +** macro to convert a Lua object into a GCObject +** (The access to 'tt' tries to ensure that 'v' is actually a Lua object.) +*/ +#define obj2gco(v) check_exp((v)->tt >= LUA_TSTRING, &(cast_u(v)->gc)) + + +/* actual number of total bytes allocated */ +#define gettotalbytes(g) cast(lu_mem, (g)->totalbytes + (g)->GCdebt) + +LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); +LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); +LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); +LUAI_FUNC void luaE_freeCI (lua_State *L); +LUAI_FUNC void luaE_shrinkCI (lua_State *L); +LUAI_FUNC void luaE_checkcstack (lua_State *L); +LUAI_FUNC void luaE_incCstack (lua_State *L); +LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont); +LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where); +LUAI_FUNC int luaE_resetthread (lua_State *L, int status); + + +#endif + diff --git a/lua/lstring.c b/lua/lstring.c new file mode 100644 index 0000000..13dcaf4 --- /dev/null +++ b/lua/lstring.c @@ -0,0 +1,273 @@ +/* +** $Id: lstring.c $ +** String table (keeps all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#define lstring_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" + + +/* +** Maximum size for string table. +*/ +#define MAXSTRTB cast_int(luaM_limitN(MAX_INT, TString*)) + + +/* +** equality for long strings +*/ +int luaS_eqlngstr (TString *a, TString *b) { + size_t len = a->u.lnglen; + lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR); + return (a == b) || /* same instance or... */ + ((len == b->u.lnglen) && /* equal length and ... */ + (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ +} + + +unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { + unsigned int h = seed ^ cast_uint(l); + for (; l > 0; l--) + h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1])); + return h; +} + + +unsigned int luaS_hashlongstr (TString *ts) { + lua_assert(ts->tt == LUA_VLNGSTR); + if (ts->extra == 0) { /* no hash? */ + size_t len = ts->u.lnglen; + ts->hash = luaS_hash(getstr(ts), len, ts->hash); + ts->extra = 1; /* now it has its hash */ + } + return ts->hash; +} + + +static void tablerehash (TString **vect, int osize, int nsize) { + int i; + for (i = osize; i < nsize; i++) /* clear new elements */ + vect[i] = NULL; + for (i = 0; i < osize; i++) { /* rehash old part of the array */ + TString *p = vect[i]; + vect[i] = NULL; + while (p) { /* for each string in the list */ + TString *hnext = p->u.hnext; /* save next */ + unsigned int h = lmod(p->hash, nsize); /* new position */ + p->u.hnext = vect[h]; /* chain it into array */ + vect[h] = p; + p = hnext; + } + } +} + + +/* +** Resize the string table. If allocation fails, keep the current size. +** (This can degrade performance, but any non-zero size should work +** correctly.) +*/ +void luaS_resize (lua_State *L, int nsize) { + stringtable *tb = &G(L)->strt; + int osize = tb->size; + TString **newvect; + if (nsize < osize) /* shrinking table? */ + tablerehash(tb->hash, osize, nsize); /* depopulate shrinking part */ + newvect = luaM_reallocvector(L, tb->hash, osize, nsize, TString*); + if (l_unlikely(newvect == NULL)) { /* reallocation failed? */ + if (nsize < osize) /* was it shrinking table? */ + tablerehash(tb->hash, nsize, osize); /* restore to original size */ + /* leave table as it was */ + } + else { /* allocation succeeded */ + tb->hash = newvect; + tb->size = nsize; + if (nsize > osize) + tablerehash(newvect, osize, nsize); /* rehash for new size */ + } +} + + +/* +** Clear API string cache. (Entries cannot be empty, so fill them with +** a non-collectable string.) +*/ +void luaS_clearcache (global_State *g) { + int i, j; + for (i = 0; i < STRCACHE_N; i++) + for (j = 0; j < STRCACHE_M; j++) { + if (iswhite(g->strcache[i][j])) /* will entry be collected? */ + g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */ + } +} + + +/* +** Initialize the string table and the string cache +*/ +void luaS_init (lua_State *L) { + global_State *g = G(L); + int i, j; + stringtable *tb = &G(L)->strt; + tb->hash = luaM_newvector(L, MINSTRTABSIZE, TString*); + tablerehash(tb->hash, 0, MINSTRTABSIZE); /* clear array */ + tb->size = MINSTRTABSIZE; + /* pre-create memory-error message */ + g->memerrmsg = luaS_newliteral(L, MEMERRMSG); + luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ + for (i = 0; i < STRCACHE_N; i++) /* fill cache with valid strings */ + for (j = 0; j < STRCACHE_M; j++) + g->strcache[i][j] = g->memerrmsg; +} + + + +/* +** creates a new string object +*/ +static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) { + TString *ts; + GCObject *o; + size_t totalsize; /* total size of TString object */ + totalsize = sizelstring(l); + o = luaC_newobj(L, tag, totalsize); + ts = gco2ts(o); + ts->hash = h; + ts->extra = 0; + getstr(ts)[l] = '\0'; /* ending 0 */ + return ts; +} + + +TString *luaS_createlngstrobj (lua_State *L, size_t l) { + TString *ts = createstrobj(L, l, LUA_VLNGSTR, G(L)->seed); + ts->u.lnglen = l; + return ts; +} + + +void luaS_remove (lua_State *L, TString *ts) { + stringtable *tb = &G(L)->strt; + TString **p = &tb->hash[lmod(ts->hash, tb->size)]; + while (*p != ts) /* find previous element */ + p = &(*p)->u.hnext; + *p = (*p)->u.hnext; /* remove element from its list */ + tb->nuse--; +} + + +static void growstrtab (lua_State *L, stringtable *tb) { + if (l_unlikely(tb->nuse == MAX_INT)) { /* too many strings? */ + luaC_fullgc(L, 1); /* try to free some... */ + if (tb->nuse == MAX_INT) /* still too many? */ + luaM_error(L); /* cannot even create a message... */ + } + if (tb->size <= MAXSTRTB / 2) /* can grow string table? */ + luaS_resize(L, tb->size * 2); +} + + +/* +** Checks whether short string exists and reuses it or creates a new one. +*/ +static TString *internshrstr (lua_State *L, const char *str, size_t l) { + TString *ts; + global_State *g = G(L); + stringtable *tb = &g->strt; + unsigned int h = luaS_hash(str, l, g->seed); + TString **list = &tb->hash[lmod(h, tb->size)]; + lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ + for (ts = *list; ts != NULL; ts = ts->u.hnext) { + if (l == ts->shrlen && (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { + /* found! */ + if (isdead(g, ts)) /* dead (but not collected yet)? */ + changewhite(ts); /* resurrect it */ + return ts; + } + } + /* else must create a new string */ + if (tb->nuse >= tb->size) { /* need to grow string table? */ + growstrtab(L, tb); + list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */ + } + ts = createstrobj(L, l, LUA_VSHRSTR, h); + memcpy(getstr(ts), str, l * sizeof(char)); + ts->shrlen = cast_byte(l); + ts->u.hnext = *list; + *list = ts; + tb->nuse++; + return ts; +} + + +/* +** new string (with explicit length) +*/ +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { + if (l <= LUAI_MAXSHORTLEN) /* short string? */ + return internshrstr(L, str, l); + else { + TString *ts; + if (l_unlikely(l >= (MAX_SIZE - sizeof(TString))/sizeof(char))) + luaM_toobig(L); + ts = luaS_createlngstrobj(L, l); + memcpy(getstr(ts), str, l * sizeof(char)); + return ts; + } +} + + +/* +** Create or reuse a zero-terminated string, first checking in the +** cache (using the string address as a key). The cache can contain +** only zero-terminated strings, so it is safe to use 'strcmp' to +** check hits. +*/ +TString *luaS_new (lua_State *L, const char *str) { + unsigned int i = point2uint(str) % STRCACHE_N; /* hash */ + int j; + TString **p = G(L)->strcache[i]; + for (j = 0; j < STRCACHE_M; j++) { + if (strcmp(str, getstr(p[j])) == 0) /* hit? */ + return p[j]; /* that is it */ + } + /* normal route */ + for (j = STRCACHE_M - 1; j > 0; j--) + p[j] = p[j - 1]; /* move out last element */ + /* new element is first in the list */ + p[0] = luaS_newlstr(L, str, strlen(str)); + return p[0]; +} + + +Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) { + Udata *u; + int i; + GCObject *o; + if (l_unlikely(s > MAX_SIZE - udatamemoffset(nuvalue))) + luaM_toobig(L); + o = luaC_newobj(L, LUA_VUSERDATA, sizeudata(nuvalue, s)); + u = gco2u(o); + u->len = s; + u->nuvalue = nuvalue; + u->metatable = NULL; + for (i = 0; i < nuvalue; i++) + setnilvalue(&u->uv[i].uv); + return u; +} + diff --git a/lua/lstring.h b/lua/lstring.h new file mode 100644 index 0000000..450c239 --- /dev/null +++ b/lua/lstring.h @@ -0,0 +1,57 @@ +/* +** $Id: lstring.h $ +** String table (keep all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#ifndef lstring_h +#define lstring_h + +#include "lgc.h" +#include "lobject.h" +#include "lstate.h" + + +/* +** Memory-allocation error message must be preallocated (it cannot +** be created after memory is exhausted) +*/ +#define MEMERRMSG "not enough memory" + + +/* +** Size of a TString: Size of the header plus space for the string +** itself (including final '\0'). +*/ +#define sizelstring(l) (offsetof(TString, contents) + ((l) + 1) * sizeof(char)) + +#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ + (sizeof(s)/sizeof(char))-1)) + + +/* +** test whether a string is a reserved word +*/ +#define isreserved(s) ((s)->tt == LUA_VSHRSTR && (s)->extra > 0) + + +/* +** equality for short strings, which are always internalized +*/ +#define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b)) + + +LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); +LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts); +LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); +LUAI_FUNC void luaS_resize (lua_State *L, int newsize); +LUAI_FUNC void luaS_clearcache (global_State *g); +LUAI_FUNC void luaS_init (lua_State *L); +LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); +LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue); +LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); +LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); +LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); + + +#endif diff --git a/lua/lstrlib.c b/lua/lstrlib.c new file mode 100644 index 0000000..47e5b27 --- /dev/null +++ b/lua/lstrlib.c @@ -0,0 +1,1817 @@ +/* +** $Id: lstrlib.c $ +** Standard library for string operations and pattern-matching +** See Copyright Notice in lua.h +*/ + +#define lstrlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** maximum number of captures that a pattern can do during +** pattern-matching. This limit is arbitrary, but must fit in +** an unsigned char. +*/ +#if !defined(LUA_MAXCAPTURES) +#define LUA_MAXCAPTURES 32 +#endif + + +/* macro to 'unsign' a character */ +#define uchar(c) ((unsigned char)(c)) + + +/* +** Some sizes are better limited to fit in 'int', but must also fit in +** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.) +*/ +#define MAX_SIZET ((size_t)(~(size_t)0)) + +#define MAXSIZE \ + (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX)) + + + + +static int str_len (lua_State *L) { + size_t l; + luaL_checklstring(L, 1, &l); + lua_pushinteger(L, (lua_Integer)l); + return 1; +} + + +/* +** translate a relative initial string position +** (negative means back from end): clip result to [1, inf). +** The length of any string in Lua must fit in a lua_Integer, +** so there are no overflows in the casts. +** The inverted comparison avoids a possible overflow +** computing '-pos'. +*/ +static size_t posrelatI (lua_Integer pos, size_t len) { + if (pos > 0) + return (size_t)pos; + else if (pos == 0) + return 1; + else if (pos < -(lua_Integer)len) /* inverted comparison */ + return 1; /* clip to 1 */ + else return len + (size_t)pos + 1; +} + + +/* +** Gets an optional ending string position from argument 'arg', +** with default value 'def'. +** Negative means back from end: clip result to [0, len] +*/ +static size_t getendpos (lua_State *L, int arg, lua_Integer def, + size_t len) { + lua_Integer pos = luaL_optinteger(L, arg, def); + if (pos > (lua_Integer)len) + return len; + else if (pos >= 0) + return (size_t)pos; + else if (pos < -(lua_Integer)len) + return 0; + else return len + (size_t)pos + 1; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + size_t start = posrelatI(luaL_checkinteger(L, 2), l); + size_t end = getendpos(L, 3, -1, l); + if (start <= end) + lua_pushlstring(L, s + start - 1, (end - start) + 1); + else lua_pushliteral(L, ""); + return 1; +} + + +static int str_reverse (lua_State *L) { + size_t l, i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + char *p = luaL_buffinitsize(L, &b, l); + for (i = 0; i < l; i++) + p[i] = s[l - i - 1]; + luaL_pushresultsize(&b, l); + return 1; +} + + +static int str_lower (lua_State *L) { + size_t l; + size_t i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + char *p = luaL_buffinitsize(L, &b, l); + for (i=0; i MAXSIZE / n)) + return luaL_error(L, "resulting string too large"); + else { + size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep; + luaL_Buffer b; + char *p = luaL_buffinitsize(L, &b, totallen); + while (n-- > 1) { /* first n-1 copies (followed by separator) */ + memcpy(p, s, l * sizeof(char)); p += l; + if (lsep > 0) { /* empty 'memcpy' is not that cheap */ + memcpy(p, sep, lsep * sizeof(char)); + p += lsep; + } + } + memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ + luaL_pushresultsize(&b, totallen); + } + return 1; +} + + +static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + lua_Integer pi = luaL_optinteger(L, 2, 1); + size_t posi = posrelatI(pi, l); + size_t pose = getendpos(L, 3, pi, l); + int n, i; + if (posi > pose) return 0; /* empty interval; return no values */ + if (l_unlikely(pose - posi >= (size_t)INT_MAX)) /* arithmetic overflow? */ + return luaL_error(L, "string slice too long"); + n = (int)(pose - posi) + 1; + luaL_checkstack(L, n, "string slice too long"); + for (i=0; iinit) { + state->init = 1; + luaL_buffinit(L, &state->B); + } + luaL_addlstring(&state->B, (const char *)b, size); + return 0; +} + + +static int str_dump (lua_State *L) { + struct str_Writer state; + int strip = lua_toboolean(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, 1); /* ensure function is on the top of the stack */ + state.init = 0; + if (l_unlikely(lua_dump(L, writer, &state, strip) != 0)) + return luaL_error(L, "unable to dump given function"); + luaL_pushresult(&state.B); + return 1; +} + + + +/* +** {====================================================== +** METAMETHODS +** ======================================================= +*/ + +#if defined(LUA_NOCVTS2N) /* { */ + +/* no coercion from strings to numbers */ + +static const luaL_Reg stringmetamethods[] = { + {"__index", NULL}, /* placeholder */ + {NULL, NULL} +}; + +#else /* }{ */ + +static int tonum (lua_State *L, int arg) { + if (lua_type(L, arg) == LUA_TNUMBER) { /* already a number? */ + lua_pushvalue(L, arg); + return 1; + } + else { /* check whether it is a numerical string */ + size_t len; + const char *s = lua_tolstring(L, arg, &len); + return (s != NULL && lua_stringtonumber(L, s) == len + 1); + } +} + + +static void trymt (lua_State *L, const char *mtname) { + lua_settop(L, 2); /* back to the original arguments */ + if (l_unlikely(lua_type(L, 2) == LUA_TSTRING || + !luaL_getmetafield(L, 2, mtname))) + luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2, + luaL_typename(L, -2), luaL_typename(L, -1)); + lua_insert(L, -3); /* put metamethod before arguments */ + lua_call(L, 2, 1); /* call metamethod */ +} + + +static int arith (lua_State *L, int op, const char *mtname) { + if (tonum(L, 1) && tonum(L, 2)) + lua_arith(L, op); /* result will be on the top */ + else + trymt(L, mtname); + return 1; +} + + +static int arith_add (lua_State *L) { + return arith(L, LUA_OPADD, "__add"); +} + +static int arith_sub (lua_State *L) { + return arith(L, LUA_OPSUB, "__sub"); +} + +static int arith_mul (lua_State *L) { + return arith(L, LUA_OPMUL, "__mul"); +} + +static int arith_mod (lua_State *L) { + return arith(L, LUA_OPMOD, "__mod"); +} + +static int arith_pow (lua_State *L) { + return arith(L, LUA_OPPOW, "__pow"); +} + +static int arith_div (lua_State *L) { + return arith(L, LUA_OPDIV, "__div"); +} + +static int arith_idiv (lua_State *L) { + return arith(L, LUA_OPIDIV, "__idiv"); +} + +static int arith_unm (lua_State *L) { + return arith(L, LUA_OPUNM, "__unm"); +} + + +static const luaL_Reg stringmetamethods[] = { + {"__add", arith_add}, + {"__sub", arith_sub}, + {"__mul", arith_mul}, + {"__mod", arith_mod}, + {"__pow", arith_pow}, + {"__div", arith_div}, + {"__idiv", arith_idiv}, + {"__unm", arith_unm}, + {"__index", NULL}, /* placeholder */ + {NULL, NULL} +}; + +#endif /* } */ + +/* }====================================================== */ + +/* +** {====================================================== +** PATTERN MATCHING +** ======================================================= +*/ + + +#define CAP_UNFINISHED (-1) +#define CAP_POSITION (-2) + + +typedef struct MatchState { + const char *src_init; /* init of source string */ + const char *src_end; /* end ('\0') of source string */ + const char *p_end; /* end ('\0') of pattern */ + lua_State *L; + int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ + unsigned char level; /* total number of captures (finished or unfinished) */ + struct { + const char *init; + ptrdiff_t len; + } capture[LUA_MAXCAPTURES]; +} MatchState; + + +/* recursive function */ +static const char *match (MatchState *ms, const char *s, const char *p); + + +/* maximum recursion depth for 'match' */ +#if !defined(MAXCCALLS) +#define MAXCCALLS 200 +#endif + + +#define L_ESC '%' +#define SPECIALS "^$*+?.([%-" + + +static int check_capture (MatchState *ms, int l) { + l -= '1'; + if (l_unlikely(l < 0 || l >= ms->level || + ms->capture[l].len == CAP_UNFINISHED)) + return luaL_error(ms->L, "invalid capture index %%%d", l + 1); + return l; +} + + +static int capture_to_close (MatchState *ms) { + int level = ms->level; + for (level--; level>=0; level--) + if (ms->capture[level].len == CAP_UNFINISHED) return level; + return luaL_error(ms->L, "invalid pattern capture"); +} + + +static const char *classend (MatchState *ms, const char *p) { + switch (*p++) { + case L_ESC: { + if (l_unlikely(p == ms->p_end)) + luaL_error(ms->L, "malformed pattern (ends with '%%')"); + return p+1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a ']' */ + if (l_unlikely(p == ms->p_end)) + luaL_error(ms->L, "malformed pattern (missing ']')"); + if (*(p++) == L_ESC && p < ms->p_end) + p++; /* skip escapes (e.g. '%]') */ + } while (*p != ']'); + return p+1; + } + default: { + return p; + } + } +} + + +static int match_class (int c, int cl) { + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'g' : res = isgraph(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + case 'x' : res = isxdigit(c); break; + case 'z' : res = (c == 0); break; /* deprecated option */ + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + + +static int matchbracketclass (int c, const char *p, const char *ec) { + int sig = 1; + if (*(p+1) == '^') { + sig = 0; + p++; /* skip the '^' */ + } + while (++p < ec) { + if (*p == L_ESC) { + p++; + if (match_class(c, uchar(*p))) + return sig; + } + else if ((*(p+1) == '-') && (p+2 < ec)) { + p+=2; + if (uchar(*(p-2)) <= c && c <= uchar(*p)) + return sig; + } + else if (uchar(*p) == c) return sig; + } + return !sig; +} + + +static int singlematch (MatchState *ms, const char *s, const char *p, + const char *ep) { + if (s >= ms->src_end) + return 0; + else { + int c = uchar(*s); + switch (*p) { + case '.': return 1; /* matches any char */ + case L_ESC: return match_class(c, uchar(*(p+1))); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); + } + } +} + + +static const char *matchbalance (MatchState *ms, const char *s, + const char *p) { + if (l_unlikely(p >= ms->p_end - 1)) + luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')"); + if (*s != *p) return NULL; + else { + int b = *p; + int e = *(p+1); + int cont = 1; + while (++s < ms->src_end) { + if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + + +static const char *max_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + ptrdiff_t i = 0; /* counts maximum expand for item */ + while (singlematch(ms, s + i, p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i>=0) { + const char *res = match(ms, (s+i), ep+1); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; +} + + +static const char *min_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + for (;;) { + const char *res = match(ms, s, ep+1); + if (res != NULL) + return res; + else if (singlematch(ms, s, p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } +} + + +static const char *start_capture (MatchState *ms, const char *s, + const char *p, int what) { + const char *res; + int level = ms->level; + if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); + ms->capture[level].init = s; + ms->capture[level].len = what; + ms->level = level+1; + if ((res=match(ms, s, p)) == NULL) /* match failed? */ + ms->level--; /* undo capture */ + return res; +} + + +static const char *end_capture (MatchState *ms, const char *s, + const char *p) { + int l = capture_to_close(ms); + const char *res; + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ + return res; +} + + +static const char *match_capture (MatchState *ms, const char *s, int l) { + size_t len; + l = check_capture(ms, l); + len = ms->capture[l].len; + if ((size_t)(ms->src_end-s) >= len && + memcmp(ms->capture[l].init, s, len) == 0) + return s+len; + else return NULL; +} + + +static const char *match (MatchState *ms, const char *s, const char *p) { + if (l_unlikely(ms->matchdepth-- == 0)) + luaL_error(ms->L, "pattern too complex"); + init: /* using goto's to optimize tail recursion */ + if (p != ms->p_end) { /* end of pattern? */ + switch (*p) { + case '(': { /* start capture */ + if (*(p + 1) == ')') /* position capture? */ + s = start_capture(ms, s, p + 2, CAP_POSITION); + else + s = start_capture(ms, s, p + 1, CAP_UNFINISHED); + break; + } + case ')': { /* end capture */ + s = end_capture(ms, s, p + 1); + break; + } + case '$': { + if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */ + goto dflt; /* no; go to default */ + s = (s == ms->src_end) ? s : NULL; /* check end of string */ + break; + } + case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ + switch (*(p + 1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p + 2); + if (s != NULL) { + p += 4; goto init; /* return match(ms, s, p + 4); */ + } /* else fail (s == NULL) */ + break; + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (l_unlikely(*p != '[')) + luaL_error(ms->L, "missing '[' after '%%f' in pattern"); + ep = classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s - 1); + if (!matchbracketclass(uchar(previous), p, ep - 1) && + matchbracketclass(uchar(*s), p, ep - 1)) { + p = ep; goto init; /* return match(ms, s, ep); */ + } + s = NULL; /* match failed */ + break; + } + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': { /* capture results (%0-%9)? */ + s = match_capture(ms, s, uchar(*(p + 1))); + if (s != NULL) { + p += 2; goto init; /* return match(ms, s, p + 2) */ + } + break; + } + default: goto dflt; + } + break; + } + default: dflt: { /* pattern class plus optional suffix */ + const char *ep = classend(ms, p); /* points to optional suffix */ + /* does not match at least once? */ + if (!singlematch(ms, s, p, ep)) { + if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ + p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ + } + else /* '+' or no suffix */ + s = NULL; /* fail */ + } + else { /* matched once */ + switch (*ep) { /* handle optional suffix */ + case '?': { /* optional */ + const char *res; + if ((res = match(ms, s + 1, ep + 1)) != NULL) + s = res; + else { + p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ + } + break; + } + case '+': /* 1 or more repetitions */ + s++; /* 1 match already done */ + /* FALLTHROUGH */ + case '*': /* 0 or more repetitions */ + s = max_expand(ms, s, p, ep); + break; + case '-': /* 0 or more repetitions (minimum) */ + s = min_expand(ms, s, p, ep); + break; + default: /* no suffix */ + s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ + } + } + break; + } + } + } + ms->matchdepth++; + return s; +} + + + +static const char *lmemfind (const char *s1, size_t l1, + const char *s2, size_t l2) { + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative 'l1' */ + else { + const char *init; /* to search for a '*s2' inside 's1' */ + l2--; /* 1st char will be checked by 'memchr' */ + l1 = l1-l2; /* 's2' cannot be found after that */ + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { + init++; /* 1st char is already checked */ + if (memcmp(init, s2+1, l2) == 0) + return init-1; + else { /* correct 'l1' and 's1' to try again */ + l1 -= init-s1; + s1 = init; + } + } + return NULL; /* not found */ + } +} + + +/* +** get information about the i-th capture. If there are no captures +** and 'i==0', return information about the whole match, which +** is the range 's'..'e'. If the capture is a string, return +** its length and put its address in '*cap'. If it is an integer +** (a position), push it on the stack and return CAP_POSITION. +*/ +static size_t get_onecapture (MatchState *ms, int i, const char *s, + const char *e, const char **cap) { + if (i >= ms->level) { + if (l_unlikely(i != 0)) + luaL_error(ms->L, "invalid capture index %%%d", i + 1); + *cap = s; + return e - s; + } + else { + ptrdiff_t capl = ms->capture[i].len; + *cap = ms->capture[i].init; + if (l_unlikely(capl == CAP_UNFINISHED)) + luaL_error(ms->L, "unfinished capture"); + else if (capl == CAP_POSITION) + lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); + return capl; + } +} + + +/* +** Push the i-th capture on the stack. +*/ +static void push_onecapture (MatchState *ms, int i, const char *s, + const char *e) { + const char *cap; + ptrdiff_t l = get_onecapture(ms, i, s, e, &cap); + if (l != CAP_POSITION) + lua_pushlstring(ms->L, cap, l); + /* else position was already pushed */ +} + + +static int push_captures (MatchState *ms, const char *s, const char *e) { + int i; + int nlevels = (ms->level == 0 && s) ? 1 : ms->level; + luaL_checkstack(ms->L, nlevels, "too many captures"); + for (i = 0; i < nlevels; i++) + push_onecapture(ms, i, s, e); + return nlevels; /* number of strings pushed */ +} + + +/* check whether pattern has no special characters */ +static int nospecials (const char *p, size_t l) { + size_t upto = 0; + do { + if (strpbrk(p + upto, SPECIALS)) + return 0; /* pattern has a special character */ + upto += strlen(p + upto) + 1; /* may have more after \0 */ + } while (upto <= l); + return 1; /* no special chars found */ +} + + +static void prepstate (MatchState *ms, lua_State *L, + const char *s, size_t ls, const char *p, size_t lp) { + ms->L = L; + ms->matchdepth = MAXCCALLS; + ms->src_init = s; + ms->src_end = s + ls; + ms->p_end = p + lp; +} + + +static void reprepstate (MatchState *ms) { + ms->level = 0; + lua_assert(ms->matchdepth == MAXCCALLS); +} + + +static int str_find_aux (lua_State *L, int find) { + size_t ls, lp; + const char *s = luaL_checklstring(L, 1, &ls); + const char *p = luaL_checklstring(L, 2, &lp); + size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1; + if (init > ls) { /* start after string's end? */ + luaL_pushfail(L); /* cannot find anything */ + return 1; + } + /* explicit request or no special characters? */ + if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { + /* do a plain search */ + const char *s2 = lmemfind(s + init, ls - init, p, lp); + if (s2) { + lua_pushinteger(L, (s2 - s) + 1); + lua_pushinteger(L, (s2 - s) + lp); + return 2; + } + } + else { + MatchState ms; + const char *s1 = s + init; + int anchor = (*p == '^'); + if (anchor) { + p++; lp--; /* skip anchor character */ + } + prepstate(&ms, L, s, ls, p, lp); + do { + const char *res; + reprepstate(&ms); + if ((res=match(&ms, s1, p)) != NULL) { + if (find) { + lua_pushinteger(L, (s1 - s) + 1); /* start */ + lua_pushinteger(L, res - s); /* end */ + return push_captures(&ms, NULL, 0) + 2; + } + else + return push_captures(&ms, s1, res); + } + } while (s1++ < ms.src_end && !anchor); + } + luaL_pushfail(L); /* not found */ + return 1; +} + + +static int str_find (lua_State *L) { + return str_find_aux(L, 1); +} + + +static int str_match (lua_State *L) { + return str_find_aux(L, 0); +} + + +/* state for 'gmatch' */ +typedef struct GMatchState { + const char *src; /* current position */ + const char *p; /* pattern */ + const char *lastmatch; /* end of last match */ + MatchState ms; /* match state */ +} GMatchState; + + +static int gmatch_aux (lua_State *L) { + GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); + const char *src; + gm->ms.L = L; + for (src = gm->src; src <= gm->ms.src_end; src++) { + const char *e; + reprepstate(&gm->ms); + if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) { + gm->src = gm->lastmatch = e; + return push_captures(&gm->ms, src, e); + } + } + return 0; /* not found */ +} + + +static int gmatch (lua_State *L) { + size_t ls, lp; + const char *s = luaL_checklstring(L, 1, &ls); + const char *p = luaL_checklstring(L, 2, &lp); + size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1; + GMatchState *gm; + lua_settop(L, 2); /* keep strings on closure to avoid being collected */ + gm = (GMatchState *)lua_newuserdatauv(L, sizeof(GMatchState), 0); + if (init > ls) /* start after string's end? */ + init = ls + 1; /* avoid overflows in 's + init' */ + prepstate(&gm->ms, L, s, ls, p, lp); + gm->src = s + init; gm->p = p; gm->lastmatch = NULL; + lua_pushcclosure(L, gmatch_aux, 3); + return 1; +} + + +static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e) { + size_t l; + lua_State *L = ms->L; + const char *news = lua_tolstring(L, 3, &l); + const char *p; + while ((p = (char *)memchr(news, L_ESC, l)) != NULL) { + luaL_addlstring(b, news, p - news); + p++; /* skip ESC */ + if (*p == L_ESC) /* '%%' */ + luaL_addchar(b, *p); + else if (*p == '0') /* '%0' */ + luaL_addlstring(b, s, e - s); + else if (isdigit(uchar(*p))) { /* '%n' */ + const char *cap; + ptrdiff_t resl = get_onecapture(ms, *p - '1', s, e, &cap); + if (resl == CAP_POSITION) + luaL_addvalue(b); /* add position to accumulated result */ + else + luaL_addlstring(b, cap, resl); + } + else + luaL_error(L, "invalid use of '%c' in replacement string", L_ESC); + l -= p + 1 - news; + news = p + 1; + } + luaL_addlstring(b, news, l); +} + + +/* +** Add the replacement value to the string buffer 'b'. +** Return true if the original string was changed. (Function calls and +** table indexing resulting in nil or false do not change the subject.) +*/ +static int add_value (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e, int tr) { + lua_State *L = ms->L; + switch (tr) { + case LUA_TFUNCTION: { /* call the function */ + int n; + lua_pushvalue(L, 3); /* push the function */ + n = push_captures(ms, s, e); /* all captures as arguments */ + lua_call(L, n, 1); /* call it */ + break; + } + case LUA_TTABLE: { /* index the table */ + push_onecapture(ms, 0, s, e); /* first capture is the index */ + lua_gettable(L, 3); + break; + } + default: { /* LUA_TNUMBER or LUA_TSTRING */ + add_s(ms, b, s, e); /* add value to the buffer */ + return 1; /* something changed */ + } + } + if (!lua_toboolean(L, -1)) { /* nil or false? */ + lua_pop(L, 1); /* remove value */ + luaL_addlstring(b, s, e - s); /* keep original text */ + return 0; /* no changes */ + } + else if (l_unlikely(!lua_isstring(L, -1))) + return luaL_error(L, "invalid replacement value (a %s)", + luaL_typename(L, -1)); + else { + luaL_addvalue(b); /* add result to accumulator */ + return 1; /* something changed */ + } +} + + +static int str_gsub (lua_State *L) { + size_t srcl, lp; + const char *src = luaL_checklstring(L, 1, &srcl); /* subject */ + const char *p = luaL_checklstring(L, 2, &lp); /* pattern */ + const char *lastmatch = NULL; /* end of last match */ + int tr = lua_type(L, 3); /* replacement type */ + lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */ + int anchor = (*p == '^'); + lua_Integer n = 0; /* replacement count */ + int changed = 0; /* change flag */ + MatchState ms; + luaL_Buffer b; + luaL_argexpected(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || + tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, + "string/function/table"); + luaL_buffinit(L, &b); + if (anchor) { + p++; lp--; /* skip anchor character */ + } + prepstate(&ms, L, src, srcl, p, lp); + while (n < max_s) { + const char *e; + reprepstate(&ms); /* (re)prepare state for new match */ + if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */ + n++; + changed = add_value(&ms, &b, src, e, tr) | changed; + src = lastmatch = e; + } + else if (src < ms.src_end) /* otherwise, skip one character */ + luaL_addchar(&b, *src++); + else break; /* end of subject */ + if (anchor) break; + } + if (!changed) /* no changes? */ + lua_pushvalue(L, 1); /* return original string */ + else { /* something changed */ + luaL_addlstring(&b, src, ms.src_end-src); + luaL_pushresult(&b); /* create and return new string */ + } + lua_pushinteger(L, n); /* number of substitutions */ + return 2; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** STRING FORMAT +** ======================================================= +*/ + +#if !defined(lua_number2strx) /* { */ + +/* +** Hexadecimal floating-point formatter +*/ + +#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) + + +/* +** Number of bits that goes into the first digit. It can be any value +** between 1 and 4; the following definition tries to align the number +** to nibble boundaries by making what is left after that first digit a +** multiple of 4. +*/ +#define L_NBFD ((l_floatatt(MANT_DIG) - 1)%4 + 1) + + +/* +** Add integer part of 'x' to buffer and return new 'x' +*/ +static lua_Number adddigit (char *buff, int n, lua_Number x) { + lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */ + int d = (int)dd; + buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */ + return x - dd; /* return what is left */ +} + + +static int num2straux (char *buff, int sz, lua_Number x) { + /* if 'inf' or 'NaN', format it like '%g' */ + if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL) + return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x); + else if (x == 0) { /* can be -0... */ + /* create "0" or "-0" followed by exponent */ + return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", (LUAI_UACNUMBER)x); + } + else { + int e; + lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */ + int n = 0; /* character count */ + if (m < 0) { /* is number negative? */ + buff[n++] = '-'; /* add sign */ + m = -m; /* make it positive */ + } + buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */ + m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */ + e -= L_NBFD; /* this digit goes before the radix point */ + if (m > 0) { /* more digits? */ + buff[n++] = lua_getlocaledecpoint(); /* add radix point */ + do { /* add as many digits as needed */ + m = adddigit(buff, n++, m * 16); + } while (m > 0); + } + n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */ + lua_assert(n < sz); + return n; + } +} + + +static int lua_number2strx (lua_State *L, char *buff, int sz, + const char *fmt, lua_Number x) { + int n = num2straux(buff, sz, x); + if (fmt[SIZELENMOD] == 'A') { + int i; + for (i = 0; i < n; i++) + buff[i] = toupper(uchar(buff[i])); + } + else if (l_unlikely(fmt[SIZELENMOD] != 'a')) + return luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); + return n; +} + +#endif /* } */ + + +/* +** Maximum size for items formatted with '%f'. This size is produced +** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.', +** and '\0') + number of decimal digits to represent maxfloat (which +** is maximum exponent + 1). (99+3+1, adding some extra, 110) +*/ +#define MAX_ITEMF (110 + l_floatatt(MAX_10_EXP)) + + +/* +** All formats except '%f' do not need that large limit. The other +** float formats use exponents, so that they fit in the 99 limit for +** significant digits; 's' for large strings and 'q' add items directly +** to the buffer; all integer formats also fit in the 99 limit. The +** worst case are floats: they may need 99 significant digits, plus +** '0x', '-', '.', 'e+XXXX', and '\0'. Adding some extra, 120. +*/ +#define MAX_ITEM 120 + + +/* valid flags in a format specification */ +#if !defined(L_FMTFLAGS) +#define L_FMTFLAGS "-+ #0" +#endif + + +/* +** maximum size of each format specification (such as "%-099.99d") +*/ +#define MAX_FORMAT 32 + + +static void addquoted (luaL_Buffer *b, const char *s, size_t len) { + luaL_addchar(b, '"'); + while (len--) { + if (*s == '"' || *s == '\\' || *s == '\n') { + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); + } + else if (iscntrl(uchar(*s))) { + char buff[10]; + if (!isdigit(uchar(*(s+1)))) + l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); + else + l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); + luaL_addstring(b, buff); + } + else + luaL_addchar(b, *s); + s++; + } + luaL_addchar(b, '"'); +} + + +/* +** Serialize a floating-point number in such a way that it can be +** scanned back by Lua. Use hexadecimal format for "common" numbers +** (to preserve precision); inf, -inf, and NaN are handled separately. +** (NaN cannot be expressed as a numeral, so we write '(0/0)' for it.) +*/ +static int quotefloat (lua_State *L, char *buff, lua_Number n) { + const char *s; /* for the fixed representations */ + if (n == (lua_Number)HUGE_VAL) /* inf? */ + s = "1e9999"; + else if (n == -(lua_Number)HUGE_VAL) /* -inf? */ + s = "-1e9999"; + else if (n != n) /* NaN? */ + s = "(0/0)"; + else { /* format number as hexadecimal */ + int nb = lua_number2strx(L, buff, MAX_ITEM, + "%" LUA_NUMBER_FRMLEN "a", n); + /* ensures that 'buff' string uses a dot as the radix character */ + if (memchr(buff, '.', nb) == NULL) { /* no dot? */ + char point = lua_getlocaledecpoint(); /* try locale point */ + char *ppoint = (char *)memchr(buff, point, nb); + if (ppoint) *ppoint = '.'; /* change it to a dot */ + } + return nb; + } + /* for the fixed representations */ + return l_sprintf(buff, MAX_ITEM, "%s", s); +} + + +static void addliteral (lua_State *L, luaL_Buffer *b, int arg) { + switch (lua_type(L, arg)) { + case LUA_TSTRING: { + size_t len; + const char *s = lua_tolstring(L, arg, &len); + addquoted(b, s, len); + break; + } + case LUA_TNUMBER: { + char *buff = luaL_prepbuffsize(b, MAX_ITEM); + int nb; + if (!lua_isinteger(L, arg)) /* float? */ + nb = quotefloat(L, buff, lua_tonumber(L, arg)); + else { /* integers */ + lua_Integer n = lua_tointeger(L, arg); + const char *format = (n == LUA_MININTEGER) /* corner case? */ + ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hex */ + : LUA_INTEGER_FMT; /* else use default format */ + nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n); + } + luaL_addsize(b, nb); + break; + } + case LUA_TNIL: case LUA_TBOOLEAN: { + luaL_tolstring(L, arg, NULL); + luaL_addvalue(b); + break; + } + default: { + luaL_argerror(L, arg, "value has no literal form"); + } + } +} + + +static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { + const char *p = strfrmt; + while (*p != '\0' && strchr(L_FMTFLAGS, *p) != NULL) p++; /* skip flags */ + if ((size_t)(p - strfrmt) >= sizeof(L_FMTFLAGS)/sizeof(char)) + luaL_error(L, "invalid format (repeated flags)"); + if (isdigit(uchar(*p))) p++; /* skip width */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + if (*p == '.') { + p++; + if (isdigit(uchar(*p))) p++; /* skip precision */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + *(form++) = '%'; + memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char)); + form += (p - strfrmt) + 1; + *form = '\0'; + return p; +} + + +/* +** add length modifier into formats +*/ +static void addlenmod (char *form, const char *lenmod) { + size_t l = strlen(form); + size_t lm = strlen(lenmod); + char spec = form[l - 1]; + strcpy(form + l - 1, lenmod); + form[l + lm - 1] = spec; + form[l + lm] = '\0'; +} + + +static int str_format (lua_State *L) { + int top = lua_gettop(L); + int arg = 1; + size_t sfl; + const char *strfrmt = luaL_checklstring(L, arg, &sfl); + const char *strfrmt_end = strfrmt+sfl; + luaL_Buffer b; + luaL_buffinit(L, &b); + while (strfrmt < strfrmt_end) { + if (*strfrmt != L_ESC) + luaL_addchar(&b, *strfrmt++); + else if (*++strfrmt == L_ESC) + luaL_addchar(&b, *strfrmt++); /* %% */ + else { /* format item */ + char form[MAX_FORMAT]; /* to store the format ('%...') */ + int maxitem = MAX_ITEM; + char *buff = luaL_prepbuffsize(&b, maxitem); /* to put formatted item */ + int nb = 0; /* number of bytes in added item */ + if (++arg > top) + return luaL_argerror(L, arg, "no value"); + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) { + case 'c': { + nb = l_sprintf(buff, maxitem, form, (int)luaL_checkinteger(L, arg)); + break; + } + case 'd': case 'i': + case 'o': case 'u': case 'x': case 'X': { + lua_Integer n = luaL_checkinteger(L, arg); + addlenmod(form, LUA_INTEGER_FRMLEN); + nb = l_sprintf(buff, maxitem, form, (LUAI_UACINT)n); + break; + } + case 'a': case 'A': + addlenmod(form, LUA_NUMBER_FRMLEN); + nb = lua_number2strx(L, buff, maxitem, form, + luaL_checknumber(L, arg)); + break; + case 'f': + maxitem = MAX_ITEMF; /* extra space for '%f' */ + buff = luaL_prepbuffsize(&b, maxitem); + /* FALLTHROUGH */ + case 'e': case 'E': case 'g': case 'G': { + lua_Number n = luaL_checknumber(L, arg); + addlenmod(form, LUA_NUMBER_FRMLEN); + nb = l_sprintf(buff, maxitem, form, (LUAI_UACNUMBER)n); + break; + } + case 'p': { + const void *p = lua_topointer(L, arg); + if (p == NULL) { /* avoid calling 'printf' with argument NULL */ + p = "(null)"; /* result */ + form[strlen(form) - 1] = 's'; /* format it as a string */ + } + nb = l_sprintf(buff, maxitem, form, p); + break; + } + case 'q': { + if (form[2] != '\0') /* modifiers? */ + return luaL_error(L, "specifier '%%q' cannot have modifiers"); + addliteral(L, &b, arg); + break; + } + case 's': { + size_t l; + const char *s = luaL_tolstring(L, arg, &l); + if (form[2] == '\0') /* no modifiers? */ + luaL_addvalue(&b); /* keep entire string */ + else { + luaL_argcheck(L, l == strlen(s), arg, "string contains zeros"); + if (!strchr(form, '.') && l >= 100) { + /* no precision and string is too long to be formatted */ + luaL_addvalue(&b); /* keep entire string */ + } + else { /* format the string into 'buff' */ + nb = l_sprintf(buff, maxitem, form, s); + lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ + } + } + break; + } + default: { /* also treat cases 'pnLlh' */ + return luaL_error(L, "invalid conversion '%s' to 'format'", form); + } + } + lua_assert(nb < maxitem); + luaL_addsize(&b, nb); + } + } + luaL_pushresult(&b); + return 1; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** PACK/UNPACK +** ======================================================= +*/ + + +/* value used for padding */ +#if !defined(LUAL_PACKPADBYTE) +#define LUAL_PACKPADBYTE 0x00 +#endif + +/* maximum size for the binary representation of an integer */ +#define MAXINTSIZE 16 + +/* number of bits in a character */ +#define NB CHAR_BIT + +/* mask for one character (NB 1's) */ +#define MC ((1 << NB) - 1) + +/* size of a lua_Integer */ +#define SZINT ((int)sizeof(lua_Integer)) + + +/* dummy union to get native endianness */ +static const union { + int dummy; + char little; /* true iff machine is little endian */ +} nativeendian = {1}; + + +/* dummy structure to get native alignment requirements */ +struct cD { + char c; + union { double d; void *p; lua_Integer i; lua_Number n; } u; +}; + +#define MAXALIGN (offsetof(struct cD, u)) + + +/* +** information to pack/unpack stuff +*/ +typedef struct Header { + lua_State *L; + int islittle; + int maxalign; +} Header; + + +/* +** options for pack/unpack +*/ +typedef enum KOption { + Kint, /* signed integers */ + Kuint, /* unsigned integers */ + Kfloat, /* single-precision floating-point numbers */ + Knumber, /* Lua "native" floating-point numbers */ + Kdouble, /* double-precision floating-point numbers */ + Kchar, /* fixed-length strings */ + Kstring, /* strings with prefixed length */ + Kzstr, /* zero-terminated strings */ + Kpadding, /* padding */ + Kpaddalign, /* padding for alignment */ + Knop /* no-op (configuration or spaces) */ +} KOption; + + +/* +** Read an integer numeral from string 'fmt' or return 'df' if +** there is no numeral +*/ +static int digit (int c) { return '0' <= c && c <= '9'; } + +static int getnum (const char **fmt, int df) { + if (!digit(**fmt)) /* no number? */ + return df; /* return default value */ + else { + int a = 0; + do { + a = a*10 + (*((*fmt)++) - '0'); + } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10); + return a; + } +} + + +/* +** Read an integer numeral and raises an error if it is larger +** than the maximum size for integers. +*/ +static int getnumlimit (Header *h, const char **fmt, int df) { + int sz = getnum(fmt, df); + if (l_unlikely(sz > MAXINTSIZE || sz <= 0)) + return luaL_error(h->L, "integral size (%d) out of limits [1,%d]", + sz, MAXINTSIZE); + return sz; +} + + +/* +** Initialize Header +*/ +static void initheader (lua_State *L, Header *h) { + h->L = L; + h->islittle = nativeendian.little; + h->maxalign = 1; +} + + +/* +** Read and classify next option. 'size' is filled with option's size. +*/ +static KOption getoption (Header *h, const char **fmt, int *size) { + int opt = *((*fmt)++); + *size = 0; /* default */ + switch (opt) { + case 'b': *size = sizeof(char); return Kint; + case 'B': *size = sizeof(char); return Kuint; + case 'h': *size = sizeof(short); return Kint; + case 'H': *size = sizeof(short); return Kuint; + case 'l': *size = sizeof(long); return Kint; + case 'L': *size = sizeof(long); return Kuint; + case 'j': *size = sizeof(lua_Integer); return Kint; + case 'J': *size = sizeof(lua_Integer); return Kuint; + case 'T': *size = sizeof(size_t); return Kuint; + case 'f': *size = sizeof(float); return Kfloat; + case 'n': *size = sizeof(lua_Number); return Knumber; + case 'd': *size = sizeof(double); return Kdouble; + case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint; + case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; + case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; + case 'c': + *size = getnum(fmt, -1); + if (l_unlikely(*size == -1)) + luaL_error(h->L, "missing size for format option 'c'"); + return Kchar; + case 'z': return Kzstr; + case 'x': *size = 1; return Kpadding; + case 'X': return Kpaddalign; + case ' ': break; + case '<': h->islittle = 1; break; + case '>': h->islittle = 0; break; + case '=': h->islittle = nativeendian.little; break; + case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break; + default: luaL_error(h->L, "invalid format option '%c'", opt); + } + return Knop; +} + + +/* +** Read, classify, and fill other details about the next option. +** 'psize' is filled with option's size, 'notoalign' with its +** alignment requirements. +** Local variable 'size' gets the size to be aligned. (Kpadal option +** always gets its full alignment, other options are limited by +** the maximum alignment ('maxalign'). Kchar option needs no alignment +** despite its size. +*/ +static KOption getdetails (Header *h, size_t totalsize, + const char **fmt, int *psize, int *ntoalign) { + KOption opt = getoption(h, fmt, psize); + int align = *psize; /* usually, alignment follows size */ + if (opt == Kpaddalign) { /* 'X' gets alignment from following option */ + if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) + luaL_argerror(h->L, 1, "invalid next option for option 'X'"); + } + if (align <= 1 || opt == Kchar) /* need no alignment? */ + *ntoalign = 0; + else { + if (align > h->maxalign) /* enforce maximum alignment */ + align = h->maxalign; + if (l_unlikely((align & (align - 1)) != 0)) /* not a power of 2? */ + luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); + *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); + } + return opt; +} + + +/* +** Pack integer 'n' with 'size' bytes and 'islittle' endianness. +** The final 'if' handles the case when 'size' is larger than +** the size of a Lua integer, correcting the extra sign-extension +** bytes if necessary (by default they would be zeros). +*/ +static void packint (luaL_Buffer *b, lua_Unsigned n, + int islittle, int size, int neg) { + char *buff = luaL_prepbuffsize(b, size); + int i; + buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */ + for (i = 1; i < size; i++) { + n >>= NB; + buff[islittle ? i : size - 1 - i] = (char)(n & MC); + } + if (neg && size > SZINT) { /* negative number need sign extension? */ + for (i = SZINT; i < size; i++) /* correct extra bytes */ + buff[islittle ? i : size - 1 - i] = (char)MC; + } + luaL_addsize(b, size); /* add result to buffer */ +} + + +/* +** Copy 'size' bytes from 'src' to 'dest', correcting endianness if +** given 'islittle' is different from native endianness. +*/ +static void copywithendian (char *dest, const char *src, + int size, int islittle) { + if (islittle == nativeendian.little) + memcpy(dest, src, size); + else { + dest += size - 1; + while (size-- != 0) + *(dest--) = *(src++); + } +} + + +static int str_pack (lua_State *L) { + luaL_Buffer b; + Header h; + const char *fmt = luaL_checkstring(L, 1); /* format string */ + int arg = 1; /* current argument to pack */ + size_t totalsize = 0; /* accumulate total size of result */ + initheader(L, &h); + lua_pushnil(L); /* mark to separate arguments from string buffer */ + luaL_buffinit(L, &b); + while (*fmt != '\0') { + int size, ntoalign; + KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); + totalsize += ntoalign + size; + while (ntoalign-- > 0) + luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ + arg++; + switch (opt) { + case Kint: { /* signed integers */ + lua_Integer n = luaL_checkinteger(L, arg); + if (size < SZINT) { /* need overflow check? */ + lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); + luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); + } + packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); + break; + } + case Kuint: { /* unsigned integers */ + lua_Integer n = luaL_checkinteger(L, arg); + if (size < SZINT) /* need overflow check? */ + luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), + arg, "unsigned overflow"); + packint(&b, (lua_Unsigned)n, h.islittle, size, 0); + break; + } + case Kfloat: { /* C float */ + float f = (float)luaL_checknumber(L, arg); /* get argument */ + char *buff = luaL_prepbuffsize(&b, sizeof(f)); + /* move 'f' to final result, correcting endianness if needed */ + copywithendian(buff, (char *)&f, sizeof(f), h.islittle); + luaL_addsize(&b, size); + break; + } + case Knumber: { /* Lua float */ + lua_Number f = luaL_checknumber(L, arg); /* get argument */ + char *buff = luaL_prepbuffsize(&b, sizeof(f)); + /* move 'f' to final result, correcting endianness if needed */ + copywithendian(buff, (char *)&f, sizeof(f), h.islittle); + luaL_addsize(&b, size); + break; + } + case Kdouble: { /* C double */ + double f = (double)luaL_checknumber(L, arg); /* get argument */ + char *buff = luaL_prepbuffsize(&b, sizeof(f)); + /* move 'f' to final result, correcting endianness if needed */ + copywithendian(buff, (char *)&f, sizeof(f), h.islittle); + luaL_addsize(&b, size); + break; + } + case Kchar: { /* fixed-size string */ + size_t len; + const char *s = luaL_checklstring(L, arg, &len); + luaL_argcheck(L, len <= (size_t)size, arg, + "string longer than given size"); + luaL_addlstring(&b, s, len); /* add string */ + while (len++ < (size_t)size) /* pad extra space */ + luaL_addchar(&b, LUAL_PACKPADBYTE); + break; + } + case Kstring: { /* strings with length count */ + size_t len; + const char *s = luaL_checklstring(L, arg, &len); + luaL_argcheck(L, size >= (int)sizeof(size_t) || + len < ((size_t)1 << (size * NB)), + arg, "string length does not fit in given size"); + packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */ + luaL_addlstring(&b, s, len); + totalsize += len; + break; + } + case Kzstr: { /* zero-terminated string */ + size_t len; + const char *s = luaL_checklstring(L, arg, &len); + luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros"); + luaL_addlstring(&b, s, len); + luaL_addchar(&b, '\0'); /* add zero at the end */ + totalsize += len + 1; + break; + } + case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */ + case Kpaddalign: case Knop: + arg--; /* undo increment */ + break; + } + } + luaL_pushresult(&b); + return 1; +} + + +static int str_packsize (lua_State *L) { + Header h; + const char *fmt = luaL_checkstring(L, 1); /* format string */ + size_t totalsize = 0; /* accumulate total size of result */ + initheader(L, &h); + while (*fmt != '\0') { + int size, ntoalign; + KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); + luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1, + "variable-length format"); + size += ntoalign; /* total space used by option */ + luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, + "format result too large"); + totalsize += size; + } + lua_pushinteger(L, (lua_Integer)totalsize); + return 1; +} + + +/* +** Unpack an integer with 'size' bytes and 'islittle' endianness. +** If size is smaller than the size of a Lua integer and integer +** is signed, must do sign extension (propagating the sign to the +** higher bits); if size is larger than the size of a Lua integer, +** it must check the unread bytes to see whether they do not cause an +** overflow. +*/ +static lua_Integer unpackint (lua_State *L, const char *str, + int islittle, int size, int issigned) { + lua_Unsigned res = 0; + int i; + int limit = (size <= SZINT) ? size : SZINT; + for (i = limit - 1; i >= 0; i--) { + res <<= NB; + res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i]; + } + if (size < SZINT) { /* real size smaller than lua_Integer? */ + if (issigned) { /* needs sign extension? */ + lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1); + res = ((res ^ mask) - mask); /* do sign extension */ + } + } + else if (size > SZINT) { /* must check unread bytes */ + int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC; + for (i = limit; i < size; i++) { + if (l_unlikely((unsigned char)str[islittle ? i : size - 1 - i] != mask)) + luaL_error(L, "%d-byte integer does not fit into Lua Integer", size); + } + } + return (lua_Integer)res; +} + + +static int str_unpack (lua_State *L) { + Header h; + const char *fmt = luaL_checkstring(L, 1); + size_t ld; + const char *data = luaL_checklstring(L, 2, &ld); + size_t pos = posrelatI(luaL_optinteger(L, 3, 1), ld) - 1; + int n = 0; /* number of results */ + luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); + initheader(L, &h); + while (*fmt != '\0') { + int size, ntoalign; + KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); + luaL_argcheck(L, (size_t)ntoalign + size <= ld - pos, 2, + "data string too short"); + pos += ntoalign; /* skip alignment */ + /* stack space for item + next position */ + luaL_checkstack(L, 2, "too many results"); + n++; + switch (opt) { + case Kint: + case Kuint: { + lua_Integer res = unpackint(L, data + pos, h.islittle, size, + (opt == Kint)); + lua_pushinteger(L, res); + break; + } + case Kfloat: { + float f; + copywithendian((char *)&f, data + pos, sizeof(f), h.islittle); + lua_pushnumber(L, (lua_Number)f); + break; + } + case Knumber: { + lua_Number f; + copywithendian((char *)&f, data + pos, sizeof(f), h.islittle); + lua_pushnumber(L, f); + break; + } + case Kdouble: { + double f; + copywithendian((char *)&f, data + pos, sizeof(f), h.islittle); + lua_pushnumber(L, (lua_Number)f); + break; + } + case Kchar: { + lua_pushlstring(L, data + pos, size); + break; + } + case Kstring: { + size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); + luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short"); + lua_pushlstring(L, data + pos + size, len); + pos += len; /* skip string */ + break; + } + case Kzstr: { + size_t len = strlen(data + pos); + luaL_argcheck(L, pos + len < ld, 2, + "unfinished string for format 'z'"); + lua_pushlstring(L, data + pos, len); + pos += len + 1; /* skip string plus final '\0' */ + break; + } + case Kpaddalign: case Kpadding: case Knop: + n--; /* undo increment */ + break; + } + pos += size; + } + lua_pushinteger(L, pos + 1); /* next position */ + return n + 1; +} + +/* }====================================================== */ + + +static const luaL_Reg strlib[] = { + {"byte", str_byte}, + {"char", str_char}, + {"dump", str_dump}, + {"find", str_find}, + {"format", str_format}, + {"gmatch", gmatch}, + {"gsub", str_gsub}, + {"len", str_len}, + {"lower", str_lower}, + {"match", str_match}, + {"rep", str_rep}, + {"reverse", str_reverse}, + {"sub", str_sub}, + {"upper", str_upper}, + {"pack", str_pack}, + {"packsize", str_packsize}, + {"unpack", str_unpack}, + {NULL, NULL} +}; + + +static void createmetatable (lua_State *L) { + /* table to be metatable for strings */ + luaL_newlibtable(L, stringmetamethods); + luaL_setfuncs(L, stringmetamethods, 0); + lua_pushliteral(L, ""); /* dummy string */ + lua_pushvalue(L, -2); /* copy table */ + lua_setmetatable(L, -2); /* set table as metatable for strings */ + lua_pop(L, 1); /* pop dummy string */ + lua_pushvalue(L, -2); /* get string library */ + lua_setfield(L, -2, "__index"); /* metatable.__index = string */ + lua_pop(L, 1); /* pop metatable */ +} + + +/* +** Open string library +*/ +LUAMOD_API int luaopen_string (lua_State *L) { + luaL_newlib(L, strlib); + createmetatable(L); + return 1; +} + diff --git a/lua/ltable.c b/lua/ltable.c new file mode 100644 index 0000000..33c1ab3 --- /dev/null +++ b/lua/ltable.c @@ -0,0 +1,971 @@ +/* +** $Id: ltable.c $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + +#define ltable_c +#define LUA_CORE + +#include "lprefix.h" + + +/* +** Implementation of tables (aka arrays, objects, or hash tables). +** Tables keep its elements in two parts: an array part and a hash part. +** Non-negative integer keys are all candidates to be kept in the array +** part. The actual size of the array is the largest 'n' such that +** more than half the slots between 1 and n are in use. +** Hash uses a mix of chained scatter table with Brent's variation. +** A main invariant of these tables is that, if an element is not +** in its main position (i.e. the 'original' position that its hash gives +** to it), then the colliding element is in its own main position. +** Hence even when the load factor reaches 100%, performance remains good. +*/ + +#include +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lvm.h" + + +/* +** MAXABITS is the largest integer such that MAXASIZE fits in an +** unsigned int. +*/ +#define MAXABITS cast_int(sizeof(int) * CHAR_BIT - 1) + + +/* +** MAXASIZE is the maximum size of the array part. It is the minimum +** between 2^MAXABITS and the maximum size that, measured in bytes, +** fits in a 'size_t'. +*/ +#define MAXASIZE luaM_limitN(1u << MAXABITS, TValue) + +/* +** MAXHBITS is the largest integer such that 2^MAXHBITS fits in a +** signed int. +*/ +#define MAXHBITS (MAXABITS - 1) + + +/* +** MAXHSIZE is the maximum size of the hash part. It is the minimum +** between 2^MAXHBITS and the maximum size such that, measured in bytes, +** it fits in a 'size_t'. +*/ +#define MAXHSIZE luaM_limitN(1u << MAXHBITS, Node) + + +/* +** When the original hash value is good, hashing by a power of 2 +** avoids the cost of '%'. +*/ +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) + +/* +** for other types, it is better to avoid modulo by power of 2, as +** they can have many 2 factors. +*/ +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) + + +#define hashstr(t,str) hashpow2(t, (str)->hash) +#define hashboolean(t,p) hashpow2(t, p) + +#define hashint(t,i) hashpow2(t, i) + + +#define hashpointer(t,p) hashmod(t, point2uint(p)) + + +#define dummynode (&dummynode_) + +static const Node dummynode_ = { + {{NULL}, LUA_VEMPTY, /* value's value and type */ + LUA_VNIL, 0, {NULL}} /* key type, next, and key value */ +}; + + +static const TValue absentkey = {ABSTKEYCONSTANT}; + + + +/* +** Hash for floating-point numbers. +** The main computation should be just +** n = frexp(n, &i); return (n * INT_MAX) + i +** but there are some numerical subtleties. +** In a two-complement representation, INT_MAX does not has an exact +** representation as a float, but INT_MIN does; because the absolute +** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the +** absolute value of the product 'frexp * -INT_MIN' is smaller or equal +** to INT_MAX. Next, the use of 'unsigned int' avoids overflows when +** adding 'i'; the use of '~u' (instead of '-u') avoids problems with +** INT_MIN. +*/ +#if !defined(l_hashfloat) +static int l_hashfloat (lua_Number n) { + int i; + lua_Integer ni; + n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN); + if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */ + lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == cast_num(HUGE_VAL)); + return 0; + } + else { /* normal case */ + unsigned int u = cast_uint(i) + cast_uint(ni); + return cast_int(u <= cast_uint(INT_MAX) ? u : ~u); + } +} +#endif + + +/* +** returns the 'main' position of an element in a table (that is, +** the index of its hash value). The key comes broken (tag in 'ktt' +** and value in 'vkl') so that we can call it on keys inserted into +** nodes. +*/ +static Node *mainposition (const Table *t, int ktt, const Value *kvl) { + switch (withvariant(ktt)) { + case LUA_VNUMINT: { + lua_Integer key = ivalueraw(*kvl); + return hashint(t, key); + } + case LUA_VNUMFLT: { + lua_Number n = fltvalueraw(*kvl); + return hashmod(t, l_hashfloat(n)); + } + case LUA_VSHRSTR: { + TString *ts = tsvalueraw(*kvl); + return hashstr(t, ts); + } + case LUA_VLNGSTR: { + TString *ts = tsvalueraw(*kvl); + return hashpow2(t, luaS_hashlongstr(ts)); + } + case LUA_VFALSE: + return hashboolean(t, 0); + case LUA_VTRUE: + return hashboolean(t, 1); + case LUA_VLIGHTUSERDATA: { + void *p = pvalueraw(*kvl); + return hashpointer(t, p); + } + case LUA_VLCF: { + lua_CFunction f = fvalueraw(*kvl); + return hashpointer(t, f); + } + default: { + GCObject *o = gcvalueraw(*kvl); + return hashpointer(t, o); + } + } +} + + +/* +** Returns the main position of an element given as a 'TValue' +*/ +static Node *mainpositionTV (const Table *t, const TValue *key) { + return mainposition(t, rawtt(key), valraw(key)); +} + + +/* +** Check whether key 'k1' is equal to the key in node 'n2'. This +** equality is raw, so there are no metamethods. Floats with integer +** values have been normalized, so integers cannot be equal to +** floats. It is assumed that 'eqshrstr' is simply pointer equality, so +** that short strings are handled in the default case. +** A true 'deadok' means to accept dead keys as equal to their original +** values. All dead keys are compared in the default case, by pointer +** identity. (Only collectable objects can produce dead keys.) Note that +** dead long strings are also compared by identity. +** Once a key is dead, its corresponding value may be collected, and +** then another value can be created with the same address. If this +** other value is given to 'next', 'equalkey' will signal a false +** positive. In a regular traversal, this situation should never happen, +** as all keys given to 'next' came from the table itself, and therefore +** could not have been collected. Outside a regular traversal, we +** have garbage in, garbage out. What is relevant is that this false +** positive does not break anything. (In particular, 'next' will return +** some other valid item on the table or nil.) +*/ +static int equalkey (const TValue *k1, const Node *n2, int deadok) { + if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */ + !(deadok && keyisdead(n2) && iscollectable(k1))) + return 0; /* cannot be same key */ + switch (keytt(n2)) { + case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: + return 1; + case LUA_VNUMINT: + return (ivalue(k1) == keyival(n2)); + case LUA_VNUMFLT: + return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2))); + case LUA_VLIGHTUSERDATA: + return pvalue(k1) == pvalueraw(keyval(n2)); + case LUA_VLCF: + return fvalue(k1) == fvalueraw(keyval(n2)); + case ctb(LUA_VLNGSTR): + return luaS_eqlngstr(tsvalue(k1), keystrval(n2)); + default: + return gcvalue(k1) == gcvalueraw(keyval(n2)); + } +} + + +/* +** True if value of 'alimit' is equal to the real size of the array +** part of table 't'. (Otherwise, the array part must be larger than +** 'alimit'.) +*/ +#define limitequalsasize(t) (isrealasize(t) || ispow2((t)->alimit)) + + +/* +** Returns the real size of the 'array' array +*/ +LUAI_FUNC unsigned int luaH_realasize (const Table *t) { + if (limitequalsasize(t)) + return t->alimit; /* this is the size */ + else { + unsigned int size = t->alimit; + /* compute the smallest power of 2 not smaller than 'n' */ + size |= (size >> 1); + size |= (size >> 2); + size |= (size >> 4); + size |= (size >> 8); + size |= (size >> 16); +#if (UINT_MAX >> 30) > 3 + size |= (size >> 32); /* unsigned int has more than 32 bits */ +#endif + size++; + lua_assert(ispow2(size) && size/2 < t->alimit && t->alimit < size); + return size; + } +} + + +/* +** Check whether real size of the array is a power of 2. +** (If it is not, 'alimit' cannot be changed to any other value +** without changing the real size.) +*/ +static int ispow2realasize (const Table *t) { + return (!isrealasize(t) || ispow2(t->alimit)); +} + + +static unsigned int setlimittosize (Table *t) { + t->alimit = luaH_realasize(t); + setrealasize(t); + return t->alimit; +} + + +#define limitasasize(t) check_exp(isrealasize(t), t->alimit) + + + +/* +** "Generic" get version. (Not that generic: not valid for integers, +** which may be in array part, nor for floats with integral values.) +** See explanation about 'deadok' in function 'equalkey'. +*/ +static const TValue *getgeneric (Table *t, const TValue *key, int deadok) { + Node *n = mainpositionTV(t, key); + for (;;) { /* check whether 'key' is somewhere in the chain */ + if (equalkey(key, n, deadok)) + return gval(n); /* that's it */ + else { + int nx = gnext(n); + if (nx == 0) + return &absentkey; /* not found */ + n += nx; + } + } +} + + +/* +** returns the index for 'k' if 'k' is an appropriate key to live in +** the array part of a table, 0 otherwise. +*/ +static unsigned int arrayindex (lua_Integer k) { + if (l_castS2U(k) - 1u < MAXASIZE) /* 'k' in [1, MAXASIZE]? */ + return cast_uint(k); /* 'key' is an appropriate array index */ + else + return 0; +} + + +/* +** returns the index of a 'key' for table traversals. First goes all +** elements in the array part, then elements in the hash part. The +** beginning of a traversal is signaled by 0. +*/ +static unsigned int findindex (lua_State *L, Table *t, TValue *key, + unsigned int asize) { + unsigned int i; + if (ttisnil(key)) return 0; /* first iteration */ + i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0; + if (i - 1u < asize) /* is 'key' inside array part? */ + return i; /* yes; that's the index */ + else { + const TValue *n = getgeneric(t, key, 1); + if (l_unlikely(isabstkey(n))) + luaG_runerror(L, "invalid key to 'next'"); /* key not found */ + i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */ + /* hash elements are numbered after array ones */ + return (i + 1) + asize; + } +} + + +int luaH_next (lua_State *L, Table *t, StkId key) { + unsigned int asize = luaH_realasize(t); + unsigned int i = findindex(L, t, s2v(key), asize); /* find original key */ + for (; i < asize; i++) { /* try first array part */ + if (!isempty(&t->array[i])) { /* a non-empty entry? */ + setivalue(s2v(key), i + 1); + setobj2s(L, key + 1, &t->array[i]); + return 1; + } + } + for (i -= asize; cast_int(i) < sizenode(t); i++) { /* hash part */ + if (!isempty(gval(gnode(t, i)))) { /* a non-empty entry? */ + Node *n = gnode(t, i); + getnodekey(L, s2v(key), n); + setobj2s(L, key + 1, gval(n)); + return 1; + } + } + return 0; /* no more elements */ +} + + +static void freehash (lua_State *L, Table *t) { + if (!isdummy(t)) + luaM_freearray(L, t->node, cast_sizet(sizenode(t))); +} + + +/* +** {============================================================= +** Rehash +** ============================================================== +*/ + +/* +** Compute the optimal size for the array part of table 't'. 'nums' is a +** "count array" where 'nums[i]' is the number of integers in the table +** between 2^(i - 1) + 1 and 2^i. 'pna' enters with the total number of +** integer keys in the table and leaves with the number of keys that +** will go to the array part; return the optimal size. (The condition +** 'twotoi > 0' in the for loop stops the loop if 'twotoi' overflows.) +*/ +static unsigned int computesizes (unsigned int nums[], unsigned int *pna) { + int i; + unsigned int twotoi; /* 2^i (candidate for optimal size) */ + unsigned int a = 0; /* number of elements smaller than 2^i */ + unsigned int na = 0; /* number of elements to go to array part */ + unsigned int optimal = 0; /* optimal size for array part */ + /* loop while keys can fill more than half of total size */ + for (i = 0, twotoi = 1; + twotoi > 0 && *pna > twotoi / 2; + i++, twotoi *= 2) { + a += nums[i]; + if (a > twotoi/2) { /* more than half elements present? */ + optimal = twotoi; /* optimal size (till now) */ + na = a; /* all elements up to 'optimal' will go to array part */ + } + } + lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal); + *pna = na; + return optimal; +} + + +static int countint (lua_Integer key, unsigned int *nums) { + unsigned int k = arrayindex(key); + if (k != 0) { /* is 'key' an appropriate array index? */ + nums[luaO_ceillog2(k)]++; /* count as such */ + return 1; + } + else + return 0; +} + + +/* +** Count keys in array part of table 't': Fill 'nums[i]' with +** number of keys that will go into corresponding slice and return +** total number of non-nil keys. +*/ +static unsigned int numusearray (const Table *t, unsigned int *nums) { + int lg; + unsigned int ttlg; /* 2^lg */ + unsigned int ause = 0; /* summation of 'nums' */ + unsigned int i = 1; /* count to traverse all array keys */ + unsigned int asize = limitasasize(t); /* real array size */ + /* traverse each slice */ + for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) { + unsigned int lc = 0; /* counter */ + unsigned int lim = ttlg; + if (lim > asize) { + lim = asize; /* adjust upper limit */ + if (i > lim) + break; /* no more elements to count */ + } + /* count elements in range (2^(lg - 1), 2^lg] */ + for (; i <= lim; i++) { + if (!isempty(&t->array[i-1])) + lc++; + } + nums[lg] += lc; + ause += lc; + } + return ause; +} + + +static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { + int totaluse = 0; /* total number of elements */ + int ause = 0; /* elements added to 'nums' (can go to array part) */ + int i = sizenode(t); + while (i--) { + Node *n = &t->node[i]; + if (!isempty(gval(n))) { + if (keyisinteger(n)) + ause += countint(keyival(n), nums); + totaluse++; + } + } + *pna += ause; + return totaluse; +} + + +/* +** Creates an array for the hash part of a table with the given +** size, or reuses the dummy node if size is zero. +** The computation for size overflow is in two steps: the first +** comparison ensures that the shift in the second one does not +** overflow. +*/ +static void setnodevector (lua_State *L, Table *t, unsigned int size) { + if (size == 0) { /* no elements to hash part? */ + t->node = cast(Node *, dummynode); /* use common 'dummynode' */ + t->lsizenode = 0; + t->lastfree = NULL; /* signal that it is using dummy node */ + } + else { + int i; + int lsize = luaO_ceillog2(size); + if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE) + luaG_runerror(L, "table overflow"); + size = twoto(lsize); + t->node = luaM_newvector(L, size, Node); + for (i = 0; i < (int)size; i++) { + Node *n = gnode(t, i); + gnext(n) = 0; + setnilkey(n); + setempty(gval(n)); + } + t->lsizenode = cast_byte(lsize); + t->lastfree = gnode(t, size); /* all positions are free */ + } +} + + +/* +** (Re)insert all elements from the hash part of 'ot' into table 't'. +*/ +static void reinsert (lua_State *L, Table *ot, Table *t) { + int j; + int size = sizenode(ot); + for (j = 0; j < size; j++) { + Node *old = gnode(ot, j); + if (!isempty(gval(old))) { + /* doesn't need barrier/invalidate cache, as entry was + already present in the table */ + TValue k; + getnodekey(L, &k, old); + luaH_set(L, t, &k, gval(old)); + } + } +} + + +/* +** Exchange the hash part of 't1' and 't2'. +*/ +static void exchangehashpart (Table *t1, Table *t2) { + lu_byte lsizenode = t1->lsizenode; + Node *node = t1->node; + Node *lastfree = t1->lastfree; + t1->lsizenode = t2->lsizenode; + t1->node = t2->node; + t1->lastfree = t2->lastfree; + t2->lsizenode = lsizenode; + t2->node = node; + t2->lastfree = lastfree; +} + + +/* +** Resize table 't' for the new given sizes. Both allocations (for +** the hash part and for the array part) can fail, which creates some +** subtleties. If the first allocation, for the hash part, fails, an +** error is raised and that is it. Otherwise, it copies the elements from +** the shrinking part of the array (if it is shrinking) into the new +** hash. Then it reallocates the array part. If that fails, the table +** is in its original state; the function frees the new hash part and then +** raises the allocation error. Otherwise, it sets the new hash part +** into the table, initializes the new part of the array (if any) with +** nils and reinserts the elements of the old hash back into the new +** parts of the table. +*/ +void luaH_resize (lua_State *L, Table *t, unsigned int newasize, + unsigned int nhsize) { + unsigned int i; + Table newt; /* to keep the new hash part */ + unsigned int oldasize = setlimittosize(t); + TValue *newarray; + /* create new hash part with appropriate size into 'newt' */ + setnodevector(L, &newt, nhsize); + if (newasize < oldasize) { /* will array shrink? */ + t->alimit = newasize; /* pretend array has new size... */ + exchangehashpart(t, &newt); /* and new hash */ + /* re-insert into the new hash the elements from vanishing slice */ + for (i = newasize; i < oldasize; i++) { + if (!isempty(&t->array[i])) + luaH_setint(L, t, i + 1, &t->array[i]); + } + t->alimit = oldasize; /* restore current size... */ + exchangehashpart(t, &newt); /* and hash (in case of errors) */ + } + /* allocate new array */ + newarray = luaM_reallocvector(L, t->array, oldasize, newasize, TValue); + if (l_unlikely(newarray == NULL && newasize > 0)) { /* allocation failed? */ + freehash(L, &newt); /* release new hash part */ + luaM_error(L); /* raise error (with array unchanged) */ + } + /* allocation ok; initialize new part of the array */ + exchangehashpart(t, &newt); /* 't' has the new hash ('newt' has the old) */ + t->array = newarray; /* set new array part */ + t->alimit = newasize; + for (i = oldasize; i < newasize; i++) /* clear new slice of the array */ + setempty(&t->array[i]); + /* re-insert elements from old hash part into new parts */ + reinsert(L, &newt, t); /* 'newt' now has the old hash */ + freehash(L, &newt); /* free old hash part */ +} + + +void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) { + int nsize = allocsizenode(t); + luaH_resize(L, t, nasize, nsize); +} + +/* +** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i +*/ +static void rehash (lua_State *L, Table *t, const TValue *ek) { + unsigned int asize; /* optimal size for array part */ + unsigned int na; /* number of keys in the array part */ + unsigned int nums[MAXABITS + 1]; + int i; + int totaluse; + for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */ + setlimittosize(t); + na = numusearray(t, nums); /* count keys in array part */ + totaluse = na; /* all those keys are integer keys */ + totaluse += numusehash(t, nums, &na); /* count keys in hash part */ + /* count extra key */ + if (ttisinteger(ek)) + na += countint(ivalue(ek), nums); + totaluse++; + /* compute new size for array part */ + asize = computesizes(nums, &na); + /* resize the table to new computed sizes */ + luaH_resize(L, t, asize, totaluse - na); +} + + + +/* +** }============================================================= +*/ + + +Table *luaH_new (lua_State *L) { + GCObject *o = luaC_newobj(L, LUA_VTABLE, sizeof(Table)); + Table *t = gco2t(o); + t->metatable = NULL; + t->flags = cast_byte(maskflags); /* table has no metamethod fields */ + t->array = NULL; + t->alimit = 0; + setnodevector(L, t, 0); + return t; +} + + +void luaH_free (lua_State *L, Table *t) { + freehash(L, t); + luaM_freearray(L, t->array, luaH_realasize(t)); + luaM_free(L, t); +} + + +static Node *getfreepos (Table *t) { + if (!isdummy(t)) { + while (t->lastfree > t->node) { + t->lastfree--; + if (keyisnil(t->lastfree)) + return t->lastfree; + } + } + return NULL; /* could not find a free place */ +} + + + +/* +** inserts a new key into a hash table; first, check whether key's main +** position is free. If not, check whether colliding node is in its main +** position or not: if it is not, move colliding node to an empty place and +** put new key in its main position; otherwise (colliding node is in its main +** position), new key goes to an empty position. +*/ +void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) { + Node *mp; + TValue aux; + if (l_unlikely(ttisnil(key))) + luaG_runerror(L, "table index is nil"); + else if (ttisfloat(key)) { + lua_Number f = fltvalue(key); + lua_Integer k; + if (luaV_flttointeger(f, &k, F2Ieq)) { /* does key fit in an integer? */ + setivalue(&aux, k); + key = &aux; /* insert it as an integer */ + } + else if (l_unlikely(luai_numisnan(f))) + luaG_runerror(L, "table index is NaN"); + } + if (ttisnil(value)) + return; /* do not insert nil values */ + mp = mainpositionTV(t, key); + if (!isempty(gval(mp)) || isdummy(t)) { /* main position is taken? */ + Node *othern; + Node *f = getfreepos(t); /* get a free place */ + if (f == NULL) { /* cannot find a free place? */ + rehash(L, t, key); /* grow table */ + /* whatever called 'newkey' takes care of TM cache */ + luaH_set(L, t, key, value); /* insert key into grown table */ + return; + } + lua_assert(!isdummy(t)); + othern = mainposition(t, keytt(mp), &keyval(mp)); + if (othern != mp) { /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ + while (othern + gnext(othern) != mp) /* find previous */ + othern += gnext(othern); + gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */ + *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + if (gnext(mp) != 0) { + gnext(f) += cast_int(mp - f); /* correct 'next' */ + gnext(mp) = 0; /* now 'mp' is free */ + } + setempty(gval(mp)); + } + else { /* colliding node is in its own main position */ + /* new node will go into free position */ + if (gnext(mp) != 0) + gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */ + else lua_assert(gnext(f) == 0); + gnext(mp) = cast_int(f - mp); + mp = f; + } + } + setnodekey(L, mp, key); + luaC_barrierback(L, obj2gco(t), key); + lua_assert(isempty(gval(mp))); + setobj2t(L, gval(mp), value); +} + + +/* +** Search function for integers. If integer is inside 'alimit', get it +** directly from the array part. Otherwise, if 'alimit' is not equal to +** the real size of the array, key still can be in the array part. In +** this case, try to avoid a call to 'luaH_realasize' when key is just +** one more than the limit (so that it can be incremented without +** changing the real size of the array). +*/ +const TValue *luaH_getint (Table *t, lua_Integer key) { + if (l_castS2U(key) - 1u < t->alimit) /* 'key' in [1, t->alimit]? */ + return &t->array[key - 1]; + else if (!limitequalsasize(t) && /* key still may be in the array part? */ + (l_castS2U(key) == t->alimit + 1 || + l_castS2U(key) - 1u < luaH_realasize(t))) { + t->alimit = cast_uint(key); /* probably '#t' is here now */ + return &t->array[key - 1]; + } + else { + Node *n = hashint(t, key); + for (;;) { /* check whether 'key' is somewhere in the chain */ + if (keyisinteger(n) && keyival(n) == key) + return gval(n); /* that's it */ + else { + int nx = gnext(n); + if (nx == 0) break; + n += nx; + } + } + return &absentkey; + } +} + + +/* +** search function for short strings +*/ +const TValue *luaH_getshortstr (Table *t, TString *key) { + Node *n = hashstr(t, key); + lua_assert(key->tt == LUA_VSHRSTR); + for (;;) { /* check whether 'key' is somewhere in the chain */ + if (keyisshrstr(n) && eqshrstr(keystrval(n), key)) + return gval(n); /* that's it */ + else { + int nx = gnext(n); + if (nx == 0) + return &absentkey; /* not found */ + n += nx; + } + } +} + + +const TValue *luaH_getstr (Table *t, TString *key) { + if (key->tt == LUA_VSHRSTR) + return luaH_getshortstr(t, key); + else { /* for long strings, use generic case */ + TValue ko; + setsvalue(cast(lua_State *, NULL), &ko, key); + return getgeneric(t, &ko, 0); + } +} + + +/* +** main search function +*/ +const TValue *luaH_get (Table *t, const TValue *key) { + switch (ttypetag(key)) { + case LUA_VSHRSTR: return luaH_getshortstr(t, tsvalue(key)); + case LUA_VNUMINT: return luaH_getint(t, ivalue(key)); + case LUA_VNIL: return &absentkey; + case LUA_VNUMFLT: { + lua_Integer k; + if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */ + return luaH_getint(t, k); /* use specialized version */ + /* else... */ + } /* FALLTHROUGH */ + default: + return getgeneric(t, key, 0); + } +} + + +/* +** Finish a raw "set table" operation, where 'slot' is where the value +** should have been (the result of a previous "get table"). +** Beware: when using this function you probably need to check a GC +** barrier and invalidate the TM cache. +*/ +void luaH_finishset (lua_State *L, Table *t, const TValue *key, + const TValue *slot, TValue *value) { + if (isabstkey(slot)) + luaH_newkey(L, t, key, value); + else + setobj2t(L, cast(TValue *, slot), value); +} + + +/* +** beware: when using this function you probably need to check a GC +** barrier and invalidate the TM cache. +*/ +void luaH_set (lua_State *L, Table *t, const TValue *key, TValue *value) { + const TValue *slot = luaH_get(t, key); + luaH_finishset(L, t, key, slot, value); +} + + +void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { + const TValue *p = luaH_getint(t, key); + if (isabstkey(p)) { + TValue k; + setivalue(&k, key); + luaH_newkey(L, t, &k, value); + } + else + setobj2t(L, cast(TValue *, p), value); +} + + +/* +** Try to find a boundary in the hash part of table 't'. From the +** caller, we know that 'j' is zero or present and that 'j + 1' is +** present. We want to find a larger key that is absent from the +** table, so that we can do a binary search between the two keys to +** find a boundary. We keep doubling 'j' until we get an absent index. +** If the doubling would overflow, we try LUA_MAXINTEGER. If it is +** absent, we are ready for the binary search. ('j', being max integer, +** is larger or equal to 'i', but it cannot be equal because it is +** absent while 'i' is present; so 'j > i'.) Otherwise, 'j' is a +** boundary. ('j + 1' cannot be a present integer key because it is +** not a valid integer in Lua.) +*/ +static lua_Unsigned hash_search (Table *t, lua_Unsigned j) { + lua_Unsigned i; + if (j == 0) j++; /* the caller ensures 'j + 1' is present */ + do { + i = j; /* 'i' is a present index */ + if (j <= l_castS2U(LUA_MAXINTEGER) / 2) + j *= 2; + else { + j = LUA_MAXINTEGER; + if (isempty(luaH_getint(t, j))) /* t[j] not present? */ + break; /* 'j' now is an absent index */ + else /* weird case */ + return j; /* well, max integer is a boundary... */ + } + } while (!isempty(luaH_getint(t, j))); /* repeat until an absent t[j] */ + /* i < j && t[i] present && t[j] absent */ + while (j - i > 1u) { /* do a binary search between them */ + lua_Unsigned m = (i + j) / 2; + if (isempty(luaH_getint(t, m))) j = m; + else i = m; + } + return i; +} + + +static unsigned int binsearch (const TValue *array, unsigned int i, + unsigned int j) { + while (j - i > 1u) { /* binary search */ + unsigned int m = (i + j) / 2; + if (isempty(&array[m - 1])) j = m; + else i = m; + } + return i; +} + + +/* +** Try to find a boundary in table 't'. (A 'boundary' is an integer index +** such that t[i] is present and t[i+1] is absent, or 0 if t[1] is absent +** and 'maxinteger' if t[maxinteger] is present.) +** (In the next explanation, we use Lua indices, that is, with base 1. +** The code itself uses base 0 when indexing the array part of the table.) +** The code starts with 'limit = t->alimit', a position in the array +** part that may be a boundary. +** +** (1) If 't[limit]' is empty, there must be a boundary before it. +** As a common case (e.g., after 't[#t]=nil'), check whether 'limit-1' +** is present. If so, it is a boundary. Otherwise, do a binary search +** between 0 and limit to find a boundary. In both cases, try to +** use this boundary as the new 'alimit', as a hint for the next call. +** +** (2) If 't[limit]' is not empty and the array has more elements +** after 'limit', try to find a boundary there. Again, try first +** the special case (which should be quite frequent) where 'limit+1' +** is empty, so that 'limit' is a boundary. Otherwise, check the +** last element of the array part. If it is empty, there must be a +** boundary between the old limit (present) and the last element +** (absent), which is found with a binary search. (This boundary always +** can be a new limit.) +** +** (3) The last case is when there are no elements in the array part +** (limit == 0) or its last element (the new limit) is present. +** In this case, must check the hash part. If there is no hash part +** or 'limit+1' is absent, 'limit' is a boundary. Otherwise, call +** 'hash_search' to find a boundary in the hash part of the table. +** (In those cases, the boundary is not inside the array part, and +** therefore cannot be used as a new limit.) +*/ +lua_Unsigned luaH_getn (Table *t) { + unsigned int limit = t->alimit; + if (limit > 0 && isempty(&t->array[limit - 1])) { /* (1)? */ + /* there must be a boundary before 'limit' */ + if (limit >= 2 && !isempty(&t->array[limit - 2])) { + /* 'limit - 1' is a boundary; can it be a new limit? */ + if (ispow2realasize(t) && !ispow2(limit - 1)) { + t->alimit = limit - 1; + setnorealasize(t); /* now 'alimit' is not the real size */ + } + return limit - 1; + } + else { /* must search for a boundary in [0, limit] */ + unsigned int boundary = binsearch(t->array, 0, limit); + /* can this boundary represent the real size of the array? */ + if (ispow2realasize(t) && boundary > luaH_realasize(t) / 2) { + t->alimit = boundary; /* use it as the new limit */ + setnorealasize(t); + } + return boundary; + } + } + /* 'limit' is zero or present in table */ + if (!limitequalsasize(t)) { /* (2)? */ + /* 'limit' > 0 and array has more elements after 'limit' */ + if (isempty(&t->array[limit])) /* 'limit + 1' is empty? */ + return limit; /* this is the boundary */ + /* else, try last element in the array */ + limit = luaH_realasize(t); + if (isempty(&t->array[limit - 1])) { /* empty? */ + /* there must be a boundary in the array after old limit, + and it must be a valid new limit */ + unsigned int boundary = binsearch(t->array, t->alimit, limit); + t->alimit = boundary; + return boundary; + } + /* else, new limit is present in the table; check the hash part */ + } + /* (3) 'limit' is the last element and either is zero or present in table */ + lua_assert(limit == luaH_realasize(t) && + (limit == 0 || !isempty(&t->array[limit - 1]))); + if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1)))) + return limit; /* 'limit + 1' is absent */ + else /* 'limit + 1' is also present */ + return hash_search(t, limit); +} + + + +#if defined(LUA_DEBUG) + +/* export these functions for the test library */ + +Node *luaH_mainposition (const Table *t, const TValue *key) { + return mainpositionTV(t, key); +} + +int luaH_isdummy (const Table *t) { return isdummy(t); } + +#endif diff --git a/lua/ltable.h b/lua/ltable.h new file mode 100644 index 0000000..7bbbcb2 --- /dev/null +++ b/lua/ltable.h @@ -0,0 +1,66 @@ +/* +** $Id: ltable.h $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + +#ifndef ltable_h +#define ltable_h + +#include "lobject.h" + + +#define gnode(t,i) (&(t)->node[i]) +#define gval(n) (&(n)->i_val) +#define gnext(n) ((n)->u.next) + + +/* +** Clear all bits of fast-access metamethods, which means that the table +** may have any of these metamethods. (First access that fails after the +** clearing will set the bit again.) +*/ +#define invalidateTMcache(t) ((t)->flags &= ~maskflags) + + +/* true when 't' is using 'dummynode' as its hash part */ +#define isdummy(t) ((t)->lastfree == NULL) + + +/* allocated size for hash nodes */ +#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t)) + + +/* returns the Node, given the value of a table entry */ +#define nodefromval(v) cast(Node *, (v)) + + +LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); +LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, + TValue *value); +LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); +LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); +LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); +LUAI_FUNC void luaH_newkey (lua_State *L, Table *t, const TValue *key, + TValue *value); +LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key, + TValue *value); +LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key, + const TValue *slot, TValue *value); +LUAI_FUNC Table *luaH_new (lua_State *L); +LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, + unsigned int nhsize); +LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize); +LUAI_FUNC void luaH_free (lua_State *L, Table *t); +LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); +LUAI_FUNC lua_Unsigned luaH_getn (Table *t); +LUAI_FUNC unsigned int luaH_realasize (const Table *t); + + +#if defined(LUA_DEBUG) +LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); +LUAI_FUNC int luaH_isdummy (const Table *t); +#endif + + +#endif diff --git a/lua/ltablib.c b/lua/ltablib.c new file mode 100644 index 0000000..d80eb80 --- /dev/null +++ b/lua/ltablib.c @@ -0,0 +1,429 @@ +/* +** $Id: ltablib.c $ +** Library for Table Manipulation +** See Copyright Notice in lua.h +*/ + +#define ltablib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** Operations that an object must define to mimic a table +** (some functions only need some of them) +*/ +#define TAB_R 1 /* read */ +#define TAB_W 2 /* write */ +#define TAB_L 4 /* length */ +#define TAB_RW (TAB_R | TAB_W) /* read/write */ + + +#define aux_getn(L,n,w) (checktab(L, n, (w) | TAB_L), luaL_len(L, n)) + + +static int checkfield (lua_State *L, const char *key, int n) { + lua_pushstring(L, key); + return (lua_rawget(L, -n) != LUA_TNIL); +} + + +/* +** Check that 'arg' either is a table or can behave like one (that is, +** has a metatable with the required metamethods) +*/ +static void checktab (lua_State *L, int arg, int what) { + if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */ + int n = 1; /* number of elements to pop */ + if (lua_getmetatable(L, arg) && /* must have metatable */ + (!(what & TAB_R) || checkfield(L, "__index", ++n)) && + (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) && + (!(what & TAB_L) || checkfield(L, "__len", ++n))) { + lua_pop(L, n); /* pop metatable and tested metamethods */ + } + else + luaL_checktype(L, arg, LUA_TTABLE); /* force an error */ + } +} + + +static int tinsert (lua_State *L) { + lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */ + lua_Integer pos; /* where to insert new element */ + switch (lua_gettop(L)) { + case 2: { /* called with only 2 arguments */ + pos = e; /* insert new element at the end */ + break; + } + case 3: { + lua_Integer i; + pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ + /* check whether 'pos' is in [1, e] */ + luaL_argcheck(L, (lua_Unsigned)pos - 1u < (lua_Unsigned)e, 2, + "position out of bounds"); + for (i = e; i > pos; i--) { /* move up elements */ + lua_geti(L, 1, i - 1); + lua_seti(L, 1, i); /* t[i] = t[i - 1] */ + } + break; + } + default: { + return luaL_error(L, "wrong number of arguments to 'insert'"); + } + } + lua_seti(L, 1, pos); /* t[pos] = v */ + return 0; +} + + +static int tremove (lua_State *L) { + lua_Integer size = aux_getn(L, 1, TAB_RW); + lua_Integer pos = luaL_optinteger(L, 2, size); + if (pos != size) /* validate 'pos' if given */ + /* check whether 'pos' is in [1, size + 1] */ + luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 1, + "position out of bounds"); + lua_geti(L, 1, pos); /* result = t[pos] */ + for ( ; pos < size; pos++) { + lua_geti(L, 1, pos + 1); + lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */ + } + lua_pushnil(L); + lua_seti(L, 1, pos); /* remove entry t[pos] */ + return 1; +} + + +/* +** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever +** possible, copy in increasing order, which is better for rehashing. +** "possible" means destination after original range, or smaller +** than origin, or copying to another table. +*/ +static int tmove (lua_State *L) { + lua_Integer f = luaL_checkinteger(L, 2); + lua_Integer e = luaL_checkinteger(L, 3); + lua_Integer t = luaL_checkinteger(L, 4); + int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */ + checktab(L, 1, TAB_R); + checktab(L, tt, TAB_W); + if (e >= f) { /* otherwise, nothing to move */ + lua_Integer n, i; + luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3, + "too many elements to move"); + n = e - f + 1; /* number of elements to move */ + luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, + "destination wrap around"); + if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) { + for (i = 0; i < n; i++) { + lua_geti(L, 1, f + i); + lua_seti(L, tt, t + i); + } + } + else { + for (i = n - 1; i >= 0; i--) { + lua_geti(L, 1, f + i); + lua_seti(L, tt, t + i); + } + } + } + lua_pushvalue(L, tt); /* return destination table */ + return 1; +} + + +static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { + lua_geti(L, 1, i); + if (l_unlikely(!lua_isstring(L, -1))) + luaL_error(L, "invalid value (%s) at index %I in table for 'concat'", + luaL_typename(L, -1), i); + luaL_addvalue(b); +} + + +static int tconcat (lua_State *L) { + luaL_Buffer b; + lua_Integer last = aux_getn(L, 1, TAB_R); + size_t lsep; + const char *sep = luaL_optlstring(L, 2, "", &lsep); + lua_Integer i = luaL_optinteger(L, 3, 1); + last = luaL_optinteger(L, 4, last); + luaL_buffinit(L, &b); + for (; i < last; i++) { + addfield(L, &b, i); + luaL_addlstring(&b, sep, lsep); + } + if (i == last) /* add last value (if interval was not empty) */ + addfield(L, &b, i); + luaL_pushresult(&b); + return 1; +} + + +/* +** {====================================================== +** Pack/unpack +** ======================================================= +*/ + +static int tpack (lua_State *L) { + int i; + int n = lua_gettop(L); /* number of elements to pack */ + lua_createtable(L, n, 1); /* create result table */ + lua_insert(L, 1); /* put it at index 1 */ + for (i = n; i >= 1; i--) /* assign elements */ + lua_seti(L, 1, i); + lua_pushinteger(L, n); + lua_setfield(L, 1, "n"); /* t.n = number of elements */ + return 1; /* return table */ +} + + +static int tunpack (lua_State *L) { + lua_Unsigned n; + lua_Integer i = luaL_optinteger(L, 2, 1); + lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); + if (i > e) return 0; /* empty range */ + n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ + if (l_unlikely(n >= (unsigned int)INT_MAX || + !lua_checkstack(L, (int)(++n)))) + return luaL_error(L, "too many results to unpack"); + for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */ + lua_geti(L, 1, i); + } + lua_geti(L, 1, e); /* push last element */ + return (int)n; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Quicksort +** (based on 'Algorithms in MODULA-3', Robert Sedgewick; +** Addison-Wesley, 1993.) +** ======================================================= +*/ + + +/* type for array indices */ +typedef unsigned int IdxT; + + +/* +** Produce a "random" 'unsigned int' to randomize pivot choice. This +** macro is used only when 'sort' detects a big imbalance in the result +** of a partition. (If you don't want/need this "randomness", ~0 is a +** good choice.) +*/ +#if !defined(l_randomizePivot) /* { */ + +#include + +/* size of 'e' measured in number of 'unsigned int's */ +#define sof(e) (sizeof(e) / sizeof(unsigned int)) + +/* +** Use 'time' and 'clock' as sources of "randomness". Because we don't +** know the types 'clock_t' and 'time_t', we cannot cast them to +** anything without risking overflows. A safe way to use their values +** is to copy them to an array of a known type and use the array values. +*/ +static unsigned int l_randomizePivot (void) { + clock_t c = clock(); + time_t t = time(NULL); + unsigned int buff[sof(c) + sof(t)]; + unsigned int i, rnd = 0; + memcpy(buff, &c, sof(c) * sizeof(unsigned int)); + memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int)); + for (i = 0; i < sof(buff); i++) + rnd += buff[i]; + return rnd; +} + +#endif /* } */ + + +/* arrays larger than 'RANLIMIT' may use randomized pivots */ +#define RANLIMIT 100u + + +static void set2 (lua_State *L, IdxT i, IdxT j) { + lua_seti(L, 1, i); + lua_seti(L, 1, j); +} + + +/* +** Return true iff value at stack index 'a' is less than the value at +** index 'b' (according to the order of the sort). +*/ +static int sort_comp (lua_State *L, int a, int b) { + if (lua_isnil(L, 2)) /* no function? */ + return lua_compare(L, a, b, LUA_OPLT); /* a < b */ + else { /* function */ + int res; + lua_pushvalue(L, 2); /* push function */ + lua_pushvalue(L, a-1); /* -1 to compensate function */ + lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */ + lua_call(L, 2, 1); /* call function */ + res = lua_toboolean(L, -1); /* get result */ + lua_pop(L, 1); /* pop result */ + return res; + } +} + + +/* +** Does the partition: Pivot P is at the top of the stack. +** precondition: a[lo] <= P == a[up-1] <= a[up], +** so it only needs to do the partition from lo + 1 to up - 2. +** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] +** returns 'i'. +*/ +static IdxT partition (lua_State *L, IdxT lo, IdxT up) { + IdxT i = lo; /* will be incremented before first use */ + IdxT j = up - 1; /* will be decremented before first use */ + /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ + for (;;) { + /* next loop: repeat ++i while a[i] < P */ + while ((void)lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (l_unlikely(i == up - 1)) /* a[i] < P but a[up - 1] == P ?? */ + luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ + /* next loop: repeat --j while P < a[j] */ + while ((void)lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { + if (l_unlikely(j < i)) /* j < i but a[j] > P ?? */ + luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[j] */ + } + /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */ + if (j < i) { /* no elements out of place? */ + /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */ + lua_pop(L, 1); /* pop a[j] */ + /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */ + set2(L, up - 1, i); + return i; + } + /* otherwise, swap a[i] - a[j] to restore invariant and repeat */ + set2(L, i, j); + } +} + + +/* +** Choose an element in the middle (2nd-3th quarters) of [lo,up] +** "randomized" by 'rnd' +*/ +static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) { + IdxT r4 = (up - lo) / 4; /* range/4 */ + IdxT p = rnd % (r4 * 2) + (lo + r4); + lua_assert(lo + r4 <= p && p <= up - r4); + return p; +} + + +/* +** Quicksort algorithm (recursive function) +*/ +static void auxsort (lua_State *L, IdxT lo, IdxT up, + unsigned int rnd) { + while (lo < up) { /* loop for tail recursion */ + IdxT p; /* Pivot index */ + IdxT n; /* to be used later */ + /* sort elements 'lo', 'p', and 'up' */ + lua_geti(L, 1, lo); + lua_geti(L, 1, up); + if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ + set2(L, lo, up); /* swap a[lo] - a[up] */ + else + lua_pop(L, 2); /* remove both values */ + if (up - lo == 1) /* only 2 elements? */ + return; /* already sorted */ + if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */ + p = (lo + up)/2; /* middle element is a good pivot */ + else /* for larger intervals, it is worth a random pivot */ + p = choosePivot(lo, up, rnd); + lua_geti(L, 1, p); + lua_geti(L, 1, lo); + if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */ + set2(L, p, lo); /* swap a[p] - a[lo] */ + else { + lua_pop(L, 1); /* remove a[lo] */ + lua_geti(L, 1, up); + if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */ + set2(L, p, up); /* swap a[up] - a[p] */ + else + lua_pop(L, 2); + } + if (up - lo == 2) /* only 3 elements? */ + return; /* already sorted */ + lua_geti(L, 1, p); /* get middle element (Pivot) */ + lua_pushvalue(L, -1); /* push Pivot */ + lua_geti(L, 1, up - 1); /* push a[up - 1] */ + set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */ + p = partition(L, lo, up); + /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */ + if (p - lo < up - p) { /* lower interval is smaller? */ + auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */ + n = p - lo; /* size of smaller interval */ + lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */ + } + else { + auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */ + n = up - p; /* size of smaller interval */ + up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ + } + if ((up - lo) / 128 > n) /* partition too imbalanced? */ + rnd = l_randomizePivot(); /* try a new randomization */ + } /* tail call auxsort(L, lo, up, rnd) */ +} + + +static int sort (lua_State *L) { + lua_Integer n = aux_getn(L, 1, TAB_RW); + if (n > 1) { /* non-trivial interval? */ + luaL_argcheck(L, n < INT_MAX, 1, "array too big"); + if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ + luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ + lua_settop(L, 2); /* make sure there are two arguments */ + auxsort(L, 1, (IdxT)n, 0); + } + return 0; +} + +/* }====================================================== */ + + +static const luaL_Reg tab_funcs[] = { + {"concat", tconcat}, + {"insert", tinsert}, + {"pack", tpack}, + {"unpack", tunpack}, + {"remove", tremove}, + {"move", tmove}, + {"sort", sort}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_table (lua_State *L) { + luaL_newlib(L, tab_funcs); + return 1; +} + diff --git a/lua/ltm.c b/lua/ltm.c new file mode 100644 index 0000000..b657b78 --- /dev/null +++ b/lua/ltm.c @@ -0,0 +1,271 @@ +/* +** $Id: ltm.c $ +** Tag methods +** See Copyright Notice in lua.h +*/ + +#define ltm_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + +static const char udatatypename[] = "userdata"; + +LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTYPES] = { + "no value", + "nil", "boolean", udatatypename, "number", + "string", "table", "function", udatatypename, "thread", + "upvalue", "proto" /* these last cases are used for tests only */ +}; + + +void luaT_init (lua_State *L) { + static const char *const luaT_eventname[] = { /* ORDER TM */ + "__index", "__newindex", + "__gc", "__mode", "__len", "__eq", + "__add", "__sub", "__mul", "__mod", "__pow", + "__div", "__idiv", + "__band", "__bor", "__bxor", "__shl", "__shr", + "__unm", "__bnot", "__lt", "__le", + "__concat", "__call", "__close" + }; + int i; + for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); + luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */ + } +} + + +/* +** function to be used with macro "fasttm": optimized for absence of +** tag methods +*/ +const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { + const TValue *tm = luaH_getshortstr(events, ename); + lua_assert(event <= TM_EQ); + if (notm(tm)) { /* no tag method? */ + events->flags |= cast_byte(1u<metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(o)->metatable; + break; + default: + mt = G(L)->mt[ttype(o)]; + } + return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : &G(L)->nilvalue); +} + + +/* +** Return the name of the type of an object. For tables and userdata +** with metatable, use their '__name' metafield, if present. +*/ +const char *luaT_objtypename (lua_State *L, const TValue *o) { + Table *mt; + if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) || + (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) { + const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name")); + if (ttisstring(name)) /* is '__name' a string? */ + return getstr(tsvalue(name)); /* use it as type name */ + } + return ttypename(ttype(o)); /* else use standard type name */ +} + + +void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, const TValue *p3) { + StkId func = L->top; + setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ + setobj2s(L, func + 1, p1); /* 1st argument */ + setobj2s(L, func + 2, p2); /* 2nd argument */ + setobj2s(L, func + 3, p3); /* 3rd argument */ + L->top = func + 4; + /* metamethod may yield only when called from Lua code */ + if (isLuacode(L->ci)) + luaD_call(L, func, 0); + else + luaD_callnoyield(L, func, 0); +} + + +void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, StkId res) { + ptrdiff_t result = savestack(L, res); + StkId func = L->top; + setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ + setobj2s(L, func + 1, p1); /* 1st argument */ + setobj2s(L, func + 2, p2); /* 2nd argument */ + L->top += 3; + /* metamethod may yield only when called from Lua code */ + if (isLuacode(L->ci)) + luaD_call(L, func, 1); + else + luaD_callnoyield(L, func, 1); + res = restorestack(L, result); + setobjs2s(L, res, --L->top); /* move result to its place */ +} + + +static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ + if (notm(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (notm(tm)) return 0; + luaT_callTMres(L, tm, p1, p2, res); + return 1; +} + + +void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + if (l_unlikely(!callbinTM(L, p1, p2, res, event))) { + switch (event) { + case TM_BAND: case TM_BOR: case TM_BXOR: + case TM_SHL: case TM_SHR: case TM_BNOT: { + if (ttisnumber(p1) && ttisnumber(p2)) + luaG_tointerror(L, p1, p2); + else + luaG_opinterror(L, p1, p2, "perform bitwise operation on"); + } + /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ + default: + luaG_opinterror(L, p1, p2, "perform arithmetic on"); + } + } +} + + +void luaT_tryconcatTM (lua_State *L) { + StkId top = L->top; + if (l_unlikely(!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2, + TM_CONCAT))) + luaG_concaterror(L, s2v(top - 2), s2v(top - 1)); +} + + +void luaT_trybinassocTM (lua_State *L, const TValue *p1, const TValue *p2, + int flip, StkId res, TMS event) { + if (flip) + luaT_trybinTM(L, p2, p1, res, event); + else + luaT_trybinTM(L, p1, p2, res, event); +} + + +void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, + int flip, StkId res, TMS event) { + TValue aux; + setivalue(&aux, i2); + luaT_trybinassocTM(L, p1, &aux, flip, res, event); +} + + +/* +** Calls an order tag method. +** For lessequal, LUA_COMPAT_LT_LE keeps compatibility with old +** behavior: if there is no '__le', try '__lt', based on l <= r iff +** !(r < l) (assuming a total order). If the metamethod yields during +** this substitution, the continuation has to know about it (to negate +** the result of rtop, event)) /* try original event */ + return !l_isfalse(s2v(L->top)); +#if defined(LUA_COMPAT_LT_LE) + else if (event == TM_LE) { + /* try '!(p2 < p1)' for '(p1 <= p2)' */ + L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ + if (callbinTM(L, p2, p1, L->top, TM_LT)) { + L->ci->callstatus ^= CIST_LEQ; /* clear mark */ + return l_isfalse(s2v(L->top)); + } + /* else error will remove this 'ci'; no need to clear mark */ + } +#endif + luaG_ordererror(L, p1, p2); /* no metamethod found */ + return 0; /* to avoid warnings */ +} + + +int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, + int flip, int isfloat, TMS event) { + TValue aux; const TValue *p2; + if (isfloat) { + setfltvalue(&aux, cast_num(v2)); + } + else + setivalue(&aux, v2); + if (flip) { /* arguments were exchanged? */ + p2 = p1; p1 = &aux; /* correct them */ + } + else + p2 = &aux; + return luaT_callorderTM(L, p1, p2, event); +} + + +void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci, + const Proto *p) { + int i; + int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */ + int nextra = actual - nfixparams; /* number of extra arguments */ + ci->u.l.nextraargs = nextra; + luaD_checkstack(L, p->maxstacksize + 1); + /* copy function to the top of the stack */ + setobjs2s(L, L->top++, ci->func); + /* move fixed parameters to the top of the stack */ + for (i = 1; i <= nfixparams; i++) { + setobjs2s(L, L->top++, ci->func + i); + setnilvalue(s2v(ci->func + i)); /* erase original parameter (for GC) */ + } + ci->func += actual + 1; + ci->top += actual + 1; + lua_assert(L->top <= ci->top && ci->top <= L->stack_last); +} + + +void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { + int i; + int nextra = ci->u.l.nextraargs; + if (wanted < 0) { + wanted = nextra; /* get all extra arguments available */ + checkstackGCp(L, nextra, where); /* ensure stack space */ + L->top = where + nextra; /* next instruction will need top */ + } + for (i = 0; i < wanted && i < nextra; i++) + setobjs2s(L, where + i, ci->func - nextra + i); + for (; i < wanted; i++) /* complete required results with nil */ + setnilvalue(s2v(where + i)); +} + diff --git a/lua/ltm.h b/lua/ltm.h new file mode 100644 index 0000000..73b833c --- /dev/null +++ b/lua/ltm.h @@ -0,0 +1,103 @@ +/* +** $Id: ltm.h $ +** Tag methods +** See Copyright Notice in lua.h +*/ + +#ifndef ltm_h +#define ltm_h + + +#include "lobject.h" + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER TM" and "ORDER OP" +*/ +typedef enum { + TM_INDEX, + TM_NEWINDEX, + TM_GC, + TM_MODE, + TM_LEN, + TM_EQ, /* last tag method with fast access */ + TM_ADD, + TM_SUB, + TM_MUL, + TM_MOD, + TM_POW, + TM_DIV, + TM_IDIV, + TM_BAND, + TM_BOR, + TM_BXOR, + TM_SHL, + TM_SHR, + TM_UNM, + TM_BNOT, + TM_LT, + TM_LE, + TM_CONCAT, + TM_CALL, + TM_CLOSE, + TM_N /* number of elements in the enum */ +} TMS; + + +/* +** Mask with 1 in all fast-access methods. A 1 in any of these bits +** in the flag of a (meta)table means the metatable does not have the +** corresponding metamethod field. (Bit 7 of the flag is used for +** 'isrealasize'.) +*/ +#define maskflags (~(~0u << (TM_EQ + 1))) + + +/* +** Test whether there is no tagmethod. +** (Because tagmethods use raw accesses, the result may be an "empty" nil.) +*/ +#define notm(tm) ttisnil(tm) + + +#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ + ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) + +#define fasttm(l,et,e) gfasttm(G(l), et, e) + +#define ttypename(x) luaT_typenames_[(x) + 1] + +LUAI_DDEC(const char *const luaT_typenames_[LUA_TOTALTYPES];) + + +LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o); + +LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); +LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, + TMS event); +LUAI_FUNC void luaT_init (lua_State *L); + +LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, const TValue *p3); +LUAI_FUNC void luaT_callTMres (lua_State *L, const TValue *f, + const TValue *p1, const TValue *p2, StkId p3); +LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event); +LUAI_FUNC void luaT_tryconcatTM (lua_State *L); +LUAI_FUNC void luaT_trybinassocTM (lua_State *L, const TValue *p1, + const TValue *p2, int inv, StkId res, TMS event); +LUAI_FUNC void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, + int inv, StkId res, TMS event); +LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, + const TValue *p2, TMS event); +LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, + int inv, int isfloat, TMS event); + +LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, + struct CallInfo *ci, const Proto *p); +LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, + StkId where, int wanted); + + +#endif diff --git a/lua/lua.h b/lua/lua.h new file mode 100644 index 0000000..820535b --- /dev/null +++ b/lua/lua.h @@ -0,0 +1,518 @@ +/* +** $Id: lua.h $ +** Lua - A Scripting Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "4" +#define LUA_VERSION_RELEASE "3" + +#define LUA_VERSION_NUM 504 +#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 0) + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2021 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" + + +/* mark for precompiled code ('Lua') */ +#define LUA_SIGNATURE "\x1bLua" + +/* option for multiple returns in 'lua_pcall' and 'lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** Pseudo-indices +** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty +** space after that to help overflow detection) +*/ +#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000) +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) + + +/* thread status */ +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + +#define LUA_NUMTYPES 9 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + +/* unsigned integer type */ +typedef LUA_UNSIGNED lua_Unsigned; + +/* type for continuation-function contexts */ +typedef LUA_KCONTEXT lua_KContext; + + +/* +** Type for C functions registered with Lua +*/ +typedef int (*lua_CFunction) (lua_State *L); + +/* +** Type for continuation functions +*/ +typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); + + +/* +** Type for functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud); + + +/* +** Type for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + +/* +** Type for warning functions +*/ +typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont); + + + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* +** RCS ident string +*/ +extern const char lua_ident[]; + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); +LUA_API int (lua_resetthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +LUA_API lua_Number (lua_version) (lua_State *L); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_absindex) (lua_State *L, int idx); +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_rotate) (lua_State *L, int idx, int n); +LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); +LUA_API int (lua_checkstack) (lua_State *L, int n); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isinteger) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API lua_Unsigned (lua_rawlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** Comparison and arithmetic functions +*/ + +#define LUA_OPADD 0 /* ORDER TM, ORDER OP */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPMOD 3 +#define LUA_OPPOW 4 +#define LUA_OPDIV 5 +#define LUA_OPIDIV 6 +#define LUA_OPBAND 7 +#define LUA_OPBOR 8 +#define LUA_OPBXOR 9 +#define LUA_OPSHL 10 +#define LUA_OPSHR 11 +#define LUA_OPUNM 12 +#define LUA_OPBNOT 13 + +LUA_API void (lua_arith) (lua_State *L, int op); + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len); +LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API int (lua_getglobal) (lua_State *L, const char *name); +LUA_API int (lua_gettable) (lua_State *L, int idx); +LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawget) (lua_State *L, int idx); +LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); + +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_setglobal) (lua_State *L, const char *name); +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API int (lua_setiuservalue) (lua_State *L, int idx, int n); + + +/* +** 'load' and 'call' functions (load and run Lua code) +*/ +LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k); +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) + +LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k); +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) + +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, const char *mode); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx, + lua_KFunction k); +LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg, + int *nres); +LUA_API int (lua_status) (lua_State *L); +LUA_API int (lua_isyieldable) (lua_State *L); + +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) + + +/* +** Warning-related functions +*/ +LUA_API void (lua_setwarnf) (lua_State *L, lua_WarnFunction f, void *ud); +LUA_API void (lua_warning) (lua_State *L, const char *msg, int tocont); + + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 +#define LUA_GCISRUNNING 9 +#define LUA_GCGEN 10 +#define LUA_GCINC 11 + +LUA_API int (lua_gc) (lua_State *L, int what, ...); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); +LUA_API void (lua_len) (lua_State *L, int idx); + +LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); + +LUA_API void (lua_toclose) (lua_State *L, int idx); +LUA_API void (lua_closeslot) (lua_State *L, int idx); + + +/* +** {============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE)) + +#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL) + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) lua_pushstring(L, "" s) + +#define lua_pushglobaltable(L) \ + ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + +#define lua_insert(L,idx) lua_rotate(L, (idx), 1) + +#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) + +#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) + +/* }============================================================== */ + + +/* +** {============================================================== +** compatibility macros +** =============================================================== +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is)) +#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) + +#endif + +#define lua_newuserdata(L,s) lua_newuserdatauv(L,s,1) +#define lua_getuservalue(L,idx) lua_getiuservalue(L,idx,1) +#define lua_setuservalue(L,idx) lua_setiuservalue(L,idx,1) + +#define LUA_NUMTAGS LUA_NUMTYPES + +/* }============================================================== */ + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILCALL 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debugger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); +LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); +LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); + +LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); +LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, + int fidx2, int n2); + +LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook (lua_gethook) (lua_State *L); +LUA_API int (lua_gethookmask) (lua_State *L); +LUA_API int (lua_gethookcount) (lua_State *L); + +LUA_API int (lua_setcstacklimit) (lua_State *L, unsigned int limit); + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ + const char *source; /* (S) */ + size_t srclen; /* (S) */ + int currentline; /* (l) */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams;/* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ + unsigned short ftransfer; /* (r) index of first value transferred */ + unsigned short ntransfer; /* (r) number of transferred values */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct CallInfo *i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2021 Lua.org, PUC-Rio. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/lua/lua.hpp b/lua/lua.hpp new file mode 100644 index 0000000..dd1ae9c --- /dev/null +++ b/lua/lua.hpp @@ -0,0 +1,9 @@ +// lua.hpp +// Lua header files for C++ +// <> not supplied automatically because Lua also compiles as C++ + +//extern "C" { +#include "lua.h" +//#include "lualib.h" +#include "lauxlib.h" +//} diff --git a/lua/luaconf.h b/lua/luaconf.h new file mode 100644 index 0000000..e64d2ee --- /dev/null +++ b/lua/luaconf.h @@ -0,0 +1,790 @@ +/* +** $Id: luaconf.h $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef luaconf_h +#define luaconf_h + +#include +#include + + +/* +** =================================================================== +** General Configuration File for Lua +** +** Some definitions here can be changed externally, through the compiler +** (e.g., with '-D' options): They are commented out or protected +** by '#if !defined' guards. However, several other definitions +** should be changed directly here, either because they affect the +** Lua ABI (by making the changes here, you ensure that all software +** connected to Lua, such as C libraries, will be compiled with the same +** configuration); or because they are seldom changed. +** +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +** {==================================================================== +** System Configuration: macros to adapt (if needed) Lua to some +** particular platform, for instance restricting it to C89. +** ===================================================================== +*/ + +/* +@@ LUA_USE_C89 controls the use of non-ISO-C89 features. +** Define it if you want Lua to avoid the use of a few C99 features +** or Windows-specific features on Windows. +*/ +/* #define LUA_USE_C89 */ + + +/* +** By default, Lua on Windows use (some) specific Windows features +*/ +#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_USE_WINDOWS /* enable goodies for regular Windows */ +#endif + + +#if defined(LUA_USE_WINDOWS) +#define LUA_DL_DLL /* enable support for DLL */ +#define LUA_USE_C89 /* broadly, Windows is C89 */ +#endif + + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#endif + + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* MacOS does not need -ldl */ +#endif + + +/* +@@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits. +*/ +#define LUAI_IS32INT ((UINT_MAX >> 30) >= 3) + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Number types. These options should not be +** set externally, because any other code connected to Lua must +** use the same configuration. +** =================================================================== +*/ + +/* +@@ LUA_INT_TYPE defines the type for Lua integers. +@@ LUA_FLOAT_TYPE defines the type for Lua floats. +** Lua should work fine with any mix of these options supported +** by your C compiler. The usual configurations are 64-bit integers +** and 'double' (the default), 32-bit integers and 'float' (for +** restricted platforms), and 'long'/'double' (for C compilers not +** compliant with C99, which may not have support for 'long long'). +*/ + +/* predefined options for LUA_INT_TYPE */ +#define LUA_INT_INT 1 +#define LUA_INT_LONG 2 +#define LUA_INT_LONGLONG 3 + +/* predefined options for LUA_FLOAT_TYPE */ +#define LUA_FLOAT_FLOAT 1 +#define LUA_FLOAT_DOUBLE 2 +#define LUA_FLOAT_LONGDOUBLE 3 + + +/* Default configuration ('long long' and 'double', for 64-bit Lua) */ +#define LUA_INT_DEFAULT LUA_INT_LONGLONG +#define LUA_FLOAT_DEFAULT LUA_FLOAT_DOUBLE + + +/* +@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. +*/ +#define LUA_32BITS 0 + + +/* +@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for +** C89 ('long' and 'double'); Windows always has '__int64', so it does +** not need to use this case. +*/ +#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS) +#define LUA_C89_NUMBERS 1 +#else +#define LUA_C89_NUMBERS 0 +#endif + + +#if LUA_32BITS /* { */ +/* +** 32-bit integers and 'float' +*/ +#if LUAI_IS32INT /* use 'int' if big enough */ +#define LUA_INT_TYPE LUA_INT_INT +#else /* otherwise use 'long' */ +#define LUA_INT_TYPE LUA_INT_LONG +#endif +#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT + +#elif LUA_C89_NUMBERS /* }{ */ +/* +** largest types available for C89 ('long' and 'double') +*/ +#define LUA_INT_TYPE LUA_INT_LONG +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE + +#else /* }{ */ +/* use defaults */ + +#define LUA_INT_TYPE LUA_INT_DEFAULT +#define LUA_FLOAT_TYPE LUA_FLOAT_DEFAULT + +#endif /* } */ + + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Paths. +** =================================================================== +*/ + +/* +** LUA_PATH_SEP is the character that separates templates in a path. +** LUA_PATH_MARK is the string that marks the substitution points in a +** template. +** LUA_EXEC_DIR in a Windows path is replaced by the executable's +** directory. +*/ +#define LUA_PATH_SEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXEC_DIR "!" + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +** Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +** C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ + +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#if defined(_WIN32) /* { */ +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\" + +#if !defined(LUA_PATH_DEFAULT) +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \ + LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \ + ".\\?.lua;" ".\\?\\init.lua" +#endif + +#if !defined(LUA_CPATH_DEFAULT) +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.dll;" \ + LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \ + LUA_CDIR"loadall.dll;" ".\\?.dll" +#endif + +#else /* }{ */ + +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/" +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/" + +#if !defined(LUA_PATH_DEFAULT) +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ + "./?.lua;" "./?/init.lua" +#endif + +#if !defined(LUA_CPATH_DEFAULT) +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif + +#endif /* } */ + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if !defined(LUA_DIRSEP) + +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Marks for exported symbols in the C code +** =================================================================== +*/ + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all auxiliary library functions. +@@ LUAMOD_API is a mark for all standard library opening functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) /* { */ + +#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ +#define LUA_API __declspec(dllexport) +#else /* }{ */ +#define LUA_API __declspec(dllimport) +#endif /* } */ + +#else /* }{ */ + +#define LUA_API extern + +#endif /* } */ + + +/* +** More often than not the libs go together with the core. +*/ +#define LUALIB_API LUA_API +#define LUAMOD_API LUA_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +** exported to outside modules. +@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables, +** none of which to be exported to outside modules (LUAI_DDEF for +** definitions and LUAI_DDEC for declarations). +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. Not all elf targets support +** this attribute. Unfortunately, gcc does not offer a way to check +** whether the target offers that support, and those without support +** give a warning about it. To avoid these warnings, change to the +** default definition. +*/ +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ +#define LUAI_FUNC __attribute__((visibility("internal"))) extern +#else /* }{ */ +#define LUAI_FUNC extern +#endif /* } */ + +#define LUAI_DDEC(dec) LUAI_FUNC dec +#define LUAI_DDEF /* empty */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Compatibility with previous versions +** =================================================================== +*/ + +/* +@@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.3. +** You can define it to get all options, or change specific options +** to fit your specific needs. +*/ +#if defined(LUA_COMPAT_5_3) /* { */ + +/* +@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated +** functions in the mathematical library. +** (These functions were already officially removed in 5.3; +** nevertheless they are still available here.) +*/ +#define LUA_COMPAT_MATHLIB + +/* +@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for +** manipulating other integer types (lua_pushunsigned, lua_tounsigned, +** luaL_checkint, luaL_checklong, etc.) +** (These macros were also officially removed in 5.3, but they are still +** available here.) +*/ +#define LUA_COMPAT_APIINTCASTS + + +/* +@@ LUA_COMPAT_LT_LE controls the emulation of the '__le' metamethod +** using '__lt'. +*/ +#define LUA_COMPAT_LT_LE + + +/* +@@ The following macros supply trivial compatibility for some +** changes in the API. The macros themselves document how to +** change your code to avoid using them. +** (Once more, these macros were officially removed in 5.3, but they are +** still available here.) +*/ +#define lua_strlen(L,i) lua_rawlen(L, (i)) + +#define lua_objlen(L,i) lua_rawlen(L, (i)) + +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) + +#endif /* } */ + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Numbers (low-level part). +** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* +** satisfy your needs. +** =================================================================== +*/ + +/* +@@ LUAI_UACNUMBER is the result of a 'default argument promotion' +@@ over a floating number. +@@ l_floatatt(x) corrects float attribute 'x' to the proper float type +** by prefixing it with one of FLT/DBL/LDBL. +@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. +@@ LUA_NUMBER_FMT is the format for writing floats. +@@ lua_number2str converts a float to a string. +@@ l_mathop allows the addition of an 'l' or 'f' to all math operations. +@@ l_floor takes the floor of a float. +@@ lua_str2number converts a decimal numeral to a number. +*/ + + +/* The following definitions are good for most cases here */ + +#define l_floor(x) (l_mathop(floor)(x)) + +#define lua_number2str(s,sz,n) \ + l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n)) + +/* +@@ lua_numbertointeger converts a float number with an integral value +** to an integer, or returns 0 if float is not within the range of +** a lua_Integer. (The range comparisons are tricky because of +** rounding. The tests here assume a two-complement representation, +** where MININTEGER always has an exact representation as a float; +** MAXINTEGER may not have one, and therefore its conversion to float +** may have an ill-defined value.) +*/ +#define lua_numbertointeger(n,p) \ + ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \ + (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \ + (*(p) = (LUA_INTEGER)(n), 1)) + + +/* now the variable definitions */ + +#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ + +#define LUA_NUMBER float + +#define l_floatatt(n) (FLT_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.7g" + +#define l_mathop(op) op##f + +#define lua_str2number(s,p) strtof((s), (p)) + + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */ + +#define LUA_NUMBER long double + +#define l_floatatt(n) (LDBL_##n) + +#define LUAI_UACNUMBER long double + +#define LUA_NUMBER_FRMLEN "L" +#define LUA_NUMBER_FMT "%.19Lg" + +#define l_mathop(op) op##l + +#define lua_str2number(s,p) strtold((s), (p)) + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */ + +#define LUA_NUMBER double + +#define l_floatatt(n) (DBL_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.14g" + +#define l_mathop(op) op + +#define lua_str2number(s,p) strtod((s), (p)) + +#else /* }{ */ + +#error "numeric float type not defined" + +#endif /* } */ + + + +/* +@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER. +@@ LUAI_UACINT is the result of a 'default argument promotion' +@@ over a LUA_INTEGER. +@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. +@@ LUA_INTEGER_FMT is the format for writing integers. +@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. +@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. +@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED. +@@ LUA_UNSIGNEDBITS is the number of bits in a LUA_UNSIGNED. +@@ lua_integer2str converts an integer to a string. +*/ + + +/* The following definitions are good for most cases here */ + +#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" + +#define LUAI_UACINT LUA_INTEGER + +#define lua_integer2str(s,sz,n) \ + l_sprintf((s), sz, LUA_INTEGER_FMT, (LUAI_UACINT)(n)) + +/* +** use LUAI_UACINT here to avoid problems with promotions (which +** can turn a comparison between unsigneds into a signed comparison) +*/ +#define LUA_UNSIGNED unsigned LUAI_UACINT + + +#define LUA_UNSIGNEDBITS (sizeof(LUA_UNSIGNED) * CHAR_BIT) + + +/* now the variable definitions */ + +#if LUA_INT_TYPE == LUA_INT_INT /* { int */ + +#define LUA_INTEGER int +#define LUA_INTEGER_FRMLEN "" + +#define LUA_MAXINTEGER INT_MAX +#define LUA_MININTEGER INT_MIN + +#define LUA_MAXUNSIGNED UINT_MAX + +#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */ + +#define LUA_INTEGER long +#define LUA_INTEGER_FRMLEN "l" + +#define LUA_MAXINTEGER LONG_MAX +#define LUA_MININTEGER LONG_MIN + +#define LUA_MAXUNSIGNED ULONG_MAX + +#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ + +/* use presence of macro LLONG_MAX as proxy for C99 compliance */ +#if defined(LLONG_MAX) /* { */ +/* use ISO C99 stuff */ + +#define LUA_INTEGER long long +#define LUA_INTEGER_FRMLEN "ll" + +#define LUA_MAXINTEGER LLONG_MAX +#define LUA_MININTEGER LLONG_MIN + +#define LUA_MAXUNSIGNED ULLONG_MAX + +#elif defined(LUA_USE_WINDOWS) /* }{ */ +/* in Windows, can use specific Windows types */ + +#define LUA_INTEGER __int64 +#define LUA_INTEGER_FRMLEN "I64" + +#define LUA_MAXINTEGER _I64_MAX +#define LUA_MININTEGER _I64_MIN + +#define LUA_MAXUNSIGNED _UI64_MAX + +#else /* }{ */ + +#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \ + or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)" + +#endif /* } */ + +#else /* }{ */ + +#error "numeric integer type not defined" + +#endif /* } */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Dependencies with C99 and other C details +** =================================================================== +*/ + +/* +@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89. +** (All uses in Lua have only one format item.) +*/ +#if !defined(LUA_USE_C89) +#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i) +#else +#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i)) +#endif + + +/* +@@ lua_strx2number converts a hexadecimal numeral to a number. +** In C99, 'strtod' does that conversion. Otherwise, you can +** leave 'lua_strx2number' undefined and Lua will provide its own +** implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_strx2number(s,p) lua_str2number(s,p) +#endif + + +/* +@@ lua_pointer2str converts a pointer to a readable string in a +** non-specified way. +*/ +#define lua_pointer2str(buff,sz,p) l_sprintf(buff,sz,"%p",p) + + +/* +@@ lua_number2strx converts a float to a hexadecimal numeral. +** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. +** Otherwise, you can leave 'lua_number2strx' undefined and Lua will +** provide its own implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_number2strx(L,b,sz,f,n) \ + ((void)L, l_sprintf(b,sz,f,(LUAI_UACNUMBER)(n))) +#endif + + +/* +** 'strtof' and 'opf' variants for math functions are not valid in +** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the +** availability of these variants. ('math.h' is already included in +** all files that use these macros.) +*/ +#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF)) +#undef l_mathop /* variants not available */ +#undef lua_str2number +#define l_mathop(op) (lua_Number)op /* no variant */ +#define lua_str2number(s,p) ((lua_Number)strtod((s), (p))) +#endif + + +/* +@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation +** functions. It must be a numerical type; Lua will use 'intptr_t' if +** available, otherwise it will use 'ptrdiff_t' (the nearest thing to +** 'intptr_t' in C89) +*/ +#define LUA_KCONTEXT ptrdiff_t + +#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 199901L +#include +#if defined(INTPTR_MAX) /* even in C99 this type is optional */ +#undef LUA_KCONTEXT +#define LUA_KCONTEXT intptr_t +#endif +#endif + + +/* +@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point). +** Change that if you do not want to use C locales. (Code using this +** macro must include the header 'locale.h'.) +*/ +#if !defined(lua_getlocaledecpoint) +#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + + +/* +** macros to improve jump prediction, used mostly for error handling +** and debug facilities. (Some macros in the Lua API use these macros. +** Define LUA_NOBUILTIN if you do not want '__builtin_expect' in your +** code.) +*/ +#if !defined(luai_likely) + +#if defined(__GNUC__) && !defined(LUA_NOBUILTIN) +#define luai_likely(x) (__builtin_expect(((x) != 0), 1)) +#define luai_unlikely(x) (__builtin_expect(((x) != 0), 0)) +#else +#define luai_likely(x) (x) +#define luai_unlikely(x) (x) +#endif + +#endif + + +#if defined(LUA_CORE) || defined(LUA_LIB) +/* shorter names for Lua's own use */ +#define l_likely(x) luai_likely(x) +#define l_unlikely(x) luai_unlikely(x) +#endif + + + +/* }================================================================== */ + + +/* +** {================================================================== +** Language Variations +** ===================================================================== +*/ + +/* +@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some +** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from +** numbers to strings. Define LUA_NOCVTS2N to turn off automatic +** coercion from strings to numbers. +*/ +/* #define LUA_NOCVTN2S */ +/* #define LUA_NOCVTS2N */ + + +/* +@@ LUA_USE_APICHECK turns on several consistency checks on the C API. +** Define it as a help when debugging C code. +*/ +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(l,e) assert(e) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Macros that affect the API and must be stable (that is, must be the +** same when you compile Lua and when you compile code that links to +** Lua). +** ===================================================================== +*/ + +/* +@@ LUAI_MAXSTACK limits the size of the Lua stack. +** CHANGE it if you need a different limit. This limit is arbitrary; +** its only purpose is to stop Lua from consuming unlimited stack +** space (and to reserve some numbers for pseudo-indices). +** (It must fit into max(size_t)/32.) +*/ +#if LUAI_IS32INT +#define LUAI_MAXSTACK 1000000 +#else +#define LUAI_MAXSTACK 15000 +#endif + + +/* +@@ LUA_EXTRASPACE defines the size of a raw memory area associated with +** a Lua state with very fast access. +** CHANGE it if you need a different size. +*/ +#define LUA_EXTRASPACE (sizeof(void *)) + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@@ of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +*/ +#define LUAL_BUFFERSIZE ((int)(16 * sizeof(void*) * sizeof(lua_Number))) + + +/* +@@ LUAI_MAXALIGN defines fields that, when used in a union, ensure +** maximum alignment for the other items in that union. +*/ +#define LUAI_MAXALIGN lua_Number n; double u; void *s; lua_Integer i; long l + +/* }================================================================== */ + + + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + + + +#endif + diff --git a/lua/lualib.h b/lua/lualib.h new file mode 100644 index 0000000..2625529 --- /dev/null +++ b/lua/lualib.h @@ -0,0 +1,52 @@ +/* +** $Id: lualib.h $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + +/* version suffix for environment variable names */ +#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + + +LUAMOD_API int (luaopen_base) (lua_State *L); + +#define LUA_COLIBNAME "coroutine" +LUAMOD_API int (luaopen_coroutine) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUAMOD_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUAMOD_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUAMOD_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUAMOD_API int (luaopen_string) (lua_State *L); + +#define LUA_UTF8LIBNAME "utf8" +LUAMOD_API int (luaopen_utf8) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUAMOD_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUAMOD_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUAMOD_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + +#endif diff --git a/lua/lundump.c b/lua/lundump.c new file mode 100644 index 0000000..5aa55c4 --- /dev/null +++ b/lua/lundump.c @@ -0,0 +1,333 @@ +/* +** $Id: lundump.c $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#define lundump_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstring.h" +#include "lundump.h" +#include "lzio.h" + + +#if !defined(luai_verifycode) +#define luai_verifycode(L,f) /* empty */ +#endif + + +typedef struct { + lua_State *L; + ZIO *Z; + const char *name; +} LoadState; + + +static l_noret error (LoadState *S, const char *why) { + luaO_pushfstring(S->L, "%s: bad binary format (%s)", S->name, why); + luaD_throw(S->L, LUA_ERRSYNTAX); +} + + +/* +** All high-level loads go through loadVector; you can change it to +** adapt to the endianness of the input +*/ +#define loadVector(S,b,n) loadBlock(S,b,(n)*sizeof((b)[0])) + +static void loadBlock (LoadState *S, void *b, size_t size) { + if (luaZ_read(S->Z, b, size) != 0) + error(S, "truncated chunk"); +} + + +#define loadVar(S,x) loadVector(S,&x,1) + + +static lu_byte loadByte (LoadState *S) { + int b = zgetc(S->Z); + if (b == EOZ) + error(S, "truncated chunk"); + return cast_byte(b); +} + + +static size_t loadUnsigned (LoadState *S, size_t limit) { + size_t x = 0; + int b; + limit >>= 7; + do { + b = loadByte(S); + if (x >= limit) + error(S, "integer overflow"); + x = (x << 7) | (b & 0x7f); + } while ((b & 0x80) == 0); + return x; +} + + +static size_t loadSize (LoadState *S) { + return loadUnsigned(S, ~(size_t)0); +} + + +static int loadInt (LoadState *S) { + return cast_int(loadUnsigned(S, INT_MAX)); +} + + +static lua_Number loadNumber (LoadState *S) { + lua_Number x; + loadVar(S, x); + return x; +} + + +static lua_Integer loadInteger (LoadState *S) { + lua_Integer x; + loadVar(S, x); + return x; +} + + +/* +** Load a nullable string into prototype 'p'. +*/ +static TString *loadStringN (LoadState *S, Proto *p) { + lua_State *L = S->L; + TString *ts; + size_t size = loadSize(S); + if (size == 0) /* no string? */ + return NULL; + else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ + char buff[LUAI_MAXSHORTLEN]; + loadVector(S, buff, size); /* load string into buffer */ + ts = luaS_newlstr(L, buff, size); /* create string */ + } + else { /* long string */ + ts = luaS_createlngstrobj(L, size); /* create string */ + setsvalue2s(L, L->top, ts); /* anchor it ('loadVector' can GC) */ + luaD_inctop(L); + loadVector(S, getstr(ts), size); /* load directly in final place */ + L->top--; /* pop string */ + } + luaC_objbarrier(L, p, ts); + return ts; +} + + +/* +** Load a non-nullable string into prototype 'p'. +*/ +static TString *loadString (LoadState *S, Proto *p) { + TString *st = loadStringN(S, p); + if (st == NULL) + error(S, "bad format for constant string"); + return st; +} + + +static void loadCode (LoadState *S, Proto *f) { + int n = loadInt(S); + f->code = luaM_newvectorchecked(S->L, n, Instruction); + f->sizecode = n; + loadVector(S, f->code, n); +} + + +static void loadFunction(LoadState *S, Proto *f, TString *psource); + + +static void loadConstants (LoadState *S, Proto *f) { + int i; + int n = loadInt(S); + f->k = luaM_newvectorchecked(S->L, n, TValue); + f->sizek = n; + for (i = 0; i < n; i++) + setnilvalue(&f->k[i]); + for (i = 0; i < n; i++) { + TValue *o = &f->k[i]; + int t = loadByte(S); + switch (t) { + case LUA_VNIL: + setnilvalue(o); + break; + case LUA_VFALSE: + setbfvalue(o); + break; + case LUA_VTRUE: + setbtvalue(o); + break; + case LUA_VNUMFLT: + setfltvalue(o, loadNumber(S)); + break; + case LUA_VNUMINT: + setivalue(o, loadInteger(S)); + break; + case LUA_VSHRSTR: + case LUA_VLNGSTR: + setsvalue2n(S->L, o, loadString(S, f)); + break; + default: lua_assert(0); + } + } +} + + +static void loadProtos (LoadState *S, Proto *f) { + int i; + int n = loadInt(S); + f->p = luaM_newvectorchecked(S->L, n, Proto *); + f->sizep = n; + for (i = 0; i < n; i++) + f->p[i] = NULL; + for (i = 0; i < n; i++) { + f->p[i] = luaF_newproto(S->L); + luaC_objbarrier(S->L, f, f->p[i]); + loadFunction(S, f->p[i], f->source); + } +} + + +/* +** Load the upvalues for a function. The names must be filled first, +** because the filling of the other fields can raise read errors and +** the creation of the error message can call an emergency collection; +** in that case all prototypes must be consistent for the GC. +*/ +static void loadUpvalues (LoadState *S, Proto *f) { + int i, n; + n = loadInt(S); + f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc); + f->sizeupvalues = n; + for (i = 0; i < n; i++) /* make array valid for GC */ + f->upvalues[i].name = NULL; + for (i = 0; i < n; i++) { /* following calls can raise errors */ + f->upvalues[i].instack = loadByte(S); + f->upvalues[i].idx = loadByte(S); + f->upvalues[i].kind = loadByte(S); + } +} + + +static void loadDebug (LoadState *S, Proto *f) { + int i, n; + n = loadInt(S); + f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte); + f->sizelineinfo = n; + loadVector(S, f->lineinfo, n); + n = loadInt(S); + f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo); + f->sizeabslineinfo = n; + for (i = 0; i < n; i++) { + f->abslineinfo[i].pc = loadInt(S); + f->abslineinfo[i].line = loadInt(S); + } + n = loadInt(S); + f->locvars = luaM_newvectorchecked(S->L, n, LocVar); + f->sizelocvars = n; + for (i = 0; i < n; i++) + f->locvars[i].varname = NULL; + for (i = 0; i < n; i++) { + f->locvars[i].varname = loadStringN(S, f); + f->locvars[i].startpc = loadInt(S); + f->locvars[i].endpc = loadInt(S); + } + n = loadInt(S); + for (i = 0; i < n; i++) + f->upvalues[i].name = loadStringN(S, f); +} + + +static void loadFunction (LoadState *S, Proto *f, TString *psource) { + f->source = loadStringN(S, f); + if (f->source == NULL) /* no source in dump? */ + f->source = psource; /* reuse parent's source */ + f->linedefined = loadInt(S); + f->lastlinedefined = loadInt(S); + f->numparams = loadByte(S); + f->is_vararg = loadByte(S); + f->maxstacksize = loadByte(S); + loadCode(S, f); + loadConstants(S, f); + loadUpvalues(S, f); + loadProtos(S, f); + loadDebug(S, f); +} + + +static void checkliteral (LoadState *S, const char *s, const char *msg) { + char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ + size_t len = strlen(s); + loadVector(S, buff, len); + if (memcmp(s, buff, len) != 0) + error(S, msg); +} + + +static void fchecksize (LoadState *S, size_t size, const char *tname) { + if (loadByte(S) != size) + error(S, luaO_pushfstring(S->L, "%s size mismatch", tname)); +} + + +#define checksize(S,t) fchecksize(S,sizeof(t),#t) + +static void checkHeader (LoadState *S) { + /* skip 1st char (already read and checked) */ + checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk"); + if (loadByte(S) != LUAC_VERSION) + error(S, "version mismatch"); + if (loadByte(S) != LUAC_FORMAT) + error(S, "format mismatch"); + checkliteral(S, LUAC_DATA, "corrupted chunk"); + checksize(S, Instruction); + checksize(S, lua_Integer); + checksize(S, lua_Number); + if (loadInteger(S) != LUAC_INT) + error(S, "integer format mismatch"); + if (loadNumber(S) != LUAC_NUM) + error(S, "float format mismatch"); +} + + +/* +** Load precompiled chunk. +*/ +LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { + LoadState S; + LClosure *cl; + if (*name == '@' || *name == '=') + S.name = name + 1; + else if (*name == LUA_SIGNATURE[0]) + S.name = "binary string"; + else + S.name = name; + S.L = L; + S.Z = Z; + checkHeader(&S); + cl = luaF_newLclosure(L, loadByte(&S)); + setclLvalue2s(L, L->top, cl); + luaD_inctop(L); + cl->p = luaF_newproto(L); + luaC_objbarrier(L, cl, cl->p); + loadFunction(&S, cl->p, NULL); + lua_assert(cl->nupvalues == cl->p->sizeupvalues); + luai_verifycode(L, cl->p); + return cl; +} + diff --git a/lua/lundump.h b/lua/lundump.h new file mode 100644 index 0000000..f3748a9 --- /dev/null +++ b/lua/lundump.h @@ -0,0 +1,36 @@ +/* +** $Id: lundump.h $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#ifndef lundump_h +#define lundump_h + +#include "llimits.h" +#include "lobject.h" +#include "lzio.h" + + +/* data to catch conversion errors */ +#define LUAC_DATA "\x19\x93\r\n\x1a\n" + +#define LUAC_INT 0x5678 +#define LUAC_NUM cast_num(370.5) + +/* +** Encode major-minor version in one byte, one nibble for each +*/ +#define MYINT(s) (s[0]-'0') /* assume one-digit numerals */ +#define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)) + +#define LUAC_FORMAT 0 /* this is the official format */ + +/* load one chunk; from lundump.c */ +LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name); + +/* dump one chunk; from ldump.c */ +LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, + void* data, int strip); + +#endif diff --git a/lua/lutf8lib.c b/lua/lutf8lib.c new file mode 100644 index 0000000..901d985 --- /dev/null +++ b/lua/lutf8lib.c @@ -0,0 +1,289 @@ +/* +** $Id: lutf8lib.c $ +** Standard library for UTF-8 manipulation +** See Copyright Notice in lua.h +*/ + +#define lutf8lib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#define MAXUNICODE 0x10FFFFu + +#define MAXUTF 0x7FFFFFFFu + +/* +** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits. +*/ +#if (UINT_MAX >> 30) >= 1 +typedef unsigned int utfint; +#else +typedef unsigned long utfint; +#endif + + +#define iscont(p) ((*(p) & 0xC0) == 0x80) + + +/* from strlib */ +/* translate a relative string position: negative means back from end */ +static lua_Integer u_posrelat (lua_Integer pos, size_t len) { + if (pos >= 0) return pos; + else if (0u - (size_t)pos > len) return 0; + else return (lua_Integer)len + pos + 1; +} + + +/* +** Decode one UTF-8 sequence, returning NULL if byte sequence is +** invalid. The array 'limits' stores the minimum value for each +** sequence length, to check for overlong representations. Its first +** entry forces an error for non-ascii bytes with no continuation +** bytes (count == 0). +*/ +static const char *utf8_decode (const char *s, utfint *val, int strict) { + static const utfint limits[] = + {~(utfint)0, 0x80, 0x800, 0x10000u, 0x200000u, 0x4000000u}; + unsigned int c = (unsigned char)s[0]; + utfint res = 0; /* final result */ + if (c < 0x80) /* ascii? */ + res = c; + else { + int count = 0; /* to count number of continuation bytes */ + for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */ + unsigned int cc = (unsigned char)s[++count]; /* read next byte */ + if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ + return NULL; /* invalid byte sequence */ + res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ + } + res |= ((utfint)(c & 0x7F) << (count * 5)); /* add first byte */ + if (count > 5 || res > MAXUTF || res < limits[count]) + return NULL; /* invalid byte sequence */ + s += count; /* skip continuation bytes read */ + } + if (strict) { + /* check for invalid code points; too large or surrogates */ + if (res > MAXUNICODE || (0xD800u <= res && res <= 0xDFFFu)) + return NULL; + } + if (val) *val = res; + return s + 1; /* +1 to include first byte */ +} + + +/* +** utf8len(s [, i [, j [, lax]]]) --> number of characters that +** start in the range [i,j], or nil + current position if 's' is not +** well formed in that interval +*/ +static int utflen (lua_State *L) { + lua_Integer n = 0; /* counter for the number of characters */ + size_t len; /* string length in bytes */ + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); + lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); + int lax = lua_toboolean(L, 4); + luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, + "initial position out of bounds"); + luaL_argcheck(L, --posj < (lua_Integer)len, 3, + "final position out of bounds"); + while (posi <= posj) { + const char *s1 = utf8_decode(s + posi, NULL, !lax); + if (s1 == NULL) { /* conversion error? */ + luaL_pushfail(L); /* return fail ... */ + lua_pushinteger(L, posi + 1); /* ... and current position */ + return 2; + } + posi = s1 - s; + n++; + } + lua_pushinteger(L, n); + return 1; +} + + +/* +** codepoint(s, [i, [j [, lax]]]) -> returns codepoints for all +** characters that start in the range [i,j] +*/ +static int codepoint (lua_State *L) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); + lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); + int lax = lua_toboolean(L, 4); + int n; + const char *se; + luaL_argcheck(L, posi >= 1, 2, "out of bounds"); + luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of bounds"); + if (posi > pose) return 0; /* empty interval; return no values */ + if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */ + return luaL_error(L, "string slice too long"); + n = (int)(pose - posi) + 1; /* upper bound for number of returns */ + luaL_checkstack(L, n, "string slice too long"); + n = 0; /* count the number of returns */ + se = s + pose; /* string end */ + for (s += posi - 1; s < se;) { + utfint code; + s = utf8_decode(s, &code, !lax); + if (s == NULL) + return luaL_error(L, "invalid UTF-8 code"); + lua_pushinteger(L, code); + n++; + } + return n; +} + + +static void pushutfchar (lua_State *L, int arg) { + lua_Unsigned code = (lua_Unsigned)luaL_checkinteger(L, arg); + luaL_argcheck(L, code <= MAXUTF, arg, "value out of range"); + lua_pushfstring(L, "%U", (long)code); +} + + +/* +** utfchar(n1, n2, ...) -> char(n1)..char(n2)... +*/ +static int utfchar (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + if (n == 1) /* optimize common case of single char */ + pushutfchar(L, 1); + else { + int i; + luaL_Buffer b; + luaL_buffinit(L, &b); + for (i = 1; i <= n; i++) { + pushutfchar(L, i); + luaL_addvalue(&b); + } + luaL_pushresult(&b); + } + return 1; +} + + +/* +** offset(s, n, [i]) -> index where n-th character counting from +** position 'i' starts; 0 means character at 'i'. +*/ +static int byteoffset (lua_State *L) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer n = luaL_checkinteger(L, 2); + lua_Integer posi = (n >= 0) ? 1 : len + 1; + posi = u_posrelat(luaL_optinteger(L, 3, posi), len); + luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, + "position out of bounds"); + if (n == 0) { + /* find beginning of current byte sequence */ + while (posi > 0 && iscont(s + posi)) posi--; + } + else { + if (iscont(s + posi)) + return luaL_error(L, "initial position is a continuation byte"); + if (n < 0) { + while (n < 0 && posi > 0) { /* move back */ + do { /* find beginning of previous character */ + posi--; + } while (posi > 0 && iscont(s + posi)); + n++; + } + } + else { + n--; /* do not move for 1st character */ + while (n > 0 && posi < (lua_Integer)len) { + do { /* find beginning of next character */ + posi++; + } while (iscont(s + posi)); /* (cannot pass final '\0') */ + n--; + } + } + } + if (n == 0) /* did it find given character? */ + lua_pushinteger(L, posi + 1); + else /* no such character */ + luaL_pushfail(L); + return 1; +} + + +static int iter_aux (lua_State *L, int strict) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer n = lua_tointeger(L, 2) - 1; + if (n < 0) /* first iteration? */ + n = 0; /* start from here */ + else if (n < (lua_Integer)len) { + n++; /* skip current byte */ + while (iscont(s + n)) n++; /* and its continuations */ + } + if (n >= (lua_Integer)len) + return 0; /* no more codepoints */ + else { + utfint code; + const char *next = utf8_decode(s + n, &code, strict); + if (next == NULL) + return luaL_error(L, "invalid UTF-8 code"); + lua_pushinteger(L, n + 1); + lua_pushinteger(L, code); + return 2; + } +} + + +static int iter_auxstrict (lua_State *L) { + return iter_aux(L, 1); +} + +static int iter_auxlax (lua_State *L) { + return iter_aux(L, 0); +} + + +static int iter_codes (lua_State *L) { + int lax = lua_toboolean(L, 2); + luaL_checkstring(L, 1); + lua_pushcfunction(L, lax ? iter_auxlax : iter_auxstrict); + lua_pushvalue(L, 1); + lua_pushinteger(L, 0); + return 3; +} + + +/* pattern to match a single UTF-8 character */ +#define UTF8PATT "[\0-\x7F\xC2-\xFD][\x80-\xBF]*" + + +static const luaL_Reg funcs[] = { + {"offset", byteoffset}, + {"codepoint", codepoint}, + {"char", utfchar}, + {"len", utflen}, + {"codes", iter_codes}, + /* placeholders */ + {"charpattern", NULL}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_utf8 (lua_State *L) { + luaL_newlib(L, funcs); + lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1); + lua_setfield(L, -2, "charpattern"); + return 1; +} + diff --git a/lua/lvm.c b/lua/lvm.c new file mode 100644 index 0000000..c9729bc --- /dev/null +++ b/lua/lvm.c @@ -0,0 +1,1836 @@ +/* +** $Id: lvm.c $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#define lvm_c +#define LUA_CORE + +#include "lprefix.h" + +#include +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + +/* +** By default, use jump tables in the main interpreter loop on gcc +** and compatible compilers. +*/ +#if !defined(LUA_USE_JUMPTABLE) +#if defined(__GNUC__) +#define LUA_USE_JUMPTABLE 1 +#else +#define LUA_USE_JUMPTABLE 0 +#endif +#endif + + + +/* limit for table tag-method chains (to avoid infinite loops) */ +#define MAXTAGLOOP 2000 + + +/* +** 'l_intfitsf' checks whether a given integer is in the range that +** can be converted to a float without rounding. Used in comparisons. +*/ + +/* number of bits in the mantissa of a float */ +#define NBM (l_floatatt(MANT_DIG)) + +/* +** Check whether some integers may not fit in a float, testing whether +** (maxinteger >> NBM) > 0. (That implies (1 << NBM) <= maxinteger.) +** (The shifts are done in parts, to avoid shifting by more than the size +** of an integer. In a worst case, NBM == 113 for long double and +** sizeof(long) == 32.) +*/ +#if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \ + >> (NBM - (3 * (NBM / 4)))) > 0 + +/* limit for integers that fit in a float */ +#define MAXINTFITSF ((lua_Unsigned)1 << NBM) + +/* check whether 'i' is in the interval [-MAXINTFITSF, MAXINTFITSF] */ +#define l_intfitsf(i) ((MAXINTFITSF + l_castS2U(i)) <= (2 * MAXINTFITSF)) + +#else /* all integers fit in a float precisely */ + +#define l_intfitsf(i) 1 + +#endif + + +/* +** Try to convert a value from string to a number value. +** If the value is not a string or is a string not representing +** a valid numeral (or if coercions from strings to numbers +** are disabled via macro 'cvt2num'), do not modify 'result' +** and return 0. +*/ +static int l_strton (const TValue *obj, TValue *result) { + lua_assert(obj != result); + if (!cvt2num(obj)) /* is object not a string? */ + return 0; + else + return (luaO_str2num(svalue(obj), result) == vslen(obj) + 1); +} + + +/* +** Try to convert a value to a float. The float case is already handled +** by the macro 'tonumber'. +*/ +int luaV_tonumber_ (const TValue *obj, lua_Number *n) { + TValue v; + if (ttisinteger(obj)) { + *n = cast_num(ivalue(obj)); + return 1; + } + else if (l_strton(obj, &v)) { /* string coercible to number? */ + *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ + return 1; + } + else + return 0; /* conversion failed */ +} + + +/* +** try to convert a float to an integer, rounding according to 'mode'. +*/ +int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode) { + lua_Number f = l_floor(n); + if (n != f) { /* not an integral value? */ + if (mode == F2Ieq) return 0; /* fails if mode demands integral value */ + else if (mode == F2Iceil) /* needs ceil? */ + f += 1; /* convert floor to ceil (remember: n != f) */ + } + return lua_numbertointeger(f, p); +} + + +/* +** try to convert a value to an integer, rounding according to 'mode', +** without string coercion. +** ("Fast track" handled by macro 'tointegerns'.) +*/ +int luaV_tointegerns (const TValue *obj, lua_Integer *p, F2Imod mode) { + if (ttisfloat(obj)) + return luaV_flttointeger(fltvalue(obj), p, mode); + else if (ttisinteger(obj)) { + *p = ivalue(obj); + return 1; + } + else + return 0; +} + + +/* +** try to convert a value to an integer. +*/ +int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode) { + TValue v; + if (l_strton(obj, &v)) /* does 'obj' point to a numerical string? */ + obj = &v; /* change it to point to its corresponding number */ + return luaV_tointegerns(obj, p, mode); +} + + +/* +** Try to convert a 'for' limit to an integer, preserving the semantics +** of the loop. Return true if the loop must not run; otherwise, '*p' +** gets the integer limit. +** (The following explanation assumes a positive step; it is valid for +** negative steps mutatis mutandis.) +** If the limit is an integer or can be converted to an integer, +** rounding down, that is the limit. +** Otherwise, check whether the limit can be converted to a float. If +** the float is too large, clip it to LUA_MAXINTEGER. If the float +** is too negative, the loop should not run, because any initial +** integer value is greater than such limit; so, the function returns +** true to signal that. (For this latter case, no integer limit would be +** correct; even a limit of LUA_MININTEGER would run the loop once for +** an initial value equal to LUA_MININTEGER.) +*/ +static int forlimit (lua_State *L, lua_Integer init, const TValue *lim, + lua_Integer *p, lua_Integer step) { + if (!luaV_tointeger(lim, p, (step < 0 ? F2Iceil : F2Ifloor))) { + /* not coercible to in integer */ + lua_Number flim; /* try to convert to float */ + if (!tonumber(lim, &flim)) /* cannot convert to float? */ + luaG_forerror(L, lim, "limit"); + /* else 'flim' is a float out of integer bounds */ + if (luai_numlt(0, flim)) { /* if it is positive, it is too large */ + if (step < 0) return 1; /* initial value must be less than it */ + *p = LUA_MAXINTEGER; /* truncate */ + } + else { /* it is less than min integer */ + if (step > 0) return 1; /* initial value must be greater than it */ + *p = LUA_MININTEGER; /* truncate */ + } + } + return (step > 0 ? init > *p : init < *p); /* not to run? */ +} + + +/* +** Prepare a numerical for loop (opcode OP_FORPREP). +** Return true to skip the loop. Otherwise, +** after preparation, stack will be as follows: +** ra : internal index (safe copy of the control variable) +** ra + 1 : loop counter (integer loops) or limit (float loops) +** ra + 2 : step +** ra + 3 : control variable +*/ +static int forprep (lua_State *L, StkId ra) { + TValue *pinit = s2v(ra); + TValue *plimit = s2v(ra + 1); + TValue *pstep = s2v(ra + 2); + if (ttisinteger(pinit) && ttisinteger(pstep)) { /* integer loop? */ + lua_Integer init = ivalue(pinit); + lua_Integer step = ivalue(pstep); + lua_Integer limit; + if (step == 0) + luaG_runerror(L, "'for' step is zero"); + setivalue(s2v(ra + 3), init); /* control variable */ + if (forlimit(L, init, plimit, &limit, step)) + return 1; /* skip the loop */ + else { /* prepare loop counter */ + lua_Unsigned count; + if (step > 0) { /* ascending loop? */ + count = l_castS2U(limit) - l_castS2U(init); + if (step != 1) /* avoid division in the too common case */ + count /= l_castS2U(step); + } + else { /* step < 0; descending loop */ + count = l_castS2U(init) - l_castS2U(limit); + /* 'step+1' avoids negating 'mininteger' */ + count /= l_castS2U(-(step + 1)) + 1u; + } + /* store the counter in place of the limit (which won't be + needed anymore) */ + setivalue(plimit, l_castU2S(count)); + } + } + else { /* try making all values floats */ + lua_Number init; lua_Number limit; lua_Number step; + if (l_unlikely(!tonumber(plimit, &limit))) + luaG_forerror(L, plimit, "limit"); + if (l_unlikely(!tonumber(pstep, &step))) + luaG_forerror(L, pstep, "step"); + if (l_unlikely(!tonumber(pinit, &init))) + luaG_forerror(L, pinit, "initial value"); + if (step == 0) + luaG_runerror(L, "'for' step is zero"); + if (luai_numlt(0, step) ? luai_numlt(limit, init) + : luai_numlt(init, limit)) + return 1; /* skip the loop */ + else { + /* make sure internal values are all floats */ + setfltvalue(plimit, limit); + setfltvalue(pstep, step); + setfltvalue(s2v(ra), init); /* internal index */ + setfltvalue(s2v(ra + 3), init); /* control variable */ + } + } + return 0; +} + + +/* +** Execute a step of a float numerical for loop, returning +** true iff the loop must continue. (The integer case is +** written online with opcode OP_FORLOOP, for performance.) +*/ +static int floatforloop (StkId ra) { + lua_Number step = fltvalue(s2v(ra + 2)); + lua_Number limit = fltvalue(s2v(ra + 1)); + lua_Number idx = fltvalue(s2v(ra)); /* internal index */ + idx = luai_numadd(L, idx, step); /* increment index */ + if (luai_numlt(0, step) ? luai_numle(idx, limit) + : luai_numle(limit, idx)) { + chgfltvalue(s2v(ra), idx); /* update internal index */ + setfltvalue(s2v(ra + 3), idx); /* and control variable */ + return 1; /* jump back */ + } + else + return 0; /* finish the loop */ +} + + +/* +** Finish the table access 'val = t[key]'. +** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to +** t[k] entry (which must be empty). +*/ +void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, + const TValue *slot) { + int loop; /* counter to avoid infinite loops */ + const TValue *tm; /* metamethod */ + for (loop = 0; loop < MAXTAGLOOP; loop++) { + if (slot == NULL) { /* 't' is not a table? */ + lua_assert(!ttistable(t)); + tm = luaT_gettmbyobj(L, t, TM_INDEX); + if (l_unlikely(notm(tm))) + luaG_typeerror(L, t, "index"); /* no metamethod */ + /* else will try the metamethod */ + } + else { /* 't' is a table */ + lua_assert(isempty(slot)); + tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ + if (tm == NULL) { /* no metamethod? */ + setnilvalue(s2v(val)); /* result is nil */ + return; + } + /* else will try the metamethod */ + } + if (ttisfunction(tm)) { /* is metamethod a function? */ + luaT_callTMres(L, tm, t, key, val); /* call it */ + return; + } + t = tm; /* else try to access 'tm[key]' */ + if (luaV_fastget(L, t, key, slot, luaH_get)) { /* fast track? */ + setobj2s(L, val, slot); /* done */ + return; + } + /* else repeat (tail call 'luaV_finishget') */ + } + luaG_runerror(L, "'__index' chain too long; possible loop"); +} + + +/* +** Finish a table assignment 't[key] = val'. +** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points +** to the entry 't[key]', or to a value with an absent key if there +** is no such entry. (The value at 'slot' must be empty, otherwise +** 'luaV_fastget' would have done the job.) +*/ +void luaV_finishset (lua_State *L, const TValue *t, TValue *key, + TValue *val, const TValue *slot) { + int loop; /* counter to avoid infinite loops */ + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; /* '__newindex' metamethod */ + if (slot != NULL) { /* is 't' a table? */ + Table *h = hvalue(t); /* save 't' table */ + lua_assert(isempty(slot)); /* slot must be empty */ + tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ + if (tm == NULL) { /* no metamethod? */ + luaH_finishset(L, h, key, slot, val); /* set new value */ + invalidateTMcache(h); + luaC_barrierback(L, obj2gco(h), val); + return; + } + /* else will try the metamethod */ + } + else { /* not a table; check metamethod */ + tm = luaT_gettmbyobj(L, t, TM_NEWINDEX); + if (l_unlikely(notm(tm))) + luaG_typeerror(L, t, "index"); + } + /* try the metamethod */ + if (ttisfunction(tm)) { + luaT_callTM(L, tm, t, key, val); + return; + } + t = tm; /* else repeat assignment over 'tm' */ + if (luaV_fastget(L, t, key, slot, luaH_get)) { + luaV_finishfastset(L, t, slot, val); + return; /* done */ + } + /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */ + } + luaG_runerror(L, "'__newindex' chain too long; possible loop"); +} + + +/* +** Compare two strings 'ls' x 'rs', returning an integer less-equal- +** -greater than zero if 'ls' is less-equal-greater than 'rs'. +** The code is a little tricky because it allows '\0' in the strings +** and it uses 'strcoll' (to respect locales) for each segments +** of the strings. +*/ +static int l_strcmp (const TString *ls, const TString *rs) { + const char *l = getstr(ls); + size_t ll = tsslen(ls); + const char *r = getstr(rs); + size_t lr = tsslen(rs); + for (;;) { /* for each segment */ + int temp = strcoll(l, r); + if (temp != 0) /* not equal? */ + return temp; /* done */ + else { /* strings are equal up to a '\0' */ + size_t len = strlen(l); /* index of first '\0' in both strings */ + if (len == lr) /* 'rs' is finished? */ + return (len == ll) ? 0 : 1; /* check 'ls' */ + else if (len == ll) /* 'ls' is finished? */ + return -1; /* 'ls' is less than 'rs' ('rs' is not finished) */ + /* both strings longer than 'len'; go on comparing after the '\0' */ + len++; + l += len; ll -= len; r += len; lr -= len; + } + } +} + + +/* +** Check whether integer 'i' is less than float 'f'. If 'i' has an +** exact representation as a float ('l_intfitsf'), compare numbers as +** floats. Otherwise, use the equivalence 'i < f <=> i < ceil(f)'. +** If 'ceil(f)' is out of integer range, either 'f' is greater than +** all integers or less than all integers. +** (The test with 'l_intfitsf' is only for performance; the else +** case is correct for all values, but it is slow due to the conversion +** from float to int.) +** When 'f' is NaN, comparisons must result in false. +*/ +static int LTintfloat (lua_Integer i, lua_Number f) { + if (l_intfitsf(i)) + return luai_numlt(cast_num(i), f); /* compare them as floats */ + else { /* i < f <=> i < ceil(f) */ + lua_Integer fi; + if (luaV_flttointeger(f, &fi, F2Iceil)) /* fi = ceil(f) */ + return i < fi; /* compare them as integers */ + else /* 'f' is either greater or less than all integers */ + return f > 0; /* greater? */ + } +} + + +/* +** Check whether integer 'i' is less than or equal to float 'f'. +** See comments on previous function. +*/ +static int LEintfloat (lua_Integer i, lua_Number f) { + if (l_intfitsf(i)) + return luai_numle(cast_num(i), f); /* compare them as floats */ + else { /* i <= f <=> i <= floor(f) */ + lua_Integer fi; + if (luaV_flttointeger(f, &fi, F2Ifloor)) /* fi = floor(f) */ + return i <= fi; /* compare them as integers */ + else /* 'f' is either greater or less than all integers */ + return f > 0; /* greater? */ + } +} + + +/* +** Check whether float 'f' is less than integer 'i'. +** See comments on previous function. +*/ +static int LTfloatint (lua_Number f, lua_Integer i) { + if (l_intfitsf(i)) + return luai_numlt(f, cast_num(i)); /* compare them as floats */ + else { /* f < i <=> floor(f) < i */ + lua_Integer fi; + if (luaV_flttointeger(f, &fi, F2Ifloor)) /* fi = floor(f) */ + return fi < i; /* compare them as integers */ + else /* 'f' is either greater or less than all integers */ + return f < 0; /* less? */ + } +} + + +/* +** Check whether float 'f' is less than or equal to integer 'i'. +** See comments on previous function. +*/ +static int LEfloatint (lua_Number f, lua_Integer i) { + if (l_intfitsf(i)) + return luai_numle(f, cast_num(i)); /* compare them as floats */ + else { /* f <= i <=> ceil(f) <= i */ + lua_Integer fi; + if (luaV_flttointeger(f, &fi, F2Iceil)) /* fi = ceil(f) */ + return fi <= i; /* compare them as integers */ + else /* 'f' is either greater or less than all integers */ + return f < 0; /* less? */ + } +} + + +/* +** Return 'l < r', for numbers. +*/ +static int LTnum (const TValue *l, const TValue *r) { + lua_assert(ttisnumber(l) && ttisnumber(r)); + if (ttisinteger(l)) { + lua_Integer li = ivalue(l); + if (ttisinteger(r)) + return li < ivalue(r); /* both are integers */ + else /* 'l' is int and 'r' is float */ + return LTintfloat(li, fltvalue(r)); /* l < r ? */ + } + else { + lua_Number lf = fltvalue(l); /* 'l' must be float */ + if (ttisfloat(r)) + return luai_numlt(lf, fltvalue(r)); /* both are float */ + else /* 'l' is float and 'r' is int */ + return LTfloatint(lf, ivalue(r)); + } +} + + +/* +** Return 'l <= r', for numbers. +*/ +static int LEnum (const TValue *l, const TValue *r) { + lua_assert(ttisnumber(l) && ttisnumber(r)); + if (ttisinteger(l)) { + lua_Integer li = ivalue(l); + if (ttisinteger(r)) + return li <= ivalue(r); /* both are integers */ + else /* 'l' is int and 'r' is float */ + return LEintfloat(li, fltvalue(r)); /* l <= r ? */ + } + else { + lua_Number lf = fltvalue(l); /* 'l' must be float */ + if (ttisfloat(r)) + return luai_numle(lf, fltvalue(r)); /* both are float */ + else /* 'l' is float and 'r' is int */ + return LEfloatint(lf, ivalue(r)); + } +} + + +/* +** return 'l < r' for non-numbers. +*/ +static int lessthanothers (lua_State *L, const TValue *l, const TValue *r) { + lua_assert(!ttisnumber(l) || !ttisnumber(r)); + if (ttisstring(l) && ttisstring(r)) /* both are strings? */ + return l_strcmp(tsvalue(l), tsvalue(r)) < 0; + else + return luaT_callorderTM(L, l, r, TM_LT); +} + + +/* +** Main operation less than; return 'l < r'. +*/ +int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { + if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */ + return LTnum(l, r); + else return lessthanothers(L, l, r); +} + + +/* +** return 'l <= r' for non-numbers. +*/ +static int lessequalothers (lua_State *L, const TValue *l, const TValue *r) { + lua_assert(!ttisnumber(l) || !ttisnumber(r)); + if (ttisstring(l) && ttisstring(r)) /* both are strings? */ + return l_strcmp(tsvalue(l), tsvalue(r)) <= 0; + else + return luaT_callorderTM(L, l, r, TM_LE); +} + + +/* +** Main operation less than or equal to; return 'l <= r'. +*/ +int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { + if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */ + return LEnum(l, r); + else return lessequalothers(L, l, r); +} + + +/* +** Main operation for equality of Lua values; return 't1 == t2'. +** L == NULL means raw equality (no metamethods) +*/ +int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { + const TValue *tm; + if (ttypetag(t1) != ttypetag(t2)) { /* not the same variant? */ + if (ttype(t1) != ttype(t2) || ttype(t1) != LUA_TNUMBER) + return 0; /* only numbers can be equal with different variants */ + else { /* two numbers with different variants */ + /* One of them is an integer. If the other does not have an + integer value, they cannot be equal; otherwise, compare their + integer values. */ + lua_Integer i1, i2; + return (luaV_tointegerns(t1, &i1, F2Ieq) && + luaV_tointegerns(t2, &i2, F2Ieq) && + i1 == i2); + } + } + /* values have same type and same variant */ + switch (ttypetag(t1)) { + case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: return 1; + case LUA_VNUMINT: return (ivalue(t1) == ivalue(t2)); + case LUA_VNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2)); + case LUA_VLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); + case LUA_VLCF: return fvalue(t1) == fvalue(t2); + case LUA_VSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2)); + case LUA_VLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2)); + case LUA_VUSERDATA: { + if (uvalue(t1) == uvalue(t2)) return 1; + else if (L == NULL) return 0; + tm = fasttm(L, uvalue(t1)->metatable, TM_EQ); + if (tm == NULL) + tm = fasttm(L, uvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + case LUA_VTABLE: { + if (hvalue(t1) == hvalue(t2)) return 1; + else if (L == NULL) return 0; + tm = fasttm(L, hvalue(t1)->metatable, TM_EQ); + if (tm == NULL) + tm = fasttm(L, hvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + default: + return gcvalue(t1) == gcvalue(t2); + } + if (tm == NULL) /* no TM? */ + return 0; /* objects are different */ + else { + luaT_callTMres(L, tm, t1, t2, L->top); /* call TM */ + return !l_isfalse(s2v(L->top)); + } +} + + +/* macro used by 'luaV_concat' to ensure that element at 'o' is a string */ +#define tostring(L,o) \ + (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1))) + +#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0) + +/* copy strings in stack from top - n up to top - 1 to buffer */ +static void copy2buff (StkId top, int n, char *buff) { + size_t tl = 0; /* size already copied */ + do { + size_t l = vslen(s2v(top - n)); /* length of string being copied */ + memcpy(buff + tl, svalue(s2v(top - n)), l * sizeof(char)); + tl += l; + } while (--n > 0); +} + + +/* +** Main operation for concatenation: concat 'total' values in the stack, +** from 'L->top - total' up to 'L->top - 1'. +*/ +void luaV_concat (lua_State *L, int total) { + if (total == 1) + return; /* "all" values already concatenated */ + do { + StkId top = L->top; + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (!(ttisstring(s2v(top - 2)) || cvt2str(s2v(top - 2))) || + !tostring(L, s2v(top - 1))) + luaT_tryconcatTM(L); + else if (isemptystr(s2v(top - 1))) /* second operand is empty? */ + cast_void(tostring(L, s2v(top - 2))); /* result is first operand */ + else if (isemptystr(s2v(top - 2))) { /* first operand is empty string? */ + setobjs2s(L, top - 2, top - 1); /* result is second op. */ + } + else { + /* at least two non-empty string values; get as many as possible */ + size_t tl = vslen(s2v(top - 1)); + TString *ts; + /* collect total length and number of strings */ + for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) { + size_t l = vslen(s2v(top - n - 1)); + if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) + luaG_runerror(L, "string length overflow"); + tl += l; + } + if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ + char buff[LUAI_MAXSHORTLEN]; + copy2buff(top, n, buff); /* copy strings to buffer */ + ts = luaS_newlstr(L, buff, tl); + } + else { /* long string; copy strings directly to final result */ + ts = luaS_createlngstrobj(L, tl); + copy2buff(top, n, getstr(ts)); + } + setsvalue2s(L, top - n, ts); /* create result */ + } + total -= n-1; /* got 'n' strings to create 1 new */ + L->top -= n-1; /* popped 'n' strings and pushed one */ + } while (total > 1); /* repeat until only 1 result left */ +} + + +/* +** Main operation 'ra = #rb'. +*/ +void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { + const TValue *tm; + switch (ttypetag(rb)) { + case LUA_VTABLE: { + Table *h = hvalue(rb); + tm = fasttm(L, h->metatable, TM_LEN); + if (tm) break; /* metamethod? break switch to call it */ + setivalue(s2v(ra), luaH_getn(h)); /* else primitive len */ + return; + } + case LUA_VSHRSTR: { + setivalue(s2v(ra), tsvalue(rb)->shrlen); + return; + } + case LUA_VLNGSTR: { + setivalue(s2v(ra), tsvalue(rb)->u.lnglen); + return; + } + default: { /* try metamethod */ + tm = luaT_gettmbyobj(L, rb, TM_LEN); + if (l_unlikely(notm(tm))) /* no metamethod? */ + luaG_typeerror(L, rb, "get length of"); + break; + } + } + luaT_callTMres(L, tm, rb, rb, ra); +} + + +/* +** Integer division; return 'm // n', that is, floor(m/n). +** C division truncates its result (rounds towards zero). +** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer, +** otherwise 'floor(q) == trunc(q) - 1'. +*/ +lua_Integer luaV_idiv (lua_State *L, lua_Integer m, lua_Integer n) { + if (l_unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */ + if (n == 0) + luaG_runerror(L, "attempt to divide by zero"); + return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */ + } + else { + lua_Integer q = m / n; /* perform C division */ + if ((m ^ n) < 0 && m % n != 0) /* 'm/n' would be negative non-integer? */ + q -= 1; /* correct result for different rounding */ + return q; + } +} + + +/* +** Integer modulus; return 'm % n'. (Assume that C '%' with +** negative operands follows C99 behavior. See previous comment +** about luaV_idiv.) +*/ +lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { + if (l_unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */ + if (n == 0) + luaG_runerror(L, "attempt to perform 'n%%0'"); + return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */ + } + else { + lua_Integer r = m % n; + if (r != 0 && (r ^ n) < 0) /* 'm/n' would be non-integer negative? */ + r += n; /* correct result for different rounding */ + return r; + } +} + + +/* +** Float modulus +*/ +lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) { + lua_Number r; + luai_nummod(L, m, n, r); + return r; +} + + +/* number of bits in an integer */ +#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT) + +/* +** Shift left operation. (Shift right just negates 'y'.) +*/ +#define luaV_shiftr(x,y) luaV_shiftl(x,-(y)) + +lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { + if (y < 0) { /* shift right? */ + if (y <= -NBITS) return 0; + else return intop(>>, x, -y); + } + else { /* shift left */ + if (y >= NBITS) return 0; + else return intop(<<, x, y); + } +} + + +/* +** create a new Lua closure, push it in the stack, and initialize +** its upvalues. +*/ +static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, + StkId ra) { + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; + int i; + LClosure *ncl = luaF_newLclosure(L, nup); + ncl->p = p; + setclLvalue2s(L, ra, ncl); /* anchor new closure in stack */ + for (i = 0; i < nup; i++) { /* fill in its upvalues */ + if (uv[i].instack) /* upvalue refers to local variable? */ + ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx); + else /* get upvalue from enclosing function */ + ncl->upvals[i] = encup[uv[i].idx]; + luaC_objbarrier(L, ncl, ncl->upvals[i]); + } +} + + +/* +** finish execution of an opcode interrupted by a yield +*/ +void luaV_finishOp (lua_State *L) { + CallInfo *ci = L->ci; + StkId base = ci->func + 1; + Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ + OpCode op = GET_OPCODE(inst); + switch (op) { /* finish its execution */ + case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: { + setobjs2s(L, base + GETARG_A(*(ci->u.l.savedpc - 2)), --L->top); + break; + } + case OP_UNM: case OP_BNOT: case OP_LEN: + case OP_GETTABUP: case OP_GETTABLE: case OP_GETI: + case OP_GETFIELD: case OP_SELF: { + setobjs2s(L, base + GETARG_A(inst), --L->top); + break; + } + case OP_LT: case OP_LE: + case OP_LTI: case OP_LEI: + case OP_GTI: case OP_GEI: + case OP_EQ: { /* note that 'OP_EQI'/'OP_EQK' cannot yield */ + int res = !l_isfalse(s2v(L->top - 1)); + L->top--; +#if defined(LUA_COMPAT_LT_LE) + if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ + ci->callstatus ^= CIST_LEQ; /* clear mark */ + res = !res; /* negate result */ + } +#endif + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); + if (res != GETARG_k(inst)) /* condition failed? */ + ci->u.l.savedpc++; /* skip jump instruction */ + break; + } + case OP_CONCAT: { + StkId top = L->top - 1; /* top when 'luaT_tryconcatTM' was called */ + int a = GETARG_A(inst); /* first element to concatenate */ + int total = cast_int(top - 1 - (base + a)); /* yet to concatenate */ + setobjs2s(L, top - 2, top); /* put TM result in proper position */ + L->top = top - 1; /* top is one after last element (at top-2) */ + luaV_concat(L, total); /* concat them (may yield again) */ + break; + } + case OP_CLOSE: case OP_RETURN: { /* yielded closing variables */ + ci->u.l.savedpc--; /* repeat instruction to close other vars. */ + break; + } + default: { + /* only these other opcodes can yield */ + lua_assert(op == OP_TFORCALL || op == OP_CALL || + op == OP_TAILCALL || op == OP_SETTABUP || op == OP_SETTABLE || + op == OP_SETI || op == OP_SETFIELD); + break; + } + } +} + + + + +/* +** {================================================================== +** Macros for arithmetic/bitwise/comparison opcodes in 'luaV_execute' +** =================================================================== +*/ + +#define l_addi(L,a,b) intop(+, a, b) +#define l_subi(L,a,b) intop(-, a, b) +#define l_muli(L,a,b) intop(*, a, b) +#define l_band(a,b) intop(&, a, b) +#define l_bor(a,b) intop(|, a, b) +#define l_bxor(a,b) intop(^, a, b) + +#define l_lti(a,b) (a < b) +#define l_lei(a,b) (a <= b) +#define l_gti(a,b) (a > b) +#define l_gei(a,b) (a >= b) + + +/* +** Arithmetic operations with immediate operands. 'iop' is the integer +** operation, 'fop' is the float operation. +*/ +#define op_arithI(L,iop,fop) { \ + TValue *v1 = vRB(i); \ + int imm = GETARG_sC(i); \ + if (ttisinteger(v1)) { \ + lua_Integer iv1 = ivalue(v1); \ + pc++; setivalue(s2v(ra), iop(L, iv1, imm)); \ + } \ + else if (ttisfloat(v1)) { \ + lua_Number nb = fltvalue(v1); \ + lua_Number fimm = cast_num(imm); \ + pc++; setfltvalue(s2v(ra), fop(L, nb, fimm)); \ + }} + + +/* +** Auxiliary function for arithmetic operations over floats and others +** with two register operands. +*/ +#define op_arithf_aux(L,v1,v2,fop) { \ + lua_Number n1; lua_Number n2; \ + if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \ + pc++; setfltvalue(s2v(ra), fop(L, n1, n2)); \ + }} + + +/* +** Arithmetic operations over floats and others with register operands. +*/ +#define op_arithf(L,fop) { \ + TValue *v1 = vRB(i); \ + TValue *v2 = vRC(i); \ + op_arithf_aux(L, v1, v2, fop); } + + +/* +** Arithmetic operations with K operands for floats. +*/ +#define op_arithfK(L,fop) { \ + TValue *v1 = vRB(i); \ + TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \ + op_arithf_aux(L, v1, v2, fop); } + + +/* +** Arithmetic operations over integers and floats. +*/ +#define op_arith_aux(L,v1,v2,iop,fop) { \ + if (ttisinteger(v1) && ttisinteger(v2)) { \ + lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \ + pc++; setivalue(s2v(ra), iop(L, i1, i2)); \ + } \ + else op_arithf_aux(L, v1, v2, fop); } + + +/* +** Arithmetic operations with register operands. +*/ +#define op_arith(L,iop,fop) { \ + TValue *v1 = vRB(i); \ + TValue *v2 = vRC(i); \ + op_arith_aux(L, v1, v2, iop, fop); } + + +/* +** Arithmetic operations with K operands. +*/ +#define op_arithK(L,iop,fop) { \ + TValue *v1 = vRB(i); \ + TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \ + op_arith_aux(L, v1, v2, iop, fop); } + + +/* +** Bitwise operations with constant operand. +*/ +#define op_bitwiseK(L,op) { \ + TValue *v1 = vRB(i); \ + TValue *v2 = KC(i); \ + lua_Integer i1; \ + lua_Integer i2 = ivalue(v2); \ + if (tointegerns(v1, &i1)) { \ + pc++; setivalue(s2v(ra), op(i1, i2)); \ + }} + + +/* +** Bitwise operations with register operands. +*/ +#define op_bitwise(L,op) { \ + TValue *v1 = vRB(i); \ + TValue *v2 = vRC(i); \ + lua_Integer i1; lua_Integer i2; \ + if (tointegerns(v1, &i1) && tointegerns(v2, &i2)) { \ + pc++; setivalue(s2v(ra), op(i1, i2)); \ + }} + + +/* +** Order operations with register operands. 'opn' actually works +** for all numbers, but the fast track improves performance for +** integers. +*/ +#define op_order(L,opi,opn,other) { \ + int cond; \ + TValue *rb = vRB(i); \ + if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \ + lua_Integer ia = ivalue(s2v(ra)); \ + lua_Integer ib = ivalue(rb); \ + cond = opi(ia, ib); \ + } \ + else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \ + cond = opn(s2v(ra), rb); \ + else \ + Protect(cond = other(L, s2v(ra), rb)); \ + docondjump(); } + + +/* +** Order operations with immediate operand. (Immediate operand is +** always small enough to have an exact representation as a float.) +*/ +#define op_orderI(L,opi,opf,inv,tm) { \ + int cond; \ + int im = GETARG_sB(i); \ + if (ttisinteger(s2v(ra))) \ + cond = opi(ivalue(s2v(ra)), im); \ + else if (ttisfloat(s2v(ra))) { \ + lua_Number fa = fltvalue(s2v(ra)); \ + lua_Number fim = cast_num(im); \ + cond = opf(fa, fim); \ + } \ + else { \ + int isf = GETARG_C(i); \ + Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \ + } \ + docondjump(); } + +/* }================================================================== */ + + +/* +** {================================================================== +** Function 'luaV_execute': main interpreter loop +** =================================================================== +*/ + +/* +** some macros for common tasks in 'luaV_execute' +*/ + + +#define RA(i) (base+GETARG_A(i)) +#define RB(i) (base+GETARG_B(i)) +#define vRB(i) s2v(RB(i)) +#define KB(i) (k+GETARG_B(i)) +#define RC(i) (base+GETARG_C(i)) +#define vRC(i) s2v(RC(i)) +#define KC(i) (k+GETARG_C(i)) +#define RKC(i) ((TESTARG_k(i)) ? k + GETARG_C(i) : s2v(base + GETARG_C(i))) + + + +#define updatetrap(ci) (trap = ci->u.l.trap) + +#define updatebase(ci) (base = ci->func + 1) + + +#define updatestack(ci) \ + { if (l_unlikely(trap)) { updatebase(ci); ra = RA(i); } } + + +/* +** Execute a jump instruction. The 'updatetrap' allows signals to stop +** tight loops. (Without it, the local copy of 'trap' could never change.) +*/ +#define dojump(ci,i,e) { pc += GETARG_sJ(i) + e; updatetrap(ci); } + + +/* for test instructions, execute the jump instruction that follows it */ +#define donextjump(ci) { Instruction ni = *pc; dojump(ci, ni, 1); } + +/* +** do a conditional jump: skip next instruction if 'cond' is not what +** was expected (parameter 'k'), else do next instruction, which must +** be a jump. +*/ +#define docondjump() if (cond != GETARG_k(i)) pc++; else donextjump(ci); + + +/* +** Correct global 'pc'. +*/ +#define savepc(L) (ci->u.l.savedpc = pc) + + +/* +** Whenever code can raise errors, the global 'pc' and the global +** 'top' must be correct to report occasional errors. +*/ +#define savestate(L,ci) (savepc(L), L->top = ci->top) + + +/* +** Protect code that, in general, can raise errors, reallocate the +** stack, and change the hooks. +*/ +#define Protect(exp) (savestate(L,ci), (exp), updatetrap(ci)) + +/* special version that does not change the top */ +#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci)) + +/* +** Protect code that can only raise errors. (That is, it cannnot change +** the stack or hooks.) +*/ +#define halfProtect(exp) (savestate(L,ci), (exp)) + +/* 'c' is the limit of live values in the stack */ +#define checkGC(L,c) \ + { luaC_condGC(L, (savepc(L), L->top = (c)), \ + updatetrap(ci)); \ + luai_threadyield(L); } + + +/* fetch an instruction and prepare its execution */ +#define vmfetch() { \ + if (l_unlikely(trap)) { /* stack reallocation or hooks? */ \ + trap = luaG_traceexec(L, pc); /* handle hooks */ \ + updatebase(ci); /* correct stack */ \ + } \ + i = *(pc++); \ + ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \ +} + +#define vmdispatch(o) switch(o) +#define vmcase(l) case l: +#define vmbreak break + + +void luaV_execute (lua_State *L, CallInfo *ci) { + LClosure *cl; + TValue *k; + StkId base; + const Instruction *pc; + int trap; +#if LUA_USE_JUMPTABLE +#include "ljumptab.h" +#endif + startfunc: + trap = L->hookmask; + returning: /* trap already set */ + cl = clLvalue(s2v(ci->func)); + k = cl->p->k; + pc = ci->u.l.savedpc; + if (l_unlikely(trap)) { + if (pc == cl->p->code) { /* first instruction (not resuming)? */ + if (cl->p->is_vararg) + trap = 0; /* hooks will start after VARARGPREP instruction */ + else /* check 'call' hook */ + luaD_hookcall(L, ci); + } + ci->u.l.trap = 1; /* assume trap is on, for now */ + } + base = ci->func + 1; + /* main loop of interpreter */ + for (;;) { + Instruction i; /* instruction being executed */ + StkId ra; /* instruction's A register */ + vmfetch(); +// low-level line tracing for debugging Lua +// printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p))); + lua_assert(base == ci->func + 1); + lua_assert(base <= L->top && L->top < L->stack_last); + /* invalidate top for instructions not expecting it */ + lua_assert(isIT(i) || (cast_void(L->top = base), 1)); + vmdispatch (GET_OPCODE(i)) { + vmcase(OP_MOVE) { + setobjs2s(L, ra, RB(i)); + vmbreak; + } + vmcase(OP_LOADI) { + lua_Integer b = GETARG_sBx(i); + setivalue(s2v(ra), b); + vmbreak; + } + vmcase(OP_LOADF) { + int b = GETARG_sBx(i); + setfltvalue(s2v(ra), cast_num(b)); + vmbreak; + } + vmcase(OP_LOADK) { + TValue *rb = k + GETARG_Bx(i); + setobj2s(L, ra, rb); + vmbreak; + } + vmcase(OP_LOADKX) { + TValue *rb; + rb = k + GETARG_Ax(*pc); pc++; + setobj2s(L, ra, rb); + vmbreak; + } + vmcase(OP_LOADFALSE) { + setbfvalue(s2v(ra)); + vmbreak; + } + vmcase(OP_LFALSESKIP) { + setbfvalue(s2v(ra)); + pc++; /* skip next instruction */ + vmbreak; + } + vmcase(OP_LOADTRUE) { + setbtvalue(s2v(ra)); + vmbreak; + } + vmcase(OP_LOADNIL) { + int b = GETARG_B(i); + do { + setnilvalue(s2v(ra++)); + } while (b--); + vmbreak; + } + vmcase(OP_GETUPVAL) { + int b = GETARG_B(i); + setobj2s(L, ra, cl->upvals[b]->v); + vmbreak; + } + vmcase(OP_SETUPVAL) { + UpVal *uv = cl->upvals[GETARG_B(i)]; + setobj(L, uv->v, s2v(ra)); + luaC_barrier(L, uv, s2v(ra)); + vmbreak; + } + vmcase(OP_GETTABUP) { + const TValue *slot; + TValue *upval = cl->upvals[GETARG_B(i)]->v; + TValue *rc = KC(i); + TString *key = tsvalue(rc); /* key must be a string */ + if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) { + setobj2s(L, ra, slot); + } + else + Protect(luaV_finishget(L, upval, rc, ra, slot)); + vmbreak; + } + vmcase(OP_GETTABLE) { + const TValue *slot; + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Unsigned n; + if (ttisinteger(rc) /* fast track for integers? */ + ? (cast_void(n = ivalue(rc)), luaV_fastgeti(L, rb, n, slot)) + : luaV_fastget(L, rb, rc, slot, luaH_get)) { + setobj2s(L, ra, slot); + } + else + Protect(luaV_finishget(L, rb, rc, ra, slot)); + vmbreak; + } + vmcase(OP_GETI) { + const TValue *slot; + TValue *rb = vRB(i); + int c = GETARG_C(i); + if (luaV_fastgeti(L, rb, c, slot)) { + setobj2s(L, ra, slot); + } + else { + TValue key; + setivalue(&key, c); + Protect(luaV_finishget(L, rb, &key, ra, slot)); + } + vmbreak; + } + vmcase(OP_GETFIELD) { + const TValue *slot; + TValue *rb = vRB(i); + TValue *rc = KC(i); + TString *key = tsvalue(rc); /* key must be a string */ + if (luaV_fastget(L, rb, key, slot, luaH_getshortstr)) { + setobj2s(L, ra, slot); + } + else + Protect(luaV_finishget(L, rb, rc, ra, slot)); + vmbreak; + } + vmcase(OP_SETTABUP) { + const TValue *slot; + TValue *upval = cl->upvals[GETARG_A(i)]->v; + TValue *rb = KB(i); + TValue *rc = RKC(i); + TString *key = tsvalue(rb); /* key must be a string */ + if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) { + luaV_finishfastset(L, upval, slot, rc); + } + else + Protect(luaV_finishset(L, upval, rb, rc, slot)); + vmbreak; + } + vmcase(OP_SETTABLE) { + const TValue *slot; + TValue *rb = vRB(i); /* key (table is in 'ra') */ + TValue *rc = RKC(i); /* value */ + lua_Unsigned n; + if (ttisinteger(rb) /* fast track for integers? */ + ? (cast_void(n = ivalue(rb)), luaV_fastgeti(L, s2v(ra), n, slot)) + : luaV_fastget(L, s2v(ra), rb, slot, luaH_get)) { + luaV_finishfastset(L, s2v(ra), slot, rc); + } + else + Protect(luaV_finishset(L, s2v(ra), rb, rc, slot)); + vmbreak; + } + vmcase(OP_SETI) { + const TValue *slot; + int c = GETARG_B(i); + TValue *rc = RKC(i); + if (luaV_fastgeti(L, s2v(ra), c, slot)) { + luaV_finishfastset(L, s2v(ra), slot, rc); + } + else { + TValue key; + setivalue(&key, c); + Protect(luaV_finishset(L, s2v(ra), &key, rc, slot)); + } + vmbreak; + } + vmcase(OP_SETFIELD) { + const TValue *slot; + TValue *rb = KB(i); + TValue *rc = RKC(i); + TString *key = tsvalue(rb); /* key must be a string */ + if (luaV_fastget(L, s2v(ra), key, slot, luaH_getshortstr)) { + luaV_finishfastset(L, s2v(ra), slot, rc); + } + else + Protect(luaV_finishset(L, s2v(ra), rb, rc, slot)); + vmbreak; + } + vmcase(OP_NEWTABLE) { + int b = GETARG_B(i); /* log2(hash size) + 1 */ + int c = GETARG_C(i); /* array size */ + Table *t; + if (b > 0) + b = 1 << (b - 1); /* size is 2^(b - 1) */ + lua_assert((!TESTARG_k(i)) == (GETARG_Ax(*pc) == 0)); + if (TESTARG_k(i)) /* non-zero extra argument? */ + c += GETARG_Ax(*pc) * (MAXARG_C + 1); /* add it to size */ + pc++; /* skip extra argument */ + L->top = ra + 1; /* correct top in case of emergency GC */ + t = luaH_new(L); /* memory allocation */ + sethvalue2s(L, ra, t); + if (b != 0 || c != 0) + luaH_resize(L, t, c, b); /* idem */ + checkGC(L, ra + 1); + vmbreak; + } + vmcase(OP_SELF) { + const TValue *slot; + TValue *rb = vRB(i); + TValue *rc = RKC(i); + TString *key = tsvalue(rc); /* key must be a string */ + setobj2s(L, ra + 1, rb); + if (luaV_fastget(L, rb, key, slot, luaH_getstr)) { + setobj2s(L, ra, slot); + } + else + Protect(luaV_finishget(L, rb, rc, ra, slot)); + vmbreak; + } + vmcase(OP_ADDI) { + op_arithI(L, l_addi, luai_numadd); + vmbreak; + } + vmcase(OP_ADDK) { + op_arithK(L, l_addi, luai_numadd); + vmbreak; + } + vmcase(OP_SUBK) { + op_arithK(L, l_subi, luai_numsub); + vmbreak; + } + vmcase(OP_MULK) { + op_arithK(L, l_muli, luai_nummul); + vmbreak; + } + vmcase(OP_MODK) { + op_arithK(L, luaV_mod, luaV_modf); + vmbreak; + } + vmcase(OP_POWK) { + op_arithfK(L, luai_numpow); + vmbreak; + } + vmcase(OP_DIVK) { + op_arithfK(L, luai_numdiv); + vmbreak; + } + vmcase(OP_IDIVK) { + op_arithK(L, luaV_idiv, luai_numidiv); + vmbreak; + } + vmcase(OP_BANDK) { + op_bitwiseK(L, l_band); + vmbreak; + } + vmcase(OP_BORK) { + op_bitwiseK(L, l_bor); + vmbreak; + } + vmcase(OP_BXORK) { + op_bitwiseK(L, l_bxor); + vmbreak; + } + vmcase(OP_SHRI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Integer ib; + if (tointegerns(rb, &ib)) { + pc++; setivalue(s2v(ra), luaV_shiftl(ib, -ic)); + } + vmbreak; + } + vmcase(OP_SHLI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Integer ib; + if (tointegerns(rb, &ib)) { + pc++; setivalue(s2v(ra), luaV_shiftl(ic, ib)); + } + vmbreak; + } + vmcase(OP_ADD) { + op_arith(L, l_addi, luai_numadd); + vmbreak; + } + vmcase(OP_SUB) { + op_arith(L, l_subi, luai_numsub); + vmbreak; + } + vmcase(OP_MUL) { + op_arith(L, l_muli, luai_nummul); + vmbreak; + } + vmcase(OP_MOD) { + op_arith(L, luaV_mod, luaV_modf); + vmbreak; + } + vmcase(OP_POW) { + op_arithf(L, luai_numpow); + vmbreak; + } + vmcase(OP_DIV) { /* float division (always with floats) */ + op_arithf(L, luai_numdiv); + vmbreak; + } + vmcase(OP_IDIV) { /* floor division */ + op_arith(L, luaV_idiv, luai_numidiv); + vmbreak; + } + vmcase(OP_BAND) { + op_bitwise(L, l_band); + vmbreak; + } + vmcase(OP_BOR) { + op_bitwise(L, l_bor); + vmbreak; + } + vmcase(OP_BXOR) { + op_bitwise(L, l_bxor); + vmbreak; + } + vmcase(OP_SHR) { + op_bitwise(L, luaV_shiftr); + vmbreak; + } + vmcase(OP_SHL) { + op_bitwise(L, luaV_shiftl); + vmbreak; + } + vmcase(OP_MMBIN) { + Instruction pi = *(pc - 2); /* original arith. expression */ + TValue *rb = vRB(i); + TMS tm = (TMS)GETARG_C(i); + StkId result = RA(pi); + lua_assert(OP_ADD <= GET_OPCODE(pi) && GET_OPCODE(pi) <= OP_SHR); + Protect(luaT_trybinTM(L, s2v(ra), rb, result, tm)); + vmbreak; + } + vmcase(OP_MMBINI) { + Instruction pi = *(pc - 2); /* original arith. expression */ + int imm = GETARG_sB(i); + TMS tm = (TMS)GETARG_C(i); + int flip = GETARG_k(i); + StkId result = RA(pi); + Protect(luaT_trybiniTM(L, s2v(ra), imm, flip, result, tm)); + vmbreak; + } + vmcase(OP_MMBINK) { + Instruction pi = *(pc - 2); /* original arith. expression */ + TValue *imm = KB(i); + TMS tm = (TMS)GETARG_C(i); + int flip = GETARG_k(i); + StkId result = RA(pi); + Protect(luaT_trybinassocTM(L, s2v(ra), imm, flip, result, tm)); + vmbreak; + } + vmcase(OP_UNM) { + TValue *rb = vRB(i); + lua_Number nb; + if (ttisinteger(rb)) { + lua_Integer ib = ivalue(rb); + setivalue(s2v(ra), intop(-, 0, ib)); + } + else if (tonumberns(rb, nb)) { + setfltvalue(s2v(ra), luai_numunm(L, nb)); + } + else + Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM)); + vmbreak; + } + vmcase(OP_BNOT) { + TValue *rb = vRB(i); + lua_Integer ib; + if (tointegerns(rb, &ib)) { + setivalue(s2v(ra), intop(^, ~l_castS2U(0), ib)); + } + else + Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT)); + vmbreak; + } + vmcase(OP_NOT) { + TValue *rb = vRB(i); + if (l_isfalse(rb)) + setbtvalue(s2v(ra)); + else + setbfvalue(s2v(ra)); + vmbreak; + } + vmcase(OP_LEN) { + Protect(luaV_objlen(L, ra, vRB(i))); + vmbreak; + } + vmcase(OP_CONCAT) { + int n = GETARG_B(i); /* number of elements to concatenate */ + L->top = ra + n; /* mark the end of concat operands */ + ProtectNT(luaV_concat(L, n)); + checkGC(L, L->top); /* 'luaV_concat' ensures correct top */ + vmbreak; + } + vmcase(OP_CLOSE) { + Protect(luaF_close(L, ra, LUA_OK, 1)); + vmbreak; + } + vmcase(OP_TBC) { + /* create new to-be-closed upvalue */ + halfProtect(luaF_newtbcupval(L, ra)); + vmbreak; + } + vmcase(OP_JMP) { + dojump(ci, i, 0); + vmbreak; + } + vmcase(OP_EQ) { + int cond; + TValue *rb = vRB(i); + Protect(cond = luaV_equalobj(L, s2v(ra), rb)); + docondjump(); + vmbreak; + } + vmcase(OP_LT) { + op_order(L, l_lti, LTnum, lessthanothers); + vmbreak; + } + vmcase(OP_LE) { + op_order(L, l_lei, LEnum, lessequalothers); + vmbreak; + } + vmcase(OP_EQK) { + TValue *rb = KB(i); + /* basic types do not use '__eq'; we can use raw equality */ + int cond = luaV_rawequalobj(s2v(ra), rb); + docondjump(); + vmbreak; + } + vmcase(OP_EQI) { + int cond; + int im = GETARG_sB(i); + if (ttisinteger(s2v(ra))) + cond = (ivalue(s2v(ra)) == im); + else if (ttisfloat(s2v(ra))) + cond = luai_numeq(fltvalue(s2v(ra)), cast_num(im)); + else + cond = 0; /* other types cannot be equal to a number */ + docondjump(); + vmbreak; + } + vmcase(OP_LTI) { + op_orderI(L, l_lti, luai_numlt, 0, TM_LT); + vmbreak; + } + vmcase(OP_LEI) { + op_orderI(L, l_lei, luai_numle, 0, TM_LE); + vmbreak; + } + vmcase(OP_GTI) { + op_orderI(L, l_gti, luai_numgt, 1, TM_LT); + vmbreak; + } + vmcase(OP_GEI) { + op_orderI(L, l_gei, luai_numge, 1, TM_LE); + vmbreak; + } + vmcase(OP_TEST) { + int cond = !l_isfalse(s2v(ra)); + docondjump(); + vmbreak; + } + vmcase(OP_TESTSET) { + TValue *rb = vRB(i); + if (l_isfalse(rb) == GETARG_k(i)) + pc++; + else { + setobj2s(L, ra, rb); + donextjump(ci); + } + vmbreak; + } + vmcase(OP_CALL) { + CallInfo *newci; + int b = GETARG_B(i); + int nresults = GETARG_C(i) - 1; + if (b != 0) /* fixed number of arguments? */ + L->top = ra + b; /* top signals number of arguments */ + /* else previous instruction set top */ + savepc(L); /* in case of errors */ + if ((newci = luaD_precall(L, ra, nresults)) == NULL) + updatetrap(ci); /* C call; nothing else to be done */ + else { /* Lua call: run function in this same C frame */ + ci = newci; + ci->callstatus = 0; /* call re-uses 'luaV_execute' */ + goto startfunc; + } + vmbreak; + } + vmcase(OP_TAILCALL) { + int b = GETARG_B(i); /* number of arguments + 1 (function) */ + int nparams1 = GETARG_C(i); + /* delta is virtual 'func' - real 'func' (vararg functions) */ + int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0; + if (b != 0) + L->top = ra + b; + else /* previous instruction set top */ + b = cast_int(L->top - ra); + savepc(ci); /* several calls here can raise errors */ + if (TESTARG_k(i)) { + luaF_closeupval(L, base); /* close upvalues from current call */ + lua_assert(L->tbclist < base); /* no pending tbc variables */ + lua_assert(base == ci->func + 1); + } + while (!ttisfunction(s2v(ra))) { /* not a function? */ + luaD_tryfuncTM(L, ra); /* try '__call' metamethod */ + b++; /* there is now one extra argument */ + checkstackGCp(L, 1, ra); + } + if (!ttisLclosure(s2v(ra))) { /* C function? */ + luaD_precall(L, ra, LUA_MULTRET); /* call it */ + updatetrap(ci); + updatestack(ci); /* stack may have been relocated */ + ci->func -= delta; /* restore 'func' (if vararg) */ + luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */ + updatetrap(ci); /* 'luaD_poscall' can change hooks */ + goto ret; /* caller returns after the tail call */ + } + ci->func -= delta; /* restore 'func' (if vararg) */ + luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ + goto startfunc; /* execute the callee */ + } + vmcase(OP_RETURN) { + int n = GETARG_B(i) - 1; /* number of results */ + int nparams1 = GETARG_C(i); + if (n < 0) /* not fixed? */ + n = cast_int(L->top - ra); /* get what is available */ + savepc(ci); + if (TESTARG_k(i)) { /* may there be open upvalues? */ + if (L->top < ci->top) + L->top = ci->top; + luaF_close(L, base, CLOSEKTOP, 1); + updatetrap(ci); + updatestack(ci); + } + if (nparams1) /* vararg function? */ + ci->func -= ci->u.l.nextraargs + nparams1; + L->top = ra + n; /* set call for 'luaD_poscall' */ + luaD_poscall(L, ci, n); + updatetrap(ci); /* 'luaD_poscall' can change hooks */ + goto ret; + } + vmcase(OP_RETURN0) { + if (l_unlikely(L->hookmask)) { + L->top = ra; + savepc(ci); + luaD_poscall(L, ci, 0); /* no hurry... */ + trap = 1; + } + else { /* do the 'poscall' here */ + int nres; + L->ci = ci->previous; /* back to caller */ + L->top = base - 1; + for (nres = ci->nresults; l_unlikely(nres > 0); nres--) + setnilvalue(s2v(L->top++)); /* all results are nil */ + } + goto ret; + } + vmcase(OP_RETURN1) { + if (l_unlikely(L->hookmask)) { + L->top = ra + 1; + savepc(ci); + luaD_poscall(L, ci, 1); /* no hurry... */ + trap = 1; + } + else { /* do the 'poscall' here */ + int nres = ci->nresults; + L->ci = ci->previous; /* back to caller */ + if (nres == 0) + L->top = base - 1; /* asked for no results */ + else { + setobjs2s(L, base - 1, ra); /* at least this result */ + L->top = base; + for (; l_unlikely(nres > 1); nres--) + setnilvalue(s2v(L->top++)); /* complete missing results */ + } + } + ret: /* return from a Lua function */ + if (ci->callstatus & CIST_FRESH) + return; /* end this frame */ + else { + ci = ci->previous; + goto returning; /* continue running caller in this frame */ + } + } + vmcase(OP_FORLOOP) { + if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ + lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); + if (count > 0) { /* still more iterations? */ + lua_Integer step = ivalue(s2v(ra + 2)); + lua_Integer idx = ivalue(s2v(ra)); /* internal index */ + chgivalue(s2v(ra + 1), count - 1); /* update counter */ + idx = intop(+, idx, step); /* add step to index */ + chgivalue(s2v(ra), idx); /* update internal index */ + setivalue(s2v(ra + 3), idx); /* and control variable */ + pc -= GETARG_Bx(i); /* jump back */ + } + } + else if (floatforloop(ra)) /* float loop */ + pc -= GETARG_Bx(i); /* jump back */ + updatetrap(ci); /* allows a signal to break the loop */ + vmbreak; + } + vmcase(OP_FORPREP) { + savestate(L, ci); /* in case of errors */ + if (forprep(L, ra)) + pc += GETARG_Bx(i) + 1; /* skip the loop */ + vmbreak; + } + vmcase(OP_TFORPREP) { + /* create to-be-closed upvalue (if needed) */ + halfProtect(luaF_newtbcupval(L, ra + 3)); + pc += GETARG_Bx(i); + i = *(pc++); /* go to next instruction */ + lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); + goto l_tforcall; + } + vmcase(OP_TFORCALL) { + l_tforcall: + /* 'ra' has the iterator function, 'ra + 1' has the state, + 'ra + 2' has the control variable, and 'ra + 3' has the + to-be-closed variable. The call will use the stack after + these values (starting at 'ra + 4') + */ + /* push function, state, and control variable */ + memcpy(ra + 4, ra, 3 * sizeof(*ra)); + L->top = ra + 4 + 3; + ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ + updatestack(ci); /* stack may have changed */ + i = *(pc++); /* go to next instruction */ + lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); + goto l_tforloop; + } + vmcase(OP_TFORLOOP) { + l_tforloop: + if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ + setobjs2s(L, ra + 2, ra + 4); /* save control variable */ + pc -= GETARG_Bx(i); /* jump back */ + } + vmbreak; + } + vmcase(OP_SETLIST) { + int n = GETARG_B(i); + unsigned int last = GETARG_C(i); + Table *h = hvalue(s2v(ra)); + if (n == 0) + n = cast_int(L->top - ra) - 1; /* get up to the top */ + else + L->top = ci->top; /* correct top in case of emergency GC */ + last += n; + if (TESTARG_k(i)) { + last += GETARG_Ax(*pc) * (MAXARG_C + 1); + pc++; + } + if (last > luaH_realasize(h)) /* needs more space? */ + luaH_resizearray(L, h, last); /* preallocate it at once */ + for (; n > 0; n--) { + TValue *val = s2v(ra + n); + setobj2t(L, &h->array[last - 1], val); + last--; + luaC_barrierback(L, obj2gco(h), val); + } + vmbreak; + } + vmcase(OP_CLOSURE) { + Proto *p = cl->p->p[GETARG_Bx(i)]; + halfProtect(pushclosure(L, p, cl->upvals, base, ra)); + checkGC(L, ra + 1); + vmbreak; + } + vmcase(OP_VARARG) { + int n = GETARG_C(i) - 1; /* required results */ + Protect(luaT_getvarargs(L, ci, ra, n)); + vmbreak; + } + vmcase(OP_VARARGPREP) { + ProtectNT(luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p)); + if (l_unlikely(trap)) { /* previous "Protect" updated trap */ + luaD_hookcall(L, ci); + L->oldpc = 1; /* next opcode will be seen as a "new" line */ + } + updatebase(ci); /* function has new base after adjustment */ + vmbreak; + } + vmcase(OP_EXTRAARG) { + lua_assert(0); + vmbreak; + } + } + } +} + +/* }================================================================== */ diff --git a/lua/lvm.h b/lua/lvm.h new file mode 100644 index 0000000..1bc16f3 --- /dev/null +++ b/lua/lvm.h @@ -0,0 +1,136 @@ +/* +** $Id: lvm.h $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lvm_h +#define lvm_h + + +#include "ldo.h" +#include "lobject.h" +#include "ltm.h" + + +#if !defined(LUA_NOCVTN2S) +#define cvt2str(o) ttisnumber(o) +#else +#define cvt2str(o) 0 /* no conversion from numbers to strings */ +#endif + + +#if !defined(LUA_NOCVTS2N) +#define cvt2num(o) ttisstring(o) +#else +#define cvt2num(o) 0 /* no conversion from strings to numbers */ +#endif + + +/* +** You can define LUA_FLOORN2I if you want to convert floats to integers +** by flooring them (instead of raising an error if they are not +** integral values) +*/ +#if !defined(LUA_FLOORN2I) +#define LUA_FLOORN2I F2Ieq +#endif + + +/* +** Rounding modes for float->integer coercion + */ +typedef enum { + F2Ieq, /* no rounding; accepts only integral values */ + F2Ifloor, /* takes the floor of the number */ + F2Iceil /* takes the ceil of the number */ +} F2Imod; + + +/* convert an object to a float (including string coercion) */ +#define tonumber(o,n) \ + (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n)) + + +/* convert an object to a float (without string coercion) */ +#define tonumberns(o,n) \ + (ttisfloat(o) ? ((n) = fltvalue(o), 1) : \ + (ttisinteger(o) ? ((n) = cast_num(ivalue(o)), 1) : 0)) + + +/* convert an object to an integer (including string coercion) */ +#define tointeger(o,i) \ + (l_likely(ttisinteger(o)) ? (*(i) = ivalue(o), 1) \ + : luaV_tointeger(o,i,LUA_FLOORN2I)) + + +/* convert an object to an integer (without string coercion) */ +#define tointegerns(o,i) \ + (l_likely(ttisinteger(o)) ? (*(i) = ivalue(o), 1) \ + : luaV_tointegerns(o,i,LUA_FLOORN2I)) + + +#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) + +#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) + + +/* +** fast track for 'gettable': if 't' is a table and 't[k]' is present, +** return 1 with 'slot' pointing to 't[k]' (position of final result). +** Otherwise, return 0 (meaning it will have to check metamethod) +** with 'slot' pointing to an empty 't[k]' (if 't' is a table) or NULL +** (otherwise). 'f' is the raw get function to use. +*/ +#define luaV_fastget(L,t,k,slot,f) \ + (!ttistable(t) \ + ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ + : (slot = f(hvalue(t), k), /* else, do raw access */ \ + !isempty(slot))) /* result not empty? */ + + +/* +** Special case of 'luaV_fastget' for integers, inlining the fast case +** of 'luaH_getint'. +*/ +#define luaV_fastgeti(L,t,k,slot) \ + (!ttistable(t) \ + ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ + : (slot = (l_castS2U(k) - 1u < hvalue(t)->alimit) \ + ? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \ + !isempty(slot))) /* result not empty? */ + + +/* +** Finish a fast set operation (when fast get succeeds). In that case, +** 'slot' points to the place to put the value. +*/ +#define luaV_finishfastset(L,t,slot,v) \ + { setobj2t(L, cast(TValue *,slot), v); \ + luaC_barrierback(L, gcvalue(t), v); } + + + + +LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); +LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); +LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); +LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); +LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode); +LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p, + F2Imod mode); +LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); +LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, + StkId val, const TValue *slot); +LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, + TValue *val, const TValue *slot); +LUAI_FUNC void luaV_finishOp (lua_State *L); +LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci); +LUAI_FUNC void luaV_concat (lua_State *L, int total); +LUAI_FUNC lua_Integer luaV_idiv (lua_State *L, lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Number luaV_modf (lua_State *L, lua_Number x, lua_Number y); +LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); +LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); + +#endif diff --git a/lua/lzio.c b/lua/lzio.c new file mode 100644 index 0000000..cd0a02d --- /dev/null +++ b/lua/lzio.c @@ -0,0 +1,68 @@ +/* +** $Id: lzio.c $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + +#define lzio_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "llimits.h" +#include "lmem.h" +#include "lstate.h" +#include "lzio.h" + + +int luaZ_fill (ZIO *z) { + size_t size; + lua_State *L = z->L; + const char *buff; + lua_unlock(L); + buff = z->reader(L, z->data, &size); + lua_lock(L); + if (buff == NULL || size == 0) + return EOZ; + z->n = size - 1; /* discount char being returned */ + z->p = buff; + return cast_uchar(*(z->p++)); +} + + +void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { + z->L = L; + z->reader = reader; + z->data = data; + z->n = 0; + z->p = NULL; +} + + +/* --------------------------------------------------------------- read --- */ +size_t luaZ_read (ZIO *z, void *b, size_t n) { + while (n) { + size_t m; + if (z->n == 0) { /* no bytes in buffer? */ + if (luaZ_fill(z) == EOZ) /* try to read more */ + return n; /* no more input; return number of missing bytes */ + else { + z->n++; /* luaZ_fill consumed first byte; put it back */ + z->p--; + } + } + m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ + memcpy(b, z->p, m); + z->n -= m; + z->p += m; + b = (char *)b + m; + n -= m; + } + return 0; +} + diff --git a/lua/lzio.h b/lua/lzio.h new file mode 100644 index 0000000..38f397f --- /dev/null +++ b/lua/lzio.h @@ -0,0 +1,66 @@ +/* +** $Id: lzio.h $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + + +#ifndef lzio_h +#define lzio_h + +#include "lua.h" + +#include "lmem.h" + + +#define EOZ (-1) /* end of stream */ + +typedef struct Zio ZIO; + +#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) + + +typedef struct Mbuffer { + char *buffer; + size_t n; + size_t buffsize; +} Mbuffer; + +#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) + +#define luaZ_buffer(buff) ((buff)->buffer) +#define luaZ_sizebuffer(buff) ((buff)->buffsize) +#define luaZ_bufflen(buff) ((buff)->n) + +#define luaZ_buffremove(buff,i) ((buff)->n -= (i)) +#define luaZ_resetbuffer(buff) ((buff)->n = 0) + + +#define luaZ_resizebuffer(L, buff, size) \ + ((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \ + (buff)->buffsize, size), \ + (buff)->buffsize = size) + +#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) + + +LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, + void *data); +LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ + + + +/* --------- Private Part ------------------ */ + +struct Zio { + size_t n; /* bytes still unread */ + const char *p; /* current position in buffer */ + lua_Reader reader; /* reader function */ + void *data; /* additional data */ + lua_State *L; /* Lua state (for reader) */ +}; + + +LUAI_FUNC int luaZ_fill (ZIO *z); + +#endif diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..b1f6ed3 --- /dev/null +++ b/main.cpp @@ -0,0 +1,27 @@ +#include "mini.h" + +int current_editor = 0; + +void do_terminal() { + cls(0); + pdebug(); +} + +void do_sprite_editor() { + cls(); + sspr(0, 0, 8, 8, 8, 8, 64, 64); +} + +void loop() { + if (btnp(KEY_TAB)) { + current_editor = (++current_editor)%5; + } + switch(current_editor) { + case 0: + do_terminal(); + break; + case 1: + do_sprite_editor(); + break; + } +} \ No newline at end of file diff --git a/mini.cpp b/mini.cpp new file mode 100644 index 0000000..59d173a --- /dev/null +++ b/mini.cpp @@ -0,0 +1,678 @@ +#include "mini.h" +#include +#include "lua.h" + +#define swap(a, b) {auto tmp=a;a=b;b=tmp;} +#define SCREEN_WIDTH 160 +#define SCREEN_HEIGHT 120 +#define SCREEN_SIZE_BYTES SCREEN_WIDTH*SCREEN_HEIGHT +#define SPRITES_WIDTH 128 +#define SPRITES_HEIGHT 128 +#define SPRITES_SIZE_BYTES SPRITES_WIDTH*SPRITES_HEIGHT +#define SPRITES_PER_LINE SPRITES_WIDTH/8 +#define SPRITES_PER_ROW SPRITES_HEIGHT/8 +#define TILES_WIDTH 128 +#define TILES_HEIGHT 128 +#define TILES_SIZE_BYTES TILES_WIDTH*TILES_HEIGHT + +#define SCREEN(x, y) screen[x+(y)*SCREEN_WIDTH] +#define SPRITES(x, y) sprites[x+(y)*SPRITES_WIDTH] +#define TILES(x, y) tiles[x+(y)*TILES_WIDTH] + +namespace ds { + uint8_t pen_color = 6; + int cam[2] = {0, 0}; + int clip[4] = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; + int clp[4] = {0, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-1}; + uint8_t draw_palette[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + uint8_t screen_palette[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + bool trans[16] = {true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}; + uint16_t fill_pattern = 0b1111111111111111; + bool fill_trans = false; +} + +SDL_Window *mini_win; +SDL_Renderer *mini_ren; +SDL_Texture *mini_bak; +Uint32 *pixels; +int pitch; +uint8_t screen[SCREEN_SIZE_BYTES]; +uint8_t sprites[SPRITES_SIZE_BYTES]; +uint8_t tiles[TILES_SIZE_BYTES]; + +uint32_t palette[16] = { 0x1a1c2c00, 0x5d275d00, 0xb13e5300, 0xef7d5700, 0xffcd7500, 0xa7f07000, 0x38b76400, 0x25717900, + 0x29366f00, 0x3b5dc900, 0x41a6f600, 0x73eff700, 0xf4f4f400, 0x94b0c200, 0x566c8600, 0x333c5700 }; + +char base64font[241] = "00@B@]0X__OnZDYK[G10:9BTDEG5j20@1h000RB:_]OBjW?odl]Wlil9_oTT__omT@@02:DA477ADid@Z=nm]_[g9a[]oIi?;a9m]_mBjGB[M]99o_][]e]M" + "_?A]c_[eiLGBZ]e]mZ]o]Z]mlW:O9IABdTdZ000hR00__H[7?iH]3Oih;1?mXm5GjhB3M]897o]H]5^Mhm1ZchM5>LhB2]eXm2]oXZ5mlh>3)+(base64font[bi+3]-48<<3)+(base64font[bi+4]-48<<9); + bi += 5; + } + FILE *f = fopen("sprites.bmp", "rb"); + if (f) { + uint8_t buffer[SPRITES_SIZE_BYTES/2]; + fseek(f, 118, SEEK_SET); + fread(buffer, SPRITES_SIZE_BYTES/2, 1, f); + fclose(f); + for (int y=0; y> 4; + SPRITES(x*2+1, SPRITES_WIDTH-1-y) = buffer[x+y*(SPRITES_WIDTH/2)] & 0xf; + } + } + } + + SDL_Init(49); + mini_win = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH*4, SCREEN_HEIGHT*4, SDL_WINDOW_SHOWN); + mini_ren = SDL_CreateRenderer(mini_win, -1, SDL_RENDERER_PRESENTVSYNC); + //SDL_CreateWindowAndRenderer(512,512,0,&mini_win,&mini_ren); + SDL_RenderSetLogicalSize(mini_ren, SCREEN_WIDTH, SCREEN_HEIGHT); + mini_bak = SDL_CreateTexture(mini_ren, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT); + bool exit = false; + SDL_Event mini_eve; + + debug("MINI SYSTEM BOOTING..."); + lua_init(); + lua_call_init(); + + while(!exit) { + key_just_pressed = 0; + while(SDL_PollEvent(&mini_eve)) { + if (mini_eve.type == SDL_QUIT) { exit=true; break; } + if (mini_eve.type == SDL_KEYDOWN) { + if (mini_eve.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { + if (lua_is_playing()) { + lua_quit(); + reinit(); + } else { + lua_init(); + lua_call_init(); + } + } else if (mini_eve.key.keysym.scancode == SDL_SCANCODE_F5) { + lua_quit(); + reinit(); + lua_init(); + lua_call_init(); + } else { + key_just_pressed = mini_eve.key.keysym.scancode; + } + } + } + keys = SDL_GetKeyboardState(NULL); + + if (lua_is_playing()) { + lua_call_update(); + } else { + loop(); + } + SDL_LockTexture(mini_bak, NULL, (void**)&pixels, &pitch); + for (int i=0;i ds::clp[2] || y < ds::clp[1] || y > ds::clp[3]) return; + SCREEN(x, y) = color; +} + +void pset(int x, int y) { + x -= ds::cam[0]; y -= ds::cam[1]; + if (x < ds::clp[0] || x > ds::clp[2] || y < ds::clp[1] || y > ds::clp[3]) return; + int pbx = x % 4, pby = y % 4; + int pb = pbx+pby*4; + if (ds::fill_pattern & (1 << pb)) { + if (!ds::trans[ds::pen_color & 0xf]) SCREEN(x, y) = ds::draw_palette[ds::pen_color & 0xf]; + } else { + if (!ds::fill_trans) SCREEN(x, y) = ds::draw_palette[ds::pen_color >> 4]; + } +} + +void pset(int x, int y, uint8_t color) { + ds::pen_color = color; + pset(x, y); +} + +uint8_t pget(int x, int y) { + x -= ds::cam[0]; y -= ds::cam[1]; + if (x < 0 || x > (SCREEN_WIDTH-1) || y < 0 || y > (SCREEN_HEIGHT-1)) return 0; + return SCREEN(x, y); +} + +// Bresenham Line Algorithm +void line(int x0, int y0, int x1, int y1) { + int x, y; + int dx, dy; + int incx, incy; + int balance; + + if (x1 >= x0) { dx = x1 - x0; incx = 1; } else { dx = x0 - x1; incx = -1; } + if (y1 >= y0) { dy = y1 - y0; incy = 1; } else { dy = y0 - y1; incy = -1; } + + x = x0; y = y0; + + if (dx >= dy) { + dy <<= 1; + balance = dy - dx; + dx <<= 1; + + while (x != x1) { + pset(x, y); + if (balance >= 0) { y += incy; balance -= dx; } + balance += dy; + x += incx; + } + pset(x, y); + } else { + dx <<= 1; + balance = dx - dy; + dy <<= 1; + + while (y != y1) { + pset(x, y); + if (balance >= 0) { x += incx; balance -= dy; } + balance += dx; + y += incy; + } + pset(x, y); + } +} + +void line(int x0, int y0, int x1, int y1, uint8_t color) { + ds::pen_color = color; + line(x0, y0, x1, y1); +} + +void hline(int x0, int y, int x1) { + if (x0>x1) swap(x0, x1); + for (int x=x0; x<=x1; ++x) pset(x, y); +} + +void hline(int x0, int y, int x1, uint8_t color) { + ds::pen_color = color; + hline(x0, y, x1); +} + +void vline(int x, int y0, int y1) { + if (y0>y1) swap(y0, y1); + for (int y=y0; y<=y1; ++y) pset(x, y); +} + +void vline(int x, int y0, int y1, uint8_t color) { + ds::pen_color = color; + vline(x, y0, y1); +} + +void rect(int x0, int y0, int x1, int y1) { + hline(x0, y0, x1); + hline(x0, y1, x1); + vline(x0, y0, y1); + vline(x1, y0, y1); +} + +void rect(int x0, int y0, int x1, int y1, uint8_t color) { + ds::pen_color = color; + rect(x0, y0, x1, y1); +} + +void rectfill(int x0, int y0, int x1, int y1) { + for (int y=y0; y<=y1; ++y) hline(x0, y, x1); +} + +void rectfill(int x0, int y0, int x1, int y1, uint8_t color) { + ds::pen_color = color; + rectfill(x0, y0, x1, y1); +} + +void fillp(uint16_t pat, bool transparent) { + ds::fill_trans = transparent; + ds::fill_pattern = pat; +} + +void print_char(char chr, int x, int y) { + int xi = 0, yi = 0; + uint16_t val = 1; + while(1) { + if (font[chr-32] & val) pset(x+xi, y+yi); + if (xi<2) xi++; else { if (yi==4) return; else { xi=0; yi++; } } + val <<= 1; + } +} + +void print(const char *str, int x, int y) { + for (int i=0; i < SDL_strlen(str); ++i) print_char(str[i], x+i*4, y); +} +void print(const char *str, int x, int y, uint8_t color) { + ds::pen_color=color; + print(str, x, y); +} + +void clip(int x, int y, int w, int h) { + ds::clip[0] = x; ds::clip[1] = y; ds::clip[2] = w; ds::clip[3] = h; + ds::clp[0] = x; ds::clp[1] = y; ds::clp[2] = w-x-1; ds::clp[3] = h-y-1; +} + +void camera(int x, int y) { + ds::cam[0] = x; + ds::cam[1] = y; +} + +void _drawcirc(int xc, int yc, int x, int y) { + pset(xc+x, yc+y); + pset(xc-x, yc+y); + pset(xc+x, yc-y); + pset(xc-x, yc-y); + pset(xc+y, yc+x); + pset(xc-y, yc+x); + pset(xc+y, yc-x); + pset(xc-y, yc-x); +} + +void _fillcirc(int xc, int yc, int x, int y) { + hline(xc-x, yc+y, xc+x); + hline(xc-x, yc-y, xc+x); + hline(xc-y, yc+x, xc+y); + hline(xc-y, yc-x, xc+y); +} + +void _anycirc(int x, int y, uint8_t r, void (*fun_ptr)(int, int, int, int)) { + int xi=0, yi=r; + int d=3-2*r; + (*fun_ptr)(x, y, xi, yi); + while (yi>=xi++) { + d += d>0 ? 4*(xi-yi--)+10 : 4*xi+6; + (*fun_ptr)(x, y, xi, yi); + } +} + +void circ(int x, int y, uint8_t r) { + _anycirc(x, y, r, &_drawcirc); +} + +void circ(int x, int y, uint8_t r, uint8_t color) { + ds::pen_color=color; + circ(x, y, r); +} + +void circfill(int x, int y, uint8_t r) { + _anycirc(x, y, r, &_fillcirc); +} + +void circfill(int x, int y, uint8_t r, uint8_t color) { + ds::pen_color=color; + circfill(x, y, r); +} + +void _drawoval(int xc, int yc, int x, int y, float xf, float yf) { + pset((xc+x)*xf, (yc+y)*yf); + pset((xc-x)*xf, (yc+y)*yf); + pset((xc+x)*xf, (yc-y)*yf); + pset((xc-x)*xf, (yc-y)*yf); + pset((xc+y)*xf, (yc+x)*yf); + pset((xc-y)*xf, (yc+x)*yf); + pset((xc+y)*xf, (yc-x)*yf); + pset((xc-y)*xf, (yc-x)*yf); +} + +void _filloval(int xc, int yc, int x, int y, float xf, float yf) { + hline((xc-x)*xf, (yc+y)*yf, (xc+x)*xf); + hline((xc-x)*xf, (yc-y)*yf, (xc+x)*xf); + hline((xc-y)*xf, (yc+x)*yf, (xc+y)*xf); + hline((xc-y)*xf, (yc-x)*yf, (xc+y)*xf); +} + +void _anyoval(int x0, int y0, int x1, int y1, void (*fun_ptr)(int, int, int, int, float, float)) { + int rx = (x1-x0)/2; + int ry = (y1-y0)/2; + int r = rx; + int x = x0 + rx; + int y = y0 + ry; + float xf = 1.0f, yf = 1.0f; + if (rx>=ry) {r=rx;yf=float(ry)/float(rx);} else {r=ry;xf=float(rx)/float(ry);} + int xi=0, yi=r; + int d=3-2*r; + (*fun_ptr)(x, y, xi, yi, xf, yf); + while (yi>=xi++) { + d += d>0 ? 4*(xi-yi--)+10 : 4*xi+6; + (*fun_ptr)(x, y, xi, yi, xf, yf); + } +} + +void oval(int x0, int y0, int x1, int y1) { + _anyoval(x0, y0, x1, y1, &_drawoval); +} + +void oval(int x0, int y0, int x1, int y1, uint8_t color) { + ds::pen_color=color; + oval(x0, y0, x1, y1); +} + +void ovalfill(int x0, int y0, int x1, int y1) { + _anyoval(x0, y0, x1, y1, &_filloval); +} + +void ovalfill(int x0, int y0, int x1, int y1, uint8_t color) { + ds::pen_color=color; + ovalfill(x0, y0, x1, y1); +} + +uint8_t sget(int x, int y) { + if (x < 0 || x > (SPRITES_WIDTH-1) || y < 0 || y > (SPRITES_HEIGHT-1)) return 0; + return SPRITES(x, y); +} + +void sset(int x, int y) { + if (x < 0 || x > (SPRITES_WIDTH-1) || y < 0 || y > (SPRITES_HEIGHT-1)) return; + SPRITES(x, y) = ds::draw_palette[ds::pen_color & 0xf]; +} + +void sset(int x, int y, uint8_t color) { + ds::pen_color=color; + sset(x, y); +} + +void spr(uint8_t n, int x, int y, float w, float h, bool flip_x, bool flip_y) { + int tx = (n%(SPRITES_PER_LINE))<<3; + int ty = (n/(SPRITES_PER_LINE))<<3; + int tw = w*8 - 1; + int th = h*8 - 1; + //int tx2 = tx1 + tw; + //int ty2 = ty1 + th; + int txd = 1; + int tyd = 1; + if (flip_x) {tx+=tw;txd=-1;} + if (flip_y) {ty+=th;tyd=-1;} + for (int yi=0; yi<=th; ++yi) { + int ttx = tx; + for (int xi=0; xi<=tw; ++xi) { + pset(x+xi, y+yi, sget(ttx, ty)); + ttx += txd; + } + ty += tyd; + } +} + +void sspr(int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, bool flip_x, bool flip_y) { + if (dw==0)dw=sw; if (dh==0)dh=sh; + float sdx = float(sw)/float(dw); + float sdy = float(sh)/float(dh); + float ssx = sx; float ssy = sy; + if (flip_x) { sdx = -sdx; ssx += sw+sdx; } + if (flip_y) { sdy = -sdy; ssy += sh+sdy; } + float csx = ssx; + float csy = ssy; + for(int y=dy;y= x0) { dx = x1 - x0; incx = 1; } else { dx = x0 - x1; incx = -1; } + if (y1 >= y0) { dy = y1 - y0; incy = 1; } else { dy = y0 - y1; incy = -1; } + + x = x0; y = y0; + + if (dx >= dy) { + dy <<= 1; + balance = dy - dx; + dx <<= 1; + + while (x != x1) { + pset(x, y, sget(mx*8, my*8)); + if (balance >= 0) { y += incy; balance -= dx; } + balance += dy; + x += incx; + mx += mdx; + my += mdy; + } + pset(x, y, sget(mx*8, my*8)); + } else { + dx <<= 1; + balance = dx - dy; + dy <<= 1; + + while (y != y1) { + pset(x, y, sget(mx*8, my*8)); + if (balance >= 0) { x += incx; balance -= dy; } + balance += dx; + y += incy; + mx += mdx; + my += mdy; + } + pset(x, y, sget(mx*8, my*8)); + } +} + +void thline(int x0, int y, int x1, float mx, float my, float mdx, float mdy) { + if (x0>x1) swap(x0, x1); + for (int x=x0; x<=x1; ++x) { + pset(x, y, sget(mx*8, my*8)); + mx += mdx; + my += mdy; + } +} + +void tvline(int x, int y0, int y1, float mx, float my, float mdx, float mdy) { + if (y0>y1) swap(y0, y1); + for (int y=y0; y<=y1; ++y) { + pset(x, y, sget(mx*8, my*8)); + mx += mdx; + my += mdy; + } +} + +void cline(int x0, int y0, int x1, int y1, uint8_t c0, uint8_t c1) { + +} + +void chline(int x0, int y, int x1, uint8_t c0, uint8_t c1) { + +} + +void cvline(int x, int y0, int y1, uint8_t c0, uint8_t c1) { + +} + +uint8_t mget(uint8_t celx, uint8_t cely) { + if (celx < 0 || celx > (TILES_WIDTH-1) || cely < 0 || cely > (TILES_HEIGHT-1)) return 0; + return TILES(celx, cely); +} + +void mset(uint8_t celx, uint8_t cely, uint8_t snum) { + if (celx < 0 || celx > (TILES_WIDTH-1) || cely < 0 || cely > (TILES_HEIGHT-1)) return; + TILES(celx, cely) = snum; +} + +void map(uint8_t celx, uint8_t cely, int sx, int sy, uint8_t celw, uint8_t celh, uint8_t layer) { + //if (celw <= 0 || celh <= 0 || celw >= TILES_WIDTH || celh >= TILES_HEIGHT) return; + sx -= ds::cam[0]; sy -= ds::cam[1]; + if (sx+celw*8 < ds::clp[0] || sx > ds::clp[2] || sy+celh*8 < ds::clp[1] || sy > ds::clp[3]) return; + if (sx<0) { + int diff = -sx/8; + celx += diff; + celw -= diff; + sx += diff*8; + } + if (sy<0) { + int diff = -sy/8; + cely += diff; + celh -= diff; + sy += diff*8; + } + sx += ds::cam[0]; sy += ds::cam[1]; + for (int y=0; y= 0 ? 1 : -1; +} + +float sin(float x) { + return SDL_sinf(x); +} + +float cos(float x) { + return SDL_cosf(x); +} + +float atan2(float dx, float dy) { + return SDL_atan2f(dx, dy); +} + +float sqrt(float x) { + return SDL_sqrtf(x); +} + +float max(float x, float y) { + return SDL_max(x, y); +} + +float mid(float x, float y, float z) { + return max(x, min(y, z)); +} + +float min(float x, float y) { + return SDL_min(x, y); +} + +int rnd(int x) { + return rand()%x; +} + +/*void srand(int x) { + srand(x); +}*/ + + +void debug_one_line_up() { + for (int i=0; i= debug_total_size) debug_one_line_up(); + } + debug_cursor = (int(debug_cursor/debug_line_size)+1)*debug_line_size; + if (debug_cursor >= debug_total_size) debug_one_line_up(); +} + +void pdebug() { + int i=0; + for (int y=0; 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

GP#{gAi7U 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

!%;r?7`=J-E1o!0$nuH7jVAA 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�=dl|MS;Wkw+s%{?jOOqc`97L;4Ab#{A{TH*{TR59UQT+3=3~ zGNaxVRz0-0n?2K7HtTHpt2Vr)ew9JrWYLkDuXz=wJOIRg|Na47dOJkJ4f4kmThd)d zT{{H0!_D(F--f+8R$Uy)b==E6Ydngv;%5$q8Rd27ZJKn~RUO>n4;Wsb@a&X`C3(KC zjf)KqyY!HY_*7SuyNmnF*$2IKi?aGw#Oh_kYImV}a;mx8Yt_CosN>%MKCetG{SFH1 z_hc6`+xc88$nN!b+!IvPVMf%QCga@U&iR@HCq!D$X0LIAw^)0PfSuimwxoLNFE<=i zW%dlvWY^-%@2f z^()G_*Ry3&-Jq#j>RDR{Tl7+|i4nAxBT>r=e3QY2Xl;?^GU_@m?!#yCOufmZ74Q6W zhfg!y=N7o5f1K+zY5yqP=M}g|e23&>8Mj(%(AFE3Z=u-#V)#}UvIC`F?Jd-b9n{f? ziC(~Q$9l45n5J&RbZ;1-W4S9BRiI7{C*wSsj=|jN%(2CSmB#+Q?M9WPSANg+s>U@@ z@;&4qqs#1`KGeUTyLK?wf%O;G18DEOXLBgAU)u1FI&2=? zht37AqICH0WL0>^HTrI`{qwUHa&n#VGWwi_Y_9){QFFY>GIp20bB77blmIQ z@{E!8A+5Ejwv(GQFRybWLk#+j>s)Jvapu4#%lmoa7O3;x^8Tw;@6Sb?-fK9WAL)(n zJr27u6V179dBPCxiU=<@gy*`pzs1)Lj4FHdv?WHB9<2#4U8yoBMR_%~S+(zR?GPtM zWGr2}JKYNH7dO*#w9Bm|uCxtV;OVtF)LFmzDrNh5qmlGpdtBMBA`3vtfSl%1qitRM zdh0tKm(jX1e4Jr)+8HJ19HZ0mQF7Q5Z`1{5Hbb+(vB`~w6ET+YJN;<4+%*i}A2Iy4 zVR*DV&5lQ?p2ye(pon$lnEL5@gyT+g%TM`&ChMvww~oLRj}x3}g?0nYrn!fh2|>$O zfjSLHk^^%JIZ)sAMdj5MWf3O3u9^B_E}$!6u+7S3)pL2GOII`%7PD#e9B?S^=_{1u zhoWTu2erd2&U2$#9B(}KT)QeZdl1>~xh>a@(X*H|*PFpm>9k9RoqREy=*9-IPw z9fp=x8;mJZFs?XTjWTCM%B)z3Ep$-k_3`FIq!s*MuQeI97@7DdYXNc&5$4;ltF@;K z>jOAA#7H$Sg=aaAP#ek1-R`_)D9FWELp@h=GTkoYny~>|ESvz5!eH8}i~KG@Nsm;Z_CZ ziH~ow^Vsuw7e;K!@=Q}FocbmsHgDn=WBC7Y^mT;2B^bXF&XZ`&|Li$K9xVM=T$+4V z$(Dkt-$4G`lZNaC{})FK|Cxh?|B@qwiSzJn=Pw@jUKihqd@meGOQG_&7tWdaJ1fru zQaU&fzrpX2zDw|u;SYf8CF)CfFXPXb5zIOvIq0pl{-;KK5wP+zAtL9^%)Np@g>1I= zW>sE>fKwr-@x0oqod^X^f|%ZH|C~zdW}J7}ygD@oU?8zEI;ASD7YV0LGfMQ(B(x@cCeuNB6aO4pWI8A~`U^3f%}s z@UtTwP$}o!nXHrFL(lt9*GbrPw*4zAWe%Fzzb~^w2JP+J_V)A+_4Hw{cDuCC+koJk zike^`$q(mtTop5|{xQY{Y2L_EBR@q>fBhg?h=CE?@!$0TY~meqNhFDp7=;|dyU-Dk z8qjYv?0}Y?(*AXB?JD4;gEjaKqR6eim?U)fV@|!dW60U!`uDiGRhU3zYW#1zW%mNN zOfFWzZ8i_M*#_)_a?18u$ama|g@6Rv`&hld>z1uWC|9;`Pgl1&r}?15svSkS*G*GV z@a$;kmT!FFg7G)q9M2*q6bjSxP*-~gu9Ue?;Q`@To$bT|pMSqQVHD z7p?k_xPc_eMq`yc7W;jTt+uhd`}<`qxA5j%pVq3csx3xJb|28)_1w~f2Z!Om0 z_e#C^nww`82W%xBE3;s~t{{(~&aO5=yIo;87O%YgZ@4}kSfvBDx^%D}|Vp52E-##|D~2gVH8i)H*AvCTo{Ls-#iw+CsQWYLc@#F}IAxo$u`G z=-Iusw_R3}oWwkBM0wofv3C%adaxZ!L{4J9fP?(@J^gzJ=;0#KAdp-hRZ>c^eel5U zZT-DYVu3_d=UKE|_>LkPC88$JdRQX0Nup{cszh?LL^ViML3)coTk`|`gFQnqgtyZv zxszBZ;N|(gE|{hY;6(ynExLB^+1ktZeBZhvG~JXQSwRH;77}mB&e(3TSzIyKP)@=qVk11ke%f?LE5( z+S^TQP0pEc8=&ccjo8NR)0UiEB5@WvV8KTTxRR3pi2ox=hc6Os?8&xCFDWa6q_roH zv!DUqsU^)YxnV3@At(oiY(q>QKbGwfuSIV~1MR-qR1?B2I%luI#-58VS^e zJ$1ZPBZN9Ig1Hki)GWy3%YfUMCQ4*3-_B!vSk;!;Y6N?@@nfVOKx#m~ zw;Lm`<4zI4^nCl!?tyNZ6uDD{XRVVw^60gz9C!NI?_>RK)ZkF3Q|X*hhV#zt?H&8~ zFIeCN33tU9{tQCf>eL6b3-MW4ojNOfsyxrj?!}rxb?Ot@Ps;QB?5*;=Ap3|sKbd`A zo)=}CD~NY-woRU&&hC`wXR{xX=jXE5$n&zS_#jMOo_$rqS7k@QyjPvNCObu*U&=0& z=e5~Q^1Lofztq*K>$9Ji=Z#sqCag|JENQB`Iph}k>_7We;&`VI9%nVyZ!c)jvs2m`*!CIKtGGmpK*LK@f)M~ zK8NSP?_@k*O#HeizRUR(a_wh~=ZlFyCW`NNJ`V8PjOUAqKQfB%bj|{JEK)L#FD8Cj z6u;m3Pe2zlo-Zc8HHzk9Qc{S*#MN7|sMVp1!@T3^)(y zX3G#=s2c(627W#%dHYaS^ZKc*=J5+z&EsEZHE&+-`n^~DW0;qm;iH4s@bmNl%6VqHmW}KbMzo%Q(sIVDP{o9Vy7{IP>M1ywXsCeY}|}bJKLT_er+bfGw`W$&7WS!-zvq zb21a%5qX^YOb5IsF&$7+gn_FTw*zI0JGw<8m&h;YsTQTH@3bD6ke$pdWnTX%2k-No**tYr*UuECsoe-A3x$K6U65Bs-qSEA$?)8Fl6&Uf={gx3s!BKo-> zjK|5(IKZ4KK{^IGjULQFCv&YUO@v)@tS_iR4q@|U=6X#PJ8Yp6#T>*A4)yQr7<4kXxOwWzo_rju zUojSuoXpM2guQ$z&h%3U`*EZybE%tS=RZ#JLJ}`Ok^?jLU& z9Lvw)b)-Z6K>D^@!-C>~p_;HN;|c&qqcC37!r(Ykh&CA|ID3KgvOAX3V-7M0BOSnI zVbu8Fsxlma1jngCZeUA1#*oZwnk5{R#xcvsT@Q^+#$g%+Bq#F+rDx}dXUfan5|#TkseduxBpC(u_on zf7qSOVTrwV0mo(}GWsX(EDmemERL_v&I)CckZlTO@{nx~*#XyZaLs&B6a9PAu!cI- z*@fXx5ke2!ju{U++XaoS0zHr+G|A~#1p6#tq`1>Oe`cOQH7a*<(VPwPe?XGHc1M4Q1AnJvNkCOLko-vzBaID6^LAaUm3AdG2u!JZa=YQ*~hn{^>D%EwGN5ASt+uSt}DBN#gZ3uR8C z{GQA&0I%s|7igNdyC?h2}0jqfaU$>sMYFGi@wnR`1_%9YQ|tpu;U%xueN zRZ3@^7js{EZ55LrIJ1aZKHI1231U~?1}R;5na67X58s*lTjBNl+ywyUyPfhsWccRf zxfb4q@T-PZI^e{87SYRJ^T{H)_V^(z?(BBF%SK&{@Z{&b8{J&vhIP(=Ayn4wcwcsv zSy_kU-DK=BWqpqK6=Q`d6Muu=&F%zJN}I6|t4;@iWQBWt~I? z-sktw!smD|dSe)s@tqNBq!jG67CQ|i0I_#tBZK3;<&9xX#(yr3e83_noJ5a7#!c-c zNc&?LoAJ*YsoZ&!E)Aggs&Tv~KL-P73>3G1vTZMYeFZWUSAWPam*Yo{a-0QgNji(= z3lnJL)duNrSWIYqG#>a>vU#)4f89mWcSrK$z`ZRE}JYZX#Gf57o-{g7>)jOdB}G?Owin^a(C5`c`|>UcT7{AYhu?azx?l#SNR$@$X_3#YjoUE*+hnurP-8?vXA>?A|BG9ue&$e!}1L}cACFbti>Z%Xe`rThA8 zs^m2h-PkdzPv<&YD-pJXA%J^IIT2)$x3I3rs;ZOmeWx(^n{4q~j2eNp6 zKQifYPi&<)9XKCriQW_NCogql^L*Z$<^9M;Z*(drAnz$gX4;;Upf;5^p*Sf-fIbXQ zct^(Jz%`2dPLq&VH6acd@XsB75m>B>cY2eH5^|SKNKllJyKO>hVhOpYI3f31O*hXU zXmY%7+JtPG-{0MhtaZHmymEGk-bE)nL8IpqS=xz_Ga6bgl`Xq z8`v7qmge^XfWo@OW_c<@CoUllIc!ux zQiZbltD)Kv<+9Vf-H2MKM7R8>AuFg( ztv0lA{@~t@j;=vuY^zshiecfYzfr;3njPmlh-FC};pMa>Ham;%HaHKNd|;NY_C^)T zhUphW6?o6q1ik%=^1UOtupvd-XO!D2&lXtoJHUNB`kpbpJl5NfhA5LT`dszSfAoDH8p#5j`R5%_w?;H^+z;VG|3& zz9C+<2Ybo1 z*Jz6qS_B0x=3|bL(X#X}x@X^_i7%^!k6ER3t`SChv8tDQVl~0;|9w!C<7#^sK61T( zxKhDCW3)Ur$|+v`%?{xot{pF!Q~z-5Y)(N7D5)y;nv`P|i9QOvr4t5CRxcn_+imtIiSHb#=>PBM}nbjMgp zGLAgx&eBE}IL+KMfy}>MnRFT^XGcu7SthqfOr&pOwM4T#Tj>@*ufpdxH*!xqDIqxXhg;~ zaH!j0O1M?#SBJWG+Pdh&hDE1gp*g73@u2Os)Zop?^SVHpZ$SRtDm4>x)p%LYfqv6_r8JI5Pu z3ebqO71tfU&4?Tyl{@vGU|H^HTx3YLuqSCVfjySLCa7GwFMe7R^th%66S0|7H9_T3 z9oGa^*aVmaRobv5C}*W_p1&ItkSZJ5<}^{B92IiBq+9;wU#h_KBY~G1fyt;C>=#ec zZ7ix>Nq3cob4+l`irmo{np7~s&SEUcY03Ysil0dRM&hza;!}`#2%7QVW|%4U60rMw zRC^ZlyTla2n=;OfF)RvYP&Z9kylI;rS^U|uSR!8pZ`tn!XK{BsZ0Fu@h1qw1p*gT2 z(r1TZ_S=aueST+|In>9f^K0R7rs1$U;&8d)@M}BjQKX@HMrht+Xr@OrPZ*kKqP}b~ z`!YlIQ=tkCRbhag3I@!(pT-mZq}6pv2l|Ak#x0W%qb*VtSWni{cvwo~+dtRT9~0@( zZ8$z$8%zBomZP&6R&8m=cS{G+Vd&c<`Y##!yKUN86!#S9yW5AjorY`p-Yt@aW5OftB-z@Qh?OPrRIP4r%^ zFnP^vq_Yzsceo2omP$8TJ3}ivZtm(Hfa*h7KV9c0+fQ0#f^7?R#kOrt$LS774g0q; zQi+y|1?}7+LK_gsN9t^aK(2*gxd^~I)54a`Z^w*&h&R`{ZP7pkpe#eT%NmY*oIC0= z@W*`CIrK{yKl$I?Fy_$b@Z|r*aZ?WK8Psh8g$-C1f~fs6YjNUn2DBU-1K87=hx=J? z>)Xd#I zw70Ko8P4c;H6p;pjAgKr^!IJ8nTtIg^XQ9XK5j?Y|F77ER`VyVSBq=35FUE~d1bdo zUJh8y3B#St$NzT6nOC~wEP?f|&Yo`6Wyjk*?Z+g3*F9*SZa>2#+If}?C>rQ?!_B{B z2W9GaXyb6g@FCQ_G~dMu!wesV@G?U5v~X_#xz-88U0BEuf@%}RP>~Y`0!p1Q5LR%) z@FtiQoG={7U^W~%VHi;jBdm48Fctw^V_)oqf%tJJ3=Ee#Vc^<%u@eSjEf2U=m`)g` zV0|X;gy9jGW=fne)I)Z$6NcrOK*yXgyqI)KoG|AJ4S3Bw5YsIT9DoW2T3FKmC=r3c($g;0a5RC3*G)k_yoV ze3Rp&EU~xx*Fy0dQuqlJ1^$bOYz5zP_<^u%@ar=w43fbOmdOfkuED0-d@W*lw5caKg%B#UFy7{ONe*jxBRS#P}HE#P6cKE8zM@bHxRk%0BR4NH{5_gngMa% z@MF}2nDYkVqqi{Ac>{R|5{#TT5EOIXz+iQ-oxFdc_^9#)&kan=!JZo^r6IVQMDX0e zP;+o6L-pN0rKtR8IeFIB)&2duoCG$M{sx&ff;pB9Uc+y>0}`zPd;|1yHRn7rQ z)^+?ls(uYvq@I`5k& zGhjS7Oas03+`ud>_T12fyeswGK&9!qfu(`A+zzjuPI7!sTcw63j9^AF(t2)S{qou6 z$2~VZi}3&CxuF3>rJftuefs~vPsJnnnTg%DH>y6l^orbH5gxY`ywivK z58z#WJRl&)AjE^EV!GPxufV{%DSm>3@q=}(Vj z!5JS9=}(oBSLEX%eQ9zct4@l{)1UEk2qcal+I4iNlO7)R5rmQf8MMRT@@ZnI%LIh%2 zXhPP#LwcW^Wo+c$A-!J##=S%OfSY4=p?ilk+&g?3I>g*Nq(9*1H$g5h;r<+=q&w*X zK)MsGx7wtnKj`{In7YXp((P{L_klPC=a$oO@4#%Ef^^*hKNqMOQy>nn9B`*#*B)M3 zo2H-+;gywWO0T?*fNr?-TbZWsbp6x7bF#W1XieYm=1#!^w$>~7a42L70!-eEi@HPtf3NyEJZr#Rx?Ar1Eqvk<678Oj;s*7Q%j z9FbK8_;4twfIv(I6SD3d(m(Y~xfI+xq@Pq+7T4kS?8ef0`YF#8j=Fb9|IEw&63g_) zy+iuvUglwZU&P!yq<^8H8chk@J5ae=O$ppPFeP;Fz+6iP=d(mvNQ(eAC7S-6G!wW$ zI2S-2eA94&z)-;jLi#POMS-|LNWZNi;{qZ5j;V7H!MajKmT9;^pqR;P`#Vm+Cgoh( z^Kws9gmr~yhxIjp!JpWQKNpo*QkRIXX=n#P}5Yi(R z*SJ7PkJ2DqAP_YT7YM(nHf`ca_pJ1IFUOqKVuYWALNOu`D@GHFyFf@!v_)BPfsmeL zi?YZCLVB`-OI#qNYg9Sw0wFy`!!Z{K>8T1Tae;fST7YLXi;!_|}6)q4`fWUh>iwXV@Sn&q50>l3SD=_^Z zuscZx9M5p!F!;hL5DGpSd>rw~;4y)-D&PWgK#c!`bff1JZL<25txfOna*se*O)lN* zWlqQ2v|JjigeT)oYXbZq5WxvJ8%V?d!Q+f_rpQNmdcebohpy^087I@HdLh*^q;PUj zs6+_FDv=4P|AX{STYb<`?y?OW-QylFIS1U?^^V6g8Bi1B{~$f+`2?mnLa&DO>0a(c ze5R?+aAZ&rj6h7V31x!GOpXbaY33rt%%%T>^ckKE=>`7>=`+0%lu+YTFp1moYWj;R zYLJHigBPjJj}WL$f5^+d7^wqC1_gBxh^b>jMjaC}>L8@*poYQ!0n0e@e~>=c%ToZf z;nyku8*P%oPoYK?)kwqt!4P7mt~CBR8`2;3Di@%?oPyrrV_wKaaFqGD7ybpW&eV1E z?oploidT6zuqHFO2A4oor*HPkz5qxd6At)4kjaAhKS(1a39|kV(zkf!1Z1=<;QxS4 zD2)6cq~ZU7YBtHw2fVqgFZ|pU190VwL0bZSAUcPJ%D1j&qWHt~de* zocMD5ro){yUyj|h)(PZg{Si)vFKz2jbjtX0#L*`>S-u?2w~%j#uUL14Q!a1oH#imY zvKeocd^>*iS|_J38=NY>Y+84$lNY3Q>o+Zjq$Xbf>b4Gfq1X}BD)nrhwv zsCT>4T?1h;cMVgJsDs=!uq#@gDRS39P|RHe+sM1PYhVj4cGo~ik-G*0O58ONwEZA= z4TK)-u7S`}cMXIc?5=^(Vs{OMl)7sm>>zgy1jgMpu){2N*TCW`a@RnVn7alBKPuiE zaETMHYopT!!eUMv7%X+#Kv=QU211IRHV{(mw1JQkrws(foHj66>a>BdQl|}sl{#%8 z>>#HN1RmtHfxx)a23joNnl-Ss57(jlQ(YPQ9CucU(*|M%fbw3hJ-czb$e*sW;+#8c zXt!)<^=G(a9%lmq8cv z{^YE^o$Z7<{%lwJl(Xoxfx0FGnv*NoX30ZD&RP#P8&ErO~Jw6ZElXUttr@y>UX#!nTRR4 zbI$QQ-5e(`&g>1Vj$gImgjGjirq7m|tx2uJMy0xqYuY)MI4<7~->_=M8poCQBi6(2 zLEx&j7y|t0_2?s=ga$yCl(!>S5GAGW7=_aMwrSnUjYqFvhms_lqt=9*;UD=|0XGD=$Z_a>mIEsK?98 zx>e2udErny(Y$SNCdu0ohp$|}7RjD0p;haTcWUJANDR4CN3T1|neIAsg6x9IMaOsTKAQHkvrtN7_c+-`vGTz3lWkJV59$aG46r7`3}TS8 zEj~+i;>P}6Fl^+qt+~4p9QS8bnCxQt!f?jrP)oCiWXTt|Jt$^&iGLx&qtb{Q$S%)a zfbCw@dYX91$*xe!YHm(3JC(AB3oIcc3E@t5r9dzyIoTsJ6q~E=h5dBv4sHm{t`bm9 zbvLv=a@6;*NvZ+kc=o7KZ0oJnr#soz!4CjkE~B)QJv#g`LaVEHIN4*$eume!>dph; zvu4EFiTJb`$4?d<8({LcRO8GJP8c35p&iad8vBo@X9^tmzc5Ex)!j~bQP~yPsDo+7 zp03lJ@ZUv;pt^U^2|qRR8pPzPxAi*V#UsCt_v&hV)`pizigdKZ9a7jU;)I_T*mU92 zgY(*w_V7}H)>h-5s_--NUSHie;Dn!*_lD}exHG!&a{_Iymi>qL8pDcbc$vUj4Q%VS zF2IHbwzL|1O}6dbE^h0>%QLihE(gaBES2Jj!{^1ead@@3JPxmr&`M4ly5Mff3BMqK zBdUA$4ej8$lJJWHSXJHE)zzs>nc>Wegy+Z{+)RSPb9F`zG^6Z?ldqvPoa*h!$@9w3mt61F z#C}AAH4ynMP*SXk*>(Oys7J7k!Uw=$hf^JHsr(hiSBG26zK<8ND2Cf&7DWU&QU}%I z3o7i;4}|JH^d1>@N~o-QKtf$v=46PR+}-7b-O{JSRDN2g6K+rTgZo$%<_`TzfOS+= z2z&ff5H*TtK&r#O+)=D7%AsG|qSTxLDLK?Gwv6yp2~m>ChCPzuxoVUDgA%NAQsf#A z`G2H@zaisu;r`r5C_%FMKn349qYY0t{AD&9zF+wx>!?nOl;Iiv@pw-L%&%k+VhBhE z%*@)uQQ>y2#A#~W=nD*)#(y6#GKfug{JZg9j{$2lHZ7nN!Syb+;~0;_5TjN>JZ=(` z*h1TOmwVV3u%NjZ+}66bYrnQa&V;9pJY0wu$}h&7;iIt&Y#y2)$S3n1y91%q2I$Kr z@y$5sj#WRm#lwA2^h=_E7}r}zD92MHj+a@EE#7#`v4KnLj(e{gQj43jO5 ztub2M>rOB<3)n+~Vm9NjN3pT0T&dQP1b>Md$7$jn4en!Zp2ke>VQqZUV4X}9{MFT1 ztfyUBdElmn#@%`4^}OIX&U#|;mf4BkNOoqtv8{Q%N!p19sR_Pg=6Lck!X5F*CidPf z{7T~P3fi~b54hzc(#m_7-wF70ha0At)P2C6Zc;Z74q1p@&-~y~4@vC@+(R_AxrP0G zy|`!rw|YA6O>XevGUd6j4_AE%@D?}tx&^8R0=~fwmKt#LuZJqvO}II3k1iD=&zo>Tz@QEFIxTyLx?6>1 zk6V6~VRwRZ1G}dzyB@d3vXdRZxN9$9B+gYd;byK~1&(5Ze+5y}IMS+jB;`bR^m5m6 zuJKjzzvG>M?(kt#O|GBl&b5-D>Sni!_$Wap<2_c)W@U?wv0FuXY@1|8tubs*Qm$b8 zQOkC{J1xc*du23ZPj(tGM3Il<;szK3ul7{8Ya=H2SthI9sMWPVu51o++{19mqM_kF z8~(Y&Rnts*4s)j%!Pu+<+}SEPn8!If!mV5s#vun&H96&t>SwiEKJypYUSXr9=U16aWifu#f|#ADqMxEtx{3O({R6nc?L{$}Kx(}nXK-IK)d7N~P^BYnblgWp?noo|I!zIh^sJTp zsI674+&b+(+N3!X#QETA`TK;=74NA2dm}zGW*GhNi};|D+&9P65xMAZGY?Mb_F(r~ zd(mG37&{kN=;+&;U@&T1WLCd=oEzU($$yF@KTgSO9rxNA8ig>9NH$(;+FsC#n?9~x z$jK$D=3-79-D?lmzP7qmGL1KcIPP_0Rn;123Ec0nMw!X3J6wL{TPif;s#JG)^h}f7 z;hCo9*30$omz(VG#l?O)YVEUK^m%2`Fo_+a3XP?6O~(O;YJKF-Drci=I?q;( zR#3wiL9;2MR@AHWmYWt*kF5BJ*vD8aIJSILrY0DF>QP}nRz-HWKezdBMv!gk^@BsW zAo2WiuFjx>HIFiho@;Wt9)>&jf}}>TuHTRA3NJ`%MlJ^mJR;+Jb(y4k@Ic?t*8TW; z$7KZWz6{dMJ2p|$1$a@)os*3&bBru^c%M!5z8NNiTcyeFYq9n6Pz>!xM1StlH#OHT zj2L{+GU$(TO&IjsTwBcVBDa5;7JJTFG_-$6zlYq8krdKxcy>oT!&*}k9koU&Wzx}L ztGSlC%$*vgkT#S@r5-^GY44HUM3=vz%0C2lijnk=iotgzk@FkJp>esyr0=QOlJ&>%k93zS0XXeL>EuAC5xV7@eGqPoPu@_k7zo3Y&hR zcFBcTDPDz?bDqNdGi|RzO5qlyfImZEp20N)gS?4=C-9dFN4*Q?P{;K?7(NP=vUH+} zYJDjDHXhj#_|U``OZ&zF=WKj`mT-s@^P0&5@jpt4FFKf5u1QeAtBPosAQTsT8EMP? z*@^70@K)~EC9;p>rGlT#iTFK7=iyUmABZdYV&dcX91R0}DdYKK;^X%mF@@h?yd+im z$L~3!B2O}2G}8F^Jx5IBpBXQy)%f^5M^8fP7>t6Id@=Il_Z%gWX^R-o7sPk;!_@d* zx#*~wfi5Y7_YlKqC>SReFuEP8_I_d*9pT^8@%s!00?Om^7!SeNS-?;p_r-V&Z3T}H z84LuJ$FE{M1mnyChVo#4XY~L^qvKyJC@pX@)7RLgY~~V)$+2lt%nM_f-OBDn%g*qW z#NQ)$O;PUbv+SG-iN7O?S0!LwU4EJg6pk+^MR_BJqFjC(ajC$(*YTg%EXBLB$YSZtq(N&8;F8lhmZib%#gQ=ZU1@M7*rja0 z60!X|n`O?R9u`OKR<1vbxEj=cEPtG!h)uoyxE+;c_Ksx;UPRbXK+yD#Pee%GELbIo=TtdKQ?k1QvK?Pr<@e! zu^5UfcC2NER^8Qum6q#Gdq6;$^hZn##x(^D<$+tkZEw`gp~HVeF&I!Dw-tCO#vcn9 z%HuyG9yttOm_Pf0>e?bfW%EwN#v&!+NXlt4rsKBGqd**gyh(I7LMESA6NedNa)(il zKPHA~a{5%uOgUD48>6;A%@gex;EYfQ)|3Z(x({?YthZdbQjUr^>0rc8L41ISGL|Xg z*n<(f1@U)QzEkxniataUTYCoKN~~uH$r&>ZTQ|xgxq`K@1glf9T8X7X1q*wXc#~no zt6Q*6A(nO-J?QaJ^EWA8iv(5RIg!AeL28R5sl4kVc@}AP97)CfATF+t!{I=LgrJK1 zuedlt+7(AqabvJ3sL6vkLF$Mjsko&?lGIh*%KSV}QIH3?Kn}Ols=RH)l6Iq5*eYal zO0iVnM$P=VXijh>@ zM0`q{1inUbw<*%%p26)f$iNSzsWQh9uh0Uj1o`Gt}4fc*fWT$TX83hBw;%-W0@nEFBD-KH7+VqLolB$!ZgzFE|I>S(p_JBk_AS5EKh!0 zqJ!Z7%_K06Z!{SX^F=&E1pn=K!8iJ>A$}}3R#2buMxQ3tr?|?TNs3sm2*sFpr7$|( zT%waujCfZHqt&lUwE7aYYANK>Uh#~*2Nxx4NmXHqC$5v=FL)PxqtOcD$7-_R&wUqs zqtB_tFXU2=9}AeweLErL)*?Y2n?7wdaV*j|<48I--EG+cNhg;-u}Fp4<#RDkiu8CK zNjW9)m96zS$2mWAddVUcW|(zEl77r0Js(F>PU{PtI<|2h@s{E=Go)$TQ{ba0e~O_f zmrEipRnM}_%97d{cJvP%U{{Coq9Wh2oK!8vO_ksx@0sPi1TdcWU3)MXO;X$@1e9Y1 ztXU?Ff-tUtpls$7f&82t5U|~(K{1*cQXU(McmSn7hN4{d#<=Vszz5gi76l>Y@|hSH zK{+&rqFlJo((1B*VD|#Y->5h(m_+YhpnQ0u*QQ93+TuvcDG7tF;ndyPv)l2zjWC8x zX3rx|p~2=9aa#=0W-hV{>jSmP5!5I-J6G;Dp;u3}yJ9e!nmh!1hi#(E;gQ@@*tpN}CLj+;t2?l>^e zk7jVYVzx-o@I0%8r$N0nj%v8xSi-dj-x}K-{}F>KL7g=|ZkakcgY;k=NhgADSawd; zA$awlR+NRk+qdpU0ZHQ;ij5sucIWyF!zP<1!?ylQcJdEC9rp#f!Ufsf$) zwg{(Na6Vk%(@s8aO4>Uv-NnWI*t#J|Hxw8N(%+PkMN&?WMV#bw4BwI?lvfMC&di7I zpCV2csWOhFX&Z}MCrmv9Dca~v#c5_pvuG(%v`18wsWBAg(q6;`Mb=tC*`{31F5&`| z<`{}{xhBSiIqUexC{ByXXj-BkiSbdSBjZTj*lFfCuST4zLgw_zin7pVG;v0Zw#ibQ z%|$rMXAyC<`29siecB<1w6h*MP~Q~Y0wvS<){ySDZAVaEkoea*5`YZzl7%q-YK3e@-o0=OOb22J0qi;|D6=P z40Jhe@pb$B7GI{Z4TvR}-q?3c5u(<|A64*!jp0Wy?@ z1YJ$wB9_cxJ8NXcyyy&rSA6k*;c5rZx&}xFYy`=GA05en6>*fg*?;vW?6D1oN8BJW z*JI!vEh{&4XfWhTogJ;~K!o5RFIkMCDyX$i@F~B7H98aXfxv21ZG9j}b;p?!@qxeq zF7QRxgBN@tB!HQT`#@k37}6DGvPz<)hf4sY1s@290@bD=?$abQn4|d^i3GyfWWdY1 z#&HwLtq70jk{{_xoF7~%%m}p352)&xgPb3ba~z6m>EZk!iG6cefR|rNiZC!r80QDI z5;;$P$HY(~9|v%LKsJ`N$oT<@ZG?4l0Oto3Xu)yk2b5yrCC(3SMpQE30$>5bIzM2X zg~ps8lzcTD|stdU&m(SLPTz8uUJAo72 zAtYb5B#508eonCGgj{oDn9FLDME`FH_A@c;`tTvat`E7mme1CQTtk~A>fb5YVND^m zbHg_Udv3^uw0w4M$n`R6vcn1P7W5@C^m*ZQg!0*WAy>`#pK)*-OKN~}D2+tPuhL9^^`D{bT<*rFwD+<0P*x!p`F9>fD>;)lL zyz90>6%sWC&B-##n&lNKHC^RD@2VUm$?|`I@TmzWeQ#wq6Je-{@5zp6pjQa z59b41$l{Z$RFm*A-~`_ml6Fgi*yiwP!EO$@K*cbZpoooSqu>F-|6~lmCEO?YEg@H; z^4XSyhqmF)L{voO3?XcmTCb7GjwN|U(s6MRQV-i%00GguVc zTvy7&kpUNuCdnF4@Li#qF||-JTEhy2^6+!Og(E(>Ff>Wldx8fAePaxLakxy-7l&LN z%EK)Jmw+b8!cFk#Sn6<24E>O>SI`d$xek|G zk32jyZ~=u+E|KubMUZ@UMaX3iKDm;?Cl@R7*~3GwNASrd2R^x~kcWo{E*$X5r2#%^ z{LjPV1I_z<(t^(?jr4hVfS?_oPukh}qzOHrJu;+qoKKp(`J^2?4^I&^PV-6AGoLgp z=ixbmW@A2S4(5|)-aO8U(0t1$jk0{w)S8Ef2^vuOq+yg#8ayYf)iU^&Cxy3sdZB8p z3uhsehwBMiI{Bm>bFvyIg9nx1)EL3~aI+As4{6KHXV-@`S58(NWbl0@xH3l27Jf_! z+CrKv^KfoKtK?*{BL=&D(db7p{NuvA1pl~@hRHmfV9@$lL!)9aDX=3D)Mns}_IKjsipLYV<+P5)0R`555 zv?b=V8$%ilC!;UJu<(>7`H~p^rtnO`-xShnn9ptsX&NLxEPlZ=O7LKe;DqodAvhtF zgV@;28E#kX3W7(OFJCx)~I=Cdb;wD(P>IWE|#G|e;P8D$AKha&*b zXE%qm`|(M;9tq*pt6eF3iYS5fo^Y)Yy(gqyk6~KuK*W)^Q;9xbN_0~AAt5>`q}48; zJt?fmbFx~^f<2nkKPjbpZ+N>CMzAHkK?t^l zw1nleTS6MUNPyavRQ%Ut_*=tY2>#ZP_O5((Ye=IO@wYianc`2YE#%I&FpE$=yDg+; zi%*)bCW{%$3BKZw;%t9ojG!Z2A_N^Fjad0?M@TzWO~?di6Jv;eP7J*>>=pFRkd~@^ zwlkzPs)oj+;3`$;));zMc$uJgg)~Uzvt1!APBpX(1;=PTddZ^O8rvN{A~fA0%})7j zcSy5R4edR_dZigR+g5dcZUJX|_;;b%9@47BFwI3ZwBrO5m1bQ;WBQRDVIx5K?2eGO zB0gybs-blzn5r}%DWb7ck)E(y2zx@Bg7Vp(kY=9AVuA^-_s5X`H!LOMcZOF8{?3rr z9foPRnXL90Y$}v)?v)t9uJAD-*cH-zlh5u7X`!j1*(KPnnLMG+=74;@<+Ht^0}!7y z)bL4DObtyXaB?dm+9DdZDd6l5n}ud~NLviUw6xUFAQF69X+CIa5ZxE<5cIx~W)_BN zMVYL&kzk~zhL(a%@FrBZ&j0S1q1$zUs9rY3_O zcub=Z+FA+}&SY_o29Ij|=%)QeW|%t7oE-D0CLh3zR=p#SYW(1)nI>lUm|XCvMu9Zm z2$d-2AU5Vvjk?mRQ^{}IVywuc8kx}IQ;HMws76CjrQ}6P4ir49kxR^@8cju&{3vuL zW23kAsKyFT+?ENxcjS?r|r}tw&QTZ7H5yRA)`NlBig2~Y7>M`uhu}c6RQ{Xw;6{ch8M_gHq zb%n+xERaIG_nM;&@PyRht3@u?Bz zfX!YHb#j$6a~l!Rqq~)}v?A*jm6f$szXX%OnMusb*?t`mePU0jag$!Ib;H&^Jv?z9 zU=wlTA?20x6@tG9!cXH>Y<#{mIzn~Rp5KLtaa-_nhsE$5|2n+a(Mcn(?*y;?-WWz_ z{QD=YB1@(Cjingx_&+CwIj!Kh-}1&V5}wB{Xra9{Q4d#o`IjGzBt zFYxBH!$nfzY}3{SILm=kM6Y_YnXNpTI~NDHteTE{wpV_sp=uXeo{hWKP@V0~FjVtq zAP3!ZymCh2FcQj#xig=twUb-_ZfrE_blja@NKO7aRW-RR;yI^LHQDLa7V+E_@oYH4 zD6-lR)%D?!+JIMe8_EJlp6akC+&$F>HzOq!tYSO7@>`6^HIc}FHzGT{sYc`iNk)e^ zUy~8kks3ley&MZ12@?q9bXmw2$uO1D=9P~(Qa&9?ahfz?ZQhh3DQ#Xoqi`^{p6NKw zo2DXi^-RZcUb6

u@S(gO_Hmc^CB}V+oIEtmEPuI7Z)BqnUa#yLkM$!=Es+=X%qP z?7CjqSloGDrDocWy1h7GInNtu^AMr=Hfe2Is<Il$NN*H@6-I+wQ~_v^Xh!N$4n&!wbaa=9&@v4Ln&+duS{0IOSZ0`*bYThvPIJ-H57moIBzRkon!on(Ct?nF}csN5PMCCmV^*d@iK2Iyi2#TS@3|CMnr3 zBCgv;xAbFRBs z!*Db7L8lS-B;q_@gKG3cqY(yi`NLtv7EMTlJHaG`S=Zo7UxFfSdh`u&a^Wy4==t@KMOIv4KAoyuh2|HVQg!ma-DO*rQ zpEZFUmOVa_-5(13+(GQ!g{spJf~3_W>dL#6d*64ABE6L^R*J-xQ)%hUlm$pT1y-zF9(qFH^_8UWhh~SH)hB zh(;{Z)L(CjT2K-E%b{Dw;_70(U0 z|0YyVj8!dOh_v{Nq53yV)iBaBbi&nH?=E{&=*ih#pq{+~La&!=tT=Ex47l2TYHN z+A5f?DPbyWP3{Wex!Lfvwbvc~z2UjSW@gI)$35Is_Z@5sD^0*wMOhhhmkPfs!>>>k zryZh+UTXQ7q{#xAyGW=W8Ko&JP`$@cEh?enI+NQdMCTktbb%piw5`b29xQyhbA@Q> zK|~K2qPZnRT>o-wh3E})jI^NMTZX8%goulh?nEK7XHRX@afjC~(VUoQi5ku^jKNL* zSOq4Vx{p%EWx-tDU$Bs_J`(cY)X4W7wjQ8j!0mL6JtXQlzZ!)Zy7SxRm@)seCvUrU z|0{f-I5V^~k4ZOWX{xmS?sb z0NkHESB4wGGDG|J4&Y?fGI!JkkX7RTPt_*SUV$l~c+@CB#Srzuk6nzW-@7$l93r4t$8NcHG_s5WfVeUFI?D6EcVj}{C2mXzin%di z5Ep&-@7;qP@bqLt04nhRlP8l5FA3>{cQO1HJep*9yJ}I)zuvn^2Qwq`ZbIMV|DAV} zSCBzRWZ-Y2$4R{6jy!<6eO8HglShFvf*F|%euUrh=kX(TD9blMcOc8m7zoCVp{ScB=X2wv zd%k%xGtGE6NrK*bH(?eQdpG$ra_hhIZo<+)>->NBZc?&;FVWk+7vp(Tqm#U8G%p1$ zb!5Vh(0>#^UhEPm)^c44Zf3M_KHDhwAi_88H(O;5`(O;4jdgGZSRpgl@ z^{FySjXaa2E=}G|$tf~Vea8O^0>(2*YIxKPNYblus+a{ScqU`1|5$IpSM zr46?n1$_~S>1#sPV@C=eJ5=9-$Bq;{cBsn6V@ImQV@C=eJAMaYxlA7~mrucC$4O{B zF^?T7c1|0D!l7in3s#t3$8Y#H$;6#J2J4WJ}4CWw3$$;ri1}yhU#-%|D zE)BkjSH3N8(f!`qZx3N8(r@TMt-O9LV}0lR<{TpC=RTAVj!ET^gj| z(tz9zDf|``G7EuNW|@$>G)Tdvfo9cdP6{p!Gza!NDY!K7z@25r9X!c^ni!V`DY!IH z;7tIU%lK2cjDIb1XHs+-e+rlJF90Nv=7sC`rG3a{{3(P)C3_iv3YYN{kkOPMbQymN zm+_N4=hQ$sT*m(dldhNXr*Ij+Bwa7#PvJ8DZzDDtP@RgOqxTrVi&Qq;GrtAz2i-HD zKFTFd@%`THq%G zZZRv``<&ufi2K{wAx}F2?{a_pM>#LX#=WiL0?vP@oO>wk{q5{AOYd*L0DR;3w=-ON zfBOdkE4{y+u-N_WFG9(K?r&%QmfYV?(Et7Zb{1;!{q2Ml-QP|?$^GpF9ejT~p$FgJ zPH5@HY15mEPY@Sn2)kgdKE$JAnt?-%eos z{&s$Hy*0gXe>;bJ$DLkse><@PK#T5gXFJNd(_{CyU(5yqG<@#ObSGbp&~xr|EG8H3 zZ~q!#wchl?{q6kT*q@vpzrUR==`7ygPF>CY?UY4+(r4iQcJ}b(C1Kp(&iF@cIJ&=` zEtmJV=kUo07chuV2K;=S!9_%x3H1K<7Z5QMpkuMb#-@#H@a|5VMYaeQTVy-X<50&B z)T({rG2|Hk+~LnvVRaNX_`7TP!RB3rrBb=r?C!c75D!cKtf8$i7~kEj7o+8BuQDvI z76w?$MC^Sd`2Ed=u9Z;VyeZf zXoR`LOR&$4`rbOj=sTy1B5$3?(x~zTXCt~ zo&)N!!M(VG3?HAV@=uTCZ@|2c8FTTpBKa5B7shup7xY&!-H zxCeC4>Fk|zQw&JbtN=<>cu7j6ZkF6T}x(&gNlMY^2ZY;>XM4@aWsiJ+nW{%t*g zpTT<@7sNm@;m!$0^2A8;1e87{pJ7YE6!72>&sq39-`d*_8)yGyZAjIE(%#jJ z6G3i&y#i~rb`F?Iuz5Ca^VIr#syK^5g`FK;J-Ek!wm7`2`q=jEdvF>PuFD;FeW4Cp zU{S()m@@dxmL_IRmcNS<$NXDw^G}=CdRvQU;T&PtZdiKPx0nuL)_`ib{%}oeEMY)v z8)s5BOI_T#ZFLH$ou!xIwk@Nv!@H6r<$?6vVkWfnl1 zOm-$4S!O{Id@d}CG6=YU%2QDgP!wlAvgrSN&Z&F5x)bL4 z{QvU#q-#0fI(2HVI(4h6RB~L(h93oc{+s@65L=`hH7XW_Z?mY;pko z6mBE#=9f+QxmWR&+b$= z7D8iPxH8QCsukUefH~qjG=%NzR5u=oe?a^L)2I zA`Xjy{iEZ@mHkaCb|HKlLKM%?;9&%ORH6=8q2WU*ydHt^@tCr|CBBXYsAX1&pI5Ciu>T?0N|&VU z?^?6yru5BLXpGUye!`mlN%-s}pP}I{KnrR%r}pzWpL6(alZNNj3X#E(TKILf_*9we5wy!tMZ+~9*YW7lfz?u z@|@8E=DAGe)YBt1zD2X2fp9UpY;}oxFV-%z%*$4b=(1HhbXJ^mVJLxRTyf4tp^Mmj zPv{dta=$P1Wi~Gl{glo3hyKjw2STKCD9$+%qNjt3bFK=V&*n9utJwTV=yoU2^u=yE$rBD8!4PD6QjiFDmc~j_7Hg697n$2560nDU} zb6zZY8_V%>$$ueL#W{Z|S<3#elqA^vTggpqzFKlNo3E9;lg-yl9)(##JDs_Gd<=da z?EPwfSg9MKH7zBJrknS%Zh-frL??@;oA%I7U z)Cb_bjOb+1bn`yeC*j*bbh2o=c^@l%bT>eB{`#(rKBdmdI1x_8%0xk^*_kK8XM>!s z8#oMJL?^;O4vxh+kA@_#e;krLel{d|{9H)#_W6+H?QcVp=P!gPk41(zIT20_IVqAJ zG#@!g9mv}jql#F_2W<1Ua|Kt0biOw4Gh?$r-1z z^KM!4G-%?_?Kex5OOLz?-Z*f z#l&9zrIFr+xTmu7a4MVFxc=U$?7USH*d^#w*?BmXO%b}@?y2m&O;$0*;`$q>vh%iE zvwy<^&>SHRpi|j-)k1T9^{MQ<`f1*BDm!n_bON8s&TAFI+-Tmtb_^HaNX4NFl`oa% zUb~VTNj}$_d+m+n3aDHcig2gx0envSRCZuPDT$1O$$V-e?=mYw#Y0_R>EkFlqTtj- z-sM(|+UNJkpMFp%H{#bvc7ot7>?_==0~Aytsn^v0?g5ItYplX;@TULL z)4ZQs!MK!v>flFO{Xi`&75>0(7^jeY)b*xAsCm@t^KgKIS`c-|r3B(1HBTR)$orU8 zNHvIhX)OnTte^K;i(3!%+D11qPYzJz-6W}^zMMm`U^s^B9-zp(-HMT{)XA4p^~*%@ z0gAjY2oo9rvM~$Jn;6ASX?Y*AqBJg)a$aQRz(W4QGVhDRWx<3v@4`k9g`o1osR}tj zfw#gdsGw*p5lN^j<2)~sQ5ZNtL4`p>Oq#4SiZM7qk@s6`_8DMG5S6{DDwU&;i+F049$3O99qicetR+1YwB%{&XOw> zB>$oL(AmIQ7k*HgqF1mYwBJb;V6-}O~)6PaoMxw@l%bHIk7Io-pjGK`? zD({EZQXcv;>Bad=9iBhruXA`_k-y%dzL~E*z`OI@x=JyUN}dxsf4o@a@HqKQNA8?kC;>ODX-pb2g0djj&z`%ThH5dIx>5 zA^5>r7sGGyrHDRM8ov$pWn{0&3Eds2g>rDY$_d?Q=6 zH%uaz74q8?p$Brm3Ri_%c@sp6hL%K!z-v`Lz8VWHjc{LFNJk%3XjvhpKA;v8Ftpr9 zlKTi8z8;Z~N_jQa`hWP488lO0Q`?xVX;;>cIZvU20CV_OrWIW-|<^?w+JKJe|6NuYe!)%EWdpX>~D35eERU6{?(F^N6YG$IC6{G=!eGj)>MzkYChVlq|Vnn)!_=n1>s+8?5jufpkfVvtj}zoiW?LSH_YgmouBdRZG@ z8Gi(^`vbJvb!q6xj^jqT@HVEozGJTUF7^)dYKoMr6b{-iSrvy{=h4e4+KZRP;k~Zc z*rdB&4Y$pv47bF5nFbNZ%kJdtfy`9On zL>*fa?H%a=cbWnACF>IDOjFS>PA778R@F=9Yui&9#YiM0d@As;h35>`S!O zCYn1^$>v(T*^AeAqjyh7*Cm_M-0qo9ulBf6l_C)p-cUEIQ%iHQqoqw(7rbd3{fbGh zOYBQRV5yL;EsaT(mSjjxTXI)JM{}Yb74+VJE(i&02D{G;CR}Sf+uA76OWurujy<-`{p#HC$tx@iau(h+8YyzRwLQpnobmH(y@Fy z1JZ%#t7{IXv-vTT+Sy#)(UEAbOGz|dk{&lf4au5B8-PaB`_9bt`s((M_VuXnRMl1V zKTK3@Te8FGTRYmSo7>?-jpn;1uKi$pN1`cJy}$ZkQ%fCc*%KyJYFV22z3D_$PEIjb zQnat{PlvR1)TZ`V?*a24Oebmq(lz*pCPq_hIy*X0=h8LlM<$31Q$yT|(~~BEvpWm$ zlnLm>W8`=SJJD8OU7N@P{@4UIChKY&TiO%e1nuc8YD;TEk9oS)K4SuEsQlZ^LF6Yh zk-uOxzVI5RrIGP2R0`5B^n9$vy@G<6Yl3H$4Ne>s#NqBCkINz!2R;% zIEfgzU!5GMBVMbbzdkuoA_nf+lj9^};GR1MV~)8P$CBIHz&tQ#K8U5#I?4y z)M6l_&Nb1|L6atC1e6(;$J)o-kq>`QonQ( zu*cjjhCiJI>~W@EUPb@sBv6m9K>vIaC?Qgq^VaTB(U(txt7&P$km$WvV{xb9zJCJlr9&!t&OZ^vON9i<{U?G{*Vm&*>o}NdNVa3Ca4_ZZ zz{m~{d~E-(a51V>-v1^1{sb*NxWNSeiEu6Zu$0DvuQ7Q>H81<#G!^;(f4CW`3H~d5 zj8ujGmGDOV&dlN6#>SPJa-|ImTNN!hIhux+l%95lPY%TrOO|g~BO2mFP9CZuQC-*8 z(t>4dx(!F)BnZi(i%&%hPXcPhRG$6QbA9+~d1_M~MljuC1%ZxWYQ0mQJktRkYNkV}jhi zKiN^+AO(T3s=67sX-CUUkUI@Vfsxvv8WY{NL{l|dF3m7zo6ud2Ej7>((F8r!ioOY1 z1#WXpNIRxeq$5Ed@w%F7Kqoq}@|i$cjN&GSQ(aSCyN6UxSfzDTw_}){YeKT9spgiB zWIfhdva*_ILaSRLO=mN5LKYM%I^QI>)+Q4NC`Fk6O`ix>ya}|ry|u|3)=x1(iDnve zQ#$kOTadF@XEtCjRtr{D?SW6Pk;oubnnJqk`zltZ`b zp~&xNfcOJ9;5VlMQ?gD>q6(fYrhqwZt@vyTT?$s)@GY$2z1}&={evSN(40@y;J%I2 zk;+t63SY_fO^o$+tJw0A|3S!^FnAGJV^(Mkw7JR7k;5aSM@Q7G(~9;(hdT$V;Z!xA zNbgQl?zdRGOO#|SJ+WBdMc>gLSF?sKgVfYDJ~7ZWq>4sN-{w)zztc9*)&2NVspSw~ z(o=NRG)h}9eKJ0R1F=QlH;J0rT2-{#XK-th11?2(n4ayEJsO_GM{TNTFvkdyIEH6Y z@KJ8<=*S2@3#L7kqQ^}@6Rs^8+?!NIyK>XPBxgL*#|=`Fw%3TGo1;aJKOHcc7?~RO zCrKc}9@--t(q#YZ&$#K<>pW14WnJ}@tG#1$2&$vA8|4Pt>dG| zj=K{6F^kwfId#aT?JF<>wzlh<=ThTggR0ZrK*#KhK9NBg8bm&}_u?zb!O7#Q=xY%p zSbOg{J~BxYhoc4&X=xdw$}ypeW)&KQUA%SV(LQg|+VL^wXg{a>l-RT|Tuu7Ax_jk- zV$r201R2*oFg`j$8*oLjSw>)k(jXtn7QOFH=!qkA*Id!B-h_-AKZ)0MsBTmj%^XA1 z6h3BAMPD$t~yO!BluVooG&v;1b6$4qCkle2>IL4 zJ2XZi`ZE0SnK?Q)-F&6E5#jet%>J&yNp6W__~fx@RjI+Yx~FHnW4x>TFd7vlcN`yX z6n!`wkvP^pG&O<3^&oGUkk-Mm-kRf7dk4x4-sIhggE*?_>1^-1(Wyfu%kJ3*zIJrD zgTK*+EYc4xDmTbz3Eg<>GKoz^PmDWEKs`?Kx8czr>ZFVE;zm%NJK*c~54%k=<@zDy z!T!O?f#%V+UQ`Nv_R@X4W3+l~Y-q5%i|RE7D^-*~w}g85IlRBu+}YTuiVI{kph*sG z`L(q-U<0d76^GNKL^9nGsNzVbKQ&=h95p=2$E_X3g$4m!xHnM6F~gU=Jp3$^;&uY6 zxXAE!d*3EBp2Mh5#l;4(uCJ|kg4#K*%quRLk+4=3m(EC7r;5vjz?-D0^r)hWXP2By z`6h(wew2ed;;7;|CJh8`AJ~ld5>+k$9#$p4;)Vb^Pv#n4G=%KxMZ+EJR>kwO2n{$Z zLdl+=S-Zc#3@=Rjg zcvpYj_~@7_UXe+t!3$%xlgCu?%1nRC=H799c{e_xidUI5x^i={8(m-*e`a00dOERg z5cPhI_D9pHt?QfEH#!84s`ykBURR4bb~iPBx7in0n)J*8rnt(ap*9IQYb+^VYogHc zP!efgQM}G1Ah-+>#p_LPR0uo*ObumHlQ)=TV*nzFWdteSXhNvl^-{CRq}0~d)#FL$ zJ>w%os(5o21yvm*z~piM&cAp|7L~%)VGcBkWNgi%A&J8n3~Q$F6y1m_-Zq_lXtZV& zMZ7(W(t%4CnQ&Sbp?09R`!G{>WKkNs4&e>8;?uLdWeVU*urrI=h>L`nTXhzpy&GfF zP)!$FY)uwv7cL$j<3P396l(lkLz($iHxp=(`cxxR6Iq~olwc;JJ_}JhIy5?-3E7ne z;T*|?G-N^C?94 zhtl_-VuWt(9iO0E%Ss0qO!w8pbm>=3nkU7%3yl!ibfmA%ROx}mhA&A?S=ZjNOO<}f zq_kt4r1M#&2bLIkEloY0Mk=jdHl5-Hd&wj=j-vC$lzT#z-oD%jMA1XL)r7L^s8yv8 zuE?U1XryIQr9&$XQrqb0q!&?Ol|iZQIWjoW+m18As`O5SAnSXRI5GW z>~J8jIWvl4L(GrMJO>=rB|*uf_2~m z`|6P%V%gp6&YDX9YC>AZD7aUHn>QH2>juZ6w%QMcM(?jOcH$G3p2|8N1Mt_5c(i;-ojY>}xugnuJ-eq|rc@=Z?m4jV~$z|<`wkY0y%(!j}FkC@uU zG(Z+=ZldC*`Y;WWX-nBFGgIBbFPXZ&14tkFo6g*@O-pxa*x%WoMd-!gL7TN0j};B+~$f0>h?ejVe1L%0j8T zx;3EP96@(Cu4Zr1YiuO7dTMf1I(A(Zs?4e|=OsN!c{8L}C+7S~*BRE}LzO()OAJ{X zHD{YyOKUTTYt@`XriMFBZNxHn&K+jm$)F+NSInA2Ev9R-dqB;(%d9VyEBmV3lGWG* zopZ5S4M;r9(8tuA4QBDDrG9!QZ$#T_>U{~$l0Ipch4uybG*k7;QS!(By!xF`bGl3g zY63dlamle~On*tYLA}6Knzm1kjp1;bL9Q?rqZFsB7@aefP0F*=r+m|i=*=-0_h4Bvrpj-d4#4&T4T+d5(e$`H zCubUq>PhV49D?dxm0vTRnvj&M@<{HqkhB0+<)4{Opj9fTb+Lb1AU)J#c99&J;0qgQ z23Y>_>Bw4|8)Juqr-fKE*pStu|qbb=Rrs{Fz?Bc(U<%3qm| z;W3pfuPX1#H@SB-VogL3{UC2Np^heUQkh(#b#pC0Ehu3{35nX~0#x}~!7@_R#yt|P zKSe9w+mnW!qhUN*L?jK9lVfeP2}gCNKZ89{J33lD>UXk&*0r~|Gl=pZW`{J11tAg5 zjZ;?>s9%QM0xJrcnSzF-TY@Uz{U(&Ps{D>Dl2`o}Ihouv0YUyPi(=I0=d(z}eL|ao}W_f!JzId4I>1=CsSDo>BO` zrgQz;3~FY1UY9}3D6EfVl4dBVk84CaTfKVn36rGtCSD_HH5VV+7vheo_$lVJjhLlV zabY%zwgBS4%=V?-jHwB4e<(g>PW6amCLnQ4#cwdbTfppe0AmwvB=)L!k2x7MNfho0 zlSt*5{xl$7ZB7(3Xlqscp*JP2Q}J!)ToMbCq%*1F zmFAR_ZW_|fOU17>DVjA;x#BmNQ%SCp?q>z@nE4Ta4nznEc>GPMqz8chU_!-T(Fh#H zOp%lgxUWmaH_T#PrA(vJ-lv{1{AjH1tH7r84&nV zInmsS)5D$ZDY7Kms_Edt{8BEFXbMMY+DIMe9_7Zxi~k-|?f5pd=cwDes)|pBuE(7Q zs<8V|YxiJd??^vh&#d?qd*c47X*?=EoqKN^PVf_-IsK{e{`Oj^=sPMASe>$X&FoC? zD)Bxo)4Q$fsQ5RsKeuvpjw6_;QhRnAg<7ENMK(aIuO`$2sTtv8xPIa;#H=qL@O=jM z%CW;K{kG_xb}3Quw&*ExRR#z6tsB5nzNaX_(2yJ8LA#Ww`Mz@&NC3JF7EN&^HAZ6u zcAl(f`F+t1S^mbAr?`3nFIb!|cXkf)C%AO?ac>81%D`o(&)Tc#wh&x?tk!k20t}Z) z;&vh)fUIZif^Y7Spi}hmF8-|RuGc}Iu~%dTo#^cvhqf74W=QaF*acA?{B8-2;K5Fb z`5X2c9lX*Dr>t+<^X346_f&O~EAfiqw`{&slOEa(_d{Aja31FT zsu^^s?i1}IWhCA(EqK>fVe&_h z$>W;In7v3d*~m=B>~(aR3T|O0fzR^?ajiBZl$(qVW{vhzm)TEn z)r-~SGCLso(d@bhD)G`^i|ab462%Jst!~;njHJ{mt4`wGq2qm@M2mP|)bZA3<$J>A zJg|Y~sCV7xpg@r?d@YT&R@l~VlH|PRvAt@)M>wzZ;;Y0~;$da2cRdC+eMm<)qNCGk-)!^kGxmwIQ0csKY@EWgji-p5_iPk7 z-|NZw-&)R7?8O<`zQB#`9Le^Du6sbOM>TtY_{5rr8^GoYRfbV(&gbzx>UbmL$gjM1? zp*JkuN*mmq7dF4LI2}3bgw5?>)`IWWOtsmS{e`Rge>Db63{@Qg%*K!h`b=_rN zs-APbDk=}*%W`EsZ+Y#xlEjew_>IN4GvN{0qm{iQJ!!&kg@7JLYWfRqTJV-4y&l<1 z`t^~~$v)biRMt~g!I8C+ocDXVvf&KLm8a6lVey}GWeZf|z0e=Kf<1wb20JzMz%G@y z2>5{H)gP*a`K2E78^Bz0;{j_GUHOLbU@ek>>+P-0bmJ8DYn(d|rjx?C`H<^Iqs8#S zo8-8XUdr}H9gz%P)Cc_+MZ~r84r_rFgQC*C)5@nCrl=35&YY?~h9PBLD~x_$DH7lB zNxc6|$&PC+uQTWDxX#Vmfl9iPNLe3qJ>355<8mJ|wPAEKqlfVUf%FIOk+^boT)*++ z`jw9BJ(kz!b6oGS+&+Kp#Bp3@{vInKNs3ltuUT0aTlsXY7ZSDU6PjtgW=d(k(wap# zZrLZ!L1)t6JqZqnMTDzQmE?|jA}m0ML&No9Yp&ZSaH0B;6`|Y0c;xEp>4Ex;Gwm%_ zfu%X5yNjcm!&|%zlLCK>wbpCaI`j^aI;#62VcKGa$@^n#M6@1Hv?ny+qeWG~eY`!Jk(O%bRTBXG zg@sDFb(iM3h@#xi>6;qy+VL*^Vf-enmSPD8BIZ z__+)?o^M{LPNSNOFJds@DeLwE_cHuh-msI0P$aG)zkt$*wjJ!??WzN8)JZ2f?H+dcw|FjRhg6JL&{c6=0rEd4LMWbTevVbcG? z&bd3DgGv7jFP^*O>oDnm(VFtp!6KAz`4GxcvoYgYYTQ`nR*DF?6bdJEpw|baJR`m2%;8i;ua~teB ztEczKS@`m8@+`cfJg9c+jsPiEA9xO#!dEVLr;gwi7}~rPC$=@F!dHjJ933;>|d#c2X+_;;T(RuE>zM50s z^t;(}tbhk17AkK7mz0;NkvS+j_mc8_+)tiQKVJvipnrKz=pE%`S&^eGap z5O)>2GEU$rX#a>tz#%-=5km7|#JOpN@aQyn(8JaKcW4A0!sDpHgAo^`5yFF>R&nJ3 zVy*ID#gGk9CXTG_6*gaU*|_ou@(Kfq$tor54=y{+lM{a*@g6)O=*B|pl2*J2Tt~HGyo1s(G_V94ES{#ARKP@ID{bMfbxHr zWmr!RVetcxg+@Gww5jt%VWZ5`x_ z{|A?i^LA<7Ol-hzr-IprR(9=z5pKu-Z zxN0cA)$#8W;5sPVB)M0(48e;4ZE1j{_jZ>J1F9;Of6$F=w7;rSxICG`g+RR~NI1Qg z<^(kX-cEg+VAhkXw^cYT#+AmBz^zE7DiGu`1KHOq>{oIsE~J2A?@GgTd;OTlO}Dr6aLKp-2RhyfxJ14OU3RK~JkcBshzRzq%Swg1dk2S< z|0dlY;1DLc0i8$}aYGs*JeCrIB?(BXes5abXZ$uti^yp%==kHa31f<7#}#xdrJ ztQ*)VY_9OwxS$*pB%Hova6*A7f4NR{A6z=0f9^7puCahf3Xk7vsi+))3C$%Zzf05=a#Kvjd!JbTrB3-H25I$lO?%tG}r>OazvGHPuWs*h2B_F^m;M30A>-zm5a z?34&+Lp7wcPJ>!aki@rxK%7XIQ-cYT=(-6cwRmu1goeX04+N(~cZnGtgASV@iSAZ2 zItF!{Ac^k#UUcDeDL>yM5aj0w9TY&7r~G`yi%(GhmW7fC=Y`z#3F_@xD2b6?8IS~q zZ=e`ICa6slgZ(3i=tEtKaF9S!aTxTGOpwI){&ai{x;hgi(cPJj?ne~eodVi2IDxP9 z@ihWI?&27K>Bgv|W$+iW!95al0j^%>lGJsU!8d1v(PStsTM0}hs#AS2HJR@SxN3b` zj`MJ$QVTOoL3p5$Jm4VTnmLFT>G~{@ILOy$4x$D7L6%_GkYK-+AR7lKaL+YXtek{5 zvgBdpvl&P&2E8y~<_sf$k%82)?Ex)1Cv3$~#RO#rAJb4GKX7_o;)a840#G@v4F|k z!#P}T8`vph(<(x8^>smCH9<0*kg`RZMM0NLE`R8P(zDAW1}6bMVS{U zdvxqLb#*8&%AEZ!Ct)X8e-;*bPn_QAveY@&JC4Chy%2zY@|vmVP}jU@;@ zPUyeP0BW`$$zV%BT8Dqq17aaA+4%4@js*O;0n{9SpT%+D_!u@y{dWm+13NX(l38X3 zr~(bW!-Q(C)dcmDuL=gSVmYMz-_}re%B-=^W$J;xVS;2L_+FQt3V(^(*Utp9aj3rw zCmkilU+@?S=IIQK)SDlq`Bc*g^xrOKh`wy-Rir@qYnl&ZexHHqV@x>|gHop9Uy(eP zpW8bgj^aaf!e}RfxJ3x)4PoShgj27_i57KLSWC_lUK`jcNxRJB`oPOO#>6uPlZ^={n7Z?!X@^S_j6xrr9-GBCpDJ83?5Q^}7A zX3Ge^$~bhK3!jSW&uLZ+J2x99=_>~dUH-Qcw~IX3F#K9Ip& zYh9$a{D*{CFHM(Hb%)Dc6$s?p21H8kM=n1=cthF$OTlc=EtmMbYVZ-zPfd_;nqQ`q zt->Fpn)xSzY?|oq8agzDd)9c!-%Tj40jzu#=pQqoeM4MAQ!Yc%(}vF?t~q(!vutFp zBU-ie36Cl3iv+1MkXp0!Esv)l?<1Zi8aZk7o_}yzsxV_>85l`%;cPd>1vpiNXOaBN z1hs*kQgt>Gh^v?jT4aKR)0rNpNZ`WI6Ug#N;G$3{PUd?;!z;*qU+7{sFAsf!&G(1y zX7dA~@3MI!bjnJ?T@^Zw&1*vY+5AXolFg5Xu4MDt&^>H^Ec8=0KNV7|DBKO9Fq@wV zEoAevp)1+EF?1K3H-&z}=FOp(*}NrGzM8_lSn{89$$YuwyVzBT1pZR8mHl5SIl$)M zO73Ix)spkre68dfHeWCK3Ct)xrx(b0M3a)uMK0xzS6);7BU7pFW5-m!-wM5+v3G&@ zGxPKD^A3*t(U8dU@eH=7 zf;Uuh>|EK_p$Wwdg%6_q0jdiA04;<30qP`T`gO{NPFw^V zyl&P`ru+a3#N2aWokc%I92omQ!AUDZfr^AL`Ak_+VpdE-q5i7i2Yq3x+a>N}pZ2yG zRj5*ax6$67&lSIvo^7;GV@Hm%<#|VYNA9PAEb$)uw0Fj+Fm%xBAU9bFTEh+m9nxWI zbAOJoZfa7-Q=axjloZMSz&7wI^9PQ@G5ZjH+Tfn^SEQ7}(S9~|UwO~YzGX=bXyS>R zeDGrPt&2$R;*6&}Z9L^koK4>&%EnWkHz2e>a5Mi>OtZ-9!Q?$p8}E63hY>&E-vNV@ z`<|zb_dJQ08`OKx)5d$A6xb!`_dIR9=V?aezUOJ8$3$fuR>ivkb#3_IaO(KP- zmr?ht)^1kh`v>51qPg@6nCDkuqvrr^wKkiyIjqggwRtPdxx8N&{A!G<{Z$kpSrB}w za{*jreuv>p9ooX1OG|4Nyr1D;GvLddTNu8~p?$oFv&^C0y1BGxrh*SJ{7(jax$_f- zFL!9mF5)bAXk(7yYgO<;#xI?(rEx`C;RN9oaaK6AM@J@Y!_B1~v*0}(q|*%o>PqKy zMz3^e3y$2h%QlzgznjtTG|;P@VMecVXs<2eta4~eZ7z%dWk%m_pjSKBGJ3T``)Uzq zwL{xyB*}mZ-plY`8t^sFw-~<0p-r@iv&NyVG7<&wuP{7PksToGr3LmN|M(%#ct z+Fnq>ml;0b!W|k0fZ6CYa+r+{Z9$QncA4hVPEha>4sxv*L^p#?&P5z#lSA7~5oeP_ z`$%(n%P07C4)bj{49J_EI~l&&p?xHB(>~E$-u?-GgW-QO;9HzuGkl9fdqojvi$gm? zb9o;p`1ov+VcCLo9&L3B;fgq09oiNmlQw_m@-B`Fev{cBF!0-)os8e+&=yd{+2+tL z&s^S-3I2uQ?{nd9BirtbahUB6ZT3W*?GA0|M4Zzd+OHv#c4Ek+jg}nCJ~WDBvk_;f zL;ERY(vAt4v?mgAsvX+(Ad@yW$fUiCh*RUx_5_)<13@NjGDMtOhxQT3q@4mXX)hq+ z)H$T>CzBNVWRlK4;v^hW%aciJcQQ$%9&zfCJ7SUsoZO_=jySs<(p8g5nrJdf&m3_Y z9MU3_N!npDN$VSNk`8He$s`>unWTA*IJ+Ivr;73gyKuL9v^gK( zFl`QLB_mFoLu$u)q#g{uTcUWz4Fht!^EHOIJEUi+SpZkW>2yemNG53t2@l;~@aGcXun}ON)5ZbzIixR) zIQtw@3C?5nU9eLUeZ7l!6TRPgCkNW^kZLgE>~~20H;+_#!E+_d(-~phfCrp=IN$+? z)PND^fJ16N3V2KfQxY<~L?_=3bkKQ;108fo%@=VFI;6luAR2jlBv5U3pfj8$@QOHR zIHbfQlXP_RM2Qw0mz+MH9qLTyOb&IXLyEeHbEZRDxOt*a3;vf~LS6ai+)x0V<(%LE zXE~&UBR6T-=9Ahi_yLLJX#@Ti=V6Aw#UUMA#CeNDdbIhZ`3m0QTghx}@NzM4bHwyw};u@Lq@XQxT`vAqCWYQWFJtOFeq83wJADpEJr~`W(_i zMVvl|v`q6!{S$1FFb{ZPcp)Bf`kha4n0|+pOynl*(R@}(akf5LI z)G_{Chm<|!COytPQO^YZ64m8KfWyut2RQ7IHYeg7c1U3}pR_Q+e#zvAT)3>MBhHX> z1BV%MNN+=K(#*^!9ZRrV!o2K-(bJ=0=V=Zz?2u|E;tV^ac$rW7k>E8FX3>gt*^f8{ za7COEhqNwal2T=!s7iuGl8#Ozz^JpG1B^PPS&2BK4k=GCeDof}$NBbU7Oyc#3*v0R zVu~oE=)`>%&kIN^;?QcD{RfqOh2Tj`lJ*}`_LWwYswrtrv_C#fp|fbpzQ!v2JG|-N zQ7he_7r@iupFH@fihw`hhvgK1pa8}K${kX@q(i8Aq}8ymvkGbDP3jn46v@hH9!^@& z*WdQXtU_9wl9ooxL2GGcf7aqvH)(AQHORbS+$cDr?3*N2q|4z@ESLgy0@~2-31#1I z#Yk3C@;J1n%|sDM*jTg=tkY|`eiHZRxat!!>`Sif1Y*pKf-9oBai)H$s0EJ!%4?=0Bmu)edP!C`%8!ET53odtUw)^`>( zI;`(3XmVKJS7Za1#U*QUb!FrV7SWi zy}AKeAD^6LhaZl>%8N9KT={W2c}Fj(ueCzt5sc%an$e>J^c+Wco%n^~_|#p6*ITjm zRKMbrxXC2E!OFjDBUGmGq0}xF-e?tGPzQxtoPe9Gf_K7ELA<*Ur|=ybqTej|W#XyA zTf|)%r(=y%V@L1=O?aynT(|>AJmQmwaCC=4Z4=bamB&fw?N-6rTd;8xpFBD>2ANN@ ziq|8e);OP(*o}+l!aJFUJ)9%ilm65@9s z`we$ZARFtgl1@nQAoP<{U8!bV)(Lf54lo+2 zHkK;7|&DFFA&nVqwQ+TS%kl8)`2(c3xj z-S}PgxEGMdN$C}5{{YcF1;T0-qrAf1ipb~42WJs@%>`83@3-ds1&$TuxFqtV6_}6G zjQ8^6DUqin^HrSBRz+~8ka!2!d2|3O@5s~Q6^)DY8F7}ad=d34@)L2P;*R42?GY9E zsTHKrW?39>(BNI8$szidKJqh(rE+DA1p2wS)~~#QSo}gK zRTF1ze+ts7$ZxE88*-v9K1j7b@`6?L?0Tgxg3=WE$gk@}9$_d|>KSmPegdcR)z_On5 zEc{RjbysRVWm))PcGx&4kH#|C1D^Nue#5$v<8(exg}t?8%= ze=RQv-l|mOyOp~?q?J0u&$A=2egj4I1BxD};SYgPD> zT*|`Dr6Y(AFIFMSujhwQRkxRN7o_{-Z*YgZ1I0q6fo7N*#!gAJJW7?)9uil4mhK5s zhv?ax=%P}pakNSb`22-lA$s)i;9EHN=t$|oo58^bhKsTC(sT+vvm6{TQ2bj8Yyp^F@p92vS?S3a_Z zVzfno*e2hFaFuk3Ga9RoZrO;^-%$*?YkUfJ6xL*l9L!AF8XBwhg+a|F_$Hi3f+$x; zJ_pCzXzZ%s<**2ot8)z|S91mjN_%>TaIa+Snj)%eLA8#?vDgQL#A}^9ip4&Zdj{NU zIWdoY*w+My-9C9Z*`s3D6+Z%(KS1%Vp?rwVwtSSV%^mIXx>!XFyK3*-gtK{p*!foe zEZDXVjr3Fh6nm@16TPhi)W%foZB{V>brv2mvk(p=3$-gh&P`Lrj=F>Y#K1T+KIV@6 z16|O`$BtW3sxD4^O2sa)a(@S5qw#JUi$+j)V{f-&S0dgrq~j@&xc~ShJoJ8Ak(-p* zg_e&1+dADsy32|LHX}h(M^x-?i?eMj(shsJqnfc5(ZNdNGYdM)CRdi9W*DR3B>qFwpux>1U#)3Jx8pAE)2 zPrfFDL3HIPRjEg;!ULF#l<~|Y_H~(=RKzJE->||xAT2`~@@*oUV?VT`1Qro~WT$6k zF*pnnv@1W}H`ImhGWMjcCuKu)_-}+RS&cmL zR9Dsz%h+p{kD}R(o5=U!gkUsg+tE2&!4qR8kLfX=tz$tPX)ZCp?fW6Pu9$}?0THoB6IEby2L` zj#AD_F~-eegu^IC?V_4AtjGP>T(>9(CvfJI2maVRws)9d2b!>Cz7`i33EH+?AUjcecG&W@C-w50G zXl&SaE`v>qe#9;&fLcl8eQeY&`8!+zwUw4KDmG^4b;G??cOvK64#}Z|4w|(F4x`p+ zS3a$NRP0>0zMw-n?6zq1hvRncL2#$OHVM-oAW4cu^w@;$BhM9ogM6_^n95u`KouJ30#;kz^sxt$0h*7#xN;+NH(OE-emRA`Yt5JMBU$R4ooF@Vo37 zMF44N6-obE8h;=MVyq!CV(+$npM+yu?a=51-m5`2U1CR4z-~pRUurv)2pU!{vz_Je zRonP#>$2GA?a1%o-b~Ity~kBq>HXBfBHGCROh8&eFpI6?8ly~k5ne8+CL z3&=Z&tHbx_G-LySjx7> zmiB}yBWtsojoBR1KWnw`4dlw~KFk;vA}_f7Ln?O`>@<1pNYUJt29k-CnzhR!49?Z} zr=aT^9_+>^Ohqx)>z=w3l*(>Ym}vN#=#_Ak@=PfFp#pNKQhFO$g+DAKPbv4?;g7J( zLD5imw46eRKk7RJcz>W3rN8_D+E@6SKAOy*z8>~Va>IX%u7SFu6yq}KU9hNmwSbo3 zs&oo#lGk|l9Kad_*EG`X9_xhH^IyTrAzHetwx{*{XMALENII{uEncm0oIip< zKA8uew~3Wvn^Fnq_lxR4z2 z8RDpW$2gV(@f+5DQhs6a93d4LmNDUoOzOts6F3ArMm|w1OvQC9jw6nvcx^FUD3FWd z{WSFo$HaLFJG=Vv*{%xD62B|rM|-=l*ew$0hvU7t_Znj3KGblr_+3vC3#vqXZiKGw zP;cMJ`6^s0KDQz2W4%2jOquxH6GuOGWRSXw@Eq}akQ7%{DqJqkNAVpMI3I_n3dhCo z3Gl&fcY>QMem~a90zVa=Cw{-wegd2?o-b%mJcb9372^4#tCc%Nv~sWP9P1jvo0s7Q z77rWB+DYFrPx7m(D!foo0r*ljjMHs%;YBiqj9NPX79wObT||mUS<`MQtDXl&Z(Xh`Kj=7i(Aq~xoC+re)t2V zGM!D$l=yKsQKn|o9G!TvJ0SEi*S(&7EwzSPZg_>|yNeq((Xo7ky_z&F^vUJ9P(=Cz zmx8cuS1m3MK@mS1KFi80NT5@vl6#Bg(5!kZt^3cmVzeZ}QYW0UqGgz8Z|z1&o?{hm zq%mLsr)y>XvK4xULspb#Fk5j8S-9IOqC{-Pgi3{btSAlq?s!nVGQ6>VZIX@-S0mCL zu=k!PrhM&Ukr#hfV=G%Di%<2Dgq!Kz-uia+W8bA#^yBb|H!9y{R+zPjalXW+NBQ0> zdagj6H-dcc6DOvuxZkl?`7XDLC}>pHf}e+#bMKp~NOSkS-}2#RQdNUYYe{tvOpP2K z1l!fNKXpdcTGO+&yLAs5_UZd;kUph;kKvB~tn2#fv1fxjm?_kpL-4jws9MtF!M&37 ze%P*AqBVK&+R93k6VW=lMTZu2zBM*$_i&X>V%GuT{!?MD>PCi?ui7pYHs>f+&mvLk z`%v|$|M8XE1(0=PHo>^T5`v$vh{db>ggp|>f7W%ck?_daa(e}3EJR<@hZ+v|7A^X& zI%*QWxXn6D2w4Xe+L-cTA@O4{u}_?12zA7h>Pd^F+T=;)QZmJA?Pj?Swu@ZP*YAQ-!H6UVL70Z@6{O6=h5Hq2-B^6&s$+qM*2?t_XR5XRSl|U2=p@z0AY!x zeE(^&vWM;{O1LQOmGNKQ;HdKb-pZ$yoA1P<7bundhh`*lDfL#5(Tgsl+b&4Bs0>Cg zxr}ZkM%9=i(I1*R|2^U{!qS+g#J&?(T##^4(7*E^OY~Ql(Iv#_-I~#;hLoWg>L$)t zzSnWp8mhMM#Jeu2JJhFqxJ*#0`hhysg}+-7(um+%uR5;L|F8;ZDeOCO(FH2;XU+2r zH(CmxV~44TeJ5Udn*_7}36TjQ3gv z$MEzL{e8fTao27)#(UE-B8>9gYpr+dD2_~{f!}NG)QvvzVa=yj^Wn_A-wJ7Qut$uY za1rtr3;itA$~pvUBL7*}z2A%Z7HhtnRw|@htmTyLNUGY6jRPE7;tczwRq&_1BL3+f zlSe!zpR_786SbQ<7EZ&}RzX6Cxz!8PvBypF)z&;OVoLJWR;8O{bXZqg+jV;D(6wA6 zeKvJ(J({IkPq_wu$nr@6ol|!#rF?MGcxazE;P%RsxRzYHx+4~K%j>vPaed7WWusQ5 zKHVzG9r8qwbuW-6@FE~r5t z7vXVZ<%KLg+$6p4#BCSqdb|+qxE`-mi(Q$eT)HjZZTg=U;rJU**vm;+7O&e{AmZuD z-EFOwni3H4dR+0&+Vcr5-YuQr)5uvgHQBehcLLp4t(EHyXWFy1dzi1!XxFh{@5LT( za!a|^;v)&vl#UUT)%1Y?HzeiLdycqKIB}6?ajs@jH{5qf`I1(QRr|P*QV$T+ptwn{ zw*sCx+7m-mt6O?hcRt@NnR0_C)=Lm;3A*d`)&i+&$RcvBc3bzL@@=qKr;pyg4$W?Z zHJ7xvs7W*uY?MtkRKw)YHFJ!J{P$h3=F;43qThEV9UhxJu6!kK z!FJS*;3iC8sq1b`JlG_W47q|~zOu;T4J~xQGz%n^bdyL2+G{M@racm>A4N!i)^)Wl zN;M-xUt6y8vxOylZ8H%dSnJnl4)eM@?C%}JG!FUrhW0pTuekrtt4&-6n)soP;wut^ zk{0E&f=MvMSn&3`u^t>7_T^Z5KGV8qh0ZXpw2++2i+lfr2*R!AQ7U zB<409lXcx!bz+`dm64d|w&}z)i?Gk_k`6K|iF@811`r7*%_z=eR6}WB+;_t)66Tg& z64Os?i3%~bO19mgdpy;``EJ4YoxT(IUAPzPe~#f6jc7=|FDWwKt#jixNVpf@&Q>Yk zH(0@ApQs}?aDS8C)LW@N-_l9ryl=zxE>zDh=PqfVChha`_eGuR%PYu+9sz|#Io-}3 z%|P$5E?KGjE~cJleWvdq_cZf0Qz+T_&$;TePoBwN_QOlcIkg@0NVJUUK8DUNp~BH0b-^K38}B&DbmTy`2wFp}?9c zqu#!eQ1*#vGp;4@y}dzPWzDn=>$|XwJ~6RRR3Om}uywLb<6T(Pv7iSj%`z&vo^L8^ zdsT{avBtS6K|^#L05Y{V_t`pL~@x~ z63J8Dk~o5NCwEA?qs>Q%IXS46q>^Ceo*>9*c*>Bh>MI-Dt zYFC+VZ?t0O&z*e>(^b#)JeTX&FZH*D>80L}DO!x<3r~@8S?vXj6og+?_5w)xzUvnX zcrT`KYjp22BwO$V;O_VzDwp`wPmEzkHi_$TduVF0NjrIsd_KoN_7j=pxf5OMx(hKe zS(2howiib-5wJ+6GUO?5P?P5h>AwTJ>QYb%PLevw>T?IbA$VdK=o(64@rS#D`>otDXO zb&NKeCf58vxVg3MMI=XGzv@FTtL!(uU)7#=zv_&)soHXzDh%%;Rol*UFHf~|GH*I=p^-rQ@#(*YJ^`NJ{;k1L##!m3*h$AV;V@T zd|)O=hXXBRO*GBO%XxzmU*V_wSMvv}Yfz8KIHoKZ6EJO_VS{Cl zDq~wq-5xcYY}jJiqvnteJ1cusIoW8FWsi!Jm3CS7sJU!yY1^abu?_nycu?|e=?d&We3+?ADB@6HDEF&B5>?~&+_H$OS zg?4sUl8ttDR*9uettLxTQ%$m2t?{f$b*g9Ig9`}(q0OHvveeM#&swsPWgS^)V`@EF z^!CpNw)3XXMzVIGYHlLS?xt3?nJkIDY73dzKibM>LTwZOJ!-pHlIk=;B-IXqB-QC; z+0~I$JK2&*s%o-yB-%SvjcY??P_^W!r46V$_O4DgvMWKZHq^JaW>ufISE^lUN0n+I zM}13MV@pe`N@_=ITcTC%CPxQI?AqhHn0KS=;$ThWf+&qi$kt4bT4YFPTSB#v1Ftey zx9w7`X*+Y=OYX#hj<#x|wyBVAsrClTN6kEk4#9r}&DQxi+J2kzT?%^vx{=n@C@((n zmHC)u5hDC?{N%)D=ld#_CIH4?9=h`!bw8GJ|8h5uPYn+Jzv#p(56Y0g%n{K(Yj*0N zfL{)6^k8tZ7p}S&&i_LnpOd~r+di=HM-=#Ey}mC@U98dd11!F0QDmQn|QbJ3v1-gL%I1 z!q7+#nHPm_V)H$rNB!h}U+C9tULMNLBlr75bJ_erXak!kLKm}nRp?V}UK6^X&5wkh zVe_M*SJ=EZG%rBmKNhNC^HZTdHg5<`viX_NrEGpSbR(NLh8}10rqD}l-W&?$Q}|m# zRcyXkas$ita!E1E`r(MwA{I$7n12jE(vfT?&vZhy2_ks`O{t*8}vfh6E@9&P`M24CxL1exadil>af5nShxl=I2nBWt`sxrrt`4CHU2pg55I?RC zp;%mhcK8Uo1GA%0vPLNqs+zB zJ>}=eDZd_g(|@SX`?&>-L;N!gKYV|g8yJFRPHtcVMma@7U2i&sDx+5K$0F66uW7r}F$bl}F*JUlj}u^{Pxx z<@s?ckLoq`wnk^k6$VtLMl01-bDvwCiEl(HSJ(cIjsXXefsMF3y$@xXp zc$~_k5sNzXG{((HWHe6Y@z94+(V*uCmO4Ct2&{8>UJ+RDQ0*$Cao2yLBzh->q13DV zz(!{|TV>~wfS6R34~LKCQSctR6MI6R>V>~eTQ6KHUF zLKE2S@PsC?$KeT0pwZz8O`yr)2~D8c;R#Kk)!_+EV6Q_JB#Z~N7Ug#Ze-pw0HaU#9 z=DJn>AwBxRO*a?hcgp}s^np=)pp)Oj9s%+g?!m`L`MvDnum?Ul$?s!#l-$R$C#mxL z*`tU&j&g_r_9$ZndknHioID06uo0{B&t;zq^p^k(4fYSf@B9)fIQUFV9vbYLQ2B2y zr3Mw{8SeRbmtN(+jeU4vT-_1+&ZHU6kfoVlmSqniC6)*%tFCa)ZpV z$|#I&-f=cRuN3p4Epsjbp@Qr=r2J@>orK^SMbr(jS5lv_3!Ys}ZG-*16L!I_5^4(U znLbPxJU8+Su+0rTk6-R_{|rlre&G2w7_rZiwEzdMRWz-134UuP6S_Na7hDTfPUyb;W3Vk6QK9>DF9&+j6xm4JMH6JBE^yHx*{&z*(ErEUo50Cc zRPDp}&h6#)^zBa1Wa|WyG-R1crZbr(AuA9FAqh(uvJnD0lgyHtWHJ+y2_%4QA|Q$^ z0wN58C>WNo2ne#tCg2XJ$SaEIE6a-uD54;|@;%QvRkv?X_`l!xe?Rm4WxA^FsZ*!+ zs#B+)qKjobX@iq~WS_qvt}_hI`%@fSoMB?Wmi~6-ZSeTR!1V!f=7t^Rq#w*u2YwU0cf`i~4nfUJMgj>nHRz)+J%wZ7zz=C_ph%GAZ6hou(Eik8x?0G@JhadYOd z!30GV_^?QHoDVw=l~^arU!I?x3vN^KPSq`L4RcljZQZnf;I;8yzI&k?FxDm$>#{J` zk4&r!-GYf#Lt8~$eRW~W#5jDUm5lICmgqY1)Z`h;?TvPo;hd1$+F>fg8SZ4utsU13 z-80=0-T0L9awfAi2o`%&$35HK_fzt%&3=Q5_0z5tI!;Gxa5&j~s9W)Gbk-&uGZGoFY^L;1w9mgF|nJ+Xle=?N$mmp=i4Y-r6%(%u}g_gs07@+n|Yjrd1R9Y=xwOMCMg#A`PWP#J&~zX;TU2See_~@kp#&xe(vIOFw^R z4PHT8>{g9thq&~Wlj~NjSNdyJV5bI$SF}HIk8*SDkvM`y9GZlA;-VLH{?+b$#=yay1V{#l zyLGQ2CXVl>YW{}1^E7{XG-pj|ge`ftaEUdt)X0linaTr+j{AXh+~Yo>0!=Vw?+*SD z0!>G={a`;M&vY2o!`on_nU1$UKbWg|&P~_*c$cPj3^EPxr|8fh)5rus3O5GM*g{j6Njrv@7T_-BE2)yh@@=)7LF=2Fr>f$ zSGXd**D^mjL0LA0x!h=2zBa|?Qd;F}Gqq9r4tYdGdnxl-!{hK!tcMJbmqH#=QZLQ2 zC8bBj?n?)m(h{a7ug_)X8-~k6hT}(QKA+p)3MCAmYaGJxxp_m1|GCAc_?;rgrgjXc zc%=9NDa{I#iakwq2UnU@9j_u}%x@;83>DnppQ(*(BD$7W2aI%@VEM zL~9G9{l-MQd7{aZdF1dGpI<62-N08D9rspKcPDE1d<);CduAjRTm{D!0>`~U5_!*P z9XE%G963_U?FK7beb=^rHE4FfX2<*bfqv!kbraHNcyH-H8N3ID_in?xCFFgD;XPR5 z9lnx#t>rD8I(K%q@8H1t1z}~CqdP-Z?-^EK2+N{<3p&%qmPD#%ZAqbB_HQE^hzB%~ zuOscXDT@Z;0S)Al{T!z)C1@ZX&_I44cbw}PN0z-F&_G^CzILbj7Rgn7#{(M3pOEi6 zQ@HJbJEO42OR~=H5vC3lGw#`A3sJE{Y=(`*e|~kt<@hixx-*M?aX5*qh+q~2j>z5cB|o*E2Pshg=Wl2jM_IL=TApJ%oV=`=1~Q z&_mc)7y93$59lHE9hxekhs1y$63621u#}*O#DE@hC7S$Miozo3Au*tb{1=L7ILj&S zzlFb||;mBL` z5bv8~@81tG@`4`X-947Q#Lq|2L%e&WMFQ$B?|mz{j*&Mz-hCr)WDCuscZTR8-u+eV z8-BhW=po*>N3ad!E(+{x?oHMq-WYV_2a-(Q85Q#$N=<}lqhsEq!EX^XmSyHWHj0Jh zjAfB|kBg@Q7Yhw~i1%=c^)tqxhj@<|ub8cUM?GceA>I?ohnZYnN0~h`kRh)eJZ~3| zKlWfIb%&IEZmbO1cT8ZRAPR#G+s#@o!dh(DeR=Kl`YGpr2?Qwhj}}7@l@Cjo@4~1{bB8Q|$0#pl+O5 zHGp~=13mhzVMo%1M{y3wasqRbC!rDL@C;&((PTbLf}(@qnb46W zG^Ga!kZ?7SfG1LV#+OPdI!FTOApBa10YlJ15ADi$=#)nx5knsWgUz-)EhCLGOXVF2R-XC@i2nzt!NB|v##a2L@ z0OAK5MFGjd$$7H?#WI|1NCh+>IN5#*C~P=KK{lt_Fiij*ftRl2Y z0Rp5{DDXrI#rRSfk#!q|V+QG9l__p&6F>)HVdwl=tVW=N`~h6^vQmL9m8?_>DP{!d zApgLpTGXMUgCu|sLShvG5FjNH;E9M}e5sV8gCu|sqV-Zj2T1@OM61T2gCu|sqLriQ zAPJy@+yqrvE+yz737~^~5t@X2DntiK03C!u18d6|W zsUpV&z(JVG_@fLsNCMy>yP3jIS>yl)(G)NZ3NT0lz#tr?{geWOBmfLTf8bOb4haB* zbb&$g9Wd|{00#LTd?_sQ5&#Avt>Z5xZ{UK^7jvpenE)=x{S?IDf+T(*Bne!QZ^FGaRmu-=K^{R+ zOR6L&a6z6#(Ard4^1uc8K0@14&@TvtNdmYa&myE-)?o?Yg0Mww)uszv5H{VNXi^+V z;y$OQxPL$Bv77;2+&^Ca{#e4<60nBF-)gPq1RkX&*?0pJk^oG|aN%R&=2Do(0TaS`Ja4NMlS0LCrciLQ%wi*)W~8X11PQ=| z+yUv5Z^BcX08Gdop*X<%D2W44L>%KY;uxP12R;=CEetRrtYae%CJMlWFab!z?Ir&k zX|Oqm7*!M_0ho}3@MXUcCL{rvkPjFQg$|eyW`gqzU_uDB?(C;9Aql{Qdk=JxaIRlImrcCZZHeZzDH9H4AOjZ zbZ#LT8hBMaGd01tj5sb`hpt$B$dQgK?!%73DwTnYX+Z3S&Si(=sRao~w79s`#yFvF7_lbR zwR-uYRm+Z94h0s;mmIU|7$+r8u&7kWawjd0qmF@vrW1&pM#vd;!G1L>E@GaD12&$E zfnSm{9VTuwz!O z1VV!3?^tJyIF>AS#)<>6_YueP#m>Ispr!6O<67a27uR8jE;{BYWP5`679X?HDTwQE z*wXGNu4T(tIs1!i`5{Lyb|#8*<*F6SmM?K8xz1$YZyYvzW#^V<#7dkFed(BOj^8A! zcdY3BW?j+a^as`eGEc`Wu|LaWt?s+3e>29#oIfYG1<|oJqSv1*(+IYSoj3*uYkyvv z+GUUzj@ty2-rRXFL8OCN`%MOuD>a<{v6yu{>8i40rrR65{6v z9RIKs6VK)G(EH}~-DvlYzgU6_`7X$Q_{bipm>SUL{UxGpnv*{jYXqOj?F*$vJN~lZ zH29Y0yB+_C%Cq5Y$#?7mpCgC=4W6}QsUv`801Kfl4+|}1@@VmOJ0oAhx235|a!e)P z<)kjH%#UZc*}ARsWG8i*r0(Z|QJebWi1GN6%Wvp)QkReT3f%cT7A~nPBrgTY9Tq}R zqdTc9C2W##>FM7g$X-tBOA=a}@7wI8t`c`K-?!CCeOcTM`M&66o4Q&;XXXVq1QRZH zGO24MY|hw5tjb4*b%O*Qj!})(9QUc}#3YSjEbeo-iThvX zkapOvJ{h7KQfK8@=A(0|vn!urkzx_-q|V7!NTI?;;?pw1`gs|LQs?S;3$k`xfC1%a z;#VOS?59wO=VksrPFlwL4R}59v2s-pi1YLS1LR`EOAr83`L6=;KPzSC=&|$7bgic(E2;I06LAP9qphK@j&?Q$Q z=#VQBbl58q;?^q>bjpA zu^3k(=+G+>)+JXW=)p9ID-jYLUWuU3UWq8VaV4VU!IcPl!YdKRqgNv6DP4)MK1t~) z>(eU{^o3U<=n1bx&||Mel-znHg8s;rh-z~sq7qjk66nevyKMG*Sd0Az4p|@KUIa1U zX}waq7g33O5u`AEJ~bvg8yA3O5Buak==5vW9J34ym6|o|l5Wi!>8BMnYqUFiHMq_b z!yitwar|;8RCs_!aZElRA1BSFshOI7VK_$Zr#p772I8zRKy~ zSgTVN=&IC`DpmP$ots*kqk?A)Od7?zEX&DqjLiS3BUHOe4AIo`P^)3AUXi3M zR0*dRr&;(8)TXJG@mJyG)Sg-;6I71V>S}S0C^sf!&LyX*HQvt<32IBc=PNmH8`grc ze{>#3dh_5AjbCa*MB@jKtmN}j^{IAU#+z(+h_5ogRSKaq&2kFH@@OH|B{_p?`efv0 zWBfPxG6osw)}=i3mMTH2$NMopjXWI%mrwQO?xYaHpkEhLGWBnjT=`?EvPhjIo@@5*{F5W6^)krzuwSnEpD!6m0ow>K+(Rp%LmTs=uQ>Q9xGf$qTyfODtkOX6< zPWK*yJMOpOZ_G}>sS7;Lj&c75*@JR+9GOJE^KN5~OBPXiyG^ouaby|cHk*`Wow2ch zpx<$4MzZ40GFj0>LiYg8O1@`1R%|e!nl1k7Jk(48kLMQIog+cRA;lylncxyD^)-(R zh>3^x^c}Mm8yneOq{n7&njjPP3Yix;Wv>tvL|0s#88}U^AbO(A(koKTcIx#=^>f!{E5+`SfO5?)4EOD8!o%8Stj^CVyS8xE&s$(&_F+;GP=e)ZD za4beoW(YS&!^MS^IN5^wm_wH>hr=1^#7wSX(|0EdWa8>*88m0Tf+>Temn~nt z(zsI0+UoFgW$wIlMn~%H~Wod@Rz`#@Pvme+2uhGC$(piG1q>u2F z{8e~Lx&)q*4wOWkznrlXbO<~p9jq5$9H^EQ9h|W%>EMi=rbFr^pi8PGBQ6w9RvfI5 zVRW%Ra_Rs)B^?4!DMZZoaJoS4 zunXZSy?Q)T>xx9g=^!{7?dH6$kO7CBlgP_qZ3hqY$ zc+>Gdk}%o>0G`qVJmqbWs{!T&Av~oAcuFcb7N$aYN)Paq3~EUUJf#PCN~#Ik>^ZB# zQv&xyMu3i#g{SlYPs!oB6CpBSd$+k~(ZJf#PCN``JmsKQfvfTv_guOzMTlpf$I8MeiQ$?gPK3MH_Q zHW@fV^8imtCD+!Jg{SlYPs!@qnKJN{9^ffSa#l*eXST_@*GGw_ri;3=1~ zgMbXp7Vwm7;d{lMhGyI@@RT0lDZ3F?TQQALlz>qKJSA-%cE+b!cuEiOlsviuJZ0Qx z24qn{PBK8`oh(ma$VL3Vem}$dXG*B+RI$%`0H)-Ns<8FI_qb1EmpU4!TVTq#|0R6b zF9fFa08F{h6m&;6DF9RQK&JpTjR#;#p2p#n%>yvytvrWo#{qhqTlGA3pTLO$FeSB# z1sq`mn3B5j0^wr-Ov!zD0W-AY0hp4iW+%aE-<|7m3Qlf>pbhRkFLx>uPQkWxzL$Q4 zi?Q%v)H4aK4mXd0-RvH$A+^jX;#ZNeyU_D$z+nFh z_j|FC_c4Xu&Mq+ieoXq0liDWN7~CJI-v#&%h_a;oA^uBgj&Qt(;4T7fqaRo^us8i- z%;VRT_h@l3B!!CisHH1g*Ka3?0+eO@#QpI#_$-PV7*mX*Px3Y{E_w4I3K2@^Y_L`Sj7Ilr5U=}mf1!r+A`a$ssP#5<9wkOS4Qtr6Srj*A`ol_8Cs8x z#^;g~sgQ+feEq5P)lokM%Uxsa__^e4s;FSLTTjiD`}yR4mm_AyrTH0LRKnjx0~P@9 z)Jr!czz0JYaPFzNw6@sWNxXX67G9JL{s~rqeLSN`(*_g#g=FUIsA=!g>(3~n)wmZY zGnCD{^r|x&zG%drrcyg6;6o8gXc!uLJimZV_8CPW($TMxE;z$!{FR9{-Ncd@U$imK z(irel;RbZWPqFb+GavVT2-3v9Ev6Ulu4HEYomy~j8(!|<72_rcpx zF_m7w2t}KFYBFG7f%$fkujaX@CFQ7!=GAeZ`;0 zgQp}nExEr*u9>TLw=OB|omUZ>fWksPj$4_`Ty~qXXh8+=pF8-dWl@B?Bc0d?)ndW=<}}$>-nC1*Asy`;CYIF3P*Rs+6Ibn;g2qE4|n2fg+VXgmGBFphX&;e&MLAAVnIT4V> zTeoONPYM(Lz$W@~!WM2ln7*8t&Y=mdL6dwXOwwr*m8h28J&DYco0aA6u)glCGi7&A z!dAJI-M4Jntt}4p>;BBWFXUU~*4Dj05l~}^dk)RqI=kPt-&Yl7`GSCqmPJeR(JYGx zEJ1e>_EUI>%6-s=bg)@Gq@^R}(WJKxY}&UZGEePR;m;1sqfj)$-;$VYyGJi<<X6H`r^ zjRzR2&)5{m2n{n)rQ;RblO&*B{h~zX)8Ej%d_Ls+y5)OOsUpxszF-^7LaCOEZMAe4 zyQB^-2@B9^>H*rW-1bRietVPhzaiwm6eE;$k~0$%jNIB_&rH;ql9Ck84pV3z%Q`zJ zk^qq22U-WZaYt$cvIE=sb&1T>8#Sf-!zT4to6@>OtxZW-txGgEgUXItCnjXnVr@&x zpRg&nu%~>|wuMX1EN;RTl~yaqiH+x)Bp)}K(=nhN$k_2=+)VSlJA=Is z6Ih}Yg(6BHD;(%q{uLj+2}z{9h0}F8#80Y%`N)1+YCm!6biz86thuGEDZ`2|YnWO) zzzoxb9o5>L?DwIHWP)a`>oI>#*lU1r6O3sv{KqpbrWC#ww!imT3asfr$0zA1-F+)AHY=F2iv3+(xQpYsZ^zAqgUY}l zi>q|Mjc3Lf8D@tv%x*L_@!R+~(@Qx7|4x^Mya|SxerxA?Gub~8&;0yaty9pNQ9)j5OcOj`LkBQ?HcrQ}J+O)-+n>7O4BQB|8!Q3xYorH|v^(@Hf$4 z#dQvrZ)Y~1@)eclRFk8kUbK8JZbpH%s0eJddr^)Y6Yq>?(nkL8hh=bflPQBc<971X z#&>6Ynvq}R{ic<-yC^JG+Pkf^9h%8|tY1fmdqd$d`15d11-U7nId@P+KR*=Y1uMu+ zB|&7#dsBQySx>wvZhNAm6Qq_O9>H)291g~(*cuYXgYjlN9O^#WNR}R7>lWD{QKlh1t=u>Wj9B zFf>t#syt3dkzB2k$HKP72NPw!Iz3*tsQZ+yi?zz~49jv=vt;bdxEZ6D7MZcLY{nKg zI!4a3Y{q&wn8m_*+GvQUiq!y2L{XgE;<5-^U<6xgBDsTGtzg^Y``V6!`D&o7;~-F+2V- z3;&8uGizyQ=Jp*Ml))>pVN}82a=8}E`C+k)#&{}?^p%($K*;2k*bKv@ULV6l$N{z@ zc^vTDSS1-^KULg8|LcBdqfNe_hn(8dUyGTct;1Ztox zEW_=D?5a@UWc+q4(1cD@9)Gbs+5r2)TcyCSVG-S;IsEoz%Jwf|4qKQ*a=IlpUUQ%k zcWAupVxpMuHSw&_?%)MB-gU8kZM>%KJzH?q7G>(V-LcFemuO;j6`Bcm@Q=1QyUU8R zJ1ow|YcJI}TW!AC0M3t9himz!?XdKsu1``qG?w|`3mW6_FiT&aV=C>?*d*JQQE7+9 z8cn6in7=q?=BREhxx-_2T5b6J#maJ?5n=}z7Uc@+F|jIB15V>phAJFKg<_3Ta0)}; zgB}Oqv%5srVl1=H$of^o*d6@H%36%s8I}#K7;7-HHlAtX;7CONsk99-xs$>TJJuuE zS;FK7CH1bCx$W~R{Ow_RTsGH~$Ge^#Y3s4ze%GrvY3Q8zt~bjzVHWz|y>Jd!-v3Z# z8C##O=-yK;7@)wLc|XW~&ojHhUS}q9tjpy$JQ-%^8>vcj$g5VWH$1yvVb0(1inf-p z1bovb!J$J|ozHujMW53gz899_M%0va)91aguVXxY-m`suhHTZJ_Zm$OHOJ3;2dh7i zf%BAB=K5!zRUn-ygU!!9vxhnBOw{Ijvj@1_%gnq`g&+g|a|eH6g}B?ZOJ8Yd_m&D0 zrT#5XOsfFNtc7-8n8RjXt8(wReyByT+`}GFuGjDJGXM2iP0=bf+`)b4BiodEk2ldQ zGiOLm?D6dK48wmvbRXMxv_o_0xR-jF6E9FU7lndfM>bSKUFwDX1@pwEURi&++-Ae{ zmn*EG9Yro}ue9E_VmrKF@`jydrzxzL`P8v{nwNR;d`(xdXt@Y-HjJ9>Qn>;P@ zGP%#FEW^X9S$?3&)1p$>r7VlQCc{Fx0TUR99WM<(vniwl|gEWms7pe z^=CrUgE@7HH&O%G%y-Go6)Hq8^T@d>(TXrrU$7EQE9JUmRmnI#Jk z;7;>ivE%wWDn0XQ&EDama64>Vztk5_0qFaVzJVTO$oK394jqfOfvu|Xd7~n8&e?`n zg)(yoU$DI1sIX&u@hHdruL`kR=9Z4F?9GaBoW=0)hYCA9I8A~~qx^qVk*PjQ`ELyy z$LxbmK7UjZHh6OUQAMLRH|X6V^N%VHCMC4)MI`WJn*deE+-zZh=;&l#_$sCQR7K{x zGc}>@VWC`V6MCv593W6*PgRr+5Kr5TbUQQgoX*y5SpW0cL&t@2I?YL!pP`KTun_;b zgLMl{4sNfot4^rxv3h{@J(oQfBCzN=gj+#xI)`&KCYySAE1G z^&Yin$2`SRq!X{kn^oxL6`Aj!t}>k)%5*bjVliG`VfXGb6I@Y|(PC^Xa;&_vBBN`I zwM86(8wKi@^zsRpecJ~%o6W~nHgJ`5zz*nyy41Slyoy|bOOq}e`s|XdI zFam{lCT(JCa&(;VFyGF^R$$fS2k`(HZ3Racz=M!I9N#)~yDKuEIaN9TJmmaK%elK^iXGwDc=CRZnGxeX_7B3651A-QfUr5ua-)4MPpg1G*`^GrNRll zxni*?6G=)6-=sB3(<+{#S*7g*|G9&2*t8~=As=cLm@1OzgQW( zQk7#`_A0E_3GI&7+z6SYZ6L>vVlEC+Cbo!psYS3~Br1#wXRUJpb&uQIF+m9C1QzRV zE@`AVFD!|5(2z<={N0^q_d#UzcXzI7c&hdOhvEisLXyGdJ?n3Cn$~x0+JQ3xtL(rl ze^UoEw=ak3q%eI-Ixo1P4oXzIFSzwuuYSEb4tl}0>aBXr3op3KbgiG4as3x=I1{qX zQ|I-f;t^ozZrp6r#W9Nfvnq#Qx@OnRozQl?kceTIhgVO!nG3h8sMm#}UTj5u(ha9f zLv45TS|;CBlM6dZPxbM4kVD#iL8c)wt`o7u5V1tGK=|G9&6 zmY~cy*6cyH;ygFJkR>57rXOK|f60|894w=_-wP8m2!}o(>OHZnK5a z-T0CD9G+Rx3e^3kTiQ1|v#~ebYz!K&b~95QP(cJBH++G#q6I)e`@nJQ5-ipy1W>ANyUe`_;+?4i) z)ll4l)yWpu9>2p-0~ci6zOZ><=|iBAFy%IPI4_lU^lQq3?EsP8!PjicZEn#N09P~X zU9<3M)3wWnFw4#?E!U9s8qL)Eead=sShg+DNJ!bP3EP%tYE9U>SenO$tR+)xZKlxc z0b-2FA2o;ux)jgsnk23XlX%D`u@r;5X}$ot)uY*^u3aQI-eF=MVq)sK@{w+a*JaVU z&{=eZk<(L65Wqd(+M;>d9VXZXHKB|#v)yo1moa9x+hE2R8AIlTHPL)D*M4(LnM9W7 zSzmYKTPBGOCJ8;^USRvri7M%Vwneo-QdOk#QeuB!FQ#1Br+u+k1+`Baxr0+M^NOG& zUAv^^P&d+@Y1JC+^`oqq=HPL(9d4G+*;?T^Zz8u8K+M41@ovsG>p9ostA`|{$|kwh zY+PIgHtsU{frd@~=}?a%6w{?Xwiv=YIqp059kSzF!_bzwheI>A61&AtT#1B!*9cY{ z3U>5SMzD7ZMlk0fX*aLRxYc4JtP3ODZX>+9pNTM!$vN(;X3gR^o@64`n@Ezk*UiX; z7Jsm{MhGkTr7G6%ND~iQ5BcW~{?jJ*()6-od&wy3d}l88R<`dr?qec#dXtuaWjM^8 zj?M8rZYv(M`?vYBBznxQ02dtPxR2Xy=>pc&6L!K|Aj_jC&FX0F0?F-nO;xoxbJb9` z6Nj+4ng}A%60o|w{_;BOs=ap3rGj1?C49P*1akd-z)aRCiYbY8yhY3syf~d!4_^FMxv|i z;kPpvVkq*aX6NE6Ci26LT6$2Dnk*$SElV9ISuPZkr2MKb<6sJcAPYw zlNn)H+#j;oY+0ORo54K6k#f(m12+6Hh&#vjaCmV^5&>3EY7!wh5)^Bh*Sl28>0uJL z+9U?-`f46kaCY5m;ydo<%zY+qLm2mU8+WtS1TyaCDQ1jt=F&VxlWvtJcD7-G6BPO9 z4o<^3Cxz5%Rj_2yYAp{;^5)FuxXj^(L8;4KKn868$Ju#p9_IJs!t%kg{5UgcZx<();c8aLdJ$bG{=0hX4ZV~#c4kFc7>d6s&H$)#a>gkhRv&pa~hnX*1V%Iy7H z7Rp)t(e~V8fvK(Kp>E(X5s2-yvweW;>BDjspAaiMQ)W_LhuKCoPwzjwhnWWIJI;gq z;W~hmT}`v(CCgVA7S+`?&MeHSZ>(=9Oy4rFqp$P8c9_LB!NY~$fqnhZIj=8F-{{2Z zXJDM3At&RV{|+jYEchxYJ{+}5aH}4Z-DC)7CBj}0`!u!8QSEP>P{{mf+Nk`BX z|2?>hm1B^fxnn<#0W?Xs;3`h?Pz}5DSOow|aV=^m#8o^OiW}d5$9$qM<^O~}fGW~A z6jYI6B~Zopz^MePI4lKo^AJ?=HzR2mZ9o-Yg=a5NMbbw>73m)es(5B@D5xT-7W&JP zHG(SMmv+iP6|Y1>LqHV?09p>J7~uAG1XS^k_)t*A*O0H>WuS_8Bi~U_MMB1Y9H=70 zhk`0HYzV00Ema=_syG|9^nV6b{5fP&IK)N$P~KrI1*jqgmB11dJU|uC0;9Np9{yG` z?JM9&^A7?~fnT|Bl_Q|X09Cw8BHU*qJZmH9vmC26>Nmi^q(lZD z?6)%GKuTl>TG8+DiGl)BBFiZ^RtDia zCeUM$68{9jEm9(jupBAzBb3%qq(ll$q(s&RdZI;2WTPx0CB7!U5>g`DR}>`i>yY4o z0!eHl{Sc5u4uam3_!9w1EMPVq<6eN+oe~f@6ZlX&-5(#~$Ac>rf0AYg~5RgPh zlgWulh~eZ!4<{R)oUD%^iA=EslK5-TL_re2gs)@&i6RFs;wRxoWef;NqAavp9;!+}5?>4BUlEVQzalR2OCX7?gc3+1Q;mWo-p!N~WDbx-qA|uo zki>CFDeg19Di#4j5}BiNki=KA@2zJ>!dlB=Tz+ zNFoCwAc?Gh3zB#!5*Y%L_y+_Lud4ySGBkVuhYSq_a9XLGB!VQ8pbR8&eI+trKoVJO z1|*STDHP)?2T7D_ z4M7rF*g5|NwkCii-i5VBURE9iN#x2S1W9}to^p^x5~~P6LM({@PecUci-II-y_AC_ zYSlzQ618$lAc;G&te_AiaU}+gAs~qiDrimsl1SldH75W`WKIZ@$Wn{@6Ir9Iq#q&J z)M)Y*6hSV51B0;v=2qEr5+#woa+E~LT!@lLUj!vl@`fbXR;tL7D2Ys_3?*?plfX2n zsQ@WaQ-R7RL`vj997Rf`zZ@xXI+!G9p??Wd;_YOK^C==Fk`}k@h^0iRM0x?0NK!&2 zej1cfs6>{mRwM8bOVtREB>S3YAFz5U4~3 zeGF70gQHN1^zRLo$k306O5~SXS<4VAk-nm=WeAl>pM^?f`9z=+PlMM&C7uoU5U9k9 z5HtiT@rwxB8!GY32rY+7ybdAVc2P#OM7D~p+J=Fa$Tm#0M2;wN|49@lu#ONV?mq}R zOd9g{atUW^z}s~A8-+()h25dTBgWuTc*NJhL2DoIh$L`)&gO(iTnAqi9`QRMjld&P z4igm^h^2-D59`{@YQ|TBN94CkTrwp*qIPP9N4yu@Io#eTS)wEncti#!d(eOd9`Uyn zjLQt79+nb@Cz7!7rTo=w_r_PLr3oKP)50Ti1}}$4WC{f*%Pjr{PBTVSQ3Apv_9HC$ z6a)}>#C~kxRGf37;=mIT$M}pm#%IKVPsLGqL{@4UJR%c-G~6iizmX>Hw?T|5ia~h9 zf5B4@kN6;?DLf)GVc-!zgU~2E;$jS&1Ia=^~Mfcn{qaLG9E8M@)#3!fpm#3fBR zK7(H^Px=kN0$)Z>Ktv%hK&dt3f91|2w20P zAmmVP0kg9ltbzRqsGAY6hCy}^kSSQhZScL~PJ-gU1lI5n!fGofmB1RPd)XPE z6a{NwPdbZW4U{$RQ!$ujTI45V1|S=_9waaE1G0hNpSS**5(>x$_FO_X!-TkOBgoVjeb3kyb+dw@Sj-sY9g$k~nf&_Eiz4DHH~Q<)ZXBQ;aMntKkbUYfzT2x)ZD{lFV1#dLzkH+(L&klq9n` zAHf81+9@~zyuls8o?r#xqh7Rwx!TRPuA9r&DghA*oPRu~B{4$_0wwV?lls-}B$K*g zli=_aTM@!ZY;Z@Qgqf*U8`yGq%gHNSSGMljwRmN#C|FHpu^3o3`?h>8Fso=RIbC$bsE}dmzyL?Um1g0TXfR_DM#H!Tw!_joshtjuCoBH_^jV)3?_ywn^1 z?qF)HR?+e9R8vUPd3xZkv*PzkVvD0(VQKF2-2DJ)4IiIek36S&{KHyyNuwj@8fm>}}7f4%VUZdfWysm6$#k13z^zoW9 zl6G+p%htFcOnT~3xQ)8NZBR*kR>pyDl5|WM&j{I~M(ePNkCQgjY}$;5Mv|5$bMu3m zHdS`~=ML^MX^(U3O}5z%#@lw#J&lq~u#KdxSbRu1)F=aO2zA;JVE8eOfF(j6lx2uV=3RwhFO1jDC)Z{`y24ojvFEqUkuzVD^UT8@LH0 z(u9y)?u(gU-LDLv3>o&q8kF+9SYsK2#fx){Jk6!ZzpUgWhI*a(pZTurU_c7%!U`EfV8pQy)v6VwZ`58?*9H_`hPP7Yg+&!e4uJ z6Pq_Gk0vcY$gDR4o)+fvD<+peu*D{~A#m)^5`w9Frg)zg%&f4*{Zpc#Ro!DpKNizH z&00);GdkJ5q6mQ9X*0Xry(6^8wK>|edivTI8Iktz)m)v3!q8}&f8kr2`kGMSV_@0B z^!C)5YB5a3Sb?xT%;}As-*ga(ghv^lVi==4%Rf9sY8c-bmV`=+$6|W=HZNL+;gVe0 zKNq*!z$nY-?^RiE3|Y>=XiHfyEErj(I6h|wpaZxScRz2uYiB=Of#yPcgeI6_46|is z^2d6l5T{ZI0xjtXwP;yXgylwrb3+lXF(RBgJ}Sa#Ce1b#;dCpJGe;Oh1Yj31wI0Gc zX_jqZG(F1r!abVpone|zL9^XshXcv>rZ5qiW--HPZ5e}wcFr zuH+29(^+nkIXO(`btZ!`;Q0M@3~(9^vpViJkxKIbtnk;R)Yt9IN18n_pV^Grl(rH} zMp7DUad3Oc_nZ4^aV?o)t4QCVUF!1-ChumL-z>{%R*q_hz336Pd(C{**e^^n+_oS_ zGctIjcN;>m3~*-tehA5>hU6$Akx`=Po6Oo_h%Ama-|svV$4u9Oo2*E&28^Rg#hjn7 zDd{22}dA zD~5GeKMqv!A|}Jqe%XtdzI_ohgS}YJw=ZJefXOcJ8{>`L@D#`!GlpD!;ft80uhl?# z5tIG~pHsKmhVw8qC`5=PU z`ZQy2r8IaE^CuV++I-E^LU-gI=#;K!9J%urzKH2ZU&Oo%`M%R1@*<`%B^&elrF{`o zSPyv-Q^LX*F}Fa1N7b5Pxjxf?7cpmX?e51q`gZ_7LO(8pnZ`yu;_!d>BIX%jl=9ET z-%46{eG!f{{~&N1{CgX3+#wO}wGn=7BZ$p@dZk9)4F(=R4K?22>zFD39sI5Q5B#aZ zwkb`A{@H_Q|HI3c(?Ff_8}K)?IE*L)P;`CSvIQT88gG!es>t>Zp)j5iwLh#GG^#3?v5-eA)oYP`X!HpUzBMy42Vd>N&_m+{8y2n&rj*f6c}#@`^C z8gDRpHQx9mCE_!ex4zN+ z#{_ze@x~t@xHaBj5tbWoJdV;DYP`WpKM2*r+K3o$u%nfXH&{^oXrH-c`-&QG+yDvw zC*zIjq#t6u!9mb_9DgFl8{;vd7~>7jEo!{M-mk_R-E@iZ#=&&S3zwXboWw#@hZt`# zn#@nM&X=BV6w<3I6PjW-07_W%6CB?(RG!9t@{dhkR_&-hZlC^Q|uaLKQg7%RdTE*X&a z!xt`D|ADVBTrNZ+IiG4WT*SnSVtC>5zYvs1KI-u+L&N)U$j~svc!LCG#v85F#~R}e z7Mn5NV52a`8=MD?@dg`GL5(-qet5)o|Hr&=SqYv|*k`&flA+_)9%jJ&KmXt=>uN5MC*TT&@rZn!~WO&-=6rR3p>ByW5v zzx2AL)=9bHhE_|&a6>DmWVo>eM~^u_G~Aes0VD5ojm4cH;QuR93@T_&V7NiyYBeV? z++a=`P>(FJl)oQqlNIzdf^BW;%b|&5Fb^Dpl(!xEI|@ zTa$3wnuOEVB%HP;;gq*ZwWxj;ttogSMP+=ZrhabTA=R3C!MsDN`TK>bDIfSl@+1-j z8v8mjQ^09A0~(yff4JTY2uUoH0SE>ue}wF^AaH1qLZ9OkxRojbKHDjh_`C|lXFKUj z`GP~rXFKVwL;%}=6vGe}vS0neyGil%}zLW2~}fxiDgJ>B^cxF()KgA{|5 zv&eF*8l=cl$qx-u=!HQFNokO>8kA9k6t);Gb6A~}nkPJwGB>^y)-2JtJ0-hVlSJR{ zWLVnY>+Mbk2R^af&DBAS90k2co|E9n+nwU)-54i)yHkRgCAs1izTGLoILEhdcPg2E z5YxWhDWTE#yb|{9PFbIYZ+FW2EPT7u*S9-aK65bKnYTNShIgTlB=L6VO1Sa**;as; z?C3;(@OEb_f?A~PRZzU$*@>XFep&K(yK^%_+k9MCLOVcIyxn;cLb~ljlLjel6JHbDL4jGgOnE#PYqJ; zhf8Z81}P+Pl3bzCAf*Uj)F9%KY z;uxP12R;=?4N_RCMjSK@yw}MDAPqOa{BNX5`Ara`iek_pRRNP;QX&At>Yoh%a=?q6ZoReXmn8dH*U5mCX5PNnDW3`FlfZkO zj2;@K3{s$yL5eh>l0gc^P5Bfj`!iI?d^jYhut2GU`{OK7NVAs(3WvMlYw=~|ttc8= zpxgpaXn{gc$pS@&S$)?hd?6&|v*X1X8x| z)N){^mD|@2o(thQg0(>5oHx`0WdMAm7AW)&wLs}a*iZ`;hEZ8!o(s7XLN-9x5*{z` zxe%7`Lch!cg+VQT_*@7V4{dhiT6!*omD=G)p9^6~CqiVN<8vVl=n@hrX!N-d25t0* zJ{Q8!ZV8P(7sAjUM2|if!mv#U>)g_bcN_cKcR746grS=eT6!*oA-$4x>A4VwZ82ft zb0G}uqrz&VJ{Q71w$+b57sBe==|`RmA<0>O_*@9R7l^m?TnNK1@x$jr=)KA>e=dY! z*E8Ypxe$izhGwkvTnIz%MAD__LKt$tU-n!GgC3=tNuLX$_ZeSW*DeG)d@h7x&w>vw zAS)f73t`xcCR_Ho5Qe>C!jurtg)s096Bs@h!oat!4h_$RP=^+^K;dZV>}7#Ms=X{w z*pJFBP+HkRLJJfgXuUGT0_9AEm06%rfi%Pdg+1x4IJzZeP5D%CW|7E7ATy!tpy4*5n7;dzH_GFBw!^C0d~mR)va)SbF5Mdjhu7r>T!M! zp;~^Vx@`yi_|F|=XbsMjD%}0Qh=PN8Kn-q|R=CAI_>2RHTJCt@w--vM?f@c;TghlR zdz^}+xR?bj=$(pV$+$Kg-uF-W+!{=?f;#SBDqGj_I7TFl2!~fY9M(Y14^_IUp>%CH z&8mZRf0Yo{0Zz z2qI@SA_>FFrP(FoT>1kQ=SnFm7S_8)oL^5Y6X(}WMx44{@IFXOE;s$VCO#m&A4Z&O>#R7a^=oID{vs9d6;lD-PQCKC312LA>=~YYA?5)(xyjMP6*7uj){B7ay&SJ}>EAV$y3Xq6c0oBR6Yb9v_n#&%I2Z5ofdGIqyny z6n`3OgeRx!kL2BnKdrU!uTaD{jfki1YqHJ8b-HO>ZS07j3i}>9;-};|fxVK|bB3v& zwWdk51LDpY7P@_G7CaYU2|FnpJml=u8F)(Nxiplg6~-BL5TS3fwr{+X*wQ) zFeehZ^<>;`cigq%h}48m)eGPPQKGpAWln!mlP!(R-+)a-oklxok`81}ond{D1+A(x zq8wx~t5^yL+ftbRoZ)(n$qYxuMP>wQo1QgU4F{-hMJ_m8)EsOZFle-WOApfP4$)lZ znB}4w7l9EhX?C6jrK<4QpO$1Qhz$(0N;@vL2YY_pAIeY%)bahtnT*ze{Z`lzPb@ymZ+?+C3C;=`AC=?eqmTL-pv^mKJG^4f`S zGV;eBj>j@6WG@yMCNX6~cVerWfskx7}kSz{bO$K3iu~UTtwX14{Sy6X}9`Dgf0!3PH)divNArmn_-OQ0Ya!{y@Lx?bj{+eUYy})UO5e)$xAh zR&B&FRjnJe6J@nALi=N-ZLpsl?y#p5cbU2NH4+QrT8q<<3rX0%yf!K8l#*rM~CLd+3#rx^W7pY70#CChr@u(R-q|8wlEaem*ss}7@>Y+Z(E z*lFN&Z^>UJEy-CMn_kK4t_D^wAmw{oxAwDN#_F{bRS$Ic@7Rt;y&dLQTbmegYF_FY>x^!GZkM){Dh)>HKMUEzl&`B124I~30^9)c5PeV-rCW#u?I6+ zY)&QXpryJjaIOR%TfMcleS0e`SK9#{3EFuQyaK@}5gfm^Zr{4T9p)VKC46OdUpe^# z30{TZa`FQud^Oo%d_}Qu?{i`YN#Gh1mjVx#z~j&uSba&KjVS?| zcg6_{&6VP-vg`@?sKEfXLjQv`U3|6uKtt6YQPXJ>Yic=#AV%o}W)bb$N^#s+jt!(> zk+enz-1rZ298gDYALwwZou&K1-k`O$edo@`MyE379x|GLeh+0-72<)**4zjJr>AYAk&$T>B)a#nKDm*cS&Hj^E|Au3I_K4EILorAdzSIwFsw z!+c*Ae(!Vsg5V_7Bje~W-y7jIoeq=!obY?EGXo9a8~jcOzPI;pcakRv!AyEo!tas7NGKG?l_*q3 zA{kg2fduO$`wRs<$|D06kmVs1n@SYQV+JWqJ_pu=$JvGg9_4XtgojXkszjkYwwLp0 za*~$|$t)av_BG)&n7O#tva#~;o0GgGLfNJ4p0@0aT$1^RgswR(o!2cpXJ7e#fB0RQ zB%v8(YQoKrVbBRDXEGu!4Y`^_zp#YP=(;_9@npE*=Aq)Nfa`;{2UlYb3kE086XwWof ziMO+*N7y`V*^J|0=UCcel(q}BY_;!LmWH-h-pNTWGPL6DRJP+YCWGT-5k20J9vmg@ zQm)HLO7@ntf1{IJqlC@9{aAIgpf*{C&Ul15$rU96&F|+d8zE?Hz*TpfSpUYx2IX>R z85a_DMv0Wu&r6)P^mlYQ$941R++-XXzx^Z}7A1db(xp%3yV|mI49QO-Br4d$ zmKAz+Cmx_k-fa2Nm%&fELO9rgyZ)n>=43c63Sergk$z5 z>=MEgNvKI53l&~+o)XUK*^Z;Fo&jX1cdFx@Q%YB;4j4k!Aym6di3(NI5UMVr`f-@z z_#TXSX!)y^ZkBj8!FR$0Em2F9NYl&XU_>)%iIzr*G`Rywq^-DTdmpF6tsxP-n%o8w z=}2jaHb;pxx$~pR38(fbktTOrnB0UuR^@q0g7WO^--ca}ruTf9o>JiypKGCzN)vo9 zOi-y{Jy1raDUOFK-qhes*5I{DHJj`D4X8mW^hG3+3{DWDFP9T(dfg<_Mk7R5loM%k z7nPE`hRNNnM04@tDNYx0Vqu!h12#pItPtNZl(<7ve%+>Qk{9AzhZ3X9urZDpZZd3g zeGlV&yTW8`U8dCHs2pN2>zF-CuE3?tJ7 z+y;wQlEfJPu`!HP$1+BwlonH}S*23Kqk+II--Zpi*3{XgkCc+oH+~Ggk?5`=5()kE zkD)j6{I*=4@!Tw6G52^(>TQ;Ib#6-FoKE|aC3+-Eq;pdpiFCAEuZzo{S)$VFvL(Vv ziJpxTDJQ}YSWdcne9aP-R+v{uI4RNZqD0E+J0(u-8@P^mPibb-r+NEbiI0-}EkdGP z;y6+^E&D9iS!G-YLp&j}i$fjii`CRfvPgXiZDI&5%ARHP3Cq&tvvV6Jqwz}H43Ba= z!*X=S3&GeDfwH;IvJrxIEP<6`Cdi?#p)ik^@c>CNLZV!VCU51~xfR=}LoEq>%Eia| zvS|TWYJ=pU2#Ip3BZ<~ONVYUO$yG`-OT5abrHl`WTB1bCX-A1uS4YnlC)s5Zqt6uf zS1cnVl@e}<5So&H+A=e;b!}PiBu`bkW_UUc!@rd=v|LGia*4RhFx?Nw%fhep2RjRD zv6El0BEV-@A3^F;!!U#wMhFet?PYAqk^Ar)LPBiBwHOEY;z+`;Ly1UoG| zXF`nq>(@$hK<~!&TTnsLj6WMPQkwrLqtSM=r^M$T@_EbB^x_64y8D~h$2?c!BQ$>~ zqv;ZwcT0RufivkQq`%MZ?S(=ZZ;%PmSfrpin;=C0t&A*@aypnq+9yy%jo70OS6;Kk zt6A#^IdSJlqG3@Y&D&?oIH3bhQJR^EV*2Q9Wqd%ge}qK2{G^Nvs%%b)WP?ic*D@|3 znHeEbE+cX5Y;(nub&^LY%`8*U)I`lA5gR?Wt4eful&DMeRy- z^`;GUi6>qOIk}8e^t*T{8W=Lg!LnpvjjlF!c~e3a-{Q6lB^e#mJ8`&II1hTlt#1kwUDP$zQ9@^ zWhe(Cqvz9>r87Zjs>^6J$A7TQobfnV?88c-R;gx*SDQ|*U@{yMO^OmJr&%PDQLm6X zGkrapXCZY~`X%{2FFmf2{?Dgp%kM?$W90V>>5cMxar#X8y)^xt{9c~^ll)$pPBt;# zm(!Ev_v-Ya@_S9XTYj%ie_npSmcCPdZ%jWTzc;0SD!<=I|5bi>r$;rD&&}!i@_TD~ zwfx?eK23h#9(6U;{DsuJqi#n17E*s7b+v@QH|l=*eSg%xGa3HRQO}A0gHeB%-w#L4 zNBDjnJtsSk|y*Vh#@=N99c}HC}_33w<`x;RXDpm83cYXznaac8iUP%6D&wcbFaqe z;{*qaC+5VJG&m?e0LrS?UK@2`HLJixJ)}~4pGG}YJcw#&gGKS%L7Md6#@|Uve>D`w z!)RuaoM=v%nZfP5wzuM%y%?DUw@vv6Xf=?4V@|MV5`~*+&)a}u-|hrsTsdlshMw#M z+f@d8f9a{PYFL1HM0G% zb>kKovN%DLTg?P*@F_NYwmXuk*zo@CTVegt1=SHs+#M5}B$7r1=-+;FC)gdL-)yu~ zdio^z@V$b!(3IW@j@RGZqxr7#;W-#C{z<)$W93!hR@5zT3e-g zHa5+182U8M1HD|F$EpK1jAw-Wmc%(3e{0O|67##!{GN~BDRK&zex#bs`mo7JkPbwv z38urx-){(cO~8Y>DcmqS>4$}UdxX3;I8n%J1D?(mvb6!v;HK~-%t?Po$Zv>{PYpgN z8(i9f(Inhw16jXh3vF|hig-K4wk-OqQs|^GEf)1 zCDe7n(?VSryiRJ7|30B^j!+kaaqtzg#egSh{N+K}6cPX1LcKmhJv}&5sHX=!Eh}WF z2Rsy`B;8K>K_R~+LS7&267u?hM`ML-eZT`SiURTng#0@Z@)^NyA)gWO6s(Y)5%8#s zvVi;{A^&rPydn67kT(Q8?kZ#(0-kA2;XzaSF`?eKrc^AAK?1%)wlUzb7JqqsHAN4m z(ti{BV=cX|a|+p}V5UTB3V4=9KM$*>=uuMo9f@>a7)i#wLbf^Rkx0z}PpjzXQPdP{ z1Dy2Z66GEn1z%?dUlHn=0Z*am=Q$IpaW<5GLg;@Vp`R7}Q0Qj`JZ>svX9YY_nj(ik z>34-ZUu&{Gj)OaB4hTM!I0pngSfZb2M^kvdlYUa792rJ2-C%amfS^KlcEH0U{_=Ea zik$VNzbkQ0wQ=xyPS7soa{`_Y(a+PLDRQWjeoDx1j*!m{E)(*(0Z)Jm*|`DFd8Wwe zO!|joD8q{p@_E5yLOw6xVNW4DFW`~R6buL$mC{cOdw*)FuIC4D3;q0n2RnuA{D5aS zQ{V99MKTM!fwRLCv}c!a}W9@7-E2L}QojbEOx(9h!&&#lauyDXrNmcP`z@|XJ5LiUJ&T2lT}`^jHwHEUEgnSQK7D({MErOH?y zoDN?hyF8#elfP6})~E(D{gg&{DiYzCV2?yNCZNKykUb`#PO^qWD#n2yXoP=6BD4fA zON5qyddWhzC7|lDMwEr=EuKhJQ&*Dc*kBlZh3v5bwU7Lzim{g3z;sPa$WO53wt1`w z4wg780_qwI*%bkmi8WOEr9Y!dTxjFq^U7emkgp7=N2H&cLXx*T=?j(qfe8Jo;0B>z z6;NSV$gT>g6|50WUiwAN@|zL*)xq;ZzdE35u#jCHQ2$4IXzbE2YlMA@r97_*D&Q+* z*96o8@|TLf8d1unS8JwQEWOS2aY3_0Ixe8XuaG@1pi-}f3cBm)&*3} z6|(CBYTjy8HJ09{B|UYzDF`dy2|*e`h3p9d)o=WzZmmWYVCg?rjN(wf&c*`4iNPTf z;lzNNHTtPHtEDn5eX%C;*$DY3f^9aIezEucn=5wPfpEB(?4{raE*zCw0=K&2Lcxx*&?1}9yq^gAQ;8-g~W-w;rJ zRmg4#sH3V;ty21SZzPxWH%B702bV~M_JEqILbg4iGOCsurgSt;45S|2h`E2{5CV;ILQkG2G#l{i}hDqITLEdkXjwbXi~uhcj{vvKgbFL+qU z`vU4x=%=crMin6G5t@&9V=3eP!5<|;e?WanA=@A13Wz`yML>uK7rL^?pl)N_n_M2@ zOFss2&y{rnbsgj8+3+4GxJ2ox`zVF?I>BYIz(zBrF2sbx+=TB#I>D80)$Iu8|8aMQ ze;z|x?TN&j1LOiTI?vxtuvISc+&QMoaO~za&y%7jFYk$QUcSr!Jyj-?olqq?dtuO zo1;Ex95;ndJ?vx$U>p-X?iSd5w*UI?~bxT4)(0P202yP1BI317#?KJQ+kNvl^d>sP&;z5TPjZpy)%vfx&@6C>>`23-6>Cl098$;P$I}JD)^x@l&T%7p$afokP!4QoMSkLXsu)U;y`O1%a;aP z>sY=l&|1gx;{vU9EMF05tz-GhKx-Y#j}O>+^5v@n_K$pdQ=qku)!Okc=jtn^t<{oSGiJEd@oCmtEYDm|s{2wi>`3V8_+$5Lkh^3+U>hURtMFk0%y z#>;))FPjODSe*My@sp}tsN7$bzpLq${}8By0ipd)QYuF1I*@?3$oAGAgk^+d$L5{N zJ9uZgr%FItzi8l-njbe!8n!r`si+ORrS!nT`l9tv_rHC$FA1OP%#mMxgmad*%_++))qrImG7Hsa)xX-3ju~q=pb!x{K)VduCF?U(qBWlX~?`b0J?50I3=dO(V z6|+FwcUQ$z?`hf!k8)54m#g9f*-_`V^KmSD>Rb?86|ZBLR%z7fcvEP47xU{M1`UK} zScWeKptt1Qb@5yi3ZT5#$F;mwW-jG)iZJg(`g;-lY%9o~Dp`R_7`1GrYn;#kHSp~RPcq)v`W~*-R*I21B%rh{3AT*4ql;RZ{nF993Gs? z{d1x}-=SC6iJ<3W;$X;I`lPWGw@=c>I*(*WyqUEDXw8sDHl=FSe;LML?`(7^h_O#{ z9LGCiKBxuar_NEO9g~&oCCj=83+BNP^G<{5CC6CIgyi5vfp8BjtAn4Da=$7Na8|BEyMHaA`>}gqZR4~W;h~==JS^h8=iZjk7a87x zf1JPQ2@Z+d5_&7?9eD5jx*c6$;TwrE_6YaDqQ!qUB$f#U_3b%m9e9x|_wGbr_Fx_9 zdhv{bQqp___B_G1DEGdEzJc)${P+24agPDQJN@sU2I!GQ9}WQT!0Q0Iy##1Dq((|l zB=pUVci?3Jl@F5QzG^5fCy<`VewN5_R`(7dzINkx4A{RJFai0c1v$7M`3t4p*yr6( zCHk;R!>fh*GBhLqIlZm*(sZ9nj5STyz}^moS)4@S{=P&H!%Gt**!K7+$`UQ=OA}Kh zUERnoE5m7_>?DnunE*dou_3yMjvaRt%L-LT}Mf%`bmX$@)1<#T$h{)>F1G{Yx+#F#Q z-q*tBg*jnU$CA|zw6{Un^b^A@o0vUP3B8JX2mZR7LoIEG+RM9z?Tj62&+o3|C!pOx zMC~2;#crucS)n5F3Mur}xYR@{QfUX%)4Qc6m3A;axm&7I6;@^O6NbbiMixUcTsUNF zWGG<(H@UrfpP~W`mI!rB#5`8(WyaO1aiwE?Ts&Mnje~TI{*6|kWpvGEdv2MoDf5u?_ zRO48T^%mo1jd6;_xM@GY7SPIaPkT?BUFH7~FZ)Ni6n=>zus@npjs{9(9?6yYw@y_DdcZqA>9j52s-d< z@ezDv3Fs!T#iz*-H?z&_@fu5Cm-l+S*3LHY)K%{5@u_B_k+%LrTyKBf0~l;wZiui(h*On&8QJj!VEV%B22<&y@6C2-Yx|o{W#=BUoFahy0WAi4TK+ zOoa`48T)a3%s~A<*U%+%%#Y*KXs3hfFVV}+kK^+totJ^~lXyl}osK%Qg?Y-d2xDQN zt7OurfXOJVkd{_~)pNda0%r?M#3a@9I2Cv(>4+}|wRf+`VD0jCM@nlL^y)`W2 zb1Xu)%6TnxrKTvrngXtykqm^yz;coUsi{~_0yPH9WL0@ctu<| z`pA>I)M;x3_m{DNoOuVH-iff!S(c`k+L@yc_E$+ai2MZ1EEYC~O)6K|ueA^`~kM zONVOQ?F*sb8$xxEPbRMQUwR3|u*R*A%&h$Uh@4ILfs)>P4^<1Wb;mA>Zd~rev9cRI zp?AHZ=k&e}*ai{J!?7WD@++WBHuE1#eneV^jnDz9J!+F1>UMUuqK`Zl)8{MqKr=QY zn_3WOLi)(TSRYdP$dST73sLi*(|g7e=_3bYcFWF9n6&u8*lbg@VeepUxv-a`l)i2o zzD?@L!#4tOx|hVtb}A|7im;sJOQoDkV&R}ht6mbDE>p4JptlN_#LO-(xAqno^+M;B<#Z*R~d1fY|3BOEQ1_7yt;sovS4I`HkUA_m8&5??+^gKY z$T(-%d&tm6*Ih0$&c|xaIw3O7$EH{rb3)IDeM)BPVX-m7e{}<>4~xx`Cdjk#hufJE zTWnJv<`(^rtNX~9owkoV-@JZ~l~4=8G1+a|1(He_e*JwBMy)FZ@KH)IEG(+RI46rL zX7(69SyHi?rdKrH{ejR}YdTgPR46IS#D+S|0O?pxfZND_#=hHp+`oM&sM6RA(bi_2 zdC#jN##x5FJ;EKPg0qgZ?7ioOdoU1v&zm6qPILF3H^*>S2gfD%eJ^XvN9qI5tSp=5 zEVOm!F7%&od3u2w_pWfX#Ipjqc!jj!x4iIx!4I4$_jb=LKnHPL$5eB>XAYoTkf^3Q zB+4kxgLr+1O>J1DRaJM|^!hp;D8FsFTE_LJ8GZOJuUxkN4RtM@o7!L~;(kYfyaV^` zrzG#T5KVP9jE8%VrL(e*Ii+s>rr_)YJMveQ;K61H`vN z&~6+^MI;yhw}|9mIB|?v36YTc<=zNBbC(L@mwVwvsoyn97tS?+))n3~NmVznwpVy& zKa;P+1oUZ7YqTJ!#(PX*Cz=*#HLvpYvg;n$%zYqLdYly~qOD%pzr8Ko{WIk5ZOh$O zFCXDl+{Wo3PSs zd55l3xw||w_c!p+5AwUciVp#yXX=GpwbE3%CyT64drL@+3u|-H@zVWH_J-Q?EqCeb zZ09>Hoo}6&eHcX9h@7U^Tdtbe^-i&=Ws9^1_*7fL^>te@JWum-EQKe*q)#oY;i_5B z6ibA&9e)+h{$wiW^r}_D*%B|@xslpZOAX6CN5L{%cw6J$hQ`%aKN!T{Q1i%R)VcX;;-6lyZ2q^EM(6FiX(k3a}CJl>U{IhWI z6;tQ&D8Fv!ROMFKk&1m`s0O^;6^r?ol?blB4pc72xUUHAImDBJug=3#{;!ExlQ#r2N zFS}-0>Zt3~mnMM!t%-FEvLjE`h##W&Gba4cQ&SP z-L?<7<04!<;7&8+g>CzQyD-AVgYGyppifSIlXt{IH(0PyQp8xcEf&w{y01A7b`b! z>AwTF=4BPy25ruD0h-n{O#WfPd5u9 zDn1aJXI=40?j+kIz|JIhz7X>{^d`AWq<`e(5H&e6@}Qb46f;taS!{~=W?0PCwwRIb zgh(+X-FjOL1T)H=Bq_@nhpqggQO976xNZnIB`?L$UDCkM$QWv z`Lbms<&KZkKjqGi)IaS`w2ZKyq^)qO8_P`1>?|#O1;sslZ^*_6jvi`j4I5ty*{H)| zRk!vBPLz!goG2R~Iz?=J=$JOD=4|*6$4)zqhYWeFYxfjIf?{Mn$-K*0DNea`mjU zDB5PvIin<5-S{U%(4LX%u;==9lnY({Mnq}chVK9~-i~q~6kdM#qVV!=$jc+-1q2>+ z%ypJtARlz5N@-ZO^h>*Z)Zu1Jxev)*KNW?`&3qum+$P0b_<|I(%*-=R?|)$KU@^Bj z+QfIbF^azL>?iQAdjZxTOZ;&ziDHMLL+Qkz0tE4{7zH&V&+u#$geCAllQ z)(MwlwB)spRak+F7(+Do>_FIBhS77c5Rt_UHG3K4^e#NbP`e_eW@m{{hhhT7wpM&O z*3eb%MMCb}Ukh`Wh7EnCC3le%Zcxwy7dew;O7d|Mgr!OwF1N9#Uo2!!GGyS2q5nC( zkCV(w0u(mmg4a$PK6im2PCNqfBZIiWv4;m+pvJ2gyyOvh$DS$$)*n$IeL>t=g7@;T zq`n14I}P5fBk;7&bB5sEdj#HB4c?3+@nDhXP7%Coj=+1-;7vIKPiq?{2;R0M@cNx5 z^_y@69*(@q9V2*)j=)=G@WzzlLANA0Kl`P~q;U6etHH@TL(EC4ftvTcGs^UVhV4Dt z;t5%1F3PC|h|5b&dtayQ>F0%_8+Q5E48^{VJ*jV!Y$$Ku0yK*sf(mS(NP<%DR-Us#jgD!RF zbHe1!+AV`xwMXo^+!r;~xS?7Y zx5GXmRA00bS&c>H#fhT2_fOE*cQ4in*SXcZ(8ez=qNxzhIJW$k`jH5$k@U%lu8TIq zaUa#C{_Pp5OJ&#)cbHNi4eJ6u%43#mgd%hwH;L1mz|Z%MR_M^4Ce-c+_Oh_?jAw;# zml0AE=IkFQIY*R$Zy8ZO(KH00;Z zyQap2KbNBP2OELiq`yOt|562SUSa&BMShD8sEmGVWV)-X3wBrTWt#i@ ze<~z@Bg|treYxTOGCS*%`^!T?K^9k-L>tTcbfI}sk1Gq}R_%$S1%gl+-lw7)(>O<uH5!^}1=tEVejxU-w~=tLmYYOmniIairmh)r z_j~x!J!ea}PeP^+f87ir?pDrLr*E$o)CL5O&v9m*ax6jucrpDvZ7QF0N$aVdw?V?y z+Sh8}*M$FLCk#8Oedi{`tnW~T&qUaqlVIJh$8+J8&A}@fWzkoX1A;9bU2QEz1SJQr z@FBLYwxU;(gIA>lZ4O>_A?8L;5tiiOl>}ceuwirXs+4(~gI6sbT*;$Yl7m-!_ZpjrKeTa;Zq+Ht^B=e%+EGjc^rYtWBkK& z8=dw)E?T*}Kj3~Sk&F!=fU$RB@E#D7lLwQ$&uHcR*lY=fFj_f~=NBQ<`X-9ZZ%&mU z>sww#D+lg5MYv~`;Qp4lDG$-g>6VxB5UqR*9?~sv4T)`$cp`Y-s@4rcupc02_+Z{g zqm^$*_K*3V59WO|S~+X@XTH}}75dR=yk8QQzge-86Zl@&R^CUWmEVK+ z$MZcOO!?7h<@`M5cE0BW-ZRXAR}`(Bj9om#bzkW375LB)MbXMhV-_I{AAp#uypm|;WMz{jW9uZ4 zCDF=By(aK5W$Cii+bj6FJm6O1mAprp>idIevxIUyoHbLVd zDaAx9Cy~P;5d%^jt(;VTU7!N)K&3cZIjMY9pdui}(aK3>Slmh^%@7dYD^g!POHWzA z_gWzGJ{ql@_$?uRAVDF#BchcP`$|hDGYP|AS=b|@m6PPXmZX7|xDj4yv~rTAb*$zt zb1PCRFrcN;%1O06VJd1t5m>@2idIg7lL@7(8^CW@c}3C6N#+Dg28HQh6JANQaw6|8 zqJoGNUP-iaQu=&>k`6=Rl}0NkrN=F$%nU6zfh>(yPI7;- zlUi!9;%MchR!=ZKn9-smSl|;sGLcBMauV2J$zez`pgF!NQ~;3?bFn3bQO#)OUQx7i z68TC<#6WySXb@az{GdQXN4xNfqLq`z9||-Cq9|Iqu8AMkMnYhCCDF=BW-@{JfG(=z zWOyaf%1P;@2qkKAypm|;#6RB>veYzSNwjhj`d0v2gz6-e6sn<)j8;yl z>j=fFt3aZadnM7z33M-kq#+DYNwjhTy+|Nko~2Y0t(-t!I#L{CjC&=~$_Z3UAX}UU zDv4H3pyLT-i_<_Q(aH(b9TrzMnDRU_S~;O^3d<9yBcqiQ>VdF8fjTl;IiX%Hlz0Y9 z{DK6KE<`IQP%2|9Sf+uFh*nOZi3F1N(?CZ=D<{wz0_o-}`wWZwwiH(st(IMOAX;x+KmqLmZ)SC#|A##9cOkB?SPl(N87-!P+5K0aDGQ5uLsVHlP) z%Ew15C(2HuP&9_ICNg$Jv~ogzp@bg|c|^2wLNatxlno7eM6_~3zEx8CO>CWyiB?Yd zVP&AqK5t~A;s1G*=;KfV6aECkM+BnbKPFl^;V&e7L>f;H1V0}et(+L&F5yUHd~CFG zV*FPLPa5N6qm>h*f3}#b3)w~=6Rn)^O9>y5l7|17Xyt@wB&Vp9H2lXzD<}Ndiunn6 za=>P;Bw9Hcc+zsBEKo_ba?1KGOAbJ?xh#oRPD=gCO`SrZl4#|mG>1TZ0Fdk+OQMyN z(uN2n0V;`BP6C${DCy`zUU9T?(m7b5BOt}m%1PxvLn>uSw%Jjlm6OunEhW>dHSAHM zm6PO%oT;LzC*u-%MbXMhaS@^TpaKn06s??OS}hq3fUnyZM=K}lrA0IVQXH+ERBnq< zVJLF1I9fTWFgBLuM1vGZD<_q=il`v0kyjF}oOJqCMClNyBw9Hs%^?sUuoYsoa<3#> zISKJQ>XE@=0865klg5>nn5BqdNM1>_auWP*5kXT|Mo#idqLq{AYehs0l=02Yl4#{5 zovSS2m0^{ z(aK5nwrP0dC-Rh8#z?4QSC;H9; zoxhMyX|(ct0CQu3j)p0XR!*4j73f?^I!8n+C(z3ULK^6ZXypWo_pvq8XEvO2OQMyt zYGVn+2RYaQs3clB>$bXx62@q8v~r?%7tsMoakO$$xxR?XM&%VpD<_r1MN|M%9Ic#G zejTBr;~9A+(aN?qO7$;|f()V7e?(V~@;-0PN{v|gD8K3cSL67Ad1RMpg1k@C@_m6P@& zg7d-9*5F5vR!-_WL+Zp)Wur;`Xwk~~`sNba8u)0@%1QahA!Vji*}ZJ1qeLqw;g5<4 zixNc;juNe$8U^hXL%*j%8CBD2pt`* z+$)JzPD&4kl**_V_Ku8JPEv1JQlfkn&?BRjlVD%y*LBkyPzF-N7kIV4p%AT{MCTKd z527zB(~w6*D<{qNkS3>5RrWadxuwy{N$E;U(!i8PD<`o#EHNk`b+mG?Bw9HMJsT3r z8laMB<)kD%T$P8hvQ->$xp_fQxL`m??pPduGRRfAk}nnKNr$%{OJ8uDi;kbQ7>E=6|Yoc`fh|*n>Em69CMCmSlp`&#Bh|UH&y)QjTC=* z^Tc1?Fb&XmN67~&*;yW9fqcO0V}h?E#a~`D@t4<019Xh-G1)tcLr$o@72&RM4%@GKhV$<0^ae|q$dQt${{DPVEUd04-jn8GCnbQM}tocc%f61 zo*3}jhO7YmyBd5>1bk935~-T>q=0uf{N)7=c>(x+8vM)%_~c-X2A>@8lBOm-Ip9sq z0A8>pAJ)(}MWCky7is7z0WV`}(o+Inx(qNMfBkO_|6>a;t8-0yYH&y+O$~Sh!!)m0 z2AI#a{!JsfLrsNkmz@^;mqwZv@Q$S>JuTn`$^hPUBp=ZzlPwC~P7i93;xF$`_{-Z7 zLgPjw`KX595P_c&EYt8a0$!5Tq-O-Y2N|HRERyeN@arsihVv$1jt%x|oMQuChcL|> zj{&@uNIs@f7`IZlnr*t7!8bI@%z#%OHR+iF?=%MJ>xbmy8s}Y$gV%MzOB%c`;GG83 zyt5dfuOgD)*Wjb_g^n>R$Rbsfo)z%kg1@|-7@+SIl1~ocP+S`UpB>a|@Yw;cC~DHP z171W7kh_EA4>b8tM&RcJ9U6X4kb#1}COs$Mjl%%>mg&11{ICVL6`mXPYMi+NFCJ>r za|2#3)THMJygT48Zw2^ErGL)E*se)81k~;Gm)d*&Qa@jlUJy_N&tEFp`Aa=|O?qKK zRXKmD4d*Wv-ZkmQfI4mdQftj$>ZNPaivnt%`Ag+8f2lvNNiPnlBIYku!2G3lw*QVF}4Z*oCUYt58t24-8nT-7i2+q$1F5P?BE~jx5+e$g zUK9L9gRcpw{i;c?38>#9IKGU77~6zDHUhsk7=lzydTl^87k{bC8i=_J%K~C-6Mjns z{-j`)hCeBwLaQcyl8)$3c<7muh_OwC8zTrO2j^>qlLP9mYSJeMR8I|*58oliHsPPN z@V3(Hg4;FHx`1k`n)JGWs;Gg~6eSU3n>g{2(TT$%t`A<-i0cEYq-xUZ1FD>eh;Q5> z#x^l$7hwYElwdHj_)C=&f2m9Y5?3z7*e24BQlwLZ6E)JQ0ToI$=~Dyhiw2s{&mqP( zvA$A@bz1N#jdfZ;rBO}#w166+f#xG~h_TIW$g>s;0H^CvqWq;kh`-eK4BEjigBaUd z5~B*u|B2vDP5%=C^*uG|PXyHI4C2Nii5T1Wfco?Z_!+@qq-xS<1XSzrm#UjV)U_lL zW1HZcBH+!zN)6r|PGpk`&D`Ena# zY-|0;=z@GU1p!hu=}iIkEBsZ^FASnyB#9W?1Ya8g-yGCy@XZ00C^hNL0Tm^KsMkm$ z#x~ixI0D`pbZGF_fVz^JbZbCm$RMgLl8CWQ@Ovz{?Xg>e&ug450W~5u=`8^@9)qZg zNFv5IasC+M@VEk)t-(_oXKO%(2h-GK45Er5i5T0&8G1}~cmSp?@Q}q{sxkOW4aFd8 z8j^^yO`P>bICd-29?aB;?E$qEHR<+%8i;{fJAhA<_b2A178CE!47xP@nE@3KOjD;Y z(0teoF}8_tZvT+a11>5ky18mA+m4uNTE z2?p^LpG1sp;tZ>`65yBu%=RFTEdEkWz+Wl>2Jt+fM2v0XG+7+H?hIyW@Xml50H%4s zA1EjCBw}n6;lc>Qj-X8=>#BysU6+N!CN9T&*?t|Wv|a~Y}wh`Om5~o!PMEfZpurY8l1kr7!MU1adbr7 z%mSw@fi301d}kxRWCs`Q%t9ylA!KnVzoTPw7rr0S=p@2s#oBNSxja`UrjIXX7LgQEYcjNCcvivw6GW>(g&!U%TgcVC@SIekm!H)9ZYJ}G; zf*NNK^u|AP2~mgp8f^hO27-{ESJ?+JRelZr4kLISQ8b?Z^LG@R;U6h%T}yXop}dQ8 zCurn#_&cH_M5O*hP8$8G57~nkBUK;PSVAuc*H#gD)B?;x!TnCn4M+@O;?m$*$A1Lv znTH1|nk0Bm#IN$&6DWAzDJN}TC$$@E@Jq?ceS{p?dtAEAszVUtO{O`f+i2;IXie!Qqza>dkMiylB&z2Vl6-R56<{^ub?bs7l@H@$zKXe5v{;CYXhN0iXU_c0V zJscP2_2=oD8N4F+y))6v_ynUrnxl@%fQ5$4H*%y{Tb((Sx)m?S+vvlXUpzZ zJy`Cn89y6T#v*bL#^bkZ*!BIf{F-NX3u=ntb(e1HK#i%++#Os+WXv`9^!-ovwXqm- z{Fa;y&BGP!<^I@BJ@|~ty?xjlb7~xBiti)`0&g6~=691U9s#N|_ob@98tjE13Vw>L z@swHS;eMR6)Od<4^N3EkY8118D15}5}j0k%7LZfV7u zv}Fgr50(5TiyJHaeN)eYs4Hj0Z|Q_T{!JEjyOw-zyqAS9}g_GOk@^XOy4Lr%shUHp>-A z4LJ$&&t>~NIil$WDO(*`keJ|#BMXvErBF|nSSbu-XL^4lPd&(rua&%9c0uk=q{sgq zg3d1V_zq3b)69gXs45L;w$bC)KPm`5@hcdbx$HINBd~0Z$z`ugC-5Ldu8&8ETp!m& z#%^xy=xI^e8~U&ZrPVktQQ2$Lq&3biP}v*fKWFiSNj!U#_kAQP*Ys>#zFB2^`|@ia zRX)obMPXzII3DXZY3&+`37yYEvCB_sO!l+;oYbcQIHiL=*pT8mPQV79(#DaavgbN| z325ZFJ1R#cB62jTR9+7_mEB|4^_^|qn($t`sJFF1!IeGR$+0H{`CTe|o)g~)9&&j) zhhwJOsj}xgl^K*D*K4cp6R@n$)hsG=Z4m@86R^hz7ML^def18Ts9r~ zJS*~jC;KzJszn>N;KLrOF8d2NM_^&$8Mm>TA!7epQh8zjH?C&C zR@i^R)qAGNXh4dp%5P*dvSnUj9iGF_TvA*mQCW0>furH+LzEz_KT$c&;f0 zWpwvox0Q{#dbj20>12jn#M4Ay1<6ezwZZJxY>h8k&lFbWqIi0;tWrs<+k4|sW%{*MPusH!HtE3m9>ZuS;rHEG!kqZ8cVAhOoyi;AD<=Dvm84f&AO zNp9vYTr}FHoxdrvX>x&(MGG)%olVRX)4f zq?5WZ9jV%Eo15EuEaur##uBqH6$q*6T2sO*`x!(bZOW=At-!EQJHBhcmy`(0fj z^3hiq&+c?RW)A5^!IQK5+}wZTrEq*sv|uD61)EfA=qEV_O)4$2M2csqTpp|UxvpNm zt8F7<1#qiaLSFS}6=OJznHgdfImp6__#(U>@)3koo4wG@T?7bW2WH6OSu=}7gdLMI z?3k2c2Pt6(ed=Pjf=z1JK@a|yrsf~z8!7p`8 z&R*)4{{%TxAoR=JfR*54a=9Daghw@X6+3fv_FHZ_gU3x`az*Re$hqB3*CS`B-d7xQ zWlw;!Gd31T=?dkywVvIK({%O@w~QGnsr;R;-YW+BwcaOu+s$xGk<$y^U2gmZa?#FE zg(~|USFeVuujV9sx9gGJ3UX7W1KRbK#U=Zq>v7JmI16uPh=*QzWp>)yC#niQoV4nARjGkitzN6D__T7Z>Z5-btG@hgT)nDs!CKW%KQCChQuWtQD_5^s ztg89AN)5o~4)rge;9UZ#^l!oW;5NuYcZ`gx_&lC@a9rEmb2f%9K0C9sS(Pt!2!jj# ztU-JIPvFflgV4KknHzF7IJ%708>7sPWlX5Cox9-9ow-TYq_KKN z&wN&=0yGzAslmj~e9n6Xl&btU(Jcn^u$1|M#~u63SMc`Ic;@}w-Ss>;zz{!!L+_q8gd$d%m@M*}^IP$iF3mw)a$1q2_W>DLig09X(IA*U@$K@Y zWNpoFMa*X2nQuohl8i68Z9119!q&Md$!!NZj95DP>6A=b^3FtF>-N@eP}zh^WF&VR za=Th|BL$Mvp^I+q()7wCZ@bBp_RC6UCzV||+GNUQkJpvoxu>)ke0VZ^oD(z#D%`b*9s6uq}~GnuKDoWprcaJ$<%hh%Cb>mjPB@Bz|+l6)es zd)L{>RGC4N_cZ8qj})Dln=_;Sf(f%B!q^GBeYSo`xcGA*mU*5lG)6;dXqegM$X2v?+JPe>JpYN-D>Jn#B zokBaKGof;<@++WloVv8}q)w{Tp2(c;B(F!#6t>(aoPhi7DLmYt;Z*X3gp*IE*~uN? z*$7djG8>$VuW)g|r*>Q9ID-q1%tj~2jm;E%oGP=)>BCA)!Bz|3Wp#4g5!m&hVqEsv zB~zEvMeK(tl+Uea$*2FkQI|WayVOmP>KhNX5}w)J|d7-y_|QP1D>955R_}){CYv#C0Ob@K+a!)rf|OC_2F5Sp=BE8 z%o8Z?#Q0Aj4q1rJY%8vt3pV2TBHxL0TD`u+cMM-`f(gE6G=MKTX#r>=li&@Xzd~xE z6zR`B6CoLFD%UX75CL=gUp<05w0V^R+`-Z*vxQtsnr-BZUq1E*_dG;3zBnI)~aH)M7JGT3@~Z&-xcyf?0h*}ON`FgsV68|F=wjB07l zVP1o9pKo~9lu<1EQC9XFMD|FBvJdAA<)plFD|^fzruT&cS44TLPU`SzSck`02S^29 zSF^)I_qmieMau9S<{GAKuVRlX_o}2zqWMD>u$(C8Ll<0_Aptg!XE~W^6`&TvwY z=Ke*($%pQUB2GSZCvl14M`bQCNPyJ;>bIfu{!7k`?tu;A`-u3IqpbAS*YCw-jHHlj z0*S@C7m!T^RVS~?`J?9l*wPnAt;E026mi~b_;GrNV}_?V|LB?_tYirP(VcE8QICoJ zPoh*J%hjezGYyIQ&b`Wc+tq4({k@e?x_ZKSs#v&XRsVK6H)#8PIS#<0qcjI8x%J@yrJ~vC+Z%vW1 zPcvmZy`QJ>(Qo&;!_45b6DLrWvy<&BI}y@4vT@a=hGct4@*k!>ce;Zjv*S*8w3!{v zyn*h5uuHCQr!J%;i%{}%v&zRR=D{HqbuC8hS9mL=oTy7Ii}yu{}sA}vr?4E_!2>VXA5=^ zHo2i5icCm)m7617eyWf=jMbw0!-$?=HyG$mHr=MQIdc_Y_11W(kvs0Kpl~$%rba!y zWKN2_h{(yz0%xl4O_J(ilcxVUyTdZ6?zVgeQ zMV8BsBCeD(Br@KGp`-9}ruwf5!pyVbbo9yNMAk!!2KkV}AV>2Xc80ihhMl>cZNkq` zn^jGj=B>;->Vbt8ALgdGE!D#fhblv7xPW;FdiN8~h;)Rg3DH;7vev!uOz7OI`v`Q< zpcHelIlSiv!Z@fNdv7)fk}V(t_p%K5x-aN?qkbPw#P=K(-D2|Fomn9n-} zCu!5`*)zF^W|?m}W&bu_=;&`b!)@bnfAf|z-nO1j&6HHG9$VYD<%S$x ztzM+|H=EJc@O@Lj#ioFIo;{s+96Q-Jd|&`pTL5(Z_nj;?mY74s*LKp98R`Q^&xjm% zoWPJI+xj~W+^qBPvlLq|3S)OGJ}!<`_8F&a_Bg5R%CK`BSSgi##yQ4T7PWiEvErR8 z^?AlwU^+&_#fHX*mR)p<-#A)fh-Iq2Ll9oDIqMrzrhYhY>VI5~f9I5$wGLVQG!7IV zGF{y71YGfUj}=ZIGf0SPe>}T_a_&d)Wju1dMz$>}4up)jvk`4>R03xr+Msc&)gA?&I#!tZM# zzyC7)-r`Iu=Jyt-!SGw(u~j)=w&i!!;{(XZxK(sjI2IayzhW~sli#n})CQRqzh={G zmt5^(J?q${od0ml$qnrRhh^tBn?@xTYRewIv$;lOJ)C-RgksbWnAM7mpzM> z_BGB7%RTz(wYKmMwP4eZ?OnT|>ccdK$rv}h>@i=f6}em!(*8SXOUs?>Ocq*7TJBtD ziKUH-o);0!9^7yt>wH@rM5CPjHYMx91va^%o?j{44!x3dq0Kv8E#)dIeXPwXYczZn z=IlC*KMwo0!mvkgYYRtxxOU?H+BuN{6J>Gch4zs%anqE^YiKTZvc8{Xk3M6xNaDZ3 zvG)MB!z}ScCwlNY(J4N7o#;%YWg1SR(%x%ql{(lP*4osfc|S7+3^k(uCn|)=LOJVX zuF#(io%fc3T4122g9$)kid}EP4w)?tGQwTZmyZ$dKV{H3G|rGg%w5^M$IN>>OI;>p zF*P;YnQFbBsgRVJs!27xZIGZl(*J~y4VDk=;Pkl{8Nvs4AZj7MGlBnFvD1X{8~a$# zDBK0nbb~LXfSQ>zUQjBfQmr}qjng)uYDnP7&L{-y`izp%!^pv^n|Nb%8; zQk%je*zZIjqSNJ_P@SUr&pWe)1%K{ls3u_!1&~HLFJM2RoMDc>R_B=~XV{skn^qWA9GmC|BSc2FL7d*y8U%@ljNY1I zs5bn|z}RJHwp8n#f=+8i>sh;6Ipa3R|q4$)?k-G;&O)JPFEV$@^%@ziwb z!~Str@K4P(a#t&;EXK~iohFHEPgc&|djCJw(8fid{)bJXVfpTHhUMclD|Z{!g4uDrF3HZ(G8onv555fJqpVQ{=V*p~)d`r~O0zc4Vi ztl60QzEMG~xttrT{EM)qTG7$WML>I}Drb*wcN>QEE<@ev?K%lEMRoU#lN$ZCQg|+IX_{0&#una`b|5!Tc;w?(!Hq-+g(^Uwd5ykRk4YaFpws}%4=gs z`^JfzRO9T^Pr^QT=jkW5v~Suz4Dt|^H`;D3Dw?m zI(CbvV+rp$9rs%8>S?2t?vs<6^gjwxI|x+BKlhot+lzRqr`^RjzX z4{BH3p79g9J;SLKYkBLj(^BYUoJOx&)yk*HJd~T?Vi1s zeiV@gESNZZXO_RCtMDQI`u_w#8sj>}Kd9HG`qe?^`WgO=Kz^XgNLVb1y=$wgk(c-; z8SFo30iLsb&c|Z+_`g7^T*YGdrEb7eu2aSCkMpyxxm|o>1#*Zzdw;wi-?sDVZsv9H zDaNObD)zv@at{Sp;PG&3Dl%1to=0Q%roV}VUjeG$)sMM~l`8hVELpFv;1`@#?7{eI zr1GlrRs?hgiv17_}NT>>Jc^a#&cnP$9l^|qnj7QczLT7FUP#!E)QF{OK zRBZX?y=#^8QolwZ#5Td^W*fRfd~S{$mo;y0IlH5MYa4R*_4_9}tU-M2uqpQDNPEsz-CXc~PjN{v%Z z95?FBpGhOKb;^5ajx4kN(ZV#^#K*c9C);nd@D+K=*wj};Jz4Y5mYlHcGN$IkWcWNc+OWDUev!v`?zwYVKAvwM+7hJ5i zsWy1xLQA37bmfeZLN8h_h1xH8IlbwGRDX;!B3k`1&Ny2pt3Sq>F3DU!tRrJ>86Ewg zNf>8SD3Nk*=BY|KmC|4jFOw1<4y$>ADY4QSZcD_;sL~n3_NBZxGBsIJxxq=pvb~J# z2ThW4`Z*~9=zud0_JP>p_)gh=Q`o|=u>UlL;maVlFjT;IM%&t<0=_fRR89?njRroL z1p}3Rwz=NvOJNT+lsANw7bKC3J@C7k3204d_=ciw|DGP9d&T;p8+UENV*g%_VD5pH zLs9DcIcc_zp}GsbUnNQ0FZ1C90P5lFsv%f2yKoXy&cnLX=U__2e}zv4eFMOGblQjW zrdC7IY%zJxB}TyENfFON8)e!&<#(2;XJJMOxoU8dtW-r=_Ge-JxvI!aGCef!Sl_%)YS8 zB$|eDZ@b%wZROzK8^T;F`Hw=~S0Su4u!{To*r^LFb+-yrr)s7aE)b?Np@_d_m^w8S zu^bvs3;EJ2{nJg7t!7n;^_t}H1|gXbNmgJ#$IewBl0?jP zCOx=K4n^7Ped{*q!EJI{l~Nmg?KbH_bM!TA5N;-p-hp~>oBSQ>b>2Mc50s~ zXsC}lNW{+Q%bukXLSM<)=6+2d^@HhPo{*+v>R z{*iKv+$Lie=SBlM<&VeTvIQZcW`Jd@?5+5-5--Ye90?CQv1_XcT=6J+K@4t_+mJ{w zacK;0lh>m?lP~fWoF+9DUrriunj~dkC$*Pk3{I2G%K4In(pIkz+aGK=sYeK8H`8u*%PJIZ}ysv_LKa zA4;O>)hSUOS)G{RQX{LAO{Gw6mKYNT5;MJL05izCPbL=RuEN`zzeD7Sh2F_{Mq~6e zGogv8m;p^RdYkdqBlzH~X62f4m0}N0T$lb`NaXr>gvj-AO{7}fClfdHVP8tC0lRU% zl(;rcS_AAtmAEl}2x%23@x)Eumyw8x`(&cGZw*RH`7E!3a!9~^lGPewO|TKFLlH_`6gB?vwLTNX`%4Clhd=d>vWUsK*5S>iOY4Jm~oW9tpN8 z3Aj%ZV3>8EOu&8e4DM9nb(nzrB*lhJV*)Ob>>2RZaV5H=nw z!JDcyL=$kIOo8SQ<35>q$jQBhwDc?ZNEU>GL_{big=NvWPbT0#shicO`()x#ne21P zSJ|cDKKU(dH>&mKBLVkGZa(rpD+2e)?;=r)HWc^C1l%VHEG)oBvcLio5f)4;<%|1d z0`8O2F8cahn=mBcL@7;UoG24;qLjvwtLFp^#=5g?Ac2PyB}4yI`#cEpvQs7CNy)6d z)C8WCWUf|f0#8cTWHQ>4QcL-HwkR9vN60oUnwYGI2|OwLV-GD0Y66~=Oer5{AMWi` z0-lt*ay~sN6Y!*DD&=briUd3ViC8VlnHoJ zGB4v7c~U0eNy+TM=P5JvJWRlolFa3FHlzzrN~ZhhwDw(043{kISb!ONLMGrzNytGu z8?!PzDVfGThG52%G67FY=8n|4QCG$UJSq96R&Qt$@T6pFyx!0x;7Q5UWFH*ClalhO z!_)v{n*=;5_afQgqeysCo{#5cexW|_q`VwiO=j+ohv7-dKD-xQi!(~fzfbqOPXZ<79|l~?AFTg=TIaJjq zN@?i?zRN-|?-pPTG2WF4cvrTTV;asS;9c1lPs4Kwcvt=%Fw!I7T}c3yXGC59*wP@5V1?c9dNytS8`K$;?C?oqBQt{*`azrSJ?#$wI+ML<%;kRPq{guKeKiY`uVX5OeE2MPFBUVzt$ZX{|G@UOf85W)@| zB@65z5n;!q3_B)e*g;CzK~IB!B^%nXgJlE$l`H_<@chXC4L2$OEU-~QHWKi!EXSK+ zjn=<10sqP;i3Xv=zmk>UY6Jhu8}O)xtzs9iPQbtNWK5+)m|Q{s$^`r?8FDSDHy-e) z)SCtzva$0(N>|8-nuPw93HVnsBPErGe`KKqVCMs`M+%*-};a;Z5Hg(0_8?4Y@4#=hb?@QsQ1;*1q1w)Z*jSx`#(Popyw-4VrkwDNx7aeqH*0G=<6d++D& zfnK8;OF6YMIOlv&_8e-0dklPO>qEWa_Hpb8T`awSq&h)2S8ZG@y?^R-HPWGrrT0;~ z88G?kh>NB7FP%rF3@(Q}cpCIUr6xnC6S`P>aIs`3Z16)DOAjuV%xdzri=_t_OZL4D z_J}MlmiTIzp2s%(*2U6;izUZGD{}M(!Gnt>Gqz|D?PBS{#gbWD{ius2K2xT1+jOpV zvGm|#N!WIvTNg_YE|$zY6L|#}OAjuV%-x1uak2E^V#%BiU9`AZdT_C1-gc8GjR_Y^ zW_D6BhLev67fVh=UA}d(^x$I2=GyBU7fTN=mIS%L*DjXWyXxenIw>xe9$YL5a<#9W zCq1}WGI^6OD3Q2b??$HmL6OznfEm4SQkqVE|$!D-c*Y&mL6OznfJ2E6M}HDWajH8 zQ@dDtaIs|OU#+eVE|%2Qy*FB1EIqhba!FCn=!lD@2Nz31;bN)aV(G!flH(}nj5aQo z9$YLR4UQ<35sacjqdV0>NR$13vZ*7<5ngQ7fTN=maGH=At(%nYFtZd&WAKD`!v@ zAyVFkxr>2<$U?VbzH){P#@)2Z8LKBwcsNLy5L_QZrGVS%8729V`{|~-M)cn0h&WYb z7Kvzfr#9+R$SnUky&qO191(6BTxU3Sm$6N^R2&z3IsTDJ1kGgri$mnaKjAqtgc7}}J9A!i_xf285L~?Q794|ufCsS~5 zE)==tCgbk!FUJrS@~Op}zv|@);;C)f)B`&><-BEb+G?%9-ZnX#CuC0%E*eA-it)K> zwKU%Kj4+UdFy8e<7VFi-PZ*q)21nrEH^OTW`1g(Mnkc(FAXa*Iu5G6FYe)BHSVpcr zUO6wo+IGs!BVI%#7y8__x3}wv5){JY>xAhq8U~!+(_ko0(Y-LjimnUBeJ@NGp8d(Y zQG*xeiU4zyw{)~aYA+5ly=rp%PGdIq;%LdrPo=`yd2t$dTJC|`TI~S!l3o|lfoc&M z*m-HN5O16CJHw7O(47rtAOz+7*7hegF=kqOP(fzOdDV*S2!6neB1=GSeQW&WFt4ub!;ye5kId&W9G5 zIv1Ktj1E|Zudxc!jZg)fAE|(PLOD(u_P;0?yE+iA7h=he) z$3kewWP8QOcGM$##j|Ur_&UXx^ODQU0`{BKvFwkf)%A!RyS-pIY($bH#_YfMpA?gxk2%AKhz2YYN0`!lmLh<(Y^GzcApPN4A^uA_ff7)0pdn~@E%`vjC#VNu$Jxw4?T@(Lh(1i%9 zsBe=ISVX`#aKCb9gKim$R?4z-%7dw*s!)htz&XCppBcz)w z9T#DB>0HCAOkPVHWirWW&X-xvm55Grq@1~AX0o1fb&l~`WzkJxbO4e)&+yO@@(_#! z4>}MrHu-ahi(r(LJ$Is%?N8QGsqlUtPfS>S^~_dZGP7xWU}rQ251ppgHZvWOh_aSC zSB8aul7(Zg9X-ehpjIPlcBCba8FU?BQr^q;GM2fiooqI&r;E~u0OkPak)WE5861{L z+jzMA-&xo1>O`2CuKx?`q^nPpMt_%wGyE$%A!40$GcqF9N%tZ7zqU?#mdO9VStq@O zMH<#g=VJy;@L5|Y4fmj>{1#F)Ncs#;OrdqsccEqRlf%(Ye8p6ebrLg5t&^Bnuugg( z#0u6)i*ZIQSSNMjKpt8r^&oMCbrRvD)=5m4S|>e*!*{WD5}_KB$B}7RC;b_!f~a-U zC=^s;o%AVW6db}&Cm;U8o&a)wZe zS|{DE5x!#)eqs?2-3+K}h^moJgzFnzGGe=`f2%QGBL)UJUYjB^89q_(gTfBtFT4oY zM^Zjr7&MUu)~aa~-lY6-_?srya{Mpong-!B{3BSUR!ti~eF%_|EIuXfYyC&w8*frgZQs$M~H8FF3@-)uLuxsML zZAhNQ6zrOqDz$4$z*Ht;*K{NL{{O>aP6RTNsv|118MDWK?nmf;g}KZp8fZ^mOk zq_v4S?3$iM&1ly|irTK}J9w$>n%eOYwQIT*gQQ^B#355^*F@Y$;!A7S#QqhvYx)&9_@C^WCJ?^Fu8EVU_W}My?3#E5 zXY87|CW&1W2fo-fwV{c`u4z7>v|SSyGL`rP`j572BAQ;;XuK4zYfNyFl6B3dXxGFN z3wBLaNJZ_MevEWY79xi!({*?b?V2>Ps9n=7csqCuAajXp%4eaev`Nz-JP7{v@d*C) zagARvX<{Q3Oqy6~)THSTEICf%FlqV?5(Sf{H7FqEv%Ct5fF@0>QL#zWK1GX0nkejCaypw4CQYw_YPH_6(4>hwme8c> zZ%7oIG!a->fZbAo1tcOYm{ioHN!q2@q)D14V$vjyQ!r_|4cp;}Nz+X@VwIRQF)J@M zfk_jYtCgC-q=_}5NfV`(@=sxlvXMNTO-zd>-qwQ^CQVJqESNMgRcz9vD;JtHF%>as z(se@y`$`2#(xi#S6qz)Aokc`VnxvGdNfRgHs7Vvk#U@RgKqN5_4W~_-UM0ycF=--f z#H5Kym^2ZTCQbK}n}|shB`eJcyQM-iBB5)lH{CR8lA0EqH0kP=m^3l(C?-wJK8i^b znTwhWDQppoo9g|9naFL>L{~y-g1WbzR>Knh+)k{rxO?NXe zFbvzU@5r#DF!Zn}2*SvshM)+;3=GWXEbIzKlaRzjP@|ZTycmtas1XwvToOr)5wjSQ zXo6)czX>}e)W=!K`5 zSVDzLQ^hH`HA6->O2E@hk3hQkvjFsIrbhyCa4ab=4uFt21~TFp$cO_-#F5iXtmA^y zOe_G>@OhK}Mw%k;%Mha*#o%eCIY=oy&7?R!%4sGl!HEW^nZA$P@M)$`f~xQ|QwuN& zz1+b0CB0qG2EP_g#r?v=QD^ZwQu{WzEW)rr&y0Wv$Aaj#uE( zD$8)rfzOHF`Ds2%X3O+9SG)^~I4zgqon>!En$M#ZT}}WMm1L-0cXBSRLzChOpv^4C zo&X|{KLJGI{0Sg!7-+{19%F8t0IC9gk(Y*n3Qqv>Ap|FYxDp;*3Q~OnXaF1q1t);I zLtJ|Th@y8r0mPSC!zX|UcRd001>m}#03t4Q0%#|MJnIAyE3V54AfiGifH;|-;{*^} zOW_G1VhTAa>ru z6F{u4f)hX_37r5U*!2VuaiJ4H1iPL9BChZR5HW=(fQTtP0Yprf6F@|TP5=??dIE^J zt|x$q>v{r+xU)_G5qZ`LAR@yjfani9GbDckh{LdQhIBarL@E#1AjmpT0I?rsogtwU zK%?0~Kqe=EE&z1W8B%ZpXd!STB17^gfauiO8XFQm0mPo9PXJNYB9G3>G|M7CJs9Bx z5Eq){rD2=^V)_~jPtsVN0AkPO381g&Ue5F)kG{R3^sD7h0BuJ?;RzsqD%73;;=0wI z0OCW3IRW$)K5m#3K)>L~E+>Gv)-@-9IP=>RKvW_)0mO+^4J&g7W~VP|S+j1L{@TG* z9I0WnhCzDdQ)MfaGuR^%J`H?o0(GLt&MZ{;0Y}_?PG_h~d3mg9#cFYhD`%>cGMi%- z7jp5}OvD&nv#?h6!Cu46hB*)i?lp+WKj#3kBOuCDXAnnWockF8X{I`(C=QPOnBAAD z&UB9E*k%~HOgYn>;+Z-*HxgEHraQ%C!wtq!ubL8uO95&m&sogH2e@Ddh6@_WxWs@Z z!=YWQCeDzf^{deHWv*}rImQ22FQU#4M7^A%qVz$|P~I}EMv+H3M%U}i`oN%r<8}v4 z)(;yQoCA-VtmV!SlXZlp9>?c1D%v5YFL!cAQzKI&zF5)5V>&ojIMHx!3OJAMEkbp3 zh6S8SI$4-_BlwvDz;mtnB&0%#<1r@!E{x=>FHUzyPn?YJls*XN7a-A0#-kh2ZUP6b zqYzE9UQEO1O#V3sZZlG-ycF2oRL*!NP`Os~h9z(_*nd!wFy1dwDPzcfZr$2Wi1|kG zUuuQ*f{11PH*gpWtG_YW=rQf%7xPyVeNjjREKT4CiNTeUtMu z<3ds&4Rijs0gTjhTKIwuKV0X0zWBsyVV*w+c0Z1&Q0&hS51Hiil_BN_!py&5faRlF zuNGGS6630I=o@zzvuj{Oe;jr}@6jtdSns_5GNeNd>2j1gj(zEHkF{!B%~3PN-_^K{08tLEqoTZ4@4CgZ%IX_(J^%$s0FZQ9^MQ(GIxAymgjrtz(lGG^l& zNQeQFHeg4FJTjnN<91vu#`xWRGIWLA@pgLnE?J z8pAaW#@w;emL^RRQSk{c9VbCKBeHe}`jUVZ*^CH!)Rqkh@-d>)Od(2Ligip>{jCWL zg#YR8c}M-U|3|^;_HLAFq63b9U%V`|eSQ}ZcKbX&c+58e{(sm$|G(ZWk9jO8=Ji7( z4Tbf~_ zef?N!A08ZwA~&V(*Vj*{UeMRiq+Zk4n^W)U>%P=Nw85gtZK?J8dVA`6eZ4dFMScBT z>S=xbeCl<5{X!~^N4%oQ-KkOf`sLI#eZ4nziN1a%)u^wBQhW9FzSN`odVlK2`uafX zU41>>vsst_ZqMI9tD?x?d-lM>wkUF@=LCIyujlRh`hL%a`udNat@`>w&qr}h;ypp- z*1M}$F6)?xdwgLU)&4oG4pO`^>C1!kW;F=tCz;M0lfF1euT!_dYOgY#Hzxh!AiZ9F z3h4Kl&Kr|{VUWH~T@Q3QG)eKsq|Xe}x2j(Ndp^^7W74Mu>5VFeT3pF=-rxi14VzWu zVM)h5zLw2u)rmrZuym`}H+Qlzs3_i;Veihj4UcUDKYO)pkEO)cCsJbLH&SBbH&bHU z-=)O1zfXzHPo-#Mk>O>?uy}e<)tt>D5R;;5{#PK?xgT=9*4~V~fow zVxw0X1X@zDnHq?ysF230ViY>Py3uCMl~75OwK}OSAz5c@09g%fY))(*Nb@HVBGIUv z#qJWeF}r$oLsRSO)vKGCmIoZL&Y8#_5-8|65)BjLo zWk~@AollNh6@{;bxV*iMl#!k*7Z#YMxT-JXg|nD9F(g1sJ3@o1Shb|tY+D+dHTuG{&`o?3 zOT`wRoxpG7saTC9lxAa3MM|bNni^$;>M4!psmOTUNf3+NQPk8#iG-Q;EsFC~_IT*|!yuCS#v;GOQjBeW`Du=9tn_uVSBeO4vW2C7wS}^*)o@ zpkjL^7Y9g5WiE8hTksicaOZ$&@c4KbqpjjCKBwCVjEnqFjS7Cg2A(PXQwf~v?Zv$D zxG9f$Q*r4-(KzbnbEq=(0TnyobYth?NSq>({!wK(sE5i{u`f8?*myWV8#!n^75j># zI}Qiz&H^csM>N%TeTYCo^)_;jGoR&0=DuXrf`Ap0# zvD0D_PF46cB7UBOM8g*XisSXUsnFP8a0YO);#i)iv4(`9Uvh?X zvU|BOy~rEx>!pJ?(br1~Z<5bpxr|e8Y?mk<#Uv^=FY>1Ne*_1NyQ^30A-HnFG(5vk z@wa2PjAUaNA)7la?sLE~?MZWe)m+~7yVPd`>Ax52?V{=BC2+e9;JrRUW*&Kp zR`y_H)+qZZRdiJ;D_`S+hmE2&Jz1d|nLj93v@z2FwlS{-zk1xb4mTCBM~Y2lA>6ZjThPhp3Exu1G$SWY_mH;QFM#&1M#< z%hU|by+2pY7M)1mLKUZ>iMvu!G{Te}XM7L$2^i+RRCP%sy z-6eI&T`1)y+zh4F{*4oSogH}57LSM(Jvp4XOe@)ppTqdqlX_ga2XQ})obhm-ae6VS z$URs+4=luase|l-(=_Gu(J^)>z@r%;L+(q(;raZIIXdUZ^)DS>LyN_2*~b}4h3N|% zNk1LJwyvYM$#HyUe6n3K?hZ0Gn~aV#*kl~mh@}eNVN5UsUdvOXG$XuGrV~EUj6P== zRRoOg1tY#N`N0q?K#&hZOhYX!bVg_0epc4kOx82Q&&sNtlRDGpHW8eWllkWyxFId& zog8Q~jkd*{93hf>W3(&rHQgHU7Tg%v;dNchctdgw95ZiZ*uLLO58SWd+<-VGKfs zUoy40VeB9y-PKk_u)kL?jQM6N9@M|m?Jiiu-FI{gTsp0t?Hhs;?Q)yMEq3)toSJL%AiVh-m409Sshfq)c4i4 zzNrh|;8;_r%i2Jfu|16Of)?A37j`!2_Nl)@pw8oHvU**e=rO$qTkeb2RS}5%E=7h> zr;nAEtwu8ph%&p>6gc5 zCZ+#u7@IK0`g-2Hog6f)O$%H%w#-lnGx*_a!Ea6v;deE%#XLQGNu|u8z^uIBP&rrC$3KW;K%T zwE6!@u-M~faDUBw1tN20$e(lo(prBKK6Y?~!vEiY?BM@Lu-KRm{uuK{v3~QPIKU1g zYev7|`akzDm8wzLp9s7NaeA2eb3K?Bxg(>gX>hU^xuc?~;keO0m}uAs^Xq;}y#U%2 zZ%lgF2lF?e-)1^*OnTS{^Abug!b&j38u?1L$RY@c8{Z;)P#mg;_3J7Fdfs8bZ|eo`0-HO1w5ih4!Senbi*V|zoh za+?hW0O9fH5D!hUF;5{py198C*z-~D^@aj~@R&#nBZsEAHcufuRuu9;c*)x|$z+6h zXr6$8aLm2SvI+45<=zk_f~`}V`z$-7n^yj5O*b*H&I^{EO6v3@LAo$`+cHtUR{TLn z2m;e2vHlcMgy6nBfp8d20&QJitNoTC2n@qOv4(>tcs)-b9GU_Slo6ZeKh`o#A|OV& zIbdNZevqdS9uEgRC?Arj&8-+3+&6#fNb2<81nH9h+91D=;6mguUdouPK?Lj9E#*GTCUrjh zhov18rmY7pC3)GhG_;NQKo|JVF|-=26Sj(O6}Chj0#^BkbXJ(OUbv1XDcM`nmi5ZL zOb917wyYO*7g>hjMS`Vy0@1h0ve5*UE7wy7Gl`YlyPGM%bn3g3Y{E(5vej5Od}}(;ol` zlWzx148@o86vE?;Jdb+qzJFIJ2ndfD-7Q+Bq)_}NPa!;plR~tCuL0gf#DLN?lQk%8 z76oj4Llg}Y38!m9oKPVQfMf~-WbFJo%g9)#UK92T5gJQBYnh2`#S1I2f*%~w3@gXi zx7H%MR(nJJwmQWb`VW?^62ksx6Joaqgr)S%=($V?d!J2MuL-M2sLfLR5{o`x2&W-H z37@#3PV*p~xFeM|uTV|tLbXm)eKKFD=7o@m++_)P)oZH5L5Y3?Mm)6q6+$;zgHoXO zEJ+hJL^WX|DewKDJj-c*m`I8nK!20edqaCOr^D8O2%r=G4on#tJ4U7AR5KV7r zUypOKa9EfobHJ8piq*sqbtPUWCBI-xHpOe=`@0gO%dj#2-AZ7@=tevLNQf&Z<>lZf z`HV0l`N%=_jW9aP3+K*aL|VlxG=>pLXL;`2S&U#eGYgxV5v+oO{a&(6X=rb(Ye#%L ztpeYt2+N}>-zcCoV!Y8s3{Cml0!mYQF?=xL($}zd@FEGDOl74hK4g=bqz~Cd)Bn>b z7^XLpG?6}J5KaHyIp~c%U+5ywUGT%XeT+O4MV`VY^W!cO=^VYznZwBBz&#U|N$2Q( z&KyRniOdnIqsv%Flk-;ULA(gILQL@ElZSNVeSlZ5~A0`M8fH=Jg3^VTt}P{nn{F2x9{fp2+2Dk65;aufJ^af zY)Q$O42HEWt=n`Mdg0VPTUcM3Hr|C6wr3NVMcRB@@ax(z8TA+1i2#J-)s~|Yg7Q3p zu({r{(F6#*H(n?vfkmzGxTk;zNXCRngv;|GE?W_;#hq3~|vURUs1LQVd^; zsei1Rn-HCGxzJ43pzxVMBB_5vR1+o=PM7C7)vv>spWS*>7$I~H=HG1@8E!(jHbiJF zeV=7!WUFslqulL6HxWRcVfga`hL$UdH|L4#4O16BqZ{;z+_Th6oKu9^lRks{9SxT5-a`eM~4P zYtZogX&0V`^y^_#!}XtCxHjO4Wi39iVn{V8tHwbH8)^MtEC8e$uI|EHlkYv795V%(-W+h(4XOAoa=+Jz zf)gqDnlqOc!u#niyfyKcx)K|?-wrrSJ#8oFCxv(lIOFt7o%OYp_X-aD|NAu|LM+~*Kjm>q9dQ^&+S%tOpRY?C-NLt^hYp9Z>T2&$aGglJP zgdSO@Xs*r1we;bDDIcd*v8Gf7l*Y64(SWB=evUkQ8p@8)=y{)IsfsmCNdb*${3FXu z`5g#Bjg`U(p_;5gX*z!m7+InrVItww3vW3{uTIByr9KX)P&&3d^&NfvSZcs1!Z)R+ z>+7dem+I?hQVsfgbLx71-IqF{ueYV%(bwBk>Cw!0XKJ**elE2@Uq7E}(bq4eZq?Vj zQ;+NGms8K_>%FO0_4O;M_w@Bps^1v$xi2+aU++(?($@!4AJNy-JrBUmpN_rT^HXRl z>Db?U-lg$pdOoAC@AVu!miYI3p3v|=dj3;iKj=9d_>4Z;RB!^4YHQcL_~&u{D>wle z#|g+IC?&sl!4r^i{LIv4A4`cWCsHEA8!3_D&6Je=yOfmu`;^FZDwUVve{%wo4E08W z>?Wu#0Y?hnMC!FPkmr#n~FXu2wKtD9!C?qLsUdKZ+iEtTr?cHRvA^#N7N z<96Om4FrcYy{Z^vL@DWV!fno1yW<=^EnBId!s8siYBbXkJV3KnfyIJ8t zcK21_9P`%dUzQY5$Pr8rM=*Ek#E?1Gjfm>!N`c1_Sn zFg+Z>WJ2$(7e0c?7F{k)0!J{p#8c(EP2dP7ArG;Y%xO*Jo4E<(-SS5;izfG?$bIPA zP5euLCgEjJh^IcC9Ogd*sPL2+vG*ZQ_>>rNF965u+vZw?-7>->&2@pfHsIPv@6si{ zRl*j}&%24IC!HMbp9hH7PiXStJ~!_A@PS$-zNyJOL*yg;t2FrtpSySIe9)PKDXmE`2>|Xs_9>`^j4%%{?j_sD4#oX>EtM%n{R!% zPnI~Mvm`L>SnARKUo`b-pBr!KTYY5XD)Ek{UuNlL9h6Q^@TcfZ6MXJ<5$0xAAK7Y3{7q-t6J*j$ zfOK-Aze#7B=yNxVFt@7u;4wiZzN51|X0sr5l7CQBPtxB$B+Pv%Qe*EZ@vNrj^3YcA zWdB7?KiTJYR604?=Z;e!Y%$cU#Jifje4rsuaqtJt6#rj3&lH~0o$$ywd;7E4|C<N8?&Ouu%)a8GOngr=91CSw;yCOS{^=0?a{nGpzuc!oF`Wdg>FMc9oDh}&5TakpR6-o?$aTdPG0WQ>DQMIyu?Py z^QnS7HsclkMxF5rpU%H@@(Q2MJ!agBwYKCuT96Y&AM)?knLgyxxks38J7nU_yG}B_ z+cncl|Afx8(x>Y#om}bDGuKyKXNfkk^yp#65LUhq`^7+|lOOi!p5v9ix4z;aOZ*|y zlSBC`n+pW1{5d+qDxaP=!t|^4n~PyJakCWisSx>%cQ z^rskNpA3;-<=?Hzukz_YODC`L=_Kp7mgMQ^aFV|rB46$QRFkjv=_gAkSNn8@^%d7u zLWwx#!}FDYweJ8*C$IMD4&#*`FJ?gNiV6M2A^J7`1Wmujr_(E)T;tQTMf$ZWkrevv zA^NrcT1~&!r+X`%TfIT>-=Xm`8uEOs&sOlPnT3b&QOWFMVz7$d3EdjziRS2pI)hSvd*X5sow~aUo7ot zrX{y6qTU|}R61Gj)Az(HeM|k0Qlcf2=b9jo_VA>W>-`lv&w8J(CBpO>^?QqX`bnNI z2YJlAy21a1&a=U%!zi8H;L{h>Z#(l0l03gD$YYlx4gNQE#s;7Mpmegqr?024_QNFZ zb9<40dSu=R8~wj)`i(waJn7^{pWd6k;*?3mrKnk<44eF6fYQlLK7Ba6(oNHE3?*AH zMsBy{@+6&3Hu{(AJdHlRHH7Jp=|_J_qE_;JCCFozM@{~xbe<-k4w-ba$)~%eAH5=p z+a=G>Z5|{y`_E|dW}m(m!gQtd6$eS8hv<Tyr*9;WZ&V&$?qV~guf*W(%UvE` z?m7%K|5INNe(nQL{VDU*w}4aq@p9KUapRI=0A4D@rGh2V>ypo=`qH7{;SDc7dD9c4 zpN!=3sIPg$%flO9d^V+n#t5U|Ci3ux7oWQ6unBoU`pO$#9^UX`fpp{OT=JoHq?$Lp zJiOsWsp;QI@xiu`O26Ud;SDb`q3@?F%|Lm>%flO9bP1)jLAsb>kbb4h!y8`YGEm;| z^6-Wiokl4>8LGbe9jA55`;Jq=R!%pPNWzC?lZ+a{8(yptdYAIa#!#9C-thA9hF1-U z=z2PvNZ#=B@P-$Kp<7DRsJ_7)ULM}?q6TzTrD*aLKX+pcXWsDg@P-%j(`6(yJY|dF zQ0fG4c=3suj--$uh^-JWXnA60 zuE|u+*RILb9ACR8Q*(XonoMDhjJA?aUF2)mWNN;zU6ZMceeIe|E%dc(GPTIpuF2FT zJ{wOuwb*C-NT+Ii?V3zo>a)HFf2jh#;OXVf;}9W|_s9J4j#n}sFBAPI1}`6R<|j{v z>C5q@P6C@I!S^wg54aX8Dn}faj?Q-FPjFI9PL}igR9iN*v}{uTM8T!XoAJdhf0BGl z+Ars)aQw+m(OVaFHTcxetE~1&Q{1g(<%Kd3aTmB zfgdhzf>>2fum1+>it@E<+Ur(RnpuvY${~1Lx#*O0NnL z_%Rglo$dI0VT;4%_yAyQt@7u{=hYt3Ov$Dedj!yFuHcVo)&@6Ea8GMo)0%de@j|EP zW3!YxD(}RZ_vwmP_TbP_@IGDfRi*4th40f9uj$F|qmc^{I0v&vhbmsz^9_s4zhqau zF|!SoAMQz zfR{OnUlCNcT)2#|DIHSDTe8{f&HNng*Z)lfK4XWbT9sN2)6;K^( z8XDOSRq-2woHg`)vPB^IcNM}E4lNxB2!Z4Y%`R`>(9+hi8q%ubx17FD!x(eR8`$uR zPdPp2qZRKC1(GlRwv#;wl94o8%)1xA!ydzrZXzk(0b2v}_Bw#u9|G1c>DLNcu6-dWC(v5B0E3NI=s{AKL2y@<7OOf=6|~)GwPEh`LV>IEkad%SC=Zc=kU@)Up4?t!_{+_PkD%1!o0-aDtjZgQ< za=MQ;3e>l|83!bWe0oSPHa0!d2Z7|%Lrb}(ge;xd_MSLFr625>164uf`1IFHIOe%` z;pe=|^cTLpOl9Vu0LLOCL}o${P95KZ%NsLbs>-Ua`p8p}7>GPfqlYpk7_GIzv23s?;%^UQvC4*(NBK69Y--+*Es%Ns#E zWDq`{YE{~p>lGR7Y&}0ksR>?YyHm6ncM}_%*K@$h>~MTm@Wc)5G%B;xDJ7vXA!5Ym zO$Z=lLIV|*BU>B9-(n~9_6=>C@m4#V>-esjZBCYrz%TDqnQNWc5EPOvujTy0xNMp0 zoRS{_RR%puaMc6CuZiGfgiSiDN(SNMN#HVZ(h6Hsk2#t7Q=vuYW|eu|(YBii<&JI!9Ydj^^I#V2xfjBF{`aczHHviU~rjV z2rh*cSVL0-s{Ta8)R4rG&%6>zt-646mEoQ zf*A7DWIQUAR*QKt*s>QZ=@Fn!wGNq~yDehKBOaxhMl=8I_=Hq>1EcmKSXbtZG$pT` z!)WF`fr`rYSFbbgn}&xX*d|7hWdy=D5I?d z%dSi`q9;`}yU0ea1x69YED++l!!MBmQ=vt|%`keq1EG8`!JM15wY5q&^1B z2D={1jE@wv?X^l9MhtnjVMIRiI2t2L8AjEZ*NiMN?@OSIc?tcyTjSXpVji2Bi6NiC zJ0K*hT+xbwN{z^Dh-5FGfnhkCX^a%T4>pstnWl*UE8IzAKn!^jsG*$KGl(Hy1ISYo z`P8B^t&zl|Af0H2m1`nC#WGnDC_dkg0EF6+fr|K`qcR(93&Iey$@X!KkZqCJ{ou|a z`182NJW66>$Y#ArfkcrR!Qk@+0|*stprWA{vQru;DaHjv<7Ue- zv+s=PslCkBDyE1?ca~70dQrvSq$=3&rIgwa0{@u>tS8pM#_0j!#|n60}k^R-Ck0t~E`1Q*tA1LmPfvI3Z) zdf|Z>@_NyLr)sP`0BMEFH`Q%hjpyvl!;xYlibQ$DkY_LQbuyZX%6ub|V)m?_1RsgS zj#40rA)k3PqGw7aG2}CkMO=y-^C(V<%sH9gL|l&FQxZ{5-`SG1{@CJ%SxQY^e#z$@dORa)O%fx8Uvmd#(JvU0Oj zb>q#7#h0iOO|*E)a@C!8i-32XMb9=D(M{8IFolOx*Oi;92JVVm^GU(oQ^z z{6nv?Jv>@;;A|lxgW!qegQ6?JDqDKdoON|;;eGh0hRXogwRbc$!JVx9e=Xq2(cj|i%!94`q$AXiq4 zSKG(nEgSeQmmih6eqH%`M4ZwR!~|0Zj9w1-IMBxaP_IcaY&I!BA*l7`>+71amxedd z;0X0S!EVr4hF;UyBEdEwJ5C@rH#9RsqTn_H#~|w9QVS(gg53mc>l$52zF-=4(RHnw zU$Nkt3{L7VEy!j%zwoew*sOYov3~QSkII8%F%1v>O(q&bt{5}F6!?7oD-Ug)d`wH$j__V>F zuIc&-?u1bb{FL8ca3>8;2nPuAltH#>junDDZT)cr#UFQOx`e>@2RV8cLHLhQ2z-CA zP@${jL*V-efzPgkWv2;&?+_5$IugLAS@Q(2J6ML$WIRwWvUm~$>gPBMCfDs zPb@r1V;wbuJ=aGF{9ZXSVmcyK;QoC2s%!}SnD?JZm~_#c70nH(;$!|QC(%3?V?1l_ zO2_B2dm^5&{HvT2J~-i7$Y1SbufUi-u@*IXwbN}6r-Ti7u}U6rCc?e2*2!|=GO+{b zTBiq{t^@3RQ1adMlqIcmIFSvSk9lB84MzOS=E>cnCDn5mD2GViUWggN z+%CkFU~jL$tY9gs7h$B0Y4AecFI%{v26Kc-UcPh%PIOvm@d8d3NV;g=@)b3gRWHJf z0ce?pk|u3=_3RZjm^*|L(4u*mKLlEU`9tn5Trh9ZTudUuLGons5b|UVv;fnIP)VK= zLYVx7b9YHwbRlLI;4#N7z}zBt3o)}W=Ze`2F|*(f^W8#BEWBGXccJRdJIr_sRXOi4 z(JfScc*i+!q3X+9PI?PfKYhDo=|a_C-(lKYs0Q$M+5DvoRE69vTA&8&(BlR7o*HQY06YXf;aiSd~H%rx6-du9Y z>;;R}xZrkyIxo0isK)c2b8#haW^*o{z&qYdHI+9P zUs9u{@dgWu>AYe(KVM(xsS5sGPo;w?I|%X8F8j z%hhaqhvuZ_5SYXDz+8>4Ua&|*^9U_Pdt16#U6{WguP(|1m1;hL3zsZiv}8$*T3~>h zrSodk#RQfkNka=Qq0gC=q;k6hO+y4?v)_E0E{nNUAMKawi8pi(-7qs z;29<^K!(D^)l8d%iDUtvIxn~r;~V}q@6{KCPP=e3e3uBb)es%Py#@q}n*j$jz%kqh zLNKJ6jjI`$6@d;Adj7BRq5}h=E&dE%ySts&QsvlErmGm-d@Vc`T@ z#ZESn=rJ^$Vq1dqUOaJRP&kFHNw*m1FY!d6wibd(x@kGD#S?+%L6S)KN<2|*jiQrm z>vVn=PnTvSlfx8sR+Yd4)ox&-2R-5XDw?i0=)FuSdDVLZ{$y=w|$cEuBuO2X)i(Dj{}@x-uf0Tv^J zGd-RtONX(GNIN;6Ncsg>(pEy-qA+&erN9o2CqC>IVizi>e>{;%gt3@lobq_$WV8SY zC3?ma4@bgCjCM{Yo*0c!kmxq8P0q2`#SQj1os;iPqC$ z>}<|m&f!?%o<9_ziG3iJ_zu@ofrxtUa}LE4Cr^dZdUAB`0qeKIXilEa!C2x89EbuQ zoLij(vBXDS4`VUqD`!7Ua>s63*RV;Dku>v%gNzTexBKEy7TCby= z%VLSIJsU>DDxh8(OI-f#E@R6)Wn_+aYo^#HF#kf=tRK?ID z3qNOYEV1xNmn4)?8cWQ2vB{*^H1UJ~=$f|h3d9DDCcgf~ zvl7s`qKSLH&=rq*y(5}<`aoAaOm|B(@$%=xc>U1gd?uQB@pFQ%!n2XHF3ekdy|X=c+*lpYjd?bAS~jQ1 z##UGwdH7ef4AQhgoG(PXi4rHb=bksUDweWpe$g^Iv0c;zLexBc9XQ)2(%W#ZwVc0X zIUnDiJ89ZcA?JH6=VOL55W@KsIop>0pCYpQI5|V)M@4l++EvxIpY$-LpENX2Tl2hm zUG7cOmsT1+QhVRDg&#GA10jWhy#QabClxPq3c&hoMkJlI6t%E>_OSE z`%AX$-6G4&7Cy7B3bAW{9_=|@H|*2favvNzmn5%RNltB(mIQ=Ia)grD@wM4V((^Ja z$!k`UliRc;uiKJOY^#D%-msPZ(zfau^!(t@+Tb|UkqZBvE&Z4&9SAA?@O3KpF_Z63 zof~<0`T z{$k<1+ob5f+KN4NU2e~Vg-VG+@7S{U7=?fkg$~l3c7l7|$Wnc|HRnI9EW5YacJ_fS z{>)Zw;eT5AG+>DLFAJaAD&qayinsr|oH~3i@tl|$z)xHLCUNk2e($Qc&xDG`CuZ|RBlV(Z%PM3O5crkSM<2#J0Mmt z?XF+Uw7cC~1B!xn*WWTdvxV)>u8f{GbzS};tHKbg!s#u#VuxCpPXUHb!z_Gqi&X6J zm>E#cT$`KqM4?im&`4YMi7isGK!`%8uZ1jj0hcned>XQF*d8y|!^iq)%SsE)t%5gT zLM*#p&z#4%>Yuu{`cAV-wZnT~uoV+rXvH~bOaO$K;N-O`xA0r%GTVG> zw*4j#5R&Hv&1P51oYna^{KF`0GnN@kY*~Aeuc=8RWa__ZOZ6Y0k)jq$CUsnkXtJ4g z#+F?Cs8C@j(|_8e0pByQd~T5;sk0=_s4|f7M31}g^yaF1Tee_MZO&~oSqdsD;Cd2V zF{Ycxf`^S(MXQWf%dA!>Hdk%N+9`mKZ?689$+X7E@(4}Q08@ZSbUL=VszEXdd~|c} zl*u&JD!^tFa6LjDhkQrO@TMhc7M`Nf;muXe!c*Wwn{&rah5`)(o(Hvt_Ib!^_+M7T z%dLj{MZ*BzyScjbyCR9z@OEaRh9DA+_K1c7ynAzQmdRA0VZilFCp6q)ND4FriK)d- ztziJ4>dXy)P6R2?FyMI-JXN)Q5d6BS!yjQOtXt-Xt%fH$bsYxq@y_Z-^YpmZ*m^57 zQ9}@!I_%VS7{Et6bGMsJ1=0juk5I#(8Il4GL1OAqGz{QFow;4lpF_id=RvKZeFC;0 z7kKC@qv2|+;eOFDfcJJ*A2W~5O-93&%tQ@ABpM#SR%;l*$F9x&)npQxm;tRc;JSwz zp8tX*o(Z>7kcfu6MZ*9-(~*12WLRV~6!1LV0d%!}^zSrvIDNIzu-0mLszcXd0H5s0 z4g7&fGR9=8Vt)aFNOGb>x26C--jVx>$*?mlNx<=#mc;rd_;EA-J!>UdZzVY@k_7OP zj@*nNi6jNJ4gyo_B1r%r>d2ik846lb!117##5zyDZzTEh)y5{9tR(wIk^tV@QC<0C zk;K+|4KuOUL1e}vsr3Lpa&7LzCX-|}wH|QY18H)18E2B8lGy`wI0AH+qE))MVS+TF(?M`@%G$1#ursE z3BWNT@zcyx^0jJt>cN=__3l?vg|m;(4vTkaNjRvp=)wElc_+Ofa^hOc&#BR&=4f14n@NN-g`}M z0 z$s}2s0kd|%^>iyVeAAGek;X6MH%LUoQ?0rV1NdZXZtrWttzgy;c%A@HRc-e$?5zD~ ztKk={hR0iV9R~2R*4z(X7sds%HV8zLqasNFA8F0)ctbK2%-R9R!&(x%$6{ygZR?G# z@3N8{5=jF1U~BHJH-&LQt%E=$*)Ng=@ZQ$kEx(ft1uZGyxJOH3_kirI{oxHpk}q3H zc8eqde5R%Pmv0GUTkCOVVy%NnYJI=ddI0aeHW&N7WRhP~>jBr(EvWTN3`xPP4H8r9 zExOhN_+(4&J(Ho@HWRj_faeMDRMmF#Yla!+e`Ynj&uVzQMb~-&A8XOd02XDA0>(fa zz(-ngzk6HMC>VwU28U5_wcU%ez5#ryId|V5&rxo`;AAt(wcD3-jh!#p zX!L#5mV2UE+c|)bOSyoh++$L103U76ed^CrE{ zVJSC&4@tRzrQCy3ZUFCZ&UOAp%AFoAH(;=r<=Rc$8%(*$P0+U$+aKSImCE+VP0f1M z@-4d<*mG@F2OJL1#EN+Y+1+>JwX;_agroXsEF=3PXLhP;yJx)DufzbfYQhxYgi< zl=Kr@(o43apW2d+o05KJOFD*52Wo+Vs0Hp*=G3F+;Q+M6>@s0Ieq*H*VBNc50h;iyQy$k)638nS&NpR>o$u&+hRe zX`hc!MteZx6Na&ewk?c%#r1jo$iAHB3sAPU4mDN3Yfg38#r5wfas#&dKqPf@Xs0$< z03Y0`av!*JwHyV~fI_6Xhtk+HBvzU`0%`h)H2j#L76-71v%jf&NK6=8aXOGoivuDN zXTOLOz$%7hvQTM#C(lBfHSel{4JJH#Oyab3~_r@i@zP4;kB2JROFy!YnV0Cs+eM zB8&t0#-{28Nil^T?jD0URrRP(5J`tT(^v(UWe9P)QB{B3Wc#>jUcY8Ge1ArhiBokq z3_T_#+=Cv-RtU~w=s%!SRNEs-8;sbG2VzgLVjmW<1Nc;9^_Auz(-c!aq8f@e2j^Ein@dGV4Pbw^oo2|ILjaZLhr38d*J)D9fzB$lWQ2wHLN))+?<=ZoVEvEdb z@U~Pn*KOfR&`aapxz2a@o!G%`o~2f^H+RgwvjW5YGK)C5Lsi=|h3}Y&^=>jkuCbNv@;PYAy3rzzL&9crQt~5)vjgv3RkQv==@;YrEg~Ef*`=!2^c4wyW9Y8T(|yg- z?cbGq(2(T}8SIY=`9{20=7KYuq(Xp@3OTj|l7G^i@O;5!8VSE}mBb)%o{g8uHv7>X zxd#p1J(fAX8IM)ebMf9XiJS&^yu|B#&mvB3s{WD510(Cd-%@Tqg*1f+VwQk~eOay<>zAVZ}ozHcdxV|k{kA2r8;g`ZMugcFSLj%}64j1hnkBOF0J z*rT?qOiTF}^I?(kzOAg=c2()V*MkVa?cuyMV3O>PcmUT%wZ!M5F*-P)Q_sRCxky`n%3aW5Du2_mdG~Y7GEDm zzp@96?a3HQ-z#C(KKGDM%;UR>y^i4g4^JuCli`bSAMba#yhfk92iNAAH){9JCtc znuAtXSMjZI<&1VSG8kZP;3@AhZjvvcME0$!o_dFrV)qSaZP5({)q9?s5GxDM zSjE5{&c$xAImorE3X6k#b|w% zA>7ujilfd8w~79>hP!j%l5J>q7=>JS7zy|W0S+#??qq>Hb)n{>V+uR(MEun&rw52o zgT_~{IBEAa{2vVXzd-(rFrGvPS^Hw$_fBLy$!TBoyLTd00%fb(l=E&x2Qop6&zFtQ zy+@$ZG+T72WTV-ww~A(;2ufbDT}pnvpybyhl}0m`{CXrOP&W5F!yss25asPiH%W$* zN9@qR5PZ&y6h`bo#M#oke~Uh|3s(qh{e06Vv75eInxFpey_xqaLg3 z{z!i-B3t(Tk>S#^y%}88+#i`PJwB`51P?^I33&CKlToD}0uPS!4@J^E0)k4+eP9Y2 zW>w)#_4SAzf6zTJU=KIe8fqwBA`?aW+M8kMy2wyIeW0=CR+((CxROl%=VaUhEM|nJFPdBv&D>DMF8!HE`abZ8?7O-O zuP{0{M|7MJ9CX}OefP~$$^)j95@=F|EVo2-z#@z)s(STap|P#|eA2A##Ajuk{gE_v z=UHBrJ8I~v4KG~{2Sr$Zjb4vGfaO@@Ar7(d3?Nztzu zmd*k9I+$8d0j-h#(zX@XAcDQ#;vAttMZmZ$A!b(gJcU7dj^mt6>$XylDz9`)*WW3Seili3G8KqU2 zq=&!&{eRNou8)fj@L=jc=fHf_7j+mFv1^POnsKF70b|~%Km&DAP)tk5hB^c^ar#H_ zvNv9HH=M5zIDg4-?jIRp#}07rZ^sG@9fU46wlRY#*>`Nf*Abi^q3W^N|C4HueXOf$ zgLjK+J@VB90ea+X2LkknR9gYGYAoAo=80xg4P)J~p`CMJr(x_xhKDrsBGW=P^CAlZ z#*5}5L=E1xL-0db>SG@jK_3n*6@}4g^}jj;C6A(Q{_0FH{HniXvdH3Csn;PuRU=jn z?>fP3lzYn%Ei`G| zoUckb|M*DPa=y!QAmLY?A=1CKc3*WSm{m`1!MV!$T0uF>^X1$r)-|>vf|3 zPtEM>9LRnY>MtUj$P>V7r1Qx@Cpnh3mr4cR#eH` zxQirOCDsWGc4L;&tEt6KcNqq*m~$AoU)=~iR#P>OSxsSe@ZH@a-&ku6y`EU_nDx|r zSx*2KMpuJORz_j~go%c~`7FBt{lBwI!TOOF`j4F=!8?wK;2h}jF|p8q0t*cY#uBm6 zfG!pq;LJBqP-3A9XQ;?*Ei^E&kTwp2S{UQx=9)?>G{X7T2zbciGcDl22p8)v8@vjg zl(zoU9iqyQj4_=9FHjXOdy|fNpi@=ixJfzoxdfvi!^9zQhQVO=rYEP^!dFyZZfsO) z7=Hz9^;)W%6O(3vs%$hw0}YWTD6s@s(k_I&t!?xgy{KoCE4PZcovyX~_x31-xAC19 z?S#IFvcEXetk`F@^5gBw`LXtxpli-*HL@Q!n5$>Cih4gWh%2fOn^Ll-e*X-I{4C+~ zGc$11%#utm8F>CI!}eu^$W{N=a2a5fyH9h$qW*+709URmH+h>V^eIC$%lOfL)kEB9 zhj-<^Y)JZ85!*}B(7 z{mT&W-7Q`D#;S*P?N@IRWA!y^ItM<4r(M?mVLLD_l4?3UUdDHC5f~tOu5^R!BDAE3 zE13&!i$zj}51S|8irh_x|9@CZW7`+GA2ExH4IF04_Y%DX?P$ULRJXnkqxpWWt!0!A zu)&JDW~+^p!1d6dH;WESO&QLC|Dq0hjlO@dh^Z*%{>dVyw}{~v0MBBW1-M^k;raVc z9juEB{VuXJV^;bErI}JFV{`leMxGmtJl0k19BBTemFE*?IMVWbVrrp0pQtwS7!m3l z@yXD@BHJj#R4qd|VO^mye$gq$un%s|fxokGtcSPRWe`oVZDL{3+h$r*V8yiE4oZP3 zuDUjVdgY!9}n2B9Ac_@u|BS_vQoxFPa!a6?S?gNl~WKCEE3iC z6DROKi*GW*w3QR4RdhD%Z+x%A2O_#7j+lD96F~u;ix#h_m@|5G<)n&f<0{9EuNd3Z z(b-%#v$mzJZUTTcZM7R_Hn+eHu%=?{dKDda9%|;i#_bI)<7(BM^H;5C$HUF4rE40R zTAEiaX|9{w*08y*Vr&KC2yI461LA8{tgEYl0|m~&hBd3!)oosdz+fG#5JIa#9W?@rL<4y;Lkc`oo&L5Th`aY7_LJ_nr6NSY@MSw!2;{~u5y~_tDW1q%I6`fwb z16sy;f6PV1`#~-$VlyBYLGEwyAfSgxd<0%h;6Cw1lSHVbUd-V+}0}7x zzBkIM@q(cDE`r|g0O|_Q2EBI?^#0~zrLOjL(0dm_@85%4{2=q_Xelm&-oFXe4tX}{ zy^Emte}w9XJ%sjZ#g|?Y^xlV+AJI(nLGN7zy(j*NW-Sw?i=g+!J*{y%=)H@e_hTW! zQG}gFaID38G*Ho%Jtm{B@}CXWi3`jK9=)oRjZ5Q#NcYioJt?S0<|ExlH)gH_qayD{ z{3coUt++|?2S{!~3YQBJ>brwsxS}nYhjfNVZH5mNBc&w6tywzKg7)on^1- z9KUA{baEt{B2p>d6%$qDeHp(llYFnp`>JJ9tz-H{uPqshlp=35ev{0#0RNI*^B{eS zKT>o-xcul1*|j?J2K*LZ8)VdCP-c~8*?W+XQCV79!sSPA?M~uuhX;Zy!sUMjK%Bsy zD8l9c9__%BaQRV$%h!B79WFnLaQWozX;8<f#>w(QPlqJ77Nto1|Ir zD8M~9++Ltccc9Rm`#_c)dzQI}i(WutudMs9e=TmxYzTe#>*YJqaa5U(Sm1u6oZZMP z3x&{kAJI+LSG~&I$NWc_d6RMGmdYUKvB^yHE6BBhRYdjmmvA zkwd=T=;u!+SiI^Pb)PPp2GM#&-J|~BfhwoX+;8`!kyJTN=6**55!IW62p=}wZx*ql zdYcgX?zarcy*Kw60SZFsyU!+m%Hqmo7gr?AJ8lmEXvs9@3W2mg`~tp#d~n zSy`uYpNdUI{)#e$(09KZqY0;#aqGRa5e{khxuTE2S~JROF{ayb{(HKbt57Yh4RmoG zIX~7XE1gxKzTIgkCNkQliVf+-_SNN6$oUBRu?Ktd6FSia*!yhjlp!Ye^%4%C?!WNU zM{jc|FJ75hiTSAa`dSsA(1TM`?^YF`Sj5iXyI#d7b=!a{>D{2>lQXk;*R0}G(wxs! zya{H=#t}iE+4S@lFAGg?1oG3Hg^HjiOEeMm<5S&Ufcn}9`tj=QPXL$S0p9W1?ta|E z_=sZ*Kr>TOLmHps-iy?JU)ECGl9`D~saH0BTe1Q-lK-=@Q2x)xbpA3qh!MZN2b)b& z^`;jheruAY_O_E;{EpZkS#pfbPQ9uzs-;5!QCWs?=J~irZBhFXE z5j>xttQ_FQ5j_815LTGr`Edl#XRTI9@ccM}=abM_4-xW%#X%fE$a)4U@+5eE9KrLM zn#9yu?|Yppj^Oz_Aw$*+g6GE(Jbx(4ErT8#k)(%$$w26# zK;?ty#}PcA1pQ4s`8eXq`nB1CZ2p8 z@#IBli6HLd1CA5+^#2IMMHDktt3(j0_K^-RE77^n;(o{hpZnUbZ_I>Or7o_xD6`tC4rV*1X^ZmS%+T7c@0)Vpk-p}fYE`L zT?AStqF$5eK+7%yEfclg3kO%0!@LBAfZlg*nkhpk>|)It81%= zMI!w%E&?r+WVfdSE#s3Q8r-8n3AF4Y&@xH(dOC!%i$Kc+_j~z3%Ps;f6L*jW3l#z_ z6LSa;cM@pXMWAJ34x?xZwCp0#GBHQIAkealK+8lOBXxT-eW#W#5 zj}5f!BG58%CyZJQwCp0#GI1vjP8cH4GLfeYQU_Xg5onpn)Aktby~nf)m13^9S0T?ASlzzza3G+P8(J`d1IXGjoe z*+rn`S-_2m43R*~E&?s{L1t@ghz+#tBG57yH3+nfZixblJU*kRSr+-}!Kh57Idzbi zhCNANVc|&{>!@z*xh?`Ne_r=;rWbj9o*l}k92;o4$ZJNzFrZeVhpkzsobjHVhY`4D zA_laY&D+#hVVTd3nu}j}{`4<*RAVIwps^j9%6Ny(q~SPLGJYVHfPZN?oJiwGGbfyV zBc3q1kDA;g;gFo5R~kGY1mT{+_&G{TBCgM2*zw`XoR#nxH5BY=XrV5wSy;Pl{OX#` zHQVMbo4i`hH~jPd$U7+=e5%9xay+GU5OvrP5!D-R#$jjJ1dhWHakw6donbkVzf6tR zrPnub6Ra0pa3T$1Z5PCRMg{AZ=H3k`}`>a!@rvaP>7zufL>+v00kCd|! z<$7YE4^)lDgdbHCa6HYp!YZd$R8|^KSX0whxWFc^Yi`+sYkNB!Tl}S843~+xXkQt| zsk*j?T7cSHwsqQ+u~R0&TUIf4325q@TgIYQHq>^E#hQlS>qap6apTUz!{>Qy_~&i; zU+ldJbe>mw-}f!J!1rO_H*Ns9FCYN!q5zU036fa23_(hOG&Rfx03mT35+EhbICe<6 zcATUoHFjd3CZfi*)3hOHdQRIDN7UrFZPH3}k|t?ta+)}alSmr7NpliWljS6J`upE| z-|Yj)5j7fToKQ2w`@MHxp8a|5eP=G7y>$I**XaI{3IBUS85r2Qta+^q)_QHS>&oQ$ zN$!hNIsMzzxoKnf#-44RPOa^lx^$`YwQXBc)qC9f1gA&W|3b{B_A!eV+SJx;$grMI zV^a&wV$;ogshZWP$IrhTQLDGMv=6|pQ_OY<`OVZVvSnfslx;kB_8D@tl!Pigh-*J^5 zIricxZJG7y)}L_i`&>d-y7{av*6WgOsblHpKd#q9+?C0-uI880cH9M~#mFdSa(#AM zuiC#~(P$5i9OZJ`RQ5M(-=U@ap}`}gC;E@<8z7>*DEl|F)gWQ%oTL{-iocoF+Nn}d zN@>#RxEkIL?iKzPxo@#y7%g5?|5NJYBnDGH&Q|ibYB$=l|BN=uzSoX*XJXM$l2WeU zCU=6L6(vQgl3SH-gj`h$+z$_oj`klM*n4zrV&M33u1>8kOn$Nd_>sXQ2UBf@8G}c- zI{0w^iNT{sQhN$B_ntg);^>i4ZUH}VV&cTniQ|I@51mN;OjSXjK{1=Haw-p*O;xMl z=($VRM`tcvK0kSwV4G9ZlY1|{mdgE)OSDkOm_dzn-P9?SeHUB4XHNVFn*St_XRrb;kSQ@{UAlPn()r1W>lPl;=h7I zjv>o&xUt7}|C{r=*I0e`6HV&=Tm1VA{8J*mPb?SU{!Cw!T7px}H{7^3SHG(i_UvjrMp}i9`u?<~5qX z#oPbNzr}8aI?I)qy?ytm7dayv2LZM0sAFe=u7Dx%hF@H*>w58 z=fBp}(uclC9dgIlT@l)`W%%fgEAtP08KL)Ii1qb-pDx5}&-*17rfM*Mguh?PDE6*H z%UI*HGndIv_f*RO*52h4MSrQ2-b0mqc6?~Su0MmwXZM6J@sAo(!@{tG5mLo;pc7U@eHB8ZIeD-q;Tn1{ELX^ zJ=a18Z)MwCKHYZnXZ?$4@k8HDH- zT_JM6IsI4Ja;tcVW=>3;o|`#O^qq{YN~lI$rcx$#0o2Z=f9Fr6Q~!MLe!F%Z``q)B zc3`%H@7eP&{WA}iigNr>TiW_r5iUQ2m(_}nk{%H>gMX4Dt)~QmQo}k6CGI>wb9(v= za;Fn9apHAezH(`H^33cdzKDZ}8UMe;O$v9~{<~aF|JdYQxp-u!ukYyT{xSmW#I`M+ z{Or7Z>FUgDomVH%b@IL5Yuh>@e%)WT{eL-ZEGU1SI<}3?o4)MYPrZx?7W#7yi~BUf zreqDAxCk5R;SIG^E(*lY^y%gaHTEQjZgx&3VqRU7(*QVlWdFL{&m(?5Rszcuc~P?% zm-~gw6B82`PEX)bg0#Mt%3Q7f729z$WU3@5(R3}p@|qV`!-=b}UzG#IdQUTVSGADm z5>YL#q%!wbXuzdG!dOW9R|tQgY@m`2K5r8U%Gnv{3(4_ z<3cLan{HVJZ8f<&u>oAVO58vy)9>k z^!Zm&4)KXMsY7<@Dqj(~GBf-7#2G%1J~Npr`l)&e(Z!dzVjCV{mRD-^^ooj>GCk$m z1iflc%(n2Al$6J3ie@1rtrBloM`!U*wQMH2G-|UkZ5u6(nrKPeHcEpkt?6df zNoqARUZPNfRwe5iwGc(;Fp^JLn`TK@!*5W*OBLTc+v#K0j<(SD`p;cjB@Q@41pHxnKL|DCBY`zY?YY7^hzgTUb;MS z>O690k%fyT#eW|@Qg!i?mp^g3rK+GW@|Iz)B*brmI6tgk6FtrimWiiracS9j+76di zRHb0jpq8<3sp6`+ioO;wx3wYU7RyFJ3ClbLgT>(X|;;a1mbpGSq-@_bMd+O}jRQ`Jv zZfqDPQu*JtFGaQXB%Qu0o67&5P0INsiMq3?{QqMU%WL_v-K@1VrSkuz;uG4ec1fp+ zy3GH-w$O@Nj)=kbQu%*oORTBAaOv7r7UiFpXxhDceS_D3VPE&uo(F9wY4a*8^NDR? zzluywu(J3G@{erVAzSVAdG_=allZ<(9I1uf_>_NHQG#jgm`&lMb9{v}|8H#4musgk zPpH9E{@>bK=ak@@`FFO&c_sKdzi(4stH+GwD-q|a1$)ybxoYWj#bP@9d7I=bW?kB? z`qwU8@HLIA`OEdM$C8@V*q^C?BTOnz<2_8J-l@kt<%d<0wk!8*Hfipn1se<8ntI-4 z{)Wx;otL__zgAGe=a#$N-_dZ@$?PSCm)Tgxe1#k1r>dzr$Mdk6Yh?ere)^Qo!>~l` z$eC2W+NJ-y2A_VJJicVEjK!+JY0#@2N`vBtRWPP2rzpw^E7hi#C@Yt4INvjIMjzbs zFpqUz8RcYbN@QSSS4MTZK|}-{<=n(+K5Y4FDvzmMIrVfiBTzkcaq`mKRZDABj97s@ zws#e2PB)ysa_S;gg(Rtbi%VXdZkV!Ig7sa++IZL39P^mp^}d349f{0ide{3Jl|N0h znBDchf%h}#c*o?f_io;=eg!X09&@`AwlFld04kO5a49>|4fJ@GI?G)`Z@Pglm9WAk z>~RU~{YsaxpH>NeqQokfaL6T4Vzo;cNjES|m005vj=2O%taS+|7zhJXk##O*%%@Oh zy-WFWx&iwyq~weMCY9gdl7BKvo?;#w(yf}=*(eqA8&p`OtaHgMS82O)&NDS9sOLAQ zTiQXY%Qi*F8A$0+%4_KcsLsUpYbI)-Lz1tZLZXtX@X23kU4cM z+GVL`Q7Ze7_-zwKL2P0smHk&iqA=Yv_G~%7P3|&{l+H-vcCfQEy=te;5Rr8mqSHS2 z`SePqH`)raJ+m}tXQ0rYS?2$A8c_rOI7WjfP97PU7~OYhVE;)Bh_SR|{l`xX_K)z< zxq}n?2aXN!_1z=;#^I$=tON|~I89bquM)8Y<^@F+xM*0uhZZJF&Y+V$U z;8Q7MDHD4iIDGW@_{8DCQEYnq4o$cU#ZiF+CmGYe!+eME$o`4F$FXA`nvmh~$tAFd z=bl_*^r!|on#vax>mNB8>nc?mW%uvfcal#Z_MaG-IC}EL!K0WbC-^kpXsRqKbL{xh zk)sDs4osXJRkr;wOnH<&aBOg1c14t}sg4Zv^99VxDDl|I(L)$awM?n1C|T`~uv_Hv zf%RuB+4BfIr`$nAp6dr!^Bpz6RD+-$=;D#7Uj5R zDbDBp0A01c&%#4nRK{-$hJV(CU1*Q8z=-~l!GlKzH1`)kXj_IgJUS6T(P*k8DzD`j z?LTxNwLF=&Z{)=O)QV)<-V>>nQHmR={dkhdf*tAJ!-J_+u_F72PL7`7!<&HjNNRPI zaTHQBct9W9e1XjvJ;LYILr~O+4h`CEI55cM)+Vz?V_EBxSqBarAK(j@>!Vb@Lpiad zd-IO%>Pp^>6QijOQT9Qg>A0h8qZ6ZA2@q{0)ftsg;>jbyit77QY|Dwk!@%Fh$CVmA zaTKTxighK69qZpW%-;AN)ZD|8-N}+C#*Yn*;P7AzX>T;ulg!pwx+nIIPaM;iq1)zQN6N(%-e)O;{v}M6U+NXizqxeonQ(L1Fj+iGv^??0?Dur3- zZBa?>DPv$F6Y&z;7cAj=qk$b!wne97qlZo&*qeGTN_H@~W$!q|Rb*mtjD^}6<*VO= z{U;6$98WzTrMg<2aX4_ee*!NYyO8RQXOC^#y6th>-uHxp$(`SoC`otWPVY|SsIvfC z_Cz_J%Dy;w;*kBAZhw^3Kk{P#_~^s|xEef=`Aq=gsl8DFhjBuFeMWI#lref}@W6?l z)cz>tr2&zKu@kWM3D?(={i%T{AIfp~D9h_nQY0;PAj&?_4}!a;PaTYsW5jpj#p8n~ z22zKjOiP#!_e{Jn*gpa64n{eA-jQ`b)<1aMeld9{$_YdS2_cTu563e77{6p`LuzDx z&Y?jkbR3Sd{Dic8sUuOc18VEawdj*N8s!O`#`YaLxHokynMld*)R&?(&BMXF=veA_ zl;dE};{r@b*`rammsD8L{ezZ=vhE^UC!!*5l6KouC!^$GpT6X0`a+a70B4t+e@~mn5ykI5o*h5`{YF@1z?gEIMgYp$mo5WJjjB zr^!o>{l^iw#JH00$FzK2bo51R(vH0;Cn?&*F@0px$%poR@92yD$GkXb6YQ{!8+Jck zdU4tbz;qBJx$eq`z)@4r;sp;Y|2Mc_wF5F?_EN!>PzlNo|cbH_?ObE6C*%i7m}1dOyb zYGcWR`v#N-s0^~GC`VCaLDuNNamJUbk7psUji3}og%1vhEi}ebhPR>bLJ%tN4 zpU*c~qrWw9%v?NkNe;z%rAl3?oM`l=B@xC>@VgXZZfUv0){6WRl_-ewDmwY4L5q52 zU$q<~`ztC_ZGyA1{9fSPY$lgwK*R&R*5+c$GSy+i*-LY$&rhZ@ZDEQ%jv6Fa7fl?% z-m7!C@iI|j?!RRO&*Lw))aT!)vg`Sc_v`Yd%l5b;wy4vovVWIuR2kCGoPWb5WimFY zNJo<< z&%X29`?0@b-u$yl+Nq@9@JTlPY5$~a(kpXyW!c=K+{vbzbTu?Lvx0MlyGX)iwkkDP zhgG*RmCfxed%o6KA>Ngc1fY=5pHJy@5fK;GE;rK*5GY89g^Py4)z zcHSzt#9H3nqRLgeVxs!FwCho=)I8@3ndi#>Seg>GJ5zMZTQiw;IlVA4z0_|^?`{c( zdNDUx*W0278s;Y>VE8U*M`fDo=&`KKwWS137z8a1*6m>UE$vLEiyy6i(9|5PbAw(~ zm$r3Dx|mb##lE&JquNXS8rlS+DZ(My1UJrQ@kE!@wlU>r#WIwkyAeWvPrW%UUKD?ztwmE-XPM zO?|yDVaKNu8$6iUgjA}tDQMDH*ch*nN_EAT4hws7wKL5GQ^gnMVy-4#Te7G5PwfRX zHYIZg>s;QSR^I0Lx`lN#;w>fwu)#WYur=PN61Mrec6k$ZxBI#_M@4tUL0So{ifW`% zJIM)`PC3tSOdpJoFcrf_Re4HmbXZm*{K>@!;XpJm>?@7qRapUEmB;a_B92#;arlbx zs>-2v_555RZ3v}W;@U#=s`I;S*G*7T9}tFy0M8oZyWl1PmL~Bmz|s)dT9SCy8jj7D zaG0?upihhAxh`)>9D+nZ; zR?py;z59;~Zj*qxJOCrdKj0QCWAGos^QsU$Jv^^21mK9DcmNLgiG@4MPm%!qv~U{` zIEPPN5g3bXIU)i_IcUjzPn4@X0r@6Ne3;+nc%E{$#A!v0=?HD-^NWDy2kgO4PtELD zs2TW^n(>@MKX)dJ1&j;7bJVjctG&|>}idI#e5f;Ro?9E|4$ zQ=;Bu2o>-a6K=EOqFI&{u{RQgjT3~61If1}i5|HS?paqYOFm9q1=Xc-@~VWgfCrU3 zCR*XRccr*=m0S1ffFssORIZH!qyyx-B&yW=nb^IB9&NS4cVoa#CE+GSx#lLvOg*l) zc;4z?Tm6XbMry>1;t5W|4W$|7FM-1(BM(&LUP|zk6ETRzM;F8oNRGvQ(Bfs;`>(J~^sWD+Qx2piT7wd1>$^E!?}3 zjS+e}Tx?2U9P?^UlB||+M79+-S`LQFday{8adAL3m&8lDa!ccE&q?km)DeceQf;1Q zT6jX44g{MH(b(la)AmjjE)jeYo|$ ziw*H*wDiQ5P}{yl0X<3JSyv%7f~qWp*dFG4qV-8Mv#F5cZ2n_6I82@H0V0rtqBTv_ z+8U6uKwGxU7$S_oX}iZ}o1@u5Ra8KE&=o&a7AX>H{7`omQjq84kg2A6`6n_GZzM53 zM4bSS6Y0DCZ0%;LC5T8+Fdzkf6#as+-j<7%fg+zu?e$5ypbDe-T>4NF6(UiiaQ_iD z0v%Y(CQ&2eVjzk{jgUK7Q6o_TK35)qaYZ5YRR(BX6`*x>e3>0uJ8>jVk?IO4Qhl5v zHN+`WV{(523tf|=NX_$evAZQL39aFnJuW5W63ut92-K1|9=UNNj|2T? zI1rW;0AVf;gn0{uY@W=-rQy;tJ1wo-t1<_K!*E7lBw$f-`F`3a4w^a!Zjgj0NlCcy0(v zuH;gOF3W^2Z2`JqqK>$ZE7vg}T>@@v`(23J780^mPA^(5R=p<4s@FPYCo)FUsHThg zAa1?h;7Neb4UArX1c4#izG_jsLWRRu=q}V?dcuuiLDk`=qz1D&PJ3aVVS~Q-)`%vl z_O@uajzn#bnOPWvOWYBd8J`OX`OYFZR@~aJ#-3+vm2s)0H$E6CJQ26F@R30CU4;~8 zcN{D&n+*6pf_21#Tq9oO-Yca68$cn&*&h)awEUoQqW=ShWDB)ES?t5HC5`~+ z=I2HlkjI^0(3ju#k1Y`y9xHcdgNH~!o5w^ytW8(8;TwuY@7)`P` zK2*0Wvd@Jw3i@=QZsn7Pop?{72CuDf2Ec3tWJM0hOtReqAwA|jex||4p!>&3gLfjt zssQdIhnk1`HF01P!Tu2n<^dvXjO67mj}vzF98P%F5VH@4xFT})G=h4BaET_iFip&Z zpG`PVV!(fBbGh5js(>C;iykawvr5uI8O}qU8P~HD9wP@{NG3f{G(}>Wmb^JBMYa?& zlt9MzBv}foq-OhS71U4)^zAPx;thCPIYKGc0RgB1&j zl`bR%jy2!96>nXFEr@6#%-ah@uK>kQFiJ}!8XMsB@O4^f>0GgqPL(jx%h z6v>>M3+2%Tj9MP;Flsro_ckZWZjT0)z#;s40Z1j#_J_7=`Kemq(NvMyBi5Ga%DM79 z+nXou7TC=bgO3@!5-kRTz3n_vV_|DKs~qFqs_+>8og^a0;a|i}<5Fd=K&s5grOMK{ zR9RLip*YPmaInqKCH^dFTdE4N%p+!XA!;u~TmBH)!#x?a`-#3D(m78hL`6cp5~acb zCUUV{WOYT7hOP`N`?Xq?B$9B}xaKX3c!CJZ@gEb>)`b+yHy1hneFD0>cPIMM5=a)< z^E60l?=hkt>F&OGcO6i0rTB-NtXc2()ZRj%5}cEN9?|lI{(xV#u=v43au{g;lyIZsP~xHAuDB2@&=10de4wwE21c~N9O+cU3aN&b z&%_#p3F;Vb}M`40j;@qY!4nY`N!XA8aOfB)^@$gSZ=|C$A z#x8_U1%8I>C2k|fku}sr;7CXFXnp{WmaK@p2H+SbJTaE#iJ;zD26gZ)6j)wC2gw}vy z&pQPXK$3?9k@}GHi}ug=*gl5jKf^Ug4Sq~;EdfNI3DW``PSl)7_$_WGiU_kpkg=HM zu_r|1Zl{g*BxSMyl_=)gi%=;TO2EGYM2e)iNYf1wk9Hyw<3%zQ;K!mRl*;xKVwPmu zg#7o!AhC!L1f%qQBIpLqB<2-}xG@}OUQdJ2A)DY>6C~CiUlKxxgGP1>5PjaUroie{ zCiSR1K2^sA6<(2GDwT0QB~q|(n1yz{W}#*F%TZgn%y9ztx$M|U_8iUFvdLKNQ9jAl z=0~*_(z^0OMph9pvdAw3l!;)+jd<>$RZSt6t}R@@z*TMmz%4pL1+lMj3qoUo1)(W! zL1>O!5Tf`q8WiL^3qq^&OC>zzE|*}Fqy=G#i~&nMC|GQDqr!d{hy#xIw}ty_OSz8P zovhy>S$}!J6jsDbx^gS$JJWH`SfGuyw%W^Jc5$4|&cb)XR~}PwVQZL4LS>f zd1K&I34-ix*Mi*wYg_>`E1WfyZB%?yWd4o?vL*;(!0&Ari5!LACrBlBIu#H^Z4X2Y z(WOKota8!Z677A4I5XdvT~>|1kAJCM^UdeGeG-vjiYasEbr&YaJkX#MNi;_@pUZp} z5U6L8NJ!2_To(lZx;PZhS!4mmA7Xp^LV+IZfRzstfVlGyvqVxw2&4jy`3g!@u%Jye6;(yyFJ!_oZ6&Bvps(27 zO>`U_)wVgBP;m4vOo-|IiJH$?Yb-qF4}n1~!a)JtLJsX@aN~*uj$$&44r|1bbshzu zAGs6&Y~b4tK}*K8P{Od-RLEe0DD3%w8!=w;3eJ#4Cpv6iA*YC#u+0u|1!eH_@{1&; zjQp;J>fRslQG-IBR1?=gB+=Ez`P(1pp#x7x?Y=r@vPisRah$%obY#mU^N4r_oG|1S zPSb0Xrq>>5deJo=lysb8xpag;EK+6suyIoB^}!@lkTb(-dM;AhDsC~wZf#P}TNhtt zID{=8qZPqL0e0@%h0Z{(o^Jql7E2CTM?)5#5Tg{$Vjczt2MX-+sQ4G51r{=!NEeLc zt{5hX#ym%zP~p`$c1DV+4lpKA|1+4R671&*`k^~a#O#yk92#;ww%YaQP98zd4?dtA z$CS?yLP75my*_IQ1;r!b%?X0@WV))jOjjL3fTv-CXy zYM6BB1V;@+sBIR$wgj?XtA$}!{4?C#6CZkjzY8O^Em1p-b(gbn)Qy%C|-$oi5B zkkg-c1@R!e?KERVbWgl>dFc8B!zR%XablO)xA_Ml;-D;=GZ080(G3TTcOK0=NYT_G zDu>Xf%7d=5rbB>3K!Xz_7>;Nf#~9)R4XB})!4E%{P97&y8CMA&6Q~x@i_aQp zzL0q)9{^E-j_p9KEGdkY2ZX624jGQfRX#p?T?_G;DJ0oPba`8xLp<455GUlN$qfkT zVGyh`KUX)`g`godqn0Oo4V| z%ZN{}5BPLo8@D+^mq zZB8r{J<&ug_SB{O24a`C6s`?-P6e_@JPT6%%=_l7@B-mK1SY~liM}xAu25zVIH|>0 z(SpcCXmyDg*+}qGM_LNFX#xu8^U^|I`~wW{0fYSvmo-G>ATfl%9S6oF5Fv24hnN(Y z-NS-j9uP@Nm_HW0JBnHb)=NI;6rs0J6;q22eMdLl**XD&``#XNF2-Z;f{r?$$K`j? zI1@|ID{1}nqH$70`%y%2KMUt`^8V9?^F0L`hw29?9_fxA`o%6jP_{uExw*Q}>8 z9Lb8dE|D`7nE-~J@Gz1L`Z>(2ABfJL9eJz>AX8*Qh>WRiosa%e2P&LP>ftaF@AKnSrvko90^rPB2gXPic#Zk#RyLK zSmwsvkb(6jxGu$}J95&HDuGB>OXE4^9L~@`XA%;+oB~r~#27OUImc@guv&u}~@^96D~v zSRNOH&_xP`pp}8)VpUxB5iNXLFpq$_0N!8$0lXFD1PmagzX1aX6Be?PCU7EVBMln& zV$uQ#K+fltWCF$Y*}c+sZzNDZyH{E+r6^L8g%RP6owU>IkNv&U3#sVa0~KA7lnJHl zxk43vXAm?|pphrAbiO{GG~($~E+N4b@d<8}4hcb|lSeFWFSQbiJJv~eBVXXhhX5zW z5nU-oPQ)a!S5-h=%3u*ISgjT?1XtdJ8 zJ(E-aaLK7j^VyHbS*9e!IRx^68^tPsnGpj05GI0~B1zmtk1GSxR%L%+{;7`7cXdnPv#N1^wc60pL~pC@cZlo43Q&=# zLVYsX$$bsU>S`R$nJif#xbVf3NM6b`{l&eIl4j=y`K7%r`p{0|G71eKu}6Vn$&R-m zZ&5;BcWnnJmF#MYhG1ZFWOOOLV)wyYMyJbufe-y;ns4u=L|f#QX%EWaGF(E@vv#3%Jdq%9WLMY)hPyJ!SlIe3H(L z$ER;sv+%jV$e0gesY~OW$Cc&#dm5zGs{M#|1H%1~~t=pBQx;(PMv=gv-coms!W>-5a* z)zlZ#tsh{#JKxb4)BaOUYjpp}rqublQ-APX|H1dT&_>&BOHW-iXU-z?jNeLurH0IE9YQbnoMK3AI0 z9BbHPbDPYX`=&eBYs&jf^*v+8&6;y&)qS&(q{<*^)j89C-!$jmGRw!zvN^Nw6SMl7 z+3>)u?$h5D{Piv5#?{1XTfT+zE5^*WIrIDjvv8@FG&2&C6%lgcU2d3htss6~9 z?znGOKQJAA`rFiJ7Tq%WDYJ3dY<^&B`f@Ls>hCO2u&vKDzaO=+{JvT9z%1`8{5!wB z_e?cIb5nJ-T+gmXwHo?z@wu#J+a8#;!}?np ztS;NR=)UR5%{_L7nc+8?;m86@?AFEotpFNww^eAZ-QHCXO#7VSZ`GWs{$PR1?9Up& zqF{a4&yQ*7B~@Ui@tt3|0+S3Y{6Q`#eZ>bie;S_wELWYoZ`KEZ?Uu1!$a2fH-?onx zx6N7*=%)Ubvt^m*>ikMR4shb2M_X%IVgCRPU0drMa%J|}wg7;~wdHHrF)Y6g8MtM5 zY|OQp%G-?PfUVDN&qtES*Q`>_-k|1ubSbE*&V1LgnymfG`-XX}?9<=1eFEtS01L83 z2yz=eC4g3WJg}AG%jKGJf7kSdRL`%u-z$hy^IcQ@&~F2zkPTE1vBYKfP16`aY-dS_ zZhe;CHcjsasjH`b>auw1svtE{_J>bhGi_Gfx4UomvW-503qQagFcelFx~Tz0Rl*Uu z%vcdt!B0DwN-Q(%lKO7vwVH4H)nt$^QGDf&*0(7OnJ=$1={Zx=VH$6mk};FNW>)6z z8Z%}phwqzwrlT&`XUxlHn-XC!&z?WJb*P6di=foA&QJSX=j%Oty7hau4u81UVZDdv zFXEX8uU2O^)fP~-+LujU0yAuPeJWFw9x`Um)aG`DshweJHK|a^#&afr)0nqS?M+)~ zX+fi4ZXZCyJOPhrsbM`=lPu(t}_+aED2dOY?^PGMN?+O6yoy( zW6qiMKQ+zSH#VAzakHdbf72bA5@^65uNMvY_A?srqcd+lqX8*QzcbHhz*ExzQKu`D z7tc;!fy6-*L@{Ndgs2sghbobWAx9pvy=hZ-(=3@Yi%`&}%(7{-+zx4sYkC_ z=^jVis--|?$M{mMzdRwTV{_Q zADVqG&lh>Y6&Z6y#$AywyCT(kjG2QjPZOoFay?L^m+1KwH{n@R|DPcW-Zqurm@}0$wd9&<*T^z!YE9|fbyIQQ)Q+37 zmrN@I!v^@FepF1EO*D|6wfo4UwM%Jh(e0T%OBX4;3%vT@UX&8!+X-PcU>lvy%v z7Qt-BO~<(DeaEbtGWqPKDYGI=>B_gwqH88UW)=^d8cM%pYOw|w0TCHiH73;=Frd8EV_9s3x71 z$*9;R0Uj~icOmINz^PA6dfK#t7!QM7yV+A#MaVEEI{;g%jqy^-wb`}H)IBmK@bX@> zqE~C%IA_e1S);bcEF{r|Fr{eBj;v_PLV8iJ86mNF$n@(mWqS4KHD(x9q}LqHb((aC zY3Vj~4@0*JEO}^I%gVHyQ zkSzU)Ii&~F*J`9O27ats8aWHT)D;oNtB6&m9+;!qH$IdegaK4GB#A$O>orq%CovIp zt|}_BI2(8r-7+Ertjbm%tV*{Yy%vA4PLRi>{gSDU&&8iV@QKOz~|29YR{s2c}icx&7u*K5dGpP4={@*kW*vzi*1Ovm2kH z%6H68rkuNH=T8UA1+nc$bcvx?@>8<_J_WoG6ANDN3kWx<-kd3A-Ev)@yWaY1rZhL6 z>(c*hL&@QE0qN+#ehga4U<_Dv8N@C(c=%76!Ed-`>OV4#yxcQur6>29npq)I!#UFo z#mUv0{E*uZEQwHdyF*i^P3=0+2JH9pRy1oWhE4vESG-Z`nGAazqi6*d(FWqGdN}T z_iBcVc3};L>|l7entyIOH*EiBpG+Hnj$6Y=IsQk&BXbzK$ktTZxno1Ef*{j*Ty(?aZ<&fAQ*D1V-;1R{+o2Ss*dK{9VM&&{kFJiMZ>#DWeplAgn zPG?rtiCBc&eba!QVGfw69FK|6QFA9CoRSH_E3q2DNwOJ)Q*sD|Q=&#dIB$!Oe70&^ zu#3HKo_pWay>CYTv4I7x>8AgHj2~rRGi&Qie%4g8Dj%9EUov zlAn0YOOUNgS&#z|7|zQJQmz#4)e2bOqujWGs$9PR@B+z zbfN|!sA_{%K@eUvX3EA)&29IC2SP3`B=RY(RTI}*uIJmvJbX+>*~2?pd^_5y0Fo+h zo0>az(2zGZ2=(l`Z5F?)#)_>(`o5K5ii&U9H7HV!u{p(>7}A~O#$55N{z9T91m^yc z6A6DYm?eDlm(2^;zBs0LKjL7E@55$lP2-S#;N>Y|6dpq?Cl7dF_4G$3E1ur|lhB%4 zvuMaZD(=D;tKk;K*(}9g zt80J`lG}@Kn8SL2kGG{kR_3~+bq3l%EwGcW_hhi-!~2CQ6BD?`g79K+>h4V8f5VUb@aB?1|;Rxcl&(% zXs0{^LR#|IIh(TNoGE{3D}Jbo^v1&!kDFE9sDsm%??1Lob@x3}H>Lr$UWn-~FRG^0y`~nGby{E{U4jBAN>xZKp~|BToDMe7QZ4+~8boe3(8X;kYJgJz zlIvj-)UoEszeV(8CiRH;rFmhA8@s-+P`W2LCQ|25UB*-;6U((zQG8k=Snd4P*;BI$ z;i8ZWPScO`GZzSB^r@FlzcP77@odVOz2JYm5m;}o&P-oCb)Hm=I_IzX>=Y)DeC8*= z;*B`l)28AhQ+D5E5#uoE&YH4!P0ffYLy-4+ku!53b-;hh-!kZQ<=1fHzo}mpbEfWw z0jl!v?lR`CsTwv7H{>{~d0Sd{-CeV~*J)fsRxN^ENgqnXhpm-lqfO2HQPVx_wBF@r z(~L%xg{ZT`4Cj`*t9n)aG=N#VRG|2GP3e24m6RK1>H8*&fHQ7t-a@9mB|DV4VagCC z-!j?UIV-Btt>`OrkQUBEf@}I+86g^Pn2L8z>6<3qXZFlc1N!lI(KsGjwgzxp;KcY% zjZCJ$&XMFBM9A^}8>Y^3@N8L|IW%MP-!~=X+%r|kd*3waVbe8ZoBqIT%9hWXs(Yri z&omC2I=hDJb95{WOC#;1i+7pTJ*M=g#nYZ1Q~Y}-$F|(lYOa8SEu&3@0d-59gK8n3 z=#jf>s$W-L)r=OYlo5n7iPzGq&M_kf^q$#r-86pBw)R97 z0SrsKV#aN76C|D&iG4h!YBQD z$atvr&@8hLtdIvBO4cYLRU&yw&I)zKDAFtwu$=ukkS)zCihA0a+ifatm{mij0h`!| zrWhSEe?xF~=(;J%0guMr|O!s0+FS$9RcOErWle0+G)3u9#oVO+eoNHtf6h4mPAN-Q3fJNUP}{S${n#di_aRPvsAE;gK{ne}yM z-K;{gHh>A!X8o)ohHKTV>4suru27Yi%&qA_7G+hM2ZGOwN zzH7?5HR0;vw_M*Zo3#q^%D#EuBKOYS?0vnpV(c=#p#7&*6xJX88kA#qu#8ryBQmg< zAr?bCwSC0`jN%N3Uz8>h)2?u7F+JThdx7px1yi;Ex5<4X>t&vzreuh&3knaLt*;>O zY9x0OtqhwXagf(c>rEc-6yyP=;x1-dBhJ=A5L&ZW#|)m+{IDrw7qGO*K(CW2Pc-be0 zjqbVOc!yK3;e-|+XPx|wd7l1^rE(AztmnG?sPbKxq}oc?`ExE_G9`fUq;=&5d+$$7D0>>zO9e zGfeaO8B_8|XlsVq1T9FA(>-HaKQiqg^oSf&yjJ}lrs;N5166z^qS(luJ(7q~1^zqH z{hoW>1YER}bcdKZbkTOR&lNJa;LR2a0wD%dMK*Vjaa+hu1G&#bXTN9auL)w;d20JBcBh@ZrZ73jtU}hRq!{9jKn5&Ngz#UvCf$68)E?^ zuD3AQisbq(Ge-#mC;M0s3x}YS;BfPGQ~P^A3>^9~jV8xbSDZU+;{BJ}{&$(Z*Uche zv)sWZ@=R@R^A`-83y!Ebcf`VLn_ZLQOh>)v#QU!UahRJp7y+4i7XZ4SYq#s1b7WjQ ztYt0*PSd&XnjS>Nk0cbQaoP1lR+vtOWHkQqTIF!9nJ_Qg*g{PeJCH{X06yz~58#Bw zfO7D>(r=jDho%g@;#f)|u*WnT|2D5fX;*GiUOT?Ce2LF@7~Z=ZuAS-NvF0qFx~e zFhFW!pemV$j1;_9BM-q_rcL9^6tewOQTy$r@~ljwMexu-{1cl+e8d^oJY?#pH9p|5 zk(QZO-3+T*$J=LWN-7{t*%oapb!x@_D&ZGhG@-NDhHH13lI+P_rZn5trd3~M2YIjkuG#o&VqQz&N$~kBM8ME$PP<_N#c_6dr{E|Uvg+srrpQ4Z z0PSrhrVpDg(BOMAt(#9X93w&SVbmel+6YmCG7?Q z90HqRFQt_;EH<8wu9-cOfrOn-?M{Ew?Ai^D62E@Q47~>U@3D?y&q;$(u=)Nc565Z{ zWhL!eh3-|L3+Ep?GwwnBeDIidpbe|vu#IdPGLVJx_XQ}{urO;i81YG5iQl$9#Suk0 zP_Kh}I2jPAiHMmpOF<<&r+7WgRyA{G2@LuZQ%=}3oj46FJ?8etzqy?v07Tju7QP0i zscF1q1_4OuG&aX4?evrZ3rnrGDeLIQH1V9xsjjfPJX4f`zQFCMFQ{?y!SioiW1b7yE(#WEUMRrTV6 zd3751vxfXWF3Q&#Wo29SJzGO-GGuP@%9V>gmM#TE=QC}=q1yi=lg74jP0oN)g!Xiw z4VLF{ZLebN{(?8pZcf9)x|{{dAxY9qlm$s-U4T0i>PGNUGY4KjkkJd{dDBg^N<0$l z=&+7Z5yjgD_k?8UM_}s;X3{Y=C~x)(ib1v-0yu8^&YPx3rt&^S6t@+E!!qg51OOpf z5HcX^0Gzc1rJ+JXrb?B=xT>z>eUK3VYg)@A(}vMyOoYrx#YksMGaYGDlYNb$A}v`G zhr76iB*KMV62u_=uT0Ils6;n0Z4h}_k0FTYky(js|FIm|jZ8aBOqm|ggta^|Ds0lj z>H3OE>ozsk8r5(gQ3g9MmI@UZG8Oks_Kd08EN@5OFPf&zh6d=;u-Ps{op*Xdn|P6h zP$twO^e#Qv3Zx;!P1!V5{66!jDTdHBlD;~#qSn-XU>b?(uoFkrZoCcq!Q-vqiUz0} zA}xVc!#LNhbXIqt>@F=e5-^*U&0fL_S(~kAAMTrxY}wo7zr<2Q^~Ox&u-Su@UOA4q zaT^l8QPMPKisot4iIi5_ZRBx)^;=Wb=;pl zP-9FS*li^#-Zo2+Xc2g!^4}pBAG4rDAtY>T4TDYVecM-2H9FA2?Z9AdrDewzHi|PNO~^Y zg2DSECzmNL{?d@DO;pL zoF@XV24JpwWP!a(j0Qj)Hv^b!z!JSYG{e&B7&8(}%baNgy~f16n#r|dD1Kvb0{;}% z;hW={q^od~wNDpYRlwQHv=>9HacMDTvSG|%jA<$Bvv|;jp^fG4+bT>*K8JMih+~d$ zdtj-GWb+|M8!bR)UNB8F=Ai6-T3Bh|B^EdXem?7B(g0%%zcOq{(nzBa)@(58Pt9&n zDyX4AIfRNeJOuc@23^Trvz>w;xq7;gh`_X@G9oFOxE5f@w7-dQ2#e*1qAMks1}YTcg8`_Pjqbok0NP`3AQB7Z zvZB{O*swe?R#NJ3DqIS2e9x<<@e%7gE?H8xCJax6?3RgSu=!~~e-G*aMMPRQT{qBc zf~acWG%YyjU|%=`Ka{5~3sp&H*3?;>1kuf^%+(Wethp*}RFO-Ima_!GsqH#>l%S5a z_u*S}@^i9=aFQd}!FKk@4Xi6$2jYAj03tN0?j72%V=u87SoR6+tbUmLGL4h6>miyA z?YF|2aG>D`FI8`SvJc8L(ICcIr-db1$DO6&02~OE+kUyo2Eje?sC32Y;l4E zmQWADMCe>LNZ z9sCn*QGC`^^{^^!(mV0dGaMxLrJ0qDrsG{X`m=Zw35aG`r4LNKn24a;5?=^`I5IlU z^LjAh+Lz2C3*hjS8Z>y^wrK2tCbk0@F6lf1<0$2z^4bZsO zOmDsE!1^_2T5$v5e1O2_;s32Knk{+*%(V=Sfb>JN_9fFKHx{00{$^w-#3?C$R8)Nb zB{=9y+9Cfs+>jG>DFD1xK1c@=1)GvjhX!EYQl zmEX4}FNl-`Jn!bt{0q}`&Md{eaKo(lSoA5Iy`H-z=?Fv~ktl+4sYxT+0v6Xy6EX#B zs-9{d0(ubnm&`7~vBHt7cyHjJ+Z;0tvO}8;G(u}mg=}s_L#~}>RX;WRWkMh}6_GaA zi@P;$wWmSf618jrbe%6bddg^Wo~_FB@Ae61TZDtW*Dou&Nk5-bC#OoNlk?lvrYUs# zC{QZY$>}($lT+SCNKrLKoJBs9df>I~rnDppdL}A15u^`( z8Fbxc3G~W~ssi)O?y_9N*M#L|bI&UX$R}`LNj9^pM*jU$2~ooISCI{15;m$0$Eh$2 zQAS;Ri!59cZ~UyI5*U_=f`j^T(a*41`;L5j&rhqgjTu4W+gSXfi>?}SXI|bWGc#_r z3gznUw;T;ehv2OUr?BcHY@h~V%p5btb7nc>z^qvb>&m`?nR7xu-F1-kUKe2Ok31{vX2(}j+-}Ej9noybfV%bC0M=&)y!#VVfsFwH z0OrFTD(d;62BUy95^$T)S2kxgq{sHtR@`A~vFN~uY!#eDl6ET|2JLeHkxN504-B^jbBXDyuK3S>(EE8q;pt z&Fqzv%uCW*aR-0`2)e~KLfo}AE^wv=ko&GRlz6TVU^LNV=!R!~*R%FKZw!U7OiGdI!oUWRUF=!{X&_1~tXQK#a%({? z$4DMZ%By;$eo5hg2<4#Vs8SHWwd!TepRI5wgVPI&UoC7Eg6BiC>N@lZI;D#KxD;dz z)o?6~nY(R=F4!yp&`JOlWe0KXVBCgNNJl(@ver|eh)x@?o7TIg9Yq@x7_j@Epo>ji zq4mVeB4tFTjn%Lz*qStV?#>d{13Z1?Z*}>W&`9{T1{92l*$$LF-3_SQ6G0V(Vy%@U zdDc`t!Ii??2f5Il4$lO-AHO?mpGIeOKD_8AZ2YR`5Su+X(>ixy5 z$_T>g7Yw3L3Y001cH-IjCtix&kQS!Y-6Mjv)rX5Au;Cak|5S#4X>#c?XkIx%TjA>? z#U_CNz2{BUd-A(48!~Hp%?7LF_HTtzKs&AEhh+v$w?tuS#G917ll&{UZ^?B|+7q3- z^qN_Y&e?$>oftsOPW5mYJk3xnPNj2T3`+SO8?BbjbNiuWQBF%^HYe_bQ(d=p+>$%> z2)e4~aJ4)82~Cs@m%uQqy7pRcFizq1Bxax2xqP@w4c5Y5Z_SqI?8H2No~b>mS2z~Oe#9tHD`LaDeP|v_f*({%AMd=r%I39hwyDe z7KaHV!ursm6^2EyxZE6o%*|Y^06yzZ7ryHj${wA^w%2HK5`;>b+qed)CNm$oIQwbG zpinWyP}9sY-EG#`5Pk;Rq|k*rm;g=b8bnCA=sE&D%e&1y|26n+H!Jo?v0g17i7$vr z?8;U$5`HLNfiv!yE4icbu9Ic_y%0C77Lbu@G0zfVZZhK0deeNvthi;?&g!;B{U)0I zUDHV%1=eLI{iZ3-9IaQ#24G%~75ffGTtfB{SGhpg^-2&)_O5s}ajcxZZNzTHwV?O{ zf8FHQn+7%sJHwl1^H;^OOMq0)2;DIoziLXc7Jrit7zQS7j75Y7QXGRbuR17>Zi75A z$Ts2wsk3LWJ}~=buS1GNCEV7N>s;u!B0YEHz z=nTX-a8^~;PS`ZYzRnAZs#{7p5rTf7l(%ZI5o0bUD{NbH2+^FPA$)@Iafaay-QEG; z)xK=}npymj4#I%<^5n7%-!R(*>s?K-ug*}Y05!H1>!9<+TV)trx znKG{MU{31P2d<#RTGfvYSLzMLB0iT{V~0>I*%{T(@Q~_PIby1RmVjtfZdPbFGa%B0 z1J{5A*lN#pW%gsAqd3y8q+E!SLxcB0uuPvl)tmL9*`iiN6!O={r+s861PpZln#q0& zr3A@apcm}$RvT&lDIrOf{PT(1U!`AYEj#H`I?hWp!rSzi_jcuv&@u+lpvXlTiwXUL zPVBT2?eZ;V@lB1r*y57@pn)nPI(AxMdk->im#HSu(mSiZZK`lqNo2=!*NhauhLEcs zYT@n`UChXbjf0WDT0I_GQtRjPRabJa$Q$;=7wkk_r2TDOw1XJ}0;%74k~ru^6h3DA zPEF~VaX2?___3t%R>*Rl?tz70HmQ)1Wb7t#4tH^UI6JsJ2^r2Zy^bp~M za~dOIf;GgD$KRe0-Y5sKqE6Rjo|v|lU`lNLa5I^AF^)#X8+ydUIkgEN-Sai*YM&oW zmDa8#H~caHq<^NIfp7o}D@P5%it^R!aoe=Mj3UDV&*eUn;))3e<_I2_h*#%U%UQ++ z9q3Obf5fC$nw|LMEDqzvSc*zSL^$-DqYh%wI=!N^`#l$27}iH-1+@Nw>EyN}>?2b) zFbs59dj+6{cWe^x*eT{C0|57EXyx&fi2TqYEh1Fp-{chE912;RJO1j<{duIZpaf(J zI|Z5e5tmI_wTo`Vy*LWHod>$1EY?MG#uSMM+2=Xa`d!$IlremV&}8NcBfv@6i#;Nk zIBpkMcLVALa+6iaN;T_o(*u3y;nu?)mBGl(-O})sIu4wQxv^ol|CA&y*zpz^fL%Ks zFJgRF8N=;_o#v70`l^@4^!k0%WJ5~eAh1Ceq54fN-!kFs%6Cm$mw46^91HL2BogO` zyUcbR9PRFHF+RQ_gNoF|F(eE@;0xpmAeJleHLZE4ND1M-&DNcT{D-}$oH4#+R=fh@ z$StT~3eaTt8+LElmr8+m2fzjfGV7%RpDqbXJ1ux_u;5t&6m7Hbh=+iy-gg33H%ydY z_^!iKK=sb^R_|A^2x#-jaPS?h#G{7VUuwg29+~IfFw0qw+{;?P;+)8m*Hs-K;2d(F zW!8WbL&j-SgFDW_-eOKuqGxk<7f(xOO{4Y#ziywf6Y2`1Y=GXfzl2qi1@4xDT%1+p zFIZE#Tw94_jkt(=Vr8y$DSYt<7L}n7u4hpavc<}A(SgO>rcLUS*~W-Oex(k_EF#ol z7KerU;~%67=iYATH;rINW>XwBtMqW;yqpo*&6~;n7Jo}Det_N^IRyn%S-M&BIB_f9 zacBWi=9y4h5|xgT__nPQVOqE&i*(qft>Dh|S;Oe8y~!h1q5XodAjTb3_$1zgWbs&q z=P!Wx2+jZ)ayhPkEK7VGLA4#urgIu#$TVc>v3wZe^*upI{R1bT;?!3qahPy6;xOuq z@E2sT^6Bf2yXtrs2wB^OjyOiBV}U1K_eihLti3^k&aq!OVHN!L0KIL*X<0| zUQlsYy%lru9Q{L`BpYLe7QPqZPS;~hLFXts<*Khxs_gZRx?df8400uYJZ1d4S-DP* zZvFm-+4?mgzY8MJ)5uA5$lEZF7ilbz{8f*=Aw zvfy0R0}-$Ph9Pi|^UvJsYqg1YZTIZ0yohKSi1LbDp&jVb@I_p`;<;TSnH8B0wc25M z?H-zKSp>I5yta^ACSOM-MY;BhY-~nVI#EC|xZonvbxyaIBlVfR^=A3kaI>N~A{e5r zWcCtvA-^pA*-9>qeKE#-JoG>bWR;;HuEu|a4kmN?r?8LF3>qv z?>Y2AY`fs zsWe`8P2{D5pn*?;@2;Sy+%VBBZz`xgH#R)?ZH3N7ZLAO4*bAixCon66r%=)+A?jw1 zMWQJ+bEpZ;Us4pj_!E;~s|(pUd#=CVw(vOYCPaQ+?o z!h7Rp-f7h5XRq|`-EYz>r0K5}$Xe?Mch}}o(-8_DS+LJ6Z$Y$$!@!PV>*!kBH3$F? ze&+4Nep7SrvuGhqd)mfbAeoH~bc_X?f3-Tu;(jt{8WdJHGJNeK0%M<+m=RY097%{I zwLXhyBWE{I-iE1@+1z55jhekGOjK{ff9~qX3aLzkX?)RTRL}}?XxLK6)Cvep>3r8fSG`Wt(_YfsBiR+PcW_96X{!zZPBxVtBLh{mEaiz1jV z9Xo_b0zX(6Fu!mgOkPre{3MDHtC8KN@w=u91#eDLX647hQH{mq0{2dKVQC0&f;VKh zn-YR<>~ZrBIOlu!oFa>2ONW@97Tq@O&^azCBkJN7f(}9(u|dm~OB9?QsKP%>+q;zx zomK>x`<0g<+|G$L#5;w;Rd<`R>}4%Cn!g|=ll=+@b+RqDY|O-8DN12tzlLRW-jRkc z(8T^Umf>ed4!)2uk_7@Lf)B{0FtJ~`6va$<6FM*unbt9i$L;ArNoYmahswfFp79a} zO2qFmr?JlxD3JoM^O;-g`U#XsrLy&W1q|^XpXsn5mD>rRqCSdwmzc~hmuw|w=QtGp z3#?JpaA{T$=?Ys1_EB1FSxIwQ{V9@D%okQ%Y~FVvI|gF63><1p0s?K73`6}9Ux<$^ zr?pC*07UvG6a5NT7BQY3-w|n&S^;B%?&G@^NvOw3=e)4k71j_~sStb{r>k-t+czIM z!!`muy#He;-AfMfr=1KenSWj&CHLiUicgldhVRP%NGv|800XIc4;}%Ue;^~Ev~MIZ zyo~sQiA(qIxa}~Aq*3Fx=n%aGQ0dO;w{^+Rh-tY_H1XRC+rx;%UAgUe*sT`MH4)Wb z+UAY~V)^+5+6M+>Tn(lKwK#6pS;sg#)};phb;Wn>Y9efk^cEr0=mDkF^5Nj8&Qjcj z_q~sr(a~@VJdveb#$g23hlRmqdR?wY5i$|@V#^--$2r{9(0 zAQav_VWczt=0q?90=R|WB7jzGwBZ(5uGV4v3lMUB5TOzVBbB}-TqpfAL?1&2XRNSqA+B=Ie2u!|LfsFzg?K#omQAkUr~QG=3p3_2-gvax2cuO@irn_4+ih-p zJeLC%6+^xa480Zfp-TL;M+pQSu!^sn#UG&fDYwHb!7`oAV*3N=c= z1V6UA=&Us&#F!;kke!g{DtvMDr#r<^X=PPK>(G+OTg=|6iI;7U--F@oBD}lStOz(${d5Y1H%kxXU0V#+}%zRYO`g|gpd6x)Bdr(`3MxLb89!5GCS0P zoCG|J1X6m!?sy<^%W0_7SwH}OPomsmZiJ{?M5qT`9?G4!92J0gEZP;v&7#Qp3&SK? zBme_fxZ=UU8ZK0@>@ABb)=CA=v^g+_30AxZ$hZrBSX%2pQcL!(!xGMK*-*X(b8Hx5 zDOOf?P^4hJwE86LL0As)*`RoJAx!3=}I zV_tB)TUh})43h)keO{Gy#{=h(w0QoE1lRDnrQ{>6WOcYKdnMCdYuaR$UDkrNxU{Yu z!x`oh8)dZk+ah2rj-^k!qk+);4(xSbXJU8$fA;P?$gb+Nxg;~GRLsRrxoTokb|qD* zF&8_PRAorolbMNQlJX=|i9;&+Csi>4IWtvLHS_tNbGy-4WLu6rOjRrq{ocLr-gD1A z%WwVuen0rFLsh|c{hHS-x;3t@@pff@)?8wT1T@U&7cir%Qt+@YofO0}cf;$l6uDDsL2%DTg5HE;+} z_G_b2MtLOVL^+)|NEH2Swxh_F12QJ}Ba_$Xd)L@lqP=?4(felA`CJvd3yz3#>{?4z1Akkt=z9;Jg(kk z+u^RFrHY6NP0Fz6bYdjW5w{+jA93sd#%;cjxb>$kBVBa#zWaaj*rAr-5>LJ7u@p@{ zi&uxQ{(xAX3nFsP#_ya-a=AVn_j4V`-859QFvi8Pr@wH!v12^yJkonxwTTlg6lr@i z?!gGdGD?^HV!0IF1iw(s_|~#q9g3DP*2elwX6{7!Ts}T&ez%s*5+=p^EO!QE$eBuD zpT9k(MXAFtmsDp@ndafMt|bgPP_7_Gqg5hfm&pRdLJBi|W0~017Vw^kjslzy_2SBim3J2~&8S=T~tK`T@Zct2mOwO$B%jacR3oIEVeP8iqN zU^heQzH*ln3_@Jx;PmX_tKKU&eUyHTGoP+G85Cz&^GKJsQPWGqq!-Z3-P6 z1hFY`$JpDsLK4CVTRgd~KMUXdxH^YkPqgS|p0~KBm18u6vq2cAPS(zT;&0+>8(Dhe zRh3N;F3gDOA2U+vIjnB>r6wIDetdzY^GQ67RtWS#c2UFWti(v=V4|%GFyraF@tkgz zH<5KIwpr!-$IP2K1cs1yoDkL}I5Q*_P}WgQ_%t036CeCu5?+5%k^)14vk_h{<+rRJ zC(`NS7t2bAyW0lbTdqvUIkF|6-9?gHz{z@`>`I)mxyWyJKt4F3YZ0?W)qHoVtT|Y= z@#yBK=GGp1zdB`%ZMZ}~vpi2C%&gAP|ClHROEBJgn^@`HRu^~{Q;PuLfr>RSm*r|2 zcQp<&I|~@GcYn5A@ndBTkdf^}uZM{-F2~EBgTaZcZ%x)Qi65}xsWn-fN|**qFc(Nm zaR6{+Q;)*yip3PS+iu>P4;;81ZRWUtDI{X_zb(^S@@1N%(&4jZ`Bi1~=lYK$8U4Ss zN+O7zP=_#5*>|^xP$FltsYx0njTU}u`3=64Xi=8eL>4+s4;4r7(Qodj7M@|ihMmiR zW&eo2&JYa8ClW501ebEqfkDiVgVGUy^4RG-9Gy;8Il-*f?sH{a!d#n1C2Y4D>M9vk z$&Rz54GG+o-#7t3_cTE~;xv;?uI9&SA55`i#UBNJ@iT`JuL&X?$;n%c@zr44NMIk` zmrTmGy}8_cwK3Rnj6l`fu$V2E+|k-HhiLnv_pM3Plb4L{^ek&Li~}RiWha|S+@{Fo znZQ}2Q9PEjD+o^FVBkHYzI-JXD_<6&xixu*zb2=(P?k!+;W7O6J4skyPP3Kh^wT&G z=sC@nHL=rVkbC_fmoBsqk>`E(J~Z?4V0glm#pH_T-Ri}sXDM%5N^nk$M*S@3r2ZeW zy_(751a zW=^=@i3JA3ti3&Zx?Kke!DGF^`mp=g{CdkJ8ndAg(YnP3zm{&Qev%KnVo6{Lik#vz ze}jDa@(X3Oe_(fiH5S+(WndRr+i>Vbp zH+JeyXjOhL$h@)N2zG&~&tEvHG5!)z94sG5Zn~^SM|qOPZcUf%m)x7o?n3`b#fmoW53(( zI?&*2Ve9i>N*c=SIE%mT0m;o&%SIR7%I^V{IbYnmNpwx`ua&W*858j+5vPsCd;`H( zR@o=GYx30Ly1+X%X%(?QO^1t|Cl_-rUOf0lS@B8P@KWg51k!xRU4h1|%{>iu*n{}; zmY;u;*4C^E*Y~bl7A>ef7D}6@ zhJa6K-So?=2LHlX@O7fkZti48Ahz_h9eHMs5W|pNG(Si44EKlSGH8MQf}0Q$JhGX6 zfn24|9rtX{1lgWp?}|@gt@8u?`gc?cc>;)bcjYl?rj)=e)g$yFZvoAH$@^ua-NhNl zPkKv#!tBTHP1K@Tc~z5l0B3)&Y&cQYSWdJTu{2OMh|bBtU`BteT)L^;V9wqzcfdyr z!RmvlwfPWIGxct8f3OC0Bio*A9JvB>ekC}m{d7c#Fm=4Y!z>KU(@XP^%h9uS2q)kq)n% zBebBXZi`1D)QlF@C_@Xyk zF!1_#=;pr{mb~BuU660?J7GEib@Mr({wv!Q`P-e{O4u8ITCRi&Y`rCDE_rCAHkR#! zn!U+A=#|2F4TFVVhw}7b1M(5&A)k9&Nwzzy(m>&>%n%jDlL_OlKz7)F6T(0;R~1n+ zhz)`(qM@GgSI9&V1T$Lr<~00h3zC>^ap>xDN76b38WT&iFcwt}Dt@TOGM^p!i7dxx zy6e^SV7LnZhSI^j8Ch3}_8fx41o-&2I@;(DWRhiTN|eIu}A%4rpGo5iyCYi$}3@Li236MD(1RT|$A zv1kP?`D5%&#+%xQ`7&BO)l?p){`&5WDFB3odijA?6X?5yT4%cmEX84I;DgL?+0DVe zEyF+iA2&VDnoL_YszG!Ht=GgauylZm@_`jv8zg^&!K5KXX+80%{-wlO57my*i9Jx| ztuay6G5hBdW(@iq2}s7P*RpySDi5R%Z%tIZ7TPxAMR-}_Xm)>{$UvHUsjR9u ztx(sO0mLL6tMB6JlP?iDPQ*j9S>VTOWx@8s`jPmS1@!vKL+srngYQ~#$=#1_CMS-- zp0Ah9^7g5^N%kDs-(EX{?3_g=6od#N>=q4)yk@s%8TD-WeDroMD#IUUnoM~O$+|N> zpnlA{ zi)Y;I3#^0ra!!#2*-R`EVh7N|gJo)MZe1Y%5V6W0I$*1&#|<7&plCh*{GzrcA8cE) zogNabWe&zZ387SN#rzubk>}dRdq2%IRn9kC@5X$baRhpS<_7!Sx?oS1eTl}IBpFh| z?M#$Zw7m%uE_UHAF~HiV=EdjSMVIGP1NDenO<8|&=HwbS%-nLO_sbq6sY+n@Yy!7D zlUt*Eo!hc|ShAx2nj6LfRUBwEBTuD;;qw-Hp4ochp;Nxr?a{hHTyJ(M2rJhiZxPn! zfyd?J-FEbH6R*uhPPPuu^VA%Dy8#@m%E*jNCIrevph$eSVDP=NGEbJZM+sCcL-f@!6BacFp?Q&hxHDyJV!lL z&4)p6^6ulYB#yk8Q^U1z!MQUx+o7cy#TsIeiw~C1{!Onb!n8}7QQ794O^28vq@m{| zTLT0UJIU~ZUx)x0SOr5i$E|0+Ue^~m7l`2djow%7`wXM7JXrz)v&6iGtgxPBca1r* z^q6G=mbbW~N2R;8Mt>zb#j_4=uhJqP=9K&!hfV)Ket+IFd8%9-`B;I7!A2h>or2DH9>e_1cZ zhwEov_e66Y&`{IJ;P+dba%bk6o0D*=mcjx^+GXI56ea(@5C1USxR^1`t~+3r4g1F% zZ;t51H~}qr@fYJFF-WEYXJy<7%ZX)US;U|neV!1|Z``rQ)_wLF6a#qv&9X?LppVMc z%n;;|!Sm_d3^sa3*0JtbggB)Io~HM`Y1O`v_xZM;7G#^9{J5-2pz~R`hgH<+HF?C8 z*E3dccRs{X1kXGiam~m3K?*DwyqEPf{bX5kT6kg34_C`zug2~0 zR>WMBeCG98Oh=46R?%c{-O~DHaqp(3iHy4GDbEQA0<%03lQd~!yLnTY-QGJ^w&J~l zD^8V7VsZsEK_r9K&i-cwD-!- zcG}QJensUqdPnNCB%v7OdSp$3E)IXil;qrqrBFbvHKvjC%Fj&S+ zOaG_J;$5*k4+XEh<;mQekgaRt_u%N&#&y1)s^4ySQWb+3q4*Dn{$*JboujKV_D)?M z^K6#vW)OWE>tj(&HrE)HH8=z|*gL>L%e~UrQ&)UY<3ZU;1XbTthI(OIBO2|5$*`g7oxzPP4{pb$;gm$%o1i?IZn^ z=C0m4xFS)X-g4|z*BN(p7Msq|SVc&V)!fy1ZSR8_C*&XhxB9f-j(_P|BYs-6k@jZY zUNif<61#2>F$cS39;vs=D1XTHxombMv4&O1G<`?1p8BQ#&&&9cKlFiTH9&c5uH*%9 z0i=r7m_XRp*l(Bdul_)d=|sR2g#BO3SnrEBZ_Yxlk_p|1*IM{4-A9H1D`gRmPG+i= z1Asq?O!Y4qsQjR)Cw#9Jda7)U&V@WB%j-+Tc$W?i$TKC`6Z2VMT$en9+CcB3z$CD$ zLE+He3>l{h1l8MRME`|PpP)Q&?BRR=)CkJ;2+9|q?+D5zL*>ek%Vp1%TlimCc5yMv zRKUD70r$DT#aN9+St;bk>LsA+Y;wrgpS2w?&KSL$qxfk2YL&y!dIYFOHxWWTh6Y3g zB(Hm(LSzh`=Gz9B&nT_T)`n=?bGZLBv2o~cmVM9EK#&_Wf}xJ>Wy6(ymm(l17IJ_P zycrjJ&GgIHfEgULVjta!a0xJm#ZGLlHJ-0FtBfVUu)N zf4Q&7`2D|J7GFa+5-^+_R+ld%$7oI0x<2811g3qWv*To3m_L+E*+$%+wDL>i^g~)j z{!}gX=4h!EZRLeV$w?a%ShY?nm9$-#en{sR0!~aae1oM@mR-UmJ^4!hlB*Zf!-r6a zt71b(`n+}(=Dj@u5EgEePT{QsmJyq}e_y#|mz!_{dNfh5|20nZO=T@_%(H=n&^Vi? z62$JR6Jg25Y}f6b1njVrA_F63v8wB!ja!7dnQ^-`6@=>yFExPFj0}eU+kZsXk&`o1 z9nT^QnZJEq$|~v)%bFs5rmqC~#-}T#e=GW?3^#0imHBj`KPDP0`$mnHf3w^c#|mlL zm_|erq(w@TKbUKSdTl+7f0SgyLsuuSKZi%wk@rsqX-ksy_er3=T4!3k+8F6D%*1qtQ~1b;@!Q1T zi6QOGhY0X|*c}I=V_c^07{bd2V8=DLYJcz#%Gg7M$7=k)X4yr=p5Oj7#hycddNgWF zOu&D;qf!446R<#Oo~z5_$7gHhP@Mg%`tFtT2h=lSL6gXPe_8iR0^j#WD4rl;5E7VA zNFDqutNKat{cL1(WQX3XEF@{7iZ>k+h^>WDsT?pNAw^|Eaj|5Y{(#YrgdD&fQqoe8 z*naNKg5IzBhs(s45DT+5G&r5?0D&Biyj`DmAWpwXTiv7W#x0_@JozpC3h0-C#irr* zVin-E9{RZ4keI(|kBbcuGhM3q6;GRyVlG8b1W8$J$l?^`|;79ey zBCAb1AB1AY%UUIz;lckLCNHOq)TU8-S}Ak10^0S=xJEnc4gZH$C8McwWUHvh(mMro zCNY&Tmnit$+WN-_j$FOpuqs_BbVVBBBvZc?O3MsD|71-hLTuE$N6vpQn_Oz@@y;69 z2+oOCUw(LSPb{tH2xB8+AqAr#{Hj2$GxyK;GzWUREZywzXE*rVw@nom|t~F6E>I z&Mp^=%NpIpR&Qer3;<>^GHB-fiWH8AVObtjX>o_QeZL-&+Slk&hpWiDQ?{c$4A(Nj zgNo_EL&Gt~{UqH*ox}du*bEem6N%h$NbLDgZ{3uBOJjIPPUi zUsNHvj=-h#l;!U?gaCU~#;KU8s=je@iw*w#9zSK3b$A*wI)Nj>3^ z*}cvFvB)v~1=UuCN({o0`Icrr7iJi;`7i*G9a$W^IWrVg>AaXRm@&G4?sCm=nS}gR;D`YV%>&GwQ zSL0ZR^R*ee(Y;x3^UQemHcE1A9yyszhok~hV*L?~nVUxHdTZ)11*hF6r?+-d4BB&_ zJbQ67hyMR_?IOMtgD9sJ_|EotKyDE1_I%dbd1Cdorq7TE#s{D<*%v{l;GlqY^B_n7uVHm@XkfKOZJO#Oj?3AtRrw}ir z6WTEJjWYI~bdYhb6YMX}X`-Mo5sL)v-Zxkpn3RBSOlml6VjQe#^+6o#00WKszZ0Gsdy z`%o!Z3m!eY5B1SMT_(T!$9R#hk;oWlH*)TaEbAW^_+k*cS6L+SAPW+)?336$;{zmE zIW_6jYh^|7yJQTArm4GYPAiTgkOF6dEH29g;m&+leI!Y*RAsz7OV5|ZcV}Kl=91#@ ztXcq`S4<)^vHC<<{QXo~TY5`vVISE~!ia4#$qF{|yECp{E0Ns68Bk9lFvX%cyYyX zCdGgC|8`>QEZgfNp3$LgNQ)FG9^|kv*X^sZyy>LeC?{gsHB>{tlDvs+b1m5~{w1pZ zByZHQe2=)xGY;2k0xU91eMW&r6PRWqJPh7PPmlmI{Jzw>zT|Wa$C()J_C-4O>t%U> zActN%`(Nw$sP!Wr0^6mujwSp*dUePJm5p9?o3BV2Pd+(`sh6pf!t?#wNO zW1cv>n1X<(&Jcv_`(ya~cgt#v#p}sRgq8AG$xlP@OWQUq&mxhRdz2W;SEPugm@ew7 z31-!b;{jQh^YQhJZohv#TXen*8Ba&SW!q#{C0Id3?!JQ^t%ezrM?H=Ty_9V|>W!eO z=5Rr6>zmyfB#r3GN^ECJxbh3+J-_5n60PN>Gg=_umR#3c>wc2Ao`YXsS7S3L%4+)! zb-A-FV~IGOsb7(18Ztu%H#rjB5I`ReRrftf9!Ae=($2h~Ltt>CwMFuJ|EJ94P=C=X zGPVp%I1~?up=0`K0yCYkE&dUUKdM$k78og{ZCMrPPBd@P-ljKnO4DMi(Mb3Ek7fwz z1D_3fT|h1-F~3$QoZVA^VK{weo-*z!b|;@AegYP~;GOLM(Ss!Wt3X@8C%qVxQv)o< z*SGlFv(IUI2UF6+v2l7z95B7+_%~&Br(@KW^*&xl9OmAN+7$;qr)cZZst-EF6mEo! zJ94)-nedMRo$NXO#q^KyB-_pD{-db_NV#*fh>VHoKi<+)u;2cXVDz~TviE8p`ly<$ z^Kzw1=88P{zGlw%4f?^I@MigJU>>Sca!Pi|JMf>mjlNWX{< zKJ)M;r`fI{&=STf(uGywO*TA!xsMXIv$SfT6R%svJN(=5QCZDP_FCSEv_ixHGB){=%RC)-%T*p&{q+@KSk`mb^w}wyO#EWi~o0}W@7e5gaJGQqDJ*plh z?Sr!Q-Q<(CJsBVk&`>|_>D1F4cmXt>S{h5+2MH{42}Rq%uob`-tZH{KVQb~lE(|*5Qp8u zt|%R>7Di`d?5+qmG4axHKrB&tG=feD5AV3_!QSns%g|M2Gg}Xmt$4SF{DufA*yk1pt{zJCf~MD7OHA25mbbXH{;zlVEk-!c5CdWBQ`4S zw@S&Eq9L`oXbsolxiObsb>TtGxRaM_)|2*D!_Z;Xj%=M>oJ>gOB4};$343XSTpkEd zVucy`R$2L_jM>z|RE=GpoFs~}L?S9X4rWp(=>I(EJLevVSeal-zbZ>#HnU>RMJnHEq8;BM~(tMC0EP%Q7xW|2gDTIoxHP3V?k!g;W;WBlq5OG^M(HpOc;E2L-vidluyG`&l6O zWB0W9@G}csC+5`7J{Obz$IH4Bx5a;$*%q)Gk#lw&1NVNTtdVG)$!rJYGGH zSWY#-D1nmQfgFYn^nT7Cg0#Oy0C-FFy0-rxFX9G#tB~y?0~1{--*`LXjFXlFHhM&c zn$LifpeCcr`3h6(>Jdp$(0b_XA}x`Pf%G1QPoX>BlBR2sK85iDUftD*DP_( z3d0pZpd1-O(DAAG*vOIlQpk0ASnj)3(&*~WzM&z?!Hmjrn=bJZ2YkL(ks6YL-Y=&( zhoYa%wZpY0)&jXWBCpVdNxHEQU>--G8?> z9P?&Be}-f19pukw{*33(M0D!OOy$DV3`+vDflrDWnARWF1^9I$0A6W=&+73F+8Z*| zXZKh=*afFWqgFS`Tr z5g3UP$}e@_uIek2Ax-0@>{*A>oeq@mYc*&Lr|R@VueD=7Nnqgn`k)Xz=&86kNRUI2p3-4|@MN00 zw11g&Kuv*vUt@FDht{A!Rz3Z$O0BYJ zHGPQ-Zt>llk0$NORaQ_s{6O^}B?x>vk9?pmDo?&DN4smSS%$kDjl`@vT3s$a3BFngAffcp8=|jIx)x3PA#e@Kz;||KMiaUs$l*qHu!Bm<2Fku{m zPp9MOBg6Zt0uDP9=e8H4uZ}XtP+nxfW?;BERooZ$)-NS?!e^U3M#vjy3#wFa)kn=M z{y@!f&DMCMC(ldFjhJPBM>0-)7>kUP;DZJ9oR{RfkWtiZDI@Dw`!`02U{Lx`eYx-A zYI<(SXlJW|yf^%g1-5vYv^<~TW_MFP+nrJqxPO-1ZgUX-M&3&fr0p*foqy9XqyQ}! zkPvcOI9k>JS7q^4k+^P<5jh2j6F#02)x*6_90~~-70+k)N*oM*{Gyqn!-*{yC!@Sy z(BV`V7}sxAN^2d~x9Nn$%uTN@m0B#LWE?D`C5(FFFWt6{^|;y?>M-&U*gwmRZs6emhNEMk`iEt%t|g$kuhv(<|M+-;!paX2g;gLA61OJ3p>{oqk4K z#vHf;gojQ^)848vTUzDraxqL^GR-dAQMSLIC2k8#zZB~-w?^*1yIk|tI;v7KTv69% zwT>hS6c~kjWI7Ne|3MqrE^k7sbSpZ7$7;KS!IvboWkgsb$|>uv3v-YCZwAW}H$!40 zHho1ruPDylE&QiT<-&_}#{D?6iritga^pyXDw6DAq%YYD8QI&(zp&kMtS_-TJcYbp zN6=u>7Z~n!ItDo-y5#M0nNmYEptXq(rllRz>duuR5kaEC+;?{^Us&5*i=RztP`J!g7EDmJ=5F1Q6s}xBajwMraK10D-#7MmTCVy> z?a;ZzKnHZ!506lgPGNxv4JPzsw7p6q(?<-jZBvS_s_z9Y!Cg{ud-IdIap4OM zLsME|fQE8eQ&of^(%YvL;wmMiGG6DGANylqd*?{5M<4mgBlq9?L>CD;lUC^aL`+_| zZdgl=y6W_86gP?g=v-6Ak0q7n%toiUmK`>FccCjT_&Do^j8^M9tx6egX7&bk<9p%i zz$mX^p(IHr@Q5`5H?B@_NmQx2CVtx+*=%f7)}>%1W~x9pZ|IP#^U-(?`S4WwO6WyOYEX;|I%j$k`KO14IVyNCdbfo}b}Ex0w3z zvw_*oPZ_}*2Xa=Qf;5<9nMv-pmB}3_GlF$vReSxuRDVny`1uRE0?wJLC!mMe+dswqc;KTo-zvWmeHWeV(9QCh7o%wxpGK9y3O4&)cgFBvc1m>I&M(E&r>G4 z?gfN&pj;2Vcsj|WNh+PdbhQg+j0>nf5O`jzIGARz@ z)T|IM*Q?HX_661&0fy0T(F6xxa7~PJZl@)EyNs)R|VRZ|2m&4(gD{owWiajhY;O-Dw8NvsV1*aR2yg@B|yn zhJ)p{H_GbA%ZA-$x0;~jNYcm9@p3b&9!W^3YB%%30M8!d?3+{>q6u`tvgce7;UJSx zSFNpbagM`g^7(FZ8b`P?$BFu;e{J#j@1yLdP<0ySiU+K0N1yi@u=R;K=98Bfeio9Q_tRkBx7W+|(wB6`zvspi)` zS(d-m)(zSVx40VJMmT;ah`9|q&u)iDx|p54`qntg9d)b0c8)`Y-<$(>gy0{=>%2aP zjtvjrSH^!=-$+}vqQK4Nj*#H!DCf;bw;>ii-`hN8ZH*4Ta-pl*a^!pT<2)IILao

@w(Lv4| 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 M@h{U+e&+A|U+7V#fB*mh literal 0 HcmV?d00001 diff --git a/mini.h b/mini.h new file mode 100644 index 0000000..5650c65 --- /dev/null +++ b/mini.h @@ -0,0 +1,205 @@ +#pragma once + +#include + +#define KEY_UNKNOWN 0 +#define KEY_A 4 +#define KEY_B 5 +#define KEY_C 6 +#define KEY_D 7 +#define KEY_E 8 +#define KEY_F 9 +#define KEY_G 10 +#define KEY_H 11 +#define KEY_I 12 +#define KEY_J 13 +#define KEY_K 14 +#define KEY_L 15 +#define KEY_M 16 +#define KEY_N 17 +#define KEY_O 18 +#define KEY_P 19 +#define KEY_Q 20 +#define KEY_R 21 +#define KEY_S 22 +#define KEY_T 23 +#define KEY_U 24 +#define KEY_V 25 +#define KEY_W 26 +#define KEY_X 27 +#define KEY_Y 28 +#define KEY_Z 29 +#define KEY_1 30 +#define KEY_2 31 +#define KEY_3 32 +#define KEY_4 33 +#define KEY_5 34 +#define KEY_6 35 +#define KEY_7 36 +#define KEY_8 37 +#define KEY_9 38 +#define KEY_0 39 +#define KEY_RETURN 40 +#define KEY_ESCAPE 41 +#define KEY_BACKSPACE 42 +#define KEY_TAB 43 +#define KEY_SPACE 44 +#define KEY_MINUS 45 +#define KEY_EQUALS 46 +#define KEY_LEFTBRACKET 47 +#define KEY_RIGHTBRACKET 48 +#define KEY_BACKSLASH 49 +#define KEY_NONUSHASH 50 +#define KEY_SEMICOLON 51 +#define KEY_APOSTROPHE 52 +#define KEY_GRAVE 53 +#define KEY_COMMA 54 +#define KEY_PERIOD 55 +#define KEY_SLASH 56 +#define KEY_CAPSLOCK 57 +#define KEY_F1 58 +#define KEY_F2 59 +#define KEY_F3 60 +#define KEY_F4 61 +#define KEY_F5 62 +#define KEY_F6 63 +#define KEY_F7 64 +#define KEY_F8 65 +#define KEY_F9 66 +#define KEY_F10 67 +#define KEY_F11 68 +#define KEY_F12 69 +#define KEY_PRINTSCREEN 70 +#define KEY_SCROLLLOCK 71 +#define KEY_PAUSE 72 +#define KEY_INSERT 73 +#define KEY_HOME 74 +#define KEY_PAGEUP 75 +#define KEY_DELETE 76 +#define KEY_END 77 +#define KEY_PAGEDOWN 78 +#define KEY_RIGHT 79 +#define KEY_LEFT 80 +#define KEY_DOWN 81 +#define KEY_UP 82 +#define KEY_NUMLOCKCLEAR 83 +#define KEY_KP_DIVIDE 84 +#define KEY_KP_MULTIPLY 85 +#define KEY_KP_MINUS 86 +#define KEY_KP_PLUS 87 +#define KEY_KP_ENTER 88 +#define KEY_KP_1 89 +#define KEY_KP_2 90 +#define KEY_KP_3 91 +#define KEY_KP_4 92 +#define KEY_KP_5 93 +#define KEY_KP_6 94 +#define KEY_KP_7 95 +#define KEY_KP_8 96 +#define KEY_KP_9 97 +#define KEY_KP_0 98 +#define KEY_KP_PERIOD 99 +#define KEY_NONUSBACKSLASH 100 +#define KEY_APPLICATION 101 +#define KEY_LCTRL 224 +#define KEY_LSHIFT 225 +#define KEY_LALT 226 +#define KEY_LGUI 227 +#define KEY_RCTRL 228 +#define KEY_RSHIFT 229 +#define KEY_RALT 230 +#define KEY_RGUI 231 + +void loop(); +void cls(uint8_t color=0); +void color(uint8_t color=6); +void pal(); +void pal(uint8_t c0, uint8_t c1, uint8_t p = 0); +void palt(); +void palt(uint16_t bits); +void palt(uint8_t col, bool t); + +void pset(int x, int y); +void pset(int x, int y, uint8_t color); + +uint8_t pget(int x, int y); + +void line(int x0, int y0, int x1, int y1); +void line(int x0, int y0, int x1, int y1, uint8_t color); + +void hline(int x0, int y, int x1); +void hline(int x0, int y, int x1, uint8_t color); + +void vline(int x, int y0, int y1); +void vline(int x, int y0, int y1, uint8_t color); + +void rect(int x0, int y0, int x1, int y1); +void rect(int x0, int y0, int x1, int y1, uint8_t color); + +void rectfill(int x0, int y0, int x1, int y1); +void rectfill(int x0, int y0, int x1, int y1, uint8_t color); + +void fillp(uint16_t pat, bool transparent = false); + +void print(const char *str, int x, int y); +void print(const char *str, int x, int y, uint8_t color); + +void clip(int x, int y, int w, int h); +void camera(int x, int y); + +void circ(int x, int y, uint8_t r = 4); +void circ(int x, int y, uint8_t r, uint8_t color); + +void circfill(int x, int y, uint8_t r = 4); +void circfill(int x, int y, uint8_t r, uint8_t color); + +void oval(int x0, int y0, int x1, int y1); +void oval(int x0, int y0, int x1, int y1, uint8_t color); + +void ovalfill(int x0, int y0, int x1, int y1); +void ovalfill(int x0, int y0, int x1, int y1, uint8_t color); + +uint8_t sget(int x, int y); +void sset(int x, int y); +void sset(int x, int y, uint8_t color); + +void spr(uint8_t n, int x, int y, float w = 1.0f, float h = 1.0f, bool flip_x = false, bool flip_y = false); +void sspr(int sx, int sy, int sw, int sh, int dx, int dy, int dw=0, int dh=0, bool flip_x = false, bool flip_y = false); + +void tline(int x0, int y0, int x1, int y1, float mx, float my, float mdx=0.125f, float mdy=0.0f); +void thline(int x0, int y, int x1, float mx, float my, float mdx=0.125f, float mdy=0.0f); +void tvline(int x, int y0, int y1, float mx, float my, float mdx=0.0f, float mdy=0.125f); + +void cline(int x0, int y0, int x1, int y1, uint8_t c0, uint8_t c1); +void chline(int x0, int y, int x1, uint8_t c0, uint8_t c1); +void cvline(int x, int y0, int y1, uint8_t c0, uint8_t c1); + +uint8_t mget(uint8_t celx, uint8_t cely); +void mset(uint8_t celx, uint8_t cely, uint8_t snum); +void map(uint8_t celx, uint8_t cely, int sx, int sy, uint8_t celw, uint8_t celh, uint8_t layer=0); + +bool btn(uint8_t i); +bool btnp(uint8_t i); + +float time(); + +//float abs(float x); +float ceil(float x); +float flr(float x); +float sgn(float x); + +float sin(float x); +float cos(float x); +float atan2(float dx, float dy); +float sqrt(float x); + +float max(float x, float y); +float mid(float x, float y, float z); +float min(float x, float y); + +int rnd(int x); +//void srand(int x); + +void debug(const char *str); +void pdebug(); + diff --git a/sprites.aseprite b/sprites.aseprite new file mode 100644 index 0000000000000000000000000000000000000000..fde30443fc9ef507acc31e1115f8aa2611cbcde6 GIT binary patch literal 718 zcmX@d#K7=iDI-Gz5OOduGB7Zt05JjxFff7yfpQ!OK`OHRfcF3T$O^WV6=<#)5VI?Q ztwge=3dojJ5P*vCBgrr@NXh8@XJCj`j|Gw&?Sg^i``U0I`TuMwkX-(u07zPFPXUsu zg_S^3(<~oITF0IQl8(#10mQ0WnD+hcbCclT*Is>#^B$Rq8q8B_j2&#B7uUb|DSwJ#W&OTe`)+RguEG5K zIm4yz8*lFWxuxUq?@9*Cf3@|-Pmjyr@n@EZxBHc+H~IJD@Amc8RzF^PJ>Fe+;<{Zn z`~Uyc|HV3ch6TQPXQrK&y(P1)Z0*&V2d*;C(NX)n_4U+WueaU5_5G&G zZq2VtcfB{Cy3eKb)ysR!%bYLFd=SUJ<8;y{_qTRaetoRm15))n)M;`spp(~kWY literal 0 HcmV?d00001 diff --git a/sprites.bmp b/sprites.bmp new file mode 100644 index 0000000000000000000000000000000000000000..09cfa23f47365147e0f18192d8553622e12dd029 GIT binary patch literal 8310 zcmeI1F-rqM5QU$)G{Gy3rKC6`qJl+8Km>zCbFGz_ROv!&1QjvSLP#Z+S6Fy|K+#Go z!RoXVETc}}s{Q=dpE{;0`9Q1Bbe_X}s;XL+Nmhf6z!{_w|zPd-~_xpIczr^`o z1=V5!X>Ovg&iU~D76Nb;Du-Vv@ q&pJ@r|8IYo@^pZsdB%DF@b{Qd=UXHu