; ==================== source-file :_nd_search.asm ===================
;
; This source-code is part of the:
; "32-bit Assembly Language and 'C' Extensions for Visual Prolog"
;
;          ( Copyright: See the comment at the end of this file. )
;
COMMENT ~
; Purpose: non-deterministic search for a character, sub-string or sub-binary,
;   inside a string or a binary.

;   Produces all the positions where a certain character or  sub-string or sub-
;   binary is found inside a string or a binary at each non-deterministic call;
;   it then fails, after all positions have been found.
;
; NOTE: Can be called with "findall/3", to find ALL the positions where a
;    char, sub-string, or sub-binary is located, inside a string or a binary.


    IDEAL
P586
    MODEL    FLAT

    DATASEG
ALIGN 4
    extrn    ctb:dword

    CODESEG
ALIGN 4
; ======= first two variants deal with strings only (most common):
    public _nd_search_0    ;(STRING,CHAR,posx)
    public _nd_search_1    ;(STRING,STRING,posx)

; ======= next three variants deal with binaries:
    public _nd_search_2    ;(BINARY,CHAR,posx)
    public _nd_search_3    ;(BINARY,STRING,posx)
    public _nd_search_4    ;(BINARY,BINARY,posx)

; ======= next two variants accept an "initial position"(arg 3):
    public _nd_search_5    ;(STRING,CHAR,inpos,posx)
    public _nd_search_6    ;(STRING,STRING,inpos,posx)

; ======= next three variants deal with binaries, accepting "initial position"(arg 3):
    public _nd_search_7    ;(BINARY,CHAR,inpos,posx)
    public _nd_search_8    ;(BINARY,STRING,inpos,posx)
    public _nd_search_9    ;(BINARY,BINARY,inpos,posx)

; ======= next two variants take a "case char-table"(arg 4), and init_pos(arg 3):
    public _nd_search_10    ;(STRING,CHAR,inpos,case,posx)
    public _nd_search_11    ;(STRING,STRING,inpos,case,posx)

; ======= next 3 variants take "case" and "initial position" but deal with binaries:
    public _nd_search_12    ;(BINARY,CHAR,inpos,case,posx)
    public _nd_search_13    ;(BINARY,STRING,inpos,case,posx)
    public _nd_search_14    ;(BINARY,BINARY,inpos,case,posx)
   
Macro pushx3   
    push    esi
    push    edi
    push    ebx
    endm

Macro popx3   
    pop    ebx
    pop    edi
    pop    esi
    ret
    endm

    extrn    _MEM_AllocGStack:near
    extrn    _MEM_AdjustGStackAlloc:near
    extrn    _RUN_Fail:near
    extrn    _RUN_JmpReturn:near
    extrn    _RUN_StackBTrack:near
    extrn    _RUN_JmpReturn1:near
    extrn    _MEM_MakeBinaryGStack:near


PROC _nd_search_0 near        ; (STRING,CHAR,UNSIGNED) -(i,i,o)
ENTER    12,0            ;
ARG    strg1:dword,char1:byte,outpx:dword
    pushx3
    mov esi,[strg1]  ; string input.............. ARG-1(input)
    mov [ebp-8], esi ;
    mov ah,[char1]   ; char ..................... ARG-2(input)
    mov [ebp-4], eax ;
; -------------------
@@LP0:
    mov eax,[ebp-4]  ;

@@LP0a:   
    lodsb            ;

    cmp    al,ah     ;
    jz    @@ok1      ;
    or    al,al      ;
    jz    @@XZ1      ; if zero, fail at end of string
    jmp    @@LP0a    ; else repeat THIS loop
; =========================
@@ok1:
    mov    [ebp-8],esi    ; store it

    call _RUN_StackBTrack ; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax         ; is the result (of StackBTrack) zero?
    jne    @@LP0          ; if not, read more...
; -------------------------
    mov    eax,esi        ; return right_hand_side string (after the char)
    mov    ecx,eax        ;
    mov ebx,[strg1]       ; string input.............. ARG-1(input)
    sub    ecx,ebx        ;
    mov edx,[outpx]       ; give Position of Char .... ARG-3(output)
    mov    [edx],ecx      ;
    call _RUN_JmpReturn1  ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    jmp    @@LP0          ; repeat big loop
; =========================
@@XZ1:    call _RUN_Fail  ; FAIL
    popx3
LEAVE
ENDP _nd_search_0


PROC _nd_search_1 near    ;  (STRING,STRING,POSITION) -(i,i,o)
ENTER    16,0    ;
ARG    strg1:dword,substr:dword,outpx:dword
    pushx3
    mov edi,[substr]     ; substring................ ARG-2(input)
    cmp [byte ptr edi],0 ; special case of substr=""?
    jnz    @@Laa         ; if not so, normal processing
; ------------------------
    jmp    @@XZ1         ; else, fail
    mov    edi,[strg1]   ;
    xor    eax,eax       ;
    mov    ecx,eax       ;
    not    ecx           ;
    repne    scasb       ;
    not    ecx           ;
    mov     edx,[outpx]  ; give Position of substring.... ARG-3(output)
    mov    [edx],ecx     ;
    jmp    @@XZ2         ;
; ========================
@@Laa:    mov esi,[strg1]; string input..............ARG-1(input)
    mov    [ebp-8], esi  ;
    mov    [ebp-4], edi  ;
