mirror of https://github.com/wwarthen/RomWBW.git
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.
551 lines
11 KiB
551 lines
11 KiB
;
|
|
; PROGRAM: VMENUCK
|
|
; AUTHOR: RICHARD CONN
|
|
; VERSION: 1.0
|
|
; DATE: 22 July 84
|
|
; PREVIOUS VERSIONS: None
|
|
; DERIVATION: MENUCK 1.0 (18 May 84)
|
|
;
|
|
VERS EQU 10 ;VERSION NUMBER
|
|
z3env SET 0f400h
|
|
|
|
;
|
|
; VMENUCK is used to check the syntax of a MENU.VMN file for the ZCPR3
|
|
; menu processor, VMENU. VMENU was optimized for size and runtime speed, and
|
|
; I tried to keep the size under 2K (and succeeded, for that matter). In
|
|
; keeping VMENU small, the error diagnostics it gives are quite limited, with
|
|
; a variety of errors producing the message "Str Err" for MENU.VMN
|
|
; structure error.
|
|
;
|
|
; VMENUCK is intended to be used to check the syntax and other features
|
|
; of a user's MENU.VMN before allowing VMENU to run with it. In this way,
|
|
; many errors may be caught before the MENU.VMN file comes into common use,
|
|
; and there is plenty of space for informative diagnostics.
|
|
;
|
|
|
|
;
|
|
; MENU Constants
|
|
;
|
|
MCMD EQU ':' ;Menu Jump Command
|
|
MINDIC EQU '#' ;Menu Indic
|
|
GOPTION EQU '-' ;Global Option Indic
|
|
XOPTION EQU 'X'
|
|
VARFLAG EQU '$' ;Variable Flag
|
|
|
|
;
|
|
; CP/M Constants
|
|
;
|
|
bentry equ 5 ;BDOS Entry
|
|
fcb equ 5ch ;FCB
|
|
tbuff equ 80h ;Temp I/O Buffer
|
|
cr equ 0dh
|
|
lf equ 0ah
|
|
EOF equ 'Z'-'@' ;^Z=EOF
|
|
|
|
;
|
|
; Externals
|
|
;
|
|
ext z3init,zfname,z3log
|
|
|
|
ext caps,crlf,eval10,retud
|
|
ext f$open,f$close,f$read
|
|
ext print,cout
|
|
ext moveb
|
|
ext phldc,padc,pfn2,pafdc
|
|
ext codend
|
|
|
|
;
|
|
; Environment Definition
|
|
;
|
|
if z3env ne 0
|
|
;
|
|
; External ZCPR3 Environment Descriptor
|
|
;
|
|
jmp start
|
|
db 'Z3ENV' ;This is a ZCPR3 Utility
|
|
db 1 ;External Environment Descriptor
|
|
z3eadr:
|
|
dw z3env
|
|
start:
|
|
lhld z3eadr ;pt to ZCPR3 environment
|
|
;
|
|
else
|
|
;
|
|
; Internal ZCPR3 Environment Descriptor
|
|
;
|
|
MACLIB Z3BASE.LIB
|
|
MACLIB SYSENV.LIB
|
|
z3eadr:
|
|
jmp start
|
|
SYSENV
|
|
start:
|
|
lxi h,z3eadr ;pt to ZCPR3 environment
|
|
endif
|
|
|
|
;
|
|
; Start of Program -- Initialize ZCPR3 Environment
|
|
;
|
|
call z3init ;initialize the ZCPR3 Env and the VLIB Env
|
|
|
|
call print
|
|
db 'VMENUCK Version '
|
|
db (vers/10)+'0','.',(vers mod 10)+'0',0
|
|
|
|
lda fcb+1 ;get first char
|
|
cpi ' ' ;no file name?
|
|
jz help
|
|
cpi '/' ;option?
|
|
jnz start1
|
|
;
|
|
; Print Help Message
|
|
;
|
|
help:
|
|
call print
|
|
db cr,lf,'Syntax:'
|
|
db cr,lf,' VMENUCK dir:filename.typ <-- Check File'
|
|
db cr,lf,' VMENUCK dir:filename <-- Check filename.VMN'
|
|
db 0
|
|
ret
|
|
|
|
;
|
|
; Begin serious processing -- locate the file pted to by HL
|
|
;
|
|
start1:
|
|
lxi d,fcb ;pt to FCB
|
|
call z3log ;log into indicated FCB
|
|
|
|
;
|
|
; Set File Type to MNU if not specified
|
|
;
|
|
start2:
|
|
lxi h,fcb+9 ;pt to file type
|
|
mov a,m ;get first char
|
|
cpi ' ' ;set type if <SP>
|
|
jnz start3
|
|
push b ;save BC
|
|
lxi d,mnutyp ;set type to MNU
|
|
xchg
|
|
mvi b,3 ;3 bytes
|
|
call moveb
|
|
pop b ;get BC
|
|
;
|
|
; Try to Open the File
|
|
;
|
|
start3:
|
|
lxi d,fcb ;prepare to open file
|
|
xra a ;A=0 to select current disk
|
|
stax d
|
|
call f$open ;open file
|
|
jz readfile ;read in file if OK
|
|
call print
|
|
db cr,lf,' File Not Found',0
|
|
ret
|
|
;
|
|
; Read in File
|
|
;
|
|
readfile:
|
|
call codend ;get address of first block
|
|
readloop:
|
|
lxi d,fcb ;read block
|
|
call f$read ;do it
|
|
ora a ;check for error
|
|
jnz readdone
|
|
lxi d,tbuff ;pt to block just read in
|
|
mvi b,128 ;128 bytes
|
|
readmove:
|
|
ldax d ;get byte
|
|
ani 7fh ;mask MSB
|
|
mov m,a ;put byte
|
|
inx h ;pt to next
|
|
inx d
|
|
dcr b ;count down
|
|
jnz readmove
|
|
xchg ;DE pts to next block
|
|
lhld bentry+1 ;get address of BDOS
|
|
mov a,h ;check for possible overflow
|
|
sui 10 ;10 pages below BDOS is limit
|
|
cmp d ;within range?
|
|
xchg ;HL pts to next block
|
|
jnc readloop ;continue read if within range
|
|
call print
|
|
db cr,lf,' TPA Overflow -- VMENU File is Too Big',0
|
|
ret
|
|
;
|
|
; Read is Done -- Store Ending ^Z and Set Initial Values
|
|
;
|
|
readdone:
|
|
mvi m,EOF ;Store ^Z to ensure EOF
|
|
lxi d,fcb ;Close File
|
|
call f$close
|
|
mvi a,0ffh ;A = -1
|
|
sta menunum ;set menu number
|
|
sta maxnum ;set max number of all menus
|
|
lxi h,0 ;HL=0
|
|
shld errors ;Set Error Count to 0
|
|
inx h ;HL=1
|
|
shld linenum ;Set Line Number to 1
|
|
;
|
|
; Count Number of Menus
|
|
;
|
|
call codend ;Pt to First Byte
|
|
mov a,m ;get first byte
|
|
;
|
|
; Skip to Beginning of Menu Display
|
|
;
|
|
mdskip:
|
|
cpi EOF ;EOF?
|
|
jz mdone
|
|
cpi MINDIC ;beginning of display?
|
|
jz mcgo ;now go skip commands
|
|
call lskip ;skip to next line
|
|
jmp mdskip
|
|
mcgo:
|
|
inx h ;pt to char after MINDIC
|
|
mov a,m ;another MINDIC?
|
|
cpi MINDIC
|
|
jz mdone ;done if 2 in a row
|
|
lda maxnum ;get menu number count
|
|
inr a ;found another one
|
|
sta maxnum
|
|
mcskip:
|
|
call lskip ;skip to next line
|
|
jz mdone ;done if premature EOF
|
|
cpi MINDIC ;end of display?
|
|
jnz mcskip
|
|
inx h ;pt to char after MINDIC
|
|
mov a,m ;get it
|
|
jmp mdskip
|
|
;
|
|
; Check for Valid First Character
|
|
;
|
|
mdone:
|
|
call print
|
|
db cr,lf,'VMenu Syntax Check on ',0
|
|
call retud ;get dir
|
|
mov a,b ;get disk
|
|
adi 'A'
|
|
call cout
|
|
mov a,c ;get user
|
|
call pafdc
|
|
mvi a,':'
|
|
call cout
|
|
lxi d,fcb+1 ;pt to FCB
|
|
call pfn2
|
|
call print ;Print Header
|
|
db cr,lf
|
|
db cr,lf,' Line Comment/Error Message'
|
|
db cr,lf,' ---- ---------------------',0
|
|
|
|
xra a ;set no global option
|
|
sta gopt
|
|
call codend ;get address of first byte
|
|
mov a,m ;get first char
|
|
cpi GOPTION ;global options?
|
|
jnz newmenu ;process globals
|
|
mvi a,0ffh ;set global option
|
|
sta gopt
|
|
call lprint
|
|
db '** Global Options Detected **',0
|
|
call optchk ;check options
|
|
xra a ;set no global option
|
|
sta gopt
|
|
call nxtline ;advance to next line
|
|
;
|
|
; This is the main entry point for processing a menu
|
|
;
|
|
newmenu:
|
|
mov a,m ;get Menu Indicator
|
|
cpi MINDIC ;must be MINDIC
|
|
jz nm1
|
|
call newerr ;add to error count
|
|
call lprint
|
|
db ' New Menu Expected, But ',MINDIC,' NOT Found -- '
|
|
db 'Aborting',0
|
|
jmp errxit
|
|
;
|
|
; Print that we have a new menu
|
|
;
|
|
nm1:
|
|
call lprint
|
|
db '** Menu Number ',0
|
|
lda menunum ;increment menu number
|
|
inr a
|
|
sta menunum
|
|
call padc
|
|
call optchk ;check options
|
|
;
|
|
; Skip Thru Display
|
|
;
|
|
nm2:
|
|
call nxtline ;skip to next line
|
|
jnz nm2a ;continue if no EOF
|
|
earlyeof:
|
|
call newerr ;add to error count
|
|
call lprint
|
|
db ' Premature EOF Encountered',0
|
|
jmp errxit
|
|
nm2a:
|
|
cpi MINDIC ;Menu Indicator?
|
|
jnz nm2 ;Continue
|
|
;
|
|
; Move Thru Menu Commands
|
|
;
|
|
nm3:
|
|
call mcmd1 ;check Menu Command Line
|
|
jz earlyeof
|
|
call lcheck ;check line
|
|
cpi MINDIC ;check for menu indicator
|
|
jnz nm3 ;continue until menu indicator encountered
|
|
inx h ;check for 2 indicators in a row for end
|
|
mov a,m ;get 2nd char
|
|
dcx h ;back up in case it is not
|
|
cpi MINDIC ;2 in a row?
|
|
jnz newmenu ;process as new menu if not
|
|
errxit:
|
|
call lprint
|
|
db '** End of Menu Check **',cr,lf,' ',0
|
|
lhld errors ;check error count
|
|
mov a,h ;check for Zero
|
|
ora l
|
|
jnz err1
|
|
call print
|
|
db 'No',0
|
|
jmp err2
|
|
err1:
|
|
call phldc ;print as decimal
|
|
err2:
|
|
call print
|
|
db ' Errors Detected',0
|
|
ret
|
|
|
|
;
|
|
; Utilities
|
|
;
|
|
|
|
;
|
|
; LPRINT -- Print "Line # "+text
|
|
;
|
|
lprint:
|
|
call crlf ;new line
|
|
push h ;save HL
|
|
lhld linenum ;get line number
|
|
call phldc ;print as decimal
|
|
pop h ;restore HL
|
|
mvi a,' ' ;print <sp>
|
|
call cout
|
|
jmp print ;print text
|
|
;
|
|
; NXTLINE -- Advance to next line, check for EOF, and increment Line Number
|
|
; LSKIP -- Advance to next line and check for EOF
|
|
; Return with HL pting to first char of next line and Z Set if EOF
|
|
;
|
|
nxtline:
|
|
push h ;increment line count
|
|
lhld linenum ;add 1
|
|
inx h
|
|
shld linenum
|
|
pop h ;fall thru to skipping
|
|
lskip:
|
|
mov a,m ;get char
|
|
cpi EOF ;EOF?
|
|
rz
|
|
inx h ;pt to next
|
|
cpi lf ;line feed?
|
|
jnz lskip ;continue if not
|
|
mov a,m ;get first char of next line
|
|
cpi EOF ;check for EOF
|
|
ret
|
|
;
|
|
; MCMD1 -- Check Menu Line, check for EOF, and increment Line Number
|
|
; Return with HL pting to first char of next line and Z Set if EOF
|
|
;
|
|
mcmd1:
|
|
mov a,m ;get char
|
|
cpi EOF ;EOF?
|
|
jz mcmdx
|
|
inx h ;pt to next
|
|
cpi VARFLAG ;variable?
|
|
jz mcmd2
|
|
cpi lf ;line feed?
|
|
jnz mcmd1 ;continue if not
|
|
mcmdx:
|
|
push h ;increment line count
|
|
lhld linenum ;add 1
|
|
inx h
|
|
shld linenum
|
|
pop h ;fall thru to skipping
|
|
mov a,m ;get first char of next line
|
|
cpi EOF ;check for EOF
|
|
ret
|
|
;
|
|
; Check Variable
|
|
;
|
|
mcmd2:
|
|
mov a,m ;get char
|
|
ani 7fh ;mask
|
|
call caps ;capitalize
|
|
inx h ;pt to next
|
|
cpi VARFLAG ;OK if double VARFLAG
|
|
jz mcmd1
|
|
cpi 'D' ;OK if D
|
|
jz mcmd1
|
|
cpi 'U' ;OK if U
|
|
jz mcmd1
|
|
cpi 'F' ;filename.typ?
|
|
jz mcmd3
|
|
cpi 'N' ;filename?
|
|
jz mcmd3
|
|
cpi 'T' ;filetype?
|
|
jz mcmd3
|
|
cpi 'P' ;pointed-to file?
|
|
jz mcmd6
|
|
;
|
|
; Invalid Variable
|
|
;
|
|
dcx h ;pt to previous (bad char)
|
|
push psw ;save char
|
|
call lprint
|
|
db ' Variable Error (Not $, D, U, F, N, or T) - ',0
|
|
pop psw ;get char
|
|
call cout ;print it
|
|
call newerr ;increment error count
|
|
jmp mcmd1
|
|
;
|
|
; Digit from 1 to 4 should follow
|
|
;
|
|
mcmd3:
|
|
mov a,m ;get next char
|
|
inx h ;pt to next
|
|
ani 7fh ;mask and cap
|
|
call caps
|
|
cpi '1' ;must be from 1 to 4
|
|
jc mcmd4
|
|
cpi '5'
|
|
jc mcmd1
|
|
;
|
|
; Invalid Digit
|
|
;
|
|
mcmd4:
|
|
push psw
|
|
call lprint
|
|
db ' Invalid Digit for F, N, or T Variable (not 1-4) - ',0
|
|
mcmd5:
|
|
pop psw
|
|
dcx h ;pt to invalid char
|
|
call cout
|
|
call newerr ;increment error count
|
|
jmp mcmd1
|
|
|
|
;
|
|
; Check for Pointed to File
|
|
;
|
|
mcmd6:
|
|
mov a,m ;get next char
|
|
inx h ;pt to next
|
|
ani 7fh ;mask
|
|
call caps
|
|
cpi 'F'
|
|
jz mcmd1
|
|
cpi 'N'
|
|
jz mcmd1
|
|
cpi 'T'
|
|
jz mcmd1
|
|
push psw ;save char
|
|
call lprint
|
|
db ' Invalid Pointed-to File Option (not F, N, or T) - ',0
|
|
jmp mcmd5 ;process error and back up ptr
|
|
|
|
;
|
|
; OPTCHK -- Check Line Pted to by HL for Valid GOPTION and MINDIC options
|
|
; Do Not Affect HL
|
|
; Print Error Message and Character if Invalid Option Found
|
|
;
|
|
optchk:
|
|
push h ;save HL
|
|
push b
|
|
inx h ;skip indicator
|
|
optclp:
|
|
mov a,m ;get char
|
|
call caps ;capitalize
|
|
inx h ;pt to next
|
|
cpi cr ;EOL?
|
|
jz optcdn
|
|
mov b,a ;char in B
|
|
cpi XOPTION ;only exit option allowed
|
|
jz optclp
|
|
call newerr ;increment error count
|
|
call lprint
|
|
db ' Invalid Option: ',0
|
|
mov a,b ;get char
|
|
call cout ;print char
|
|
jmp optclp
|
|
optcdn:
|
|
pop b
|
|
pop h ;restore ptr
|
|
ret
|
|
;
|
|
; Increment Error Count
|
|
;
|
|
newerr:
|
|
push h ;save HL
|
|
lhld errors ;increment error count
|
|
inx h
|
|
shld errors
|
|
pop h ;restore HL
|
|
ret
|
|
;
|
|
; Check Line, especially looking for Menu Jump
|
|
;
|
|
lcheck:
|
|
push h ;save ptr to first char
|
|
inx h ;pt to 2nd char
|
|
mov a,m ;get it
|
|
cpi MCMD ;menu jump?
|
|
jnz lchk1
|
|
inx h ;pt to menu number
|
|
call eval10 ;convert to binary in DE
|
|
mov a,d ;D must be 0
|
|
ora a ;check
|
|
jz lchk0
|
|
lchker:
|
|
call newerr ;increment error count
|
|
call lprint
|
|
db ' Menu Number Out of Range',0
|
|
jmp lchk1
|
|
lchk0:
|
|
lda maxnum ;get max menu number
|
|
cmp e ;check for range
|
|
jc lchker
|
|
lchk1:
|
|
pop h ;restore ptr
|
|
mov a,m ;get first char in line
|
|
ret
|
|
;
|
|
; Skip HL over Blanks
|
|
;
|
|
sblank:
|
|
mov a,m ;get char
|
|
inx h ;pt to next
|
|
cpi ' ' ;blank?
|
|
jz sblank ;continue skipping
|
|
dcx h ;pt to non-blank
|
|
ret
|
|
|
|
;
|
|
; Buffers
|
|
;
|
|
mnutyp:
|
|
db 'VMN'
|
|
errors:
|
|
ds 2 ;error count
|
|
linenum:
|
|
ds 2 ;current line number
|
|
menunum:
|
|
ds 1 ;current menu number
|
|
maxnum:
|
|
ds 1 ;max menu number
|
|
gopt:
|
|
ds 1 ;global option flag
|
|
|
|
end
|
|
|