From 2d9f74c2af9a0fb09694d3f9430e0c363efb4e7b Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Sat, 13 Jul 2019 21:08:16 -0400 Subject: [PATCH] apps/ed: refactoring --- apps/ed/cmd.asm | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ apps/ed/glue.asm | 4 +- apps/ed/main.asm | 125 +++++++++++---------------------------------------- 3 files changed, 163 insertions(+), 101 deletions(-) create mode 100644 apps/ed/cmd.asm diff --git a/apps/ed/cmd.asm b/apps/ed/cmd.asm new file mode 100644 index 0000000..0a86045 --- /dev/null +++ b/apps/ed/cmd.asm @@ -0,0 +1,135 @@ +; cmd - parse and interpret command +; +; *** Consts *** + +; address type + +.equ ABSOLUTE 0 +; handles +, - and ".". For +, easy. For -, addr is negative. For ., it's 0. +.equ RELATIVE 1 +.equ BOF 2 +.equ EOF 3 + +; *** Variables *** + +; An address is a one byte type and a two bytes line number (0-indexed) +.equ CMD_ADDR1 CMD_RAMSTART +.equ CMD_ADDR2 CMD_ADDR1+3 +.equ CMD_TYPE CMD_ADDR2+3 +.equ CMD_RAMEND CMD_TYPE+1 + +; *** Code *** + +; Parse command line that HL points to and set unit's variables +; Sets Z on success, unset on error. +cmdParse: + ld a, (hl) + cp 'q' + jr z, .quit + ld (CMD_TYPE), a + ld ix, CMD_ADDR1 + jp .readAddr +.quit: + ; Z already set + ld (CMD_TYPE), a + ret + +; Parse the string at (HL) and sets its corresponding address in IX, properly +; considering implicit values (current address when nothing is specified). +; advances HL to the char next to the last parsed char. +; It handles "+" and "-" addresses such as "+3", "-2", "+", "-". +; Sets Z on success, unset on error. Line out of bounds isn't an error. Only +; overflows. +.readAddr: + ld a, (hl) + cp '+' + jr z, .plusOrMinus + cp '-' + jr z, .plusOrMinus + call parseDecimalDigit + jr c, .notHandled + ; straight number + ld a, ABSOLUTE + ld (ix), a + call .parseDecimalM + ret nz + dec de ; from 1-based to 0-base + jr .end +.notHandled: + ; something else. Something we don't handle. Our addr is therefore "." + ld a, RELATIVE + ld (ix), a + xor a ; sets Z + ld (ix+1), a + ld (ix+2), a + ret +.plusOrMinus: + push af ; preserve that + or - + ld a, RELATIVE + ld (ix), a + inc hl ; advance cmd cursor + ld a, (hl) + ld de, 1 ; if .pmNoSuffix + call parseDecimalDigit + jr c, .pmNoSuffix + call .parseDecimalM ; --> DE +.pmNoSuffix: + pop af ; bring back that +/- + cp '-' + jr nz, .end + ; we had a "-". Negate DE + push hl + ld hl, 0 + sbc hl, de + ex de, hl + pop hl +.end: + ; We expect HL (rest of the cmdline) to be a null char, otherwise it's + ; garbage + ld a, (hl) + or a + ret nz + ; we still have to save DE in memory + ld (ix+1), e + ld (ix+2), d + ret + +; call parseDecimal and set HL to the character following the last digit +.parseDecimalM: + push bc + push ix + push hl +.loop: + inc hl + ld a, (hl) + call parseDecimalDigit + jr nc, .loop + ; We're at the first non-digit char. Let's save it because we're going + ; to temporarily replace it with a null. + ld b, a + xor a + ld (hl), a + ; Now, let's go back to the beginning of the string and parse it. + ; but before we do this, let's save the end of string in DE + ex de, hl + pop hl + call parseDecimal + ; Z is set properly at this point. nothing touches Z below. + ld a, b + ld (de), a + ex de, hl ; put end of string back from DE to HL + ; Put addr in its final register, DE + push ix \ pop de + pop ix + pop bc + ret + +; Make (IX) point to addr 1 +cmdAddr1: + ld ix, CMD_ADDR1 + ret + +; Set A to CMD_TYPE +cmdType: + ld a, (CMD_TYPE) + ret diff --git a/apps/ed/glue.asm b/apps/ed/glue.asm index 3243bf9..6eb3dd2 100644 --- a/apps/ed/glue.asm +++ b/apps/ed/glue.asm @@ -9,6 +9,8 @@ #include "ed/io.asm" .equ BUF_RAMSTART IO_RAMEND #include "ed/buf.asm" -.equ ED_RAMSTART BUF_RAMEND +.equ CMD_RAMSTART BUF_RAMEND +#include "ed/cmd.asm" +.equ ED_RAMSTART CMD_RAMEND #include "ed/main.asm" diff --git a/apps/ed/main.asm b/apps/ed/main.asm index a081e40..62d92f5 100644 --- a/apps/ed/main.asm +++ b/apps/ed/main.asm @@ -86,118 +86,43 @@ edMain: ; We're done. Process line. call printcrlf call stdioGetLine - call .processLine - ret z - jr .mainLoop - -; Sets Z if we need to quit -.processLine: - ld a, (hl) + call cmdParse + jr nz, .error + call cmdType cp 'q' ret z - call edReadAddr - jr z, .processNumber - jr .processError -.processNumber: - ; number is in DE - ; We expect HL (rest of the cmdline) to be a null char, otherwise it's - ; garbage - ld a, (hl) - or a - jr nz, .processError - ex de, hl + jr .doPrint + +.doPrint: + call cmdAddr1 + call edResolveAddr ld (ED_CURLINE), hl call bufGetLine - jr nz, .processError + jr nz, .error call printstr call printcrlf - ; continue to end -.processEnd: - call printcrlf - jp unsetZ -.processError: + jr .mainLoop +.error: ld a, '?' call stdioPutC call printcrlf - jp unsetZ + jr .mainLoop -; Parse the string at (HL) and sets its corresponding address in DE, properly -; considering implicit values (current address when nothing is specified). -; advances HL to the char next to the last parsed char. -; It handles "+" and "-" addresses such as "+3", "-2", "+", "-". -; Sets Z on success, unset on error. Line out of bounds isn't an error. Only -; overflows. -edReadAddr: - ld a, (hl) - cp '+' - jr z, .plusOrMinus - cp '-' - jr z, .plusOrMinus - call parseDecimalDigit - jr c, .notHandled - ; straight number - call .parseDecimalM ; Z has proper value - dec de ; from 1-based to 0-base. 16bit doesn't affect flags. + +; Transform an address "cmd" in IX into an absolute address in HL. +edResolveAddr: + ld a, (ix) + cp RELATIVE + jr z, .relative + ; absolute + ld l, (ix+1) + ld a, l + ld h, (ix+2) ret -.notHandled: - ; something else. Something we don't handle. Our addr is therefore - ; (ED_CURLINE). - push hl +.relative: ld hl, (ED_CURLINE) - ex de, hl - pop hl - cp a ; ensure Z - ret -.plusOrMinus: - push af ; preserve that + or - - inc hl ; advance cmd cursor - ld a, (hl) - ld de, 1 ; if .pmNoSuffix - call parseDecimalDigit - jr c, .pmNoSuffix - call .parseDecimalM ; --> DE -.pmNoSuffix: - pop af ; bring back that +/- - push hl - ld hl, (ED_CURLINE) - cp '-' - jr z, .pmIsMinus + ld e, (ix+1) + ld d, (ix+2) add hl, de - jr .pmEnd -.pmIsMinus: - sbc hl, de -.pmEnd: - ex de, hl - pop hl - cp a ; ensure Z ret -; call parseDecimal and set HL to the character following the last digit -.parseDecimalM: - push bc - push ix - push hl -.loop: - inc hl - ld a, (hl) - call parseDecimalDigit - jr nc, .loop - ; We're at the first non-digit char. Let's save it because we're going - ; to temporarily replace it with a null. - ld b, a - xor a - ld (hl), a - ; Now, let's go back to the beginning of the string and parse it. - ; but before we do this, let's save the end of string in DE - ex de, hl - pop hl - call parseDecimal - ; Z is set properly at this point. nothing touches Z below. - ld a, b - ld (de), a - ex de, hl ; put end of string back from DE to HL - ; Put addr in its final register, DE - push ix \ pop de - pop ix - pop bc - ret