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

#include "colmn.h"

#define NEWRET 1
#define NEORET 1

extern condList CLcList;		/* 情報リスト */
extern CLPRTBL  CLprocTable;	/* 情報リスト */
extern GlobalCt *pGlobTable;
extern char *PwCnCB;

/************************************/
/*									*/
/************************************/
static void _set_max_loop_count(proc)
ProcCT  *proc;
{
	BlockCB *next;

	next = proc->pTopBlockCB;
	while (next && next->iUsed) {
		if (next->cid == C_LOOP) next->iLoopCounter = 0x7ffffffe;
		next = next->nextBlockCB;
	}
}

/************************************/
/*									*/
/************************************/
static int _push_return(leaf,proc)
Leaf   *leaf;
ProcCT *proc;
{
	static Leaf	Retleaf;
	Leaf	*retleaf;

	retleaf = &Retleaf;
	memcpy(retleaf,leaf,sizeof(Leaf));
	retleaf->rightleaf = NULL;
	retleaf->leftleaf  = NULL;
	cl_copy_cmd(&(retleaf->cmd),&(leaf->cmd));
	retleaf->cmd.cid    = C_RETURN;
	retleaf->cmd.prmnum = -1;
	cl_ret_leaf_push(proc,retleaf);
	return 0;
}

/************************************/
/* cl_process_return                 */
/* function; check command of this  */
/*          leaf then call functions*/
/************************************/
int cl_process_return(leaf, proc)
Leaf    *leaf;
ProcCT  *proc;
{
	int rc,n,val[2];
	tdtInfoParm InfoParm,*pInfoParmW,*pInfoParm;

	if (!leaf || !proc) return ECL_SYSTEM_ERROR;

	rc = 0;
	/* if this return process is whithin loop process */
	/* process followed will be suspended.            */
/*
	if (cmn_chk_stat(LOP_PR,&proc->ptype) != L_OFF) {
		_set_max_loop_count(proc);
	}
*/
	/* check specification of return value */
	if (leaf->cmd.prmnum > 0) {
		rc = cl_gx_exp_obj(leaf->cmd.prmnum,&(leaf->cmd.prmp[0]),
		              proc->Obj,&InfoParm);
		if (rc) {
			ERROROUT2(FORMAT(48),"clprret",rc);	/* %s: 式が誤っていま。(rc=%d) */
			rc = ECL_EX_RETURN;
		}
		else {
			if (cmn_chk_stat(UFN_PR,&proc->ptype) == L_OFF) {
				rc = cl_get_parm_bin(&InfoParm,val,FORMAT(511));	/* リターン値: */
				if (!rc) {
					n = val[0];
					if (n < 0) PRINTOUT3("clprret: proc = %s, ret = %d %s",
					                     proc->ProcNM,n,akb_str_error(n));
					pGlobTable->error = n;
					pGlobTable->Return = n;
				/*	pGlobTable->exception = n;	*/
				}
			}
			else {
				if (pInfoParmW=proc->Retval) {
					if (rc = cl_gx_rep_info_set(pInfoParmW,&InfoParm,1)) return rc;
DEBUGOUT_InfoParm(110,"cl_process_return: proc=%s",pInfoParmW,proc->ProcNM,0);
				}
			}
		}
	}
	else if (!leaf->cmd.prmnum) {
		pGlobTable->error = 0;
		pGlobTable->Return = 0;
	/*	pGlobTable->exception = 0;	*/
	}
	cmn_set_stat(RET_PR,&proc->ptype,L_ON);
	proc->Nextleaf = NULL;
	if (proc->ucExcept > 0) {
/*	pGlobTable->try_level--;	*/
		rc = cl_back_with_finally(leaf,proc,_push_return);
	}
	return rc;
}

/************************************/
/* cl_process_throw                   */
/************************************/
int cl_process_throw(leaf, proc)
Leaf    *leaf;
ProcCT  *proc;
{
	int rc,n,val[2];
	tdtInfoParm InfoParm;

	rc = cl_gx_exp_obj(leaf->cmd.prmnum,&(leaf->cmd.prmp[0]),proc->Obj,&InfoParm);
	if (rc) {
		ERROROUT2(FORMAT(48),"cl_process_throw",rc);	/* %s: 式が誤っていま。(rc=%d) */
		rc = ECL_EX_RETURN;
	}
	else {
		rc = cl_get_parm_bin(&InfoParm,val,FORMAT(512));	/* 例外値: */
		if (!rc && (n = val[0])) {
			PRINTOUT2("Throw exception: proc = %s, exception = %d",proc->ProcNM,n);
			n = X_ABS(n);
			if (!(n & 0x7f000000)) n |= USER_EXCEPTION;
			pGlobTable->exception = ALL_EXCEPTION | n;
		}
	}
	return rc;
}

/************************************/
/*									*/
/************************************/
int cl_back_with_finally(leaf,proc,_push_return)
Leaf    *leaf;
ProcCT  *proc;
int (*_push_return)();
{
	int rc,cid;
	BlockCB *pcrLCB;

	if (!proc) return -1;

	pcrLCB = proc->pcrBlockCB;
	while (pcrLCB) {
/*
printf("cl_back_with_finally: cid=%08x\n",pcrLCB->cid);
*/
		if ((cid=pcrLCB->cid)==C_TRY) {
			rc = cl_pop_finally(proc,pcrLCB);
			if (rc) {
				if (rc == C_FINALLY) {
					_push_return(leaf,proc);
					rc= 0;
				}
				break;
			}
		}
		pcrLCB->iUsed = 0;
		pcrLCB = pcrLCB->preBlockCB;
	}
	proc->pcrBlockCB = pcrLCB;
	return rc;
}
