diff --git a/lcthw-remnants-2/liblcthw/.gitignore b/lcthw-remnants-2/liblcthw/.gitignore new file mode 100644 index 0000000..0c5003d --- /dev/null +++ b/lcthw-remnants-2/liblcthw/.gitignore @@ -0,0 +1,2 @@ +tests/runtests +tests/your_library_tests diff --git a/lcthw-remnants-2/liblcthw/LICENSE b/lcthw-remnants-2/liblcthw/LICENSE new file mode 100644 index 0000000..c5b39b0 --- /dev/null +++ b/lcthw-remnants-2/liblcthw/LICENSE @@ -0,0 +1,21 @@ +Copyright (C) 2016 Dan Buch + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lcthw-remnants-2/liblcthw/Makefile b/lcthw-remnants-2/liblcthw/Makefile new file mode 100644 index 0000000..ce425a0 --- /dev/null +++ b/lcthw-remnants-2/liblcthw/Makefile @@ -0,0 +1,59 @@ +CFLAGS = -g -O2 -Wall -Wextra -Isrc -Lbuild -rdynamic -DNDEBUG $(OPTFLAGS) +LDLIBS = -ldl $(OPTLIBS) + +PREFIX ?= /usr/local + +SOURCES = $(wildcard src/**/*.c src/*.c) +OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) + +TEST_SRC = $(wildcard tests/*_tests.c) +TESTS = $(patsubst %.c,%,$(TEST_SRC)) + +LIBNAME = lcthw +TARGET = build/lib$(LIBNAME).a +SO_TARGET = $(patsubst %.a,%.so,$(TARGET)) + +# The Target Build +all: $(TARGET) $(SO_TARGET) tests + +dev: CFLAGS = -g -Wall -Isrc -Wall -Wextra $(OPTFLAGS) +dev: all + +$(TARGET): CFLAGS += -fPIC +$(TARGET): build $(OBJECTS) + $(AR) rcs $@ $(OBJECTS) + ranlib $@ + +$(SO_TARGET): $(TARGET) $(OBJECTS) + $(CC) -shared -o $@ $(OBJECTS) + +build: + @mkdir -p build + @mkdir -p bin + +# The Unit Tests +.PHONY: tests +tests: LDLIBS += -static -l$(LIBNAME) +tests: ./tests/runtests $(TESTS) + ./tests/runtests + +valgrind: + VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE) + +# The Cleaner +clean: + rm -rf build $(OBJECTS) $(TESTS) + rm -f tests/tests.log tests/runtests + find . -name "*.gc*" -exec rm {} \; + rm -rf `find . -name "*.dSYM" -print` + +# The Install +install: all + install -d $(DESTDIR)/$(PREFIX)/lib/ + install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/ + +# The Checker +BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)' +check: + @echo Files with potentially dangerous functions + @egrep $(BADFUNCS) $(SOURCES) || true diff --git a/lcthw-remnants-2/liblcthw/README.md b/lcthw-remnants-2/liblcthw/README.md new file mode 100644 index 0000000..e69de29 diff --git a/lcthw-remnants-2/liblcthw/src/lcthw/dbg.h b/lcthw-remnants-2/liblcthw/src/lcthw/dbg.h new file mode 100644 index 0000000..a7aaa6a --- /dev/null +++ b/lcthw-remnants-2/liblcthw/src/lcthw/dbg.h @@ -0,0 +1,30 @@ +#ifndef __dbg_h__ +#define __dbg_h__ + +#include +#include +#include + +#ifdef NDEBUG +#define debug(M, ...) +#else +#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:%s: " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__) +#endif + +#define clean_errno() (errno == 0 ? "None" : strerror(errno)) + +#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__) + +#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__) + +#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__) + +#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } + +#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } + +#define check_mem(A) check((A), "Out of memory.") + +#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } + +#endif diff --git a/lcthw-remnants-2/liblcthw/tests/minunit.h b/lcthw-remnants-2/liblcthw/tests/minunit.h new file mode 100644 index 0000000..9ed511e --- /dev/null +++ b/lcthw-remnants-2/liblcthw/tests/minunit.h @@ -0,0 +1,32 @@ +#undef DNDEBUG +#ifndef _minunit_h +#define _minunit_h + +#include +#include +#include + +#define mu_suite_start() char *message = NULL + +#define mu_assert(test, message) if (!(test)) { log_err(message); return message; } +#define mu_run_test(test) debug("\n-----%s", " " #test); \ + message = test(); tests_run++; if (message) return message; + +#define RUN_TESTS(name) int main(int argc, char *argv[]) {\ + argc = 1; \ + debug("----- RUNNING: %s", argv[0]);\ + printf("----\nRUNNING: %s\n", argv[0]);\ + char *result = name();\ + if (result != 0) {\ + printf("FAILED: %s\n", result);\ + }\ + else {\ + printf("ALL TESTS PASSED\n");\ + }\ + printf("Tests run: %d\n", tests_run);\ + exit(result != 0);\ +} + +int tests_run; + +#endif diff --git a/lcthw-remnants-2/liblcthw/tests/runtests.c b/lcthw-remnants-2/liblcthw/tests/runtests.c new file mode 100644 index 0000000..9e39d3a --- /dev/null +++ b/lcthw-remnants-2/liblcthw/tests/runtests.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include + +int test_selector(const struct dirent *ep) +{ + return fnmatch("*_tests", ep->d_name, 0) == 0; +} + +int run_tests_file(char *filename) +{ + if(access(filename, R_OK | X_OK) == 0) { + return system(filename); + } + + return -1; +} + +int main(void) +{ + int entcount = 0; + int rc = 0; + int i = 0; + int ntests = 0; + char *testsdir = getenv("TESTS"); + char *valgrind = getenv("VALGRIND"); + struct dirent **namelist = NULL; + struct dirent *ep = NULL; + + if(!testsdir) { + testsdir = "./tests"; + } + + entcount = scandir((const char *)testsdir, &namelist, test_selector, alphasort); + check(entcount > -1, "Failed to scan tests dir"); + + for(i = 0; i < entcount; i++) { + ep = namelist[i]; + check(ep, "Dirent is missing."); + + char filename[256]; + rc = sprintf(filename, "%s/%s", testsdir, ep->d_name); + check(rc > -1, "Failed to build filename."); + debug("Found filename '%s'", filename); + + free(ep); + + if(valgrind) { + char command[1024]; + rc = sprintf(command, "%s %s", valgrind, filename); + check(rc > -1, "Failed to build command with valgrind."); + rc = run_tests_file(command); + } else { + rc = run_tests_file(filename); + } + + if(rc > 0) { + debug("Skipping '%s'", filename); + continue; + } + + ntests++; + + if(rc == 0) { + printf("%s PASS\n", filename); + continue; + } + + printf("ERROR in test %s: here's tests/tests.log\n", filename); + printf("------\n"); + rc = system("tail tests/tests.log"); + goto error; + } + + printf("------\n"); + printf("Total of %d test files run.\n", ntests); + + if(namelist) { + free(namelist); + } + + return 0; + +error: + if(namelist) { + free(namelist); + } + + return rc != 0 ? rc : 1; +}