* 正規表現によるパターン照合
*  Oh!X 1993/4 p122-124
*  Improved 1997 by AIG-Soft
*
	.include	re.mac
	.include	myctype.mac
	.include	defines.mac
*
	.xref	__bm_exec
	.xref	ctypetable
*
__CTYPETABLE__	reg	a5
CWORD		equ	CDIGIT.or.CALPHA
*
* デクの先頭にデータを追加する
PUSH	macro	dat
local	skip
	cmp.l	a3,d6
	bcs	skip
	movea.l	d7,a3
skip:	move.l	dat,-(a3)
	.endm

*
* デク先頭からデータを取り出す
POP	macro	dreg
local	skip
	cmpa.l	d7,a3
	bcs	skip
	movea.l	d6,a3
skip:	move.l	(a3)+,dreg
	.endm

*
* デク末尾にデータを追加する
PUT	macro	dat
local	skip
	cmpa.l	d7,a4
	bcs	skip
	movea.l	d6,a4
skip:	move.l	dat,(a4)+
	.endm
*
*
* 照合成功位置の記録領域
	.xdef	re_regs
re_regs:
	.ds.b	SIZEofREREG
*
* int _re_exec(unchar *txt,unchar *txtend,unsint *cpat,unsint *work,unsint *workend,int lastchar)
* ret(d0.l)=一致した文字列の長さ
* d0.l>0 & Z=1 : 一致   , a0=re_regsのアドレス
* d0.l<0 & Z=0 : 不一致 , a0=不定
* _re_execの引数構造
	.offset	4
txt:		.ds.l	1
txtend:		.ds.l	1
cpat:		.ds.l	1	* コンパイル済みパターン
work:		.ds.l	1
workend:	.ds.l	1
lastchar:	.ds.l	1	* 直前の文字（通常はLFになるようにする）
*lastchar:	.ds.w	1	* LFならtxtは行頭
*
	.text
	.even
*
	.xdef	__re_exec	* 関数名
__re_exec:
SAVREGS	reg	d1-d7/a1-a6
SAVSIZ	=	(7+6)*4
	movem.l	SAVREGS,-(sp)
	movem.l	txt+SAVSIZ(sp),d3-d7
	lea.l	ctypetable,a5
	movea.l	d3,a2
*	move.w	lastchar+SAVSIZ(sp),d2
	move.l	lastchar+SAVSIZ(sp),d2
	move.l	d4,-(sp)
	*
	movea.l	d5,a0
	move.w	(a0)+,d3
	move.l	a0,d5
	lea.l	re_regs(pc),a0
	moveq.l	#0,d0
	clr.l	(a0)+
	clr.l	(a0)+
	movea.l	d6,a3
	*lea.l	64(a3),a3
	bra	loop0ent
*
loop0:
	tst.b	d3
	bpl	notbolmode
	moveq.l	#LF,d0
	moveq.l	#0,d2
searchbolloop:
	move.b	(a2)+,d2
	beq	nomatch
	cmp.b	d0,d2
	bne	searchbolloop
	bra	loop0ent
*
notbolmode:
	moveq.l	#0,d2
	move.b	(a2)+,d2
	beq	nomatch
	BHAN	d2,loop0ent
	lsl.w	#8,d2
	move.b	(a2)+,d2
	beq	nomatch
loop0ent:
	movea.l	a3,a4
	moveq.l	#0,d0
	PUT	d0
	movea.l	a2,a0
	move.l	d5,d0
	tst.w	d3
	bpl	loop1ent
	move.l	d0,saved0	* d0退避
	pea.l	(a0)
	jsr	__bm_exec	* d0を破壊するように変えたから
	addq.l	#4,sp
	bne	nomatch
	move.l	saved0,d0	* d0復帰
	movea.l	a0,a2
	moveq.l	#0,d2
	move.b	-1(a2),d2
	bra	loop1ent
*
loop1:
	POP	d0
	beq	break1
loop2:
	movea.l	d0,a1
	bsr	transit