@@LP0:   
    mov    edi,[ebp-4]   ;

    mov ah,[byte ptr edi]; first char of substring in AH
@@LP0a:    lodsb         ;
    cmp    al,ah         ;
    jz    @@ok1          ;
    or    al,al          ;
    jz    @@XZ1          ; if zero, fail at end of string
    jmp    @@LP0a        ; else repeat THIS loop
; ========================
@@ok1:    push    esi    ;
@@ok2:     inc    edi    ;
     lodsb               ;
     cmp    al,[byte ptr edi]
     jz    @@ok2         ;
     mov    al,[byte ptr edi]
     or    al,al         ;
     jz    @@ok3         ;
    pop    esi           ;
    jmp    @@LP0         ;
@@ok3:
     mov    ebx,esi      ;

    pop    esi           ;
    mov    [ebp-8],esi   ; store esi
    mov    [ebp-12],ebx  ; store right_hand_string after the substring
    call _RUN_StackBTrack; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]   ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0         ; if not, read more...
; ------------------------
@@ZZ:
    mov    eax,[ebp-12]  ; return right_hand_side string (after the char)

    mov    ecx,esi       ;
    mov ebx,[strg1]      ; string input.................. ARG-1(input)
    sub    ecx,ebx       ;
    mov edx,[outpx]      ; give Position of substring.... ARG-3(output)
    mov    [edx],ecx     ;
    call _RUN_JmpReturn1 ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]   ;
    jmp    @@LP0         ; repeat big loop
; ========================
@@XZ1:    call _RUN_Fail ; FAIL
@@XZ2:    popx3
LEAVE
ENDP _nd_search_1


PROC _nd_search_2 near   ; (BINARY,CHAR,UNSIGNED) -(i,i,o)
ENTER    16,0            ;
ARG    binary:dword,char1:byte,outpx:dword
    pushx3
    mov esi,[binary]    ; binary input.............. ARG-1(input)
    mov ecx,[dword ptr esi-4]    ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    mov [ebp-8], esi    ;
    mov ah,[char1]        ; char ..................... ARG-2(input)
    mov [ebp-4], eax    ;
    mov [ebp-12],ecx    ;
@@LP0:    mov    eax,[ebp-4]    ;
    mov    ecx,[ebp-12]    ;
@@LP0a:    lodsb            ;
    cmp    al,ah        ;
    jz    @@ok1        ;
    or    al,al        ;
    jz    @@XZ1        ; if zero, fail at end of string
    jmp    @@LP0a        ; else repeat THIS loop
; ===============================
@@ok1:    mov    [ebp-8],esi    ; store it
    mov [ebp-12],ecx    ;
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
    mov    eax,esi        ; return right_hand_side string (after the char)
    mov    ecx,eax        ;
    mov ebx,[binary]        ; string input.............. ARG-1(input)
    sub    ecx,ebx        ;
    dec    ecx        ; binaries start at zero   
    mov edx,[outpx]        ; give Position of Char .... ARG-3(output)
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    call _RUN_Fail        ; FAIL
    popx3
LEAVE
ENDP _nd_search_2


PROC _nd_search_3 near        ; (BINARY,STRING,POSITION) -(i,i,o)
ENTER    20,0    ;
ARG    strg1:dword,substr:dword,outpx:dword
    pushx3
    mov edi,[substr]    ; substring................ ARG-2(input)
    mov esi,[strg1]        ; BINARY input..............ARG-1(input)
    mov    [ebp-8], esi    ;
    mov    [ebp-4], edi    ;
    mov    ecx,[dword ptr esi-4]    ;
    dec    ecx
    dec    ecx
    dec    ecx
    mov    [ebp-16],ecx    ; length of binary in local variable

@@LP0:    mov    edi,[ebp-4]    ;
    mov ah,[byte ptr edi]    ; first char of substring in AH
@@LP0a:    lodsb            ;
    cmp    al,ah        ;
    jz    @@ok1        ;
;or    al,al        ;
;jz    @@XZ1        ; if zero, fail at end of string
    dec    ecx        ;
    or    ecx,ecx        ;
    jz    @@XZ1        ;
    jmp    @@LP0a        ; else repeat THIS loop
; ===============================
@@ok1:   
    dec    ecx        ;
    or    ecx,ecx        ;
    jz    @@XZ1        ;
    mov    [ebp-16],ecx    ;
    push    esi        ;
@@ok2:     inc    edi        ;
     lodsb            ;
     cmp    al,[byte ptr edi]
     jz    @@ok2        ;
     mov    al,[byte ptr edi]
     or    al,al        ;
     jz    @@ok3        ;
    pop    esi        ;
    jmp    @@LP0        ;
; ===============================
@@ok3:     mov    ebx,esi        ;
    pop    esi        ;
    mov    [ebp-8],esi    ; store esi
    mov    [ebp-12],ebx    ; store right_hand_string after the substring
    mov    [ebp-16],ecx    ; remaining length recovered
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    ecx,[ebp-16]    ; remaining length recovered
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
@@ZZ:    mov    eax,[ebp-12]    ; return right_hand_side string (after the char)
    mov    ecx,esi        ;
    mov ebx,[strg1]        ; string input.................. ARG-1(input)
    sub    ecx,ebx        ;
    mov edx,[outpx]        ; give Position of substring.... ARG-3(output)
    dec    ecx        ; binaries start at zero   
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    mov    ecx,[ebp-16]    ; remaining length recovered
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    mov    [ebp-16],ecx    ;
    call _RUN_Fail        ; FAIL
