From b33f6c9d76daedd995db88bb7c83906e62faab12 Mon Sep 17 00:00:00 2001 From: Lassi Kortela Date: Wed, 28 Aug 2019 12:45:21 +0300 Subject: [PATCH] Add a proper list accumulator utility in C --- c/env_unix.c | 80 +++++++++++++++++++++--------------------------- c/scheme.h | 16 ++++++++++ scripts/build.sh | 2 ++ 3 files changed, 53 insertions(+), 45 deletions(-) diff --git a/c/env_unix.c b/c/env_unix.c index 1e4ce31..24dd1ad 100644 --- a/c/env_unix.c +++ b/c/env_unix.c @@ -32,50 +32,40 @@ static const struct utsname *get_global_uname(void) const char *env_get_os_name(void) { return get_global_uname()->sysname; } -static void push(value_t *tailp, value_t elt) -{ - value_t new_tail; - - new_tail = cdr_(*tailp) = fl_cons(elt, FL_NIL); - *tailp = new_tail; -} - -static void push_pair(value_t *tailp, const char *name, value_t value) -{ - push(tailp, fl_cons(symbol(name), value)); -} - static value_t envst_language(void) { - value_t head, tail; + struct accum acc = ACCUM_EMPTY; - head = tail = fl_cons(symbol("language"), FL_NIL); - push_pair(&tail, "implementation-name", string_from_cstr("Up Scheme")); - push_pair(&tail, "implementation-version", string_from_cstr("0.1.0")); - return head; + accum_elt(&acc, symbol("language")); + accum_name_value(&acc, "implementation-name", + string_from_cstr("Up Scheme")); + accum_name_value(&acc, "implementation-version", + string_from_cstr("0.1.0")); + return acc.list; } static value_t envst_language_c(void) { - value_t head, tail; + struct accum acc = ACCUM_EMPTY; - head = tail = fl_cons(symbol("language"), FL_NIL); - push_pair(&tail, "implementation-name", - string_from_cstr(SCHEME_C_COMPILER_NAME)); - push_pair(&tail, "implementation-version", - string_from_cstr(SCHEME_C_COMPILER_VERSION)); - return head; + accum_elt(&acc, symbol("language")); + accum_name_value(&acc, "implementation-name", + string_from_cstr(SCHEME_C_COMPILER_NAME)); + accum_name_value(&acc, "implementation-version", + string_from_cstr(SCHEME_C_COMPILER_VERSION)); + return acc.list; } + static value_t envst_os(void) { - value_t head, tail; + struct accum acc = ACCUM_EMPTY; - head = tail = fl_cons(symbol("os"), FL_NIL); - push_pair(&tail, "implementation-name", - string_from_cstr(get_global_uname()->sysname)); - push_pair(&tail, "implementation-version", - string_from_cstr(get_global_uname()->release)); - return head; + accum_elt(&acc, symbol("os")); + accum_name_value(&acc, "implementation-name", + string_from_cstr(get_global_uname()->sysname)); + accum_name_value(&acc, "implementation-version", + string_from_cstr(get_global_uname()->release)); + return acc.list; } static const char endianness[] = @@ -89,25 +79,25 @@ static const char endianness[] = static value_t envst_computer(void) { - value_t head, tail; + struct accum acc = ACCUM_EMPTY; - head = tail = fl_cons(symbol("computer"), FL_NIL); - push_pair(&tail, "architecture", - string_from_cstr(get_global_uname()->machine)); - push_pair(&tail, "cpu-bits", fixnum(sizeof(uintptr_t) * CHAR_BIT)); - push_pair(&tail, "byte-order", symbol(endianness)); - return head; + accum_elt(&acc, symbol("computer")); + accum_name_value(&acc, "architecture", + string_from_cstr(get_global_uname()->machine)); + accum_name_value(&acc, "cpu-bits", fixnum(sizeof(uintptr_t) * CHAR_BIT)); + accum_name_value(&acc, "byte-order", symbol(endianness)); + return acc.list; } value_t builtin_environment_stack(value_t *args, uint32_t nargs) { - value_t head, tail; + struct accum acc = ACCUM_EMPTY; (void)args; argcount("environment-stack", nargs, 0); - head = tail = fl_cons(envst_language(), FL_NIL); - push(&tail, envst_language_c()); - push(&tail, envst_os()); - push(&tail, envst_computer()); - return head; + accum_elt(&acc, envst_language()); + accum_elt(&acc, envst_language_c()); + accum_elt(&acc, envst_os()); + accum_elt(&acc, envst_computer()); + return acc.list; } diff --git a/c/scheme.h b/c/scheme.h index 3ffae13..3f40a38 100644 --- a/c/scheme.h +++ b/c/scheme.h @@ -1002,6 +1002,22 @@ value_t fl_stringp(value_t *args, uint32_t nargs); value_t fl_string_reverse(value_t *args, uint32_t nargs); value_t fl_string_sub(value_t *args, uint32_t nargs); +// util.c + +struct accum { + value_t list; + value_t tail; +}; + +#define ACCUM_EMPTY \ + { \ + .list = FL_NIL, .tail = FL_NIL \ + } + +void accum_elt(struct accum *accum, value_t elt); +void accum_pair(struct accum *accum, value_t a, value_t d); +void accum_name_value(struct accum *accum, const char *name, value_t value); + // boot_image.c extern char boot_image[]; diff --git a/scripts/build.sh b/scripts/build.sh index 9dad9eb..2adf87e 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -37,6 +37,7 @@ o_files="$o_files table.o" o_files="$o_files text_ini.o" o_files="$o_files time_unix.o" o_files="$o_files utf8.o" +o_files="$o_files util.o" default_cflags="-Wall -O2 -D NDEBUG -D USE_COMPUTED_GOTO -Wextra -std=gnu99 -Wno-strict-aliasing" default_lflags="-lm" case "$os" in @@ -120,6 +121,7 @@ $CC $CFLAGS -c ../c/table.c $CC $CFLAGS -c ../c/text_ini.c $CC $CFLAGS -c ../c/time_unix.c $CC $CFLAGS -c ../c/utf8.c +$CC $CFLAGS -c ../c/util.c $CC $CFLAGS -c ../c/boot_image.c $CC -o upscheme $o_files $LFLAGS