next2:
	POP	d0
	bne	loop2
	PUT	d0
	movea.l	d5,a1
	bsr	clrflag
	bra	next3
*
loop1ent:
loop3:
	movea.l	d0,a1
	bsr	eclosure
next3:
	POP	d0
	bne	loop3
	PUT	d0
next1:
	moveq.l	#0,d2
	move.b	(a0)+,d2
	beq	reacheos
	BHAN	d2,gethanchar
	lsl.w	#8,d2
	move.b	(a0)+,d2
	bne	loop1
	bra	reacheos
*
gethanchar:
	cmpi.b	#CR,d2
	bhi	loop1
	bne	notcr
	cmpi.b	#LF,(a0)
	bne	loop1
	bra	reacheo1
*
notcr:
	cmpi.b	#LF,d2
	bne	loop1
reacheos:
	subq.l	#1,a0
reacheo1:
	movea.l	d5,a1
	bsr	clrflag
	move.l	re_regs+reTAIL(pc),d0
	bne	match
	movea.l	a0,a2
	bra	loop0
*
break1:
next0:
	movea.l	d5,a1
	bsr	clrflag
	move.l	re_regs+reTAIL(pc),d0
	beq	loop0
match:
	lea.l	re_regs(pc),a0
	move.l	a2,reHEAD(a0)
	sub.l	a2,d0
	moveq.l	#0,d1
retn:
	addq.l	#4,sp
	movem.l	(sp)+,SAVREGS
	rts
*
fastretn:
	addq.l	#4,sp
	bra	break1
*
* 照合失敗
nomatch:
	moveq.l	#-1,d0
	bra	retn
*
*
* 次の文字を読まずに遷移出来る全ての状態を探す
eclosureloop:
	move.l	a1,d0
eclosure:
	move.w	(a1)+,d1
	bmi	eclosureretn
	st.b	-2(a1)
	move.w	ejumptable(pc,d1.w),d1
	jmp	ejumptable(pc,d1.w)
eclosureretn:
	rts
*
ejumptable:
x	=	*
	.dc.w	exec_term-x
	.dc.w	through-x
	.dc.w	through-x
	.dc.w	through-x
	.dc.w	through-x
	.dc.w	exec_caret-x
	.dc.w	exec_doller-x
	.dc.w	exec_lbracket-x
	.dc.w	exec_rbracket-x
	.dc.w	exec_lparen-x	* 未対応
	.dc.w	exec_rparen-x	* 未対応
	.dc.w	exec_refer-x	* 未対応
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	exec_main-x
	.dc.w	exec_branch-x
	.dc.w	exec_bind-x
*
exec_lparen:
exec_rparen:
exec_refer:
error:
	divu.w	#0,d0		* 内部エラー
*
through:
	PUT	d0
	rts
*
exec_term:
	lea.l	re_regs(pc),a6
	move.l	a0,reTAIL(a6)
	btst.l	#reFASTRETN_BIT,d3
	bne	fastretn
	rts
*
exec_caret:
	cmpi.w	#LF,d2
	beq	eclosureloop
	rts
*
exec_doller:
	move.b	(a0),d0
	beq	eclosureloop
	cmpi.b	#LF,d0
	beq	eclosureloop
	cmpi.b	#CR,d0
	bne	dollerretn
	cmpi.b	#LF,1(a0)
	beq	eclosureloop
dollerretn:
	rts
*
exec_lbracket:	* <
	tst.w	d2
	bmi	lbracketretn
	moveq.l	#CWORD,d0
	CTEST	d0,d2
	bne	lbracketretn
	moveq.l	#0,d1
	move.b	(a0),d1
	moveq.l	#CWORD,d0
	CTEST	d0,d1
	bne	eclosureloop
lbracketretn:
	rts
*
exec_rbracket:	* >
	tst.w	d2
	bmi	rbracket0
	moveq.l	#CWORD,d0
	CTEST	d0,d2
	beq	rbracketretn
