diff options
| author | user <user@clank> | 2026-09-24 23:08:46 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-09-24 23:08:46 +0200 |
| commit | 4bfe20f88b93645f9a277c9903620d75f0ddc179 (patch) | |
| tree | ba8af4184f10645fecc59adc9b0b0454658ad278 /usr/strings.c | |
| parent | term: ESC[2J, so clear(1) can actually clear (diff) | |
| download | gbos-4bfe20f88b93645f9a277c9903620d75f0ddc179.tar.gz gbos-4bfe20f88b93645f9a277c9903620d75f0ddc179.tar.xz gbos-4bfe20f88b93645f9a277c9903620d75f0ddc179.zip | |
usr: sort, cmp, strings, du, time
- sort [-r] [-n]: everything in RAM, which bounds it - a task has 8 KiB and a
file caps at 3 KiB, so 96 lines of 2400 bytes with room for the stack.
Insertion sort over an index; at that size the simple thing is fast and
costs far less ROM. `uniq -c f | sort -n -r` finally works.
NB the key needs a scratch SLOT of its own: gt() compares table entries, so
reusing slot i as scratch overwrites the entries being shifted into it.
- cmp: reports the first differing byte, silent when the files match. There
was no way to check a copy on the machine - you had to haul both to a host.
- strings [-n N]: pairs with xxd now that /bin/<prog> is readable. It finds
"gbos sm83 (Game Boy Color)" inside /bin/uname.
- du [dir]: 256-byte blocks, the unit df and the filesystem use. Bytes
overflow - /bin alone is 52 x 16 KiB, which wrapped a 16-bit counter and
printed 32768. Recurses by re-opendir'ing, since the kernel keeps only one
"directory being listed" cursor.
- time CMD: 1/64 s resolution from the tick counter. It rebuilds the child's
command line at $A000 - which is its own argument area, so everything is
copied to the stack first.
Diffstat (limited to 'usr/strings.c')
| -rw-r--r-- | usr/strings.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/usr/strings.c b/usr/strings.c new file mode 100644 index 0000000..b3db75d --- /dev/null +++ b/usr/strings.c @@ -0,0 +1,60 @@ +#include "gbos.h" +/* strings [-n N] [file]: print runs of N or more printable characters + * (default 4). Pairs with xxd now that /bin/<prog> is readable - it is how + * you find the text baked into a program image. */ + +#define MAXRUN 64 + +void main(void) { + char *argv[8]; + char run[MAXRUN]; + unsigned char argc = argv_parse(argv, 8); + char *nv = optval(argv, argc, 'n'); + unsigned char min = nv ? atou(nv) : 4; + unsigned char len = 0, fd = NOFD, i; + char *fname = 0; + int ch; + + if (min == 0) min = 4; + if (min > MAXRUN) min = MAXRUN; + for (i = 0; i < argc; i++) { + if (argv[i][0] == '-') continue; + if (nv == argv[i]) continue; + fname = argv[i]; + break; + } + if (fname) { + fd = open(fname, O_READ); + if (fd == EISDIR) { + puts("strings: is a directory"); + nl(); + sexit(2); + } + if (fd == NOFD) { + puts("strings: no such file"); + nl(); + sexit(2); + } + } + for (;;) { + if (fd == NOFD) { + char c = readc(); + ch = (c == EOF) ? -1 : c; + } else ch = fgetc(fd); + if (ch >= 32 && ch < 127) { + if (len < MAXRUN) run[len++] = (char)ch; + continue; + } + if (len >= min) { + writes(run, len); + nl(); + } /* run ended: keep it? */ + len = 0; + if (ch < 0) break; + } + if (len >= min) { + writes(run, len); + nl(); + } + if (fd != NOFD) close(fd); +} |
