aboutsummaryrefslogtreecommitdiffstats
path: root/usr/strings.c
diff options
context:
space:
mode:
authoruser <user@clank>2026-09-24 23:08:46 +0200
committeruser <user@clank>2026-09-24 23:08:46 +0200
commit4bfe20f88b93645f9a277c9903620d75f0ddc179 (patch)
treeba8af4184f10645fecc59adc9b0b0454658ad278 /usr/strings.c
parentterm: ESC[2J, so clear(1) can actually clear (diff)
downloadgbos-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.c60
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);
+}