static	char	sccsid[]="%Z% %M% %I% %E% %U%";
/****************************************************/
/*													*/
/*	optimize for obj by tree						*/
/*													*/
/*		coded by A.Kobayashi 2021.09.28				*/
/*													*/
/*==================================================*/
/*	       int cl_gx_cr_tree(obj,iobj,tree)			*/
/*	static int _gx_cr_nest(is,tree,nest,nnest)		*/
/*         int cl_gx_cr_nest0(tree,nest)			*/
/*         int cl_gx_chk_tree(is,tree)				*/
/****************************************************/
/*	  error code : -215240101〜-215249999	*/
#include "colmn.h"

/* 01 */
int cl_gx_cr_tree(pbxObj)
GXObject *pbxObj;
{
	short *rstk,*obj;
	int rc,i,ib,irs,ntr,nob,iva[2];
	char **da;
/*	MCAT Ms_tree;	*/
	WHERE_TREE *tree;

	nob = pbxObj->nobj;
/*
printf("cl_gx_cr_tree:Enter nob=%d\n",nob);
*/
	if (nob < 1) return 0;
	if (!(rstk = (short *)cl_tmp_const_malloc(nob/2))) return ECL_MALLOC_ERROR;
	if (!(tree = (WHERE_TREE *)cl_tmp_const_malloc(nob+3))) return ECL_MALLOC_ERROR;
/*	cl_gx_init_expand(&Ms_tree,"TR",sizeof(short),nob+3);
	cl_gx_expand(&Ms_tree,0,NULL);	*/
	obj = pbxObj->obj;
	da  = pbxObj->da;
/*	obj0 = pbxObj->obj0;	*/
	ib = irs = 0;
	ntr = 1;
	iva[0] = ib;
	iva[1] = irs;
	ntr = cl_gx_cr_tree_sub(obj,nob,da,tree,ntr,rstk,iva);
/*	cl_gx_expand(&Ms_tree,-1,&tree);	*/
	pbxObj->tree = tree;	/* add 2022.1.25 */	
	pbxObj->ntree = ntr;	/* add 2022.1.25 */

if (DEBUGOUTCHECK(155)) {
char dummy[128];
DEBUGOUTL1(155,"cl_gx_cr_tree: ntr=%d",ntr);
for (i=0;i<ntr;i++) {
sprintf(dummy,"i=%d mcode=%d t1=%d t2=%d lv=%d rv=%d t3=%d",
i,tree[i].mcode,tree[i].t1,tree[i].t2,tree[i].lv,tree[i].rv,tree[i].t3);
DEBUGOUTL1(155,"%s",dummy);
}
}

	return ntr;
}

#if 1
static int _push_exec_obj(tree,ntr,itr)
WHERE_TREE tree[];
int ntr,itr;
{
	short *obj;
	int n;

	obj = (short *)&tree[ntr-1];
	n = obj[1];
	if (obj[0] || (!obj[0] && n>=6)) {
		obj = (short *)&tree[ntr++];
		memset(obj,0,sizeof(WHERE_TREE));
		obj[1] = 1;
		obj[2] = itr;
	}
	else {
		n++;
		obj[n+1] = itr;
		obj[1] = n;
	}
	return ntr;
}
#endif

