diff options
| author | peter <peter@pmikkelsen.com> | 2026-08-20 16:04:41 +0000 |
|---|---|---|
| committer | peter <peter@pmikkelsen.com> | 2026-08-20 16:04:41 +0000 |
| commit | 3be992e3f45dcfd9f8a45fa447de3abb710819b7 (patch) | |
| tree | 6cf02c89acdb0fbf12c20f03ea190a0047221db9 | |
| parent | 3a81615601bf37ffc4f7b570030709ac0782e2ed (diff) | |
Adapt a different coding style (no typedef'ed structs, C90...), and start working on a test setup.
FossilOrigin-Name: ebb73df5fc58859b6e985c5ec84196bdd09f639dbcdc69e706f6b17652a2d413
| -rw-r--r-- | CMakeLists.txt | 30 | ||||
| -rw-r--r-- | src/aplwc.h | 16 | ||||
| -rw-r--r-- | src/aplwc_internal.h | 39 | ||||
| -rw-r--r-- | src/errors.c | 21 | ||||
| -rw-r--r-- | src/libmain.c | 48 | ||||
| -rw-r--r-- | src/main.c | 8 | ||||
| -rw-r--r-- | src/memory.c | 46 | ||||
| -rw-r--r-- | tests/aplwc_new.c | 29 | ||||
| -rwxr-xr-x | tools/check | 15 | ||||
| -rwxr-xr-x | tools/checkcov | 70 | ||||
| -rwxr-xr-x | tools/tests | 8 |
11 files changed, 259 insertions, 71 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 29f567b..73d2a62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ project(aplwc LANGUAGES C ) -set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD 90) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS OFF) @@ -15,17 +15,35 @@ target_include_directories(common INTERFACE ) target_compile_options(common INTERFACE $<$<CONFIG:Debug>: + -O0 -Wall -Wextra -Wpedantic -Werror -fsanitize=address,undefined + -DAPLWC_BUILD_TYPE_DEBUG + > + + $<$<CONFIG:Coverage>: + -O0 + --coverage + -fcondition-coverage + -DAPLWC_BUILD_TYPE_COVERAGE + > + + $<$<CONFIG:Release>: + -DAPLWC_BUILD_TYPE_RELEASE > ) target_link_options(common INTERFACE $<$<CONFIG:Debug>: -fsanitize=address,undefined > + + $<$<CONFIG:Coverage>: + --coverage + -fcondition-coverage + > ) add_library(aplwc @@ -39,3 +57,13 @@ add_executable(aplwc-repl src/main.c ) target_link_libraries(aplwc-repl PRIVATE common aplwc) + +enable_testing() +file(GLOB TEST_SOURCES CONFIGURE_DEPENDS "tests/*.c") +foreach(source ${TEST_SOURCES}) + get_filename_component(name "${source}" NAME_WE) + set(test_bin "testbin-${name}") + add_executable("${test_bin}" "${source}") + target_link_libraries("${test_bin}" PRIVATE common aplwc) + add_test(NAME "${name}" COMMAND "${test_bin}") +endforeach() diff --git a/src/aplwc.h b/src/aplwc.h index e01e38c..603e4f3 100644 --- a/src/aplwc.h +++ b/src/aplwc.h @@ -4,16 +4,18 @@ #include <stdint.h> #include <stddef.h> -typedef enum { +enum aplwc_rc { APLWC_OK, APLWC_NOT_IMPLEMENTED, - APLWC_OUT_OF_MEMORY, -} AplwcRc; + APLWC_OUT_OF_MEMORY +}; -typedef struct Aplwc Aplwc; +struct aplwc; -AplwcRc aplwc_new(Aplwc **, uint8_t *, size_t); -AplwcRc aplwc_destroy(Aplwc *); -const char *aplwc_errstr(Aplwc *); +enum aplwc_rc aplwc_new(struct aplwc **, uint8_t *, size_t); +enum aplwc_rc aplwc_destroy(struct aplwc *); +const char *aplwc_errstr(struct aplwc *); + +#define APLWC_MIN_MEM (128) #endif /* APLWC_H */ diff --git a/src/aplwc_internal.h b/src/aplwc_internal.h index ccf600f..97a89ba 100644 --- a/src/aplwc_internal.h +++ b/src/aplwc_internal.h @@ -5,41 +5,46 @@ #define UNUSED_PARAMETER(arg) ((void)arg) -#define RETURN_ERROR(aplwc, rc, msg) do{ \ - Aplwc *_p = (aplwc); \ - AplwcRc _r = APLWC_##rc; \ - if(_p) _p->last_error = _r; \ - return _r; \ +#define RETURN_ERROR(aplwcp, rc, msg) do{ \ + return ((aplwc)->last_error = (rc)); \ }while(0) #define NELEM(x) (sizeof(x)/sizeof(x[0])) +#if APLWC_BUILD_TYPE_DEBUG + #define ALWAYS(x) ((x) ? 1 : (assert(0), 0)) + #define NEVER(x) ((x) ? (assert(0), 1) : 0) +#elif APLWC_BUILD_TYPE_RELEASE + #define ALWAYS(x) (X) + #define NEVER(X) (X) +#elif APLWC_BUILD_TYPE_COVERAGE + #define ALWAYS(x) (1) + #define NEVER(x) (0) +#endif + +#include <assert.h> #include <stdalign.h> #include <stdbool.h> -#include <stdlib.h> -#include <stdio.h> #include <string.h> -typedef struct Memory Memory; - -struct Memory { +struct memory { uint8_t *data; size_t size; size_t offset; }; -struct Aplwc { - AplwcRc last_error; +struct aplwc { + enum aplwc_rc last_error; char last_error_msg[64]; - Memory memory; + struct memory memory; }; /* errors.c */ -const char *rc_to_string(AplwcRc); +const char *rc_to_string(enum aplwc_rc); /* memory.c */ -Memory memory_init(uint8_t *, size_t); -Aplwc *memory_alloc_aplwc(Memory *); -void memory_free_aplwc(Memory *, Aplwc *); +struct memory memory_init(uint8_t *, size_t); +struct aplwc *memory_alloc_aplwc(struct memory *); +void memory_free_aplwc(struct memory *, struct aplwc *); #endif /* APLWC_INTERNAL_H */ diff --git a/src/errors.c b/src/errors.c index cd93df4..65a066a 100644 --- a/src/errors.c +++ b/src/errors.c @@ -1,17 +1,14 @@ #include <aplwc_internal.h> -static const char *errors[] = { - [APLWC_OK] = - "", - [APLWC_NOT_IMPLEMENTED] = - "Not yet implemented", -}; - const char * -rc_to_string(AplwcRc rc) +rc_to_string(enum aplwc_rc rc) { - const char *str = NULL; - if((rc > 0) && (rc < NELEM(errors))) - str = errors[rc]; - return str; + switch(rc){ + case APLWC_OK: + return ""; + case APLWC_NOT_IMPLEMENTED: + return "Not yet implemented"; + default: + return NULL; + } } diff --git a/src/libmain.c b/src/libmain.c index 93ad2a0..5dce8a0 100644 --- a/src/libmain.c +++ b/src/libmain.c @@ -1,19 +1,22 @@ #include <aplwc_internal.h> -AplwcRc -aplwc_new(Aplwc **p, uint8_t *data, size_t size) +enum aplwc_rc +aplwc_new(struct aplwc **p, uint8_t *data, size_t size) { - Memory m = memory_init(data, size); + struct memory m; + + m = memory_init(data, size); + *p = memory_alloc_aplwc(&m); if(*p == NULL) - RETURN_ERROR(*p, OUT_OF_MEMORY, ""); + return APLWC_OUT_OF_MEMORY; (*p)->memory = m; return APLWC_OK; } -AplwcRc -aplwc_destroy(Aplwc *p) +enum aplwc_rc +aplwc_destroy(struct aplwc *p) { if(p) memory_free_aplwc(&p->memory, p); @@ -22,13 +25,19 @@ aplwc_destroy(Aplwc *p) } const char * -aplwc_errstr(Aplwc *aplwc) +aplwc_errstr(struct aplwc *aplwc) { - static char buf[256]; + enum { BUF_SIZE = 256 }; + + static char buf[BUF_SIZE]; + const char *err, *msg; + char *p; + size_t len, i; + buf[0] = 0; + p = buf; + err = msg = NULL; - const char *err = NULL; - const char *msg = NULL; if(aplwc){ err = rc_to_string(aplwc->last_error); msg = aplwc->last_error_msg; @@ -37,10 +46,21 @@ aplwc_errstr(Aplwc *aplwc) if(!err) err = "(unable to produce error string)"; - if(msg && (strlen(msg) > 0)) - snprintf(buf, sizeof(buf), "%s: %s", err, msg); - else - snprintf(buf, sizeof(buf), "%s", err); + for(i = 0, len = strlen(err); (i <= len) && (((p+i)-buf) < (BUF_SIZE-1)); i++) + p[i] = err[i]; + p += i; + + if(msg){ + if(((buf-p)+2) < BUF_SIZE){ + *(p++) = ':'; + *(p++) = ' '; + } + + for(i = 0, len = strlen(msg); (i <= len) && (((p+i)-buf) < (BUF_SIZE-1)); i++) + p[i] = msg[i]; + p += i; + *p = 0; + } return buf; } @@ -7,15 +7,17 @@ int main(void) { - Aplwc *aplwc; + struct aplwc *aplwc; + uint8_t *data; + int ret; - uint8_t *data = malloc(MEMORY); + data = malloc(MEMORY); if(data == NULL){ fprintf(stderr, "Couldn't allocate memory\n"); return 1; } - int ret = aplwc_new(&aplwc, data, MEMORY); + ret = aplwc_new(&aplwc, data, MEMORY); if(ret){ fprintf(stderr, "Couldn't create new aplwc instance: %s\n", aplwc_errstr(aplwc)); return 1; diff --git a/src/memory.c b/src/memory.c index c2216b2..622bb0b 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1,42 +1,54 @@ #include <aplwc_internal.h> -Memory +struct memory memory_init(uint8_t *data , size_t size) { - Memory mem = { - .data = data, - .size = size, - .offset = 0, - }; + struct memory mem; + + mem.data = data; + mem.size = size; + mem.offset = 0; return mem; } static void * -alloc(Memory *m, size_t size, size_t align) +alloc(struct memory *m, size_t size, size_t align) { - uintptr_t ptr = (uintptr_t)m->data; - size_t alloc_size = size; - if((ptr % align) != 0) - alloc_size += align - (ptr % align); + uintptr_t ptr; + size_t alloc_size, adjust; + void *p; + + ptr = (uintptr_t)m->data; + alloc_size = size; + + if(NEVER(align == 0)) + return NULL; + adjust = ptr % align; + + if(adjust) + alloc_size += align - adjust; - void *p = NULL; if((m->size - m->offset) >= alloc_size){ p = m->data+m->offset+alloc_size-size; m->offset += alloc_size; memset(p, 0, size); - } + }else + p = NULL; + return p; } -Aplwc * -memory_alloc_aplwc(Memory *m) +struct aplwc * +memory_alloc_aplwc(struct memory *m) { - Aplwc *p = alloc(m, sizeof(Aplwc), alignof(Aplwc)); + struct aplwc *p; + + p = alloc(m, sizeof(struct aplwc), alignof(struct aplwc)); return p; } void -memory_free_aplwc(Memory *m, Aplwc *p) +memory_free_aplwc(struct memory *m, struct aplwc *p) { UNUSED_PARAMETER(m); UNUSED_PARAMETER(p); diff --git a/tests/aplwc_new.c b/tests/aplwc_new.c new file mode 100644 index 0000000..1931c3c --- /dev/null +++ b/tests/aplwc_new.c @@ -0,0 +1,29 @@ +#include <aplwc.h> + +int +main(void) +{ + struct aplwc *aplwc; + uint8_t data[APLWC_MIN_MEM*2]; + int ret; + size_t i, j; + + for(i = 0; i < 32; i++){ + for(j = 0; j <= sizeof(data)-i; j++){ + ret = aplwc_new(&aplwc, data+i, j); + if(ret){ + if(ret != APLWC_OUT_OF_MEMORY) + return 1; + if(aplwc != NULL) + return 1; + if(j >= APLWC_MIN_MEM) + return 1; + } + ret = aplwc_destroy(aplwc); + if(ret) + return 1; + } + } + + return 0; +} diff --git a/tools/check b/tools/check new file mode 100755 index 0000000..a6c5d20 --- /dev/null +++ b/tools/check @@ -0,0 +1,15 @@ +#!/bin/sh + +types="Debug Release Coverage" + +mkdir build +cd build + +for type in $types +do + rm -rf $type + cmake .. -B $type -DCMAKE_BUILD_TYPE=$type +done + +cd .. +fossil ls | entr -c tools/tests $types diff --git a/tools/checkcov b/tools/checkcov new file mode 100755 index 0000000..6f2775a --- /dev/null +++ b/tools/checkcov @@ -0,0 +1,70 @@ +#!/bin/sh + +cd build/$1 + +case "$1" in + Coverage) + rm -rf CMakeFiles/aplwc.dir/src/* + ;; + *) + ;; +esac + +cmake --build . +ctest + +case "$1" in + Coverage) + ;; + *) + exit 0 + ;; +esac + +gcov -tg CMakeFiles/aplwc.dir/src/*.gcno | awk ' +BEGIN { + FS=":" +} + +function miss(t){ + printf("%c %s:%d %s\n", t, file, line, src) +} + +/^condition outcomes covered [0-9]+\/[1-9][0-9]*/ { + if($0 ~ /0\//) + skip_cond = 1 + else + skip_cond = 0 + next +} + +/^condition .* not covered/ { + if(!skip_cond){ + miss("C") + print $0 + } + next +} + +{ + hits = $1 + line = $2 + gsub(/ /, "", hits) + gsub(/ /, "", line) + + if(line == 0) + file=$NF + + src = "" + for(n = 3; n <= NF; n++) + src = src $n + + if(hits == "-") + next + if(hits ~ /^[1-9][0-9]*\*?$/) + next + + miss("L") + next +} +' diff --git a/tools/tests b/tools/tests new file mode 100755 index 0000000..66ac467 --- /dev/null +++ b/tools/tests @@ -0,0 +1,8 @@ +#!/bin/sh + +types=$* + +for type in $types +do + tools/checkcov $type +done |