diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2021-09-22 23:51:34 -0700 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2021-09-22 23:51:34 -0700 |
| commit | 7122dcdc8143c76336074fec1de172d6c569f0c2 (patch) | |
| tree | 67471ba9bde82b42845f733c16a490f0f6457390 | |
| parent | f1f60c9dcf3de1475851958af0529bed0dfc6d54 (diff) | |
Added Lua bindings
| -rw-r--r-- | Lua/Makefile | 48 | ||||
| -rw-r--r-- | Lua/README.md | 11 | ||||
| -rw-r--r-- | Lua/lbp.c | 136 |
3 files changed, 195 insertions, 0 deletions
diff --git a/Lua/Makefile b/Lua/Makefile new file mode 100644 index 0000000..4569ce6 --- /dev/null +++ b/Lua/Makefile @@ -0,0 +1,48 @@ +NAME=bp +CC=cc +PREFIX=/usr/local +LUA_DIR=/usr/local +LUA_INC= $(LUA_DIR)/include +LUA=lua +INCS=-I$(LUA_INC) +CFLAGS=-std=c99 -Werror -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -flto +CWARN=-Wall -Wextra + # -Wpedantic -Wsign-conversion -Wtype-limits -Wunused-result -Wnull-dereference \ + # -Waggregate-return -Walloc-zero -Walloca -Warith-conversion -Wcast-align -Wcast-align=strict \ + # -Wdangling-else -Wdate-time -Wdisabled-optimization -Wdouble-promotion -Wduplicated-branches \ + # -Wduplicated-cond -Wexpansion-to-defined -Wfloat-conversion -Wfloat-equal -Wformat-nonliteral \ + # -Wformat-security -Wformat-signedness -Wframe-address -Winline -Winvalid-pch -Wjump-misses-init \ + # -Wlogical-op -Wlong-long -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn \ + # -Wnull-dereference -Woverlength-strings -Wpacked -Wpacked-not-aligned -Wpointer-arith \ + # -Wredundant-decls -Wshadow -Wshadow=compatible-local -Wshadow=global -Wshadow=local \ + # -Wsign-conversion -Wstack-protector -Wsuggest-attribute=const -Wswitch-default -Wswitch-enum \ + # -Wsync-nand -Wtrampolines -Wundef -Wunsuffixed-float-constants -Wunused -Wunused-but-set-variable \ + # -Wunused-const-variable -Wunused-local-typedefs -Wunused-macros -Wvariadic-macros -Wvector-operation-performance \ + # -Wvla -Wwrite-strings +OSFLAGS != case $$(uname -s) in *BSD|Darwin) echo '-D_BSD_SOURCE';; Linux) echo '-D_GNU_SOURCE';; *) echo '-D_DEFAULT_SOURCE';; esac +EXTRA= +G= +O=-O3 +ALL_FLAGS=$(CFLAGS) $(OSFLAGS) $(INCS) $(EXTRA) $(CWARN) $(G) $(O) + +ifeq ($(shell uname -s),Darwin) + MAKESO= $(CC) -bundle -undefined dynamic_lookup +else + MAKESO= $(CC) -shared +endif + +all: bp.so + +clean: + rm -f lbp.o bp.so + +lbp.o: lbp.c + $(CC) -c $(ALL_FLAGS) -o $@ $< + +bp.so: lbp.o ../print.o ../files.o ../pattern.o ../utils.o ../utf8.o ../match.o ../definitions.o + $(MAKESO) -o $@ $^ + +test: bp.so + $(LUA) test.lua + +.PHONY: all clean test diff --git a/Lua/README.md b/Lua/README.md new file mode 100644 index 0000000..dfc10bf --- /dev/null +++ b/Lua/README.md @@ -0,0 +1,11 @@ +# Lua Bindings + +This directory contains Lua bindings for bp. + +## API + +```lua +local bp = require("bp") +local m, i, len = bp.match("like finding a needle in a haystack", '"n" +`e "dle"') +local replaced = bp.match("like finding a needle in a haystack", '"n" +`e "dle"', "cat") +``` diff --git a/Lua/lbp.c b/Lua/lbp.c new file mode 100644 index 0000000..15d549b --- /dev/null +++ b/Lua/lbp.c @@ -0,0 +1,136 @@ +/* +* lbp.c - bp library for lua +* API: +* bp.match(str, pat[, start_index]) -> nil or (match_text, start_index, match_len_in_source) +* bp.replace(str, pat, replacement, start_index) -> str with replacements +*/ + +#include <string.h> + +#include "lua.h" +#include "lauxlib.h" + +#include "../print.h" +#include "../files.h" +#include "../pattern.h" +#include "../match.h" + +// The C API changed from 5.1 to 5.2, so these shims help the code compile on >=5.2 +#if LUA_VERSION_NUM >= 502 +#define lua_objlen(L, i) lua_rawlen(L, i) +#define luaL_register(L, _, R) luaL_setfuncs(L, R, 0) +#endif + +static int Lmatch(lua_State *L) +{ + size_t textlen, patlen; + const char *text = luaL_checklstring(L, 1, &textlen); + const char *pat_text = luaL_checklstring(L, 2, &patlen); + lua_Integer index = luaL_optinteger(L, 3, 1); + if (index > (lua_Integer)strlen(text)+1) + return 0; + + file_t *pat_file = spoof_file(NULL, "<pattern argument>", pat_text, patlen); + pat_t *pat = bp_pattern(pat_file, pat_file->start); + if (!pat) { + destroy_file(&pat_file); + luaL_error(L, "Pattern failed to compile: %s", pat_text); + return 0; + } + + file_t *text_file = spoof_file(NULL, "<text argument>", text+(index-1), textlen); + match_t *m = NULL; + int ret = 0; + if (next_match(&m, NULL, text_file, pat, NULL, false)) { + char *buf = NULL; + size_t size = 0; + FILE *out = open_memstream(&buf, &size); + printer_t pr = { + .file = text_file, + .context_before = NO_CONTEXT, + .context_after = NO_CONTEXT, + .use_color = 0, + .lineformat = "", + }; + print_match(out, &pr, m); + fflush(out); + lua_pushlstring(L, buf, size); + lua_pushinteger(L, (int)(m->start - text_file->start) + index); + lua_pushinteger(L, (int)(m->end - m->start)); + fclose(out); + stop_matching(&m); + ret = 3; + } + + destroy_file(&pat_file); + destroy_file(&text_file); + + return ret; +} + +static int Lreplace(lua_State *L) +{ + size_t textlen, patlen, replen; + const char *text = luaL_checklstring(L, 1, &textlen); + const char *pat_text = luaL_checklstring(L, 2, &patlen); + const char *rep_text = luaL_checklstring(L, 3, &replen); + lua_Integer index = luaL_optinteger(L, 4, 1); + if (index > (lua_Integer)strlen(text)+1) + index = (lua_Integer)strlen(text)+1; + + file_t *pat_file = spoof_file(NULL, "<pattern argument>", pat_text, patlen); + pat_t *pat = bp_pattern(pat_file, pat_file->start); + if (!pat) { + destroy_file(&pat_file); + luaL_error(L, "Pattern failed to compile: %s", pat_text); + return 0; + } + file_t *rep_file = spoof_file(NULL, "<replacement argument>", rep_text, replen); + pat = bp_replacement(rep_file, pat, rep_file->start); + if (!pat) { + destroy_file(&pat_file); + destroy_file(&rep_file); + luaL_error(L, "Replacement failed to compile: %s", rep_text); + return 0; + } + + file_t *text_file = spoof_file(NULL, "<text argument>", text+(index-1), textlen); + char *buf = NULL; + size_t size = 0; + FILE *out = open_memstream(&buf, &size); + printer_t pr = { + .file = text_file, + .context_before = ALL_CONTEXT, + .context_after = ALL_CONTEXT, + .use_color = 0, + .lineformat = "", + }; + int replacements = 0; + for (match_t *m = NULL; next_match(&m, NULL, text_file, pat, NULL, false); ) { + print_match(out, &pr, m); + ++replacements; + } + print_match(out, &pr, NULL); + fflush(out); + lua_pushlstring(L, buf, size); + lua_pushinteger(L, replacements); + fclose(out); + + destroy_file(&pat_file); + destroy_file(&rep_file); + destroy_file(&text_file); + + return 2; +} + +LUALIB_API int luaopen_bp(lua_State *L) +{ + lua_createtable(L, 0, 2); + lua_pushcfunction(L, Lmatch); + lua_setfield(L, -2, "match"); + lua_pushcfunction(L, Lreplace); + lua_setfield(L, -2, "replace"); + // lua_pushcfunction(L, Leach); + // lua_setfield(L, -1, "each"); + return 1; +} |
