aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-09-24 20:33:47 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-09-24 20:33:47 -0400
commit4ec3e11b9f542a0239de7bedad9d732b0a20d68b (patch)
tree276f2c56ccd63016a6ba1a3b12923d5c631b0555
parent3d5944a732e34b6dd01921dee991dee54af47e18 (diff)
parentfe6da3015573079229a0da3166eb4b5f36520dbb (diff)
Merge branch 'main' of github.com:bruce-hill/bp
-rw-r--r--.gitignore3
-rw-r--r--Makefile37
-rw-r--r--bp.c16
-rw-r--r--configure.sh32
-rw-r--r--match.c7
5 files changed, 74 insertions, 21 deletions
diff --git a/.gitignore b/.gitignore
index 004ac2d..4cdeead 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,8 @@
*.o
*.so
tags
-bp
+/bp
.*
!.gitignore
/Lua/builtins.h
+config.mk
diff --git a/Makefile b/Makefile
index 9c646bb..12cac3e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,23 @@
+ifeq ($(wildcard config.mk),)
+all: config.mk
+ $(MAKE) all
+install: config.mk
+ $(MAKE) install
+install-files: config.mk
+ $(MAKE) install-files
+install-lib: config.mk
+ $(MAKE) install-lib
+test: config.mk
+ $(MAKE) test
+config.mk: configure.sh
+ bash ./configure.sh
+else
+
+include config.mk
NAME=bp
CC=cc
-PREFIX=/usr/local
-SYSCONFDIR=/etc
-CFLAGS=-std=c11 -Werror -D_XOPEN_SOURCE=800 -D_POSIX_C_SOURCE=200809L -fPIC -flto=auto -fvisibility=hidden \
- -fsanitize=signed-integer-overflow -fno-sanitize-recover
+CFLAGS=-std=c2x -Werror -D_GNU_SOURCE -fPIC -flto=auto -fvisibility=hidden \
+ -fsanitize=signed-integer-overflow -fno-sanitize-recover -DBP_PREFIX='"$(PREFIX)"'
CWARN=-Wall -Wextra -Wno-format -Wshadow
# -Wpedantic -Wsign-conversion -Wtype-limits -Wunused-result -Wnull-dereference \
# -Waggregate-return -Walloc-zero -Walloca -Warith-conversion -Wcast-align -Wcast-align=strict \
@@ -34,7 +48,7 @@ $(NAME): $(OBJFILES) bp.c
$(LIBFILE): pattern.o utils.o match.o utf8.o
$(CC) $^ $(ALL_FLAGS) -Wl,-soname,$(LIBFILE) -shared -o $@
-all: $(NAME) $(LIBFILE) bp.1 lua
+all: $(NAME) bp.1
%.o: %.c %.h utf8.h
$(CC) -c $(ALL_FLAGS) -o $@ $<
@@ -80,8 +94,8 @@ splint:
# $(CFILES) bp.c
install: $(NAME) bp.1
- mkdir -p -m 755 "$(PREFIX)/man/man1" "$(PREFIX)/bin" "$(SYSCONFDIR)/$(NAME)"
- cp -r grammars/* "$(SYSCONFDIR)/$(NAME)/"
+ mkdir -p -m 755 "$(PREFIX)/man/man1" "$(PREFIX)/bin" "$(PREFIX)/share/$(NAME)"
+ cp -r grammars "$(PREFIX)/share/$(NAME)/"
cp bp.1 "$(PREFIX)/man/man1/$(NAME).1"
rm -f "$(PREFIX)/bin/$(NAME)"
cp $(NAME) "$(PREFIX)/bin/"
@@ -92,12 +106,7 @@ install-lib: $(LIBFILE) bp.1
cp pattern.h match.h "$(PREFIX)/include/$(NAME)"
uninstall:
- rm -rf "$(PREFIX)/bin/$(NAME)" "$(PREFIX)/man/man1/$(NAME).1" "$(SYSCONFDIR)/$(NAME)"
- @if [ -d ~/.config/$(NAME) ]; then \
- printf 'Config files exist in ~/.config/$(NAME) Do you want to delete them? [Y/n] '; \
- read confirm; \
- [ "$$confirm" != n ] && rm -rf ~/.config/$(NAME); \
- fi
+ rm -rf "$(PREFIX)/bin/$(NAME)" "$(PREFIX)/man/man1/$(NAME).1" "$(PREFIX)/share/$(NAME)"
profile_grammar: bp
perf stat -r 100 -e L1-dcache-loads,L1-dcache-load-misses,L1-dcache-stores -e cycles ./bp -f plain -g bp -p Grammar grammars/bp.bp >/dev/null
@@ -105,4 +114,6 @@ profile_grammar: bp
profile_pattern: bp
perf stat -r 1 -e L1-dcache-loads,L1-dcache-load-misses,L1-dcache-stores -e cycles ./bp -f plain -p 'id parens' /usr/include/*.h >/dev/null
+endif
+
.PHONY: all clean install install-lib uninstall leaktest splint test tutorial lua profile luatest
diff --git a/bp.c b/bp.c
index d9cab52..d8cbe10 100644
--- a/bp.c
+++ b/bp.c
@@ -97,6 +97,14 @@ static inline void fprint_filename(FILE *out, const char *filename) {
else fprintf(out, "%s:\n", filename);
}
+static void *portable_memrchr(const void *s, int c, size_t n) {
+ const unsigned char *p = (const unsigned char *)s + n;
+ while (n--) {
+ if (*--p == (unsigned char)c) return (void *)p;
+ }
+ return NULL;
+}
+
//
// If there was a parse error while building a pattern, print an error message and exit.
//
@@ -106,7 +114,7 @@ static inline bp_pat_t *assert_pat(const char *start, const char *end, maybe_pat
const char *err_start = maybe_pat.value.error.start, *err_end = maybe_pat.value.error.end,
*err_msg = maybe_pat.value.error.msg;
- const char *nl = memrchr(start, '\n', (size_t)(err_start - start));
+ const char *nl = portable_memrchr(start, '\n', (size_t)(err_start - start));
const char *sol = nl ? nl + 1 : start;
nl = memchr(err_start, '\n', (size_t)(end - err_start));
const char *eol = nl ? nl : end;
@@ -517,9 +525,9 @@ int main(int argc, char *argv[]) {
bp_pat_t *pattern = NULL;
// Load builtins:
- file_t *builtins_file = load_file(&loaded_files, "/etc/" BP_NAME "/builtins.bp");
+ file_t *builtins_file = load_file(&loaded_files, BP_PREFIX "/" BP_NAME "/builtins.bp");
if (builtins_file) defs = load_grammar(defs, builtins_file);
- file_t *local_file = load_filef(&loaded_files, "%s/.config/" BP_NAME "/builtins.bp", getenv("HOME"));
+ file_t *local_file = load_file(&loaded_files, BP_PREFIX "/share/" BP_NAME "/grammars/builtins.bp");
if (local_file) defs = load_grammar(defs, local_file);
bool explicit_case_sensitivity = false;
@@ -561,7 +569,7 @@ int main(int argc, char *argv[]) {
file_t *f = NULL;
if (strlen(flag) > 3 && strncmp(&flag[strlen(flag) - 3], ".bp", 3) == 0) f = load_file(&loaded_files, flag);
if (f == NULL) f = load_filef(&loaded_files, "%s/.config/" BP_NAME "/%s.bp", getenv("HOME"), flag);
- if (f == NULL) f = load_filef(&loaded_files, "/etc/" BP_NAME "/%s.bp", flag);
+ if (f == NULL) f = load_filef(&loaded_files, BP_PREFIX "/share/" BP_NAME "/grammars/%s.bp", flag);
if (f == NULL) errx(EXIT_FAILURE, "Couldn't find grammar: %s", flag);
defs = load_grammar(defs, f); // Keep in memory for debug output
} else if (FLAG("-w") || FLAG("--word")) {
diff --git a/configure.sh b/configure.sh
new file mode 100644
index 0000000..13c3830
--- /dev/null
+++ b/configure.sh
@@ -0,0 +1,32 @@
+#!/bin/env bash
+
+error() {
+ printf "\033[31;1m%s\033[m\n" "$@"
+ exit 1
+}
+
+default_prefix='/usr/local'
+if echo "$PATH" | tr ':' '\n' | grep -qx "$HOME/.local/bin"; then
+ default_prefix="~/.local"
+fi
+
+printf '\033[1mChoose where to install bp (default: %s):\033[m ' "$default_prefix"
+read PREFIX
+if [ -z "$PREFIX" ]; then PREFIX="$default_prefix"; fi
+PREFIX="${PREFIX/#\~/$HOME}"
+
+if ! echo "$PATH" | tr ':' '\n' | grep -qx "$PREFIX/bin"; then
+ error "Your \$PATH does not include this prefix, so you won't be able to run tomo!" \
+ "Please put this in your .profile or .bashrc: export PATH=\"$PREFIX/bin:\$PATH\""
+fi
+
+if command -v doas >/dev/null; then
+ SUDO=doas
+else
+ SUDO=sudo
+fi
+
+cat <<END >config.mk
+PREFIX=$PREFIX
+SUDO=$SUDO
+END
diff --git a/match.c b/match.c
index 8175c0c..5af90ce 100644
--- a/match.c
+++ b/match.c
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/param.h>
#include "match.h"
#include "pattern.h"
@@ -306,9 +307,9 @@ __attribute__((nonnull(1, 2, 3))) static bp_match_t *_next_match(match_ctx_t *ct
// we can just rely on the highly optimized memmem() implementation to skip
// past areas where we know we won't find a match.
if (!skip && first->type == BP_STRING && first->min_matchlen > 0) {
- char *found = ctx->ignorecase
- ? strcasestr(str, When(first, BP_STRING)->string)
- : memmem(str, (size_t)(ctx->end - str), When(first, BP_STRING)->string, first->min_matchlen);
+ char *found = ctx->ignorecase ? strcasestr(str, When(first, BP_STRING)->string)
+ : strnstr(str, When(first, BP_STRING)->string,
+ MIN((size_t)(ctx->end - str), first->min_matchlen));
str = found ? found : ctx->end;
} else if (!skip && str > ctx->start && (first->type == BP_START_OF_LINE || first->type == BP_END_OF_LINE)) {
char *found = memchr(str, '\n', (size_t)(ctx->end - str));