diff options
Diffstat (limited to 'c')
| -rw-r--r-- | c/args.c | 12 | ||||
| -rwxr-xr-x | c/build.sh | 3 | ||||
| -rw-r--r-- | c/gbos.h | 5 | ||||
| -rw-r--r-- | c/head.c | 16 | ||||
| -rw-r--r-- | c/libc.c | 34 | ||||
| -rw-r--r-- | c/pid.c | 7 | ||||
| -rw-r--r-- | c/wc.c | 20 |
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(); + } +} @@ -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:" @@ -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; +} @@ -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(); } @@ -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(); +} |
