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],nparm,i;
	char *p,id;
	tdtInfoParm InfoParm[2],*pInfoParmW,*pInfoParm,*pInfoParm2,*pInfoParm1,*pInfo;

	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 */
	pInfoParm2 = InfoParm;
	if (leaf->cmd.prmnum > 0) {
		rc = cl_gx_exp_obj(leaf->cmd.prmnum,&(leaf->cmd.prmp[0]),
		              proc->Obj,pInfoParm2);
DEBUGOUT_InfoParm(110,"cl_process_return: pInfoParm2=",pInfoParm2,0,0);
		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) {
				if (rc=_ex_conv_parm_opt(&pInfoParm2,0,"NOT UFN_PR")) return ECL_EX_RETURN;
				rc = cl_get_parm_bin(pInfoParm2,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 0	/* 2019.5.11 */
					pInfoParm = pInfoParm2;
					if (rc=_ex_conv_parm_opt(&pInfoParm,0,"RETURN")) return ECL_EX_RETURN;
DEBUGOUT_InfoParm(110,"cl_process_return:",pInfoParm,0,0);
					if ((pInfoParm[0].pi_alen & D_AULN_PARMINFO2) &&
					    (nparm=pInfoParm[1].pi_pos)) {
						pInfoParm = (tdtInfoParm *)pInfoParm[1].pi_data;
						if (!(pInfoParm1=(tdtInfoParm *)Malloc(sizeof(tdtInfoParm)*2))) return -1;
						memcpy(pInfoParm1,pInfoParm2,sizeof(tdtInfoParm)*2);
						pInfo = pInfoParm1 + 1;
						pInfo = (tdtInfoParm *)pInfo->pi_data;
						for (i=0;i<nparm;i++,pInfoParm++,pInfo++) {
							if (rc=cl_gx_rep_info_set(pInfo,pInfoParm,1)) return rc;
DEBUGOUT_InfoParm(110,"cl_process_return: i=%d",pInfo,i,0);
						}
					/*	pInfoParm2 = pInfoParm1;	*/
						cl_set_parm_long(pInfoParm2,(long)pInfoParm1);
						pInfoParm2->pi_id = D_DATA_ID_STOREVAR;
						pInfoParm2->pi_scale |= D_DATA_MALLOC;
					}
#endif
					if (!(proc->pFlag & D_PFLAG_DEF_CLASS)
#if 1	/* 2021.9.13 */
					    && ((id=pInfoParm2->pi_id)==D_DATA_ID_MAPEDARY ||
						    id==D_DATA_ID_ARRAY || id==D_DATA_ID_STRUCT)
#endif
					   ) pInfoParm2->pi_aux[0] |= DEF_ZOK_DATA;
#if 1	/* 2021.10.27 */
					if (rc = cl_gx_rep_info_als(pInfoParmW,pInfoParm2,1)) return rc;
#else
					if (rc = cl_gx_rep_info_set(pInfoParmW,pInfoParm2,1)) return rc;
#endif
DEBUGOUT_InfoParm(110,"cl_process_return: proc=%s pFlag=%02x",pInfoParmW,proc->ProcNM,proc->pFlag);
				}
			}
		}
	}
	else if (!leaf->cmd.prmnum) {
		pGlobTable->error = 0;
		pGlobTable->Return = 0;
	}
	cmn_set_stat(RET_PR,&proc->ptype,L_ON);
	proc->Nextleaf = NULL;
	if (proc->ucExcept > 0) {
		rc = cl_back_with_finally(leaf,proc,_push_return);
	}
/*
printf("cl_process_return: rc=%d\n",rc);
*/
DEBUGOUTL2(110,"cl_process_return:Exit: rc=%d exception=%08x",rc,pGlobTable->exception);
	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;
}