int cl_gx_cr_tree_sub(obj,nob,da,tree,ntr,rstk,iva)
short obj[],rstk[];
char *da[];
WHERE_TREE tree[];
int ntr,nob,iva[];
{
	int rc,irs,itr,iob,i,ntr0,itw;
	int ib,mc,rdt,v,a,b,t,j,mc1,itr0,mm,kind,m_f,max_tree,max_stack;
/*	short *tree;	*/
	char c,c0,*p,wrk[2];

	ib  = iva[0];
	irs = iva[1];
/*
printf("cl_gx_cr_tree_sub:Enter nob=%d ib=%d irs=%d ntr=%d\n",nob,ib,irs,ntr);
*/
	if (nob < 1) return 0;
	max_tree = nob+3;
	max_stack = nob/2;
/*
printf("cl_gx_cr_tree_sub: max_tree=%d max_stack=%d\n",max_tree,max_stack);
*/
/*	cl_gx_expand(Ms_tree,-1,&tree);	*/
	ntr0 = ntr;
	rc = 0;
	while (ib < nob) {
		mc = obj[ib++];
/*
printf("cl_gx_cr_tree_sub: ib+1=%d mc=%d irs=%d ntr=%d\n",ib,mc,irs,ntr);
*/
		if (ntr >= max_tree) {
			rc = ERROR_MAX_TREE;
			break;
		}
		if (irs < 0) {
			rc = ERROR_MIN_STACK;
			break;
		}
		else if (irs > max_stack) {
			rc = ERROR_MAX_STACK;
			break;
		}
		if (!mc || mc==60) ;
		else if (mc == 99) {
/*
printf("cl_gx_cr_tree_sub: mc=%d irs=%d\n",mc,irs);
*/
			if (irs<0) {
				rc = -215240101;
				break;
			}
			else if (irs >= 1) {
				b = rstk[--irs];
				if ((mc1=tree[b].mcode)==91 || mc1==92) b = 0;
				tree[ntr].mcode = mc;
				tree[ntr].t2 = b;
				tree[ntr].t1 = 0;
				tree[ntr].lv = 0;
				tree[ntr].rv = 0;
				tree[ntr].t3 = 0;
				rstk[irs++]=ntr++;
				irs--;
				ntr = rstk[irs];
/*
printf("cl_gx_cr_tree_sub: mc=%d rstk[%d]=%d\n",mc,irs,ntr);
*/
				if ((mc=tree[ntr-1].mcode)==91 || mc==92) {
					tree[ntr].lv = 1;
					tree[ntr].rv = irs + 1;
				}
				else if (irs > 0) {
					mm = 0;
					while (irs > 0) {
						b = rstk[--irs];
						if ((mc1=tree[b].mcode)==91 || mc1==92) mm++;
						else break;
					}
					tree[ntr].lv = b;
					tree[ntr].rv = mm;
				}
				tree[0].mcode = tree[ntr].mcode;
				tree[0].t2    = tree[ntr].t2;
				tree[0].t1    = tree[ntr].t1;
				tree[0].lv    = tree[ntr].lv;
				tree[0].rv    = tree[ntr].rv;
				tree[0].t3 = 0;
/*
printf("cl_gx_cr_tree_sub: ntr=%d mcode=%d t1=%d t2=%d\n",0,tree[0].mcode,tree[0].t1,tree[0].t2);
*/
			}
			rc = ntr;
			break;
		}
		else if (mc==91 || mc==92) {
			tree[ntr].mcode = mc;
			tree[ntr].t1 = obj[ib];
			tree[ntr].t2 = 0;
			tree[ntr].lv = ib++;
			tree[ntr].rv = 0;
			tree[ntr].t3 = 0;
/*
printf("cl_gx_cr_tree_sub: ntr=%d mcode=%d t1=%d t2=%d lv=%d rv=%d\n",
ntr,tree[ntr].mcode,tree[ntr].t1,tree[ntr].t2,tree[ntr].lv,tree[ntr].rv);
*/
			rstk[irs++]=ntr++;
/*
printf("cl_gx_cr_tree_sub: mc=%d obj=%d rstk[%d]=%d\n",mc,obj[ib-1],irs-1,rstk[irs-1]);
*/
		}
		else if (mc==1 || mc==3 || mc==6 || mc==5 || mc==7) {	/* (), [データ並び], 配列, 関数, {} */
			if (mc==3 || mc==6) c0 = '[';
			else if (mc==7) c0 = '{';
			else c0 = '(';
			irs--;
			itr0 = itr = rstk[irs];
/*
printf("cl_gx_cr_tree_sub: itr=%d irs=%d mc=%d start find %c\n",itr,irs,mc,c0);
*/
			m_f = mm = 0;
			ntr0 = ntr;
			while (irs >= 0) {
				itr = rstk[irs];
				mc1 = tree[itr].mcode;
/*
printf("cl_gx_cr_tree_sub: itr=%d irs=%d mc1=%d\n",itr,irs,mc1);
*/
				if (mc > 1) {
#if 1
					ntr = _push_exec_obj(tree,ntr,itr);
#else
					memset(&tree[ntr],0,sizeof(WHERE_TREE));
					tree[ntr++].t1 = itr;
#endif
				}
				if (mc1==91 || mc1==92) {
					mm++;
					i = tree[itr].lv;
					i = obj[i];
/*
printf("cl_gx_cr_tree_sub: itr=%d irs=%d i=%d da[i]=[%s] mm=%d\n",itr,irs,i,da[i],mm);
*/
					if (*da[i] == c0) {
/*
printf("cl_gx_cr_tree_sub: found\n");
*/
						if (mc==5 || mc==6) {
							itw = rstk[irs-1];
#if 1
							ntr = _push_exec_obj(tree,ntr,itw);
#else
							memset(&tree[ntr],0,sizeof(WHERE_TREE));
							tree[ntr++].t1 = itw;
#endif
						}
						break;
					}
				}
			/*	else if (mc > 1) m_f = 1;	del 2022.2.1 */
				irs--;
			}
			m_f = 1;	/* add 2022.2.1 */
			if (itr<0 || irs<0) {
/*
printf("cl_gx_cr_tree_sub: i=%d irs=%d\n",itr,irs);
*/
				wrk[0] = c0;
				wrk[1] = '\0';
				/* %s: %sがありません。 */
				ERROROUT2(FORMAT(76),"cl_gx_cr_tree",wrk);
				rc = -215240103;
				break;
			}
			if (mc == 1) {
				if (irs<0) {
					rc = -215240104;
					break;
				}
			/*	if (!m_f) ntr = ntr0;	*/
				tree[ntr].mcode = mc;
				tree[ntr].t2 = itr0;	/*rstk[--irs];*/
				tree[ntr].t1 = itr;		/*rstk[--irs];*/
				tree[ntr].lv = 0;
				tree[ntr].rv = 0;
				tree[ntr].t3 = 0;
			}
			else {
				if (mc==3 || mc==7) mm--;
				else {
					itr--;
					irs--;
				}
#if 0	/* 2022.12.1 */
				if ((a=irs-1) < 0) a = 0;
				if ((mc1=tree[itr0].mcode)==91 || mc1==92) {
					if (mc==5 || mc==6) a = 0;
					itr0 = a;
				}
#endif
				if (m_f) {
					itr0 = 0;
					m_f = ntr0;
				}
				else ntr = ntr0;
				tree[ntr].mcode = mc;
				tree[ntr].t2 = 0;
				tree[ntr].t1 = itr0;	/*a;*/
				tree[ntr].lv = itr;
				tree[ntr].rv = mm + 1;
				tree[ntr].t3 = m_f;
			}
/*
printf("cl_gx_cr_tree_sub: ntr=%d mcode=%d t1=%d t2=%d lv=%d rv=%d\n",
ntr,tree[ntr].mcode,tree[ntr].t1,tree[ntr].t2,tree[ntr].lv,tree[ntr].rv);
*/
			rstk[irs++]=ntr++;
/*
printf("cl_gx_cr_tree_sub: mc=%d rstk[%d]=%d\n",mc,irs-1,rstk[irs-1]);
*/
		}
		else if (mc==98) {	/* , obj[]には現れない */
		}
		else if (mc<0				/* 単項演算子 + - */
		   /*||(mc == D_IMD_RANGE)*/) {			/* 95 .. */
			if (irs<1) {
				rc = -215240106;
				break;
			}
			b = rstk[--irs];
			tree[ntr].mcode = mc;
			tree[ntr].t2 = b;
			tree[ntr].t1 = 0;
			tree[ntr].lv = ib;	/*0;*/
			tree[ntr].rv = 0;
			tree[ntr].t3 = 0;
/*
printf("cl_gx_cr_tree_sub: ntr=%d mcode=%d t1=%d t2=%d lv=%d rv=%d\n",
ntr,tree[ntr].mcode,tree[ntr].t1,tree[ntr].t2,tree[ntr].lv,tree[ntr].rv);
*/
			rstk[irs++]=ntr++;
/*
printf("cl_gx_cr_tree_sub: mc=%d b=%d rstk[%d]=%d\n",mc,b,irs-1,rstk[irs-1]);
*/
		}
		else if ((mc>=1 && mc<=52) || mc==96 || mc==97
		      || (mc>=71 && mc<=90)	/* 代入演算子 */
		      || (mc==D_IMD_RANGE)
		        ) {	/* 95 .. */
			if (irs<2) {
				rc = -215240107;
				break;
			}
			tree[ntr].mcode = mc;
			tree[ntr].t2 = rstk[--irs];
			tree[ntr].t1 = rstk[--irs];
			tree[ntr].lv = ib;	/*0;*/
			tree[ntr].rv = 0;
			tree[ntr].t3 = 0;
/*
printf("cl_gx_cr_tree_sub: ntr=%d mcode=%d t1=%d t2=%d\n",ntr,tree[ntr].mcode,tree[ntr].t1,tree[ntr].t2);
*/
			rstk[irs++]=ntr++;
/*
printf("cl_gx_cr_tree_sub: mc=%d rstk[%d]=%d\n",mc,irs-1,rstk[irs-1]);
*/
		}
		else if (mc == 59) {	/* ? */
			iva[0] = ib - 1;
			iva[1] = irs;
			if ((ntr=cl_gx_cr_tree_3kou(obj,nob,da,tree,ntr,rstk,iva)) < 0) return ntr;
			ib  = iva[0];
			irs = iva[1];
		}
#if 0
		else if (mc == 93) {	/* GOTO */
		}
#endif
		else {
			rc = -215240198;
			break;
		}
	}
/*
printf("cl_gx_cr_tree_sub: rc=%d mc=%d ib=%d ntr=%d irs=%d\n",rc,mc,ib,ntr,irs);
for (i=ntr0;i<ntr;i++) {
printf("i=%d mcode=%d t1=%d t2=%d lv=%d rv=%d t3=%d\n",
i,tree[i].mcode,tree[i].t1,tree[i].t2,tree[i].lv,tree[i].rv,tree[i].t3);
}
*/
	iva[0] = ib;
	iva[1] = irs;
	if (!rc) rc = ntr;
	return rc;
}