rbracket0:
	moveq.l	#0,d1
	move.b	(a0),d1
	moveq.l	#CWORD,d0
	CTEST	d0,d1
	beq	eclosureloop
rbracketretn:
	rts
*
exec_main:
exec_branch:
	movea.w	(a1)+,a6
	adda.l	a1,a6
	tst.b	(a6)
	bmi	eclosureloop
	PUSH	a6
	bra	eclosureloop
*
exec_bind:
	movea.w	(a1)+,a6
	adda.l	a6,a1
	bra	eclosureloop
*
* 新たな文字入力によって遷移出来るかどうかを調べる
transit:
	move.w	#$00ff,d1
	and.w	(a1)+,d1
	move.w	jumptable(pc,d1.w),d1
	jmp	jumptable(pc,d1.w)
*
jumptable:
x	=	*
	.dc.w	error-x
	.dc.w	exec_literal-x
	.dc.w	exec_dot-x
	.dc.w	exec_class-x
	.dc.w	exec_nclass-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
*
exec_class:
	moveq.l	#7,d0
	move.w	d2,d1
	bmi	zenclass
	and.w	d1,d0
	lsr.w	#3,d1
	btst.b	d0,2(a1,d1.w)
	beq	classretn
matchclass:
	movea.w	(a1)+,a6
	adda.l	a6,a1
	bra	putit
*
zenclass:
	lsr.w	#8,d1
	and.w	d1,d0
	lsr.w	#3,d1
	btst.b	d0,2(a1,d1.w)
	beq	classretn
	lea.l	256/8+2(a1),a6
	bra	classloopent
classloop:
	cmp.w	d0,d2
	bcs	classnext
	cmp.w	(a6),d2
	bls	matchclass
classnext:
	addq.l	#2,a6
classloopent:
	move.w	(a6)+,d0
	bne	classloop
classretn:
	rts
*
exec_nclass:
	moveq.l	#7,d0
	move.w	d2,d1
	bmi	zennclass
	and.w	d1,d0
	lsr.w	#3,d1
	btst.b	d0,2(a1,d1.w)
	beq	matchclass
	rts
*
zennclass:
	lsr.w	#8,d1
	and.w	d1,d0
	lsr.w	#3,d1
	btst.b	d0,2(a1,d1.w)
	beq	matchclass
	lea.l	256/8+2(a1),a1
	bra	nclassloopent
nclassloop:
	cmp.w	d0,d1
	bcs	nclassnext
	cmp.w	(a1)+,d1
	bhi	nclassloopent
	rts
nclassnext:
	addq.l	#2,a1
nclassloopent:
	move.w	(a1)+,d0
	bne	nclassloop
*	bra	putit
*
putit:
exec_dot:
	PUT	a1
	rts
*
exec_literal:
	cmp.w	(a1)+,d2
	beq	putit
	rts
*
* 内部フラグをクリアする(d0.b=0で呼ぶこと)
skipword:
	addq.l	#2,a1
clrflag:
clrflagloop:
	move.b	d0,(a1)
	move.w	(a1)+,d1
	move.w	cjumptable(pc,d1.w),d1
	jmp	cjumptable(pc,d1.w)
skipclass:
	movea.w	(a1)+,a6
	adda.l	a6,a1
	bra	clrflagloop
clrflagretn:
	rts
*
cjumptable:
x	=	*
	.dc.w	clrflagretn-x
	.dc.w	skipword-x
	.dc.w	clrflagloop-x
	.dc.w	skipclass-x
	.dc.w	skipclass-x
	.dc.w	clrflagloop-x
	.dc.w	clrflagloop-x
	.dc.w	clrflagloop-x
	.dc.w	clrflagloop-x
	.dc.w	skipword-x
	.dc.w	skipword-x
	.dc.w	skipword-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	error-x
	.dc.w	skipword-x
	.dc.w	skipword-x
	.dc.w	skipword-x
*
	.bss
saved0:	.ds.l	1	* d0を保存するエリア

	.end
