; in: ebx -> pattern (not empty zero-terminated string), esi -> translation table,
;	dword [esp+4] = encoding, byte [esp+8] non-zero for whole words only
; out: edx and ecx -> preprocessed data
; when search will be done, edx must be pgfree()d
search_string_pre:
; FSM is used, number of states is limited by 256, so pattern length must be <= 255
; anyway, for big patterns FSM uses too many memory, so probably it is not best choice
; get pattern length, m
	or	ecx, -1
@@:
	inc	ecx
	cmp	byte [ecx+ebx], 0
	jnz	@b
	cmp	byte [esp+8], 0
	jz	@f
	inc	ecx
	inc	ecx
@@:
	push	ecx
; allocate m*257 bytes for FSM and prefix function
	imul	ecx, 257
	call	xpgalloc
	pop	ecx
	test	eax, eax
	jnz	@f
	ret	8
@@:
	shl	ecx, 8
	push	eax
	add	eax, ecx
; calculate prefix function
	xor	ecx, ecx
	mov	byte [eax], cl
	xor	edi, edi
	cmp	byte [esp+4+8], 0
	jnz	.whole.prefixcalc
.prefixcalc:
	inc	edi
	movzx	edx, byte [ebx+edi]
	mov	dl, [esi+edx]
	test	dl, dl
	jz	.prefixdone
@@:
	push	eax
	movzx	eax, byte [ebx+ecx]
	cmp	dl, [esi+eax]
	pop	eax
	jz	@f
	jecxz	.prefixint
	mov	cl, byte [eax+ecx-1]
	jmp	@b
@@:
	inc	ecx
.prefixint:
	mov	[eax+edi], cl
	jmp	.prefixcalc
.whole.prefixcalc:
	inc	edi
	movzx	edx, byte [ebx+edi-1]
	mov	dl, [esi+edx]
	test	dl, dl
	jz	.whole.prefixdone
.whole.prefixloop:
	jecxz	.whole.testfirst
	push	eax
	movzx	eax, byte [ebx+ecx-1]
	cmp	dl, [esi+eax]
	pop	eax
	jz	@f
	mov	cl, byte [eax+ecx-1]
	jmp	.whole.prefixloop
.whole.testfirst:
	cmp	[isspace_table+edx], 0
	jz	.whole.prefixint
@@:
	inc	ecx
.whole.prefixint:
	mov	[eax+edi], cl
	jmp	.whole.prefixcalc
.whole.prefixdone:
	jecxz	@f
	push	eax
	movzx	eax, byte [ebx+ecx-1]
	mov	al, [esi+eax]
	cmp	[isspace_table+eax], 0
	pop	eax
	jnz	@f
	mov	cl, byte [eax+ecx-1]
	jmp	.whole.prefixdone
@@:
	inc	ecx
	mov	[eax+edi], cl
.prefixdone:
	pop	edx
; create reverse table for encoding+translation
	push	ebp
	movzx	ebp, byte [esp+8]
	cmp	ebp, encodings.unicode
	jb	@f
	xor	ebp, ebp	; no translations for Unicode encodings,
				; they must be handled separately by caller
@@:
	mov	ecx, 256
@@:
	push	0
	loop	@b
	push	ebx eax
	mov	ebx, esp
	shl	ebp, 7
	xor	eax, eax
.createrev:
	dec	cl
	mov	al, cl
	jns	@f
	mov	al, byte [encodings.tables+ebp+ecx-80h]
@@:
	mov	al, [esi+eax]
	pushd	[ebx+8+eax*4]
	pushd	ecx
	mov	[ebx+8+eax*4], esp
	jnz	.createrev
@@:
	dec	cl
	mov	al, [esi+ecx]
	pushd	[ebx+8+eax*4]
	popd	[ebx+8+ecx*4]
	jnz	@b
; create FSM
	xor	ecx, ecx
	cmp	byte [ebx+259*4+8], 0
	mov	eax, [ebx]
	mov	ebx, [ebx+4]
	mov	edi, edx
	jz	.fsmcalc
	mov	esi, isspace_table
	push	256/4
	pop	ecx
	rep	movsd
	inc	ecx
.fsmcalc:
	movzx	esi, byte [eax+ecx]
	push	eax
	push	ecx
	push	256/4
	pop	ecx
	dec	esi
	js	.fsmzero
	shl	esi, 8
	add	esi, edx
	rep	movsd
	jmp	.fsmnext
.fsmzero:
	cmp	byte [esp+261*4+256*8+8], 0
	jnz	.whole.fsmzero
	xor	eax, eax
	rep	stosd
	jmp	.fsmnext
.whole.fsmzero:
	mov	esi, edx
	rep	movsd
.fsmnext:
	pop	ecx
	movzx	esi, byte [ebx]
	inc	ecx
	mov	esi, [esp+4+8*256+8+esi*4]
@@:
	test	esi, esi
	jz	@f
	lodsd
	mov	[edi-256+eax], cl
	mov	esi, [esi]
	jmp	@b
@@:
	inc	ebx
	pop	eax
	cmp	byte [ebx], 0
	jnz	.fsmcalc
	cmp	byte [esp+259*4+256*8+8], 0
	jz	.nowholefin
	movzx	esi, byte [eax+ecx]
	push	ecx
	mov	ecx, 256
	push	256/4
	pop	ecx
	dec	esi
	shl	esi, 8
	add	esi, edx
	rep	movsd
	pop	ecx
	inc	ecx
	xor	eax, eax
.whole.fsmfin:
	cmp	[isspace_table+eax], ah
	jz	@f
	mov	byte [edi-256+eax], cl
@@:
	inc	al
	jnz	.whole.fsmfin
.nowholefin:
; ok, now edx -> FSM, cl = final state
	add	esp, 8*256+8+4*256
	pop	ebp
	ret	8