mirror of
https://github.com/Tolik-Trek/Estex-DSS.git
synced 2026-06-15 09:21:47 +03:00
242 lines
4.8 KiB
NASM
242 lines
4.8 KiB
NASM
;///////////////////////////////////////////////////
|
|
;
|
|
; IF - conditional command (MS-DOS style)
|
|
;
|
|
; IF [NOT] ERRORLEVEL number command
|
|
; IF [NOT] EXIST filename command
|
|
; IF [NOT] string1 == string2 command
|
|
;
|
|
; If the condition is true, the rest of the line is
|
|
; executed as an ordinary command (GOTO, ECHO, a
|
|
; program, another IF, ...).
|
|
;
|
|
;///////////////////////////////////////////////////
|
|
|
|
; in: de -> argument string (everything after "IF ")
|
|
cmd_if:
|
|
ex de,hl ; hl -> args
|
|
xor a
|
|
ld (.neg),a
|
|
call IF_SKIPB ; skip leading blanks
|
|
; --- optional NOT ---
|
|
ld de,.kw_not
|
|
call IF_KW
|
|
jr nc,.noNOT
|
|
ld a,1
|
|
ld (.neg),a
|
|
.noNOT:
|
|
; --- ERRORLEVEL n ? ---
|
|
ld de,.kw_errlvl
|
|
call IF_KW
|
|
jr nc,.notErr
|
|
ld de,Buffers.work.buffer1
|
|
ld c,Dss.GSwitch ; extract the number token
|
|
RST ToDSS
|
|
ld (.cmd),hl ; rest of line = command part
|
|
ld de,Buffers.work.buffer1
|
|
call IF_ATOI8 ; a = number (0..255)
|
|
ld b,a ; b = threshold
|
|
ld c,Dss.Get_Err ; a = exit code of last program
|
|
RST ToDSS
|
|
cp b ; A >= n ? (NC = yes)
|
|
ld a,0
|
|
jr c,.decide ; A < n -> false
|
|
inc a ; true
|
|
jr .decide
|
|
.notErr:
|
|
; --- EXIST filename ? ---
|
|
ld de,.kw_exist
|
|
call IF_KW
|
|
jr nc,.strcmp
|
|
ld de,Buffers.work.buffer1
|
|
ld c,Dss.GSwitch ; extract the filename token
|
|
RST ToDSS
|
|
ld (.cmd),hl ; rest of line = command part
|
|
ld a,FAT_ATTR.NoVolID ; any file/dir (not the volume label)
|
|
ld hl,Buffers.work.buffer1 ; filespec (NUL-term DOS name)
|
|
ld de,Buffers.work.buffer2 ; F_First work buffer
|
|
ld bc,Dss.F_First.DOSname ; B=1, C=#19
|
|
RST ToDSS
|
|
ld a,0
|
|
jr c,.decide ; CF=1 -> not found -> false
|
|
inc a ; exists -> true
|
|
jr .decide
|
|
.strcmp:
|
|
; hl -> string1 "==" string2 [blank] command
|
|
push hl ; s1 start
|
|
.find: ld a,(hl)
|
|
or a
|
|
jr z,.bad ; no "==" -> malformed
|
|
cp "="
|
|
jr nz,.fnext
|
|
inc hl
|
|
ld a,(hl)
|
|
cp "="
|
|
jr z,.foundEq
|
|
dec hl
|
|
.fnext: inc hl
|
|
jr .find
|
|
.bad: pop hl
|
|
ret ; syntax error -> no-op
|
|
.foundEq:
|
|
dec hl ; hl -> first '=' of "=="
|
|
pop de ; de = s1 start
|
|
push de
|
|
or a
|
|
sbc hl,de ; hl = len1 (line < 256 -> h=0)
|
|
ld a,l
|
|
ld (.len1),a
|
|
pop de ; de = s1 start
|
|
ld hl,0
|
|
ld l,a
|
|
add hl,de ; hl = s1 + len1 = first '='
|
|
inc hl
|
|
inc hl ; hl = s2 start
|
|
ld (.s2),hl
|
|
ld b,0 ; len2
|
|
.s2l: ld a,(hl)
|
|
cp " "+1 ; <=' ' (space/tab/CR/0) -> token end
|
|
jr c,.s2e
|
|
inc hl
|
|
inc b
|
|
jr .s2l
|
|
.s2e: ld (.cmd),hl ; command part starts here
|
|
ld a,(.len1)
|
|
cp b ; len1 == len2 ?
|
|
jr nz,.neq
|
|
or a
|
|
jr z,.eq ; both empty -> equal
|
|
ld c,a ; c = length
|
|
ld hl,(.s2)
|
|
.cl: ld a,(de) ; de = s1
|
|
cp (hl) ; case-sensitive (MS-DOS)
|
|
jr nz,.neq
|
|
inc de
|
|
inc hl
|
|
dec c
|
|
jr nz,.cl
|
|
.eq: ld a,1
|
|
jr .decide
|
|
.neq: xor a
|
|
;
|
|
.decide:
|
|
; a = raw condition (0/1)
|
|
ld b,a
|
|
ld a,(.neg)
|
|
xor b ; cond ^ NOT
|
|
and 1
|
|
ret z ; false -> nothing to do
|
|
ld hl,(.cmd)
|
|
jp IF_RUN ; true -> run the command part
|
|
;
|
|
.kw_not: db "NOT",0
|
|
.kw_errlvl: db "ERRORLEVEL",0
|
|
.kw_exist: db "EXIST",0
|
|
.neg: db 0
|
|
.cmd: dw 0
|
|
.len1: db 0
|
|
.s2: dw 0
|
|
|
|
;-------------------------------------------------
|
|
; Skip blanks (space / TAB) at (hl)
|
|
;-------------------------------------------------
|
|
IF_SKIPB:
|
|
.l: ld a,(hl)
|
|
cp " "
|
|
jr z,.i
|
|
cp "\t"
|
|
ret nz
|
|
.i: inc hl
|
|
jr .l
|
|
|
|
;-------------------------------------------------
|
|
; Case-insensitive keyword test.
|
|
; in: hl -> text, de -> keyword (UPPER, 0-term)
|
|
; out: CF=1 - matched, hl past keyword + blanks
|
|
; CF=0 - no match, hl unchanged
|
|
;-------------------------------------------------
|
|
IF_KW: push hl
|
|
.l: ld a,(de)
|
|
or a
|
|
jr z,.kend ; keyword consumed
|
|
ld c,a
|
|
ld a,(hl)
|
|
call COMPARE.cmp_AZ ; -> upper
|
|
cp c
|
|
jr nz,.no
|
|
inc hl
|
|
inc de
|
|
jr .l
|
|
.kend: ld a,(hl) ; must be a blank delimiter
|
|
cp " "
|
|
jr z,.ok
|
|
cp "\t"
|
|
jr z,.ok
|
|
.no: pop hl ; restore, no match
|
|
or a ; CF=0
|
|
ret
|
|
.ok: inc hl ; skip delimiter + following blanks
|
|
.ok2: ld a,(hl)
|
|
cp " "
|
|
jr z,.oki
|
|
cp "\t"
|
|
jr nz,.done
|
|
.oki: inc hl
|
|
jr .ok2
|
|
.done: pop bc ; discard saved hl
|
|
scf
|
|
ret
|
|
|
|
;-------------------------------------------------
|
|
; ASCII decimal -> A (0..255, saturating)
|
|
; in: de -> digits
|
|
;-------------------------------------------------
|
|
IF_ATOI8:
|
|
ld hl,0
|
|
.l: ld a,(de)
|
|
sub "0"
|
|
jr c,.end
|
|
cp 10
|
|
jr nc,.end
|
|
ld c,a ; c = digit
|
|
ld b,0
|
|
push de
|
|
ld d,h
|
|
ld e,l
|
|
add hl,hl ; *2
|
|
add hl,hl ; *4
|
|
add hl,de ; *5
|
|
add hl,hl ; *10
|
|
add hl,bc ; + digit
|
|
pop de
|
|
inc de
|
|
jr .l
|
|
.end: ld a,h
|
|
or a
|
|
jr nz,.sat
|
|
ld a,l
|
|
ret
|
|
.sat: ld a,255
|
|
ret
|
|
|
|
;-------------------------------------------------
|
|
; Run the conditional command.
|
|
; in: hl -> command text (NUL-term at line end)
|
|
;-------------------------------------------------
|
|
IF_RUN:
|
|
call IF_SKIPB
|
|
ld a,(hl)
|
|
or a
|
|
ret z ; empty -> no-op
|
|
ld d,h
|
|
ld e,l ; de = command start
|
|
ld bc,0 ; b=0, c = token length
|
|
.tl: ld a,(hl)
|
|
cp " "+1 ; <=' ' -> end of command token
|
|
jr c,.tle
|
|
inc hl
|
|
inc c
|
|
jr .tl
|
|
.tle: ld hl,BATLIST ; bat + dos commands
|
|
jp COMP.start ; dispatch (recurses for nested IF)
|