/* 02 */
static int _gx_cr_nest(is,tree,nest,nnest)
int is;
short *nest,nnest;
WHERE_TREE *tree;
{
	int mc,i1,i2;

	mc = tree[is].mcode;
	if (mc == 51) {	/* and */
		i1 = tree[is].t1;
		i2 = tree[is].t2;
/*
printf("cr_nest:is=%d,mc=%d,i1=%d,i2=%d\n",is,mc,i1,i2);
*/
		if (tree[i1].mcode) nnest = _gx_cr_nest(i1,tree,nest,nnest);
		if (tree[i2].mcode) nnest = _gx_cr_nest(i2,tree,nest,nnest);
	}
	else {
		if (nnest >= FIL_MAX_NEST) return ERROR_MAX_NEST;
		nest[nnest++] = is;
/*
printf("cr_nest:nnest=%d,is=%d\n",nnest,is);
*/
	}
	return nnest;
}

/* 03 */
#if 1
int cl_gx_cr_nest0(tree,nest,nest_flg)
#else
int cl_gx_cr_nest0(bndp,tree,nest,nest_flg)
SQLDA_FIL *bndp;
#endif
WHERE_TREE *tree;
short *nest,*nest_flg;
{
	int i,rc,nnest;

	nnest = _gx_cr_nest(0,tree,nest,0);
	if (nnest < 0) return nnest;
	for (i=0;i<nnest;i++) {
#if 1
		rc = cl_gx_chk_tree(nest[i],tree);
#else
		rc = cl_gx_chk_tree(bndp,nest[i],tree);
#endif
/*
printf("cr_nest0_tree:i=%d,rc=%d\n",i,rc);
*/
		nest_flg[i] = rc;
	}
	return nnest;
}

