static char sccsid[]="%Z% %M% %I% %E% %U%";
/****************************************************************************
*																			*
*	処理目的	：	クラス処理												*
*																			*
*	処理概要	：															*
*																			*
*****************************************************************************/
#include "colmn.h"

extern CLPRTBL  *pCLprocTable;
extern GlobalCt *pGlobTable;
extern int giOptions[];

/****************************************/
/*										*/
/****************************************/
int cl_gx_new(pInfoParmW,pInfoParm2)
tdtInfoParm *pInfoParmW,*pInfoParm2;
{
	ScrPrCT *pScCT;
	ProcCT  *cur_procct;
	Leaf    *leaf;
	char *name,id;

	pGlobTable->options[7] |= 0x02;
	if (cl_check_data_id(pInfoParm2,~0x80)) return ECL_SCRIPT_ERROR;
	leaf = NULL;
	id = pInfoParm2->pi_id;
	name = pInfoParm2->pi_data;
/*
printf("cl_gx_new: id=[%c] name=[%s]\n",id,name);
*/
	if (id == 'C') {
		if (!(leaf=(Leaf *)pInfoParm2->pi_pos)) {
			/* %s: クラス[%s]へのパスがありません */
			ERROROUT2(FORMAT(546),"cl_gx_new",name);
			return ECL_SCRIPT_ERROR;
		 }
	}
	else if (id == ' ') {
		if (pScCT = cl_search_src_ct()) {
			cur_procct = cl_search_proc_ct();
			if (!(leaf=cl_search_class_leaf_and_inner(pScCT,cur_procct,name,NULL))) {
				/* %s: クラス[%s]は未定義です。 */
				ERROROUT2(FORMAT(548),"cl_gx_new",name);
				return ECL_SCRIPT_ERROR;
			}
		}
	}
	else {
		ERROROUT1("cl_gx_new: [%s]はCLASSではありません。",name);
		return ECL_SCRIPT_ERROR;
	}
/*
printf("cl_gx_new: name=[%s] leaf=%08x\n",name,leaf);
*/
	if (leaf) {
		*pInfoParmW = *pInfoParm2;
		pInfoParmW->pi_id = D_DATA_ID_INSTANCE;
		pInfoParmW->pi_pos = (long)leaf;
		pInfoParmW->pi_data = clmemdup(name,pInfoParm2->pi_dlen,D_OPT_ALC_TMP);
		pInfoParmW->pi_paux = (char *)leaf;
	}
	else return -1;
	return 0;
}

/****************************************/
/*										*/
/****************************************/
static int _count_parm(buf,buf_len)
char *buf;
int buf_len;
{
	SSPL_S ssp;
	char c;
	int nm_flg,n,k_level,len;

	if (!buf) return -1;
/*
printf("_count_parm: buf=[%s] buf_len=%d\n",buf,buf_len);
*/
	n = k_level = nm_flg = 0;
	memset(&ssp,0,sizeof(SSPL_S));
	while ((len=akxtgwnsl(buf,buf_len,&ssp,"(),",0x01)) > 0) {
		if (ssp.attr[0] < 10) {
			if (k_level > 0) nm_flg = 1;
		}
		else {
			c = *ssp.wd;
/*
printf("_count_parm: sp=%d c=%c\n",ssp.sp,c);
*/
			if (c == ',') {
				if (k_level == 1) {
					n++;
					nm_flg = 0;
				}
			}
			else if (c == '(') k_level++;
			else {
				if (k_level > 0) {
					k_level--;
					if (!k_level && nm_flg) n++;
				}
				else return -3;
			}
		}
	}
	if (n>=0 && k_level) return -2;
/*
printf("_count_parm: n=%d\n",n);
*/
	return n;
}

