static	char	sccsid[]="%Z% %M% %I% %E% %U%";
/****************************************************/
/* <clprbreak.c>									*/
/*		break process								*/
/****************************************************/

#include "colmn.h"

/************************************/
/*									*/
/************************************/
static int _push_break(leaf,proc,n,cid)
Leaf   *leaf;
ProcCT *proc;
int n,cid;
{
	static Leaf	Retleaf;
	Leaf	*retleaf;
/*
printf("_push_break: n=%d cmd=%08x %s\n",n,cid,cl_gets_cmd_name(cid));
*/
	retleaf = &Retleaf;
	memcpy(retleaf,leaf,sizeof(Leaf));
	retleaf->rightleaf = NULL;
	retleaf->leftleaf  = NULL;
	cl_copy_cmd(&(retleaf->cmd),&(leaf->cmd));
	retleaf->cmd.sub_cid = cid;
	retleaf->cmd.parnum = n;
	retleaf->cmd.prmnum = 0;
	retleaf->cmd.prmp = NULL;
	cl_ret_leaf_push(proc,retleaf);
	return 0;
}

/************************************/
/*									*/
/************************************/
int cl_pop_finally(proc,pcrLCB)
ProcCT *proc;
BlockCB *pcrLCB;
{
	static int try_cida[]={C_CATCH,C_FINALLY,C_ENDTRY,0};
	Leaf    *leafw;

	if (!(leafw=cl_ret_leaf_pop_search(proc,try_cida,3))) return -1;
	while (leafw) {
		if (leafw->cmd.cid == C_FINALLY) {
			proc->pcrBlockCB = pcrLCB;
			proc->Nextleaf = leafw;
			return C_FINALLY;
		}
		leafw=leafw->rightleaf;
	}
	/* 前のTRY状態に戻す */
	proc->pFlag = pcrLCB->pFlag;
	proc->ucExcept = pcrLCB->ucExcept;
	return 0;
}

/************************************/
/* _check_in_loop					*/
/************************************/
static int _check_in_loop(proc)
ProcCT  *proc;
{
	if (!cmn_chk_stat(LOP_PR,&proc->ptype)) {
		ERROROUT("Outside of loop !!");
		return ECL_SCRIPT_ERROR;
	}
	return 0;
}

/************************************/
/* _check_in_loop_switch			*/
/************************************/
BlockCB *_check_in_loop_switch(proc)
ProcCT  *proc;
{
	BlockCB *pcrLCB;
	int cmd;

	pcrLCB = proc->pcrBlockCB;
	while (pcrLCB) {
		cmd = pcrLCB->cid;
/*
printf("_check_in_loop_switch: cmd=%08x %s\n",cmd,cl_gets_cmd_name(cmd));
*/
		if (cmd==C_LOOP || cmd==C_FOR || cmd==C_DO || cmd==C_SWITCH) return pcrLCB;
		pcrLCB = pcrLCB->preBlockCB;
	}
	return NULL;
}


