diff options
Diffstat (limited to 'c')
| -rw-r--r-- | c/gbos.h | 4 | ||||
| -rw-r--r-- | c/libc.s | 25 | ||||
| -rw-r--r-- | c/ls.c | 5 | ||||
| -rw-r--r-- | c/mkdir.c | 8 | ||||
| -rw-r--r-- | c/sh.c | 38 |
5 files changed, 77 insertions, 3 deletions
@@ -27,6 +27,10 @@ int fgetc(unsigned char fd); /* a byte, or -1 at EOF */ void fputc(unsigned char fd, char ch); unsigned char flist(unsigned char slot, char *namebuf); /* 1 if slot used */ void fremove(const char *name); +unsigned char mkdir(const char *path); +unsigned char chdir(const char *path); +unsigned char opendir(const char *path); +void poweroff(void); /* clean emulator shutdown (saves) */ #define O_READ 0 #define O_WRITE 1 #define NOFD 0xFF @@ -221,3 +221,28 @@ _bpeek2: rst #0x30 ret + + .globl _mkdir, _chdir + ;; unsigned char mkdir(const char *path /*DE*/) -> A (0 ok / $FF) +_mkdir: + ld c, #25 ; SYS_MKDIR + rst #0x30 + ret + ;; unsigned char chdir(const char *path /*DE*/) -> A (0 ok / $FF) +_chdir: + ld c, #26 ; SYS_CHDIR + rst #0x30 + ret + + .globl _opendir + ;; unsigned char opendir(const char *path /*DE*/) -> A (0 ok / $FF) +_opendir: + ld c, #27 ; SYS_OPENDIR + rst #0x30 + ret + + .globl _poweroff + ;; void poweroff(void) - execute the emulator's clean-exit opcode ($ED) +_poweroff: + .db 0xED +1$: jr 1$ @@ -1,7 +1,10 @@ #include "gbos.h" -/* ls: list files in the filesystem. */ +/* ls [dir]: list a directory (default: current). */ void main(void) { + char *argv[4]; char name[16]; + unsigned char argc = argv_parse(argv, 4); unsigned char i; + if (opendir(argc > 0 ? argv[0] : ".")) { puts("ls: no such directory"); nl(); return; } for (i = 0; flist(i, name); i++) { name[15] = 0; puts(name); nl(); } } diff --git a/c/mkdir.c b/c/mkdir.c new file mode 100644 index 0000000..c907518 --- /dev/null +++ b/c/mkdir.c @@ -0,0 +1,8 @@ +#include "gbos.h" +/* mkdir <path>: create a directory. */ +void main(void) { + char *argv[4]; + unsigned char argc = argv_parse(argv, 4); + if (argc < 1) { puts("usage: mkdir <name>"); nl(); return; } + if (mkdir(argv[0])) { puts("mkdir: failed"); nl(); } +} @@ -18,6 +18,30 @@ static unsigned char tokenize(char *s, char **tok, unsigned char max) { } static unsigned char isop(char *t, char c) { return t[0] == c && t[1] == 0; } +static unsigned char iscmd(char *t, char a, char b) { + return t[0] == a && t[1] == b && t[2] == 0; +} + +/* keep the prompt's path string roughly in sync with chdir(). */ +static void set_cwd(char *cwd, char *arg) { + char *d, *s, *last; + if (arg[0] == '/') { /* absolute */ + d = cwd; s = arg; + while (*s) *d++ = *s++; + *d = 0; + } else if (arg[0] == '.' && arg[1] == '.' && arg[2] == 0) { + last = cwd; d = cwd; + while (*d) { if (*d == '/') last = d; d++; } + if (last == cwd) { cwd[0] = '/'; cwd[1] = 0; } else *last = 0; + } else if (arg[0] == '.' && arg[1] == 0) { + /* stay */ + } else { /* relative: append */ + d = cwd; while (*d) d++; + if (!(cwd[0] == '/' && cwd[1] == 0)) *d++ = '/'; + s = arg; while (*s) *d++ = *s++; + *d = 0; + } +} /* build the child command line "name\0arg1 arg2\0" at 0xA000 */ static void set_cmdline(char **tok, unsigned char start, unsigned char end) { @@ -74,22 +98,32 @@ done: void main(void) { char line[80]; char *tok[16]; + char cwd[40]; + cwd[0] = '/'; cwd[1] = 0; for (;;) { unsigned char nt, i, pipepos, c, bg; /* reap finished background jobs */ { unsigned char p; while ((p = reap())) { putc('['); putu(p); puts(" done]"); nl(); } } - puts("$ "); + puts(cwd); puts("$ "); /* read a line (echoing), stop at newline; exit on EOF */ i = 0; for (;;) { c = readc(); - if (c == EOF) return; + if (c == EOF) poweroff(); if (c == '\r' || c == '\n') { nl(); break; } if (i < 79) { line[i++] = c; putc(c); } } line[i] = 0; nt = tokenize(line, tok, 16); if (nt == 0) continue; + if (iscmd(tok[0], 'c', 'd')) { /* cd builtin */ + char *arg = (nt >= 2) ? tok[1] : "/"; + if (chdir(arg) == 0) set_cwd(cwd, arg); + else { puts("cd: no such directory"); nl(); } + continue; + } + if ((tok[0][0] == 'e' && tok[0][1] == 'x') || + (tok[0][0] == 'q' && tok[0][1] == 'u')) poweroff(); bg = 0; if (isop(tok[nt - 1], '&')) { bg = 1; nt--; if (nt == 0) continue; } pipepos = 0; |