/****************************************/
/*										*/
/****************************************/
static Leaf *_find_method(topleaf,name,nparm)
Leaf *topleaf;
char *name;
int  nparm;
{
	int rc,cno,len1,len2,len,ix,opt;
	Leaf *wkleaf;
	cmdInfo *cmd;
	parmList **prmp;
/*
printf("_find_method: topleaf=%08x name=[%s] nparm=%d\n",topleaf,name,nparm);
*/
	opt = 0;
	if (pGlobTable->options[7] & 0x04) opt = AKX_ARGV_USE_ICMP;
	wkleaf = topleaf->leftleaf;
	while (wkleaf) {
		cmd = &wkleaf->cmd;
		cno = cmd->cid;
		prmp = cmd->prmp;
/*
printf("_find_method: prp=[%s] prmnum=%d\n",prmp[0]->prp,cmd->prmnum);
*/
		if ((cno==C_FUNCTION || cno==C_CLASS) && !akxs_opt_strcmp(prmp[0]->prp,name,opt)) {
			if (nparm < 0) break;
			else if (cmd->prmnum >= 2) {
				if (_count_parm(prmp[1]->prp,prmp[1]->prmlen)==nparm) break;
			}
			else if (!nparm) break;
		}
		wkleaf = wkleaf->rightleaf;
	}
	return wkleaf;
}

/****************************************/
/*										*/
/****************************************/
int cl_func_new(pInfoParmW,nparm,ppParm)
tdtInfoParm *pInfoParmW;
int  nparm;
tdtInfoParm **ppParm;
{
	int rc,cno,len1,len2,len,ix;
	Leaf *topleaf,*leaf,*wkleaf;
	char *name,*p,*p0,id,*pd;
	ScrPrCT *scrprct;
	ProcCT  *cur_procct,*procct;
	tdtInfoParm tInfoParmW,*pInfoParm;
	parmList **prmp;
	cmdInfo *cmd;

	if (rc=cl_gx_new(pInfoParmW,ppParm[0])) return rc;
	/* クラス変数の定義を実行する */
	topleaf = (Leaf *)pInfoParmW->pi_pos;
	name = pInfoParmW->pi_data;
/*
printf("cl_func_new: name=[%s]クラス変数の定義を実行する\n",name);
*/
	cur_procct = cl_search_proc_ct();
/*
printf("cl_func_new: cur_procct=%08x name=[%s] topleaf=%08x\n",cur_procct,name,topleaf);
*/
	memset(&tInfoParmW,0,sizeof(tdtInfoParm));
	if (rc=cl_exec_func_setup_proc(name,&tInfoParmW,0,NULL,topleaf,NULL,D_PFLAG_NO_FREE,NULL)) return rc;
	procct = cl_search_proc_ct();
	procct->pFlag |= D_PFLAG_DEF_CLASS;
/*
printf("cl_func_new: procct=%08x\n",procct);
printf("cl_func_new:1 procct->pha_vnam=%08x\n",procct->pha_vnam);
*/
	if (rc=cl_exec_func_execute(cur_procct)) return rc;
	pInfoParmW->pi_len = (long)procct;
#if 1
	/* 自分自身を"My"として登録する */
	if ((ix=cl_gx_chk_vnam('s',procct->pha_vnam,"My",2)) <= 0) {
		/* %s: %sのエントリ用の空きがありません。rc=%d */
		ERROROUT3(FORMAT(502),"cl_func_new","My",ix);
		return ECL_SCRIPT_ERROR;
	}
	pInfoParm = cl_get_var_ent(procct->pTBL_vnam,ix);
	if (cl_gx_rep_info_set(pInfoParm,pInfoParmW,1)) return -1;
	if (p=pInfoParm->pi_data) Free(p);
	pInfoParm->pi_data = Strdup("My");
	pInfoParm->pi_dlen = 2;
	pInfoParm->pi_scale |= D_DATA_MALLOC | D_DATA_COPIED_PROC;
#endif

	/* 引数の数が同じコンストラクタをサーチする */
	nparm--;
/*
printf("cl_func_new: name=[%s] npamr=%d 引数の数が同じコンストラクタをサーチする\n",name,nparm);
*/
	wkleaf = _find_method(topleaf,name,nparm);
	if (wkleaf) {
		/* クラス変数をサーチできるようにダミーのprocctを追加する */
		if (rc=cl_exec_func_setup_proc(name,NULL,0,NULL,NULL,NULL,0,procct)) return rc;
		procct = cl_search_proc_ct();
		len1 = pInfoParmW->pi_dlen;
		if (!(p0 = p = cl_tmp_const_malloc(len1*2+2))) return ECL_MALLOC_ERROR;
		memcpy(p,name,len1);
		p += len1;
		*p++ = '.';
		memzcpy(p,name,len1);
		/* コンストラクタを実行する */
/*
printf("cl_func_new: p0=[%s]コンストラクタを実行する\n",p0);
*/
		if (rc=cl_exec_func_setup_proc(p0,&tInfoParmW,nparm,&ppParm[1],wkleaf,NULL,0,NULL)) return rc;
		rc = cl_exec_func_execute(procct);
		if (!rc && ((id=tInfoParmW.pi_id)=='F' || id=='M') && tInfoParmW.pi_pos) {	/* コンストラクタのリターン値 */
			pInfoParmW->pi_id = 'M';
			pInfoParmW->pi_pos = tInfoParmW.pi_pos;
			len2 = tInfoParmW.pi_dlen;
			if (!strncmp(pd=tInfoParmW.pi_data,"My.",3)) {
				pd += 3;
				len2 -= 3;
			}
			len = len1 + len2 + 1;
			if (!(pInfoParmW->pi_data=p= cl_tmp_const_malloc(len+1))) return ECL_MALLOC_ERROR;
			memcpy(p,name,len1);
			p += len1;
			*p++ = '.';
			memzcpy(p,pd,len2);
			pInfoParmW->pi_dlen = len;
		}
		cl_er_lk_proc_ct();
		Free(procct->ProcNM);
		Free(procct);
	}
	return rc;
}

