ADDED bind/bind.h Index: bind/bind.h ================================================================== --- bind/bind.h +++ bind/bind.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +#include +#include +#include + +#define _luafn(name) static int LX_##name (lua_State* l) +#define _export(name) lua_pushcfunction(l, LX_##name), lua_setfield(l, -2, #name); + +#define _luaret_bool(b) {lua_pushboolean(l, b); return 1;} +#define _luaAPI(mod, ...) int luaopen_bind_##mod (lua_State* l) { \ + lua_newtable(l); \ + __VA_ARGS__; \ + return 1; \ +} + +/* this comment serves only to unfuck a GCC bug */ ADDED bind/net.c Index: bind/net.c ================================================================== --- bind/net.c +++ bind/net.c @@ -0,0 +1,54 @@ +#include "bind.h" + +#include + +#define _str(...) #__VA_ARGS__ +#define _e_tag "(native-bind " __FILE__ ":" _str(__LINE__) ") " + +static size_t +buffer_string +( char* ptr, + size_t size, + size_t nmemb, + void* dest +) { + luaL_Buffer* const data = dest; + luaL_addlstring(data, ptr, size*nmemb); + return size*nmemb; +} + +_luafn(fetchURI) { + const char* p_uri = luaL_checkstring(l,1); + + CURL* h = curl_easy_init(); + if (!h) { + lua_pushstring(l, _e_tag "libcurl failed to init"); + lua_error(l); + } + +// int unwind = lua_gettop(l); + luaL_Buffer download; + luaL_buffinit(l, &download); + + char ebuf [CURL_ERROR_SIZE]; + curl_easy_setopt(h, CURLOPT_URL, p_uri); + curl_easy_setopt(h, CURLOPT_WRITEFUNCTION, buffer_string); + curl_easy_setopt(h, CURLOPT_WRITEDATA, &download); + curl_easy_setopt(h, CURLOPT_FOLLOWLOCATION,true); + curl_easy_setopt(h, CURLOPT_ERRORBUFFER, ebuf); + + CURLcode e = curl_easy_perform(h); + if (e == 0) { + curl_easy_cleanup(h); + luaL_pushresult(&download); + return 1; + } else { +// lua_settop(l,unwind); + lua_pushnil(l); + lua_pushstring(l, ebuf); + return 2; + } +} + +_luaAPI(net, + _export(fetchURI)); ADDED bind/posix.c Index: bind/posix.c ================================================================== --- bind/posix.c +++ bind/posix.c @@ -0,0 +1,30 @@ +#include "bind.h" + +#include +#include +#include + +_luafn(getcwd) { /* getcwd() */ + size_t bufsz = 256; + /* VLA resize hack */ for (;;) { + char cwd [bufsz]; + if (getcwd(cwd, bufsz) == NULL) { + assert(bufsz < (2 * 1024*1024)); /* sanity check */ + bufsz = bufsz * 2; + continue; + } + lua_pushstring(l, cwd); + return 1; + } +} + +_luafn(isatty) { /* isatty(stream) */ + luaL_Stream* stream = lua_touserdata(l, 1); + if (stream == NULL) return 0; + int fd = fileno(stream -> f); + _luaret_bool(isatty(fd)); +} + +_luaAPI(posix, + _export(getcwd); + _export(isatty)); ADDED bind/strutils.c Index: bind/strutils.c ================================================================== --- bind/strutils.c +++ bind/strutils.c @@ -0,0 +1,21 @@ +#include "bind.h" + +_luafn(rangematch) { + luaL_checkstring(l, 1); + luaL_checknumber(l, 2); + luaL_checkstring(l, 3); + + size_t strl = 0, matl = 0, start = lua_tointeger(l, 2)-1; + const char* str = lua_tolstring(l, 1, &strl); + const char* mat = lua_tolstring(l, 3, &matl); + size_t to; + if (start > strl || (to = start + matl) > strl) { + _luaret_bool(false); + } + for (size_t i = start; i {}, ...}: + +let debuggable = d: d.overrideAttrs(o: rec { + dontStrip = true; +}); + +in pkgs.mkShell { + buildInputs = with pkgs; [ + lua5_4 + curl + ]; + shellHook = '' + exec fish + ''; + NIX_ENFORCE_PURITY = false; +}