@@XZ2:    popx3
LEAVE
ENDP _nd_search_3



PROC _nd_search_4 near    ; (BINARY,BINARY,POSITION) -(i,i,o)
ENTER    24,0
ARG    binary:dword,subbin:dword,outpx:dword
    pushx3
    mov edi,[subbin]    ; sub-binary............... ARG-2(input)
    mov ecx,[dword ptr edi-4] ; "true length" of sub-binary in ECX
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ; length of sub_binary_array in ECX
    dec    ecx        ; minus 1
    mov    [ebp-20],ecx    ; store length of sub-binary-1 in local variable
    mov    edx,ecx        ; copy it also to EDX
    mov esi,[binary]    ; binary input..............ARG-1(input)
    mov ecx,[dword ptr esi-4] ; "true length" of binary in ECX
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ; length of binary_array in ECX
    dec    ecx        ;
    mov    [ebp-8], esi    ;
    sub    ecx,edx        ; subtrack sub_bin_length from binary length!
    dec    ecx
    mov    [ebp-16],ecx    ; store length of binary in local variable
    mov    [ebp-4], edi    ;
@@LP0:   
;;or    ecx,ecx        ;
;;jz    @@XZ1        ;
    mov    edi,[ebp-4]    ;
    or    ecx,ecx        ;
    jz    @@XZ1        ;
     mov ah,[byte ptr edi]    ; first char of subbinary in AH
@@LP0a:    lodsb            ;
    cmp    al,ah        ;
    jz    @@ok1        ;
    loop    @@LP0a        ;
    jmp    @@XZ1        ; if exhausted, fail
; ===============================
@@ok1:    dec    ecx        ;
    or    ecx,ecx        ;
    jz    @@XZ1        ;
    push    esi        ;
     push    ecx        ;
      mov    ecx,[ebp-20]    ; length of subbinary recovered from local var.
      jmp    @@ok2        ;
@@ok2a:      dec    ecx        ;
      jz    @@ok3        ;
@@ok2:      inc    edi        ;
      lodsb            ;
      cmp al,[byte ptr edi]    ;
      jz    @@ok2a        ;
     pop    ecx        ;
    pop    esi        ;
    jmp    @@LP0        ;
; ===============================
@@ok3:      mov    ebx,esi        ;
     pop    ecx        ;
    pop    esi        ;
    or    ecx,ecx        ;
    jz    @@XZ1        ;
    mov    [ebp-8],esi    ; store esi
    mov    [ebp-12],ebx    ; store right_hand_string after the substring
    mov    [ebp-16],ecx    ; store length in local variable
;or    ecx,ecx        ;
;jz    @@XZ1        ;
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    ecx,[ebp-16]    ; store length in local variable
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
    mov    eax,[ebp-12]    ; return right_hand_side string (after the sub-bin)
    mov    ecx,esi        ;
    mov ebx,[binary]    ; binary input.................. ARG-1(input)
    sub    ecx,ebx        ;
    dec    ecx        ; binaries start at zero   
    mov edx,[outpx]        ; give Position of substring.... ARG-3(output)
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    mov    ecx,[ebp-16]    ; recover length from local variable
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    call _RUN_Fail        ; FAIL
    popx3
LEAVE
ENDP _nd_search_4


PROC _nd_search_5 near        ; (STRING,CHAR,inpos,posx) -(i,i,i,o)
ENTER    12,0            ;
ARG    strg1:dword,char1:byte,inpos:dword,outpx:dword
    pushx3
    mov esi,[strg1]        ; string input.............. ARG-1(input)
    mov    eax,[inpos]    ; initial position.......... ARG-2(input)
    dec    eax        ; minus one, because Prolog strings start at 1
    add    esi,eax        ; add the position to the string pointer
    mov [ebp-8], esi    ;
    mov ah,[char1]        ; char ..................... ARG-3(input)
    mov [ebp-4], eax    ;
; -------------------------------
@@LP0:    mov    eax,[ebp-4]    ;
@@LP0a:    lodsb            ;
    cmp    al,ah        ;
    jz    @@ok1        ;
    or    al,al        ;
    jz    @@XZ1        ; if zero, fail at end of string
    jmp    @@LP0a        ; else repeat THIS loop
; ===============================
@@ok1:    mov    [ebp-8],esi    ; store it
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
    mov    eax,esi        ; return right_hand_side string (after the char)
    mov    ecx,eax        ;
    mov ebx,[strg1]        ; string input.............. ARG-1(input)
    sub    ecx,ebx        ;
    mov edx,[outpx]        ; give Position of Char .... ARG-3(output)
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    call _RUN_Fail        ; FAIL
    popx3
LEAVE
ENDP _nd_search_5


