Mercurial > hg > index.cgi
changeset 40:68253ccbb9dc
Immediate mode line insertion, removal, and replacement
This implements a first pass untested version of handling program line
insertion and deletion in immediate mode. This comes with auxilliary
routines for parsing line numbers and fixing up the next line pointers.
author | William Astle <lost@l-w.ca> |
---|---|
date | Wed, 23 Nov 2022 21:34:21 -0700 |
parents | e956d8b6e806 |
children | 090db8c5d509 |
files | src/lwbasic.s |
diffstat | 1 files changed, 106 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lwbasic.s Mon Nov 21 23:18:40 2022 -0700 +++ b/src/lwbasic.s Wed Nov 23 21:34:21 2022 -0700 @@ -194,14 +194,14 @@ ; Start of memory which has the direct page and other data. org 0 dpstart equ * ; start of direct page +zero rmb 2 ; constant zero word used for faster zeroing of 16 bit registers +binval rmb 2 ; arbitary binary value, usually a line number or integer memtop rmb 2 ; absolute top of memory in 64K memory map memsize rmb 2 ; top of memory not reserved freetop rmb 2 ; top of free memory (bottom of string space) stringtab rmb 2 ; bottom of used string space progtext rmb 2 ; pointer to start of program text -vartabint rmb 2 ; pointer to start of integer scalars -vartabfloat rmb 2 ; pointer to start of floating point scalars -vartabstring rmb 2 ; pointer to start of string scalars +vartab rmb 2 ; pointer to start of integer scalars objecttab rmb 2 ; pointer to start of arrays and other variable sized objects freestart rmb 2 ; pointer to start of unallocated memory readlinenoecho rmb 1 ; if nonzero, the readline routine won't echo its input @@ -461,9 +461,7 @@ stx progtext ; put the start of the program there clr ,x+ ; put a NULL pointer to mark end of program clr ,x+ - stx vartabint ; put start of integer variables at end of program - stx vartabfloat ; put start of floating point variables after that - stx vartabstring ; put start of string variables after that + stx vartab ; put start of integer variables at end of program stx objecttab ; also put the start of large objects there stx freestart ; mark the start of free memory lda #keyb_caps ; enable caps lock but disable all other shift states @@ -1056,8 +1054,108 @@ jsr tokenize ; tokenize the line at inputptr, return with result at tokebuff jsr interpretline ; go interpret the tokenized line bra immediate ; go handle another line -immediate1 ; handle line insert/delete/modify - bra immediate0 +immediate1 bsr parse_lineno ; parse the line number + bsr prog_findline ; go see if the line is in the program + bne immediate3 ; brif not - no need to delete it + ldu ,x ; get next line pointer which is where we start the copy from + leay ,x ; use temp pointer for copying +immediate2 lda ,u+ ; get source byte + sta ,y+ ; stash it + cmpu vartab ; did we reach the end of the program text? + blo immediate2 ; brif not + sty vartab ; save new end of program +immediate3 jsr curchar ; skip any spaces after line number + tsta ; is it the end of input (don't test for colon) + beq immediate6 ; brif so - we don't need to insert a line + pshs x ; save program insert location and line number + ldx inputptr ; point to line text + jsr tokenize ; tokenize line, get length to D + leay ,x ; save tokenized line pointer + addd #4 ; account for next line pointer and line number + ldx vartab ; get start of copy location + leau d,x ; set destination copy location D bytes further up + stu vartab ; save new end of program +immediate4 lda ,-x ; get byte from program + sta ,-u ; stash it above the empty space + cmpx ,s ; did we reach the insertion point? + bne immediate4 ; brif not - keep going + leas 2,s ; clear insertion location + stu ,x++ ; set next line pointer to not null + ldd binval ; set the line number for the program + std ,x++ +immediate5 lda ,y+ ; get byte from tokenized line + sta ,x+ ; stash it in the program + bne immediate5 ; brif not at end of tokenized line (see note for fixlineptrs) +immediate6 bsr prog_fixlineptrs ; fix up line pointers (all of them) + ldx vartab ; clear out variables + stx objecttab + stx freestart + bra immediate0 ; go handle more input +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Fix up next line pointers. Enter at prog_fixlineptrs to do the entire program. Enter at prog_fixlineptrsx to start +; at the line pointered to by X, which MUST NOT point to the end of the program. +; +; Works by simply scanning for a NUL in the program text after a line header (pointer to next line and line number) +; and uses that as the new next line pointer. A NULL next line pointer flags the end of the program. +; +; Observation: if the program text format is changed such that it can include NULs embedded within a line, this routine +; will need to be updated to grok that. +prog_fixlineptrs + ldx progtext ; point to start of program +prog_fixlineptrsx + ldu ,x ; are we at the end of the program? + beq prog_findline2 ; brif not (borrow RTS from findline) + leau 4,x ; point to line text (past pointer and line number) +prog_fixlineptrs1 + lda ,u+ ; are we at the end of this line? + bne prog_fixlineptrs1 ; brif not + stu ,x ; set the next pointer for the previous line + leax ,u ; move to the next line + bra prog_fixlineptrsx ; go handle the next line +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Find a line in the program. Returns with C set and Z clear if no match and C clear and Z set if a match is found. X +; will point to either the exact matched line *or* the line that would be immediately after the desired line number if +; the line had been present, which could be the end of the program. D and U are clobbered. Enter at prog_findlinex to +; start searching at the line pointed to by X. Enter at prog_findline to start at the beginning of the program. Enter +; with the desired line number in binval. +prog_findline ldx progtext ; point to start of program +prog_findlinex ldu binval ; get line number to search for +prog_findline0 ldd ,x ; end of program? + beq prog_findline1 ; brif not + cmpu 2,x ; does line number match? Z set if so, clear if not; C set not found + bls prog_findline2 + ldx ,x ; move to next line + bra prog_findline0 ; see if we found the line yet +prog_findline1 coma ; set carry for not found; also clears Z because D is zero from above +prog_findline2 rts +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Parse a line number and return it in binval; raise syntax error if the line number overflows 16 bits unsigned. +; Preserves; registers except D. This will accept the entire 16 bit unsigned number range which is why there is +; a BCS after every shift or add. Enter with the first character in A with C set for digits and clear otherwise. +parse_lineno ldd zero ; clear out accumlator but preserve carry flag + std binval + bcc parse_lineno1 ; brif first character wasn't a digit - default to zero +parse_lineno0 suba #0x30 ; adjust to binary digit + pshs a ; save digit so we can add it later + ldd binval ; get accumulated number + lslb ; multiply accumulator by 10 + rola ; times 2 + bcs SNERROR ; brif overflow + lslb + rola ; times 4 + bcs SNERROR ; brif overflow + addd binval ; times 5 (add orignal value to times 4) + bcs SNERROR ; brif overflow + lslb + rola ; times 10 + bcs SNERROR ; brif overflow + addb ,s+ ; add in accumulated digit + adca #0 + bcs SNERROR ; brif overflow + std binval ; save accumulated number + jsr nextcharraw ; get next input character; DO NOT skip spaces + bcs parse_lineno0 ; brif it's also a digit +parse_lineno1 rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Main interpretation loop ;