forked from MirrorRepos/RomWBW
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3274 lines
47 KiB
3274 lines
47 KiB
TITLE BBC BASIC (C) R.T.RUSSELL 1981-2024
|
|
NAME ('EXEC')
|
|
;
|
|
;BBC BASIC INTERPRETER - Z80 VERSION
|
|
;STATEMENT EXECUTION MODULE - "EXEC"
|
|
;(C) COPYRIGHT R.T.RUSSELL 1981-2024
|
|
;
|
|
;THE NAME BBC BASIC IS USED WITH THE PERMISSION
|
|
;OF THE BRITISH BROADCASTING CORPORATION AND IS
|
|
;NOT TRANSFERRABLE TO A FORKED OR DERIVED WORK.
|
|
;
|
|
;VERSION 2.1, 22-01-1984
|
|
;VERSION 3.1, 11-06-1987
|
|
;VERSION 5.0, 19-05-2024
|
|
;
|
|
GLOBAL XEQ
|
|
GLOBAL RUN0
|
|
GLOBAL CHAIN0
|
|
GLOBAL CHECK
|
|
GLOBAL MUL16
|
|
GLOBAL X14OR5
|
|
GLOBAL TERMQ
|
|
GLOBAL STOREN
|
|
GLOBAL STORE4
|
|
GLOBAL STORE5
|
|
GLOBAL STACCS
|
|
GLOBAL SPACES
|
|
GLOBAL FN
|
|
GLOBAL USR
|
|
GLOBAL ESCAPE
|
|
GLOBAL SYNTAX
|
|
GLOBAL CHANEL
|
|
GLOBAL CHNL
|
|
GLOBAL VAR
|
|
GLOBAL TABIT
|
|
GLOBAL MODIFY
|
|
GLOBAL MODIFS
|
|
;
|
|
EXTRN ASSEM
|
|
EXTRN ERROR
|
|
EXTRN REPORT
|
|
EXTRN WARM
|
|
EXTRN CLOOP
|
|
EXTRN SAYLN
|
|
EXTRN LOAD0
|
|
EXTRN CRLF
|
|
EXTRN PBCDL
|
|
EXTRN TELL
|
|
EXTRN FINDL
|
|
EXTRN SETLIN
|
|
EXTRN CLEAR
|
|
EXTRN GETVAR
|
|
EXTRN PUTVAR
|
|
EXTRN GETDEF
|
|
EXTRN LOCATE
|
|
EXTRN CREATE
|
|
EXTRN OUTCHR
|
|
EXTRN EXTERR
|
|
EXTRN BYE
|
|
EXTRN NXT
|
|
EXTRN NLIST
|
|
;
|
|
EXTRN OSWRCH
|
|
EXTRN OSLINE
|
|
EXTRN OSSHUT
|
|
EXTRN OSBPUT
|
|
EXTRN OSBGET
|
|
EXTRN CLRSCN
|
|
EXTRN PUTCSR
|
|
EXTRN PUTIME
|
|
EXTRN PUTIMS
|
|
EXTRN PUTPTR
|
|
EXTRN OSCALL
|
|
EXTRN OSCLI
|
|
EXTRN TRAP
|
|
;
|
|
EXTRN SOUND
|
|
EXTRN CLG
|
|
EXTRN DRAW
|
|
EXTRN ENVEL
|
|
EXTRN GCOL
|
|
EXTRN MODE
|
|
EXTRN MOVE
|
|
EXTRN PLOT
|
|
EXTRN COLOUR
|
|
EXTRN CIRCLE
|
|
EXTRN ELLIPSE
|
|
EXTRN FILL
|
|
EXTRN MOUSE
|
|
EXTRN ORIGIN
|
|
EXTRN RECTAN
|
|
EXTRN LINE
|
|
EXTRN WAIT
|
|
EXTRN TINT
|
|
EXTRN SYS
|
|
;
|
|
EXTRN STR
|
|
EXTRN HEXSTR
|
|
EXTRN EXPR
|
|
EXTRN EXPRN
|
|
EXTRN EXPRI
|
|
EXTRN EXPRS
|
|
EXTRN ITEMI
|
|
EXTRN CONS
|
|
EXTRN LOADS
|
|
EXTRN VAL0
|
|
EXTRN SFIX
|
|
EXTRN TEST
|
|
EXTRN LOAD4
|
|
EXTRN LOADN
|
|
EXTRN DLOAD5
|
|
EXTRN FPP
|
|
EXTRN COMMA
|
|
EXTRN BRAKET
|
|
EXTRN PUSHS
|
|
EXTRN POPS
|
|
EXTRN ZERO
|
|
EXTRN SCP
|
|
EXTRN LETARR
|
|
;
|
|
EXTRN ACCS
|
|
EXTRN PAGE
|
|
EXTRN LOMEM
|
|
EXTRN HIMEM
|
|
EXTRN FREE
|
|
EXTRN BUFFER
|
|
EXTRN ERRTRP
|
|
EXTRN ONERSP
|
|
EXTRN CURLIN
|
|
EXTRN COUNT
|
|
EXTRN WIDTH
|
|
EXTRN STAVAR
|
|
EXTRN DATPTR
|
|
EXTRN RANDOM
|
|
EXTRN TRACEN
|
|
EXTRN LISTON
|
|
EXTRN PC
|
|
EXTRN OC
|
|
;
|
|
LF EQU 0AH
|
|
CR EQU 0DH
|
|
TAND EQU 80H
|
|
TOR EQU 84H
|
|
TERROR EQU 85H
|
|
TLINE EQU 86H
|
|
TOFF EQU 87H
|
|
TSTEP EQU 88H
|
|
TSPC EQU 89H
|
|
TTAB EQU 8AH
|
|
TELSE EQU 8BH
|
|
TTHEN EQU 8CH
|
|
TLINO EQU 8DH
|
|
TTO EQU 0B8H
|
|
TCMD EQU 0C0H
|
|
TWHILE EQU 0C7H
|
|
TWHEN EQU 0C9H
|
|
TOF EQU 0CAH
|
|
TENDCASE EQU 0CBH
|
|
TOTHERWISE EQU 0CCH
|
|
TENDIF EQU 0CDH
|
|
TENDWHILE EQU 0CEH
|
|
TCALL EQU 0D6H
|
|
TDATA EQU 0DCH
|
|
TDEF EQU 0DDH
|
|
TFOR EQU 0E3H
|
|
TGOSUB EQU 0E4H
|
|
TGOTO EQU 0E5H
|
|
TLOCAL EQU 0EAH
|
|
TNEXT EQU 0EDH
|
|
TON EQU 0EEH
|
|
TPROC EQU 0F2H
|
|
TREM EQU 0F4H
|
|
TREPEAT EQU 0F5H
|
|
TRETURN EQU 0F8H
|
|
TSTOP EQU 0FAH
|
|
TUNTIL EQU 0FDH
|
|
TEXIT EQU 10H
|
|
;
|
|
CMDTAB: DEFW LEFTSL
|
|
DEFW MIDSL
|
|
DEFW RITESL
|
|
DEFW SYNTAX ;STR$
|
|
DEFW SYNTAX ;STRING$
|
|
DEFW SYNTAX ;EOF
|
|
DEFW SYNTAX ;SUM
|
|
DEFW WHILE
|
|
DEFW CASE
|
|
DEFW SYNTAX ;WHEN
|
|
DEFW SYNTAX ;OF
|
|
DEFW XEQ ;ENDCASE
|
|
DEFW SYNTAX ;OTHERWISE
|
|
DEFW XEQ ;ENDIF
|
|
DEFW ENDWHI ;ENDWHILE
|
|
DEFW PTR
|
|
DEFW PAGEV
|
|
DEFW TIMEV
|
|
DEFW LOMEMV
|
|
DEFW HIMEMV
|
|
DEFW SOUND
|
|
DEFW BPUT
|
|
DEFW CALL
|
|
DEFW CHAIN
|
|
DEFW CLR
|
|
DEFW CLOSE
|
|
DEFW CLG
|
|
DEFW CLS
|
|
DEFW REM ;DATA
|
|
DEFW REM ;DEF
|
|
DEFW DIM
|
|
DEFW DRAW
|
|
DEFW END
|
|
DEFW ENDPRO
|
|
DEFW ENVEL
|
|
DEFW FOR
|
|
DEFW GOSUB
|
|
DEFW GOTO
|
|
DEFW GCOL
|
|
DEFW IF
|
|
DEFW INPUT
|
|
DEFW LET
|
|
DEFW LOCAL
|
|
DEFW MODE
|
|
DEFW MOVE
|
|
DEFW NEXT
|
|
DEFW ON
|
|
DEFW VDU
|
|
DEFW PLOT
|
|
DEFW PRINT
|
|
DEFW PROC
|
|
DEFW READ
|
|
DEFW REM
|
|
DEFW REPEAT
|
|
DEFW REPOR
|
|
DEFW RESTOR
|
|
DEFW RETURN
|
|
DEFW RUN
|
|
DEFW STOP
|
|
DEFW COLOUR
|
|
DEFW TRACE
|
|
DEFW UNTIL
|
|
DEFW WIDTHV
|
|
DEFW CLI ;OSCLI
|
|
DEFW REM ;NUL
|
|
DEFW CIRCLE
|
|
DEFW ELLIPSE
|
|
DEFW FILL
|
|
DEFW MOUSE
|
|
DEFW ORIGIN
|
|
DEFW BYE ;QUIT
|
|
DEFW RECTAN
|
|
DEFW SWAP
|
|
DEFW SYS
|
|
DEFW TINT
|
|
DEFW WAIT
|
|
DEFW SYNTAX ;INSTALL
|
|
DEFW REM ;CR
|
|
DEFW PUT ;Token changed
|
|
DEFW SYNTAX ;BY
|
|
DEFW EXIT
|
|
;
|
|
TLAST EQU TCMD-128+($-CMDTAB)/2
|
|
;
|
|
RUN: CALL TERMQ
|
|
JR Z,RUN0
|
|
CHAIN: CALL EXPRS
|
|
LD A,CR
|
|
LD (DE),A
|
|
CHAIN0: LD SP,(HIMEM)
|
|
CALL LOAD0
|
|
RUN0: LD SP,(HIMEM) ;PREPARE FOR RUN
|
|
LD IX,RANDOM
|
|
RAND: LD A,R ;RANDOMISE (CARE!)
|
|
JR Z,RAND
|
|
RLCA
|
|
RLCA
|
|
LD (IX+3),A
|
|
SBC A,A
|
|
LD (IX+4),A
|
|
CALL CLEAR
|
|
LD HL,0
|
|
LD (ERRTRP),HL
|
|
LD HL,(PAGE)
|
|
CALL DSRCH ;LOOK FOR "DATA"
|
|
LD (DATPTR),HL ;SET DATA POINTER
|
|
LD IY,(PAGE)
|
|
XEQ0: CALL NEWLIN
|
|
LD A,(IY)
|
|
CP TELSE
|
|
JP Z,MELSE ;ELSE
|
|
CP TWHEN
|
|
JP Z,WHEN ;WHEN
|
|
CP TOTHERWISE
|
|
JP Z,WHEN
|
|
XEQ: LD (CURLIN),IY ;ERROR POINTER
|
|
CALL TRAP ;CHECK KEYBOARD
|
|
XEQ1: CALL NXT
|
|
INC IY
|
|
CP ':' ;SEPARATOR
|
|
JR Z,XEQ1
|
|
CP CR
|
|
JR Z,XEQ0 ;NEW PROGRAM LINE
|
|
CP TLAST
|
|
JP PE,LET0 ;IMPLIED LET
|
|
SUB TCMD
|
|
JP M,EXTRAS
|
|
ADD A,A
|
|
LD C,A
|
|
LD B,0
|
|
LD HL,CMDTAB
|
|
ADD HL,BC
|
|
LD A,(HL) ;TABLE ENTRY
|
|
INC HL
|
|
LD H,(HL)
|
|
LD L,A
|
|
CALL NXT
|
|
JP (HL) ;EXECUTE STATEMENT
|
|
;
|
|
;END
|
|
;
|
|
ENDIM: PUSH IY
|
|
POP HL
|
|
LD BC,(PAGE)
|
|
SBC HL,BC ;IMMEDIATE MODE ?
|
|
JP C,CLOOP
|
|
END: LD E,0
|
|
CALL OSSHUT ;CLOSE ALL FILES
|
|
JP WARM ;"Ready"
|
|
;
|
|
NEWLIN: LD A,(IY+0) ;A=LINE LENGTH
|
|
LD BC,3
|
|
ADD IY,BC
|
|
OR A
|
|
JR Z,ENDIM ;LENGTH=0, EXIT
|
|
LD HL,(TRACEN)
|
|
LD A,H
|
|
OR L
|
|
RET Z
|
|
LD D,(IY-1) ;DE = LINE NUMBER
|
|
LD E,(IY-2)
|
|
SBC HL,DE
|
|
RET C
|
|
EX DE,HL
|
|
LD A,'[' ;TRACE
|
|
CALL OUTCHR
|
|
CALL PBCDL
|
|
LD A,']'
|
|
CALL OUTCHR
|
|
LD A,' '
|
|
JP OUTCHR
|
|
;
|
|
;ROUTINES FOR EACH STATEMENT:
|
|
;
|
|
;OSCLI
|
|
;
|
|
CLI: CALL EXPRS
|
|
LD A,CR
|
|
LD (DE),A
|
|
LD HL,ACCS
|
|
CALL OSCLI
|
|
JR XEQ
|
|
;
|
|
;REM, *
|
|
;
|
|
EXT: PUSH IY
|
|
POP HL
|
|
CALL OSCLI
|
|
REM: PUSH IY
|
|
POP HL
|
|
LD A,CR
|
|
LD B,A
|
|
CPIR ;FIND LINE END
|
|
PUSH HL
|
|
POP IY
|
|
JP XEQ0
|
|
;
|
|
EXTRAS: CP TELSE-TCMD
|
|
JR Z,REM ;ELSE
|
|
CP TERROR-TCMD
|
|
JR Z,THROW ;ERROR
|
|
CP TLINE-TCMD
|
|
JP Z,LINE ;LINE
|
|
JP SYNTAX
|
|
;
|
|
;ERROR num,string$
|
|
;
|
|
THROW: CALL EXPRI
|
|
EXX
|
|
PUSH HL
|
|
EXX
|
|
CALL COMMA
|
|
CALL EXPRS
|
|
POP HL
|
|
XOR A
|
|
LD (DE),A
|
|
LD A,L
|
|
LD HL,ACCS
|
|
LD DE,BUFFER
|
|
PUSH DE
|
|
LD BC,256
|
|
LDIR
|
|
JP EXTERR
|
|
;
|
|
; SWAP
|
|
;
|
|
SWAP: CALL GETVAR
|
|
JR NZ,SWAPNZ
|
|
PUSH AF
|
|
PUSH HL
|
|
CALL COMMA
|
|
CALL NXT
|
|
CALL GETVAR
|
|
SWAPNZ: JR NZ,NOSUCH
|
|
POP DE
|
|
POP BC
|
|
CP B
|
|
JR NZ,MISMAT
|
|
AND 00001111B
|
|
JR Z,MISMAT
|
|
LD A,B
|
|
AND 11000000B
|
|
JR Z,SWAP1
|
|
LD B,2
|
|
JP P,SWAP1
|
|
JP PE,SWAP1
|
|
LD B,4
|
|
SWAP1: LD C,(HL)
|
|
LD A,(DE)
|
|
LD (HL),A
|
|
LD A,C
|
|
LD (DE),A
|
|
INC DE
|
|
INC HL
|
|
DJNZ SWAP1
|
|
JR XEQR
|
|
;
|
|
;[LET] var = expr
|
|
;
|
|
LET0: CP '*'
|
|
JR Z,EXT
|
|
CP '='
|
|
JR Z,FNEND
|
|
CP '['
|
|
JR Z,ASM
|
|
DEC IY
|
|
LET: CALL ASSIGN
|
|
JP Z,XEQ
|
|
JR C,SYNTAX ;"Syntax error"
|
|
JP P,LETARR ;Numeric array
|
|
JP PE,LETARR ;String array
|
|
LD A,D ;Type
|
|
PUSH DE
|
|
PUSH HL
|
|
CALL EXPRS
|
|
POP IX
|
|
POP HL
|
|
CALL MODIFS
|
|
XEQR: JP XEQ
|
|
;
|
|
; GETSTR - Get string variable
|
|
; Inputs: IY = text pointer
|
|
; Outputs: B = type
|
|
; Z-flag set if comma
|
|
;
|
|
GETSTR: CALL GETVAR
|
|
JR NZ,NOSUCH
|
|
LD B,A
|
|
AND 11000000B
|
|
JP P,MISMAT
|
|
JP PE,BADUSE
|
|
BIT 0,B
|
|
JR Z,MISMAT
|
|
CALL NXT
|
|
CP ','
|
|
RET
|
|
;
|
|
VAR: CALL GETVAR
|
|
RET Z
|
|
JP NC,PUTVAR
|
|
NOSUCH: LD A,26 ;'No such variable'
|
|
DEFB 21H
|
|
SYNTAX: LD A,16 ;"Syntax error"
|
|
DEFB 21H
|
|
ESCAPE: LD A,17 ;"Escape"
|
|
DEFB 21H
|
|
BADUSE: LD A,14 ;'Bad use of array'
|
|
DEFB 21H
|
|
MISMAT: LD A,6 ;'Type mismatch'
|
|
ERROR0: JP ERROR
|
|
;
|
|
ASM0: CALL NEWLIN
|
|
ASM: LD (CURLIN),IY
|
|
CALL TRAP
|
|
CALL ASSEM
|
|
JR C,SYNTAX
|
|
CP CR
|
|
JR Z,ASM0
|
|
LD HL,LISTON
|
|
LD A,(HL)
|
|
AND 0FH
|
|
OR 30H
|
|
LD (HL),A
|
|
JR XEQR
|
|
;
|
|
;=
|
|
;
|
|
FNEND: CALL EXPR ;FUNCTION RESULT
|
|
EX AF,AF'
|
|
ADD A,A
|
|
LD A,E
|
|
JR C,FNEND1
|
|
LD A,C
|
|
FNEND1: EX AF,AF'
|
|
PUSH HL
|
|
EXX
|
|
POP BC
|
|
EX DE,HL ;SAVE RESULT IN A'B'C'D'E'
|
|
EXX
|
|
FNEND2: POP BC
|
|
LD HL,FNCHK
|
|
XOR A
|
|
SBC HL,BC
|
|
JR Z,FNEND3
|
|
PUSH BC
|
|
CALL RESLOC
|
|
JR NZ,FNEND2
|
|
LD A,7
|
|
JR ERROR0 ;"No FN"
|
|
;
|
|
FNEND3: POP IY
|
|
LD (CURLIN),IY ;IN CASE OF ERROR
|
|
EXX
|
|
EX DE,HL
|
|
PUSH BC
|
|
EXX
|
|
POP HL
|
|
EX AF,AF'
|
|
LD E,A
|
|
LD C,A
|
|
RRA
|
|
RET
|
|
;
|
|
;DIM var(dim1[,dim2[,...]])[,var(...]
|
|
;DIM var expr[,var expr...]
|
|
;
|
|
DIM: PUSH IY
|
|
CP '!'
|
|
JP Z,DIM4
|
|
CALL LOCATE ;VARIABLE
|
|
JP C,BADDIM
|
|
CALL NZ,CREATE
|
|
LD A,(IY)
|
|
CP '('
|
|
JP NZ,DIM4
|
|
PUSH HL
|
|
POP IX
|
|
LD A,(HL)
|
|
AND 0FEH
|
|
INC HL
|
|
OR (HL)
|
|
JP NZ,DIM4
|
|
POP BC ;LEVEL STACK
|
|
LD A,D
|
|
LD HL,(FREE)
|
|
PUSH HL
|
|
EX (SP),IX
|
|
PUSH HL
|
|
PUSH AF ;SAVE TYPE
|
|
LD DE,1
|
|
LD B,D ;DIMENSION COUNTER
|
|
DIM1: INC IY
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH IX
|
|
CALL EXPRI ;DIMENSION SIZE
|
|
BIT 7,H
|
|
JR NZ,BADDIM
|
|
EXX
|
|
INC HL
|
|
POP IX
|
|
INC IX
|
|
LD (IX),L ;SAVE SIZE
|
|
INC IX
|
|
LD (IX),H
|
|
POP BC
|
|
CALL MUL16 ;HL=HL*BC
|
|
JR C,NOROOM ;TOO LARGE
|
|
EX DE,HL ;DE=PRODUCT
|
|
POP BC
|
|
INC B ;DIMENSION COUNTER
|
|
LD A,(IY)
|
|
CP ',' ;ANOTHER
|
|
JR Z,DIM1
|
|
INC IX
|
|
CALL BRAKET ;CLOSING BRACKET
|
|
POP AF ;RESTORE TYPE
|
|
CALL X14OR5 ;DE=DE*n
|
|
JR C,NOROOM
|
|
POP HL
|
|
LD (HL),B ;NO. OF DIMENSIONS
|
|
EX (SP),IX
|
|
POP HL
|
|
AND 80H
|
|
OR (IX) ;FLAGS
|
|
;
|
|
; A = flags: bit 7 = string, bit 0 = LOCAL
|
|
; DE = amount to allocate
|
|
; HL = where to allocate (if not LOCAL)
|
|
; (HL - FREE is size of 'descriptor')
|
|
; IX = where to store pointer
|
|
;
|
|
DIM3: PUSH HL
|
|
INC H ;Safety margin
|
|
ADD HL,DE
|
|
JR C,NOROOM
|
|
SBC HL,SP
|
|
JR NC,NOROOM
|
|
POP HL
|
|
PUSH HL
|
|
LD BC,(FREE)
|
|
OR A
|
|
SBC HL,BC
|
|
LD B,H
|
|
LD C,L
|
|
POP HL
|
|
SBC HL,BC
|
|
BIT 0,A
|
|
JR Z,ARRCHK ;NOT LOCAL
|
|
LD HL,0
|
|
ADD HL,SP
|
|
SBC HL,DE
|
|
SBC HL,BC
|
|
LD SP,HL
|
|
PUSH DE
|
|
PUSH BC
|
|
PUSH AF
|
|
CALL ARRCHK
|
|
ARRCHK: LD (IX+0),L ;SAVE POINTER
|
|
LD (IX+1),H
|
|
LD A,B
|
|
OR C
|
|
JR Z,DIM2
|
|
PUSH DE
|
|
EX DE,HL
|
|
LD HL,(FREE)
|
|
LDIR ;COPY DESCRIPTOR
|
|
EX DE,HL
|
|
POP DE
|
|
DIM2: LD A,D
|
|
OR E
|
|
JR Z,DIM5
|
|
LD (HL),0 ;INITIALISE ARRAY
|
|
INC HL
|
|
DEC DE
|
|
JR DIM2
|
|
;
|
|
BADDIM: LD A,10 ;"Bad DIM"
|
|
DEFB 21H
|
|
NOROOM: LD A,11 ;"DIM space"
|
|
ERROR1: JP ERROR
|
|
;
|
|
DIM5: SBC HL,SP
|
|
JR NC,DIM7 ;LOCAL
|
|
ADD HL,SP
|
|
LD (FREE),HL
|
|
DIM7: CALL NLIST ;ANOTHER VARIABLE?
|
|
JP DIM
|
|
;
|
|
DIM4: POP IY
|
|
CALL VAR
|
|
OR A
|
|
JR Z,BADDIM
|
|
JP M,BADDIM
|
|
BIT 6,A
|
|
JR NZ,BADDIM
|
|
LD B,A ;TYPE
|
|
CALL NXT
|
|
CP TLOCAL
|
|
LD A,0 ;PRESET TO NOT LOCAL
|
|
JR NZ,DIM8
|
|
INC IY
|
|
INC A ;FLAG LOCAL
|
|
DIM8: PUSH AF
|
|
LD A,B ;TYPE
|
|
EXX
|
|
LD HL,0
|
|
LD C,H
|
|
CALL STOREN ;RESERVED AREA
|
|
PUSH IX
|
|
CALL EXPRI
|
|
POP IX
|
|
EXX
|
|
INC HL
|
|
EX DE,HL
|
|
LD HL,(FREE)
|
|
POP AF ;LOCAL FLAG
|
|
JP DIM3
|
|
;
|
|
;PRINT list...
|
|
;PRINT #channel,list...
|
|
;
|
|
PRINT: CP '#'
|
|
JR NZ,PRINT0
|
|
CALL CHNL ;CHANNEL NO. = E
|
|
PRNTN1: CALL NLIST
|
|
PUSH DE
|
|
CALL EXPR ;ITEM TO PRINT
|
|
EX AF,AF'
|
|
JP M,PRNTN2 ;STRING
|
|
POP DE
|
|
PUSH BC
|
|
EXX
|
|
LD A,L
|
|
EXX
|
|
CALL OSBPUT
|
|
EXX
|
|
LD A,H
|
|
EXX
|
|
CALL OSBPUT
|
|
LD A,L
|
|
CALL OSBPUT
|
|
LD A,H
|
|
CALL OSBPUT
|
|
POP BC
|
|
LD A,C
|
|
CALL OSBPUT
|
|
JR PRNTN1
|
|
PRNTN2: LD C,E
|
|
POP DE
|
|
LD HL,ACCS
|
|
INC C
|
|
PRNTN3: DEC C
|
|
JR Z,PRNTN4
|
|
LD A,(HL)
|
|
INC HL
|
|
PUSH BC
|
|
CALL OSBPUT
|
|
POP BC
|
|
JR PRNTN3
|
|
PRNTN4: LD A,CR
|
|
CALL OSBPUT
|
|
JR PRNTN1
|
|
;
|
|
PRINT6: LD B,2
|
|
JR PRINTC
|
|
PRINT8: LD BC,100H
|
|
JR PRINTC
|
|
PRINT9: LD HL,STAVAR
|
|
XOR A
|
|
CP (HL)
|
|
JR Z,PRINT0
|
|
LD A,(COUNT)
|
|
OR A
|
|
JR Z,PRINT0
|
|
PRINTA: SUB (HL)
|
|
JR Z,PRINT0
|
|
JR NC,PRINTA
|
|
NEG
|
|
CALL SPACES
|
|
PRINT0: LD A,(STAVAR)
|
|
LD C,A ;PRINTS
|
|
LD B,0 ;PRINTF
|
|
PRINTC: CALL TERMQ
|
|
JR Z,PRINT4
|
|
RES 0,B
|
|
INC IY
|
|
CP '~'
|
|
JR Z,PRINT6
|
|
CP ';'
|
|
JR Z,PRINT8
|
|
CP ','
|
|
JR Z,PRINT9
|
|
CALL FORMAT ;SPC, TAB, '
|
|
JR Z,PRINTC
|
|
DEC IY
|
|
PUSH BC
|
|
CALL EXPR ;VARIABLE TYPE
|
|
EX AF,AF'
|
|
JP M,PRINT3 ;STRING
|
|
POP DE
|
|
PUSH DE
|
|
BIT 1,D
|
|
PUSH AF
|
|
CALL Z,STR ;DECIMAL
|
|
POP AF
|
|
CALL NZ,HEXSTR ;HEX
|
|
POP BC
|
|
PUSH BC
|
|
LD A,C
|
|
SUB E
|
|
CALL NC,SPACES ;RIGHT JUSTIFY
|
|
PRINT3: POP BC
|
|
CALL PTEXT ;PRINT
|
|
JR PRINTC
|
|
PRINT4: BIT 0,B
|
|
CALL Z,CRLF
|
|
JR XEQGO3
|
|
;
|
|
ONERR: INC IY ;SKIP "ERROR"
|
|
CALL NXT
|
|
LD HL,0 ;FLAG NOT LOCAL
|
|
CP TLOCAL
|
|
JR NZ,ONERR1
|
|
INC IY ;SKIP "LOCAL"
|
|
LD HL,(ERRTRP)
|
|
PUSH HL
|
|
LD HL,(ONERSP)
|
|
PUSH HL
|
|
LD HL,400H ;TYPE = 4, 'EXPONENT' = 0
|
|
PUSH HL
|
|
LD HL,ERRTRP
|
|
PUSH HL
|
|
LD HL,LOCCHK
|
|
PUSH HL
|
|
LD HL,0
|
|
ADD HL,SP
|
|
CALL NXT
|
|
ONERR1: LD (ONERSP),HL
|
|
LD (ERRTRP),IY
|
|
CP TOFF
|
|
JP NZ,REM
|
|
INC IY ;SKIP "OFF"
|
|
SBC HL,HL
|
|
LD (ONERSP),HL
|
|
LD (ERRTRP),HL
|
|
XEQGO3: JP XEQ
|
|
;
|
|
;ON expr GOTO line[,line...] [ELSE statement]
|
|
;ON expr GOTO line[,line...] [ELSE line]
|
|
;ON expr GOSUB line[,line...] [ELSE statement]
|
|
;ON expr GOSUB line[,line...] [ELSE line]
|
|
;ON expr PROCone [,PROCtwo..] [ELSE PROCotherwise]
|
|
;ON ERROR [LOCAL] statement [:statement...]
|
|
;ON ERROR [LOCAL] OFF
|
|
;
|
|
ON: CP TERROR
|
|
JR Z,ONERR ;"ON ERROR"
|
|
CALL EXPRI
|
|
LD A,(IY)
|
|
INC IY
|
|
LD E,',' ;SEPARATOR
|
|
CP TGOTO
|
|
JR Z,ON1
|
|
CP TGOSUB
|
|
JR Z,ON1
|
|
LD E,TPROC
|
|
CP E
|
|
LD A,39
|
|
JR NZ,ERROR2 ;"ON syntax"
|
|
ON1: LD D,A
|
|
EXX
|
|
PUSH HL
|
|
EXX
|
|
POP BC ;ON INDEX
|
|
LD A,B
|
|
OR H
|
|
OR L
|
|
JR NZ,ON4 ;OUT OF RANGE
|
|
OR C
|
|
JR Z,ON4
|
|
DEC C
|
|
JR Z,ON3 ;INDEX=1
|
|
ON2: CALL TERMQ
|
|
JR Z,ON4 ;OUT OF RANGE
|
|
INC IY ;SKIP DELIMITER
|
|
CP '"'
|
|
JR Z,ON5
|
|
CP E
|
|
JR NZ,ON2
|
|
DEC C
|
|
JR NZ,ON2
|
|
ON3: LD A,E
|
|
CP TPROC
|
|
JR Z,ONPROC
|
|
PUSH DE
|
|
CALL ITEMI ;LINE NUMBER
|
|
POP DE
|
|
LD A,D
|
|
CP TGOTO
|
|
JR Z,GOTO2
|
|
CALL SPAN ;SKIP REST OF LIST
|
|
JR GOSUB1
|
|
;
|
|
ON5: CALL QUOTE
|
|
INC IY
|
|
JR ON2
|
|
;
|
|
ON4: LD A,(IY)
|
|
INC IY
|
|
CP TELSE
|
|
JP Z,IF1 ;ELSE CLAUSE
|
|
CP CR
|
|
JR NZ,ON4
|
|
LD A,40
|
|
ERROR2: JP ERROR ;"ON range"
|
|
;
|
|
ONPROC: LD A,TON
|
|
JP PROC
|
|
;
|
|
;GOTO line
|
|
;
|
|
GOTO: CALL ITEMI ;LINE NUMBER
|
|
GOTO1: CALL TERMQ
|
|
JP NZ,SYNTAX
|
|
GOTO2: EXX
|
|
CALL FINDL
|
|
PUSH HL
|
|
POP IY
|
|
JP Z,XEQ0
|
|
LD A,41
|
|
JR ERROR2 ;"No such line"
|
|
;
|
|
;GOSUB line
|
|
;
|
|
GOSUB: CALL ITEMI ;LINE NUMBER
|
|
GOSUB1: PUSH IY ;TEXT POINTER
|
|
CALL CHECK ;CHECK ROOM
|
|
CALL GOTO1 ;SAVE MARKER
|
|
GOSCHK EQU $
|
|
;
|
|
;RETURN
|
|
;
|
|
RETURN: POP DE ;MARKER
|
|
LD HL,GOSCHK
|
|
OR A
|
|
SBC HL,DE
|
|
POP IY
|
|
JR Z,XEQGO2
|
|
LD A,38
|
|
JR ERROR2 ;"No GOSUB"
|
|
;
|
|
;REPEAT
|
|
;
|
|
REPEAT: PUSH IY
|
|
CALL CHECK
|
|
CALL XEQ
|
|
REPCHK EQU $
|
|
;
|
|
;UNTIL expr
|
|
;
|
|
UNTIL: POP BC
|
|
PUSH BC
|
|
LD HL,REPCHK
|
|
OR A
|
|
SBC HL,BC
|
|
JR Z,UNTIL1
|
|
LD A,3
|
|
CALL RESLOC
|
|
JR NZ,UNTIL
|
|
LD A,43
|
|
JR ERROR2 ;"Not in a REPEAT loop"
|
|
;
|
|
UNTIL1: CALL EXPRI
|
|
CALL TEST
|
|
POP BC
|
|
POP DE
|
|
JR NZ,XEQGO2 ;TRUE
|
|
PUSH DE
|
|
PUSH BC
|
|
PUSH DE
|
|
POP IY
|
|
XEQGO2: JP XEQ
|
|
;
|
|
;FOR var = expr TO expr [STEP expr]
|
|
;
|
|
FORVAR: LD A,34
|
|
JR ERROR2 ;"FOR variable"
|
|
;
|
|
FOR: CALL ASSIGN
|
|
JR NZ,FORVAR ;"FOR variable"
|
|
PUSH AF ;SAVE TYPE
|
|
LD A,(IY)
|
|
CP TTO
|
|
LD A,36
|
|
JR NZ,ERROR2 ;"No TO"
|
|
INC IY
|
|
PUSH IX
|
|
CALL EXPRN ;LIMIT
|
|
POP IX
|
|
POP AF
|
|
LD B,A ;TYPE
|
|
PUSH BC ;SAVE ON STACK
|
|
PUSH HL
|
|
LD HL,0
|
|
LD C,H
|
|
EXX
|
|
PUSH HL
|
|
LD HL,1 ;PRESET STEP
|
|
EXX
|
|
LD A,(IY)
|
|
CP TSTEP
|
|
JR NZ,FOR1
|
|
INC IY
|
|
PUSH IX
|
|
CALL EXPRN ;STEP
|
|
POP IX
|
|
FOR1: LD B,8 ;FPP '>'
|
|
BIT 7,H
|
|
JR NZ,FOR2 ;STEP SIGN
|
|
LD B,12 ;FPP '<'
|
|
FOR2: PUSH BC
|
|
PUSH HL
|
|
EXX
|
|
PUSH HL
|
|
EXX
|
|
PUSH IY ;SAVE TEXT POINTER
|
|
PUSH IX ;LOOP VARIABLE
|
|
CALL CHECK
|
|
CALL XEQ
|
|
FORCHK EQU $
|
|
;
|
|
;NEXT [var[,var...]]
|
|
;
|
|
NEXT: POP BC ;MARKER
|
|
LD HL,FORCHK
|
|
OR A
|
|
SBC HL,BC
|
|
JR Z,NEXT2
|
|
PUSH BC
|
|
LD A,3
|
|
CALL RESLOC
|
|
JR NZ,NEXT
|
|
LD A,32
|
|
JR ERROR3 ;"Not in a FOR loop"
|
|
;
|
|
NEXT2: CALL TERMQ
|
|
POP HL
|
|
PUSH HL
|
|
PUSH BC
|
|
PUSH HL
|
|
CALL NZ,GETVAR ;VARIABLE
|
|
POP DE
|
|
EX DE,HL
|
|
OR A
|
|
NEXT0: SBC HL,DE
|
|
JR NZ,NEXT1
|
|
PUSH DE
|
|
LD IX,6+2
|
|
ADD IX,SP
|
|
CALL DLOAD5 ;STEP
|
|
LD A,(IX+11) ;TYPE
|
|
POP IX
|
|
CALL LOADN ;LOOP VARIABLE
|
|
PUSH AF
|
|
LD A,'+' AND 0FH
|
|
CALL FPP ;ADD STEP
|
|
JR C,ERROR3
|
|
POP AF ;RESTORE TYPE
|
|
CALL STOREN ;UPDATE VARIABLE
|
|
LD IX,12
|
|
ADD IX,SP
|
|
CALL DLOAD5 ;LIMIT
|
|
LD A,(IX-1)
|
|
CALL FPP ;TEST AGAINST LIMIT
|
|
JR C,ERROR3
|
|
INC H
|
|
JR NZ,LOOP ;KEEP LOOPING
|
|
LD HL,18
|
|
ADD HL,SP
|
|
LD SP,HL
|
|
CALL NLIST
|
|
JR NEXT
|
|
;
|
|
LOOP: POP BC
|
|
POP DE
|
|
POP IY
|
|
PUSH IY
|
|
PUSH DE
|
|
PUSH BC
|
|
JP XEQ
|
|
;
|
|
NEXT1: LD HL,18
|
|
ADD HL,SP
|
|
LD SP,HL ;"POP" THE STACK
|
|
POP BC
|
|
LD HL,FORCHK
|
|
SBC HL,BC
|
|
POP HL ;VARIABLE POINTER
|
|
PUSH HL
|
|
PUSH BC
|
|
JR Z,NEXT0
|
|
LD A,33
|
|
ERROR3: JP ERROR ;"Can't match FOR"
|
|
;
|
|
;FNname
|
|
;N.B. ENTERED WITH A <> TON
|
|
;
|
|
FN: PUSH AF ;MAKE SPACE ON STACK
|
|
CALL PROC1
|
|
FNCHK EQU $
|
|
;
|
|
;PROCname
|
|
;N.B. ENTERED WITH A = ON PROC FLAG
|
|
;
|
|
PROC: PUSH AF ;MAKE SPACE ON STACK
|
|
CALL PROC1
|
|
PROCHK EQU $
|
|
PROC1: CALL CHECK
|
|
DEC IY
|
|
PUSH IY
|
|
CALL GETDEF
|
|
POP BC
|
|
JR Z,PROC4
|
|
LD A,30
|
|
JR C,ERROR3 ;"Bad call"
|
|
PUSH BC
|
|
LD HL,(PAGE)
|
|
PROC2: LD A,TDEF
|
|
CALL SEARCH ;LOOK FOR "DEF"
|
|
JR C,PROC3
|
|
PUSH HL
|
|
POP IY
|
|
INC IY ;SKIP DEF
|
|
CALL NXT
|
|
CALL GETDEF
|
|
PUSH IY
|
|
POP DE
|
|
JR C,PROC6
|
|
CALL NZ,CREATE
|
|
PUSH IY
|
|
POP DE
|
|
LD (HL),E
|
|
INC HL
|
|
LD (HL),D ;SAVE ADDRESS
|
|
PROC6: EX DE,HL
|
|
LD A,CR
|
|
LD B,A
|
|
CPIR ;SKIP TO END OF LINE
|
|
JR PROC2
|
|
PROC3: POP IY ;RESTORE TEXT POINTER
|
|
CALL GETDEF
|
|
LD A,29
|
|
JR NZ,ERROR3 ;"No such FN/PROC"
|
|
PROC4: LD E,(HL)
|
|
INC HL
|
|
LD D,(HL) ;GET ADDRESS
|
|
LD HL,2
|
|
ADD HL,SP
|
|
CALL NXT ;ALLOW SPACE BEFORE (
|
|
PUSH DE ;EXCHANGE DE,IY
|
|
EX (SP),IY
|
|
POP DE
|
|
CP '(' ;ARGUMENTS?
|
|
JP NZ,PROC5
|
|
CALL NXT ;ALLOW SPACE BEFORE (
|
|
CP '('
|
|
JP NZ,SYNTAX ;"Syntax error"
|
|
PUSH IY
|
|
POP BC ;SAVE IY IN BC
|
|
EXX
|
|
EX AF,AF'
|
|
XOR A ;INITIALISE RETURN COUNT
|
|
EX AF,AF'
|
|
CALL SAVLOC ;SAVE DUMMY VARIABLES
|
|
EX AF,AF'
|
|
OR A
|
|
JR Z,RETCHK ;NO RETURNS
|
|
PUSH HL
|
|
NEG
|
|
LD L,A
|
|
NEG
|
|
LD H,-1 ;HL = -RETURNS
|
|
ADD HL,HL
|
|
ADD HL,HL
|
|
ADD HL,HL ;-RETURNS * 8
|
|
EX (SP),HL
|
|
POP IX
|
|
ADD IX,SP
|
|
LD SP,IX
|
|
PUSH AF ;PUSH RETURN COUNT
|
|
CALL RETCHK ;PUSH MARKER
|
|
RETCHK: EX AF,AF'
|
|
CALL BRAKET ;CLOSING BRACKET
|
|
EXX
|
|
PUSH BC
|
|
POP IY ;RESTORE IY
|
|
PUSH HL
|
|
CALL ARGUE ;TRANSFER ARGUMENTS
|
|
POP HL
|
|
;
|
|
; If any of the dummy arguments is the same as a passed-by-reference
|
|
; variable, then it must not be restored on exit (it would overwrite
|
|
; the wanted returned values), therefore search the saved values on
|
|
; the stack and if a match is found set bit 4 of the type. On exit
|
|
; from the FN/PROC this will prevent the dummies from being restored.
|
|
;
|
|
EX (SP),HL
|
|
OR A
|
|
LD BC,RETCHK
|
|
SBC HL,BC
|
|
ADD HL,BC
|
|
EX (SP),HL
|
|
JR NZ,PROC5 ;No RETURNs
|
|
;
|
|
PUSH DE
|
|
PUSH HL
|
|
LD HL,7 ;Skip two PUSHes and RETCHK
|
|
ADD HL,SP
|
|
LD A,(HL) ;RETURN count
|
|
INC HL
|
|
PUSH HL
|
|
POP IX ;Address RETURNs table
|
|
PROC0: LD E,A
|
|
LD D,0
|
|
EX DE,HL
|
|
ADD HL,HL
|
|
ADD HL,HL
|
|
ADD HL,HL
|
|
ADD HL,DE ;HL addresses SAVLOC stack
|
|
INC HL
|
|
INC HL ;Bump past LOCCHK
|
|
PROC7: LD E,(HL)
|
|
INC HL
|
|
LD D,(HL) ;DE = SAVLOC VARPTR
|
|
INC HL
|
|
LD C,(HL) ;Length (if string)
|
|
INC HL
|
|
LD B,(HL) ;Variable type
|
|
;
|
|
; Scan RETURNs table for VARPTR match
|
|
;
|
|
PUSH BC ;Save type
|
|
PUSH HL
|
|
PUSH IX
|
|
LD B,A ;B = RETURN count
|
|
PROC8: LD L,(IX+4)
|
|
LD H,(IX+5) ;HL = RETURNed VARPTR
|
|
OR A
|
|
SBC HL,DE
|
|
JR Z,PROC9
|
|
EX DE,HL
|
|
LD DE,8
|
|
ADD IX,DE
|
|
EX DE,HL
|
|
DJNZ PROC8
|
|
PROC9: POP IX
|
|
POP HL
|
|
POP BC ;Restore type
|
|
;
|
|
; If match, set bit 4 of type:
|
|
;
|
|
JR NZ,PROCA
|
|
SET 4,(HL) ;Flag don't restore
|
|
;
|
|
; Increment past stacked data:
|
|
;
|
|
PROCA: LD DE,3
|
|
BIT 6,B
|
|
JR NZ,PROCB ;Whole array
|
|
LD E,5
|
|
BIT 7,B
|
|
JR Z,PROCB ;Numeric
|
|
LD E,C
|
|
INC DE
|
|
PROCB: ADD HL,DE
|
|
LD C,(HL)
|
|
INC HL
|
|
LD B,(HL)
|
|
INC HL ; BC = marker ?
|
|
EX DE,HL
|
|
LD HL,LOCCHK
|
|
OR A
|
|
SBC HL,BC
|
|
EX DE,HL
|
|
JR Z,PROC7 ;Another
|
|
POP HL
|
|
POP DE
|
|
;
|
|
PROC5: LD (HL),E ;SAVE "RETURN ADDRESS"
|
|
INC HL
|
|
LD A,(HL)
|
|
LD (HL),D
|
|
CP TON ;WAS IT "ON PROC" ?
|
|
JR NZ,XEQGO
|
|
PUSH DE
|
|
EX (SP),IY
|
|
CALL SPAN ;SKIP REST OF ON LIST
|
|
EX (SP),IY
|
|
POP DE
|
|
LD (HL),D
|
|
DEC HL
|
|
LD (HL),E
|
|
XEQGO: JP XEQ
|
|
;
|
|
LOCERR: INC IY
|
|
JR XEQGO
|
|
;
|
|
;LOCAL DATA
|
|
;
|
|
LOCDAT: INC IY
|
|
LD HL,(DATPTR)
|
|
PUSH HL
|
|
LD A,40H
|
|
PUSH AF
|
|
LD HL,DATPTR
|
|
PUSH HL
|
|
LD HL,LOCCHK
|
|
PUSH HL
|
|
JR XEQGO
|
|
;
|
|
;LOCAL var[,var...]
|
|
;
|
|
LOCAL: CP TERROR
|
|
JR Z,LOCERR
|
|
CP TDATA
|
|
JR Z,LOCDAT
|
|
POP BC
|
|
PUSH BC
|
|
LD HL,FNCHK
|
|
OR A
|
|
SBC HL,BC
|
|
JR Z,LOCAL1
|
|
LD HL,PROCHK
|
|
OR A
|
|
SBC HL,BC
|
|
JR Z,LOCAL1
|
|
LD HL,LOCCHK
|
|
OR A
|
|
SBC HL,BC
|
|
JR Z,LOCAL1
|
|
LD HL,ARRCHK
|
|
OR A
|
|
SBC HL,BC
|
|
JR Z,LOCAL1
|
|
LD HL,RETCHK
|
|
OR A
|
|
SBC HL,BC
|
|
LD A,12
|
|
JP NZ,ERROR ;"Not LOCAL"
|
|
LOCAL1: PUSH IY
|
|
POP BC
|
|
EXX
|
|
DEC IY
|
|
CALL SAVLOC
|
|
EXX
|
|
PUSH BC
|
|
POP IY
|
|
LOCAL2: CALL GETVAR
|
|
JP NZ,SYNTAX
|
|
BIT 6,A ;ARRAY?
|
|
JR NZ,LOCAL4
|
|
OR A ;TYPE
|
|
EX AF,AF'
|
|
CALL ZERO
|
|
EX AF,AF'
|
|
PUSH AF
|
|
CALL P,STOREN ;ZERO
|
|
POP AF
|
|
LD E,C
|
|
CALL M,STORES
|
|
LOCAL3: CALL NLIST
|
|
JR LOCAL2
|
|
;
|
|
LOCAL4: LD (IX+0),1 ;FLAG LOCAL ARRAY
|
|
LD (IX+1),0
|
|
JR LOCAL3
|
|
;
|
|
;ENDPROC
|
|
;
|
|
ENDPRO: POP BC
|
|
LD HL,PROCHK ;PROC MARKER
|
|
XOR A
|
|
SBC HL,BC
|
|
JR Z,ENDPR1
|
|
PUSH BC ;PUT BACK
|
|
CALL RESLOC
|
|
JR NZ,ENDPRO
|
|
LD A,13
|
|
JP ERROR ;"No PROC"
|
|
;
|
|
ENDPR1: POP IY
|
|
JP XEQ
|
|
;
|
|
;INPUT #channel,var,var...
|
|
;
|
|
INPUTN: CALL CHNL ;E = CHANNEL NUMBER
|
|
INPN1: CALL NLIST
|
|
PUSH DE
|
|
CALL VAR
|
|
POP DE
|
|
PUSH AF ;SAVE TYPE
|
|
PUSH HL ;VARPTR
|
|
OR A
|
|
JP M,INPN2 ;STRING
|
|
CALL OSBGET
|
|
EXX
|
|
LD L,A
|
|
EXX
|
|
CALL OSBGET
|
|
EXX
|
|
LD H,A
|
|
EXX
|
|
CALL OSBGET
|
|
LD L,A
|
|
CALL OSBGET
|
|
LD H,A
|
|
CALL OSBGET
|
|
LD C,A
|
|
POP IX
|
|
POP AF ;RESTORE TYPE
|
|
PUSH DE ;SAVE CHANNEL
|
|
CALL STOREN
|
|
POP DE
|
|
JR INPN1
|
|
INPN2: LD HL,ACCS
|
|
INPN3: CALL OSBGET
|
|
CP CR
|
|
JR Z,INPN4
|
|
LD (HL),A
|
|
INC L
|
|
JR NZ,INPN3
|
|
INPN4: POP IX
|
|
POP AF
|
|
PUSH DE
|
|
EX DE,HL
|
|
CALL STACCS
|
|
POP DE
|
|
JR INPN1
|
|
;
|
|
;INPUT ['][SPC(x)][TAB(x[,y])]["prompt",]var[,var...]
|
|
;INPUT LINE [SPC(x)][TAB(x[,y])]["prompt",]var[,var...]
|
|
;
|
|
INPUT: CP '#'
|
|
JR Z,INPUTN
|
|
LD C,0 ;FLAG PROMPT
|
|
CP TLINE
|
|
JR NZ,INPUT0
|
|
INC IY ;SKIP "LINE"
|
|
LD C,80H
|
|
INPUT0: LD HL,BUFFER
|
|
LD (HL),CR ;INITIALISE EMPTY
|
|
INPUT1: CALL TERMQ
|
|
JP Z,XEQ ;DONE
|
|
INC IY
|
|
CP ','
|
|
JR Z,INPUT3 ;SKIP COMMA
|
|
CP ';'
|
|
JR Z,INPUT3
|
|
PUSH HL ;SAVE BUFFER POINTER
|
|
CP '"'
|
|
JR NZ,INPUT6
|
|
PUSH BC
|
|
CALL CONS
|
|
POP BC
|
|
CALL PTEXT ;PRINT PROMPT
|
|
JR INPUT9
|
|
INPUT6: CALL FORMAT ;SPC, TAB, '
|
|
JR NZ,INPUT2
|
|
INPUT9: POP HL
|
|
SET 0,C ;FLAG NO PROMPT
|
|
JR INPUT0
|
|
INPUT2: DEC IY
|
|
PUSH BC
|
|
CALL VAR
|
|
POP BC
|
|
POP HL
|
|
PUSH AF ;SAVE TYPE
|
|
LD A,(HL)
|
|
INC HL
|
|
CP CR ;BUFFER EMPTY?
|
|
CALL Z,REFILL
|
|
BIT 7,C
|
|
PUSH AF
|
|
CALL NZ,LINES
|
|
POP AF
|
|
CALL Z,FETCHS
|
|
POP AF ;RESTORE TYPE
|
|
PUSH BC
|
|
PUSH HL
|
|
OR A
|
|
JP M,INPUT4 ;STRING
|
|
PUSH AF
|
|
PUSH IX
|
|
CALL VAL0
|
|
POP IX
|
|
POP AF
|
|
CALL STOREN
|
|
JR INPUT5
|
|
INPUT4: CALL STACCS
|
|
INPUT5: POP HL
|
|
POP BC
|
|
INPUT3: RES 0,C
|
|
JR INPUT1
|
|
;
|
|
REFILL: BIT 0,C
|
|
JR NZ,REFIL0 ;NO PROMPT
|
|
LD A,'?'
|
|
CALL OUTCHR ;PROMPT
|
|
LD A,' '
|
|
CALL OUTCHR
|
|
REFIL0: LD HL,BUFFER
|
|
PUSH BC
|
|
PUSH HL
|
|
PUSH IX
|
|
CALL OSLINE
|
|
POP IX
|
|
POP HL
|
|
POP BC
|
|
LD B,A ;POS AT ENTRY
|
|
XOR A
|
|
LD (COUNT),A
|
|
CP B
|
|
RET Z
|
|
REFIL1: LD A,(HL)
|
|
CP CR
|
|
RET Z
|
|
INC HL
|
|
DJNZ REFIL1
|
|
RET
|
|
;
|
|
;READ var[,var...]
|
|
;
|
|
READ: CP '#'
|
|
JP Z,INPUTN
|
|
LD HL,(DATPTR)
|
|
READ0: LD A,(HL)
|
|
CP ':'
|
|
CALL Z,REFIL1
|
|
INC HL ;SKIP COMMA OR "DATA"
|
|
CP CR ;END OF DATA STMT?
|
|
CALL Z,GETDAT
|
|
PUSH HL
|
|
CALL VAR
|
|
POP HL
|
|
OR A
|
|
JP M,READ1 ;STRING
|
|
PUSH HL
|
|
EX (SP),IY
|
|
PUSH AF ;SAVE TYPE
|
|
PUSH IX
|
|
CALL EXPRN
|
|
POP IX
|
|
POP AF
|
|
CALL STOREN
|
|
EX (SP),IY
|
|
JR READ2
|
|
READ1: CALL FETCHS
|
|
PUSH HL
|
|
CALL STACCS
|
|
READ2: POP HL
|
|
LD (DATPTR),HL
|
|
CALL NLIST
|
|
JR READ0
|
|
;
|
|
GETDAT: CALL DSRCH
|
|
INC HL
|
|
RET NC
|
|
LD A,42
|
|
JR ERROR4 ;"Out of DATA"
|
|
;
|
|
;IF expr statement
|
|
;IF expr THEN statement [ELSE statement]
|
|
;IF expr THEN line [ELSE line]
|
|
;IF expr THEN
|
|
;
|
|
IF: CALL EXPRI
|
|
CALL TEST
|
|
JR Z,IFNOT ;FALSE
|
|
LD A,(IY)
|
|
CP TTHEN
|
|
JP NZ,XEQ
|
|
IF0: INC IY ;SKIP "THEN"
|
|
LD A,(IY)
|
|
CP ';'
|
|
JR Z,IF0
|
|
IF1: CALL NXT
|
|
CP TLINO
|
|
JP NZ,XEQ ;STATEMENT FOLLOWS
|
|
JP GOTO ;LINE NO. FOLLOWS
|
|
;
|
|
IFELSE: LD A,(IY)
|
|
INC IY
|
|
CP ';'
|
|
JR NZ,IFNEXT
|
|
JR IFTHEN
|
|
;
|
|
IF2: CALL QUOTE ;SKIP STRING
|
|
IFNOT: LD A,(IY)
|
|
INC IY
|
|
IFNEXT: CP '"'
|
|
JR Z,IF2 ;QUOTED STRING
|
|
CP TREM
|
|
JP Z,REM ;REM
|
|
CP CR
|
|
JP Z,XEQ0 ;END OF LINE
|
|
CP TELSE
|
|
JR Z,IF1 ;ELSE CLAUSE
|
|
CP TTHEN
|
|
JR NZ,IFNOT ;TRY FOR END AGAIN
|
|
IFTHEN: LD A,(IY)
|
|
CP CR
|
|
JR NZ,IFELSE
|
|
LD BC,TELSE
|
|
LD DE,TENDIF*256+TTHEN
|
|
INC IY
|
|
CALL NSCAN
|
|
JP Z,XEQ1
|
|
NENDIF: LD A,49
|
|
ERROR4: JP ERROR ;"Missing ENDIF"
|
|
;
|
|
; ELSE (multi-line)
|
|
;
|
|
MELSE: LD BC,-3
|
|
ADD IY,BC
|
|
LD BC,TENDIF
|
|
LD DE,TENDIF*256+TTHEN
|
|
CALL NSCAN
|
|
JP Z,XEQ
|
|
JR NENDIF
|
|
;
|
|
; WHEN and OTHERWISE:
|
|
;
|
|
WHEN: LD BC,-3
|
|
ADD IY,BC
|
|
LD BC,TENDCASE
|
|
LD DE,TENDCASE*256+TOF
|
|
CALL NSCAN
|
|
JP Z,XEQ
|
|
LD A,47
|
|
JR ERROR4 ;"Missing ENDCASE"
|
|
;
|
|
; CASE
|
|
;
|
|
CASE: CALL EXPR ;String or numeric
|
|
EX AF,AF'
|
|
LD B,0 ;Flag numeric
|
|
JP P,CASE6 ;numeric
|
|
CALL PUSHS ;put string on stack
|
|
POP BC ;C = length
|
|
LD B,1 ;Flag string
|
|
CASE6: LD A,(IY)
|
|
INC IY
|
|
CP TOF
|
|
LD A,37
|
|
JR NZ,ERROR4 ;"Missing OF"
|
|
LD A,(IY)
|
|
INC IY ;Address line-length byte
|
|
CP CR
|
|
LD A,48
|
|
JR NZ,ERROR4 ;"OF not last"
|
|
CASE1: XOR A ;Level
|
|
CASE0: EXX
|
|
PUSH HL ;Push to stack
|
|
EXX
|
|
PUSH HL
|
|
PUSH BC
|
|
LD L,A ;Level
|
|
LD BC,TOTHERWISE*256+TWHEN
|
|
LD DE,TENDCASE*256+TOF
|
|
CALL NSCAN1
|
|
POP BC ;Restore from stack
|
|
POP HL
|
|
EXX
|
|
POP HL
|
|
EXX
|
|
LD A,47
|
|
JP NZ,ERROR ;Missing ENDCASE
|
|
LD A,(IY-1)
|
|
CP TENDCASE
|
|
JR Z,CASE9
|
|
CP TOTHERWISE
|
|
JR Z,CASE9
|
|
CASE4: BIT 0,B ;Numeric or string?
|
|
JR NZ,CASE3
|
|
PUSH BC ;Type/exponent/length
|
|
PUSH HL ;MS 32 bits
|
|
EXX
|
|
PUSH HL ;LS 32 bits
|
|
EXX
|
|
CALL EXPRN
|
|
LD IX,0
|
|
ADD IX,SP ;Address stack
|
|
EXX
|
|
LD E,(IX+0) ;Get LS 32-bits
|
|
LD D,(IX+1)
|
|
EXX
|
|
LD E,(IX+2)
|
|
LD D,(IX+3) ;Get MS 32-bits
|
|
LD B,(IX+4) ;Get exponent
|
|
LD A,9
|
|
CALL FPP ;In case integer vs float
|
|
LD A,L
|
|
OR A ;NZ if equal
|
|
EXX
|
|
POP HL
|
|
EXX
|
|
POP HL
|
|
POP BC
|
|
JR NZ,CASE5 ;Match found
|
|
CASE2: LD A,(IY)
|
|
INC IY
|
|
CP ','
|
|
JR Z,CASE4 ;Not found, try another
|
|
EXX
|
|
PUSH IY
|
|
EX (SP),HL
|
|
LD A,CR
|
|
LD B,A
|
|
CPIR ;Find CR
|
|
EX (SP),HL
|
|
POP IY
|
|
EXX
|
|
LD A,(IY-2) ;Last token in previous line
|
|
CP TOF ;CASE statement in WHEN line
|
|
JR NZ,CASE1
|
|
LD A,1
|
|
JR CASE0
|
|
;
|
|
;Finished, level stack if string:
|
|
;
|
|
CASE9: BIT 0,B
|
|
JR Z,CASE8
|
|
LD H,0
|
|
LD L,C
|
|
ADD HL,SP
|
|
LD SP,HL
|
|
CASE8: JP XEQ
|
|
;
|
|
;Matched, so skip any more expressions:
|
|
;
|
|
CASE5: CALL NXT
|
|
CP ','
|
|
JR NZ,CASE9 ;End of list
|
|
INC IY
|
|
PUSH BC ;Save type and string length
|
|
CALL EXPR ;Evaluate but discard
|
|
POP BC
|
|
JR CASE5
|
|
;
|
|
;String compare:
|
|
;
|
|
CASE3: PUSH BC
|
|
CALL EXPRS
|
|
POP BC
|
|
LD HL,0
|
|
ADD HL,SP
|
|
LD B,E
|
|
LD DE,ACCS
|
|
PUSH BC
|
|
CALL SCP ;String compare
|
|
POP BC
|
|
LD B,1
|
|
JR NZ,CASE2
|
|
JR CASE5
|
|
;
|
|
; WHILE
|
|
;
|
|
WHILE: PUSH IY ;Save current position
|
|
CALL CHECK
|
|
CALL WHICHK ;Push marker
|
|
WHICHK: CALL EXPRI
|
|
CALL TEST
|
|
JR NZ,XEQGO5
|
|
POP BC ;Pop marker
|
|
POP BC ;Level stack
|
|
LD BC,TWHILE+TENDWHILE*256
|
|
LD D,1
|
|
CALL WSRCH
|
|
XEQGO5: JP XEQ
|
|
;
|
|
; ENDWHILE
|
|
;
|
|
ENDWHI: POP BC ;Marker
|
|
POP DE ;Saved text pointer
|
|
PUSH DE
|
|
PUSH BC
|
|
OR A
|
|
LD HL,WHICHK
|
|
SBC HL,BC
|
|
JR Z,ENDWH1
|
|
LD A,3
|
|
CALL RESLOC
|
|
JR NZ,ENDWHI
|
|
LD A,46
|
|
JR ERROR5 ;"Not in a WHILE loop"
|
|
;
|
|
ENDWH1: PUSH IY
|
|
LD IY,0
|
|
ADD IY,DE
|
|
CALL EXPRI
|
|
CALL TEST
|
|
POP DE ;Text pointer
|
|
JR NZ,XEQGO5
|
|
POP BC ;Junk marker
|
|
POP BC ;Junk pointer
|
|
LD IY,0
|
|
ADD IY,DE
|
|
JR XEQGO5
|
|
;
|
|
;CLS
|
|
;
|
|
CLS: CALL CLRSCN
|
|
XOR A
|
|
LD (COUNT),A
|
|
JP XEQ
|
|
;
|
|
;STOP
|
|
;
|
|
STOP: CALL TELL
|
|
DEFB CR
|
|
DEFB LF
|
|
DEFB TSTOP
|
|
DEFB 0
|
|
CALL SETLIN ;FIND CURRENT LINE
|
|
CALL SAYLN
|
|
CALL CRLF
|
|
JP CLOOP
|
|
;
|
|
;REPORT
|
|
;
|
|
REPOR: CALL REPORT
|
|
JP XEQ
|
|
;
|
|
;CLEAR
|
|
;
|
|
CLR: CALL CLEAR
|
|
LD HL,(PAGE)
|
|
JR RESTR1
|
|
;
|
|
;RESTORE ERROR
|
|
;
|
|
RESERR: INC IY
|
|
LD A,2
|
|
CALL RESLOC
|
|
JP NZ,XEQ
|
|
LD A,53 ;ON ERROR not LOCAL
|
|
ERROR5: JP ERROR
|
|
;
|
|
;RESTORE DATA
|
|
;
|
|
RESDAT: INC IY
|
|
LD A,1
|
|
CALL RESLOC
|
|
JP NZ,XEQ
|
|
LD A,54 ;'DATA not LOCAL'
|
|
DEFB 21H
|
|
NOLINE: LD A,41 ;'No such line'
|
|
JR ERROR5
|
|
;
|
|
;RESTORE [line]
|
|
;
|
|
RESTOR: CP TERROR
|
|
JR Z,RESERR
|
|
CP TDATA
|
|
JR Z,RESDAT
|
|
CP '+'
|
|
JR Z,RESREL
|
|
LD HL,(PAGE)
|
|
CALL TERMQ
|
|
JR Z,RESTR1
|
|
CALL ITEMI
|
|
EXX
|
|
CALL FINDL ;SEARCH FOR LINE
|
|
JR NZ,NOLINE
|
|
RESTR1: CALL DSRCH
|
|
LD (DATPTR),HL
|
|
JP XEQ
|
|
;
|
|
RESREL: CALL EXPRI
|
|
EXX
|
|
EX DE,HL
|
|
PUSH IY
|
|
POP HL
|
|
LD A,CR
|
|
LD B,A
|
|
CPIR ;FIND LINE END
|
|
DEC E
|
|
JR Z,RESTR1
|
|
JP M,RESTR1
|
|
XOR A
|
|
LD B,A
|
|
RESTR2: LD C,(HL)
|
|
CP C
|
|
JR Z,NOLINE
|
|
ADD HL,BC
|
|
DEC E
|
|
JR NZ,RESTR2
|
|
JR RESTR1
|
|
;
|
|
;PTR#channel=expr
|
|
;PAGE=expr
|
|
;TIME=expr
|
|
;LOMEM=expr
|
|
;HIMEM=expr
|
|
;
|
|
PTR: CALL CHANEL
|
|
CALL EQUALS
|
|
LD A,E
|
|
PUSH AF
|
|
CALL EXPRI
|
|
PUSH HL
|
|
EXX
|
|
POP DE
|
|
POP AF
|
|
CALL PUTPTR
|
|
JR XEQGO1
|
|
;
|
|
PAGEV: CALL EQUALS
|
|
CALL EXPRI
|
|
EXX
|
|
LD L,0
|
|
LD (PAGE),HL
|
|
JR XEQGO1
|
|
;
|
|
TIMEV: CP '$'
|
|
JR Z,TIMEVS
|
|
CALL EQUALS
|
|
CALL EXPRI
|
|
PUSH HL
|
|
EXX
|
|
POP DE
|
|
CALL PUTIME
|
|
JR XEQGO1
|
|
;
|
|
TIMEVS: INC IY ;SKIP '$'
|
|
CALL EQUALS
|
|
CALL EXPRS
|
|
CALL PUTIMS
|
|
JR XEQGO1
|
|
;
|
|
LOMEMV: CALL EQUALS
|
|
CALL EXPRI
|
|
CALL CLEAR
|
|
EXX
|
|
LD (LOMEM),HL
|
|
LD (FREE),HL
|
|
JR XEQGO1
|
|
;
|
|
HIMEMV: CALL EQUALS
|
|
CALL EXPRI
|
|
EXX
|
|
LD DE,(FREE)
|
|
INC D
|
|
XOR A
|
|
SBC HL,DE
|
|
ADD HL,DE
|
|
JP C,ERROR ;"No room"
|
|
LD DE,(HIMEM)
|
|
LD (HIMEM),HL
|
|
EX DE,HL
|
|
SBC HL,SP
|
|
JP NZ,XEQ
|
|
EX DE,HL
|
|
LD SP,HL ;LOAD STACK POINTER
|
|
XEQGO1: JP XEQ
|
|
;
|
|
;WIDTH expr
|
|
;
|
|
WIDTHV: CALL EXPRI
|
|
EXX
|
|
LD A,L
|
|
LD (WIDTH),A
|
|
JR XEQGO1
|
|
;
|
|
;TRACE ON
|
|
;TRACE OFF
|
|
;TRACE line
|
|
;
|
|
TRACE: INC IY
|
|
LD HL,0
|
|
CP TON
|
|
JR Z,TRACE0
|
|
CP TOFF
|
|
JR Z,TRACE1
|
|
DEC IY
|
|
CALL EXPRI
|
|
EXX
|
|
TRACE0: DEC HL
|
|
TRACE1: LD (TRACEN),HL
|
|
JR XEQGO1
|
|
;
|
|
;VDU expr,expr;....
|
|
;
|
|
VDU: CALL EXPRI
|
|
EXX
|
|
LD A,L
|
|
CALL OSWRCH
|
|
LD A,(IY)
|
|
CP ','
|
|
JR Z,VDU2
|
|
CP ';'
|
|
JR NZ,VDU3
|
|
LD A,H
|
|
CALL OSWRCH
|
|
VDU2: INC IY
|
|
VDU3: CALL TERMQ
|
|
JR NZ,VDU
|
|
JR XEQGO1
|
|
;
|
|
;CLOSE channel number
|
|
;
|
|
CLOSE: CALL CHANEL
|
|
CALL OSSHUT
|
|
JR XEQGO1
|
|
;
|
|
;BPUT #channel,byte
|
|
;BPUT #channel,string[;]
|
|
;
|
|
BPUT: CALL CHANEL ;CHANNEL NUMBER
|
|
PUSH DE
|
|
CALL COMMA
|
|
CALL EXPR
|
|
EX AF,AF'
|
|
JP M,BPUTS
|
|
CALL SFIX
|
|
EXX
|
|
LD A,L
|
|
POP DE
|
|
CALL OSBPUT
|
|
BPUTX: JR XEQGO1
|
|
;
|
|
BPUTS: LD A,E
|
|
POP DE
|
|
LD D,A
|
|
LD HL,ACCS
|
|
BPUTS1: LD A,(HL)
|
|
INC HL
|
|
CALL OSBPUT
|
|
DEC D
|
|
JR NZ,BPUTS1
|
|
CALL NXT
|
|
CP ';'
|
|
INC IY
|
|
JR Z,BPUTX
|
|
LD A,LF
|
|
CALL OSBPUT
|
|
DEC IY
|
|
JR BPUTX
|
|
;
|
|
;CALL address[,var[,var...]]
|
|
;
|
|
CALL: CALL EXPRI ;ADDRESS
|
|
EXX
|
|
PUSH HL ;SAVE IT
|
|
LD B,0 ;PARAMETER COUNTER
|
|
LD DE,BUFFER ;VECTOR
|
|
CALL1: CALL NXT
|
|
CP ','
|
|
JR NZ,CALL2
|
|
INC IY
|
|
INC B
|
|
CALL NXT
|
|
PUSH BC
|
|
PUSH DE
|
|
CALL VAR
|
|
POP DE
|
|
POP BC
|
|
INC DE
|
|
LD (DE),A ;PARAMETER TYPE
|
|
INC DE
|
|
EX DE,HL
|
|
LD (HL),E ;PARAMETER ADDRESS
|
|
INC HL
|
|
LD (HL),D
|
|
EX DE,HL
|
|
JR CALL1
|
|
CALL2: LD A,B
|
|
LD (BUFFER),A ;PARAMETER COUNT
|
|
POP HL ;RESTORE ADDRESS
|
|
CALL USR1
|
|
JP XEQ
|
|
;
|
|
;USR(address)
|
|
;
|
|
USR: CALL ITEMI
|
|
EXX
|
|
USR1: PUSH HL ;ADDRESS ON STACK
|
|
EX (SP),IY
|
|
INC H ;PAGE &FF?
|
|
LD HL,USR2 ;RETURN ADDRESS
|
|
PUSH HL
|
|
LD IX,STAVAR
|
|
CALL Z,OSCALL ;INTERCEPT PAGE &FF
|
|
LD C,(IX+24)
|
|
PUSH BC
|
|
POP AF ;LOAD FLAGS
|
|
LD A,(IX+4) ;LOAD Z80 REGISTERS
|
|
LD B,(IX+8)
|
|
LD C,(IX+12)
|
|
LD D,(IX+16)
|
|
LD E,(IX+20)
|
|
LD H,(IX+32)
|
|
LD L,(IX+48)
|
|
LD IX,BUFFER
|
|
JP (IY) ;OFF TO USER ROUTINE
|
|
USR2: POP IY
|
|
XOR A
|
|
LD C,A
|
|
RET
|
|
;
|
|
; LEFT$(A$[,N]) = string
|
|
; MID$(A$,N[,M]) = string
|
|
; RIGHT$(A$[,N]) = string
|
|
;
|
|
LEFTSL: CALL GETSTR
|
|
LD HL,0FF00H ;Default all but last
|
|
JR NZ,MIDSL1
|
|
JR MIDSL0
|
|
;
|
|
RITESL: CALL GETSTR
|
|
LD HL,0FFFFH ;Default last char only
|
|
JR NZ,MIDSL1
|
|
JR MIDSL0
|
|
;
|
|
MIDSL: CALL GETSTR
|
|
LD A,5
|
|
JP NZ,ERROR ;'Missing comma'
|
|
INC IY
|
|
PUSH IX
|
|
CALL EXPRI
|
|
POP IX
|
|
EXX
|
|
CALL NXT
|
|
DEC L
|
|
LD H,254 ;Default rest of string
|
|
CP ','
|
|
JR NZ,MIDSL1
|
|
MIDSL0: INC IY
|
|
PUSH HL
|
|
PUSH IX
|
|
CALL EXPRI
|
|
POP IX
|
|
EXX
|
|
LD A,L
|
|
POP HL
|
|
OR A
|
|
JR Z,MIDSL2 ;Zero length
|
|
DEC A
|
|
ADD A,L
|
|
LD H,A
|
|
JR NC,MIDSL1
|
|
LD A,L
|
|
INC A
|
|
JR Z,MIDSL1
|
|
LD H,254
|
|
JR MIDSL1
|
|
;
|
|
MIDSL2: LD HL,1
|
|
MIDSL1: CALL BRAKET
|
|
CALL EQUALS
|
|
PUSH HL
|
|
PUSH IX
|
|
CALL EXPRS
|
|
POP IX
|
|
POP HL
|
|
LD C,E
|
|
LD B,(IX+0)
|
|
LD E,(IX+2)
|
|
LD D,(IX+3)
|
|
;
|
|
; Source string at ACCS, length C
|
|
; Destination string at DE, length B
|
|
; L = first character to modify 0-254
|
|
; H = last character to modify 0-254
|
|
; IF L=255 THEN modify rightmost H + 2 chars
|
|
; ELSE IF H=255 modify all but last character
|
|
; ELSE IF L > H do nothing
|
|
; IX = destination VARPTR
|
|
;
|
|
LD A,L
|
|
INC A
|
|
JR NZ,SUBSL1
|
|
INC H
|
|
INC H
|
|
LD A,C
|
|
CP H
|
|
JR NC,SUBSL0
|
|
LD H,A
|
|
SUBSL0: LD A,B
|
|
SUB H
|
|
JR NC,SUBSL6
|
|
XOR A
|
|
SUBSL6: LD L,A
|
|
JR SUBSL5
|
|
;
|
|
SUBSL1: LD A,H
|
|
INC A
|
|
JR NZ,SUBSL2
|
|
LD A,B
|
|
SUB 2
|
|
JR C,SUBSL9
|
|
LD H,A
|
|
SUBSL2: LD A,L
|
|
CP B
|
|
JR NC,SUBSL9
|
|
LD A,H
|
|
CP B
|
|
JR C,SUBSL3
|
|
SUBSL5: LD A,B
|
|
DEC A
|
|
LD H,A
|
|
SUBSL3: LD A,H
|
|
SUB L
|
|
JR C,SUBSL9
|
|
INC A
|
|
CP C
|
|
JR C,SUBSL4
|
|
LD A,C
|
|
SUBSL4: LD B,0
|
|
LD H,B
|
|
LD C,A
|
|
OR A
|
|
JR Z,SUBSL9
|
|
EX DE,HL
|
|
ADD HL,DE
|
|
EX DE,HL
|
|
LD HL,ACCS
|
|
LDIR
|
|
SUBSL9: JP XEQ
|
|
;
|
|
; EXIT FOR [var]
|
|
; EXIT REPEAT
|
|
; EXIT WHILE
|
|
;
|
|
EXIT: INC IY ;Skip FOR/REPEAT/WHILE
|
|
CP TFOR
|
|
JR NZ,EXIT0
|
|
LD IX,0 ;For EXIT FOR <var>
|
|
CALL TERMQ
|
|
CALL NZ,GETVAR
|
|
LD A,TFOR
|
|
EXIT0: LD D,1 ;Level for WSRCH
|
|
LD E,A
|
|
EXIT1: LD A,E
|
|
POP BC ;Marker
|
|
LD HL,FORCHK
|
|
OR A
|
|
SBC HL,BC
|
|
JR Z,EXIT4
|
|
LD HL,REPCHK
|
|
OR A
|
|
SBC HL,BC
|
|
JR Z,EXIT6
|
|
LD HL,WHICHK
|
|
OR A
|
|
SBC HL,BC
|
|
JR Z,EXIT7
|
|
PUSH BC ;Put back marker
|
|
PUSH IX
|
|
POP BC
|
|
EXX
|
|
LD A,3
|
|
CALL RESLOC
|
|
EXX
|
|
PUSH BC
|
|
POP IX
|
|
JR NZ,EXIT1
|
|
LD A,44
|
|
JP ERROR ;'Bad EXIT'
|
|
;
|
|
EXIT4: POP BC ;VARPTR
|
|
LD HL,14 ;Skip text pointer, limit & step
|
|
ADD HL,SP
|
|
LD SP,HL ;Pop FOR record
|
|
CP TFOR
|
|
JR NZ,EXIT1
|
|
PUSH IX
|
|
POP HL
|
|
LD A,H
|
|
OR L
|
|
JR Z,EXIT5
|
|
SBC HL,BC
|
|
EXIT5: LD BC,TFOR+TNEXT*256
|
|
JR Z,EXIT8
|
|
INC D ;Count nested FOR loops
|
|
JR EXIT1
|
|
;
|
|
EXIT6: POP BC ;Text pointer
|
|
CP TREPEAT
|
|
JR NZ,EXIT1
|
|
LD BC,TREPEAT+TUNTIL*256
|
|
JR EXIT8
|
|
;
|
|
EXIT7: POP BC ;Text pointer
|
|
CP TWHILE
|
|
JR NZ,EXIT1
|
|
LD BC,TWHILE+TENDWHILE*256
|
|
EXIT8: CALL WSRCH
|
|
CALL SPAN ;Skip UNTIL expression
|
|
JP XEQ
|
|
;
|
|
;PUT port,data
|
|
;
|
|
PUT: CALL EXPRI ;PORT ADDRESS
|
|
EXX
|
|
PUSH HL
|
|
CALL COMMA
|
|
CALL EXPRI ;DATA
|
|
EXX
|
|
POP BC
|
|
OUT (C),L ;OUTPUT TO PORT BC
|
|
JP XEQ
|
|
;
|
|
;SUBROUTINES:
|
|
;
|
|
;ASSIGN - Assign a numeric value to a variable.
|
|
;Outputs: NC, Z - OK, numeric scalar
|
|
; NC, NZ, PE - OK, string array (D = type, E = operator)
|
|
; else if NC, NZ, P - OK, numeric array (D = type, E = operator)
|
|
; else if NC, NZ - OK, string scalar
|
|
; C, NZ - illegal / invalid
|
|
;
|
|
ASSIGN: CALL GETVAR ;VARIABLE
|
|
RET C ;ILLEGAL VARIABLE
|
|
CALL NZ,PUTVAR
|
|
LD D,A ;Type
|
|
CALL NXT
|
|
INC IY
|
|
LD E,A ;Operator (or =)
|
|
CP '='
|
|
CALL NZ,EQUALS
|
|
LD A,D
|
|
AND 11000000B
|
|
RET NZ ;String or array
|
|
PUSH DE
|
|
PUSH HL
|
|
CALL EXPRN
|
|
POP IX
|
|
POP DE
|
|
;
|
|
; Falls through to...
|
|
;
|
|
; MODIFY - Update numeric variable according to operator:
|
|
; Inputs: D = type
|
|
; E = operator
|
|
; HLH'L'C = value
|
|
; IX = destination VARPTR
|
|
; Destroys: Everything except IX,IY,SP
|
|
;
|
|
MODIFY: LD A,E
|
|
CP '='
|
|
JR Z,STORE0 ;Simple assignment
|
|
PUSH DE
|
|
EXX
|
|
EX DE,HL
|
|
EXX
|
|
EX DE,HL
|
|
LD B,C
|
|
EX (SP),HL
|
|
LD A,H
|
|
EX (SP),HL
|
|
CALL LOADN
|
|
EX (SP),HL
|
|
LD A,L
|
|
EX (SP),HL
|
|
AND 15
|
|
PUSH IX
|
|
CALL FPP
|
|
POP IX
|
|
POP DE
|
|
JP C,ERROR
|
|
STORE0: LD A,D ;Type
|
|
STOREN: CP 5
|
|
JR Z,STORE5
|
|
PUSH AF
|
|
INC C ;SPEED - & PRESERVE F'
|
|
DEC C ; WHEN CALLED BY FNEND0
|
|
CALL NZ,SFIX ;CONVERT TO INTEGER
|
|
POP AF
|
|
CP 4
|
|
JR Z,STORE4
|
|
CP A ;SET ZERO
|
|
STORE1: EXX
|
|
LD (IX+0),L
|
|
EXX
|
|
RET
|
|
;
|
|
STORE5: LD (IX+4),C
|
|
STORE4: EXX
|
|
LD (IX+0),L
|
|
LD (IX+1),H
|
|
EXX
|
|
LD (IX+2),L
|
|
LD (IX+3),H
|
|
RET
|
|
;
|
|
; MODIFS - Update string variable according to operator:
|
|
; Inputs: H = type
|
|
; L = operator (= or +)
|
|
; E = string length (string in accumulator)
|
|
; IX = destination VARPTR
|
|
; Destroys: Everything except SP, IY
|
|
;
|
|
MODIFS: LD A,L ;Operator
|
|
CP '+'
|
|
LD A,H ;Type
|
|
JR NZ,STACCS
|
|
PUSH IY
|
|
PUSH IX
|
|
POP IY
|
|
CALL PUSHS
|
|
PUSH IY
|
|
POP IX
|
|
CALL LOADS
|
|
POP BC
|
|
LD A,B ;Type
|
|
INC C
|
|
DEC C
|
|
JR Z,MODFS1 ;Zero length
|
|
LD HL,0
|
|
LD B,H
|
|
ADD HL,SP
|
|
LDIR
|
|
LD SP,HL
|
|
MODFS1: POP IY
|
|
;
|
|
; Falls through to:
|
|
;
|
|
STACCS: LD HL,ACCS
|
|
STORES: RRA
|
|
JR NC,STORS3 ;FIXED STRING
|
|
PUSH HL
|
|
CALL LOAD4
|
|
LD A,E ;LENGTH OF STRING
|
|
EXX
|
|
LD L,A
|
|
LD A,H ;LENGTH ALLOCATED
|
|
EXX
|
|
CP E
|
|
JR NC,STORS1 ;ENOUGH ROOM
|
|
EXX
|
|
LD H,L
|
|
EXX
|
|
PUSH HL
|
|
LD B,0
|
|
LD C,A
|
|
ADD HL,BC
|
|
LD BC,(FREE)
|
|
SBC HL,BC ;IS STRING LAST?
|
|
POP HL
|
|
JR Z,STORS0
|
|
LD H,B
|
|
LD L,C ;DESTINATION
|
|
;
|
|
OR A ;V5 optimisation
|
|
JR Z,STORS0
|
|
LD A,E
|
|
STORS2: LD E,A
|
|
DEC E
|
|
AND E
|
|
JR NZ,STORS2
|
|
SCF
|
|
RL E
|
|
LD A,E
|
|
EXX
|
|
LD H,A
|
|
EXX
|
|
;
|
|
STORS0: SCF
|
|
STORS1: CALL STORE4 ;PRESERVES CARRY!
|
|
LD B,0
|
|
LD C,E
|
|
EX DE,HL
|
|
POP HL
|
|
DEC C
|
|
INC C
|
|
RET Z ;NULL STRING
|
|
LDIR
|
|
RET NC ;STRING REPLACED
|
|
LD (FREE),DE
|
|
CHECK: PUSH HL
|
|
LD HL,(FREE)
|
|
INC H
|
|
SBC HL,SP
|
|
POP HL
|
|
RET C
|
|
XOR A
|
|
JP ERROR ;"No room"
|
|
;
|
|
STORS3: LD C,E
|
|
PUSH IX
|
|
POP DE
|
|
XOR A
|
|
LD B,A
|
|
CP C
|
|
JR Z,STORS5
|
|
LDIR
|
|
STORS5: LD A,CR
|
|
LD (DE),A
|
|
RET
|
|
;
|
|
; SAVRET - SAVE 'RETURNed' PARAMETER INFO
|
|
;
|
|
SAVRET: LD (IX+0),L ;Formal VARPTR
|
|
LD (IX+1),H
|
|
LD (IX+2),A
|
|
EX (SP),IY
|
|
PUSH AF
|
|
PUSH IY
|
|
PUSH IX
|
|
CALL NXT
|
|
CALL VAR
|
|
POP IX
|
|
LD (IX+4),L ;Actual VARPTR
|
|
LD (IX+5),H
|
|
LD (IX+6),A
|
|
POP IY
|
|
POP AF
|
|
LD BC,8
|
|
ADD IX,BC
|
|
JR ARGUE0
|
|
;
|
|
;ARGUE: TRANSFER FN OR PROC ARGUMENTS FROM THE
|
|
; CALLING STATEMENT TO THE DUMMY VARIABLES VIA
|
|
; THE STACK. IT MUST BE DONE THIS WAY TO MAKE
|
|
; PROCFRED(A,B) DEF PROCFRED(B,A) WORK.
|
|
; Inputs: DE addresses parameter list
|
|
; IY addresses dummy variable list
|
|
; IX addresses RETURNed parameter data block
|
|
; Outputs: DE,IY updated
|
|
; Destroys: Everything
|
|
;
|
|
ARGUE: LD A,-1
|
|
PUSH AF ;PUT MARKER ON STACK
|
|
ARGUE1: INC IY ;BUMP PAST ( OR ,
|
|
INC DE
|
|
PUSH DE
|
|
LD B,0
|
|
CALL NXT
|
|
CP TRETURN
|
|
JR NZ,ARGUE9
|
|
INC IY ;SKIP 'RETURN'
|
|
CALL NXT
|
|
INC B ;FLAG 'RETURN'
|
|
ARGUE9: PUSH BC
|
|
PUSH IX
|
|
CALL GETVAR ;FORMAL PARAMETER
|
|
JR C,ARGERR
|
|
CALL NZ,PUTVAR
|
|
POP IX
|
|
POP BC
|
|
POP DE
|
|
PUSH HL ;VARPTR
|
|
PUSH AF
|
|
PUSH DE
|
|
DEC B
|
|
JR Z,SAVRET
|
|
EX (SP),IY
|
|
ARGUE0: BIT 6,A ;ARRAY?
|
|
JR NZ,ARGUE3
|
|
OR A ;TYPE
|
|
JP M,ARGUE2 ;STRING
|
|
PUSH IX
|
|
CALL EXPRN ;ACTUAL PARAMETER
|
|
POP IX
|
|
EX (SP),IY
|
|
POP DE
|
|
POP AF
|
|
EXX
|
|
PUSH HL
|
|
EXX
|
|
PUSH HL
|
|
LD B,A
|
|
PUSH BC
|
|
JR ARGUE4
|
|
;
|
|
ARGUE2: PUSH IX
|
|
CALL EXPRS
|
|
EXX
|
|
POP BC
|
|
EX (SP),IY
|
|
POP DE
|
|
EXX
|
|
POP AF
|
|
CALL PUSHS
|
|
EXX
|
|
PUSH BC
|
|
POP IX
|
|
ARGUE4: CALL NXT
|
|
CP ','
|
|
JR NZ,ARGUE5
|
|
LD A,(DE)
|
|
CP ','
|
|
JR Z,ARGUE1 ;ANOTHER
|
|
ARGERR: LD A,31
|
|
JP ERROR ;"Bad arguments"
|
|
;
|
|
ARGUE3: PUSH IX
|
|
CALL NXT
|
|
CALL GETVAR
|
|
JR C,ARGERR
|
|
LD C,(IX+0)
|
|
LD B,(IX+1)
|
|
POP IX
|
|
CALL NXT
|
|
EX (SP),IY
|
|
POP DE
|
|
POP AF
|
|
PUSH BC ;STACK ARRAY POINTER
|
|
PUSH AF ;STACK TYPE
|
|
JR ARGUE4
|
|
;
|
|
ARGUE5: CALL BRAKET
|
|
LD A,(DE)
|
|
CP ')'
|
|
JR NZ,ARGERR
|
|
INC DE
|
|
UNSTAK: EXX
|
|
ARGUE6: POP BC
|
|
LD A,B
|
|
INC A
|
|
EXX
|
|
RET Z ;MARKER POPPED
|
|
EXX
|
|
DEC A
|
|
BIT 6,A ;ARRAY
|
|
JR NZ,ARGUE8
|
|
OR A
|
|
JP M,ARGUE7 ;STRING
|
|
POP HL
|
|
EXX
|
|
POP HL
|
|
EXX
|
|
POP IX
|
|
CALL STOREN ;WRITE TO DUMMY
|
|
JR ARGUE6
|
|
;
|
|
ARGUE7: CALL POPS
|
|
POP IX
|
|
CALL STACCS
|
|
JR ARGUE6
|
|
;
|
|
ARGUE8: POP BC ;ARRAY POINTER
|
|
POP IX
|
|
LD (IX+0),C
|
|
LD (IX+1),B
|
|
JR ARGUE6
|
|
;
|
|
;Restore RETURNed parameters, via the stack to ensure that
|
|
; PROCFRED(A,B) DEF PROCFRED(RETURN B,RETURN A) works.
|
|
;
|
|
RETXFR: LD A,-1
|
|
PUSH AF ;PUT MARKER ON STACK
|
|
RETXF1: EXX
|
|
LD L,(IX+4) ;Actual parameter (destination)
|
|
LD H,(IX+5)
|
|
PUSH HL ;STACK VARPTR
|
|
LD L,(IX+0) ;Formal parameter (source)
|
|
LD H,(IX+1)
|
|
LD A,(IX+2)
|
|
BIT 6,A ;ARRAY?
|
|
JR NZ,RETXF3
|
|
OR A ;TYPE
|
|
JP M,RETXF2 ;STRING
|
|
PUSH HL
|
|
EX (SP),IX
|
|
CALL LOADN
|
|
POP IX
|
|
EXX ;STACK VALUE
|
|
PUSH HL
|
|
EXX
|
|
PUSH HL
|
|
RETXF6: LD B,(IX+6)
|
|
PUSH BC ;TYPE & EXPONENT
|
|
RETXF5: CALL CHECK ;CHECK ROOM
|
|
JR RETXF4
|
|
;
|
|
RETXF3: LD E,(HL)
|
|
INC HL
|
|
LD D,(HL)
|
|
PUSH DE ;STACK ARRAY POINTER
|
|
JR RETXF6
|
|
;
|
|
RETXF2: PUSH HL
|
|
EX (SP),IX
|
|
CALL LOADS
|
|
POP IX
|
|
LD A,(IX+6)
|
|
EXX
|
|
PUSH IX
|
|
POP HL
|
|
EXX
|
|
CALL PUSHS
|
|
EXX
|
|
PUSH HL
|
|
POP IX
|
|
EXX
|
|
RETXF4: LD DE,8
|
|
ADD IX,DE
|
|
EXX
|
|
DJNZ RETXF1
|
|
JP UNSTAK
|
|
;
|
|
;Restore 'RETURNed' parameters,
|
|
;
|
|
RESRET: POP BC ;B = 'RETURN' COUNT
|
|
LD H,0
|
|
LD L,B
|
|
ADD HL,HL
|
|
ADD HL,HL
|
|
ADD HL,HL ;RETURN COUNT * 8
|
|
ADD HL,SP
|
|
LD IX,0
|
|
ADD IX,SP ;ADDRESS PARAMETER LIST
|
|
PUSH AF
|
|
PUSH DE
|
|
PUSH HL
|
|
EXX
|
|
PUSH BC
|
|
PUSH DE
|
|
EXX
|
|
LD A,B
|
|
LD HL,ACCS
|
|
LD DE,BUFFER
|
|
LD BC,255
|
|
LDIR
|
|
LD B,A
|
|
CALL RETXFR ;TRANSFER VIA STACK
|
|
LD HL,BUFFER
|
|
LD DE,ACCS
|
|
LD BC,255
|
|
LDIR
|
|
EXX
|
|
POP DE
|
|
POP BC
|
|
EXX
|
|
POP HL
|
|
POP DE
|
|
POP AF
|
|
JR RESAR1
|
|
;
|
|
; Restore LOCAL array or memory block:
|
|
;
|
|
RESARR: POP BC
|
|
BIT 7,B ;String array?
|
|
POP HL
|
|
POP BC
|
|
ADD HL,BC
|
|
ADD HL,SP
|
|
CALL NZ,FREESA ;Free string array
|
|
RESAR1: LD SP,HL
|
|
JR RESLO1
|
|
;
|
|
; RESLOC - Restore local variables/arrays or DATA/ERROR status from stack
|
|
; Inputs: A = 0 if everything OK, bit0 set if DATPTR, bit1 set if ERRTRP
|
|
; Outputs: Z if nothing was restored, NZ if something was restored
|
|
; Destroys: A,B,C,D,E,H,L,H',L',IX,SP,flags
|
|
;
|
|
RESLOC: POP DE ;Return address
|
|
LD IX,0 ;To flag nothing was restored
|
|
RESLO1: POP BC ;Marker ?
|
|
LD HL,LOCCHK
|
|
OR A
|
|
SBC HL,BC
|
|
JR Z,RESLO2 ;Something to restore
|
|
OR A
|
|
JR NZ,RESLO8
|
|
LD HL,RETCHK
|
|
SBC HL,BC
|
|
JR Z,RESRET
|
|
LD HL,ARRCHK
|
|
OR A
|
|
SBC HL,BC
|
|
JR Z,RESARR
|
|
RESLO8: PUSH IX
|
|
POP HL
|
|
LD A,H
|
|
OR L
|
|
RESLO0: PUSH BC ;Put back marker
|
|
EX DE,HL
|
|
JP (HL) ;Return
|
|
;
|
|
RESLO2: POP IX ;Variable pointer
|
|
OR A
|
|
JR Z,RESLO3 ;Everything allowed
|
|
PUSH IX
|
|
POP BC
|
|
BIT 0,A
|
|
JR Z,RESLO6 ;Bit 0 set, so
|
|
LD HL,DATPTR ;test for DATPTR
|
|
SBC HL,BC
|
|
JR Z,RESLO3
|
|
RESLO6: OR A
|
|
BIT 1,A
|
|
JR Z,RESLO7 ;Bit 1 set, so
|
|
LD HL,ERRTRP ;test for ERRPTR
|
|
SBC HL,BC
|
|
JR Z,RESLO3
|
|
RESLO7: PUSH BC ;Put back pointer
|
|
LD BC,LOCCHK
|
|
JR RESLO0
|
|
;
|
|
RESLO3: POP BC ;Type / exponent
|
|
BIT 6,B
|
|
JR NZ,RESLO4 ;Array?
|
|
BIT 7,B
|
|
JR NZ,RESLO5 ;String?
|
|
POP HL
|
|
EXX
|
|
POP HL
|
|
EXX
|
|
BIT 4,B
|
|
JR NZ,RESLO1
|
|
PUSH AF
|
|
LD A,B
|
|
CALL STOREN ;Numeric
|
|
POP AF
|
|
JR RESLO1
|
|
;
|
|
RESLO4: POP HL
|
|
BIT 4,B
|
|
JR NZ,RESLO1
|
|
LD (IX+0),L ;Array
|
|
LD (IX+1),H
|
|
JR RESLO1
|
|
;
|
|
RESLO9: LD B,0
|
|
ADD HL,BC
|
|
LD SP,HL
|
|
RESLGO: JR RESLO1
|
|
;
|
|
RESLO5: LD HL,0
|
|
ADD HL,SP
|
|
BIT 4,B
|
|
JR NZ,RESLO9
|
|
PUSH AF
|
|
PUSH DE
|
|
LD E,C
|
|
LD A,B
|
|
CALL STORES ;String
|
|
POP DE
|
|
POP AF
|
|
LD SP,HL
|
|
JR RESLGO
|
|
;
|
|
;SAVLOC: SUBROUTINE TO STACK LOCAL PARAMETERS
|
|
; OF A FUNCTION OR PROCEDURE.
|
|
;THERE IS A LOT OF STACK MANIPULATION - CARE!!
|
|
; Inputs: IY is parameters pointer
|
|
; Outputs: IY updated
|
|
; A' incremented for each RETURN
|
|
; Destroys: A',A,B,C,D,E,H,L,IX,IY,F,SP
|
|
;
|
|
SAVLOC: POP DE ;RETURN ADDRESS
|
|
SAVLO1: INC IY ;BUMP PAST ( OR ,
|
|
CALL NXT
|
|
CP TRETURN
|
|
JR NZ,SAVLO6
|
|
EX AF,AF'
|
|
INC A ;RETURN counter
|
|
EX AF,AF'
|
|
INC IY ;Bump past RETURN
|
|
CALL NXT
|
|
SAVLO6: PUSH DE
|
|
EXX
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
EXX
|
|
CALL VAR ;DUMMY VARIABLE
|
|
EXX
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
EXX
|
|
POP DE
|
|
BIT 6,A ;ARRAY?
|
|
JR NZ,SAVLO3
|
|
OR A ;TYPE
|
|
JP M,SAVLO2 ;STRING
|
|
EXX
|
|
PUSH HL ;SAVE H'L'
|
|
EXX
|
|
LD B,A ;TYPE
|
|
CALL LOADN
|
|
EXX
|
|
EX (SP),HL
|
|
EXX
|
|
PUSH HL
|
|
PUSH BC
|
|
JR SAVLO4
|
|
;
|
|
SAVLO3: LD C,(IX+0) ;ARRAY POINTER
|
|
LD B,(IX+1)
|
|
PUSH BC ;SAVE TO STACK
|
|
PUSH AF ;SAVE TYPE
|
|
JR SAVLO4
|
|
;
|
|
SAVLO2: PUSH AF ;STRING TYPE
|
|
PUSH DE
|
|
EXX
|
|
PUSH HL
|
|
EXX
|
|
CALL LOADS
|
|
EXX
|
|
POP HL
|
|
EXX
|
|
LD C,E
|
|
POP DE
|
|
CALL CHECK
|
|
POP AF ;LEVEL STACK
|
|
LD HL,0
|
|
LD B,L
|
|
SBC HL,BC
|
|
ADD HL,SP
|
|
LD SP,HL
|
|
LD B,A ;TYPE
|
|
PUSH BC
|
|
JR Z,SAVLO4
|
|
PUSH DE
|
|
LD DE,ACCS
|
|
EX DE,HL
|
|
LD B,L
|
|
LDIR ;SAVE STRING ON STACK
|
|
POP DE
|
|
SAVLO4: PUSH IX ;VARPTR
|
|
CALL SAVLO5
|
|
LOCCHK EQU $
|
|
SAVLO5: CALL CHECK
|
|
CALL NXT
|
|
CP ',' ;MORE?
|
|
JR Z,SAVLO1
|
|
EX DE,HL
|
|
JP (HL) ;"RETURN"
|
|
;
|
|
TERMQ: CALL NXT
|
|
CP TELSE
|
|
RET NC
|
|
CP ':' ;ASSEMBLER SEPARATOR
|
|
RET NC
|
|
CP CR
|
|
RET
|
|
;
|
|
SPAN: CALL TERMQ
|
|
RET Z
|
|
INC IY
|
|
CP '"'
|
|
CALL Z,QUOTE
|
|
JR SPAN
|
|
;
|
|
EQUALS: CALL NXT
|
|
INC IY
|
|
CP '='
|
|
RET Z
|
|
LD A,4
|
|
JP ERROR ;"Mistake"
|
|
;
|
|
FORMAT: CP TTAB
|
|
JR Z,DOTAB
|
|
CP TSPC
|
|
JR Z,DOSPC
|
|
CP ''''
|
|
RET NZ
|
|
CALL CRLF
|
|
XOR A
|
|
RET
|
|
;
|
|
DOTAB: PUSH BC
|
|
CALL EXPRI
|
|
EXX
|
|
POP BC
|
|
LD A,(IY)
|
|
CP ','
|
|
JR Z,DOTAB1
|
|
CALL BRAKET
|
|
LD A,L
|
|
TABIT: LD HL,COUNT
|
|
CP (HL)
|
|
RET Z
|
|
PUSH AF
|
|
CALL C,CRLF
|
|
POP AF
|
|
SUB (HL)
|
|
JR SPACES
|
|
DOTAB1: INC IY
|
|
PUSH BC
|
|
PUSH HL
|
|
CALL EXPRI
|
|
EXX
|
|
POP DE
|
|
POP BC
|
|
CALL BRAKET
|
|
CALL PUTCSR
|
|
XOR A
|
|
RET
|
|
;
|
|
DOSPC: PUSH BC
|
|
CALL ITEMI
|
|
EXX
|
|
LD A,L
|
|
POP BC
|
|
SPACES: OR A
|
|
RET Z
|
|
PUSH BC
|
|
LD B,A
|
|
FILL1: LD A,' '
|
|
CALL OUTCHR
|
|
DJNZ FILL1
|
|
POP BC
|
|
XOR A
|
|
RET
|
|
;
|
|
PTEXT: LD HL,ACCS
|
|
INC E
|
|
PTEXT1: DEC E
|
|
RET Z
|
|
LD A,(HL)
|
|
INC HL
|
|
CALL OUTCHR
|
|
JR PTEXT1
|
|
;
|
|
FETCHS: PUSH AF
|
|
PUSH BC
|
|
PUSH HL
|
|
EX (SP),IY
|
|
CALL XTRACT
|
|
CALL NXT
|
|
EX (SP),IY
|
|
POP HL
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
;
|
|
LINES: LD DE,ACCS
|
|
LINE1S: LD A,(HL)
|
|
LD (DE),A
|
|
CP CR
|
|
RET Z
|
|
INC HL
|
|
INC E
|
|
JR LINE1S
|
|
;
|
|
XTRACT: CALL NXT
|
|
CP '"'
|
|
INC IY
|
|
JP Z,CONS
|
|
DEC IY
|
|
LD DE,ACCS
|
|
XTRAC1: LD A,(IY)
|
|
LD (DE),A
|
|
CP ','
|
|
RET Z
|
|
CP CR
|
|
RET Z
|
|
INC IY
|
|
INC E
|
|
JR XTRAC1
|
|
;
|
|
DSRCH: LD A,TDATA
|
|
SEARCH: LD B,0
|
|
SRCH1: LD C,(HL)
|
|
INC C
|
|
DEC C
|
|
JR Z,SRCH2 ;FAIL
|
|
INC HL
|
|
INC HL
|
|
INC HL
|
|
CP (HL)
|
|
RET Z
|
|
DEC C
|
|
DEC C
|
|
DEC C
|
|
ADD HL,BC
|
|
JP SRCH1
|
|
SRCH2: DEC HL ;POINT TO CR
|
|
SCF
|
|
RET
|
|
;
|
|
; NSCAN - scan for token at start of line, with nesting of inner structures
|
|
; Alternative entry at NSCAN1 with L = level (used by CASE)
|
|
;
|
|
; Inputs: B = token to find (1, start of line)
|
|
; C = token to find (2, start of line)
|
|
; E = token to nest (end of line)
|
|
; D = token to unnest (start of line)
|
|
; IY = start search area (line length byte)
|
|
; Outputs: NZ if not found
|
|
; Z if found, IY points to byte after token
|
|
; Destroys: A,B,C,L,IY,F
|
|
;
|
|
NSCAN: LD L,0 ;nest level
|
|
NSCAN1: LD A,(IY) ;get line length
|
|
OR A ;test zero = end of prog
|
|
JR Z,NSCAN6
|
|
LD A,(IY+3) ;initial token
|
|
CP B ;test value reqd
|
|
JR Z,NSCAN3 ;found (1)
|
|
CP C
|
|
JR Z,NSCAN3 ;found (2)
|
|
NSCAN7: CP D ;unnest?
|
|
JR Z,NSCAN5
|
|
NSCAN2: PUSH BC
|
|
LD B,0
|
|
LD C,(IY)
|
|
ADD IY,BC ;go to next line
|
|
LD A,(IY-2)
|
|
CP E ;nest?
|
|
LD A,C
|
|
POP BC
|
|
JR NZ,NSCAN1 ;continue
|
|
CP 5 ;empty line ?
|
|
JR C,NSCAN1 ;continue
|
|
INC L ;increment nest level
|
|
JR NSCAN1 ;continue
|
|
;
|
|
NSCAN3: INC L
|
|
DEC L
|
|
JR NZ,NSCAN7
|
|
NSCAN4: LD BC,4
|
|
ADD IY,BC
|
|
XOR A ;Z
|
|
RET
|
|
;
|
|
NSCAN5: DEC L ;decrement nest level
|
|
JP P,NSCAN2
|
|
JR NSCAN4
|
|
;
|
|
NSCAN6: OR 1 ;NZ
|
|
RET
|
|
;
|
|
; WSRCH - search for token, with nesting of inner structures
|
|
;
|
|
; Inputs: B = token to find or unnest (anywhere)
|
|
; C = token to nest (anywhere), ignore after EXIT
|
|
; D = ordinal (1 = find first token, 2 = second)
|
|
; IY = address to start looking
|
|
; Outputs: IY points to byte after that found
|
|
; if not found abort to END
|
|
; Destroys: A,D,IY,F
|
|
;
|
|
WSRCH: LD A,(IY)
|
|
INC IY
|
|
CP '"'
|
|
CALL Z,QUOTE
|
|
CP TREM
|
|
JR Z,WSRCHM
|
|
CP TEXIT
|
|
JR Z,WSRCHE
|
|
CP B
|
|
JR Z,WSRCHX
|
|
CP C
|
|
JR Z,WSRCHP
|
|
CP CR
|
|
JR NZ,WSRCH
|
|
WSRCH1: LD A,(IY) ;Line length
|
|
INC IY
|
|
OR A
|
|
JP Z,END
|
|
INC IY
|
|
INC IY ;Skip line number
|
|
LD A,(IY)
|
|
CP TDATA
|
|
JR NZ,WSRCH
|
|
WSRCHM: LD A,(IY)
|
|
INC IY
|
|
CP CR
|
|
JR NZ,WSRCHM ;Skip to end of line
|
|
JR WSRCH1
|
|
;
|
|
WSRCHP: INC D
|
|
JR WSRCH
|
|
;
|
|
WSRCHX: DEC D
|
|
JR NZ,WSRCH
|
|
RET
|
|
;
|
|
WSRCHE: CALL NXT
|
|
INC IY
|
|
JR WSRCH
|
|
;
|
|
; QUOTE - skip quoted string
|
|
;
|
|
QUOTE: LD A,(IY)
|
|
INC IY
|
|
CP CR
|
|
JP Z,MISQUO
|
|
CP '"'
|
|
JR NZ,QUOTE
|
|
RET
|
|
;
|
|
MISQUO: LD A,9
|
|
JP ERROR ;"Missing quote"
|
|
;
|
|
; X14OR5 - multiply by 1, 4 or 5
|
|
; Inputs: DE = number to be multiplied
|
|
; A = 1, 4 or 5 (else multiply by 4)
|
|
; Outputs: DE = DE * A
|
|
; Carry set if overflow
|
|
; Destroys: D,E,H,L,F
|
|
;
|
|
X14OR5: LD H,D
|
|
LD L,E
|
|
CP 1
|
|
RET Z
|
|
CP 5
|
|
ADD HL,HL
|
|
RET C
|
|
ADD HL,HL
|
|
RET C
|
|
EX DE,HL
|
|
RET NZ
|
|
ADD HL,DE
|
|
EX DE,HL
|
|
RET
|
|
;
|
|
; MUL16 - 16-bit multiply
|
|
; Inputs: HL = number to be multiplied
|
|
; BC = multiplier
|
|
; Outputs: HL = HL * BC
|
|
; Carry set if overflow
|
|
; Destroys: A,D,E,H,L,F
|
|
;
|
|
MUL16: EX DE,HL
|
|
LD HL,0
|
|
LD A,16
|
|
MUL161: ADD HL,HL
|
|
RET C ;OVERFLOW
|
|
SLA E
|
|
RL D
|
|
JR NC,MUL162
|
|
ADD HL,BC
|
|
RET C
|
|
MUL162: DEC A
|
|
JR NZ,MUL161
|
|
RET
|
|
;
|
|
CHANEL: CALL NXT
|
|
CP '#'
|
|
LD A,45
|
|
JP NZ,ERROR ;"Missing #"
|
|
CHNL: INC IY ;SKIP '#'
|
|
CALL ITEMI
|
|
EXX
|
|
EX DE,HL
|
|
RET
|
|
;
|
|
; FREESA - Free members of a string array if adjacent to the top of heap
|
|
; Inputs: BC = length of array (= 4 * number of elements)
|
|
; HL addresses array first byte *above* array
|
|
; Outputs: NZ if any array element freed, Z if none
|
|
; Destroys: nothing
|
|
;
|
|
FREESA: PUSH AF
|
|
FREES0: PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
XOR A
|
|
LD D,B
|
|
LD E,C
|
|
LD B,A
|
|
FREES1: PUSH DE
|
|
DEC HL
|
|
LD D,(HL)
|
|
DEC HL
|
|
LD E,(HL)
|
|
DEC HL
|
|
LD C,(HL)
|
|
DEC HL
|
|
PUSH HL
|
|
LD HL,(FREE)
|
|
EX DE,HL
|
|
ADD HL,BC
|
|
SBC HL,DE
|
|
JR NZ,FREES2
|
|
ADD HL,DE
|
|
SBC HL,BC
|
|
LD (FREE),HL
|
|
OR H
|
|
FREES2: POP DE
|
|
POP HL
|
|
LD C,4
|
|
OR A
|
|
SBC HL,BC
|
|
EX DE,HL
|
|
JR NZ,FREES1
|
|
OR A
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
OR A
|
|
JR NZ,FREES0
|
|
POP AF
|
|
RET
|
|
;
|
|
END
|
|
|