PROC _nd_search_6 near    ;  (STRING,STRING,INIPOS,POSITION) -(i,i,i,o)
ENTER    16,0    ;
ARG    strg1:dword,substr:dword,inpos:dword,outpx:dword
    pushx3
    mov esi,[strg1]        ; string input..............ARG-1 (input)
    mov    [ebp-8], esi    ;
    mov edi,[substr]    ; substring................ ARG-2 (input)
    mov    eax,[inpos]    ; initial position......... ARG-3 (input)
    dec    eax        ; minus 1, since Prolog strings start with 1
    add    esi,eax        ; add initial position to the string
    mov    [ebp-4], edi    ;
@@LP0:    mov    edi,[ebp-4]    ;
    mov ah,[byte ptr edi]    ; first char of substring in AH
@@LP0a:    lodsb            ;
    cmp    al,ah        ;
    jz    @@ok1        ;
    or    al,al        ;
    jz    @@XZ1        ; if zero, fail at end of string
    jmp    @@LP0a        ; else repeat THIS loop
; ===============================
@@ok1:    push    esi        ;
@@ok2:     inc    edi        ;
     lodsb            ;
     cmp al,[byte ptr edi]    ;
     jz    @@ok2        ;
     mov al,[byte ptr edi]    ;
     or    al,al        ;
     jz    @@ok3        ;
    pop    esi        ;
    jmp    @@LP0        ;
@@ok3:     mov    ebx,esi        ;
    pop    esi        ;
    mov    [ebp-8],esi    ; store esi
    mov    [ebp-12],ebx    ; store right_hand_string after the substring
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
    mov    eax,[ebp-12]    ; return right_hand_side string (after the char)
    mov    ecx,esi        ;
    mov ebx,[strg1]        ; string input.................. ARG-1(input)
    sub    ecx,ebx        ;
    mov edx,[outpx]        ; give Position of substring.... ARG-3(output)
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    call _RUN_Fail        ; FAIL
    popx3
LEAVE
ENDP _nd_search_6


PROC _nd_search_7 near        ; (BINARY,CHAR,inpos,posx) -(i,i,i,o)
ENTER    16,0            ;
ARG    binary:dword,char1:byte,inpos:dword,outpx:dword
    pushx3
    mov esi,[binary]    ; binary input.............. ARG-1(input)
    mov ecx,[dword ptr esi-4]    ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    mov    eax,[inpos]    ; initial position.......... ARG-2(input)
    add    esi,eax        ; add initial position to binary pointer
    sub    ecx,eax        ; subtract init_pos from binary length
    mov [ebp-8], esi    ;
    mov ah,[char1]        ; char ..................... ARG-3(input)
    mov [ebp-4], eax    ;
    mov [ebp-12],ecx    ;
@@LP0:    mov    eax,[ebp-4]    ;
    mov    ecx,[ebp-12]    ;
@@LP0a:    lodsb            ;
    cmp    al,ah        ;
    jz    @@ok1        ;
    or    al,al        ;
    jz    @@XZ1        ; if zero, fail at end of string
    jmp    @@LP0a        ; else repeat THIS loop
; ===============================
@@ok1:    mov    [ebp-8],esi    ; store it
    mov [ebp-12],ecx    ;
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
    mov    eax,esi        ; return right_hand_side string (after the char)
    mov    ecx,eax        ;
    mov ebx,[strg1]        ; string input.............. ARG-1(input)
    sub    ecx,ebx        ;
    dec    ecx        ; binaries start at zero   
    mov edx,[outpx]        ; give Position of Char .... ARG-3(output)
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    call _RUN_Fail        ; FAIL
    popx3
LEAVE
ENDP _nd_search_7


PROC _nd_search_8 near    ;  (BINARY,STRING,INIPOS,POSITION) -(i,i,i,o)
ENTER    20,0    ;
ARG    binary:dword,substr:dword,inpos:dword,outpx:dword
    pushx3
    mov esi,[binary]    ; binary input..............ARG-1 (input)
    mov    ecx,[dword ptr esi-4]    ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ; ecx is now length of binary
    mov    [ebp-8], esi    ;
    mov edi,[substr]    ; substring................ ARG-2 (input)
    mov    eax,[inpos]    ; initial position......... ARG-3 (input)
    add    esi,eax        ; add initial position to the string
    sub    ecx,eax        ; subtract it from the length
    mov    [ebp-4], edi    ;
    mov    [ebp-16],ecx    ; store the length as a local variable
@@LP0:    mov    edi,[ebp-4]    ;
    mov    ecx,[ebp-16]    ; restore the length from local variable
    mov ah,[byte ptr edi]    ; first char of substring in AH
@@LP0a:    lodsb            ;
    cmp    al,ah        ;
    jz    @@ok1        ;
    dec    ecx        ;
    jz    @@XZ1        ; if at the end, fail
    jmp    @@LP0a        ; else repeat THIS loop
; ===============================
@@ok1:    push    esi        ;
@@ok2:     inc    edi        ;
     lodsb            ;
     cmp al,[byte ptr edi]    ;
     jz    @@ok2        ;
     mov al,[byte ptr edi]    ;
     or    al,al        ;
     jz    @@ok3        ;
    pop    esi        ;
    jmp    @@LP0        ;
@@ok3:    mov    ebx,esi        ;
    pop    esi        ;
    mov    [ebp-8],esi    ; store esi
    mov    [ebp-12],ebx    ; store right_hand_string after the substring
    mov    [ebp-16],ecx    ; store length remaining
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
    mov    eax,[ebp-12]    ; return right_hand_side string (after the char)
    mov    ecx,esi        ;
    mov ebx,[strg1]        ; string input.................. ARG-1(input)
    sub    ecx,ebx        ;
    mov edx,[outpx]        ; give Position of substring.... ARG-3(output)
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    call _RUN_Fail        ; FAIL
    popx3