/* 04 */
#if 1
int cl_gx_chk_tree(is,tree)
#else
int cl_gx_chk_tree(bndp,is,tree)
SQLDA_FIL *bndp;
#endif
int is;
WHERE_TREE *tree;
{
	int mc,i1,i2;
	int i,rc=0;
#if 0
	mc = tree[is].mcode;
	i1 = tree[is].t1;
	i2 = tree[is].t2;
	if (mc) {
/*
printf("chk_tree:is=%d,mc=%d,i1=%d,i2=%d\n",is,mc,i1,i2);
*/
		if (i1>0) {
#if 1
			rc = cl_gx_chk_tree(i1,tree);
#else
			rc = cl_gx_chk_tree(bndp,i1,tree);
#endif
			if (rc) return rc;
		}
		if (i2>0)
#if 1
			rc = cl_gx_chk_tree(i2,tree);
#else
			rc = cl_gx_chk_tree(bndp,i2,tree);
#endif
	}
	else {
/*
printf("chk_tree:is=%d,mc=%d,i1=%d\n",is,mc,i1);
*/
		/* rowid 以外のカラムがあり、インデックスが張ってないとき、１にする */
#if 1
		if ((i1>101 && i1<201) || (i1>201 && i1<301)) rc = 1;
#else
		if (i1>101 && i1<201) {
			if (!bndp->M[i1-101]) rc = 1;
		}
		else if (i1>201 && i1<301) {
			if (!bndp->M[i1-201]) rc = 1;
		}
#endif
	}
#else
	rc = 1;
#endif
	return rc;
}

