home: hub: zuo

Download patch

ref: 8a66ab82791c2522e0fe4a08f157985401f8cb5b
parent: a0faa82c8383d206aa38d21462ca4ae699851a0b
author: D. Ben Knoble <ben.knoble+github@gmail.com>
date: Tue Apr 23 10:28:23 CDT 2024

fix some compiler warnings (#21)

Change parts of `zuo.c` to avoid warnings that show up with flags like

-Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wshadow -Wpointer-arith -Wcast-qual -pedantic -O2 -std=c11

New CI steps (via GitHub Actions) check compilation using flags like that.

Repair a bug in Windows for `fd-poll` that better testing exposed, but
also update test and docs to clarify that `fd-poll` is not so useful on
Windows.

--- /dev/null
+++ b/.github/scripts/msvcprep.bat
@@ -1,0 +1,42 @@
+
+REM  Find Visual Studio [Express] in one of the usual places.
+REM  Expects something like "x86", "amd64", or "x86_amd64" as an argument.
+
+set VCMODE=%1
+
+REM For 2022 and later, look in "Program Files"
+set Applications=%ProgramFiles%
+
+set VCVARBAT=%Applications%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat
+
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvarsall.bat
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat
+
+REM For 2019 and earlier, look in "Program Files (x86)"
+set Applications=%ProgramFiles(x86)%
+if "%Applications%" == "" set Applications=%ProgramFiles%
+
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvarsall.bat
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat
+
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio\2017\Professional\VC\Auxiliary\Build\vcvarsall.bat
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat
+
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio 14.0\vc\vcvarsall.bat
+
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio 13.0\vc\vcvarsall.bat
+
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio 12.0\vc\vcvarsall.bat
+
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio 11.0\vc\vcvarsall.bat
+
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio 10.0\vc\vcvarsall.bat
+
+if not exist "%VCVARBAT%" set VCVARBAT=%Applications%\Microsoft Visual Studio 9.0\vc\vcvarsall.bat
+
+"%VCVARBAT%" %VCMODE%
--- /dev/null
+++ b/.github/workflows/zuo-cflags.yml
@@ -1,0 +1,45 @@
+---
+name: Zuo with Strict Compiler Flags
+
+# yamllint disable-line rule:truthy
+on: [push, pull_request]
+
+jobs:
+  build-gcc:
+    runs-on: ubuntu-22.04
+
+    env:
+      CFLAGS: "-Werror -Wall -Wextra -Wstrict-prototypes -Wold-style-definition -Wshadow -Wpointer-arith -Wcast-qual -pedantic -O2 -std=c11 -D_POSIX_C_SOURCE=200809L"
+
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          fetch-depth: 100
+      - name: Compile
+        run: |
+          gcc -c $CFLAGS -DZUO_EMBEDDED zuo.c -o zuo_embed.o
+          gcc $CFLAGS zuo.c -o zuo
+      - name: Check
+        run: ./zuo build.zuo check
+
+  build-msvc:
+    runs-on: windows-2022
+
+    env:
+      CFLAGS: "/W1 /WX"
+
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          fetch-depth: 100
+      - name: Compile
+        shell: cmd
+        run: |
+          call .github\scripts\msvcprep.bat x86_amd64
+          cl /c %CFLAGS% /DZUO_EMBEDDED /Fo:zuo_embed.obj zuo.c
+          cl %CFLAGS% zuo.c -o zuo
+      - name: Check
+        shell: cmd
+        run: |
+          call .github\scripts\msvcprep.bat x86_amd64
+          zuo build.zuo check
--- a/build.zuo
+++ b/build.zuo
@@ -91,7 +91,7 @@
                           (lambda ()
                             (unless (= 0 (process-status
                                           (thread-process-wait
-                                           (hash-ref (process "to-run/zuo"
+                                           (hash-ref (process (.exe "to-run/zuo")
                                                               (at-source "tests/main.zuo"))
                                                      'process))))
                               (error "check failed")))))))
--- a/tests/file-handle.zuo
+++ b/tests/file-handle.zuo
@@ -155,9 +155,10 @@
                          'stdout 'pipe))])
   (define in (hash-ref ht 'stdout))
   (define out (hash-ref ht 'stdin))
-  (check (fd-poll (list in) 0) #f)
-  (check (fd-poll (list in out) 0) out)
-  (check (fd-poll (list in out)) out)
+  (unless (eq? 'windows (system-type)) ;; polling doesn't work on Windows pipes
+    (check (fd-poll (list in) 0) #f)
+    (check (fd-poll (list in out) 0) out)
+    (check (fd-poll (list in out)) out))
   (fd-write out "x")
   (check (fd-poll (list in)) in)
   (check (fd-poll (list in) 0) in)
--- a/tests/path.zuo
+++ b/tests/path.zuo
@@ -102,7 +102,7 @@
        ".")
 (check (find-relative-path "home/zuo/src" "tmp/cache")
        (build-path ".." ".." ".." "tmp" "cache"))
-(check (find-relative-path "." "tmp/cache")
+(check (find-relative-path "." (build-path "tmp" "cache"))
        (build-path "tmp" "cache"))
 (check (find-relative-path "tmp/cache" ".")
        (build-path ".." ".."))
@@ -148,7 +148,7 @@
 (check-arg-fail (file-name-from-path 10) not-path)
 
 (check (path-replace-extension "a.c" ".o") "a.o")
-(check (path-replace-extension "p/a.c" ".o") (build-path "p" "a.o"))
-(check (path-replace-extension "p/.rc" ".o") (build-path "p" ".rc.o"))
+(check (path-replace-extension "p/a.c" ".o") (build-path "p/a.o"))
+(check (path-replace-extension "p/.rc" ".o") (build-path "p/.rc.o"))
 (check-arg-fail (path-replace-extension 10 "x") not-path)
 (check-arg-fail (path-replace-extension "x" 10) not-string)
--- a/zuo-doc/lang-zuo.scrbl
+++ b/zuo-doc/lang-zuo.scrbl
@@ -1029,7 +1029,9 @@
 @racket[handles] that is ready. If @racket[timeout-msecs] is a number,
 then it specifies a number of milliseconds to wait; the result is
 @racket[#f] if no handle in @racket[handles] is ready before
-@racket[timeout-msecs] milliseconds pass.
+@racket[timeout-msecs] milliseconds pass. Polling typically does not
+work on Windows, because pipe handles claim to be ready for reading even
+when no data is available.
 
 @history[#:added "1.1"]}
 
--- a/zuo.c
+++ b/zuo.c
@@ -99,6 +99,8 @@
 # define ZUO_MIN_HEAP_SIZE (32*1024*1024)
 #endif
 
+#define ZUO_UNUSED(id) (void)id
+
 /*======================================================================*/
 /* run-time configuration                                               */
 /*======================================================================*/
@@ -108,7 +110,7 @@
 static int zuo_probe_each = 0;
 static int zuo_probe_counter = 0;
 
-static void zuo_configure() {
+static void zuo_configure(void) {
   const char *s;
 
   if ((s = getenv("ZUO_LIB_PATH"))) {
@@ -223,12 +225,13 @@
   zuo_t *val;
 } zuo_variable_t;
 
-typedef zuo_t *(*zuo_dispatcher_proc_t)(void *proc, zuo_t *arguments);
+typedef void (*zuo_proc_t)(void);
+typedef zuo_t *(*zuo_dispatcher_proc_t)(zuo_proc_t proc, zuo_t *arguments);
 
 typedef struct {
   zuo_t obj;
   zuo_dispatcher_proc_t dispatcher;
-  void *proc;
+  zuo_proc_t proc;
   zuo_int32_t arity_mask;
   zuo_t *name;
 } zuo_primitive_t;
@@ -372,12 +375,12 @@
 /* sanity checks                                                        */
 /*======================================================================*/
 
-void zuo_panic(const char *s) {
+static void zuo_panic(const char *s) {
   fprintf(stderr, "%s\n", s);
   exit(1);
 }
 
-void zuo_check_sanity() {
+static void zuo_check_sanity(void) {
   if (sizeof(zuo_int32_t) != 4)
     zuo_panic("wrong int32 size");
   if (sizeof(zuo_int_t) != 8)
@@ -390,8 +393,8 @@
 /* signal forward declarations                                          */
 /*======================================================================*/
 
-static zuo_t *zuo_resume_signal();
-static zuo_t *zuo_suspend_signal();
+static zuo_t *zuo_resume_signal(void);
+static zuo_t *zuo_suspend_signal(void);
 
 /*======================================================================*/
 /* memory manager                                                       */
@@ -500,7 +503,7 @@
   }
 }
 
-void zuo_update(zuo_t **addr_to_update) {
+static void zuo_update(zuo_t **addr_to_update) {
   zuo_t *obj = *addr_to_update;
 
   if (obj->tag != zuo_forwarded_tag) {
@@ -564,7 +567,7 @@
   }
 }
 
-static void zuo_trace_objects() {
+static void zuo_trace_objects(void) {
   zuo_int_t trace_offset = 0;
 
   while (trace_offset < allocation_offset) {
@@ -597,7 +600,7 @@
     gc_threshold = ZUO_MIN_HEAP_SIZE;
 }
 
-static void zuo_collect() {
+static void zuo_collect(void) {
   void *old_space = to_space;
   old_space_t *old_old_spaces = old_spaces;
   zuo_int_t old_heap_size = heap_size;
@@ -628,7 +631,7 @@
   zuo_resume_signal();
 }
 
-static void zuo_check_collect() {
+static void zuo_check_collect(void) {
   if (total_allocation >= gc_threshold)
     zuo_collect();
 }
@@ -651,7 +654,7 @@
 static zuo_primitive_t zuo_registered_prims[ZUO_MAX_PRIMITIVE_COUNT];
 static int zuo_registered_prim_count;
 
-static void zuo_register_primitive(zuo_dispatcher_proc_t dispatcher, void *proc, zuo_int32_t arity_mask) {
+static void zuo_register_primitive(zuo_dispatcher_proc_t dispatcher, zuo_proc_t proc, zuo_int32_t arity_mask) {
   if (zuo_registered_prim_count == ZUO_MAX_PRIMITIVE_COUNT)
     zuo_panic("primitive table is too small");
 
@@ -687,7 +690,7 @@
   zuo_int32_t symbol_count;
 } zuo_fasl_header_t;
 
-static zuo_int32_t zuo_magic() {
+static zuo_int32_t zuo_magic(void) {
   /* gets magic specific to the current machine's endianness */
   return *(zuo_int32_t *)"\0zuo";
 }
@@ -866,7 +869,7 @@
     }
   case zuo_primitive_tag:
     {
-      zuo_int32_t primitive_id;
+      zuo_int32_t primitive_id = 0;
       if (stream->mode == zuo_fasl_out) {
         primitive_id = zuo_primitive_to_id((zuo_primitive_t *)obj);
         zuo_fasl_int32(&primitive_id, stream);
@@ -976,7 +979,7 @@
   if (((zuo_fasl_header_t *)dump)->magic != magic) {
     if (((zuo_fasl_header_t *)dump)->magic == SWAP_ENDIAN(magic)) {
       /* adapt little-endian to big-endian, or vice versa */
-      for (i = 0; i < len / sizeof(zuo_int32_t); i++)
+      for (i = 0; i < len / (zuo_int_t)sizeof(zuo_int32_t); i++)
         dump[i] = SWAP_ENDIAN(dump[i]);
     } else
       zuo_panic("image does not start with zuo magic");
@@ -1057,7 +1060,7 @@
   return zuo_sized_string(str, strlen(str));
 }
 
-static zuo_t *zuo_trie_node() {
+static zuo_t *zuo_trie_node(void) {
   int i;
   zuo_trie_node_t *obj = (zuo_trie_node_t *)zuo_new(zuo_trie_node_tag, sizeof(zuo_trie_node_t));
 
@@ -1125,7 +1128,7 @@
   return (zuo_t *)obj;
 }
 
-static zuo_t *zuo_primitive(zuo_dispatcher_proc_t dispatcher, void *proc, zuo_int32_t arity_mask, zuo_t *name) {
+static zuo_t *zuo_primitive(zuo_dispatcher_proc_t dispatcher, zuo_proc_t proc, zuo_int32_t arity_mask, zuo_t *name) {
   zuo_register_primitive(dispatcher, proc, arity_mask);
   /* if `name` is undefined, we're just registering a primitive to be used for an image */
   if (name == z.o_undefined)
@@ -1393,7 +1396,7 @@
 
 static int zuo_ansi_ok = 1;
 
-static void zuo_init_terminal() {
+static void zuo_init_terminal(void) {
 #ifdef ZUO_WINDOWS
   int i;
   HANDLE h;
@@ -1423,8 +1426,6 @@
   return which;
 #endif
 #ifdef ZUO_WINDOWS
-  HANDLE h;
-
   switch (which) {
   case 0:
     which = STD_INPUT_HANDLE;
@@ -1441,7 +1442,7 @@
 #endif
 }
 
-int zuo_is_terminal(zuo_raw_handle_t fd) {
+static int zuo_is_terminal(zuo_raw_handle_t fd) {
 #ifdef ZUO_UNIX
   return isatty(fd);
 #endif
@@ -1461,12 +1462,12 @@
   }
 }
 
-static void zuo_error_color() {
+static void zuo_error_color(void) {
   zuo_suspend_signal();
   zuo_print_terminal(2, "\033[91m");
 }
 
-static void zuo_alert_color() {
+static void zuo_alert_color(void) {
   zuo_suspend_signal();
   zuo_print_terminal(1, "\033[94m");
 }
@@ -1797,7 +1798,7 @@
   }
 }
 
-static void zuo_stack_trace() {
+static void zuo_stack_trace(void) {
   zuo_t *k = Z.o_interp_k, *meta_k = Z.o_interp_meta_k;
   zuo_t *showed_name  = z.o_false;
   int repeats = 0;
@@ -1832,7 +1833,7 @@
   exit(v);
 }
 
-static void zuo_sync_in_case_of_fail() {
+static void zuo_sync_in_case_of_fail(void) {
   /* make sure state consulted by zuo_fail() is in "no context" mode */
   Z.o_interp_k = z.o_done_k;
   Z.o_interp_meta_k = z.o_null;
@@ -1911,7 +1912,7 @@
 
 static const char *symbol_chars = "~!@#$%^&*-_=+:<>?/.";
 
-static void zuo_read_fail2(const unsigned char *s, zuo_int_t *_o, zuo_t *where,
+static void zuo_read_fail2(zuo_int_t *_o, zuo_t *where,
                            const char *msg, const char *msg2) {
   const char *in_s = "";
   const char *where_s = "";
@@ -1925,9 +1926,9 @@
   zuo_fail("");
 }
 
-static void zuo_read_fail(const unsigned char *s, zuo_int_t *_o, zuo_t *where,
+static void zuo_read_fail(zuo_int_t *_o, zuo_t *where,
                           const char *msg) {
-  zuo_read_fail2(s, _o, where, msg, "");
+  zuo_read_fail2(_o, where, msg, "");
 }
 
 static int peek_input(const unsigned char *s, zuo_int_t *_o, const char *want) {
@@ -1993,13 +1994,13 @@
 
     if ((stack != z.o_null) && (ZUO_CAR(ZUO_CAR(stack)) == ZUO_IN_PAREN_END_RECUR)) {
       if (c != ')')
-        zuo_read_fail(s, _o, where, "expected closer after dot");
+        zuo_read_fail(_o, where, "expected closer after dot");
       (*_o)++;
       obj = ZUO_CAR(ZUO_CDR(ZUO_CAR(stack)));
       stack = ZUO_CDR(stack);
     } else if ((stack != z.o_null) && (ZUO_CAR(ZUO_CAR(stack)) == ZUO_IN_BRACKET_END_RECUR)) {
       if (c != ']')
-        zuo_read_fail(s, _o, where, "expected closer after dot");
+        zuo_read_fail(_o, where, "expected closer after dot");
       (*_o)++;
       obj = ZUO_CAR(ZUO_CDR(ZUO_CAR(stack)));
       stack = ZUO_CDR(stack);
@@ -2022,7 +2023,7 @@
         obj = ZUO_CAR(ZUO_CDR(ZUO_CAR(stack)));
         stack = ZUO_CDR(stack);
       } else {
-        zuo_read_fail(s, _o, where, "unbalanced closer");
+        zuo_read_fail(_o, where, "unbalanced closer");
         obj = z.o_undefined;
       }
       (*_o)++;
@@ -2043,7 +2044,7 @@
         }
         c = s[*_o];
         if (c == 0) {
-          zuo_read_fail(s, _o, where, "missing closing doublequote");
+          zuo_read_fail(_o, where, "missing closing doublequote");
         } else if (c == '"') {
           (*_o)++;
           break;
@@ -2078,11 +2079,11 @@
             }
             s2[len++] = v;
           } else
-            zuo_read_fail(s, _o, where, "bad character after backslash");
+            zuo_read_fail(_o, where, "bad character after backslash");
         } else if (c == '\n') {
-          zuo_read_fail(s, _o, where, "newline in string literal");
+          zuo_read_fail(_o, where, "newline in string literal");
         } else if (c == '\r') {
-          zuo_read_fail(s, _o, where, "carriage return in string literal");
+          zuo_read_fail(_o, where, "carriage return in string literal");
         } else {
           s2[len++] = c;
           (*_o)++;
@@ -2105,7 +2106,7 @@
         (*_o) += 1;
         obj = z.o_false;
       } else {
-        zuo_read_fail(s, _o, where, "bad hash mark");
+        zuo_read_fail(_o, where, "bad hash mark");
         obj = z.o_undefined;
       }
     } else if ((isdigit(c) || ((c == '-') && isdigit(s[(*_o)+1])))
@@ -2118,7 +2119,7 @@
       while (isdigit(s[*_o])) {
         zuo_uint_t new_n = (10 * n) + (s[*_o] - '0');
         if (new_n < n)
-          zuo_read_fail(s, _o, where, "integer overflow");
+          zuo_read_fail(_o, where, "integer overflow");
         n = new_n;
         (*_o)++;
       }
@@ -2125,11 +2126,11 @@
       if (neg) {
         n = 0 - n;
         if ((zuo_int_t)n > 0)
-          zuo_read_fail(s, _o, where, "integer overflow");
+          zuo_read_fail(_o, where, "integer overflow");
         obj = zuo_integer((zuo_int_t)n);
       } else {
         if ((zuo_int_t)n < 0)
-          zuo_read_fail(s, _o, where, "integer overflow");
+          zuo_read_fail(_o, where, "integer overflow");
         obj = zuo_integer((zuo_int_t)n);
       }
     } else if (c == '\'') {
@@ -2162,7 +2163,7 @@
                && (ZUO_CAR(ZUO_CDR(ZUO_CAR(stack))) != z.o_null))
         ZUO_CAR(ZUO_CAR(stack)) = ZUO_IN_BRACKET_PAIR_RECUR;
       else
-        zuo_read_fail(s, _o, where, "misplaced `.`");
+        zuo_read_fail(_o, where, "misplaced `.`");
       (*_o)++;
       obj = z.o_undefined;
       } else if (isalpha(c) || isdigit(c) || strchr(symbol_chars, c)) {
@@ -2201,19 +2202,19 @@
 
         if (op->car == ZUO_IN_QUOTE_RECUR) {
           if (obj == z.o_eof)
-            zuo_read_fail2(s, _o, where, "end of file after ",
+            zuo_read_fail2(_o, where, "end of file after ",
                            ZUO_STRING_PTR(((zuo_symbol_t *)op->cdr)->str));
           obj = zuo_cons(op->cdr, zuo_cons(obj, z.o_null));
           stack = ZUO_CDR(stack);
         } else if (op->car == ZUO_IN_DISCARD_RECUR) {
           if (obj == z.o_eof)
-            zuo_read_fail(s, _o, where, "end of file after comment hash-semicolon");
+            zuo_read_fail(_o, where, "end of file after comment hash-semicolon");
           stack = ZUO_CDR(stack);
           break;
         } else if ((op->car == ZUO_IN_PAREN_LIST_RECUR)
                    || (op->car == ZUO_IN_BRACKET_LIST_RECUR)) {
           if (obj == z.o_eof) {
-            zuo_read_fail(s, _o, where, "missing closer");
+            zuo_read_fail(_o, where, "missing closer");
             return z.o_undefined;
           } else {
             zuo_t *pr = zuo_cons(obj, z.o_null);
@@ -2227,7 +2228,7 @@
         } else if ((op->car == ZUO_IN_PAREN_PAIR_RECUR)
                    || (op->car == ZUO_IN_BRACKET_PAIR_RECUR)) {
           if (obj == z.o_eof) {
-            zuo_read_fail(s, _o, where, "end of file after dot");
+            zuo_read_fail(_o, where, "end of file after dot");
             return z.o_undefined;
           } else {
             ZUO_CDR(ZUO_CDR(op->cdr)) = obj;
@@ -2297,7 +2298,7 @@
   zuo_in(s, &o, where, 1);
   for (i = 0; expect[i]; i++) {
     if (s[o+i] != expect[i])
-      zuo_read_fail(s, &o, where, "expected #lang followed by a space");
+      zuo_read_fail(&o, where, "expected #lang followed by a space");
   }
   for (j = 0; 1; j++) {
     int c = s[o+i+j];
@@ -2305,9 +2306,9 @@
       break;
   }
   if (!j || !((s[o+i+j] == 0) || isspace(s[o+i+j])))
-    zuo_read_fail(s, &o, where, "expected module library path after #lang");
+    zuo_read_fail(&o, where, "expected module library path after #lang");
 
-  r = zuo_sized_string((char *)s+o+i, j);
+  r = zuo_sized_string((const char *)s+o+i, j);
   r = zuo_symbol_from_string(ZUO_STRING_PTR(r), r);
 
   *_post = o+i+j;
@@ -2319,31 +2320,32 @@
 /* primitive wrapper/dispatchers                                        */
 /*======================================================================*/
 
-static zuo_t *dispatch_primitive0(void *proc, zuo_t *args) {
-  return ((zuo_t *(*)())proc)();
+static zuo_t *dispatch_primitive0(zuo_proc_t proc, zuo_t *args) {
+  ZUO_UNUSED(args);
+  return ((zuo_t *(*)(void))proc)();
 }
 
-static zuo_t *zuo_primitive0(zuo_t *(*f)(), zuo_t *name) {
-  return zuo_primitive(dispatch_primitive0, (void *)f, (1 << 0), name);
+static zuo_t *zuo_primitive0(zuo_t *(*f)(void), zuo_t *name) {
+  return zuo_primitive(dispatch_primitive0, (zuo_proc_t)f, (1 << 0), name);
 }
 
-static zuo_t *dispatch_primitive1(void *proc, zuo_t *args) {
+static zuo_t *dispatch_primitive1(zuo_proc_t proc, zuo_t *args) {
   return ((zuo_t *(*)(zuo_t *))proc)(ZUO_CAR(args));
 }
 
 static zuo_t *zuo_primitive1(zuo_t *(*f)(zuo_t *), zuo_t *name) {
-  return zuo_primitive(dispatch_primitive1, (void *)f, (1 << 1), name);
+  return zuo_primitive(dispatch_primitive1, (zuo_proc_t)f, (1 << 1), name);
 }
 
-static zuo_t *dispatch_primitive2(void *proc, zuo_t *args) {
+static zuo_t *dispatch_primitive2(zuo_proc_t proc, zuo_t *args) {
   return ((zuo_t *(*)(zuo_t *, zuo_t *))proc)(ZUO_CAR(args), ZUO_CAR(ZUO_CDR(args)));
 }
 
 static zuo_t *zuo_primitive2(zuo_t *(*f)(zuo_t *, zuo_t *), zuo_t *name) {
-  return zuo_primitive(dispatch_primitive2, (void *)f, (1 << 2), name);
+  return zuo_primitive(dispatch_primitive2, (zuo_proc_t)f, (1 << 2), name);
 }
 
-static zuo_t *dispatch_primitive3(void *proc, zuo_t *args) {
+static zuo_t *dispatch_primitive3(zuo_proc_t proc, zuo_t *args) {
   return ((zuo_t *(*)(zuo_t *, zuo_t *, zuo_t *))proc)(ZUO_CAR(args),
                                                        ZUO_CAR(ZUO_CDR(args)),
                                                        ZUO_CAR(ZUO_CDR(ZUO_CDR(args))));
@@ -2350,10 +2352,10 @@
 }
 
 static zuo_t *zuo_primitive3(zuo_t *(*f)(zuo_t *, zuo_t *, zuo_t *), zuo_t *name) {
-  return zuo_primitive(dispatch_primitive3, (void *)f, (1 << 3), name);
+  return zuo_primitive(dispatch_primitive3, (zuo_proc_t)f, (1 << 3), name);
 }
 
-static zuo_t *dispatch_primitivea(void *proc, zuo_t *args) {
+static zuo_t *dispatch_primitivea(zuo_proc_t proc, zuo_t *args) {
   return ((zuo_t *(*)(zuo_t *))proc)((args == z.o_null)
                                      ? z.o_undefined
                                      : ZUO_CAR(args));
@@ -2360,10 +2362,10 @@
 }
 
 static zuo_t *zuo_primitivea(zuo_t *(*f)(zuo_t *), zuo_t *name) {
-  return zuo_primitive(dispatch_primitivea, (void *)f, ((1 << 0) | (1 << 1)), name);
+  return zuo_primitive(dispatch_primitivea, (zuo_proc_t)f, ((1 << 0) | (1 << 1)), name);
 }
 
-static zuo_t *dispatch_primitiveb(void *proc, zuo_t *args) {
+static zuo_t *dispatch_primitiveb(zuo_proc_t proc, zuo_t *args) {
   return ((zuo_t *(*)(zuo_t *, zuo_t *))proc)(ZUO_CAR(args),
                                               ((ZUO_CDR(args) == z.o_null)
                                                ? z.o_undefined
@@ -2371,10 +2373,10 @@
 }
 
 static zuo_t *zuo_primitiveb(zuo_t *(*f)(zuo_t *, zuo_t *), zuo_t *name) {
-  return zuo_primitive(dispatch_primitiveb, (void *)f, ((1 << 1) | (1 << 2)), name);
+  return zuo_primitive(dispatch_primitiveb, (zuo_proc_t)f, ((1 << 1) | (1 << 2)), name);
 }
 
-static zuo_t *dispatch_primitivec(void *proc, zuo_t *args) {
+static zuo_t *dispatch_primitivec(zuo_proc_t proc, zuo_t *args) {
   return ((zuo_t *(*)(zuo_t *, zuo_t *, zuo_t *))proc)(ZUO_CAR(args), ZUO_CAR(ZUO_CDR(args)),
                                                        ((ZUO_CDR(ZUO_CDR(args)) == z.o_null)
                                                         ? z.o_undefined
@@ -2382,10 +2384,10 @@
 }
 
 static zuo_t *zuo_primitivec(zuo_t *(*f)(zuo_t *, zuo_t *, zuo_t *), zuo_t *name) {
-  return zuo_primitive(dispatch_primitivec, (void *)f, ((1 << 2) | (1 << 3)), name);
+  return zuo_primitive(dispatch_primitivec, (zuo_proc_t)f, ((1 << 2) | (1 << 3)), name);
 }
 
-static zuo_t *dispatch_primitiveC(void *proc, zuo_t *args) {
+static zuo_t *dispatch_primitiveC(zuo_proc_t proc, zuo_t *args) {
   zuo_t *a = ZUO_CAR(args), *b = z.o_undefined, *c = z.o_undefined;
   args = ZUO_CDR(args);
   if (args != z.o_null) {
@@ -2398,15 +2400,15 @@
 }
 
 static zuo_t *zuo_primitiveC(zuo_t *(*f)(zuo_t *, zuo_t *, zuo_t *), zuo_t *name) {
-  return zuo_primitive(dispatch_primitiveC, (void *)f, ((1 << 1) | (1 << 2) | (1 << 3)), name);
+  return zuo_primitive(dispatch_primitiveC, (zuo_proc_t)f, ((1 << 1) | (1 << 2) | (1 << 3)), name);
 }
 
-static zuo_t *dispatch_primitiveN(void *proc, zuo_t *args) {
+static zuo_t *dispatch_primitiveN(zuo_proc_t proc, zuo_t *args) {
   return ((zuo_t *(*)(zuo_t *))proc)(args);
 }
 
 static zuo_t *zuo_primitiveN(zuo_t *(*f)(zuo_t *), zuo_int_t mask, zuo_t *name) {
-  return zuo_primitive(dispatch_primitiveN, (void *)f, mask, name);
+  return zuo_primitive(dispatch_primitiveN, (zuo_proc_t)f, mask, name);
 }
 
 /*======================================================================*/
@@ -3087,10 +3089,11 @@
 }
 
 static zuo_t *zuo_make_void(zuo_t *args) {
+  ZUO_UNUSED(args);
   return z.o_void;
 }
 
-static zuo_t *zuo_kernel_env() {
+static zuo_t *zuo_kernel_env(void) {
   return z.o_top_env;
 }
 
@@ -3217,7 +3220,7 @@
   return zuo_trie_lookup(env, sym);
 }
 
-static void interp_step() {
+static void interp_step(void) {
   zuo_t *e = Z.o_interp_e;
 
   if (zuo_probe_each) {
@@ -3274,7 +3277,7 @@
     Z.o_interp_v = e;
 }
 
-static void continue_step() {
+static void continue_step(void) {
   zuo_cont_t *k = (zuo_cont_t *)Z.o_interp_k;
   Z.o_interp_k = k->next;
   Z.o_interp_in_proc = k->in_proc;
@@ -3431,7 +3434,7 @@
   }
 }
 
-zuo_t *zuo_kernel_eval(zuo_t *e) {
+static zuo_t *zuo_kernel_eval(zuo_t *e) {
   check_syntax(e);
 
   Z.o_interp_e = e;
@@ -3496,8 +3499,7 @@
 }
 #endif
 
-static zuo_t *zuo_get_envvars()
-{
+static zuo_t *zuo_get_envvars(void) {
   zuo_t *first = z.o_null, *last = NULL, *pr;
 
 #ifdef ZUO_UNIX
@@ -3556,8 +3558,7 @@
   return first;
 }
 
-static void *zuo_envvars_block(const char *who, zuo_t *envvars)
-{
+static void *zuo_envvars_block(zuo_t *envvars) {
 #ifdef ZUO_UNIX
   char **r, *s;
   intptr_t len = 0, slen, c, count = 0;
@@ -3592,7 +3593,6 @@
 #endif
 #ifdef ZUO_WINDOWS
   zuo_t *l;
-  zuo_int_t i;
   zuo_int_t r_size = 256, r_len = 0, namelen, vallen, slen;
   wchar_t *r = malloc(r_size * sizeof(wchar_t)), *name, *val;
 
@@ -3707,7 +3707,7 @@
   return zuo_path_is_absolute(ZUO_STRING_PTR(obj)) ? z.o_false : z.o_true;
 }
 
-static char *zuo_getcwd() {
+static char *zuo_getcwd(void) {
   char *dir;
   char *s;
   int len = 256;
@@ -3753,7 +3753,7 @@
   return dir;
 }
 
-static zuo_t *zuo_current_directory() {
+static zuo_t *zuo_current_directory(void) {
   char *dir = zuo_getcwd();
   zuo_t *obj;
 
@@ -3946,6 +3946,7 @@
   return zuo_build_path_multi("build-path", paths, zuo_build_path2);
 }
 
+#ifndef ZUO_EMBEDDED
 static zuo_t *zuo_normalize_input_path(zuo_t *path) {
   /* Using "." is meant to work even if `path` is absolute: */
   return zuo_build_path2(zuo_string("."), path);
@@ -3957,8 +3958,9 @@
   else
     return zuo_build_path2(zuo_current_directory(), path);
 }
+#endif
 
-zuo_t *zuo_library_path_to_file_path(zuo_t *path) {
+static zuo_t *zuo_library_path_to_file_path(zuo_t *path) {
   zuo_t *strobj;
   int saw_slash = 0;
 
@@ -3977,7 +3979,7 @@
   return zuo_build_path2(Z.o_library_path, strobj);
 }
 
-zuo_t *zuo_parse_relative_module_path(const char *who, zuo_t *rel_mod_path, int *_ups, int strip_ups) {
+static zuo_t *zuo_parse_relative_module_path(const char *who, zuo_t *rel_mod_path, int *_ups, int strip_ups) {
   zuo_int_t i = 0, len = ZUO_STRING_LEN(rel_mod_path);
   unsigned char *s = (unsigned char *)ZUO_STRING_PTR(rel_mod_path);
   int bad = 0, ups = 1, ups_until = 0, saw_non_dot = 0, suffix = 0;
@@ -4029,7 +4031,7 @@
     return rel_mod_path;
 }
 
-zuo_t *zuo_build_module_path(zuo_t *base_mod_path, zuo_t *rel_mod_path) {
+static zuo_t *zuo_build_module_path(zuo_t *base_mod_path, zuo_t *rel_mod_path) {
   const char *who = "build-module-path";
   int saw_slash = 0, ups = 0, strip_ups;
   zuo_t *rel_str;
@@ -4077,7 +4079,7 @@
   }
 }
 
-static zuo_t *zuo_runtime_env() {
+static zuo_t *zuo_runtime_env(void) {
   return Z.o_runtime_env;
 }
 
@@ -4346,17 +4348,19 @@
       zuo_fail1w_errno(who, "file open failed", path);
 #endif
 #ifdef ZUO_WINDOWS
-    wchar_t *wp = zuo_to_wide(ZUO_STRING_PTR(path));
-    fd = CreateFileW(wp,
-                     GENERIC_READ,
-                     FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                     NULL,
-                     OPEN_EXISTING,
-                     0,
-                     NULL);
-    if (fd == INVALID_HANDLE_VALUE)
-      zuo_fail1w(who, "file open failed", path);
-    free(wp);
+    {
+      wchar_t *wp = zuo_to_wide(ZUO_STRING_PTR(path));
+      fd = CreateFileW(wp,
+                       GENERIC_READ,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                       NULL,
+                       OPEN_EXISTING,
+                       0,
+                       NULL);
+      if (fd == INVALID_HANDLE_VALUE)
+        zuo_fail1w(who, "file open failed", path);
+      free(wp);
+    }
 #endif
     return fd;
   } else if (path == zuo_symbol("stdin")) {
@@ -4524,7 +4528,7 @@
   return z.o_void;
 }
 
-zuo_t *zuo_fd_write(zuo_t *fd_h, zuo_t *str) {
+static zuo_t *zuo_fd_write(zuo_t *fd_h, zuo_t *str) {
   const char *who = "fd-write";
 
   if ((fd_h->tag != zuo_handle_tag)
@@ -4559,7 +4563,7 @@
   return zuo_drain(ZUO_HANDLE_RAW(fd_h), amt);
 }
 
-zuo_t *zuo_fd_poll(zuo_t *fds_i, zuo_t *timeout_i) {
+static zuo_t *zuo_fd_poll(zuo_t *fds_i, zuo_t *timeout_i) {
   const char *who = "fd-poll";
   zuo_t *l;
   zuo_int_t len = 0, which = -1, timeout;
@@ -4623,6 +4627,7 @@
     if (timeout != 0)
       Sleep(timeout < 0 ? INFINITE : timeout);
     which = len;
+    fds = NULL;
   } else {
     zuo_int_t i = 0;
     DWORD r;
@@ -4648,7 +4653,8 @@
   for (l = fds_i; which > 0; l = _zuo_cdr(l))
     which--;
 
-  free(fds);
+  if (fds != NULL)
+    free(fds);
 
   if (l == z.o_null)
     return z.o_false;
@@ -4709,9 +4715,9 @@
   /* no runtime state is preserved */
   {
     zuo_t **p = (zuo_t **)&zuo_roots.runtime;
-    int i, len;
-    len = sizeof(zuo_roots.runtime) / sizeof(zuo_t*);
-    for (i = 0; i < len; i++)
+    int i, runtime_len;
+    runtime_len = sizeof(zuo_roots.runtime) / sizeof(zuo_t*);
+    for (i = 0; i < runtime_len; i++)
       p[i] = z.o_undefined;
     Z.o_interp_k = z.o_done_k; /* in case of a failure that might try to show a stack trace */
     Z.o_interp_meta_k = z.o_null;
@@ -4731,7 +4737,7 @@
 /* modules                                                              */
 /*======================================================================*/
 
-static zuo_t *zuo_declare_kernel_module() {
+static zuo_t *zuo_declare_kernel_module(void) {
   /* We implement the `read-and-eval` or `zuo/kernel` and
      `module->hash` here as hand-built closures. We can't make them
      primitives, becase they need to use the `kernel-eval`
@@ -4990,7 +4996,7 @@
 /* filesystem and time                                                  */
 /*======================================================================*/
 
-#if defined(__APPLE__) && defined(__MACH__)
+#if defined(__APPLE__) && defined(__MACH__) && !defined(_POSIX_C_SOURCE)
 # define zuo_st_atim st_atimespec
 # define zuo_st_mtim st_mtimespec
 # define zuo_st_ctim st_ctimespec
@@ -5057,6 +5063,16 @@
     result = zuo_hash_set(result, zuo_symbol("size"), zuo_integer(stat_buf.st_size));
     result = zuo_hash_set(result, zuo_symbol("block-size"), zuo_integer(stat_buf.st_blksize));
     result = zuo_hash_set(result, zuo_symbol("block-count"), zuo_integer(stat_buf.st_blocks));
+# if defined(_POSIX_C_SOURCE)
+    /* IEEE Std 1003.1-2017 has `st_atim`, etc., but even when `_POSIX_C_SOURCE` is set to request
+       that, it may not be available */
+    result = zuo_hash_set(result, zuo_symbol("access-time-seconds"), zuo_integer(stat_buf.st_atime));
+    result = zuo_hash_set(result, zuo_symbol("access-time-nanoseconds"), zuo_integer(0));
+    result = zuo_hash_set(result, zuo_symbol("modify-time-seconds"), zuo_integer(stat_buf.st_mtime));
+    result = zuo_hash_set(result, zuo_symbol("modify-time-nanoseconds"), zuo_integer(0));
+    result = zuo_hash_set(result, zuo_symbol("creation-time-seconds"), zuo_integer(stat_buf.st_ctime));
+    result = zuo_hash_set(result, zuo_symbol("creation-time-nanoseconds"), zuo_integer(0));
+# else
     result = zuo_hash_set(result, zuo_symbol("access-time-seconds"), zuo_integer(stat_buf.zuo_st_atim.tv_sec));
     result = zuo_hash_set(result, zuo_symbol("access-time-nanoseconds"), zuo_integer(stat_buf.zuo_st_atim.tv_nsec));
     result = zuo_hash_set(result, zuo_symbol("modify-time-seconds"), zuo_integer(stat_buf.zuo_st_mtim.tv_sec));
@@ -5063,6 +5079,7 @@
     result = zuo_hash_set(result, zuo_symbol("modify-time-nanoseconds"), zuo_integer(stat_buf.zuo_st_mtim.tv_nsec));
     result = zuo_hash_set(result, zuo_symbol("creation-time-seconds"), zuo_integer(stat_buf.zuo_st_ctim.tv_sec));
     result = zuo_hash_set(result, zuo_symbol("creation-time-nanoseconds"), zuo_integer(stat_buf.zuo_st_ctim.tv_nsec));
+# endif
   }
 #endif
 #ifdef ZUO_WINDOWS
@@ -5425,7 +5442,7 @@
   return z.o_void;
 }
 
-zuo_t *zuo_current_time() {
+static zuo_t *zuo_current_time(void) {
 #ifdef ZUO_UNIX
   /* clock_gettime() provides more precision but may require linking
      to an extra library */
@@ -5461,7 +5478,7 @@
 static BOOL WINAPI zuo_signal_received(DWORD op);
 #endif
 
-static zuo_t *zuo_suspend_signal() {
+static zuo_t *zuo_suspend_signal(void) {
   if (zuo_signal_suspended++ == 0) {
 #ifdef ZUO_UNIX
     sigset_t set;
@@ -5483,7 +5500,7 @@
   return z.o_void;
 }
 
-static zuo_t *zuo_resume_signal() {
+static zuo_t *zuo_resume_signal(void) {
   if (zuo_signal_suspended == 0)
     return z.o_void;
 
@@ -5562,7 +5579,8 @@
 }
 
 #ifdef ZUO_UNIX
-static void zuo_signal_received() {
+static void zuo_signal_received(int sig) {
+  ZUO_UNUSED(sig);
   zuo_clean_all(0);
   _exit(1);
 }
@@ -5569,6 +5587,7 @@
 #endif
 #ifdef ZUO_WINDOWS
 static BOOL WINAPI zuo_signal_received(DWORD op) {
+  ZUO_UNUSED(op);
   if (InterlockedExchange(&zuo_handler_suspended, -1) == 0) {
     zuo_clean_all(1);
     _exit(1);
@@ -5577,7 +5596,7 @@
 }
 #endif
 
-static void zuo_init_signal_handler() {
+static void zuo_init_signal_handler(void) {
 #ifdef ZUO_UNIX
   struct sigaction sa;
   sigemptyset(&sa.sa_mask);
@@ -5642,7 +5661,7 @@
   }
 
   while (*s) {
-    int c = *(unsigned char *)s;
+    int c = *(const unsigned char *)s;
     s++;
 
     if (i + 6 >= sz) {
@@ -5695,6 +5714,8 @@
   int maxargs = 32;
   char **command = (char **)malloc((maxargs + 1) * sizeof(char *));
 
+  ZUO_UNUSED(skip_exe);
+
   while (1) {
     int c = ((unsigned char *)buf)[i];
     if (c == 0)
@@ -5938,8 +5959,6 @@
 #endif
 #ifdef ZUO_WINDOWS
   {
-    HANDLE rh, wh;
-
     if (!CreatePipe(_r, _w, NULL, 0))
       zuo_fail("pipe creation failed");
   }
@@ -5946,7 +5965,7 @@
 #endif
 }
 
-zuo_t *zuo_process(zuo_t *command_and_args)
+static zuo_t *zuo_process(zuo_t *command_and_args)
 {
   const char *who = "process";
   zuo_t *command = _zuo_car(command_and_args);
@@ -6047,26 +6066,26 @@
 
   opt = zuo_consume_option(&options, "env");
   if (opt != z.o_undefined) {
-    zuo_t *l;
-    for (l = opt; l->tag == zuo_pair_tag; l = _zuo_cdr(l)) {
-      zuo_t *a = _zuo_car(l), *name, *val;
-      zuo_int_t i;
+    zuo_t *ol;
+    for (ol = opt; ol->tag == zuo_pair_tag; ol = _zuo_cdr(ol)) {
+      zuo_t *a = _zuo_car(ol), *name, *val;
+      zuo_int_t j;
 
       if (a->tag != zuo_pair_tag) break;
       name = _zuo_car(a);
       if (name->tag != zuo_string_tag) break;
-      for (i = ZUO_STRING_LEN(name); i--; ) {
-        int c = ZUO_STRING_PTR(name)[i];
+      for (j = ZUO_STRING_LEN(name); j--; ) {
+        int c = ZUO_STRING_PTR(name)[j];
         if ((c == '=') || (c == 0)) break;
       }
-      if (i >= 0) break;
+      if (j >= 0) break;
 
       val = _zuo_cdr(a);
       if (val->tag != zuo_string_tag) break;
     }
-    if (l != z.o_null)
+    if (ol != z.o_null)
       zuo_fail_arg(who, "valid environment variables list", opt);
-    env = zuo_envvars_block(who, opt);
+    env = zuo_envvars_block(opt);
   } else
     env = NULL;
 
@@ -6308,7 +6327,7 @@
               || (((zuo_handle_t *)p)->u.h.status != zuo_handle_process_running_status)));
 }
 
-zuo_t *zuo_process_status(zuo_t *p) {
+static zuo_t *zuo_process_status(zuo_t *p) {
   if (!is_process_handle(p))
     zuo_fail_arg("process-status", "process handle", p);
 
@@ -6318,7 +6337,7 @@
     return zuo_integer(((zuo_handle_t *)p)->u.h.u.result);
 }
 
-zuo_t *zuo_process_wait(zuo_t *pids_i) {
+static zuo_t *zuo_process_wait(zuo_t *pids_i) {
   zuo_t *l;
 
   for (l = pids_i; l != z.o_null; l = _zuo_cdr(l)) {
@@ -6863,7 +6882,13 @@
 
 /* Get the final hash value after all bytes have been added */
 static void zuo_sha256_final(zuo_sha2_ctx_t *context, zuo_uint8_t digest[ZUO_SHA256_DIGEST_SIZE]) {
-  (void)mbedtls_sha256_finish_ret(context, digest);
+  if (mbedtls_sha256_finish_ret(context, digest) != 0) {
+    /* there's no way to get a non-0 result, but a compiler might worry,
+       so appease it with code to initialize `digest` */
+    int i;
+    for (i = 0; i < ZUO_SHA256_DIGEST_SIZE; i++)
+      digest[i] = 0;
+  }
 }
 
 /* ************************************************************ */
@@ -6894,6 +6919,8 @@
 /* executable self path                                                 */
 /*======================================================================*/
 
+#ifndef ZUO_EMBEDDED
+
 #if defined(__linux__)
 
 # include <errno.h>
@@ -6904,6 +6931,8 @@
   ssize_t len, blen = 256;
   char *s = malloc(blen);
 
+  ZUO_UNUSED(exec_file);
+
   while (1) {
     len = readlink("/proc/self/exe", s, blen-1);
     if (len == (blen-1)) {
@@ -6932,6 +6961,8 @@
   size_t len;
   int r;
 
+  ZUO_UNUSED(exec_file);
+
   mib[0] = CTL_KERN;
 #if defined(__NetBSD__)
   mib[1] = KERN_PROC_ARGS;
@@ -6965,6 +6996,8 @@
   char *s = malloc(size);
   int r;
 
+  ZUO_UNUSED(exec_file);
+
   r = _NSGetExecutablePath(s, &size);
   if (!r)
     return s;
@@ -6987,6 +7020,8 @@
   wchar_t *path;
   DWORD r, sz = 1024;
 
+  ZUO_UNUSED(exec_file);
+
   while (1) {
     path = (wchar_t *)malloc(sz * sizeof(wchar_t));
     r = GetModuleFileNameW(NULL, path, sz);
@@ -7067,6 +7102,7 @@
   free(s);
   return str;
 }
+#endif
 
 /*======================================================================*/
 /* initialization                                                       */
@@ -7079,7 +7115,7 @@
       zuo_trie_set(z.o_top_env, sym, make_prim); \
     } else {                                     \
       zuo_t *sym = z.o_undefined;                \
-      (void)make_prim;                           \
+      ZUO_UNUSED(make_prim);                     \
     }                                            \
   } while (0)
 
@@ -7331,7 +7367,7 @@
 
 #ifndef ZUO_EMBEDDED
 
-int zuo_main(int argc, char **argv) {
+static int zuo_main(int argc, char **argv) {
   char *load_file = NULL, *library_path = NULL, *boot_image = NULL;
   char *argv0 = argv[0];
   zuo_t *exe_path, *load_path, *lib_path;
@@ -7538,7 +7574,7 @@
 
 #ifdef ZUO_EMBEDDED
 
-void zuo_ext_primitive_init() {  zuo_primitive_init(0); }
+void zuo_ext_primitive_init(void) {  zuo_primitive_init(0); }
 void zuo_ext_add_primitive(zuo_ext_primitive_t proc, int arity_mask, const char *name) {
   int will_load_image = 0;
   ZUO_TOP_ENV_SET_PRIMITIVEN(name, proc, arity_mask);
@@ -7546,12 +7582,12 @@
 
 void zuo_ext_image_init(char *boot_image) { zuo_image_init(boot_image); }
 
-zuo_ext_t *zuo_ext_false() { return z.o_false; }
-zuo_ext_t *zuo_ext_true() { return z.o_true; }
-zuo_ext_t *zuo_ext_null() { return z.o_null; }
-zuo_ext_t *zuo_ext_void() { return z.o_void; }
-zuo_ext_t *zuo_ext_eof() { return z.o_eof; }
-zuo_ext_t *zuo_ext_empty_hash() { return z.o_empty_hash; }
+zuo_ext_t *zuo_ext_false(void) { return z.o_false; }
+zuo_ext_t *zuo_ext_true(void) { return z.o_true; }
+zuo_ext_t *zuo_ext_null(void) { return z.o_null; }
+zuo_ext_t *zuo_ext_void(void) { return z.o_void; }
+zuo_ext_t *zuo_ext_eof(void) { return z.o_eof; }
+zuo_ext_t *zuo_ext_empty_hash(void) { return z.o_empty_hash; }
 zuo_ext_t *zuo_ext_integer(long long i) { return zuo_integer((zuo_int_t)i); }
 long long zuo_ext_integer_value(zuo_ext_t *v) { return (long long)ZUO_INT_I(v); }
 zuo_ext_t *zuo_ext_cons(zuo_ext_t *car, zuo_ext_t *cdr) { return zuo_cons(car, cdr); }
@@ -7564,7 +7600,7 @@
 zuo_ext_t *zuo_ext_hash_ref(zuo_ext_t *ht, zuo_ext_t *key, zuo_ext_t *fail) { return zuo_hash_ref(ht, key, fail); }
 zuo_ext_t *zuo_ext_hash_set(zuo_ext_t *ht, zuo_ext_t *key, zuo_ext_t *val) { return zuo_hash_set(ht, key, val); }
 
-zuo_ext_t *zuo_ext_kernel_env() { return z.o_top_env; }
+zuo_ext_t *zuo_ext_kernel_env(void) { return z.o_top_env; }
 zuo_ext_t *zuo_ext_apply(zuo_ext_t *proc, zuo_ext_t *args) {
   /* special-case primtives, so this can be used to perform primitive
      operations without triggering a GC */
@@ -7587,6 +7623,6 @@
 }
 
 void zuo_ext_stash_push(zuo_ext_t *v) { Z.o_stash = zuo_cons(v, Z.o_stash); }
-zuo_ext_t *zuo_ext_stash_pop() { zuo_t *v = _zuo_car(Z.o_stash); Z.o_stash = _zuo_cdr(Z.o_stash); return v; }
+zuo_ext_t *zuo_ext_stash_pop(void) { zuo_t *v = _zuo_car(Z.o_stash); Z.o_stash = _zuo_cdr(Z.o_stash); return v; }
 
 #endif
--- a/zuo.h
+++ b/zuo.h
@@ -35,7 +35,7 @@
    primitives will effectively remove them by using the image's
    `kernel-env`.
  */
-ZUO_EXPORT void zuo_ext_primitive_init();
+ZUO_EXPORT void zuo_ext_primitive_init(void);
 
 /* Add more primitives only after calling `zuo_ext_primitive_init`: */
 typedef zuo_ext_t *(*zuo_ext_primitive_t)(zuo_ext_t *args_list);
@@ -51,12 +51,12 @@
 /* After calling `zuo_ext_image_init`, the following functions are available: */
 
 /* Functions that get a constant: */
-ZUO_EXPORT zuo_ext_t *zuo_ext_false();
-ZUO_EXPORT zuo_ext_t *zuo_ext_true();
-ZUO_EXPORT zuo_ext_t *zuo_ext_null();
-ZUO_EXPORT zuo_ext_t *zuo_ext_void();
-ZUO_EXPORT zuo_ext_t *zuo_ext_eof();
-ZUO_EXPORT zuo_ext_t *zuo_ext_empty_hash();
+ZUO_EXPORT zuo_ext_t *zuo_ext_false(void);
+ZUO_EXPORT zuo_ext_t *zuo_ext_true(void);
+ZUO_EXPORT zuo_ext_t *zuo_ext_null(void);
+ZUO_EXPORT zuo_ext_t *zuo_ext_void(void);
+ZUO_EXPORT zuo_ext_t *zuo_ext_eof(void);
+ZUO_EXPORT zuo_ext_t *zuo_ext_empty_hash(void);
 
 /* Other data constructors and accessors: */
 ZUO_EXPORT zuo_ext_t *zuo_ext_integer(long long i);
@@ -74,7 +74,7 @@
 /* To get more functions, use a symbol key to look them up in the
    kernel environment via `zuo_ext_hash_ref` --- but don't try to
    load, evaluate, or use any modules, yet: */
-ZUO_EXPORT zuo_ext_t *zuo_ext_kernel_env();
+ZUO_EXPORT zuo_ext_t *zuo_ext_kernel_env(void);
 
 /* At this stage, use `zuo_ext_apply` to apply primitives that don't
    evaluate. After `zuo_ext_runtime_init`, use this to apply and
@@ -115,7 +115,7 @@
 /* For saving and retriving a value across an evaluation, which is
    when a GC might happen: */
 ZUO_EXPORT void zuo_ext_stash_push(zuo_ext_t *v);
-ZUO_EXPORT zuo_ext_t *zuo_ext_stash_pop();
+ZUO_EXPORT zuo_ext_t *zuo_ext_stash_pop(void);
 
 #endif