diff options
-rw-r--r-- | .tdrc | 1 | ||||
-rw-r--r-- | Makefile | 152 | ||||
-rwxr-xr-x | aux/container | 4 | ||||
-rw-r--r-- | aux/manifest.scm | 7 | ||||
-rw-r--r-- | deps.mk | 25 | ||||
-rw-r--r-- | doc/favicon.svg | 62 | ||||
-rw-r--r-- | doc/papo.CHANGELOG.en.7.in | 0 | ||||
-rw-r--r-- | doc/papo.README.en.7.in | 0 | ||||
-rw-r--r-- | doc/papo.TODOs.en.7.in | 0 | ||||
-rwxr-xr-x | mkdeps.sh | 3 | ||||
-rw-r--r-- | src/catalog.c | 501 | ||||
-rw-r--r-- | src/catalog.h | 33 | ||||
-rw-r--r-- | src/config.h.in | 31 | ||||
-rw-r--r-- | src/i18n.c | 69 | ||||
-rw-r--r-- | src/i18n.h | 56 | ||||
-rw-r--r-- | src/logerr.c | 301 | ||||
-rw-r--r-- | src/logerr.h | 23 | ||||
-rw-r--r-- | src/napi-sqlite.c | 932 | ||||
-rw-r--r-- | src/papo.en.msg | 72 | ||||
-rwxr-xr-x | tests/assert-clean.sh | 40 | ||||
-rwxr-xr-x | tests/assert-deps.sh | 10 | ||||
-rwxr-xr-x | tests/assert-install.sh | 28 | ||||
-rwxr-xr-x | tests/assert-uninstall.sh | 29 | ||||
-rwxr-xr-x | tests/c-lint.sh | 65 | ||||
-rw-r--r-- | tests/slurp.c | 69 | ||||
-rw-r--r-- | tests/slurp.h | 11 | ||||
-rw-r--r-- | tests/tests-lib.c | 28 | ||||
-rw-r--r-- | tests/tests-lib.h | 15 | ||||
-rwxr-xr-x | tools/cdeps.sh | 225 |
29 files changed, 21 insertions, 2771 deletions
@@ -1 +0,0 @@ -TD_USE_BUILTIN_HOOKS='git' @@ -15,18 +15,14 @@ SRCDIR = $(PREFIX)/src/$(NAME) SHAREDIR = $(PREFIX)/share LOCALEDIR = $(SHAREDIR)/locale MANDIR = $(SHAREDIR)/man -CFLAGS.so = -fPIC -LDFLAGS.so = --shared -EXT.so = .so EXEC = ./ ## Where to store the installation. Empty by default. DESTDIR = -LDLIBS = -lsqlite3 .SUFFIXES: -.SUFFIXES: .in .c .o .lo .to .ta .t .msg .cat +.SUFFIXES: .in .in: sed \ @@ -38,88 +34,37 @@ LDLIBS = -lsqlite3 < $< > $@ if [ -x $< ]; then chmod +x $@; fi -.c.o: - $(CC) $(CFLAGS) $(CFLAGS.a) -o $@ -c $< - -.c.lo: - $(CC) $(CFLAGS) $(CFLAGS.so) -o $@ -c $< - -.c.to: - $(CC) $(CFLAGS) $(CFLAGS.a) -DTEST -o $@ -c $< - -.ta.t: - $(CC) $(LDFLAGS) $(LDFLAGS.a) -o $@ $< $(LDLIBS) - all: include deps.mk -manpages.en.in = \ - doc/$(NAME).README.en.7.in \ - doc/$(NAME).CHANGELOG.en.7.in \ - doc/$(NAME).TODOs.en.7.in \ - doc/$(NAME).en.1.in \ - doc/$(NAME).en.3js.in \ - doc/$(NAME).tutorial.en.7.in \ - doc/$(NAME).recipes.en.7.in \ - doc/$(NAME).why.en.7.in -manpages.in = $(manpages.en.in) manpages = $(manpages.in:.in=) -catalogs.en.msg = src/$(NAME).en.msg -catalogs.msg = $(catalogs.en.msg) -catalogs.cat = $(catalogs.msg:.msg=.cat) - -sources.o = $(sources.c:.c=.o) -sources.lo = $(sources.c:.c=.lo) -sources.to = $(sources.c:.c=.to) -sources.ta = $(sources.c:.c=.ta) -sources.t = $(sources.c:.c=.t) - sources = \ - $(sources.c) \ - $(sources.c:.c=.h) \ - src/config.h.in \ - src/config.h \ - $(catalogs.msg) \ - $(sources.js) \ - src/cli \ - src/napi-sqlite.c \ + $(sources.js) \ + src/cli \ installable = \ - $(sources.sql) \ - $(sources.js) \ - src/index.js \ - src/cli \ - src/napi-sqlite.node \ + $(sources.sql) \ + $(sources.js) \ + src/index.js \ + src/cli \ derived-assets = \ - $(NAME).bin \ - lib$(NAME)$(EXT.so) \ - src/config.h \ - $(manpages) \ - $(catalogs.cat) \ - $(sources.o) \ - $(sources.lo) \ - $(sources.to) \ - $(sources.ta) \ - $(sources.t) \ - tests/tests-lib.o \ - tests/slurp.o \ - src/index.js \ - node_modules/dir.sentinel \ - node_modules/ \ - node_modules/$(NAME) \ - src/napi-sqlite.lo \ - src/napi-sqlite.node \ + $(NAME).bin \ + $(manpages) \ + src/index.js \ + node_modules/dir.sentinel \ + node_modules/ \ + node_modules/$(NAME) \ side-assets = \ - src/logerr.c.txt \ - src/catalog.c.txt \ - ircd.sock \ - web.sock \ + src/logerr.c.txt \ + src/catalog.c.txt \ + ircd.sock \ + web.sock \ @@ -131,13 +76,7 @@ all: $(derived-assets) $(NAME).bin: ln -fs src/cli $@ -$(manpages) src/config.h: Makefile deps.mk -$(sources.o) $(sources.lo) $(sources.to): src/config.h Makefile deps.mk -tests/tests-lib.o: tests/tests-lib.h src/config.h Makefile deps.mk -src/napi-sqlite.lo: src/config.h Makefile deps.mk -$(sources.to): tests/tests-lib.h -$(sources.ta): tests/tests-lib.o -$(sources.js) $(tests.js): src/napi-sqlite.node +$(manpages): Makefile deps.mk src/index.js: ln -fs api.js $@ @@ -153,23 +92,6 @@ node_modules/$(NAME): node_modules/dir.sentinel node_modules/: node_modules/dir.sentinel node_modules/$(NAME) -src/napi-sqlite.node: lib$(NAME)$(EXT.so) - ln -f lib$(NAME)$(EXT.so) $@ - -lib$(NAME)$(EXT.so): $(sources.lo) src/napi-sqlite.lo - $(CC) $(LDFLAGS) $(LDFLAGS.so) -o $@ $(sources.lo) src/napi-sqlite.lo \ - $(LDLIBS) - -$(sources.ta): - $(AR) $(ARFLAGS) $@ $? - -src/$(NAME).en.cat: src/i18n.t - env DUMP_TRANSLATABLE_STRINGS=1 $(EXEC)src/i18n.t > $*.msg.new - cmp -s $*.msg.new $*.msg || mv $*.msg.new $*.msg - rm -f $*.msg.new - gencat $@ $*.msg - touch $@ - .SUFFIXES: .js .js-t @@ -177,25 +99,7 @@ tests.js-t = $(tests.js:.js=.js-t) $(tests.js-t): node $*.js -check-js-t: $(tests.js-t) - -.SUFFIXES: .t-run -sources.t-run = $(sources.c:.c=.t-run) -$(sources.t-run): - $(EXEC)$*.t - -check-t-run: $(sources.t-run) - -check-t: check-js-t check-t-run - - - -.SUFFIXES: .c-lint -sources.c-lint = $(sources.c:.c=.c-lint) -$(sources.c-lint): - sh tests/c-lint.sh $*.c - -check-lint: $(sources.c-lint) +check-unit: $(tests.js-t) integration-tests = \ @@ -207,23 +111,10 @@ $(integration-tests): $(NAME).bin ALWAYS check-integration: $(integration-tests) -tests/assert-clean.sh tests/assert-install.sh tests/assert-uninstall.sh: all -assert-tests = \ - tests/assert-clean.sh \ - tests/assert-deps.sh \ - tests/assert-install.sh \ - tests/assert-uninstall.sh \ - -$(assert-tests): ALWAYS - +sh $@ - -check-asserts: $(assert-tests) - - ## Run all tests. Each test suite is isolated, so that a parallel ## build can run tests at the same time. The required artifacts ## are created if missing. -check: check-t check-lint check-integration check-asserts +check: check-unit check-integration ## Remove *all* derived artifacts produced during the build. @@ -283,10 +174,9 @@ run: all $(MAKE) run-ircd & $(MAKE) run-web & wait -MAKEFILE = Makefile ## Show this help. help: - cat $(MAKEFILE) | sh tools/makehelp.sh + sh tools/makehelp.sh < Makefile ALWAYS: diff --git a/aux/container b/aux/container deleted file mode 100755 index 8e17ece..0000000 --- a/aux/container +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -set -eu - -exec guix shell --pure -S/usr/bin/env=bin/env -Cv3 -m aux/manifest.scm "$@" diff --git a/aux/manifest.scm b/aux/manifest.scm deleted file mode 100644 index 5f516fa..0000000 --- a/aux/manifest.scm +++ /dev/null @@ -1,7 +0,0 @@ -(specifications->manifest - (map - symbol->string - '(busybox - git-minimal - make - node))) @@ -1,8 +1,3 @@ -sources.c = \ - src/catalog.c \ - src/i18n.c \ - src/logerr.c \ - sources.js = \ src/api.js \ src/db.js \ @@ -19,26 +14,6 @@ tests.js = \ sources.sql = \ src/sql/migrations/2023-11-16T15:46:27-03:00-init-auth-data.sql \ -src/catalog.o src/catalog.lo src/catalog.to: src/catalog.h -src/i18n.o src/i18n.lo src/i18n.to: src/i18n.h -src/logerr.o src/logerr.lo src/logerr.to: src/logerr.h - -src/catalog.ta: src/catalog.to -src/i18n.ta: src/i18n.to -src/logerr.ta: src/logerr.to - -src/catalog.t-run: src/catalog.t -src/i18n.t-run: src/i18n.t -src/logerr.t-run: src/logerr.t - - -src/catalog.o src/catalog.lo src/catalog.to: src/logerr.h src/../tests/slurp.h -src/i18n.o src/i18n.lo src/i18n.to: src/logerr.h src/catalog.h -src/logerr.o src/logerr.lo src/logerr.to: src/../tests/slurp.h - -src/catalog.ta: src/logerr.o src/../tests/slurp.o -src/i18n.ta: src/logerr.o src/catalog.o -src/logerr.ta: src/../tests/slurp.o tests/js/db.js-t: tests/js/db.js tests/js/ircd.js-t: tests/js/ircd.js diff --git a/doc/favicon.svg b/doc/favicon.svg deleted file mode 100644 index ce566b2..0000000 --- a/doc/favicon.svg +++ /dev/null @@ -1,62 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> - <path d="M 0 8 L 1 8 L 1 9 L 0 9 L 0 8 Z" /> - <path d="M 0 13 L 1 13 L 1 14 L 0 14 L 0 13 Z" /> - <path d="M 1 8 L 2 8 L 2 9 L 1 9 L 1 8 Z" /> - <path d="M 1 13 L 2 13 L 2 14 L 1 14 L 1 13 Z" /> - <path d="M 2 8 L 3 8 L 3 9 L 2 9 L 2 8 Z" /> - <path d="M 2 13 L 3 13 L 3 14 L 2 14 L 2 13 Z" /> - <path d="M 3 8 L 4 8 L 4 9 L 3 9 L 3 8 Z" /> - <path d="M 3 13 L 4 13 L 4 14 L 3 14 L 3 13 Z" /> - <path d="M 4 7 L 5 7 L 5 8 L 4 8 L 4 7 Z" /> - <path d="M 4 8 L 5 8 L 5 9 L 4 9 L 4 8 Z" /> - <path d="M 4 13 L 5 13 L 5 14 L 4 14 L 4 13 Z" /> - <path d="M 5 6 L 6 6 L 6 7 L 5 7 L 5 6 Z" /> - <path d="M 5 7 L 6 7 L 6 8 L 5 8 L 5 7 Z" /> - <path d="M 5 13 L 6 13 L 6 14 L 5 14 L 5 13 Z" /> - <path d="M 6 5 L 7 5 L 7 6 L 6 6 L 6 5 Z" /> - <path d="M 6 6 L 7 6 L 7 7 L 6 7 L 6 6 Z" /> - <path d="M 6 14 L 7 14 L 7 15 L 6 15 L 6 14 Z" /> - <path d="M 7 1 L 8 1 L 8 2 L 7 2 L 7 1 Z" /> - <path d="M 7 14 L 8 14 L 8 15 L 7 15 L 7 14 Z" /> - <path d="M 7 15 L 8 15 L 8 16 L 7 16 L 7 15 Z" /> - <path d="M 7 2 L 8 2 L 8 3 L 7 3 L 7 2 Z" /> - <path d="M 7 3 L 8 3 L 8 4 L 7 4 L 7 3 Z" /> - <path d="M 7 4 L 8 4 L 8 5 L 7 5 L 7 4 Z" /> - <path d="M 7 5 L 8 5 L 8 6 L 7 6 L 7 5 Z" /> - <path d="M 8 1 L 9 1 L 9 2 L 8 2 L 8 1 Z" /> - <path d="M 8 15 L 9 15 L 9 16 L 8 16 L 8 15 Z" /> - <path d="M 9 1 L 10 1 L 10 2 L 9 2 L 9 1 Z" /> - <path d="M 9 2 L 10 2 L 10 3 L 9 3 L 9 2 Z" /> - <path d="M 9 6 L 10 6 L 10 7 L 9 7 L 9 6 Z" /> - <path d="M 9 15 L 10 15 L 10 16 L 9 16 L 9 15 Z" /> - <path d="M 10 2 L 11 2 L 11 3 L 10 3 L 10 2 Z" /> - <path d="M 10 3 L 11 3 L 11 4 L 10 4 L 10 3 Z" /> - <path d="M 10 4 L 11 4 L 11 5 L 10 5 L 10 4 Z" /> - <path d="M 10 5 L 11 5 L 11 6 L 10 6 L 10 5 Z" /> - <path d="M 10 6 L 11 6 L 11 7 L 10 7 L 10 6 Z" /> - <path d="M 11 6 L 12 6 L 12 7 L 11 7 L 11 6 Z" /> - <path d="M 11 8 L 12 8 L 12 9 L 11 9 L 11 8 Z" /> - <path d="M 10 15 L 11 15 L 11 16 L 10 16 L 10 15 Z" /> - <path d="M 11 10 L 12 10 L 12 11 L 11 11 L 11 10 Z" /> - <path d="M 11 12 L 12 12 L 12 13 L 11 13 L 11 12 Z" /> - <path d="M 11 14 L 12 14 L 12 15 L 11 15 L 11 14 Z" /> - <path d="M 11 15 L 12 15 L 12 16 L 11 16 L 11 15 Z" /> - <path d="M 12 6 L 13 6 L 13 7 L 12 7 L 12 6 Z" /> - <path d="M 12 8 L 13 8 L 13 9 L 12 9 L 12 8 Z" /> - <path d="M 12 10 L 13 10 L 13 11 L 12 11 L 12 10 Z" /> - <path d="M 12 12 L 13 12 L 13 13 L 12 13 L 12 12 Z" /> - <path d="M 12 14 L 13 14 L 13 15 L 12 15 L 12 14 Z" /> - <path d="M 13 6 L 14 6 L 14 7 L 13 7 L 13 6 Z" /> - <path d="M 13 8 L 14 8 L 14 9 L 13 9 L 13 8 Z" /> - <path d="M 13 10 L 14 10 L 14 11 L 13 11 L 13 10 Z" /> - <path d="M 13 12 L 14 12 L 14 13 L 13 13 L 13 12 Z" /> - <path d="M 13 13 L 14 13 L 14 14 L 13 14 L 13 13 Z" /> - <path d="M 13 14 L 14 14 L 14 15 L 13 15 L 13 14 Z" /> - <path d="M 14 7 L 15 7 L 15 8 L 14 8 L 14 7 Z" /> - <path d="M 14 8 L 15 8 L 15 9 L 14 9 L 14 8 Z" /> - <path d="M 14 9 L 15 9 L 15 10 L 14 10 L 14 9 Z" /> - <path d="M 14 10 L 15 10 L 15 11 L 14 11 L 14 10 Z" /> - <path d="M 14 11 L 15 11 L 15 12 L 14 12 L 14 11 Z" /> - <path d="M 14 12 L 15 12 L 15 13 L 14 13 L 14 12 Z" /> -</svg> diff --git a/doc/papo.CHANGELOG.en.7.in b/doc/papo.CHANGELOG.en.7.in deleted file mode 100644 index e69de29..0000000 --- a/doc/papo.CHANGELOG.en.7.in +++ /dev/null diff --git a/doc/papo.README.en.7.in b/doc/papo.README.en.7.in deleted file mode 100644 index e69de29..0000000 --- a/doc/papo.README.en.7.in +++ /dev/null diff --git a/doc/papo.TODOs.en.7.in b/doc/papo.TODOs.en.7.in deleted file mode 100644 index e69de29..0000000 --- a/doc/papo.TODOs.en.7.in +++ /dev/null @@ -8,12 +8,9 @@ varlist() { } export LANG=POSIX.UTF-8 -find src/*.c -not -name napi-sqlite.c | sort | varlist 'sources.c' find src/*.js -not -name index.js | sort | varlist 'sources.js' find tests/js/*.js | sort | varlist 'tests.js' find src/sql/migrations/*.sql | sort | varlist 'sources.sql' -sh tools/cdeps.sh `find src/*.c -not -name napi-sqlite.c | sort` - printf '\n' find tests/js/*.js | sort | sed 's|^\(.*\)$|\1-t: \1|' diff --git a/src/catalog.c b/src/catalog.c deleted file mode 100644 index c3ec9b2..0000000 --- a/src/catalog.c +++ /dev/null @@ -1,501 +0,0 @@ -#include "catalog.h" -#include "logerr.h" - -#include <assert.h> -#include <errno.h> -#include <nl_types.h> -#include <stdlib.h> -#include <string.h> - -#ifdef TEST -#include "../tests/tests-lib.h" -#include "../tests/slurp.h" - -static const char *const -FNAME = __FILE__ ".txt"; - -enum TEST_MSGCATALOG_ID { - MSG_X_FIRST = 1, - MSG_X_1, - MSG_X_2, - MSG_X_LAST, - MSG_STANDALONE, -}; - -static const char *const -TEST_MSGS[] = { - "", - [MSG_X_FIRST]="First line\n", - [MSG_X_1]="a second\n", - [MSG_X_2]="a third\n", - [MSG_X_LAST]="and the last one\n", - [MSG_STANDALONE]="single line message\n", - NULL -}; -#endif - - - -static const char *const -CATALOG_NAME = NAME_MACRO_STRING; - -static nl_catd -catalog_descriptor = NULL; - -static const char *const -NLSPATH = LOCALEDIR_MACRO_STRING "/%l_%t/LC_MESSAGES/%N.cat" ":" - LOCALEDIR_MACRO_STRING "/%l/LC_MESSAGES/%N.cat"; - -static const char *const -NLSPATH_KEY = "NLSPATH"; - - -int -i18n_init(void) { - int rc = 0; - - static const int should_overwrite = 0; - if (setenv(NLSPATH_KEY, NLSPATH, should_overwrite)) { - logerr("setenv(\"%s\", \"%s\", 0): %s\n", NLSPATH_KEY, - NLSPATH, strerror(errno)); - rc = -1; - goto out; - } - - catalog_descriptor = catopen(CATALOG_NAME, 0); - if (catalog_descriptor && catalog_descriptor == (nl_catd)-1) { - logerr("catopen(\"%s\", 0): %s\n", CATALOG_NAME, strerror(errno)); - catalog_descriptor = NULL; - rc = -1; - goto out; - } - -out: - return rc; -} - -#ifdef TEST -static int -test_i18n_init(void) { - int rc = 0; - - test_start("i18n_init()"); - - { - testing("simple call without touching the environment"); - - static const int should_overwrite = 1; - if (setenv(NLSPATH_KEY, "src/%N.en.cat", should_overwrite)) { - logerr("setenv(\"%s\", \"src/%%N.en.cat\", 1): %s\n", - NLSPATH_KEY, strerror(errno)); - rc = -1; - goto out; - } - - if (i18n_init()) { - logerr("i18n_init()\n"); - rc = -1; - goto out; - } - - test_ok(); - } - -out: - if (i18n_destroy()) { - logerr("i18n_destroy()\n"); - rc = -1; - } - return rc; -} -#endif - - -int -i18n_destroy(void) { - int rc = 0; - - if (catalog_descriptor) { - if (catclose(catalog_descriptor)) { - logerr("catclose(...): %s\n", strerror(errno)); - rc = -1; - goto out; - } - } - -out: - if (catalog_descriptor) { - catalog_descriptor = NULL; - } - return rc; -} - -#ifdef TEST -static int -test_i18n_destroy(void) { - int rc = 0; - - test_start("i18n_destroy()"); - - { - testing("simple call without init first"); - - if (i18n_destroy()) { - logerr("i18n_destroy()\n"); - rc = -1; - goto out; - } - - test_ok(); - } - -out: - return rc; -} -#endif - - -/** - * Infallible: always returns a valid string, no matter what. - */ -const char * -s(const char* const MSGS[], const int msg_id) { - assert(msg_id > 0); - // FIXME: assert within bounds! - // printf("sizeof(MSGS): %ld\n", sizeof(MSGS)); - if (!catalog_descriptor) { - return MSGS[msg_id]; - } - - errno = 0; - const char *const ret = - catgets(catalog_descriptor, NL_SETD, msg_id, MSGS[msg_id]); - if (errno) { - logerr("catgets(%d): %s\n", msg_id, strerror(errno)); - } - - return ret; -} - -#ifdef TEST -static int -test_s(void) { - int rc = 0; - - test_start("_()"); - FILE *file = NULL; - char *str = NULL; - - { - testing("empty string"); - - file = fopen(FNAME, "w"); - if (!file) { - perror("fopen(FNAME, \"w\")"); - rc = -1; - goto out; - } - - // FIXME: implement correct test - - - - test_ok(); - } - -out: - if (str) { - free(str); - } - if (file) { - if (fclose(file)) { - logerr("fclose(file): %s\n", strerror(errno)); - rc = -1; - } - } - return rc; -} -#endif - - -int -s_print_msgs( - const char *const MSGS[], - FILE *restrict stream, - const int msg_begin, - const int msg_end -) { - int rc = 0; - - for (int i = msg_begin; i <= msg_end; i++) { - if (fprintf(stream, "%s", s(MSGS, i)) < 0) { - logerr("fprintf(stream, \"%%s\", _(%d)): %s\n", i, - strerror(errno)); - rc = -1; - goto out; - } - } - -out: - return rc; -} - -#ifdef TEST -static int -test_s_print_msgs(void) { - int rc = 0; - - test_start("s_print_msgs()"); - FILE *file = NULL; - char *str = NULL; - - { - testing("message in range"); - - file = fopen(FNAME, "w"); - if (!file) { - perror("fopen(FNAME, \"w\")"); - rc = -1; - goto out; - } - - if (s_print_msgs(TEST_MSGS, file, MSG_X_FIRST, MSG_X_LAST)) { - logerr("print_msgs(TEST_MSGS, file, MSG_X_FIRST, MSG_X_LAST)\n"); - rc = -1; - goto out; - } - - const int ret = fclose(file); - file = NULL; - if (ret) { - logerr("fclose(file): %s\n", strerror(errno)); - rc = -1; - goto out; - } - - if (slurp_for_tests(FNAME, &str)) { - logerr("slurp_for_tests(FNAME, &str)\n"); - rc = -1; - goto out; - } - - const char *const expected = - "First line\n" - "a second\n" - "a third\n" - "and the last one\n" - ; - - assert(strcmp(expected, str) == 0); - - free(str); - str = NULL; - - test_ok(); - } - { - testing("range begin and end is the same"); - - file = fopen(FNAME, "w"); - if (!file) { - logerr("fopen(FNAME, \"w\"): %s\n", strerror(errno)); - rc = -1; - goto out; - } - - if (s_print_msgs(TEST_MSGS, file, MSG_X_FIRST, MSG_X_FIRST)) { - logerr("s_print_msgs(TEST_MSGS, file, MSG_X_FIRST, MSG_X_FIRST)\n"); - rc = -1; - goto out; - } - - const int ret = fclose(file); - file = NULL; - if (ret) { - logerr("fclose(file): %s\n", strerror(errno)); - rc = -1; - goto out; - } - - if (slurp_for_tests(FNAME, &str)) { - logerr("slurp_for_tests(FNAME, &str)\n"); - rc = -1; - goto out; - } - - const char *const expected = - "First line\n"; - - assert(strcmp(expected, str) == 0); - - free(str); - str = NULL; - - test_ok(); - } - -out: - if (str) { - free(str); - } - if (file) { - if (fclose(file)) { - logerr("fclose(file): %s\n", strerror(errno)); - rc = -1; - } - } - return rc; -} -#endif - - -int -s_print_msg(const char *const MSGS[], FILE *const fd, const int msg_id) { - return s_print_msgs(MSGS, fd, msg_id, msg_id); -} - -#ifdef TEST -static int -test_s_print_msg(void) { - int rc = 0; - - test_start("s_print_msg()"); - FILE *file = NULL; - char *str = NULL; - - { - testing("simple individual message"); - - file = fopen(FNAME, "w"); - if (!file) { - logerr("fopen(FNAME, \"w\"): %s\n"); - rc = -1; - goto out; - } - - if (s_print_msg(TEST_MSGS, file, MSG_STANDALONE)) { - logerr("s_print_msg(TEST_MSGS, file, MSG_STANDALONE)\n"); - rc = -1; - goto out; - } - - const int ret = fclose(file); - file = NULL; - if (ret) { - logerr("fopen(file): %s\n", strerror(errno)); - rc = -1; - goto out; - } - - if (slurp_for_tests(FNAME, &str)) { - logerr("slurp_for_tests(FNAME, &str)\n"); - rc = -1; - goto out; - } - - const char *const expected = - "single line message\n"; - - assert(strcmp(expected, str) == 0); - - free(str); - str = NULL; - - test_ok(); - } - -out: - if (str) { - free(str); - } - if (file) { - if (fclose(file)) { - logerr("fclose(file): %s\n", strerror(errno)); - rc = -1; - } - } - return rc; -} -#endif - - -int -dump_translatable_strings(const char *const MSGS[]) { - int rc = 0; - - for (size_t i = 1; MSGS[i]; i++) { - if (printf("%ld ", i) < 0) { - logerr("printf(\"%%ld\", %d): %s\n", i); - rc = -1; - goto out; - } - - for (size_t j = 0; MSGS[i][j]; j++) { - if (MSGS[i][j] == '\n') { - if (printf("\\n") < 0) { - logerr("printf(\"\\\\n\"): %s\n", - strerror(errno)); - rc = -1; - goto out; - } - } else { - if (printf("%c", MSGS[i][j]) < 0) { - logerr("printf(\"%%c\", " - "MSGS[%ld][%ld]): %s\n", - i, j, strerror(errno)); - rc = -1; - goto out; - } - } - } - - if (printf("\n\n") < 0) { - logerr("printf(\"\\n\\n\"): %s\n", strerror(errno)); - rc = -1; - goto out; - } - } - -out: - return rc; -} - -#ifdef TEST -int -main(void) { - int rc = 0; - - if (test_i18n_init()) { - logerr("test_i18n_init()\n"); - rc = -1; - goto out; - } - - if (test_i18n_destroy()) { - logerr("test_i18n_destroy()\n"); - rc = -1; - goto out; - } - - if (test_s()) { - logerr("test_s()\n"); - rc = -1; - goto out; - } - - if (test_s_print_msgs()) { - logerr("test_s_print_msgs()\n"); - rc = -1; - goto out; - } - - if (test_s_print_msg()) { - logerr("test_s_print_msg()\n"); - rc = -1; - goto out; - } - -out: - return !!rc; -} -#endif diff --git a/src/catalog.h b/src/catalog.h deleted file mode 100644 index 9f237a9..0000000 --- a/src/catalog.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef CATALOG_H -#define CATALOG_H - -#include "config.h" - -#include <stdio.h> - - -int -i18n_init(void); - -int -i18n_destroy(void); - -const char * -s(const char *const MSGS[], const int msg_id); - -int -s_print_msgs( - const char *const MSGS[], - FILE *restrict stream, - const int msg_begin, - const int msg_end -); - -int -s_print_msg(const char *const MSGS[], FILE *restrict stream, const int msg_id); - -int -dump_translatable_strings(const char *const MSGS[]); - - -#endif diff --git a/src/config.h.in b/src/config.h.in deleted file mode 100644 index dc379e5..0000000 --- a/src/config.h.in +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - - - -/* - From - https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_02_01: - - > For the C programming language, shall define _POSIX_C_SOURCE to be 200809L - > before any header is included -*/ -#define _POSIX_C_SOURCE 200809L - - -/* - From - https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_02_04: - - > For the C programming language, shall define _XOPEN_SOURCE to be 700 before - > any header is included -*/ -#define _XOPEN_SOURCE 700 - - -#define VERSION_MACRO_STRING "@VERSION@" -#define DATE_MACRO_STRING "@DATE@" -#define NAME_MACRO_STRING "@NAME@" -#define LOCALEDIR_MACRO_STRING "@LOCALEDIR@" - -#endif diff --git a/src/i18n.c b/src/i18n.c deleted file mode 100644 index 4363582..0000000 --- a/src/i18n.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "i18n.h" - -#ifdef TEST -#include "logerr.h" -#include "catalog.h" - -#include <stdlib.h> -#endif - -const char *const -MSGS[] = { - "", - [MSG_USAGE_FIRST]="Usage:\n", - [MSG_USAGE_1]=" " NAME_MACRO_STRING " -p FILE [-o DIRECTORY]\n", - [MSG_USAGE_2]=" " NAME_MACRO_STRING " -l FILE [-o DIRECTORY]\n", - [MSG_USAGE_LAST]=" " NAME_MACRO_STRING " [-hV]\n", - [MSG_HELP_FIRST]="\n", - [MSG_HELP_1]="\n", - [MSG_HELP_2]="Options:\n", - [MSG_HELP_3]=" -p FILE parser file to be processed\n", - [MSG_HELP_4]=" -l FILE lexer file to be processed\n", - [MSG_HELP_5]=" -o DIRECTORY output where to place the\n", - [MSG_HELP_6]=" generated files (default .)\n", - [MSG_HELP_7]=" -h, --help show this help message\n", - [MSG_HELP_8]=" -V, --version print the version number\n", - [MSG_HELP_9]="\n", - [MSG_HELP_10]="\n", - [MSG_HELP_11]="Run the " NAME_MACRO_STRING "(1) parser program.\n", - [MSG_HELP_12]="\n", - [MSG_HELP_13]="Here is the explanation for what it does, and the synopsis\n", - [MSG_HELP_14]="of its usage.\n", - [MSG_HELP_15]="\n", - [MSG_HELP_16]="See \"man " NAME_MACRO_STRING "\" for usage information and\n", - [MSG_HELP_17]="\"man " NAME_MACRO_STRING ".tutorial\" for a beginner introduction.\n", - [MSG_HELP_18]="\n", - [MSG_HELP_19]="\n", - [MSG_HELP_20]="Examples:\n", - [MSG_HELP_21]="\n", - [MSG_HELP_22]=" Do a one-line parser:\n", - [MSG_HELP_23]="\n", - [MSG_HELP_24]=" $ " NAME_MACRO_STRING " run md.grammar < README.md\n", - [MSG_HELP_25]="\n", - [MSG_HELP_26]="\n", - [MSG_HELP_27]=" Compile the grammer:\n", - [MSG_HELP_28]="\n", - [MSG_HELP_LAST]=" $ " NAME_MACRO_STRING " build csv.grammar > dunno.alsodunno\n", - [MSG_VERSION]= NAME_MACRO_STRING " " VERSION_MACRO_STRING " " DATE_MACRO_STRING "\n", - [MSG_ERR_NAPI_MISSING_ERRSTR]="Error message from Node-API is empty", - NULL -}; - - -#ifdef TEST -int -main(void) { - int rc = 0; - - if (getenv("DUMP_TRANSLATABLE_STRINGS")) { - if (dump_translatable_strings(MSGS)) { - logerr("dump_translatable_strings(MSGS)\n"); - rc = -1; - goto out; - } - } - -out: - return !!rc; -} -#endif diff --git a/src/i18n.h b/src/i18n.h deleted file mode 100644 index 2b18bbc..0000000 --- a/src/i18n.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef I18N_H -#define I18N_H - -#include "config.h" -#include "catalog.h" - -#include <stdio.h> - - -enum MSGCATALOG_ID { - MSG_USAGE_FIRST = 1, - MSG_USAGE_1, - MSG_USAGE_2, - MSG_USAGE_LAST, - MSG_HELP_FIRST, - MSG_HELP_1, - MSG_HELP_2, - MSG_HELP_3, - MSG_HELP_4, - MSG_HELP_5, - MSG_HELP_6, - MSG_HELP_7, - MSG_HELP_8, - MSG_HELP_9, - MSG_HELP_10, - MSG_HELP_11, - MSG_HELP_12, - MSG_HELP_13, - MSG_HELP_14, - MSG_HELP_15, - MSG_HELP_16, - MSG_HELP_17, - MSG_HELP_18, - MSG_HELP_19, - MSG_HELP_20, - MSG_HELP_21, - MSG_HELP_22, - MSG_HELP_23, - MSG_HELP_24, - MSG_HELP_25, - MSG_HELP_26, - MSG_HELP_27, - MSG_HELP_28, - MSG_HELP_LAST, - MSG_VERSION, - MSG_ERR_NAPI_MISSING_ERRSTR, -}; - - -extern const char *const -MSGS[]; - -#define _(msg_id) s(MSGS, msg_id) - - -#endif diff --git a/src/logerr.c b/src/logerr.c deleted file mode 100644 index 936bd28..0000000 --- a/src/logerr.c +++ /dev/null @@ -1,301 +0,0 @@ -#include "logerr.h" - -#include <stdarg.h> -#include <stdlib.h> - -#ifdef TEST -#include "../tests/tests-lib.h" -#include "../tests/slurp.h" -#include <assert.h> -#include <errno.h> -#include <string.h> -#endif - - -void -vlogerr( - const char *const file, - const char *const function, - const int lineno, - FILE *restrict stream, - const char *restrict format, - ... -) { - (void)fprintf(stream, "%s:%s:%d: ", file, function, lineno); - - va_list args; - va_start(args, format); - (void)vfprintf(stream, format, args); - va_end(args); -} - -#ifdef TEST -static const char *const -FNAME = __FILE__ ".txt"; - -static int -test_vlogerr(void) { - int rc = 0; - - test_start("vlogerr()"); - FILE *file = NULL; - char *str = NULL; - - { - testing("empty varargs"); - - file = fopen(FNAME, "w"); - if (!file) { - perror("fopen(FNAME, \"w\")"); - rc = -1; - goto out; - } - - vlogerr(__FILE__, __func__, __LINE__, file, - ""); - - const int ret = fclose(file); - file = NULL; - if (ret) { - perror("fclose(file)"); - rc = -1; - goto out; - } - - if (slurp_for_tests(FNAME, &str)) { - perror("slurp_for_tests(FNAME, &str)"); - rc = -1; - goto out; - } - - const char *const expected = - "src/logerr.c:test_vlogerr:54: "; - - assert(strcmp(expected, str) == 0); - - free(str); - str = NULL; - - test_ok(); - } - { - testing("a newline only"); - - file = fopen(FNAME, "w"); - if (!file) { - perror("fopen(FNAME, \"w\")"); - rc = -1; - goto out; - } - - vlogerr(__FILE__, __func__, __LINE__, file, - "\n"); - - const int ret = fclose(file); - file = NULL; - if (ret) { - perror("fclose(file)"); - rc = -1; - goto out; - } - - if (slurp_for_tests(FNAME, &str)) { - perror("slurp_for_tests(FNAME, &str)"); - rc = -1; - goto out; - } - - const char *const expected = - "src/logerr.c:test_vlogerr:91: \n"; - assert(strcmp(expected, str) == 0); - - free(str); - str = NULL; - - test_ok(); - } - { - testing("static format string"); - - file = fopen(FNAME, "w"); - if (!file) { - perror("fopen(FNAME, \"w\")"); - rc = -1; - goto out; - } - - vlogerr(__FILE__, __func__, __LINE__, file, - "some static string\n"); - - const int ret = fclose(file); - file = NULL; - if (ret) { - perror("fclose(file)"); - rc = -1; - goto out; - } - - if (slurp_for_tests(FNAME, &str)) { - perror("slurp_for_tests(FNAME, &str)"); - rc = -1; - goto out; - } - - const char *const expected = - "src/logerr.c:test_vlogerr:127: some static string\n"; - assert(strcmp(expected, str) == 0); - - free(str); - str = NULL; - - test_ok(); - } - { - testing("single arg format string"); - - file = fopen(FNAME, "w"); - if (!file) { - perror("fopen(FNAME, \"w\")"); - rc = -1; - goto out; - } - - vlogerr(__FILE__, __func__, __LINE__, file, - "fn(%s)\n", "an-arg"); - - const int ret = fclose(file); - file = NULL; - if (ret) { - perror("fclose(file)"); - rc = -1; - goto out; - } - - if (slurp_for_tests(FNAME, &str)) { - perror("slurp_for_tests(FNAME, &str)"); - rc = -1; - goto out; - } - - const char *const expected = - "src/logerr.c:test_vlogerr:163: fn(an-arg)\n"; - assert(strcmp(expected, str) == 0); - - free(str); - str = NULL; - - test_ok(); - } - { - testing("multiple format strings"); - - file = fopen(FNAME, "w"); - if (!file) { - perror("fopen(FNAME, \"w\")"); - rc = -1; - goto out; - } - - vlogerr(__FILE__, __func__, __LINE__, file, - "int (%d), string (%s) and char (%c)\n", - 123, - "another-str", - 'z'); - - const int ret = fclose(file); - file = NULL; - if (ret) { - perror("fclose(file)"); - rc = -1; - goto out; - } - - if (slurp_for_tests(FNAME, &str)) { - perror("slurp_for_tests(FNAME, &str)"); - rc = -1; - goto out; - } - - const char *const expected = - "src/logerr.c:test_vlogerr:199: " - "int (123), string (another-str) and char (z)\n"; - assert(strcmp(expected, str) == 0); - - free(str); - str = NULL; - - test_ok(); - } - -out: - if (str) { - free(str); - } - if (file) { - if (fclose(file)) { - perror("fclose(file)"); - rc = -1; - } - } - return rc; -} - -static int -test_logerr(void) { - int rc = 0; - - test_start("logerr()"); - - { - testing("can be called with an empty string"); - - logerr(""); - - test_ok(); - } - { - testing("can be called with a static string"); - - logerr("some err\n"); - - test_ok(); - } - { - testing("can be called with a formatted string"); - - logerr("some err: %s\n", strerror(errno)); - - test_ok(); - } - { - testing("can be called with formatting arguments"); - - logerr("int: %d\nstr: %s\n", 123, "an example string"); - - test_ok(); - } - - return rc; -} - - -int -main(void) { - int rc = 0; - - if (test_vlogerr()) { - perror("test_vlogerr()"); - rc = -1; - goto out; - } - - if (test_logerr()) { - perror("test_logerr()"); - rc = -1; - goto out; - } - -out: - return !!rc; -} -#endif diff --git a/src/logerr.h b/src/logerr.h deleted file mode 100644 index 77f98bd..0000000 --- a/src/logerr.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef LOGERR_H -#define LOGERR_H - -#include "config.h" - -#include <stdio.h> - - -void -vlogerr( - - const char *const file, - const char *const function, - const int lineno, - FILE *restrict stream, - const char *restrict format, - ... -); - -#define logerr(...) vlogerr(__FILE__, __func__, __LINE__, stderr, __VA_ARGS__) - - -#endif diff --git a/src/napi-sqlite.c b/src/napi-sqlite.c deleted file mode 100644 index d4352a2..0000000 --- a/src/napi-sqlite.c +++ /dev/null @@ -1,932 +0,0 @@ -#include "i18n.h" -#include "logerr.h" - -#include <assert.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <node/node_api.h> -#include <sqlite3.h> - - -static napi_value ffi_open(napi_env env, napi_callback_info info); -static napi_value ffi_exec(napi_env env, napi_callback_info info); -static napi_value ffi_all (napi_env env, napi_callback_info info); -static napi_value ffi_run (napi_env env, napi_callback_info info); - - -struct NAPIContext { - napi_env env; - napi_value value; - uint32_t index; -}; - -struct Fn { - const char *const label; - napi_value(*const handle)(napi_env env, napi_callback_info info); -}; - -static const struct Fn fns[] = { - { .label = "open", .handle = ffi_open, }, - { NULL, NULL }, -}; - -struct Fn methods[] = { - { .label = "exec", .handle = ffi_exec, }, - { .label = "all", .handle = ffi_all, }, - { .label = "run", .handle = ffi_run, }, - { NULL, NULL }, -}; - -static const napi_type_tag SQLITE_DB_TYPE_TAG = { - 0x0e9614d459f746cc, 0x88b814a5dc5c4cf7 -}; - -static const int -SQLITE_OPEN_FLAGS = - /* - From https://www.sqlite.org/c3ref/open.html: - - > The database is opened for reading and writing, and is created if - > it does not already exist. This is the behavior that is always - > used for sqlite3_open() and sqlite3_open16(). - */ - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | - - /* - From https://www.sqlite.org/c3ref/open.html: - - > The new database connection will use the "serialized" threading - > mode. This means the multiple threads can safely attempt to use - > the same database connection at the same time. (Mutexes will block - > any actual concurrency, but in this mode there is no harm in - > trying.) - */ - SQLITE_OPEN_FULLMUTEX | - - /* - From https://www.sqlite.org/c3ref/open.html: - - > The database connection comes up in "extended result code mode". - > In other words, the database behaves has if - > sqlite3_extended_result_codes(db,1) where called on the database - > connection as soon as the connection is created. In addition to - > setting the extended result code mode, this flag also causes - > sqlite3_open_v2() to return an extended result code. - - From https://www.sqlite.org/c3ref/extended_result_codes.html: - - > The sqlite3_extended_result_codes() routine enables or disables the - > extended result codes feature of SQLite. The extended result codes - > are disabled by default for historical compatibility. - */ - SQLITE_OPEN_EXRESCODE; - - -static const char *const -FIX_SQLITE_PRAGMAS = - /* - From https://research.cs.wisc.edu/adsl/Publications/alice-osdi14.pdf: - - > Similarly, SQLite does not provide durability under the default - > journal-mode (we became aware of this only after interacting with - > developers), but its documentation seems misleading. - > - > (...) - > - > The developers suggest the SQLite vulnerability is actually not a - > behavior guaranteed by SQLite (specifically, that durability cannot - > be achieved under rollback journaling); we believe the - > documentation is misleading. - > - > (...) - > - > Unclear documentation of application guarantees contributes to the - > confusion about crash vulnerabilities. During discussions with - > developers about durability vulnerabilities, we found that SQLite, - > which proclaims itself as fully ACID-complaint, does not provide - > durability (even optionally) with the default storage engine, - > though the documentation suggests it does. - */ - "PRAGMA journal_mode = WAL;\n" - "PRAGMA synchronous = EXTRA;\n" - - /* - From https://www.sqlite.org/foreignkeys.html: - - > Foreign key constraints are disabled by default (for backwards - > compatibility), so must be enabled separately for each database - > connection. - */ - "PRAGMA foreign_keys = ON;\n" - ; - - -// FIXME: make this async -static napi_value -ffi_exec(napi_env env, napi_callback_info info) { - size_t argc = 1; - napi_value argv[1]; - int sqlite_rc; - napi_status napi_rc; - char *sql = NULL; - size_t sql_size1; - size_t sql_size2; - sqlite3 *db = NULL; - char *error_msg = NULL; - - napi_rc = napi_get_cb_info( - env, - info, - &argc, - argv, - NULL, - (void *)&db - ); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "111TODO ERRCODE", - "Failed to parse arguments TODO i18n" - ); - goto out; - } - - napi_rc = napi_get_value_string_utf8(env, argv[0], NULL, 0, &sql_size1); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "222TODO ERRCODE", - "Invalid number was passed as argument TODO i18n" - ); - goto out; - } - - if (sql_size1 == SIZE_MAX) { - napi_throw_error( - env, - "SQLITE_EOVERFLOW", - "TODO " - ); - goto out; - } - sql_size1++; // include the NULL-terminator in size measurement - - sql = malloc(sql_size1); - if (!sql) { - napi_throw_error( - env, - "SQLITE_ENOMEM", - "TODO i18n" - ); - goto out; - } - - napi_rc = napi_get_value_string_utf8( - env, - argv[0], - sql, - sql_size1, - &sql_size2 - ); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "TODO ERRCODE", - "Invalid number was passed as argument TODO i18n" - ); - goto out; - } - assert(sql_size1 == sql_size2 + 1 && - "Unstable behaviour from Node-API"); - assert(sql); - - sqlite_rc = sqlite3_exec( - db, - sql, - NULL, - NULL, - &error_msg - ); - if (sqlite_rc != SQLITE_OK) { - napi_throw_error( - env, - "3iii33TODO ERRCODE", - sqlite3_errstr(sqlite_rc) - ); - goto out; - } - -out: - if (error_msg) { - sqlite3_free(error_msg); - } - if (sql) { - free(sql); - } - return NULL; -} - - -static int -accumulate_all_results( - void *ctxptr, - int argc, - char **argv, - char **column_names -) { - int rc = 0; - - napi_status napi_rc; - napi_value row = NULL; - - struct NAPIContext *ctx = ctxptr; - napi_env env = ctx->env; - napi_value results = ctx->value; - uint32_t index = ctx->index; - - napi_rc = napi_create_object(env, &row); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "TODO ERRCODE", - "TODO i18n" - ); - rc = -1; - goto out; - } - - for (int i = 0; i < argc; i++) { - const char *const column_name = column_names[i]; - const char *const column_value = argv[i]; - - napi_value str; // FIXME: dispatch on the type - napi_rc = napi_create_string_utf8( - env, - column_value, - NAPI_AUTO_LENGTH, - &str - ); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "SQLITE_MiiiETHOD_CREATE", - "TODO i18n" - ); - rc = -1; - goto out; - } - - napi_rc = napi_set_named_property( - env, - row, - column_name, - str - ); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "iSQLITE_MiETHOD_CREATE", - "TODO i18n" - ); - rc = -1; - goto out; - } - } - - napi_rc = napi_set_element( - env, - results, - index, - row - ); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "TODO ERRCODE", - "TODO i18n" - ); - rc = -1; - goto out; - } - - ctx->index++; - -out: - return rc; -} - -static napi_value -ffi_all(napi_env env, napi_callback_info info) { - napi_value ret = NULL; - - size_t argc = 1; - napi_value argv[1]; - int sqlite_rc; - napi_status napi_rc; - char *sql = NULL; - size_t sql_size1; - size_t sql_size2; - sqlite3 *db = NULL; - char *error_msg = NULL; - napi_value results_array = NULL; - - napi_rc = napi_get_cb_info( - env, - info, - &argc, - argv, - NULL, - (void *)&db - ); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "111TODO ERRCODE", - "Failed to parse arguments TODO i18n" - ); - goto out; - } - - napi_rc = napi_get_value_string_utf8(env, argv[0], NULL, 0, &sql_size1); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "222TODO ERRCODE", - "Invalid number was passed as argument TODO i18n" - ); - goto out; - } - - if (sql_size1 == SIZE_MAX) { - napi_throw_error( - env, - "SQLITE_EOVERFLOW", - "TODO " - ); - goto out; - } - sql_size1++; // include the NULL-terminator in size measurement - - sql = malloc(sql_size1); - if (!sql) { - napi_throw_error( - env, - "SQLITE_ENOMEM", - "TODO i18n" - ); - goto out; - } - - napi_rc = napi_get_value_string_utf8( - env, - argv[0], - sql, - sql_size1, - &sql_size2 - ); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "TODO ERRCODE", - "Invalid number was passed as argument TODO i18n" - ); - goto out; - } - assert(sql_size1 == sql_size2 + 1 && - "Unstable behaviour from Node-API"); - assert(sql); - - napi_rc = napi_create_array(env, &results_array); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "TODO ERRCODE", - "Invalid number was passed as argument TODO i18n" - ); - goto out; - } - - struct NAPIContext ctx = { - .env = env, - .value = results_array, - .index = 0, - }; - sqlite_rc = sqlite3_exec( - db, - sql, - accumulate_all_results, - &ctx, - &error_msg - ); - if (sqlite_rc != SQLITE_OK) { - napi_throw_error( - env, - "i3iiii33TODO ERRCODE", - sqlite3_errstr(sqlite_rc) - ); - goto out; - } - - ret = results_array; - -out: - if (error_msg) { - sqlite3_free(error_msg); - } - if (sql) { - free(sql); - } - return ret; -} - -static napi_value -ffi_run(napi_env env, napi_callback_info info) { - napi_value ret = NULL; - - size_t argc = 1; - napi_value argv[1]; - int sqlite_rc; - napi_status napi_rc; - char *sql = NULL; - size_t sql_size1; - size_t sql_size2; - sqlite3 *db = NULL; - char *error_msg = NULL; - napi_value results_array = NULL; - - napi_rc = napi_get_cb_info( - env, - info, - &argc, - argv, - NULL, - (void *)&db - ); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "111TODO ERRCODE", - "Failed to parse arguments TODO i18n" - ); - goto out; - } - - napi_rc = napi_get_value_string_utf8(env, argv[0], NULL, 0, &sql_size1); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "222TODO ERRCODE", - "Invalid number was passed as argument TODO i18n" - ); - goto out; - } - - if (sql_size1 == SIZE_MAX) { - napi_throw_error( - env, - "SQLITE_EOVERFLOW", - "TODO " - ); - goto out; - } - sql_size1++; // include the NULL-terminator in size measurement - - sql = malloc(sql_size1); - if (!sql) { - napi_throw_error( - env, - "SQLITE_ENOMEM", - "TODO i18n" - ); - goto out; - } - - napi_rc = napi_get_value_string_utf8( - env, - argv[0], - sql, - sql_size1, - &sql_size2 - ); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "TODO ERRCODE", - "Invalid number was passed as argument TODO i18n" - ); - goto out; - } - assert(sql_size1 == sql_size2 + 1 && - "Unstable behaviour from Node-API"); - assert(sql); - - napi_rc = napi_create_array(env, &results_array); - if (napi_rc != napi_ok) { - napi_throw_error( - env, - "TODO ERRCODE", - "Invalid number was passed as argument TODO i18n" - ); - goto out; - } - - struct NAPIContext ctx = { - .env = env, - .value = results_array, - .index = 0, - }; - sqlite_rc = sqlite3_exec( - db, - sql, - accumulate_all_results, - &ctx, - &error_msg - ); - if (sqlite_rc != SQLITE_OK) { - napi_throw_error( - env, - "i3iiii33TODO ERRCODE", - sqlite3_errstr(sqlite_rc) - ); - goto out; - } - - ret = results_array; - -out: - if (error_msg) { - sqlite3_free(error_msg); - } - if (sql) { - free(sql); - } - return ret; -} - - -static void -sqlite_error_log_callback(void *_data, int rc, const char *const msg) { - (void)_data; - logerr("%s\n%s\n", sqlite3_errstr(rc), msg); -} - -static void -throw_sqlite_error(napi_env env, sqlite3 *const db) { - const char *const errstr = sqlite3_errstr(sqlite3_errcode(db)); - const char *const errmsg = sqlite3_errmsg(db); - logerr("%s\n%s\n", errstr, errmsg); - if (napi_throw_error(env, errstr, errmsg)) { - logerr("napi_throw_err(%s, \"%s\", \"%s\");\n", - "env", - errstr, - errmsg); - goto out; - } - -out: - return; -} - -static void -throw_node_str_error( - napi_env env, - const char *const errstr, - const char *const errmsg -) { - bool is_pending; - - if (napi_is_exception_pending(env, &is_pending)) { - logerr("napi_is_exception_pending(%s, %s);\n", - "env", - "&is_pending"); - goto out; - } - - if (is_pending) { - logerr("exception already pending, not rethrowing"); - goto out; - } - - logerr("%s\n%s\n", errstr, errmsg); - if (napi_throw_error(env, errstr, errmsg)) { - logerr("napi_throw_error(%s, \"%s\", \"%s\");\n" - "env", - errstr, - errmsg); - goto out; - } - -out: - return; -} - -static void -throw_node_env_error(napi_env env) { - const napi_extended_error_info *error_info = NULL; - - if (napi_get_last_error_info(env, &error_info)) { - logerr("napi_get_last_error_info(%s, %s);\n", - "env", - "&error_info"); - goto out; - } - - const char *const errstr = "SQLITE_NAPI_ERR"; - const char *const errmsg = - error_info->error_message ? - error_info->error_message : - _(MSG_ERR_NAPI_MISSING_ERRSTR); - throw_node_str_error(env, errstr, errmsg); - -out: - return; -} - -static void -finalize_db(napi_env env, void *finalize_data, void *_finalize_hint) { - (void)_finalize_hint; - sqlite3 *db = finalize_data; - - if (sqlite3_close(db)) { - logerr("sqlite3_close(%s);\n", - "db"); - throw_sqlite_error(env, db); - goto out; - } - -out: - return; -} - -static napi_value -ffi_open(napi_env env, napi_callback_info info) { - napi_value ret = NULL; - - size_t argc = 1; - napi_value argv[1]; - char *filename = NULL; - size_t filename_size1; - size_t filename_size2; - sqlite3 *db = NULL; - napi_value wrapped_db = NULL; - char *error_msg = NULL; - - if (napi_get_cb_info(env, info, &argc, argv, NULL, NULL)) { - logerr("napi_get_cb_info(%s, %s, %s, %s, %s, %s);\n", - "env", - "info", - "&argc", - "argv", - "NULL", - "NULL"); - throw_node_env_error(env); - goto out; - } - - if (napi_get_value_string_utf8( - env, - argv[0], - NULL, // first we query the size of the string - 0, - &filename_size1 - )) { - logerr("napi_get_value_string_utf8(%s, %s, %s, %s, %s);\n", - "env", - "argv[0]", - "NULL", - "0", - "&filename_size1"); - throw_node_env_error(env); - goto out; - } - - if (filename_size1 == SIZE_MAX) { - logerr("%s: filename_size1 == SIZE_MAX;\n", strerror(EOVERFLOW)); - throw_node_str_error(env, "EOVERFLOW", strerror(EOVERFLOW)); - goto out; - } - filename_size1++; // include the NULL-terminator in size measurement - - filename = malloc(filename_size1); - if (!filename) { - logerr("malloc(filename_size1): %s\n", strerror(errno)); - throw_node_str_error(env, "ENOMEM", strerror(ENOMEM)); - goto out; - } - - if (napi_get_value_string_utf8( - env, - argv[0], - filename, - filename_size1, - &filename_size2 - )) { - logerr("napi_get_value_string_utf8(%s, %s, %s, %s, %s);\n", - "env", - "argv[0]", - "filename", - "filename_size1", - "&filename_size2"); - throw_node_env_error(env); - goto out; - } - assert(filename_size1 == filename_size2 + 1 && - "Unstable behaviour from Node-API"); - assert(filename && "filename should not be NULL at this point"); - - if (sqlite3_open_v2( - filename, - &db, - SQLITE_OPEN_FLAGS, - NULL - )) { - logerr("sqlite3_open_v2(%s, %s, %s, %s);\n", - "filename", - "&db", - "SQLITE_OPEN_FLAGS", - "NULL"); - throw_node_env_error(env); - goto out; - } - - if (sqlite3_config( - SQLITE_CONFIG_LOG, - sqlite_error_log_callback, - NULL - )) { - logerr("sqlite3_config(%s, %s, %s);\n", - "SQLITE_CONFIG_LOG", - "sqlite_error_log_callback", - "NULL"); - throw_sqlite_error(env, db); - goto out; - } - - if (sqlite3_exec( - db, - FIX_SQLITE_PRAGMAS, - NULL, - NULL, - &error_msg - )) { - logerr("sqlite3_exec(%s, %s, %s, %s, %s);\n", - "db", - "FIX_SQLITE_PRAGMAS", - "NULL", - "NULL", - "&error_msg"); - throw_sqlite_error(env, db); - goto out; - } - - if (napi_create_object(env, &wrapped_db)) { - logerr("napi_create_object(%s, %s);\n", - "env", - "&wrapped_db"); - throw_node_env_error(env); - goto out; - } - - if (napi_type_tag_object( - env, - wrapped_db, - &SQLITE_DB_TYPE_TAG - )) { - logerr("napi_type_tag_object(%s, %s, %s);\n", - "env", - "wrapped_db", - "&SQLITE_DB_TYPE_TAG"); - throw_node_env_error(env); - goto out; - } - - if (napi_wrap( - env, - wrapped_db, - db, - finalize_db, - NULL, - NULL - )) { - logerr("napi_wrap(%s, %s, %s, %s, %s, %s);\n", - "env", - "wrapped_db", - "db", - "finalize_db", - "NULL", - "NULL"); - throw_node_env_error(env); - goto out; - } - - for (size_t i = 0; methods[i].label && methods[i].handle; i++) { - napi_value fn; - if (napi_create_function( - env, - methods[i].label, - NAPI_AUTO_LENGTH, - methods[i].handle, - db, - &fn - )) { - logerr("napi_create_function(%s, %s, %s, %s, %s, %s);\n", - "env", - "methods[i].label", - "NAPI_AUTO_LENGTH", - "methods[i].handle", - "db", - "&fn"); - throw_node_env_error(env); - goto out; - } - - if (napi_set_named_property( - env, - wrapped_db, - methods[i].label, - fn - )) { - logerr("napi_set_named_property(%s, %s, %s, %s);\n", - "env," - "wrapped_db", - "methods[i].label", - "fn"); - throw_node_env_error(env); - goto out; - } - } - ret = wrapped_db; - -out: - if (error_msg) { - sqlite3_free(error_msg); - } - if (filename) { - free(filename); - } - if (!ret) { - if (db) { - if (sqlite3_close(db)) { - logerr("sqlite3_close(%s);\n", - "db"); - } - } - } - return ret; -} - - -static napi_value -ffi_init(napi_env env, napi_value exports) { - napi_value ret = exports; - - napi_status status; - - for (size_t i = 0; fns[i].label && fns[i].handle; i++) { - napi_value fn; - status = napi_create_function( - env, - fns[i].label, - NAPI_AUTO_LENGTH, - fns[i].handle, - NULL, - &fn - ); - if (status != napi_ok) { - ret = NULL; - napi_throw_error( - env, - "SQLITE_FN_CREATE", - "Unable to wrap native function TODO i18n" - ); - goto out; - } - - status = napi_set_named_property( - env, - exports, - fns[i].label, - fn - ); - if (status != napi_ok) { - ret = NULL; - napi_throw_error( - env, - "SQLITE_FN_SETNAME", - "Unable to populate exports TODO i18n" - ); - goto out; - } - } - -out: - return ret; -} - - -NAPI_MODULE_INIT() { - return ffi_init(env, exports); -} diff --git a/src/papo.en.msg b/src/papo.en.msg deleted file mode 100644 index dde462e..0000000 --- a/src/papo.en.msg +++ /dev/null @@ -1,72 +0,0 @@ -1 Usage:\n - -2 papo -p FILE [-o DIRECTORY]\n - -3 papo -l FILE [-o DIRECTORY]\n - -4 papo [-hV]\n - -5 \n - -6 \n - -7 Options:\n - -8 -p FILE parser file to be processed\n - -9 -l FILE lexer file to be processed\n - -10 -o DIRECTORY output where to place the\n - -11 generated files (default .)\n - -12 -h, --help show this help message\n - -13 -V, --version print the version number\n - -14 \n - -15 \n - -16 Run the papo(1) parser program.\n - -17 \n - -18 Here is the explanation for what it does, and the synopsis\n - -19 of its usage.\n - -20 \n - -21 See "man papo" for usage information and\n - -22 "man papo.tutorial" for a beginner introduction.\n - -23 \n - -24 \n - -25 Examples:\n - -26 \n - -27 Do a one-line parser:\n - -28 \n - -29 $ papo run md.grammar < README.md\n - -30 \n - -31 \n - -32 Compile the grammer:\n - -33 \n - -34 $ papo build csv.grammar > dunno.alsodunno\n - -35 papo 0.1.0 1970-01-01\n - -36 Error message from Node-API is empty - diff --git a/tests/assert-clean.sh b/tests/assert-clean.sh deleted file mode 100755 index 540cea6..0000000 --- a/tests/assert-clean.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh -set -eu - -if [ ! -e .git ]; then - echo "Not in a Git repository, skipping \"$0\"" >&2 - exit -fi - - -. tools/lib.sh - -R="$(mkdtemp)" -trap 'rm -rf "$R"' EXIT - -cp -pR ./ "$R" -cd "$R" - - -{ - make -s clean - - printf '%s: "clean" target deletes all derived assets...' \ - "$(yellow "$0")" - - if [ -n "$(git status -s)" ]; then - printf ' ERR.\n' - echo 'Repository left dirty:' - git status - exit 1 - fi - - if [ -n "$(git clean -nffdx)" ]; then - printf ' ERR.\n' - echo 'Untracked files left:' - git clean -ffdx --dry-run - exit 1 - fi - - printf ' %s\n' "$(green 'OK')" -} >&2 diff --git a/tests/assert-deps.sh b/tests/assert-deps.sh deleted file mode 100755 index b73933d..0000000 --- a/tests/assert-deps.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -set -eu - -. tools/lib.sh - -{ - printf '%s: all deps.mk is up-to-date...' "$(yellow "$0")" - sh mkdeps.sh | diff -U10 deps.mk - - printf ' %s\n' "$(green 'OK')" -} >&2 diff --git a/tests/assert-install.sh b/tests/assert-install.sh deleted file mode 100755 index fd1e037..0000000 --- a/tests/assert-install.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -set -eu - -. tools/lib.sh - -D="$(mkdtemp)" -R="$(mkdtemp)" -trap 'rm -rf "$D" "$R"' EXIT - -cp -pR ./ "$R" -cd "$R" - - -{ - PATH="$D/usr/bin:$PATH" - NODE_PATH="$D/usr/lib/node:$NODE_PATH" - make -s DESTDIR="$D" install - - printf '%s: that the papo(3js) library is installed correctly...' \ - "$(yellow "$0")" - node -e 'require("papo");' - printf ' %s\n' "$(green 'OK')" - - printf '%s: that the papo(1) command is installed correctly...' \ - "$(yellow "$0")" - papo -V | grep -q '^papo ' - printf ' %s\n' "$(green 'OK')" -} >&2 diff --git a/tests/assert-uninstall.sh b/tests/assert-uninstall.sh deleted file mode 100755 index 247d723..0000000 --- a/tests/assert-uninstall.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh -set -eu - -. tools/lib.sh - -D="$(mkdtemp)" -R="$(mkdtemp)" -trap 'rm -rf "$D" "$R"' EXIT - -cp -pR ./ "$R" -cd "$R" - - -{ - make -s DESTDIR="$D" install - make -s DESTDIR="$D" uninstall - printf '%s: that the "uninstall" target removes everything...' \ - "$(yellow "$0")" - if [ "$(find "$D" -not -type d | wc -l)" != 0 ]; then - printf ' ERR.\n' - cat <<-EOF - Leftover files not removed by "make uninstall": - - $(find "$D" -not -type d) - EOF - exit 1 - fi - printf ' %s\n' "$(green 'OK')" -} >&2 diff --git a/tests/c-lint.sh b/tests/c-lint.sh deleted file mode 100755 index 37822f3..0000000 --- a/tests/c-lint.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/sh -set -eu - -awk ' -BEGIN { - ret = 0 - msg = "function not on the start of the line:" -} - -/^[a-zA-Z0-9_]+ [^=]+\(/ { - if (ret == 0) { - print msg - } - printf "%s:%s:%s\n", FILENAME, FNR, $0 - ret = 1 -} - -END { - exit ret -} -' "$@" - - -awk ' -BEGIN { - ret = 0 - static = 1 - msg = "non-static function is not declared in a header:" -} - -/^[a-zA-Z0-9_]+\(.*$/ && static == 0 { - split($0, line, /\(/) - fn_name = line[1] - if (fn_name != "main" && fn_name != "LLVMFuzzerTestOneInput") { - header = substr(FILENAME, 0, length(FILENAME) - 2) ".h" - if (system("grep -q ^\"" fn_name "\" \"" header "\"")) { - if (ret == 0) { - print msg - } - printf "%s:%s:%s\n", FILENAME, FNR, $0 - ret = 1 - } - } -} - -/^static / { - static = 1 -} - -!/^static / { - static = 0 -} - -END { - exit ret -} -' "$@" - - -RE='[a-z]+\(\) {' -if grep -Eq "$RE" "$@"; then - echo 'Functions with no argument without explicit "void" parameter:' >&2 - grep -En "$RE" "$@" - exit 1 -fi diff --git a/tests/slurp.c b/tests/slurp.c deleted file mode 100644 index 683a126..0000000 --- a/tests/slurp.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "slurp.h" - -#include <stdio.h> -#include <stdlib.h> - -int -slurp_for_tests(const char *const FNAME, char **strref) { - int rc = 0; - - FILE *file = NULL; - char *str = NULL; - - file = fopen(FNAME, "r"); - if (!file) { - perror("fopen(FNAME, \"r\")"); - rc = -1; - goto out; - } - - if (fseek(file, 0L, SEEK_END)) { - perror("fseek(file, 0L, SEEK_END)"); - rc = -1; - goto out; - } - - const long lsize = ftell(file); - if (lsize == -1) { - perror("ftell(file)"); - rc = -1; - goto out; - } - const size_t size = (size_t)lsize + sizeof(char); - - if (fseek(file, 0L, SEEK_SET)) { - perror("fseek(file, 0L, SEEK_SET)"); - rc = -1; - goto out; - } - - str = malloc(size); - if (!str) { - perror("malloc(...)"); - rc = -1; - goto out; - } - - if (fread(str, sizeof(char), size - 1, file) != size - 1) { - perror("fread(...)"); - rc = -1; - goto out; - } - str[size - 1] = '\0'; - *strref = str; - -out: - if (file) { - if (fclose(file)) { - perror("flcose(file"); - rc = -1; - } - } - - if (rc) { - if (str) { - free(str); - } - } - return rc; -} diff --git a/tests/slurp.h b/tests/slurp.h deleted file mode 100644 index 056c77d..0000000 --- a/tests/slurp.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SLURP_H -#define SLURP_H - -#include "../src/config.h" - - -int -slurp_for_tests(const char *const FNAME, char **strref); - - -#endif diff --git a/tests/tests-lib.c b/tests/tests-lib.c deleted file mode 100644 index e46fb2d..0000000 --- a/tests/tests-lib.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "tests-lib.h" -#include <stdio.h> -#include <assert.h> - -#define COLOUR_RESET "\033[0m" -#define COLOUR_GREEN "\033[0;32m" -#define COLOUR_YELLOW "\033[0;33m" - -void -test_start(const char *const name) { - assert(fprintf(stdout, "%s:\n", name) > 0); -} - -void -testing(const char *const message) { - assert( - fprintf( - stdout, - COLOUR_YELLOW "testing" COLOUR_RESET ": %s...", - message - ) > 0 - ); -} - -void -test_ok(void) { - assert(fprintf(stdout, " " COLOUR_GREEN "OK" COLOUR_RESET ".\n") > 0); -} diff --git a/tests/tests-lib.h b/tests/tests-lib.h deleted file mode 100644 index a1e67ba..0000000 --- a/tests/tests-lib.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef TESTS_LIB_H -#define TESTS_LIB_H - -#include "../src/config.h" - -void -test_start(const char *const name); - -void -testing(const char *const message); - -void -test_ok(void); - -#endif diff --git a/tools/cdeps.sh b/tools/cdeps.sh deleted file mode 100755 index dd48d74..0000000 --- a/tools/cdeps.sh +++ /dev/null @@ -1,225 +0,0 @@ -#!/bin/sh -set -eu - -. tools/lib.sh - -usage() { - cat <<-'EOF' - Usage: - tools/cdeps.sh FILE... - tools/cdeps.sh -h - EOF -} - -help() { - cat <<-'EOF' - - - Options: - -h, --help show this message - - FILE toplevel entrypoint file - - - Given a list of C FILEs, generate the Makefile dependencies - between them. - - We have 3 types of object files: - - .o: plain object files; - - .lo: object files compiled as relocatable so it can be - included in a shared library; - - .to: compiled with -DTEST so it can expose its embedded unit - tests; - - We also have 2 aggregate files: - - .ta: an ar(1)-chive that includes all the .o dependencies the - $NAME.ta, plus the $NAME.to object. The goal is to have - "dep1.o", "dep2.o", ... "depN.o" included in the archive, - alongside "$NAME.to", so that recompiling "depN.o" would - replace only this file in the archive; - - .t: an executable "$NAME.t" derived from just linking together - all the objects inside a ".ta". Since the "main()" function - was only exposed in the "$NAME.to" via the -DTEST flag, this - executable is the runnable instance of all unit tests present - in "$NAME.c". Its exit code determines if its test suite - execution is successful. - - Also in order to run the unit tests without having to relink - them on each run, we have: - - .t-run: a dedicated virtual target that does nothing but - execute the tests. In order to assert the binaries exist, - each "$NAME.t-run" virtual target depends on the equivalent - "$NAME".t physical target. - - There are 2 types of dependencies that are generated: - 1. self dependencies; - 2. inter dependencies. - - The self dependencies are the ones across different - manifestations of the same file so all derived assets are - correctly kept up-to-date: - - $NAME.o $NAME.lo $NAME.to: $NAME.h - - As the .SUFFIXES rule already covers the dependency to the - orinal $NAME.c file, all we do is say that whenever the public - interface of these binaries change, they need to be - recompiled; - - $NAME.ta: $NAME.to - - We make sure to include in each test archive (ta) file its own - binary with unit tests. We include the "depN.o" dependencies - later; - - $NAME.t-run: $NAME.t - - Enforce that the binary exists before we run them. - - After we establish the self dependencies, we scrub each file's - content looking for `#include "..."` lines that denote - dependency to other C file. Once we do that we'll have: - - $NAME.o $NAME.lo $NAME.to: dep1.h dep2.h ... depN.h - - We'll recompile our file when its public header changes. When - only the body of the code changes we don't recompile, only - later relink; - - $NAME.ta: dep1.o dep2.o ... depN.o - - Make sure to include all required dependencies in the $NAME.t - binary so that the later linking works properly. - - So if we have file1.c, file2.c and file3.c with their respective - headers, where file2.c and file3.c depend of file1.c, i.e. they - have `#include "file.h"` in their code, and file3.c depend of - file2.c, the expected output is: - - file1.o file1.lo file1.to: file1.h - file2.o file2.lo file2.to: file2.h - file3.o file3.lo file3.to: file3.h - - file1.ta: file1.to - file2.ta: file2.to - file3.ta: file3.to - - file1.t-run: file1.t - file2.t-run: file2.t - file3.t-run: file3.t - - - file1.o file1.lo file1.to: - file2.o file2.lo file2.to: file1.h - file3.o file3.lo file3.to: file1.h file2.h - - file1.ta: - file2.ta: file1.o - file3.ta: file1.o file2.o - - This ensures that only the minimal amount of files need to get - recompiled, but no less. - - - Examples: - - Get deps for all files in 'src/' but 'src/main.c': - - $ sh tools/cdeps.sh `find src/*.c -not -name 'main.c'` - - - Emit dependencies for all C files in a Git repository: - - $ sh tools/cdeps.sh `git ls-files | grep '\.c$'` - EOF -} - - -for flag in "$@"; do - case "$flag" in - (--) - break - ;; - (--help) - usage - help - exit - ;; - (*) - ;; - esac -done - -while getopts 'h' flag; do - case "$flag" in - (h) - usage - help - exit - ;; - (*) - usage >&2 - exit 2 - ;; - esac -done -shift $((OPTIND - 1)) - -FILE="${1:-}" -eval "$(assert_arg "$FILE" 'FILE')" - - - -each_f() { - fn="$1" - shift - for file in "$@"; do - f="${file%.c}" - "$fn" "$f" - done - printf '\n' -} - -self_header_deps() { - printf '%s.o\t%s.lo\t%s.to:\t%s.h\n' "$1" "$1" "$1" "$1" -} - -self_ta_deps() { - printf '%s.ta:\t%s.to\n' "$1" "$1" -} - -self_trun_deps() { - printf '%s.t-run:\t%s.t\n' "$1" "$1" -} - -deps_for() { - ext="$2" - for file in $(awk -F'"' '/^#include "/ { print $2 }' "$1.c"); do - if [ "$file" = 'config.h' ]; then - continue - fi - if [ "$(basename "$file")" = 'tests-lib.h' ]; then - continue - fi - f="$(dirname "$1")/$file" - if [ "$f" = "$1.h" ]; then - continue - fi - printf '%s\n' "${f%.h}$2" - done -} - -rebuild_deps() { - printf '\n' - printf '%s.o\t%s.lo\t%s.to:' "$1" "$1" "$1" - printf ' %s' $(deps_for "$1" .h) | sed 's|^ $||' -} - -archive_deps() { - printf '\n' - printf '%s.ta:' "$1" - printf ' %s' $(deps_for "$1" .o) | sed 's|^ $||' -} - - -each_f self_header_deps "$@" -each_f self_ta_deps "$@" -each_f self_trun_deps "$@" - -each_f rebuild_deps "$@" -each_f archive_deps "$@" |