From 4335d248d18987a050d8ac26965c90718eef7562 Mon Sep 17 00:00:00 2001 From: user Date: Thu, 16 Jul 2026 07:21:40 +0200 Subject: libc + CLI tools: a small C userland - libc: add putc, puts, strlen, getargs (args string), EOF (=4) for readc. - args: shell splits the command line at the first space ("cmd\0args\0" at $A000, inherited by the child via fork); getargs() returns the arg string. - shell: exit on Ctrl-D/EOF; $ prompt over a clean read loop. - tools (c/): echo (argv), cat (stdin->stdout to EOF), uname, pid (decimal print), true, false. Each built to a ROM-bank blob and registered. - Makefile: CBLOBS list builds all C programs. - README: document libc + the tool set. --- src/programs.asm | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/programs.asm b/src/programs.asm index eabe56f..322c7fc 100644 --- a/src/programs.asm +++ b/src/programs.asm @@ -52,6 +52,24 @@ ProgHello: SECTION "prog_chello", ROMX[$4000], BANK[5] ProgChello: INCBIN "c/chello.bin" +SECTION "prog_echo", ROMX[$4000], BANK[6] +ProgEcho: + INCBIN "c/echo.bin" +SECTION "prog_true", ROMX[$4000], BANK[7] +ProgTrue: + INCBIN "c/true.bin" +SECTION "prog_false", ROMX[$4000], BANK[8] +ProgFalse: + INCBIN "c/false.bin" +SECTION "prog_uname", ROMX[$4000], BANK[9] +ProgUname: + INCBIN "c/uname.bin" +SECTION "prog_pid", ROMX[$4000], BANK[10] +ProgPid: + INCBIN "c/pid.bin" +SECTION "prog_cat", ROMX[$4000], BANK[11] +ProgCat: + INCBIN "c/cat.bin" ; ----------------------------------------------------------------------------- ; PROG_SH (bank 3) - a tiny shell. @@ -72,6 +90,8 @@ ProgSh: ld c, SYS_READ rst $30 ; A = input byte pop hl + cp $04 + jr z, .eof ; Ctrl-D / EOF: exit the shell cp $0D jr z, .eol cp $0A @@ -85,6 +105,11 @@ ProgSh: cp LOW(SH_LINEBUF) + SH_MAXLINE - 1 jr c, .rd ; keep reading unless the buffer is full +.eof + ld b, 0 + ld c, SYS_EXIT ; exit init/shell -> system idle + rst $30 + .eol ld [hl], 0 ; NUL-terminate ld de, .crlf @@ -93,8 +118,24 @@ ProgSh: rst $30 ld a, [SH_LINEBUF] or a - jr z, .prompt ; empty line + jp z, .prompt ; empty line + + ; split off the first word: replace the first space with a NUL so command + ; matching sees just the command, and the args survive at SH_LINEBUF+n + ; (inherited by the child through fork, read back via main(char *args)). + ld hl, SH_LINEBUF +.split + ld a, [hl] + or a + jr z, .lookup ; no space -> no args + cp $20 + jr z, .cut + inc hl + jr .split +.cut + ld [hl], 0 ; isolate the command word +.lookup ; look the command up in the table ld de, .cmdtab .scan @@ -122,7 +163,7 @@ ProgSh: jr z, .exec ld c, SYS_WAIT ; parent: reap the command rst $30 - jr .prompt + jp .prompt .exec ld a, [SH_PROGID] ld b, a @@ -134,7 +175,7 @@ ProgSh: ld b, 3 ld c, SYS_WRITE rst $30 - jr .prompt + jp .prompt .ps1 db "$ " @@ -149,6 +190,18 @@ ProgSh: db PROG_HELLO db "chello", 0 db PROG_CHELLO + db "echo", 0 + db PROG_ECHO + db "true", 0 + db PROG_TRUE + db "false", 0 + db PROG_FALSE + db "uname", 0 + db PROG_UNAME + db "pid", 0 + db PROG_PID + db "cat", 0 + db PROG_CAT db 0 ; terminator ; ----------------------------------------------------------------------------- @@ -191,3 +244,15 @@ ProgramTable:: dw ProgHello db LOW(BANK(ProgChello)), HIGH(BANK(ProgChello)) dw ProgChello + db LOW(BANK(ProgEcho)), HIGH(BANK(ProgEcho)) + dw ProgEcho + db LOW(BANK(ProgTrue)), HIGH(BANK(ProgTrue)) + dw ProgTrue + db LOW(BANK(ProgFalse)), HIGH(BANK(ProgFalse)) + dw ProgFalse + db LOW(BANK(ProgUname)), HIGH(BANK(ProgUname)) + dw ProgUname + db LOW(BANK(ProgPid)), HIGH(BANK(ProgPid)) + dw ProgPid + db LOW(BANK(ProgCat)), HIGH(BANK(ProgCat)) + dw ProgCat -- cgit v1.3.1-sl0p