/************************************/
/* _set_up_level					*/
/************************************/
static int _set_up_level(leaf,proc,ip,msg,err,cmd)
Leaf    *leaf;
ProcCT  *proc;
int      ip;
char    *msg;
int      err;
int      cmd;
{
	int rc,level,n,cid;
	char *nam,*p;
	uchar c;
	BlockCB *pcrLCB;
	tdtInfoParm InfoParm;
/*
printf("_set_up_level: cmd=%08x %s parnum=%d\n",
cmd,cl_gets_cmd_name(cmd),leaf->cmd.parnum);
*/
	nam = NULL;
	if (leaf->cmd.sub_cid > 0) {
		level = leaf->cmd.parnum;
	}
	else if (leaf->cmd.prmnum > ip) {
		level = 0;
		/* 2021.4.7 */
		rc = cl_arg_to_char_num(leaf->cmd.prmp[ip],proc->Obj,&InfoParm,msg,0,0);

DEBUGOUT_InfoParm(110,"_set_up_level: rc=%d",&InfoParm,rc,0);

		if (rc) {
			if (rc == ECL_NULL_DATA) level = 1;
			else return rc;
		}
		else if (InfoParm.pi_attr == DEF_ZOK_CHAR) {
			if (cl_is_name((p=InfoParm.pi_data),InfoParm.pi_dlen) > 0) nam = p;
/*
printf("_set_up_level: dlen=%d data=[%s]\n",InfoParm.pi_dlen,p);
*/
		}
		if (!level && !nam) {
			if (rc=cl_get_parm_long(&InfoParm,&level,msg)) return rc;

DEBUGOUTL1(110,"_set_up_level: level=%d",level);

			if (level < 0) {
				ERROROUT2(FORMAT(411),msg,level);	/* %sレベル(%d)が不正です。 */
				return err;
			}
			else if (!level) return C_SKIP_COMMAND;
		}
	}
	else level = 1;

	pcrLCB = proc->pcrBlockCB;
	n = level;
	for (;;) {
		if (!pcrLCB) {
			if (nam)
				ERROROUT2("%s[%s]ブロックが見つかりません。",msg,nam);
			else
				ERROROUT2(FORMAT(412),msg,level);	/* %sレベル(%d)がオーバです。 */
			return err;
		}

DEBUGOUTL4(200,"_set_up_level: pcrLCB=%08x n=%d cid=%08x %s",pcrLCB,n,pcrLCB->cid,cl_gets_cmd_name(pcrLCB->cid));

		if ((cid=pcrLCB->cid)==C_TRY) {
			rc = cl_pop_finally(proc,pcrLCB);
			if (rc) {
				if (rc == C_FINALLY) {
					_push_break(leaf,proc,n,cmd);
				}
				return rc;
			}
		}
		else if (cid==C_LOOP || cid==C_FOR || cid==C_DO || cid==C_SWITCH) {
			if (nam && (p=pcrLCB->BlockName)) {
				if (!strcmp(nam,p)) break;
			}
			else
			if (--n <= 0) break;
		}
		pcrLCB->iUsed = 0;
		pcrLCB = pcrLCB->preBlockCB;
	}

DEBUGOUTL1(110,"_set_up_level: pcrLCB->Blockleaf=%08x",pcrLCB->Blockleaf);

	proc->pcrBlockCB = pcrLCB;
	return 0;
}

/************************************/
/* cl_process_break					*/
/************************************/
int cl_process_break(leaf, proc)
Leaf    *leaf;
ProcCT  *proc;
{
	return cl_pr_break(leaf,proc,0);
}

/************************************/
/* cl_pr_break						*/
/************************************/
int cl_pr_break(leaf, proc, ip)
Leaf    *leaf;
ProcCT  *proc;
int      ip;
{
	int rc,cmd;
	BlockCB *pIfCB;
/*
printf("cl_pr_break: leaf=%08x proc=%08x\n",leaf,proc);
*/
	if (!leaf || !proc) return ECL_SYSTEM_ERROR;

DEBUGOUTL5(110,"cl_process_break: cmd=%08x %s sub_cmd=%08x %s parnum=%d",
leaf->cmd.cid,cl_gets_cmd_name(leaf->cmd.cid),
leaf->cmd.sub_cid,cl_gets_cmd_name(leaf->cmd.sub_cid),leaf->cmd.parnum);

	rc = 0;
	if ((cmd=leaf->cmd.sub_cid) > 0) ;
	else {
		if (!(pIfCB = _check_in_loop_switch(proc))) {
			ERROROUT("Outside of loop or switch!!");
			rc = ECL_SCRIPT_ERROR;
		}
		cmd = pIfCB->cid;
	}
	if (!rc) {
		rc = _set_up_level(leaf,proc,0,"cl_process_break: ",ECL_EX_BREAK,cmd);

DEBUGOUTL1(110,"cl_process_break: rc=%d",rc);

		if (!rc) {
			if (!(pIfCB = proc->pcrBlockCB)) return -1;
			if (pIfCB->cid == C_SWITCH) {
				pIfCB->iLoopMax = C_BREAK;
				rc = cl_set_continue(leaf,proc);
			}
			else {
				pIfCB->iLoopCounter = 0x7ffffffe;
				cmn_set_stat(BRK_PR,&proc->ptype,L_ON);
				rc = cl_set_continue(leaf,proc);
			}
		}
		else if (rc == C_SKIP_COMMAND) rc = 0;
		else if (rc == C_FINALLY) {
			cmn_set_stat(BRK_PR,&proc->ptype,L_ON);
			rc = 0;
		}
	}
	return rc;
}

