summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpeter <peter@pmikkelsen.com>2026-08-20 16:04:41 +0000
committerpeter <peter@pmikkelsen.com>2026-08-20 16:04:41 +0000
commit3be992e3f45dcfd9f8a45fa447de3abb710819b7 (patch)
tree6cf02c89acdb0fbf12c20f03ea190a0047221db9
parent3a81615601bf37ffc4f7b570030709ac0782e2ed (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.txt30
-rw-r--r--src/aplwc.h16
-rw-r--r--src/aplwc_internal.h39
-rw-r--r--src/errors.c21
-rw-r--r--src/libmain.c48
-rw-r--r--src/main.c8
-rw-r--r--src/memory.c46
-rw-r--r--tests/aplwc_new.c29
-rwxr-xr-xtools/check15
-rwxr-xr-xtools/checkcov70
-rwxr-xr-xtools/tests8
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;
}
diff --git a/src/main.c b/src/main.c
index 1e46fbf..b0576a5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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