aboutsummaryrefslogtreecommitdiffstats
path: root/c
diff options
context:
space:
mode:
Diffstat (limited to 'c')
-rw-r--r--c/gbos.h4
-rw-r--r--c/libc.s25
-rw-r--r--c/ls.c5
-rw-r--r--c/mkdir.c8
-rw-r--r--c/sh.c38
5 files changed, 77 insertions, 3 deletions
diff --git a/c/gbos.h b/c/gbos.h
index 6badd16..c93414f 100644
--- a/c/gbos.h
+++ b/c/gbos.h
@@ -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
diff --git a/c/libc.s b/c/libc.s
index c245bbd..d499521 100644
--- a/c/libc.s
+++ b/c/libc.s
@@ -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$
diff --git a/c/ls.c b/c/ls.c
index 5d5ce43..0e2e01f 100644
--- a/c/ls.c
+++ b/c/ls.c
@@ -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(); }
+}
diff --git a/c/sh.c b/c/sh.c
index 8aa619e..b1bf630 100644
--- a/c/sh.c
+++ b/c/sh.c
@@ -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;