/************************************/
/* cl_set_continue					*/
/************************************/
int cl_set_continue(leaf,proc)
Leaf    *leaf;
ProcCT  *proc;
{
	int rc;
	BlockCB *pcrLCB;
	Leaf   *loop_leaf,*leafw;

	loop_leaf = NULL;
	if (pcrLCB=proc->pcrBlockCB) {
		if (pcrLCB->iUsed) loop_leaf = pcrLCB->Blockleaf;
	}

DEBUGOUTL3(110,"cl_set_continue: pcrLCB=%08x iUsed=%d loop_leaf=%08x",pcrLCB,pcrLCB->iUsed,loop_leaf);

	if (loop_leaf) {
		while (leafw=cl_ret_leaf_pop(proc)) {

DEBUGOUTL1(190,"cl_set_continue: leafw=%08x",leafw);

			if (leafw == loop_leaf) break;
		}
		if (leafw) {
			proc->Nextleaf = loop_leaf;
DEBUGOUTL1(110,"cl_set_continue: found leaf=%08x",loop_leaf);
			rc = 0;
		}
		else rc = ECL_SYSTEM_ERROR;
	}
	else rc = ECL_SYSTEM_ERROR;
	return rc;
}

/************************************/
/* cl_process_continue				*/
/************************************/
int cl_process_continue(leaf, proc)
Leaf    *leaf;
ProcCT  *proc;
{
	return cl_pr_continue(leaf,proc,0);
}

/************************************/
/* cl_pr_continue					*/
/************************************/
int cl_pr_continue(leaf, proc, ip)
Leaf    *leaf;
ProcCT  *proc;
int      ip;
{
	int rc;
	BlockCB *pIfCB;

	if (leaf && proc) {

DEBUGOUTL5(110,"cl_pr_continue: cmd=%08x %s sub_cmd=%08x %s parnum=%d",
leaf->cmd.cid,cl_gets_cmd_name(leaf->cmd.cid),
leaf->cmd.sub_cid,cl_gets_cmd_name(leaf->cmd.sub_cid),leaf->cmd.parnum);

		/* 2017.3.12 */
		if (!(pIfCB = _check_in_loop_switch(proc))) {
			ERROROUT("Outside of loop or switch!!");
			rc = ECL_SCRIPT_ERROR;
		}
		else {
			rc = _set_up_level(leaf,proc,ip,"cl_pr_continue: ",ECL_EX_CONTINUE,0);
			/* 2017.3.12 */
			if (!rc) {
				if (!(pIfCB = proc->pcrBlockCB)) return -1;
				if (pIfCB->cid == C_SWITCH) {
					pIfCB->iLoopMax = C_BREAK;
					rc = cl_set_continue(leaf,proc);
				}
				else
					rc = cl_set_continue(leaf,proc);
			}
 			else if (rc == C_SKIP_COMMAND) rc = 0;
			else if (rc == C_FINALLY) {
				cmn_set_stat(BRK_PR,&proc->ptype,L_ON);
				rc = 0;
			}
		}
	}
	else rc = ECL_SYSTEM_ERROR;

	return rc;
}
