Added Lua bindings
This commit is contained in:
parent
f1f60c9dcf
commit
7122dcdc81
48
Lua/Makefile
Normal file
48
Lua/Makefile
Normal file
@ -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
|
11
Lua/README.md
Normal file
11
Lua/README.md
Normal file
@ -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")
|
||||
```
|
136
Lua/lbp.c
Normal file
136
Lua/lbp.c
Normal file
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user