From 06fb5aceeb65a75b1cd643debd667c52fdcafcb9 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sun, 8 Nov 2026 14:10:02 -0800 Subject: Better error messages Better error messages. Buffs to the std lib; getch() to fetch a single character; streaming I/O handles retries, and large sizes, with better error reporting. Formatted strings. Default int moved to i32. TicTacToe, the game. --- .../java/com/seaofnodes/simple/progs/extern_data.c | 7 ++++ .../test/java/com/seaofnodes/simple/progs/int32.c | 26 ++++++++++++ .../com/seaofnodes/simple/progs/runtime_args.c | 35 ++++++++++++++++ .../test/java/com/seaofnodes/simple/progs/sort.c | 4 +- .../java/com/seaofnodes/simple/progs/stream_io.c | 49 ++++++++++++++++++++++ .../java/com/seaofnodes/simple/progs/stringHash.c | 2 +- 6 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 chapter30/src/test/java/com/seaofnodes/simple/progs/int32.c create mode 100644 chapter30/src/test/java/com/seaofnodes/simple/progs/runtime_args.c create mode 100644 chapter30/src/test/java/com/seaofnodes/simple/progs/stream_io.c (limited to 'chapter30/src/test/java/com/seaofnodes/simple/progs') diff --git a/chapter30/src/test/java/com/seaofnodes/simple/progs/extern_data.c b/chapter30/src/test/java/com/seaofnodes/simple/progs/extern_data.c index 9325f65e..e8156d0f 100644 --- a/chapter30/src/test/java/com/seaofnodes/simple/progs/extern_data.c +++ b/chapter30/src/test/java/com/seaofnodes/simple/progs/extern_data.c @@ -7,8 +7,13 @@ double fraction=1.25; int64_t bump(void) { counter+=5; return counter; } __attribute__((CALL_CONV)) extern int64_t test_global(void); +__attribute__((CALL_CONV)) extern int64_t extern_matches(int32_t); +__attribute__((CALL_CONV)) extern int64_t extern_less(int32_t); +__attribute__((CALL_CONV)) extern int64_t extern_seven(void); int main(void) { + if (!extern_matches(7) || extern_matches(8) || !extern_seven() || + !extern_less(6) || extern_less(7) || extern_less(8)) return 2; int64_t result=test_global(); if(result!=71515 || counter!=15 || small!=-2 || fraction!=1.75) { printf("result=%lld counter=%d small=%d fraction=%g\n", @@ -17,6 +22,8 @@ int main(void) { } // A second call must observe C's new values, not a Simple initialization copy. counter=-2; + if (!extern_matches(-2) || extern_matches(7) || extern_seven() || + !extern_less(-3) || extern_less(-2)) return 3; result=test_global(); return result!=-19394 || counter!=6 || small!=-1 || fraction!=2.25; } diff --git a/chapter30/src/test/java/com/seaofnodes/simple/progs/int32.c b/chapter30/src/test/java/com/seaofnodes/simple/progs/int32.c new file mode 100644 index 00000000..9694c47b --- /dev/null +++ b/chapter30/src/test/java/com/seaofnodes/simple/progs/int32.c @@ -0,0 +1,26 @@ +#include +#include + +typedef struct { int32_t x, y; } Pair; +typedef struct { uint32_t len; int32_t values[]; } Ints; + +__attribute__((CALL_CONV)) extern int64_t int_echo(int32_t); +__attribute__((CALL_CONV)) extern int64_t int_wrap(int32_t); +__attribute__((CALL_CONV)) extern int64_t wide_echo(int64_t); +__attribute__((CALL_CONV)) extern int64_t narrow_sum(int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,int32_t,uint32_t); +__attribute__((CALL_CONV)) extern Pair *int_pair(void); +__attribute__((CALL_CONV)) extern Ints *int_array(void); + +int main(void) { + if (int_echo(-1) != -1 || int_echo(INT32_MIN) != INT32_MIN) return 1; + if (int_wrap(INT32_MAX) != INT32_MIN) return 2; + if (wide_echo(INT64_MAX) != INT64_MAX || wide_echo(INT64_MIN) != INT64_MIN) return 3; + int64_t expected = -128LL + 255 - 32768 + 65535 + INT32_MIN + UINT32_MAX - 7 + UINT32_MAX; + if (narrow_sum(-128,255,-32768,65535,INT32_MIN,UINT32_MAX,-7,UINT32_MAX) != expected) return 4; + Pair *p = int_pair(); + if (p->x != -1 || p->y != INT32_MAX) return 5; + Ints *a = int_array(); + if (a->len != 3 || a->values[0] != -1 || a->values[1] != INT32_MAX || a->values[2] != INT32_MIN) return 6; + puts("ok"); + return 0; +} diff --git a/chapter30/src/test/java/com/seaofnodes/simple/progs/runtime_args.c b/chapter30/src/test/java/com/seaofnodes/simple/progs/runtime_args.c new file mode 100644 index 00000000..cd676006 --- /dev/null +++ b/chapter30/src/test/java/com/seaofnodes/simple/progs/runtime_args.c @@ -0,0 +1,35 @@ +#include +#include +#include + +typedef struct { uint32_t len; unsigned char bytes[]; } Bytes; +typedef struct { uint32_t len, pad; Bytes *args[]; } Args; + +__attribute__((CALL_CONV)) +extern Args *simple_args(int64_t argc, char **argv); + +const char *simple_argv(char **argv, int64_t index) { return argv[index]; } + +int main(void) { + Args *empty = simple_args(0, NULL); + if (!empty || empty->len != 0) return 1; + if (simple_args(-1, NULL) != NULL) return 2; + if (simple_args(4294967296LL, NULL) != NULL) return 6; + + char name[] = "program", blank[] = "", utf8[] = "\xc3\xa9\xcf\x80"; + char *argv[] = { name, blank, utf8, name }; + Args *args = simple_args(4, argv); + if (!args || args->len != 4) return 3; + for (int i = 0; i < 4; i++) { + if (!args->args[i] || args->args[i]->len != strlen(argv[i]) || + memcmp(args->args[i]->bytes, argv[i], args->args[i]->len)) return 4; + } + // Copies survive changes to the native buffers, and repeated argv pointers + // still produce independent Simple arrays. + name[0] = 'X'; + utf8[0] = 0; + args->args[0]->bytes[0] = 'Y'; + if (args->args[3]->bytes[0] != 'p' || args->args[2]->bytes[0] != 0xc3) return 5; + puts("ok"); + return 0; +} diff --git a/chapter30/src/test/java/com/seaofnodes/simple/progs/sort.c b/chapter30/src/test/java/com/seaofnodes/simple/progs/sort.c index ad76cc7f..08acf2da 100644 --- a/chapter30/src/test/java/com/seaofnodes/simple/progs/sort.c +++ b/chapter30/src/test/java/com/seaofnodes/simple/progs/sort.c @@ -5,14 +5,14 @@ typedef struct AryInt { unsigned int len; - long long data[]; + int data[]; } AryInt; __attribute__ ((CALL_CONV)) extern AryInt* merge_sort(AryInt*); -long long primes[] = { 25, 97, 89, 83, 79, 73, 71, 67, 61, 59, 53, 47, 43, 41, 37, 31, 29, 23, 19, 17, 13, 11, 7, 5, 3, 2 }; +int primes[] = { 25, 97, 89, 83, 79, 73, 71, 67, 61, 59, 53, 47, 43, 41, 37, 31, 29, 23, 19, 17, 13, 11, 7, 5, 3, 2 }; int main() { AryInt *as = (AryInt*)primes; diff --git a/chapter30/src/test/java/com/seaofnodes/simple/progs/stream_io.c b/chapter30/src/test/java/com/seaofnodes/simple/progs/stream_io.c new file mode 100644 index 00000000..5cd1096a --- /dev/null +++ b/chapter30/src/test/java/com/seaofnodes/simple/progs/stream_io.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +// Deterministic short I/O and failures; ordinary descriptors still use libc. +extern ssize_t __real_read(int, void *, size_t); +extern ssize_t __real_write(int, const void *, size_t); +static int mode, calls, bad; +static int64_t count, offset; + +int32_t test_io_mode(int32_t next, int64_t start) { + mode = next; + calls = bad = 0; + count = 0; + offset = start; + return 0; +} +int64_t test_io_count(void) { return count; } +int32_t test_io_status(void) { + return bad || (mode == 5 && (errno != EAGAIN || calls != 1)); +} + +ssize_t __wrap_read(int fd, void *buffer, size_t size) { + if (fd != 700) return __real_read(fd, buffer, size); + ++calls; + if (mode == 1 && calls == 1) { errno = EINTR; return -1; } + if (mode == 2 && calls > 1) { errno = EIO; return -1; } + if (count == 24593) return 0; + size_t n = size < 137 ? size : 137; + if (n > (size_t)(24593-count)) n = (size_t)(24593-count); + for (size_t i=0; i 1) { errno = EIO; return -1; } + if (mode == 4) return 0; + if (mode == 5) { errno = EAGAIN; return -1; } + size_t n = size < 7 ? size : 7; + for (size_t i=0; i