/****************************************/
/*										*/
/****************************************/
int cl_set_instance_method(pInfoParmW,pInfoParm1,pInfoParm2,optW,name,len2)
tdtInfoParm *pInfoParmW,*pInfoParm1,*pInfoParm2;
int optW;
char *name;
int len2;
{
	int rc,cno,len1,iParmNo,len,iFIND_METHOD;
	Leaf *topleaf,*leaf,*wkleaf;
	ScrPrCT *scrprct;
	ProcCT  *cur_procct,*procct,*nodeleaf;
	tdtInfoParm tInfoParmW,*pInfoParm;
	parmList **prmp;
	cmdInfo *cmd;
	char *p,*p1,buf[16],id;

DEBUGOUTL2(160,"cl_set_instance_method: Enter len2=%d name=[%s]",len2,name);

	if (!(procct=(ProcCT *)pInfoParm1->pi_len)) return -1;
	iFIND_METHOD = 0;
	wkleaf = NULL;
	if ((iParmNo=cl_gx_chk_vnam('r',procct->pha_vnam,name,len2)) > 0) {
		if (pInfoParm=cl_get_var_ent(procct->pTBL_vnam,iParmNo)) {

DEBUGOUT_InfoParm(160,"cl_set_instance_method: name=[%s] iParmNo=%d",pInfoParm,name,iParmNo);

			if (pInfoParm->pi_id == 'F') {
				name = pInfoParm->pi_data;
				len2 = pInfoParm->pi_dlen;
				if (len2>=2 && *name=='{') {
					scrprct = cl_search_src_ct();
					cur_procct = cl_search_proc_ct();
					wkleaf = cl_set_func_body(scrprct,cur_procct,name,&nodeleaf,procct->ProcPath);
					if (wkleaf) {
						cmd = &wkleaf->cmd;
						prmp = cmd->prmp;
						name = prmp[0]->prp;
						len2 = strlen(name);
						cno = C_FUNCTION;
					}
				}
			}
			else {
/*
printf("cl_set_instance_method: ,name=[%s] pha_vnam=%08x pTBL_vnam=%08x\n",name,procct->pha_vnam,procct->pTBL_vnam);
DEBUGOUT_InfoParm(0,"cl_set_instance_method: procct=%08x iParmNo=%d",pInfoParm,procct,iParmNo);
*/
				pInfoParm->pi_aux[1] |= D_AUX1_HASHED_NAME | D_AUX1_LOCAL_VAR;
				if (cl_is_undef_parm(pInfoParm) && (pGlobTable->options[0] & 0x01))
					cl_null_data(pInfoParm);
				cl_set_parm_long(pInfoParmW,(long)pInfoParm);
				pInfoParmW->pi_id = D_DATA_ID_STOREVAR;
				return 0;
			}
		}
		else return -1;
	}

DEBUGOUTL3(160,"cl_set_instance_method: wkleaf=%08x iParmNo=%d name=[%s]",wkleaf,iParmNo,name);

	if (!wkleaf) {
		topleaf = (Leaf *)pInfoParm1->pi_pos;
/*
printf("cl_set_instance_method: ,topleaf=%08x\n",topleaf);
*/
		if (wkleaf = _find_method(topleaf,name,-1)) {
			cno = wkleaf->cmd.cid;
			iFIND_METHOD = D_AULN_FIND_METHOD;
		}
	}
	if (wkleaf) {
		*pInfoParmW = *pInfoParm1;
		if (cno == C_FUNCTION) {
			id = 'M';
			pInfoParmW->pi_alen |= iFIND_METHOD;
		}
		else id = 'I';
		pInfoParmW->pi_id = id;
		pInfoParmW->pi_pos = (long)wkleaf;
		len1 = pInfoParm1->pi_dlen;
		len = len1 + len2 + 1;
		pInfoParmW->pi_data = p = cl_tmp_const_malloc(len+1);
		memcpy(p,pInfoParm1->pi_data,len1);
		p += len1;
		*p++ = '.';
		memzcpy(p,name,len2);
		pInfoParmW->pi_dlen = len;

DEBUGOUTL1(160,"cl_set_instance_method: pInfoParmW->pi_data=[%s]",pInfoParmW->pi_data);

		rc = 0;
	}
	else {
		/* %s: メ\x83\\ッド[%s]は未定義です。 */
		ERROROUT2(FORMAT(333),"cl_set_instance_method",name);
		rc = ECL_SCRIPT_ERROR;
	}
	return rc;
}