static int _srch_93(obj,nob,ib)
short obj[];
int nob,ib;
{
	int rc,mc,kind,m;

	rc = 0;
	while (ib < nob) {
		mc = obj[ib++];
		if (mc==91 || mc==92) ib++;
		else if (mc == 59) {
			kind = obj[ib++];
			m = obj[ib++];
			if (kind<=1 || kind==5) {
				if ((ib=_srch_93(obj,ib+m-1,ib)) < 0) return ib;
			}
			else ib += m - 1;
		}
		else if (mc == 93) {
			rc = ib;
			break;
		}
	}
/*
printf("_srch_93: ib=%d mc=%d\n",ib,mc);
*/
	if (!rc) {
/*
printf("_srch_93: not found 93\n");
*/
		rc = -ib;
	}
	return rc;
}

int cl_gx_cr_tree_3kou(obj,nob,da,tree,ntr,rstk,iva)
short obj[],rstk[];
char *da[];
WHERE_TREE tree[];
int ntr,nob,iva[];
{
	int irs,ib,rc,i,b,ib0,mc,kind,m,ntr0,t;
	int ib1,ib2,nob1,nob2;

	ib  = iva[0];
	irs = iva[1];

	if (irs<1) return -215240106;
	b = rstk[--irs];
	mc = obj[ib++];
	ib0 = ib;
	kind = obj[ib++];
	m = obj[ib++];
/*
printf("cl_gx_cr_tree_3kou: b=%d mc=%d kind=%d m=%d ib=%d\n",b,mc,kind,m,ib);
*/
	tree[ntr].mcode = mc;
	tree[ntr].t2 = b;
	tree[ntr].t1 = 0;
	tree[ntr].lv = ib0;
	tree[ntr].rv = 0;
	tree[ntr].t3 = ntr + 1;
	if (kind == 5) tree[ntr].rv = rstk[--irs];
	rstk[irs++] = ntr++;
	ntr0 = ntr;
	tree[ntr].mcode = 0;
	tree[ntr].t2 = 0;
	tree[ntr].t1 = 0;
	tree[ntr].lv = 0;
	tree[ntr].rv = 0;
	tree[ntr].t3 = 0;
	ntr++;
	ib0 = ib;
	if (kind > 0) ib0 += 3;

	if (kind<=1 || kind==5) {
		if ((ib=_srch_93(obj,ib+m-1,ib)) < 0) return ib;
		ib1 = ib0;
		nob1 = ib - 1;
		ib2 = ib + 1;
		nob2 = ib + obj[ib];
	}
	else {
		ib1 = ib0;
		nob1 = ib + m - 1;
		ib2 = nob2 = 0;
	}
	iva[0] = ib1;
	iva[1] = irs;
/*
	if (kind <= 1) nob = ib + m - 3;
	else nob = ib + m - 1;
*/
/*
printf("cl_gx_cr_tree_3kou:1 ib1=%d nob1=%d\n",ib1,nob1);
*/
	if ((ntr=cl_gx_cr_tree_sub(obj,nob1,da,tree,ntr,rstk,iva)) < 0) return ntr;
	if (iva[1] > irs) {
		irs = iva[1];
		tree[ntr0].t1 = rstk[--irs];
	}
	nob = nob1;
/*
printf("cl_gx_cr_tree_3kou:t1 ntr=%d irs=%d\n",ntr,irs);
*/
	if (nob2 > 0) {
/*
printf("cl_gx_cr_tree_3kou:2 ib2=%d nob2=%d\n",ib2,nob2);
*/
		iva[0] = ib2;
		iva[1] = irs;
		if ((ntr=cl_gx_cr_tree_sub(obj,nob2,da,tree,ntr,rstk,iva)) < 0) return ntr;
		if (iva[1] > irs) {
			irs = iva[1];
			tree[ntr0].t2 = rstk[--irs];
		}
		nob = nob2;
/*
printf("cl_gx_cr_tree_3kou:t2 ntr=%d irs=%d\n",ntr,irs);
*/
	}
	iva[0] = nob;
	iva[1] = irs;
	return ntr;
}
