
%if 0

lDebug IF commands (conditional control flow)

Copyright (C) 2008-2025 E. C. Masloch

Usage of the works is permitted provided that this
instrument is retained with the works, so that any entity
that uses the works is notified of this instrument.

DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.

%endif


%if _INPUT_FILE_HANDLES || _INPUT_FILE_BOOT
if_exists_check:
	push ss
	pop es
	mov di, word [if_exists_si]
	mov cx, word [if_exists_length]
	mov si, word [if_exists_sp]
	rep movsb
	mov cx, word [if_exists_length]
	inc cx
	and cl, ~1

	mov si, word [if_exists_then_address]
	test si, si
	jz .error
	dec si
	mov dx, msg.then
	call isstring?
	jne .error
	retn

.error:
	mov ax, 0149h
	call setrc
	jmp error

if_exists_not_found:
	call if_exists_check
	testopt [internalflags3], dif3_if_not
	jnz if_exists_condition_met
if_exists_condition_not_met:
	jmp cmd3

if_exists_found_open:
	push ss
	pop es
	call getline_close_file

if_exists_found_closed:
	call if_exists_check
	testopt [internalflags3], dif3_if_not
	jnz if_exists_condition_not_met
if_exists_condition_met:
	mov sp, word [if_exists_sp]
	add sp, cx
	call skipcomma
	pop dx				; discard near return address
	clropt [internalflags3], dif3_in_if | dif3_auxbuff_guarded_1
	jmp cmd3_injected
%endif


		; IF command -- conditional
ii:
	mov dx, si
	push ax
	mov ax, [si - 2]
	and ax, TOUPPER_W
	cmp ax, "IF"
	pop ax
	jne .not_if

	call skipcomma
	nearcall isoperator?
	jne .if
	mov bx, cx
	add bx, bx			; bh = 0 !
	push ax
	nearcall ..@call_operator_dispatchers
	pop ax
	test bx, bx
	jnz .not_if
	call skipcomma
.if:
	clropt [internalflags3], dif3_if_not
	dec si
	mov dx, msg.not
	call isstring?
	lodsb
	jne @F
	call skipcomm0
	setopt [internalflags3], dif3_if_not

@@:
%if _INPUT_FILE_HANDLES || _INPUT_FILE_BOOT
	dec si
	mov dx, msg.exists
	call isstring?
	lodsb
	jne .if_numeric
	call skipcomm0
	dec si
	mov dx, msg.r
	call isstring?
	je .is_variable
	mov dx, msg.y
	call isstring?
	jne error
	call skipcomma

	dec si
	mov word [if_exists_si], si
	mov bx, si
@@:
	lodsb
	call iseol?.notsemicolon
	jne @B
	mov cx, si		; -> after EOL byte
	sub cx, bx		; = length including EOL
	mov word [if_exists_length], cx
	inc cx			; round up
	and cl, ~1		; make even
	sub sp, cx
	mov word [if_exists_sp], sp
	mov di, sp
	mov si, bx
	shr cx, 1
	rep movsw

	mov si, bx
	lodsb
	and word [if_exists_then_address], 0
	setopt [internalflags3], dif3_in_if
	call yy
	jmp error
%endif

.if_numeric:
	nearcall getexpression
	nearcall toboolean
	call skipcomm0
	mov bx, dx
.if_bx:
 	mov dx, msg.then
	dec si
	call isstring?
	jne error
.if_bx_after_then:
	call skipcomma
	testopt [internalflags3], dif3_if_not
	jz @F
	xor bl, 1
@@:
	test bx, bx
	jz .if_false
	pop bx			; discard near return address to cmd3
	jmp cmd3_injected	; execute tail

.if_false:
	jmp resetrc


.is_variable:
	call skipcomma
	push si
	nearcall isvariable?
	pop di			; - 1 -> start of candidate variable name
	jc .skipvariablename	; not valid, go to skip --> (si unchanged)

	mov bx, 1		; prepare valid variable return
	dec si
	call skipcomma
 	mov dx, msg.then
	dec si
	call isstring?		; keyword as expected ?
	je .if_bx_after_then	; yes, handle THEN command -->
	mov si, di		; reset - 1 -> start of name

.skipvariablename:
	dec si			; -> start of name
@@:
	lodsb
	cmp al, 32		; end of name ?
	je @F
	cmp al, 9
	je @F
	cmp al, ','
	je @F
	call iseol?
	je @F			; yes -->
	cmp al, '('		; parens (index expression) ?
	jne @B			; no, loop -->
	call skipwhite
	nearcall getexpression	; parse index expression (must be valid)
	cmp al, ')'		; closing parens ?
	jne error		; no, error -->
	jmp @B			; loop -->

@@:
	xor bx, bx		; prepare invalid variable return
.if_bx_comma:
	dec si
	call skipcomma
	jmp .if_bx		; check for the THEN keyword -->