/****************************************/
/*										*/
/****************************************/
int cl_ex_class_method(pInfoParmW,pInfoParmM,nparm,ppParm,opt)
tdtInfoParm *pInfoParmW,*pInfoParmM;
tdtInfoParm *ppParm[];
int nparm,opt;
{
	int rc,i;
	Leaf *leaf,*wkleaf;
	char *p,*name,*method,*class_name;
	ProcCT *cur_procct,*procct,*proc;

	p = pInfoParmW->pi_paux;
	memset(pInfoParmW,0,sizeof(tdtInfoParm));
	pInfoParmW->pi_paux = p;

	name = pInfoParmM->pi_data;
	if (pInfoParmM->pi_alen & D_AULN_FIND_METHOD) {
		i = akxnrskipto(name,pInfoParmM->pi_dlen,".");
		if (i >= 0) method = name + i;
		else method = name;
		leaf = _find_method(pInfoParmM->pi_paux,method,nparm);
		if (!leaf) {
			/* %s: メ\x83\\ッド[%s]は未定義です。 */
			ERROROUT2(FORMAT(333),"cl_ex_class_method",method);
			return ECL_SCRIPT_ERROR;
		}
		pInfoParmM->pi_alen &= ~D_AULN_FIND_METHOD;
	}
	else leaf = (Leaf *)pInfoParmM->pi_pos;
	proc = (ProcCT *)pInfoParmM->pi_len;
/*
printf("cl_ex_class_method: name=[%s] proc=%08x\n",name,proc);
*/
	/* クラス変数をサーチできるようにダミーのprocctを追加する */
	wkleaf = (Leaf *)pInfoParmM->pi_paux;
	class_name = wkleaf->cmd.prmp[0]->prp;
	if (rc=cl_exec_func_setup_proc(class_name,NULL,0,NULL,NULL,NULL,0,proc)) return rc;
	proc = cl_search_proc_ct();
	/* メソッドを実行する */
	if (rc=cl_exec_func_setup_proc(name,pInfoParmW,nparm,ppParm,leaf,NULL,0,NULL)) return rc;
	rc = cl_exec_func_execute(proc);
	cl_er_lk_proc_ct();
	Free(proc->ProcNM);
	Free(proc);

	return rc;
}