LEAVE
ENDP _nd_search_8


PROC _nd_search_9 near    ;  (BINARY,BINARY,INIPOS,POSITION) -(i,i,i,o)
ENTER    24,0    ;
ARG    binary:dword,substr:dword,inpos:dword,outpx:dword
    pushx3
    mov esi,[binary]    ; binary input..............ARG-1 (input)
    mov    ecx,[dword ptr esi-4]    ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ; ecx is now length of binary
    mov    [ebp-8], esi    ;
    mov edi,[substr]    ; substring................ ARG-2 (input)
    mov    edx,[dword ptr edi-4]    ;
    mov    eax,[inpos]    ; initial position......... ARG-3 (input)
    add    esi,eax        ; add initial position to the string
    sub    ecx,eax        ; subtract it from the length
    mov    [ebp-4], edi    ;
    mov    [ebp-16],ecx    ; store the length as a local variable
@@LP0:    mov    edi,[ebp-4]    ;
    mov    ecx,[ebp-16]    ; restore the length from local variable
    mov ah,[byte ptr edi]    ; first char of substring in AH
@@LP0a:    lodsb            ;
    cmp    al,ah        ;
    jz    @@ok1        ;
    dec    ecx        ;
    jz    @@XZ1        ; if at the end, fail
    jmp    @@LP0a        ; else repeat THIS loop
; ===============================
@@ok1:    push    esi        ;
@@ok2:     inc    edi        ;
     lodsb            ;
     cmp al,[byte ptr edi]    ;
     jz    @@ok2        ;
     mov al,[byte ptr edi]    ;
     or    al,al        ;
     jz    @@ok3        ;
    pop    esi        ;
    jmp    @@LP0        ;
@@ok3:    mov    ebx,esi        ;
    pop    esi        ;
    mov    [ebp-8],esi    ; store esi
    mov    [ebp-12],ebx    ; store right_hand_string after the substring
    mov    [ebp-16],ecx    ; store length remaining
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
    mov    eax,[ebp-12]    ; return right_hand_side string (after the char)
    mov    ecx,esi        ;
    mov ebx,[strg1]        ; string input.................. ARG-1(input)
    sub    ecx,ebx        ;
    mov edx,[outpx]        ; give Position of substring.... ARG-3(output)
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    call _RUN_Fail        ; FAIL
    popx3
LEAVE
ENDP _nd_search_9


PROC _nd_search_10 near        ; (STRING,CHAR,inpos,case_table,posx) -(i,i,i,i,o)
ENTER    16,0            ;
ARG    strg1:dword,char1:byte,inpos:dword,case:dword,outpx:dword
    pushx3
    mov esi,[strg1]        ; string input................... ARG-1(input)
    mov    eax,[inpos]    ; initial position............... ARG-3(input)
    dec    eax        ; minus one, because Prolog strings start at 1
    add    esi,eax        ; add the position to the string pointer
    mov    edx,[case]    ; case_table_number in EDX....... ARG-4(input)
;;or    edx,edx        ; is it zero?
;;jnz    @@ci        ; if not so, case-sensitive search
    dec    edx            ;
    shl    edx,1            ;
    shl    edx,1            ;
    mov    ebx,[dword ptr ctb+edx]    ; ebx is now the Nth char_table
    mov [ebp-12],ebx    ; put char_table in local variable
@@ci:    mov [ebp-8], esi    ;
    mov al,[char1]        ; char .......................... ARG-2(input)
    xlat    [EBX]        ; translate
    mov    ah,al        ; store as AH
    mov [ebp-4], eax    ;
; -------------------------------
@@LP0:    mov    eax,[ebp-4]    ;
    mov    ebx,[ebp-12]    ; restore case_table from local variable
@@LP0a:    lodsb            ;
    xlat    [EBX]        ; translate
    cmp    al,ah        ;
    jz    @@ok1        ;
    or    al,al        ;
    jz    @@XZ1        ; if zero, fail at end of string
    jmp    @@LP0a        ; else repeat THIS loop
; ===============================
@@ok1:    mov    [ebp-8],esi    ; store it
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
    mov    eax,esi        ; return right_hand_side string (after the char)
    mov    ecx,eax        ;
    mov edx,[strg1]        ; string input.............. ARG-1(input)
    sub    ecx,edx        ;
    mov edx,[outpx]        ; give Position of Char .... ARG-3(output)
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    call _RUN_Fail        ; FAIL
    popx3
LEAVE
ENDP _nd_search_10


