summaryrefslogtreecommitdiff
path: root/chapter30/src/test/java/com/seaofnodes/simple/progs
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-11-08 14:10:02 -0800
committerCliff Click <cliffc@acm.org>2026-11-08 14:10:02 -0800
commit06fb5aceeb65a75b1cd643debd667c52fdcafcb9 (patch)
treec99813eaf27d98f840245302c4d6e923c964307e /chapter30/src/test/java/com/seaofnodes/simple/progs
parent6560a92433a38825fd1d44d9c66ffba9f26990ff (diff)
downloadSimple-ch30.tar.gz
Simple-ch30.zip
Better error messagesch30
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.
Diffstat (limited to 'chapter30/src/test/java/com/seaofnodes/simple/progs')
-rw-r--r--chapter30/src/test/java/com/seaofnodes/simple/progs/extern_data.c7
-rw-r--r--chapter30/src/test/java/com/seaofnodes/simple/progs/int32.c26
-rw-r--r--chapter30/src/test/java/com/seaofnodes/simple/progs/runtime_args.c35
-rw-r--r--chapter30/src/test/java/com/seaofnodes/simple/progs/sort.c4
-rw-r--r--chapter30/src/test/java/com/seaofnodes/simple/progs/stream_io.c49
-rw-r--r--chapter30/src/test/java/com/seaofnodes/simple/progs/stringHash.c2
6 files changed, 120 insertions, 3 deletions
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 <stdint.h>
+#include <stdio.h>
+
+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 <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+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 <errno.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <unistd.h>
+
+// 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<n; ++i) ((unsigned char *)buffer)[i] = (count+i)%251;
+ count += n;
+ return (ssize_t)n;
+}
+
+ssize_t __wrap_write(int fd, const void *buffer, size_t size) {
+ if (fd != 701) return __real_write(fd, buffer, size);
+ ++calls;
+ if (mode == 1 && calls == 1) { errno = EINTR; return -1; }
+ if (mode == 3 && calls > 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<n; ++i)
+ if (((const unsigned char *)buffer)[i] != (offset+count+i)%251) bad = 1;
+ count += n;
+ return (ssize_t)n;
+}
diff --git a/chapter30/src/test/java/com/seaofnodes/simple/progs/stringHash.c b/chapter30/src/test/java/com/seaofnodes/simple/progs/stringHash.c
index 2c6d0fa9..6578c852 100644
--- a/chapter30/src/test/java/com/seaofnodes/simple/progs/stringHash.c
+++ b/chapter30/src/test/java/com/seaofnodes/simple/progs/stringHash.c
@@ -7,7 +7,7 @@ typedef struct ArrayU8 {
} ArrayU8;
typedef struct String {
ArrayU8 * cs;
- long long _hashCode;
+ int _hashCode;
} String;