/****************************************/
/*										*/
/****************************************/
int cl_set_class_method(pInfoParmW,pInfoParm1,pInfoParm2,optW,name,len2)
tdtInfoParm *pInfoParmW,*pInfoParm1,*pInfoParm2;
int optW;
char *name;
int len2;
{
	static char *_fn_="cl_set_class_method";
	int rc,len,varlen,iParmNo;
	tdtInfoParm tInfoParmW,*pInfoParm,*pParm[1];
	Leaf *leaf;
	char *class_name,varnam[Var_NM_MAX+5];

	/* STATICクラスのチェック */
	class_name = pInfoParm1->pi_data;
	if (!stricmp(class_name,D_SYS_CLASS_SYSTEM) ||
	    !stricmp(class_name,D_SYS_CLASS_FILE) ||
	    !stricmp(class_name,D_SYS_CLASS_MATH)) {
#if 1
		cl_gx_copy_info(pInfoParmW,pInfoParm2);
		return 0;
#else
		rc = cl_set_system_method(pInfoParmW,pInfoParm1,pInfoParm2,optW,name,len2);
		pInfoParmW->pi_hlen = 0;
		return rc;
#endif
	}
	if (leaf=(Leaf *)pInfoParm1->pi_pos) {
		if (leaf->cmd.sub_cid != CS_STATIC) {
			/* %s: [%s]は、STATICではありません。 */
			ERROROUT2(FORMAT(547),_fn_,pInfoParm1->pi_data);
			return ECL_SCRIPT_ERROR;
		}
	}
	else {
		/* %s: [%s]にleaf情報がありません。 */
		ERROROUT2(FORMAT(549),_fn_,class_name);
		return -1;
	}

	/* システムのインスタンスとして登録済みかのチェック */
	len = pInfoParm1->pi_dlen;
	strcpy(varnam,"<I>");
	varlen = len + 3;
	memnzcpy(varnam+3,class_name,len,sizeof(varnam)-4);
	if (pGlobTable->options[7] & 0x04) akxcuppern(varnam,NULL,varlen);
	if ((iParmNo=cl_gx_chk_vnam('r',pCLprocTable->pha_vnam,varnam,varlen)) > 0) {
/*
printf("cl_set_class_method:R: iParmNo=%d varlen=%d varnam=[%s]\n",iParmNo,varlen,varnam);
*/
		pInfoParm = cl_get_var_ent(pCLprocTable->pTBL_vnam,iParmNo);
#if 1
		if (rc=cl_set_instance_method(pInfoParmW,pInfoParm,NULL,optW,name,len2)) return rc;
#else
		cl_gx_rep_info_set(pInfoParmW,pInfoParm,1);
#endif
		return 0;
	}
	else if (iParmNo < 0) return iParmNo;

	/* インスタンスを生成する */
	pParm[0] = pInfoParm1;
	if (rc=cl_func_new(&tInfoParmW,1,pParm)) return rc;
	if (tInfoParmW.pi_id == 'M') {
		/* %s: コンストラクタがメ\x83\\ッド[%s]を返しました。 */
		ERROROUT2(FORMAT(550),_fn_,tInfoParmW.pi_data);
		return ECL_SCRIPT_ERROR;
	}

	/* メソッドを求める */
	if (rc=cl_set_instance_method(pInfoParmW,&tInfoParmW,NULL,optW,name,len2)) return rc;

	/* システムのインスタンスとして登録する */
	if ((iParmNo=cl_gx_chk_vnam('s',pCLprocTable->pha_vnam,varnam,varlen)) > 0) {
/*
printf("cl_set_class_method:S: iParmNo=%d varlen=%d varnam=[%s]\n",iParmNo,varlen,varnam);
*/
		pInfoParm = cl_get_var_ent(pCLprocTable->pTBL_vnam,iParmNo);
#if 1
		cl_gx_rep_info_set(pInfoParm,&tInfoParmW,1);
#else
		cl_gx_rep_info_set(pInfoParm,pInfoParmW,1);
#endif
	}
	else if (iParmNo < 0) return iParmNo;
	else {
		/* %s: %sの%sエントリ用の空きがありません。 */
		ERROROUT3(FORMAT(323),_fn_,class_name,"PUBLIC");
		return -1;
	}
	return 0;
}