PROC _nd_search_11 near    ;  (STRING,STRING,INIPOS,case_table,POSITION) -(i,i,i,i,o)
ENTER    24,0    ;
ARG    strg1:dword,substr:dword,inpos:dword,case:dword,outpx:dword
    pushx3
    mov esi,[strg1]        ; string input................. ARG-1(input)
    mov    [ebp-8], esi    ;
    mov edi,[substr]    ; substring.................... ARG-2(input)
    mov    eax,[inpos]    ; initial position............. ARG-3(input)
    dec    eax        ; minus 1, since Prolog strings start with 1
    add    esi,eax        ; add initial position to the string
    mov    edx,[case]    ; case_table_number in EDX..... ARG-4(input)
    dec    edx        ;
    shl    edx,1        ;
    shl    edx,1        ;
    mov ebx,[dword ptr ctb+edx]    ; ebx is now the Nth char_table
    mov [ebp-20],ebx    ; put char_table in local variable
    mov    [ebp-4], edi    ;
    mov al,[byte ptr edi]    ; first char of substring in AL
    xlat    [EBX]        ; translate
    mov    ah,al        ; store as AH
    mov    [ebp-16],eax    ; store in local variable
@@LP0:    mov    edi,[ebp-4]    ;
    mov    ebx,[ebp-20]    ; restore char_table from local variable
    mov    eax,[ebp-16]    ; restore AH (eax) from local variable
@@LP0a:    lodsb            ;
    or    al,al        ;
    jz    @@XZ1        ; if zero, fail at end of string
    xlat    [ebx]        ; translate
    cmp    al,ah        ; compare
    jz    @@ok1        ;
    jmp    @@LP0a        ; else repeat THIS loop
; ===============================
@@ok1:    push    esi        ;
@@ok2:     inc    edi        ;
     lodsb            ;
     xlat    [ebx]        ; translate
     mov    DL,AL        ; store in DL
     mov al,[byte ptr edi]    ; get a byte from substring
     or    al,al        ;
     jz    @@ok3        ;
     xlat    [ebx]        ; translate
     cmp    al,dl        ; compare
     jz    @@ok2        ; if translations are the same, continue loop
    pop    esi        ;
    jmp    @@LP0        ;
@@ok3:     mov    [ebp-16],eax    ;
     mov    eax,esi        ;
    pop    esi        ;
    mov    [ebp-8],esi    ; store esi
    mov    [ebp-12],eax    ; store right_hand_string after the substring
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
    mov    eax,[ebp-12]    ; return right_hand_side string (after the char)
    mov    ecx,esi        ;
    mov edx,[strg1]        ; string input.................. ARG-1(input)
    sub    ecx,edx        ;
    mov edx,[outpx]        ; give Position of substring.... ARG-3(output)
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    call _RUN_Fail        ; FAIL
    popx3
LEAVE
ENDP _nd_search_11


PROC _nd_search_12 near        ; (BINARY,CHAR,inpos,case_table,posx) -(i,i,i,i,o)
ENTER    20,0            ;
ARG    binary:dword,char1:byte,inpos:dword,case:dword,outpx:dword
    pushx3
    mov esi,[binary]        ; binary input................... ARG-1(input)
    mov    ecx,[dword ptr esi-4]    ; "true size" of binary in ECX
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    mov    [ebp-16],ecx    ; store length in local variable
    mov    eax,[inpos]    ; initial position............... ARG-3(input)
    add    esi,eax        ; add the position to the binary pointer
    mov    edx,[case]    ; case_table_number in EDX....... ARG-4(input)
    dec    edx        ;
    shl    edx,1        ;
    shl    edx,1        ;
    mov    ebx,[dword ptr ctb+edx]    ; ebx is now the Nth char_table
    mov [ebp-12],ebx    ; put char_table in local variable
    mov [ebp-8], esi    ;
    mov al,[char1]        ; char .......................... ARG-2(input)
    xlat    [EBX]        ; translate
    mov    ah,al        ; store as AH
    mov [ebp-4], eax    ;
; -------------------------------
@@LP0:    mov    eax,[ebp-4]    ;
    mov    ebx,[ebp-12]    ; restore case_table from local variable
    mov    ecx,[ebp-16]    ; restore length from local variable
@@LP0a:    lodsb            ;
    dec    ecx        ;
    jz    @@XZ1        ; if at the end of binary, fail
    xlat    [EBX]        ; translate
    cmp    al,ah        ;
    jz    @@ok1        ;
    jmp    @@LP0a        ; else repeat THIS loop
; ===============================
@@ok1:    mov    [ebp-8],esi    ; store the string pointer in local variable
    mov    [ebp-16],ecx    ; store the string length in local variable
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
    mov    eax,esi        ; return right_hand_side binary (after the char)
    mov    ecx,eax        ;
    mov edx,[strg1]        ; binary input.............. ARG-1(input)
    sub    ecx,edx        ;
    dec    ecx        ; binaries start from 0
    mov edx,[outpx]        ; give Position of Char .... ARG-3(output)
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    call _RUN_Fail        ; FAIL
    popx3
LEAVE
ENDP _nd_search_12


PROC _nd_search_13 near    ;  (binary,string,INIPOS,case_table,POSITION) -(i,i,i,i,o)
ENTER    28,0    ;
ARG    binary:dword,substr:dword,inpos:dword,case:dword,outpx:dword
    pushx3
    mov esi,[binary]        ; binary input................. ARG-1(input)
    mov    ecx,[dword ptr esi-4]    ; length
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    mov    [ebp-24],ecx    ; store length locally
    mov    [ebp-8], esi    ; store binary pointer locally
    mov edi,[substr]    ; substring.................... ARG-2(input)
    mov    eax,[inpos]    ; initial position............. ARG-3(input)
    add    esi,eax        ; add initial position to the binary
    mov    edx,[case]    ; case_table_number in EDX..... ARG-4(input)
    dec    edx        ;
    shl    edx,1        ;
    shl    edx,1        ;
    mov ebx,[dword ptr ctb+edx]    ; ebx is now the Nth char_table
    mov [ebp-20],ebx    ; put char_table in local variable
    mov    [ebp-4], edi    ;
    mov al,[byte ptr edi]    ; first char of substring in AL
    xlat    [EBX]        ; translate
    mov    ah,al        ; store as AH
    mov    [ebp-16],eax    ; store in local variable
