aboutsummaryrefslogtreecommitdiffstats
path: root/c
diff options
context:
space:
mode:
Diffstat (limited to 'c')
-rw-r--r--c/args.c12
-rwxr-xr-xc/build.sh3
-rw-r--r--c/gbos.h5
-rw-r--r--c/head.c16
-rw-r--r--c/libc.c34
-rw-r--r--c/pid.c7
-rw-r--r--c/wc.c20
7 files changed, 89 insertions, 8 deletions
diff --git a/c/args.c b/c/args.c
new file mode 100644
index 0000000..c6f4db3
--- /dev/null
+++ b/c/args.c
@@ -0,0 +1,12 @@
+#include "gbos.h"
+/* args: an argc/argv demo. Splits its argument string into argv[] and prints
+ argc plus each argument. Try: `args one two three` */
+void main(void) {
+ char *argv[8];
+ unsigned char argc = argv_parse(argv, 8);
+ unsigned char i;
+ puts("argc="); putu(argc); nl();
+ for (i = 0; i < argc; i++) {
+ puts("argv["); putu(i); puts("]="); puts(argv[i]); nl();
+ }
+}
diff --git a/c/build.sh b/c/build.sh
index 6a2deab..8034d87 100755
--- a/c/build.sh
+++ b/c/build.sh
@@ -8,12 +8,13 @@ LIBDIR=/usr/share/sdcc/lib/sm83
mkdir -p "$B"
sdasgb -o "$B/crt0.rel" c/crt0.s
sdasgb -o "$B/libc.rel" c/libc.s
+sdcc -msm83 -c -Ic c/libc.c -o "$B/libc_c.rel"
sdcc -msm83 -c -Ic "$SRC" -o "$B/prog.rel"
# link: crt0 first (=> _start at 0x4000), then libc, program, and sm83 lib
sdldgb -n -m -w -j -i "$B/prog.ihx" \
-b _CODE=0x4000 -b _DATA=0xa000 \
-k "$LIBDIR" -l sm83 \
- "$B/crt0.rel" "$B/libc.rel" "$B/prog.rel"
+ "$B/crt0.rel" "$B/libc.rel" "$B/libc_c.rel" "$B/prog.rel"
makebin -Z -p "$B/prog.ihx" "$B/prog.bin"
dd if="$B/prog.bin" of="$OUT" bs=1024 skip=16 count=16 2>/dev/null
echo "wrote $OUT ($(wc -c < "$OUT") bytes); entry:"
diff --git a/c/gbos.h b/c/gbos.h
index 3a10e06..cf94128 100644
--- a/c/gbos.h
+++ b/c/gbos.h
@@ -12,4 +12,9 @@ char *getargs(void); /* this program's argument string */
char readc(void); /* one input byte, EOF at end */
void sexit(unsigned char code);
unsigned char getpid(void);
+
+/* helpers (c/libc.c) */
+void putu(unsigned int n); /* print decimal */
+unsigned char atou(const char *s); /* parse decimal */
+unsigned char argv_parse(char **argv, unsigned char maxv); /* argc/argv */
#endif
diff --git a/c/head.c b/c/head.c
new file mode 100644
index 0000000..9363b1c
--- /dev/null
+++ b/c/head.c
@@ -0,0 +1,16 @@
+#include "gbos.h"
+/* head [n]: print the first n lines of stdin (default 10). Drains the rest to
+ EOF so the shell sees a clean end of input. */
+void main(void) {
+ char *a = getargs();
+ unsigned char n = 10;
+ unsigned char lines = 0;
+ char c;
+ if (*a) n = atou(a);
+ for (;;) {
+ c = readc();
+ if (c == EOF) break;
+ if (lines < n) putc(c);
+ if (c == '\n') lines++;
+ }
+}
diff --git a/c/libc.c b/c/libc.c
new file mode 100644
index 0000000..3b9883b
--- /dev/null
+++ b/c/libc.c
@@ -0,0 +1,34 @@
+/* gbos libc C helpers (compiled once, linked into every program). */
+#include "gbos.h"
+
+/* print an unsigned int in decimal */
+void putu(unsigned int n) {
+ char buf[5];
+ unsigned char i = 0;
+ if (n == 0) { putc('0'); return; }
+ while (n) { buf[i++] = '0' + (n % 10); n = n / 10; }
+ while (i) putc(buf[--i]);
+}
+
+/* parse a decimal number (stops at the first non-digit) */
+unsigned char atou(const char *s) {
+ unsigned char n = 0;
+ while (*s >= '0' && *s <= '9') { n = n * 10 + (*s - '0'); s++; }
+ return n;
+}
+
+/* tokenize the argument string in place into argv[]; returns argc.
+ (replaces the spaces in the arg string with NULs) */
+unsigned char argv_parse(char **argv, unsigned char maxv) {
+ char *p = getargs();
+ unsigned char argc = 0;
+ for (;;) {
+ while (*p == ' ') p++;
+ if (*p == 0) break;
+ if (argc < maxv) argv[argc] = p;
+ argc++;
+ while (*p != 0 && *p != ' ') p++;
+ if (*p == ' ') *p++ = 0;
+ }
+ return argc;
+}
diff --git a/c/pid.c b/c/pid.c
index a282a89..9e4e792 100644
--- a/c/pid.c
+++ b/c/pid.c
@@ -1,9 +1,2 @@
#include "gbos.h"
-/* print an unsigned byte as decimal (no runtime division: subtract-based) */
-static void putu(unsigned char n) {
- char buf[3]; unsigned char i = 0;
- if (n == 0) { putc('0'); return; }
- while (n) { buf[i++] = '0' + (n % 10); n = n / 10; }
- while (i) putc(buf[--i]);
-}
void main(void) { putu(getpid()); nl(); }
diff --git a/c/wc.c b/c/wc.c
new file mode 100644
index 0000000..a957542
--- /dev/null
+++ b/c/wc.c
@@ -0,0 +1,20 @@
+#include "gbos.h"
+/* wc: count lines, words, chars of stdin (like `wc`). */
+void main(void) {
+ unsigned int lines = 0, words = 0, chars = 0;
+ unsigned char inword = 0;
+ char c;
+ for (;;) {
+ c = readc();
+ if (c == EOF) break;
+ chars++;
+ if (c == '\n') lines++;
+ if (c == ' ' || c == '\n' || c == '\r' || c == '\t') {
+ inword = 0;
+ } else if (!inword) {
+ inword = 1;
+ words++;
+ }
+ }
+ putu(lines); putc(' '); putu(words); putc(' '); putu(chars); nl();
+}