@@LP0:    mov    edi,[ebp-4]    ;
    mov    ebx,[ebp-20]    ; restore char_table from local variable
    mov    eax,[ebp-16]    ; restore AH (eax) from local variable
    mov    ecx,[ebp-24]    ; restore binary length from local variable
@@LP0a:    lodsb            ;
    or    al,al        ;
    jz    @@XZ1        ; if zero, fail at end of binary
    xlat    [ebx]        ; translate
    cmp    al,ah        ; compare
    jz    @@ok1        ;
    jmp    @@LP0a        ; else repeat THIS loop
; ===============================
@@ok1:    push    esi        ;
@@ok2:     inc    edi        ;
     lodsb            ;
     xlat    [ebx]        ; translate
     mov    DL,AL        ; store in DL
     mov al,[byte ptr edi]    ; get a byte from substring
     or    al,al        ;
     jz    @@ok3        ;
     xlat    [ebx]        ; translate
     cmp    al,dl        ; compare
     jz    @@ok2        ; if translations are the same, continue loop
    pop    esi        ;
    jmp    @@LP0        ;
@@ok3:     mov    [ebp-16],eax    ;
     mov    eax,esi        ;
    pop    esi        ;
    mov    [ebp-8],esi    ; store esi
    mov    [ebp-12],eax    ; store right_hand_binary after the substring
    mov    [ebp-24],ecx    ; store remaining length in a local variable
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
    mov    eax,[ebp-12]    ; return right_hand_side string (after the char)
    mov    ecx,esi        ;
    mov edx,[binary]    ; binary input.................. ARG-1(input)
    sub    ecx,edx        ;
    dec    ecx        ; binaries start from 0
    mov edx,[outpx]        ; give Position of substring.... ARG-3(output)
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    call _RUN_Fail        ; FAIL
    popx3
LEAVE
ENDP _nd_search_13


PROC _nd_search_14 near    ;  (binary,binary,INIPOS,case_table,POSITION) -(i,i,i,i,o)
ENTER    32,0    ;
ARG    binary:dword,subbin:dword,inpos:dword,case:dword,outpx:dword
    pushx3
    mov esi,[binary]        ; binary input.......... ARG-1(input)
    mov    ecx,[dword ptr esi-4]    ; length
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    mov    [ebp-24],ecx    ; store length locally
    mov    [ebp-8], esi    ; store binary pointer locally
    mov edi,[subbin]    ; sub-binary.................... ARG-2(input)
    mov    ecx,[dword ptr edi-4]    ; length of subbin
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    dec    ecx        ;
    mov    [ebp-28],ecx    ; store sub-binary length locally
    mov    eax,[inpos]    ; initial position............. ARG-3(input)
    add    esi,eax        ; add initial position to the binary
    mov    edx,[case]    ; case_table_number in EDX..... ARG-4(input)
    dec    edx        ;
    shl    edx,1        ;
    shl    edx,1        ;
    mov ebx,[dword ptr ctb+edx]    ; ebx is now the Nth char_table
    mov [ebp-20],ebx    ; put char_table in local variable
    mov    [ebp-4], edi    ;
    mov al,[byte ptr edi]    ; first char of substring in AL
    xlat    [EBX]        ; translate
    mov    ah,al        ; store as AH
    mov    [ebp-16],eax    ; store in local variable
@@LP0:    mov    edi,[ebp-4]    ;
    mov    ebx,[ebp-20]    ; restore char_table from local variable
    mov    eax,[ebp-16]    ; restore AH (eax) from local variable
    mov    ecx,[ebp-24]    ; restore binary length from local variable
@@LP0a:    lodsb            ;
    or    al,al        ;
    jz    @@XZ1        ; if zero, fail at end of binary
    xlat    [ebx]        ; translate
    cmp    al,ah        ; compare
    jz    @@ok1        ;
    jmp    @@LP0a        ; else repeat THIS loop
; ===============================
@@ok1:    push    esi        ;
     push    ecx        ;
      mov    ecx,[ebp-28]    ;
@@ok2:      inc    edi        ;
      lodsb            ;
      xlat    [ebx]        ; translate
      mov    DL,AL        ; store in DL
      mov al,[byte ptr edi]    ; get a byte from substring
      dec    ecx        ;
      jz    @@ok3        ;
      xlat    [ebx]        ; translate
      cmp    al,dl        ; compare
      jz    @@ok2        ; if translations are the same, continue loop
     pop    ecx        ;
    pop    esi        ;
    jmp    @@LP0        ;
@@ok3:      mov    [ebp-16],eax    ;
      mov    eax,esi        ;
     pop    ecx        ;
    pop    esi        ;
    mov    [ebp-8],esi    ; store esi
    mov    [ebp-12],eax    ; store right_hand_binary after the substring
    mov    [ebp-24],ecx    ; store remaining length in a local variable
    call _RUN_StackBTrack    ; stack a 'backtrack point' in Visual Prolog
    mov    esi,[ebp-8]    ; recover ESI
    or    eax,eax        ; is the result (of StackBTrack) zero?
    jne    @@LP0        ; if not, read more...
; -------------------------------
    mov    eax,[ebp-12]    ; return right_hand_side string (after the char)
    mov    ecx,esi        ;
    mov edx,[binary]    ; binary input.................... ARG-1(input)
    sub    ecx,edx        ;
    dec    ecx        ; binaries start from 0
    mov edx,[outpx]        ; give Position of substring...... ARG-5(output)
    mov    [edx],ecx    ;
    call _RUN_JmpReturn1    ; call Visual Prolog function "_RUN_JmpReturn1"
    mov    esi,[ebp-8]    ;
    jmp    @@LP0        ; repeat big loop
; ===============================
@@XZ1:    call _RUN_Fail        ; FAIL
    popx3
LEAVE
ENDP _nd_search_14


    END

; ===================== VISUAL PROLOG TEST-PROGRAM: =====================
include "testpreds.inc"

GOAL
  easywin_CloseAfterEnd(1),
  Si = "this is a string or a binary and it is going to be searched",
  S = dlg_GetStr("Testing 'nd_search'","Give a string",Si),
 
  bin2str(B,S), repeat,
  write("\n*** Testing nd_search:\nS=\"",S,"\"\nB=",B,"\ngive a char to find: "),
  readchar(Ch), writef(" '%c', hex: %X",Ch,Ch), nl, str_len(S,Len),
  findall(P,nd_search(S,Ch,P),PL),
  write("(string,char,pos): ",PL), nl, findall(Q,nd_search(B,Ch,Q),QL),
  write("(binary,char,pos): ",QL), nl,
  write("String Length = ",Len,". Give initial position: "), readint(InPos),
  InPo1 = InPos-1,
  findall(PP,nd_search(S,Ch,InPos,PP),PPL),
  write("(string,char,inpos=",InPos,",pos): ",PPL), nl,
  findall(QQ,nd_search(B,Ch,InPos,QQ),QQL),
  write("(binary,char,inpos=",InPo1,",pos): ",QQL), nl,
  write("\ngive a substring to find: "), readln(Sub),
  bin2str(_BS,Sub), write("Sub-binary: ",_BS), nl, findall(R,nd_search(S,Sub,R),L),
  write("(string,string,pos): ",L), nl, findall(R2,nd_search(B,Sub,R2),L2),
  write("(binary,string,pos): ",L2), nl, findall(R3,nd_search(B,_BS,R3),L3),
  write("(binary,binary,pos): ",L3), nl, findall(PQ,nd_search(S,Sub,InPos,PQ),PQL),
  write("(string,string,inpos=",InPos,",pos): ",PQL), nl,
  findall(Q2,nd_search(B,Sub,InPo1,Q2),Q2L),
  write("(binary,string,inpos=",InPo1,",pos): ",Q2L), nl,
  findall(Q3,nd_search(B,_BS,InPo1,Q3),Q3L),
  write("(binary,binary,inpos=",InPo1,",pos): ",Q3L), nl,
  write("\nGive character table number (1=uptolow,2=lowtoup,etc): "), readint(CASE),
  write("S=\"",S,"\"\nB=",B,", init_pos=",InPos,"\ngive a char to find: "),
  readchar(C1), writef(" '%c', hex: %X",C1,C1), nl,
  findall(P3,nd_search(S,C1,InPos,CASE,P3),P3L),
  write("(string,char='",C1,"',inpos=",InPos,",case=",CASE,",pos): ",P3L),
  findall(P3a,nd_search(B,C1,InPo1,CASE,P3a),P3aL),
  write("\n(binary,char='",C1,"',inpos=",InPos,",case=",CASE,",pos): ",P3aL),
  write("\n\ngive a substring to find (case-insensitively): "), readln(Sub2),
  findall(P4,nd_search(S,Sub2,InPos,CASE,P4),P4L),
  write("(string,sub=\"",Sub2,"\",inpos=",InPos,",case=",CASE,",pos): ",P4L),
  bin2str(SubB2,Sub2), findall(P5,nd_search(B,Sub2,InPo1,CASE,P5),P5L),
  write("\n(binary,sub=\"",Sub2,"\",inpos=",InPo1,",case=",CASE,",pos): ",P5L), nl,
  findall(P6,nd_search(B,SubB2,InPo1,CASE,P6),P6L),
  write("(binary,subbin=",SubB2,",inpos=",InPo1,",case=",CASE,",pos): ",P6L), nl,
  write("\nESC to end, any other key to go on: "), readchar(CHx), nl, CHx='\27', !.

/*************************** COPYRIGHT ISSUES: *******************************

                      This source-code is part of the:
         "32-bit Assembly Language and 'C' Extensions for Visual Prolog"

This source-code is free for use in any application, provided this copyright
message is preserved intact, and the author is mentioned explicitly.

Author: George A. Stathis
Author's e-mail: omadeon@yahoo.com, gstathis@enm.gr
Author's personal URL: http://www.omadeon.com
Company URL:  http://www.enb.gr
*******************************************************************************/