예제 #1
0
// find
void buildin_string_find(fake * fk, interpreter * inter)
{
	BIF_CHECK_ARG_NUM(3);

	const char * findstr = fkpspopcstrptr(fk);
	int pos = fkpspop<int>(fk);
	const char * srcstr = 0;
	variant * v = 0;
	bool err = false;
	PS_POP_AND_GET(fk->ps, v);
	V_GET_STRING(v, srcstr);
	CHECK_ERR(err);
	
	int len = srcstr ? v->data.str->sz : 0;
	if (pos >= 0 && pos < len && srcstr && findstr)
	{
		const char * find = strstr(srcstr + pos, findstr);
		if (find)
		{
			fkpspush<bool>(fk, true);
			fkpspush<int>(fk, (int)(find - srcstr));
		}
		else
		{
			fkpspush<bool>(fk, false);
			fkpspush<int>(fk, -1);
		}
	}
	else
	{
		fkpspush<bool>(fk, false);
		fkpspush<int>(fk, -1);
	}
}
예제 #2
0
FAKE_API const char * fkpspopcstrptr(fake * fk)
{
	bool err = false;
	const char * ret = 0;
	variant * v = 0;
	PS_POP_AND_GET(fk->ps, v);
	V_GET_STRING(v, ret);
	CHECK_ERR(err);
	return ret;
}
예제 #3
0
// find not
void buildin_string_find_not(fake * fk, interpreter * inter)
{
	BIF_CHECK_ARG_NUM(3);

	const char * findstr = 0;
	variant * findv = 0;
	bool err = false;
	PS_POP_AND_GET(fk->ps, findv);
	V_GET_STRING(findv, findstr);
	CHECK_ERR(err);

	int pos = fkpspop<int>(fk);
	const char * srcstr = 0;
	variant * v = 0;
	PS_POP_AND_GET(fk->ps, v);
	V_GET_STRING(v, srcstr);

	int len = srcstr ? v->data.str->sz : 0;
	int findlen = findstr ? findv->data.str->sz : 0;
	if (pos >= 0 && pos < len && srcstr && findstr)
	{
		for (int i = pos; i < len; i++)
		{
			if (strncmp(srcstr + i, findstr, findlen))
			{
				fkpspush<bool>(fk, true);
				fkpspush<int>(fk, i);
				return;
			}
		}
		fkpspush<bool>(fk, false);
		fkpspush<int>(fk, -1);
	}
	else
	{
		fkpspush<bool>(fk, false);
		fkpspush<int>(fk, -1);
	}
}
예제 #4
0
variant * assembler_get_classmem_call(fake * fk, variant * classvar, variant * callpos)
{
	bool err = false;
	variant * n = fk->con.newvariant();
	
	void * classptr = 0;
	const char * classprefix = 0;
	
	// prefix
	V_GET_POINTER(classvar, classptr, classprefix);
	
	if (UNLIKE(err))
	{
		return 0;
	}
	
	const char * funcname = 0;
	V_GET_STRING(callpos, funcname);
	
	if (UNLIKE(err))
	{
		return 0;
	}
	
	if (UNLIKE(!classptr))
	{
		err = true;
		seterror(fk, efk_jit_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "jit class mem call error, the class ptr is null, type %s", classprefix);
		return 0;
	}
	
	// whole name
	char wholename[MAX_FAKE_REG_FUNC_NAME_LEN];
	if (UNLIKE(classvar->data.ponter->typesz + callpos->data.str->sz >= MAX_FAKE_REG_FUNC_NAME_LEN))
	{
		err = true;
		seterror(fk, efk_jit_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "jit class mem call error, the name is too long, func %s %s", classprefix, funcname);
		return 0;
	}
	memcpy(wholename, classprefix, classvar->data.ponter->typesz);
	memcpy(wholename + classvar->data.ponter->typesz, funcname, callpos->data.str->sz);
	wholename[classvar->data.ponter->typesz + callpos->data.str->sz] = 0;
	
	// call it
	V_SET_STRING(n, wholename);
	
	return n;
}
예제 #5
0
// substr
void buildin_string_substr(fake * fk, interpreter * inter)
{
	BIF_CHECK_ARG_NUM(3);

	int count = fkpspop<int>(fk);
	int pos = fkpspop<int>(fk);
	const char * srcstr = 0;
	variant * v = 0;
	bool err = false;
	PS_POP_AND_GET(fk->ps, v);
	V_GET_STRING(v, srcstr);
	CHECK_ERR(err);
	
	int len = srcstr ? v->data.str->sz : 0;
	if (count == -1)
	{
		count = 0x7FFFFFFF;
	}
	if (count < 0)
	{
		fkpspush<const char *>(fk, "");
		return;
	}
	if ((uint32_t)((uint32_t)pos + (uint32_t)count) > (uint32_t)len)
	{
		count = len - pos;
	}
	
	if (pos >= 0 && pos < len && srcstr && count > 0)
	{
		char * buf = (char *)safe_fkmalloc(fk, count + 1, emt_tmp);
		buf[count] = 0;
		memcpy(buf, srcstr + pos, count);
		fkpspush<const char *>(fk, buf);
		safe_fkfree(fk, buf);
	}
	else
	{
		fkpspush<const char *>(fk, "");
	}
}
예제 #6
0
파일: conf.c 프로젝트: shenzhe/bspd
static struct bspd_server_t * _parse_conf_server(BSP_OBJECT *desc)
{
    if (!desc || BSP_OBJECT_HASH != desc->type)
    {
        return NULL;
    }

    struct bspd_server_t *ret = bsp_calloc(1, sizeof(struct bspd_server_t));
    if (!ret)
    {
        return NULL;
    }

    ret->inet_type = BSP_INET_ANY;
    ret->sock_type = BSP_SOCK_ANY;
    ret->addr = NULL;
    ret->port = 0;
    ret->prop.type = BSPD_SERVER_NORMAL;
    ret->prop.data_type = BSPD_DATA_RAW;

    BSP_STRING *str = NULL;
    BSP_VALUE *node = NULL;

    node = bsp_object_value_hash_original(desc, "name");
    if (node)
    {
        str = V_GET_STRING(node);
        if (str)
        {
            ret->name = bsp_strndup(STR_STR(str), STR_LEN(str));
        }
    }

    // Inet
    node = bsp_object_value_hash_original(desc, "inet");
    if (node)
    {
        str = V_GET_STRING(node);
        if (str)
        {
            if (0 == strncasecmp(STR_STR(str), "ipv4", 4))
            {
                ret->inet_type = BSP_INET_IPV4;
            }
            else if (0 == strncasecmp(STR_STR(str), "ipv6", 4))
            {
                ret->inet_type = BSP_INET_IPV6;
            }
            else if (0 == strncasecmp(STR_STR(str), "local", 5))
            {
                ret->inet_type = BSP_INET_LOCAL;
            }
        }
    }

    // Sock
    node = bsp_object_value_hash_original(desc, "sock");
    if (node)
    {
        str = V_GET_STRING(node);
        if (str)
        {
            if (0 == strncasecmp(STR_STR(str), "tcp", 3))
            {
                ret->sock_type = BSP_SOCK_TCP;
            }
            else if (0 == strncasecmp(STR_STR(str), "udp", 3))
            {
                ret->sock_type = BSP_SOCK_UDP;
            }
            else if (0 == strncasecmp(STR_STR(str), "sctp", 4))
            {
                ret->sock_type = BSP_SOCK_SCTP;
            }
        }
    }

    // Addr
    node = bsp_object_value_hash_original(desc, "addr");
    if (node)
    {
        str = V_GET_STRING(node);
        if (str)
        {
            ret->addr = bsp_strndup(STR_STR(str), STR_LEN(str));
        }
    }

    // Port
    node = bsp_object_value_hash_original(desc, "port");
    if (node)
    {
        ret->port = (uint16_t) V_GET_INT(node);
    }

    // Type
    node = bsp_object_value_hash_original(desc, "type");
    if (node)
    {
        str = V_GET_STRING(node);
        if (str)
        {
            if (0 == strncasecmp(STR_STR(str), "internal", 8))
            {
                ret->prop.type = BSPD_SERVER_INTERNAL;
            }
            else if (0 == strncasecmp(STR_STR(str), "normal", 6))
            {
                ret->prop.type = BSPD_SERVER_NORMAL;
            }
            else if (0 == strncasecmp(STR_STR(str), "http", 0))
            {
                ret->prop.type = BSPD_SERVER_HTTP;
            }
            else if (0 == strncasecmp(STR_STR(str), "websocket", 9))
            {
                ret->prop.type = BSPD_SERVER_WEBSOCKET;
            }
            else
            {
                // Unsupported
            }
        }
    }

    // Data type
    node = bsp_object_value_hash_original(desc, "data_type");
    if (node)
    {
        str = V_GET_STRING(node);
        if (str)
        {
            if (0 == strncasecmp(STR_STR(str), "packet", 6))
            {
                ret->prop.data_type = BSPD_DATA_PACKET;
            }
        }
    }

    // LUA hooks
    node = bsp_object_value_hash_original(desc, "lua_hook_connect");
    if (node)
    {
        str = V_GET_STRING(node);
        if (str)
        {
            ret->prop.lua_hook_connect = bsp_strndup(STR_STR(str), STR_LEN(str));
        }
    }

    node = bsp_object_value_hash_original(desc, "lua_hook_disconnect");
    if (node)
    {
        str = V_GET_STRING(node);
        if (str)
        {
            ret->prop.lua_hook_connect = bsp_strndup(STR_STR(str), STR_LEN(str));
        }
    }

    node = bsp_object_value_hash_original(desc, "lua_hook_data");
    if (node)
    {
        str = V_GET_STRING(node);
        if (str)
        {
            ret->prop.lua_hook_data = bsp_strndup(STR_STR(str), STR_LEN(str));
        }
    }

    return ret;
}
예제 #7
0
파일: conf.c 프로젝트: shenzhe/bspd
// Parser
int parse_conf(BSP_OBJECT *conf)
{
    if (!conf)
    {
        return BSP_RTN_INVALID;
    }

    BSP_VALUE *node = NULL, *sub;
    BSP_STRING *str = NULL;
    BSPD_CONFIG *c = get_global_config();

    // Global
    node = bsp_object_value_hash_original(conf, "global");
    if (!node)
    {
        // No global segment?
        return BSP_RTN_ERR_GENERAL;
    }

    BSP_OBJECT *global = V_GET_OBJECT(node);
    if (global && BSP_OBJECT_HASH == global->type)
    {
        if (!c->verbose)
        {
            sub = bsp_object_value_hash_original(global, "trace_level");
            if (sub)
            {
                str = V_GET_STRING(sub);
                if (str)
                {
                    if (0 == strncasecmp(STR_STR(str), "none", 4))
                    {
                        c->opt.trace_level = I_NONE;
                    }
                    else if (0 == strncasecmp(STR_STR(str), "emerg", 5))
                    {
                        c->opt.trace_level = I_EMERG;
                    }
                    else if (0 == strncasecmp(STR_STR(str), "alert", 5))
                    {
                        c->opt.trace_level = I_EMERG | I_ALERT;
                    }
                    else if (0 == strncasecmp(STR_STR(str), "crit", 4))
                    {
                        c->opt.trace_level = I_EMERG | I_ALERT | I_CRIT;
                    }
                    else if (0 == strncasecmp(STR_STR(str), "err", 3))
                    {
                        c->opt.trace_level = I_EMERG | I_ALERT | I_CRIT | I_ERR;
                    }
                    else if (0 == strncasecmp(STR_STR(str), "warn", 4))
                    {
                        c->opt.trace_level = I_EMERG | I_ALERT | I_CRIT | I_ERR | I_WARN;
                    }
                    else if (0 == strncasecmp(STR_STR(str), "notice", 6))
                    {
                        c->opt.trace_level = I_EMERG | I_ALERT | I_CRIT | I_ERR | I_WARN | I_NOTICE;
                    }
                    else if (0 == strncasecmp(STR_STR(str), "info", 4))
                    {
                        c->opt.trace_level = I_EMERG | I_ALERT | I_CRIT | I_ERR | I_WARN | I_NOTICE | I_INFO;
                    }
                    else if (0 == strncasecmp(STR_STR(str), "debug", 5))
                    {
                        c->opt.trace_level = I_EMERG | I_ALERT | I_CRIT | I_ERR | I_WARN | I_NOTICE | I_INFO | I_DEBUG;
                    }
                    else if (0 == strncasecmp(STR_STR(str), "all", 3))
                    {
                        c->opt.trace_level = I_ALL;
                    }
                }
            }
        }
        else
        {
            c->opt.trace_level = I_ALL;
        }

        sub = bsp_object_value_hash_original(global, "daemonize");
        if (sub)
        {
            c->opt.daemonize = V_GET_BOOLEAN(sub);
        }

        sub = bsp_object_value_hash_original(global, "boss_threads");
        if (sub)
        {
            c->opt.boss_threads = (int) V_GET_INT(sub);
        }

        sub = bsp_object_value_hash_original(global, "acceptor_threads");
        if (sub)
        {
            c->opt.acceptor_threads = (int) V_GET_INT(sub);
        }

        sub = bsp_object_value_hash_original(global, "io_threads");
        if (sub)
        {
            c->opt.io_threads = (int) V_GET_INT(sub);
        }

        sub = bsp_object_value_hash_original(global, "worker_threads");
        if (sub)
        {
            c->opt.worker_threads = (int) V_GET_INT(sub);
        }

        sub = bsp_object_value_hash_original(global, "script");
        if (sub)
        {
            str = V_GET_STRING(sub);
            if (str)
            {
                c->script = bsp_strndup(STR_STR(str), STR_LEN(str));
            }
        }

        sub = bsp_object_value_hash_original(global, "lua_hook_load");
        if (sub)
        {
            str = V_GET_STRING(sub);
            if (str)
            {
                c->lua_hook_load = bsp_strndup(STR_STR(str), STR_LEN(str));
            }
        }
    }
    else
    {
        // Type error
        return BSP_RTN_ERR_GENERAL;
    }

    // Servers
    node = bsp_object_value_hash_original(conf, "servers");
    if (!node)
    {
        // No server
    }
    else
    {
        BSP_OBJECT *servers = V_GET_OBJECT(node);
        BSP_OBJECT *server_obj = NULL;
        BSP_VALUE *server_val = NULL;
        struct bspd_server_t *server = NULL;
        if (servers && BSP_OBJECT_ARRAY == servers->type)
        {
            bsp_object_reset(servers);
            server_val = bsp_object_curr(servers, NULL);
            while (server_val)
            {
                server_obj = V_GET_OBJECT(server_val);
                if (server_obj && BSP_OBJECT_HASH == server_obj->type)
                {
                    server = _parse_conf_server(server_obj);
                    if (server)
                    {
                        server->next = c->servers;
                        c->servers = server;
                    }
                }

                bsp_object_next(servers);
                server_val = bsp_object_curr(servers, NULL);
            }
        }
    }

    return BSP_RTN_SUCCESS;
}
예제 #8
0
void interpreter::call(const variant & func, int retnum, int * retpos)
{
	fake * fk = m_fk;
	paramstack * ps = getps(m_fk);
	const funcunion * f = m_fk->fm.get_func(func);
	bool & err = m_isend;
	USE(err);
	if (UNLIKE(!f))
	{
		FKERR("fkrun no func %s fail", vartostring(&func).c_str());
		m_isend = true;
		seterror(m_fk, efk_run_no_func_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "fkrun no func %s fail", vartostring(&func).c_str());
		return;
	}

	// 常规函数
	if (LIKE(f->havefb))
	{
		const func_binary * fb = &f->fb;
		variant * v = 0;

		// 准备栈大小
		int needsize = m_sp + BP_SIZE + retnum + FUNC_BINARY_MAX_STACK(*fb);
		if (UNLIKE(needsize > (int)ARRAY_MAX_SIZE(m_stack)))
		{
			int newsize = needsize + needsize * m_fk->cfg.array_grow_speed / 100;
			ARRAY_GROW(m_stack, newsize, variant);
		}

		// 老的bp
		int oldbp = m_bp;
		m_bp = m_sp;

		// 记录返回位置
		for (int i = 0; i < retnum; i++)
		{
			v = &ARRAY_GET(m_stack, m_bp);
			v->type = variant::NIL;
			v->data.buf = retpos[i];
			m_bp++;
		}

		// 记录返回值数目
		v = &ARRAY_GET(m_stack, m_bp);
		v->type = variant::NIL;
		v->data.buf = retnum;
		m_bp++;

		// 记录老的ip
		v = &ARRAY_GET(m_stack, m_bp);
		v->type = variant::NIL;
		v->data.buf = m_ip;
		m_bp++;

		// 记录profile
		if (UNLIKE(m_fk->pf.isopen()))
		{
			v = &ARRAY_GET(m_stack, m_bp);
			v->data.buf = fkgetmstick();
		}
		v->type = variant::NIL;
		m_bp++;

		// 记录老的fb
		v = &ARRAY_GET(m_stack, m_bp);
		v->type = variant::NIL;
		v->data.buf = (uint64_t)m_fb;
		m_bp++;

		// 记录老的bp
		v = &ARRAY_GET(m_stack, m_bp);
		v->type = variant::NIL;
		v->data.buf = oldbp;
		m_bp++;

		// 设置sp
		m_sp = m_bp + FUNC_BINARY_MAX_STACK(*fb);
		
		if (UNLIKE((int)ps->m_variant_list_num != FUNC_BINARY_PARAMNUM(*fb)))
		{
			FKERR("call func %s param not match", vartostring(&func).c_str());
			m_isend = true;
			seterror(m_fk, efk_run_param_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "call func %s param not match", vartostring(&func).c_str());
			return;
		}

		assert(FUNC_BINARY_PARAMNUM(*fb) <= REAL_MAX_FAKE_PARAM_NUM);
		assert(m_bp + FUNC_BINARY_PARAMNUM(*fb) <= (int)ARRAY_MAX_SIZE(m_stack));

		// 分配入参
		memcpy(&ARRAY_GET(m_stack, m_bp), ps->m_variant_list, FUNC_BINARY_PARAMNUM(*fb) * sizeof(variant));
		PS_CLEAR(*ps);

		// 重置ret
		V_SET_NIL(&m_ret[0]);

		// 标记
		FUNC_BINARY_USE(*fb)++;

		// 新函数
		m_fb = fb;
		m_ip = 0;

		return;
	}

	// 记录profile
	uint32_t s = 0;
	if (UNLIKE(m_fk->pf.isopen()))
	{
		s = fkgetmstick();
	}

	// 绑定函数
	if (f->haveff)
	{
		BIND_FUNC_CALL(f, this);
		FKLOG("call C func %s", vartostring(&func).c_str());
	}
	// 内置函数
	else if (f->havebif)
	{
		BUILDIN_FUNC_CALL(f, this);
		FKLOG("call buildin func %s", vartostring(&func).c_str());
	}
	else
	{
		assert(0);
		FKERR("fkrun no inter func %s fail", vartostring(&func).c_str());
		m_isend = true;
		seterror(m_fk, efk_run_no_func_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "fkrun no inter func %s fail", vartostring(&func).c_str());
		return;
	}

	// 返回值
	// 这种情况是直接跳过脚本调用了C函数
	if (UNLIKE(BP_END(m_bp)))
	{
		variant * cret;
		PS_POP_AND_GET(*ps, cret);
		m_isend = true;
		// 直接塞返回值
		m_ret[0] = *cret;
	}
	// 否则塞到当前堆栈上
	else
	{
		// 检查返回值数目对不对
		if (UNLIKE((int)ps->m_variant_list_num != retnum))
		{
			FKERR("native func %s param not match, give %d need %d", vartostring(&func).c_str(), (int)ps->m_variant_list_num, retnum);
			m_isend = true;
			seterror(m_fk, efk_run_param_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "native func %s param not match, give %d need %d", vartostring(&func).c_str(), (int)ps->m_variant_list_num, retnum);
			return;
		}
		
		// 塞返回值
		for (int i = 0; i < retnum; i++)
		{
			variant * ret;
			GET_VARIANT(*m_fb, m_bp, ret, retpos[i]);
			
			variant * cret;
			PS_GET(*ps, cret, i);
			
			*ret = *cret;
		}
	}
	
	if (UNLIKE(m_fk->pf.isopen()))
	{
		const char * name = 0;
		V_GET_STRING(&func, name);
		m_fk->pf.add_func_sample(name, fkgetmstick() - s);
	}

	return;
}
예제 #9
0
int interpreter::run(int cmdnum)
{
	fake * fk = m_fk;
	bool & err = m_isend;
	int i = 0;
	
	// 栈溢出检查
	if (UNLIKE((int)ARRAY_MAX_SIZE(m_stack) > m_fk->cfg.stack_max))
	{	
		m_isend = true;
		seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "stack too big %d", ARRAY_MAX_SIZE(m_stack));
		return 0;
	}

	// 切换检查
	if (UNLIKE(m_sleeping))
	{
		if (LIKE(m_yieldtime))
		{
			m_yieldtime--;
			return 0;
		}
		else if (LIKE(fkgetmstick() < m_wakeuptime))
		{
			return 0;
		}
		else
		{
			m_wakeuptime = 0;
		}
	}
	
	if (UNLIKE(m_isend))
	{
		return 0;
	}
	
	while (1)
	{
		// 当前函数走完
		if (UNLIKE(m_ip >= (int)FUNC_BINARY_CMDSIZE(*m_fb)))
		{
			FKLOG("pop stack %s", FUNC_BINARY_NAME(*m_fb));
			
			// 记录profile
			if (UNLIKE(m_fk->pf.isopen()))
			{
				uint32_t calltime = 0;
				BP_GET_CALLTIME(m_bp, calltime);
				m_fk->pf.add_func_sample(FUNC_BINARY_NAME(*m_fb), fkgetmstick() - calltime);
			}
			
			// 标记
			FUNC_BINARY_USE(*m_fb)--;
			
			// 更新
			if (UNLIKE(!FUNC_BINARY_USE(*m_fb) && FUNC_BINARY_BACKUP(*m_fb)))
			{
				FUNC_BINARY_BACKUP_MOVE(*m_fb);
			}
			
			// 出栈
			int oldretnum = 0;
			BP_GET_RETNUM(m_bp, oldretnum);
			int callbp = 0;
			BP_GET_BP(m_bp, callbp);
			BP_GET_FB(m_bp, m_fb);
			BP_GET_IP(m_bp, m_ip);
			int oldbp = m_bp;
			m_sp = m_bp - BP_SIZE - oldretnum;
			m_bp = callbp;
			
			// 所有都完
			if (UNLIKE(BP_END(m_bp)))
			{
				FKLOG("stack empty end");
				m_isend = true;
				break;
			}
			// 塞返回值
			else
			{
				for (int i = 0; i < oldretnum; i++)
				{
					int oldretpos = 0;
					BP_GET_RETPOS(oldbp, oldretnum, oldretpos, i);
					
					variant * ret;
					GET_VARIANT(*m_fb, m_bp, ret, oldretpos);
					*ret = m_ret[i];
				}
			}
			continue;
		}

		int code = COMMAND_CODE(GET_CMD(*m_fb, m_ip));

		FKLOG("next %d %d %s", COMMAND_TYPE(GET_CMD(*m_fb, m_ip)), code, OpCodeStr(code));
			
		assert (COMMAND_TYPE(GET_CMD(*m_fb, m_ip)) == COMMAND_OPCODE);

		m_ip++;

		if (UNLIKE(m_fk->pf.isopen()))
		{
			m_fk->pf.add_code_sample(code);
		}

		// 执行对应命令,放一起switch效率更高,cpu有缓存
		switch (code)
		{
		case OPCODE_ASSIGN:
			{
				// 赋值dest,必须为栈上或容器内
				if (UNLIKE(!(CHECK_STACK_POS(*m_fb, m_ip) || CHECK_CONTAINER_POS(*m_fb, m_ip))))
				{	
					err = true;
					seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "interpreter assign error, dest is not stack or container, type %s", POS_TYPE_NAME(*m_fb, m_ip));
					break;
				}

				variant * varv = 0;
				LOG_VARIANT(*m_fb, m_ip, "var");
				GET_VARIANT(*m_fb, m_bp, varv, m_ip);
				if (UNLIKE(CHECK_CONST_MAP_POS(varv) || CHECK_CONST_ARRAY_POS(varv)))
				{
					err = true;
					seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "interpreter assign error, dest is const container");
					break;
				}
				m_ip++;
				
				// 赋值来源
				const variant * valuev = 0;
				LOG_VARIANT(*m_fb, m_ip, "value");
				GET_VARIANT(*m_fb, m_bp, valuev, m_ip);
				m_ip++;

				// 赋值
				*varv = *valuev;

				FKLOG("assign %s to %s", (vartostring(valuev)).c_str(), (vartostring(varv)).c_str());
			}
			break;
		case OPCODE_PLUS:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, PLUS);
			}
			break;
		case OPCODE_MINUS:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, MINUS);
			}
			break;
		case OPCODE_MULTIPLY:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, MULTIPLY);
			}
			break;
		case OPCODE_DIVIDE:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, DIVIDE);
			}
			break;
		case OPCODE_DIVIDE_MOD:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, DIVIDE_MOD);
			}
			break;
		case OPCODE_STRING_CAT:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, STRING_CAT);
			}
			break;
		case OPCODE_AND:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, AND);
			}
			break;
		case OPCODE_OR:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, OR);
			}
			break;
		case OPCODE_LESS:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, LESS);
			}
			break;
		case OPCODE_MORE:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, MORE);
			}
			break;
		case OPCODE_EQUAL:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, EQUAL);
			}
			break;
		case OPCODE_MOREEQUAL:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, MOREEQUAL);
			}
			break;
		case OPCODE_LESSEQUAL:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, LESSEQUAL);
			}
			break;
		case OPCODE_NOTEQUAL:
			{
				MATH_OPER(*m_fb, m_bp, m_ip, NOTEQUAL);
			}
			break;
		case OPCODE_NOT:
			{
				MATH_SINGLE_OPER(*m_fb, m_bp, m_ip, NOT);
			}
			break;
		case OPCODE_AND_JNE:
			{
				MATH_OPER_JNE(*m_fb, m_bp, m_ip, AND_JNE);
			}
			break;
		case OPCODE_OR_JNE:
			{
				MATH_OPER_JNE(*m_fb, m_bp, m_ip, OR_JNE);
			}
			break;
		case OPCODE_LESS_JNE:
			{
				MATH_OPER_JNE(*m_fb, m_bp, m_ip, LESS_JNE);
			}
			break;
		case OPCODE_MORE_JNE:
			{
				MATH_OPER_JNE(*m_fb, m_bp, m_ip, MORE_JNE);
			}
			break;
		case OPCODE_EQUAL_JNE:
			{
				MATH_OPER_JNE(*m_fb, m_bp, m_ip, EQUAL_JNE);
			}
			break;
		case OPCODE_MOREEQUAL_JNE:
			{
				MATH_OPER_JNE(*m_fb, m_bp, m_ip, MOREEQUAL_JNE);
			}
			break;
		case OPCODE_LESSEQUAL_JNE:
			{
				MATH_OPER_JNE(*m_fb, m_bp, m_ip, LESSEQUAL_JNE);
			}
			break;
		case OPCODE_NOTEQUAL_JNE:
			{
				MATH_OPER_JNE(*m_fb, m_bp, m_ip, NOTEQUAL_JNE);
			}
			break;
		case OPCODE_NOT_JNE:
			{
				MATH_SINGLE_OPER_JNE(*m_fb, m_bp, m_ip, NOT_JNE);
			}
			break;
		case OPCODE_JNE:
			{
				const variant * cmp = 0;
				LOG_VARIANT(*m_fb, m_ip, "cmp");
				GET_VARIANT(*m_fb, m_bp, cmp, m_ip);
				m_ip++;

				int ip = COMMAND_CODE(GET_CMD(*m_fb, m_ip));
				m_ip++;
				
				if (!(V_ISBOOL(cmp)))
				{
					FKLOG("jne %d", ip);
					m_ip = ip;
				}
				else
				{
					FKLOG("not jne %d", ip);
				}
			}
			break;
		case OPCODE_JMP:
			{
				int ip = COMMAND_CODE(GET_CMD(*m_fb, m_ip));
				m_ip++;
				
				FKLOG("jmp %d", ip);

				m_ip = ip;
			}
			break;
		case OPCODE_PLUS_ASSIGN:
			{
				MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, PLUS);
			}
			break;
		case OPCODE_MINUS_ASSIGN:
			{
				MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, MINUS);
			}
			break;
		case OPCODE_MULTIPLY_ASSIGN:
			{
				MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, MULTIPLY);
			}
			break;
		case OPCODE_DIVIDE_ASSIGN:
			{
				MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, DIVIDE);
			}
			break;
		case OPCODE_DIVIDE_MOD_ASSIGN:
			{
				MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, DIVIDE_MOD);
			}
			break;
		case OPCODE_CALL:
			{
				int calltype = COMMAND_CODE(GET_CMD(*m_fb, m_ip));
				m_ip++;

				const variant * callpos = 0;
				LOG_VARIANT(*m_fb, m_ip, "callpos");
				GET_VARIANT(*m_fb, m_bp, callpos, m_ip);
				m_ip++;

				int retnum = COMMAND_CODE(GET_CMD(*m_fb, m_ip));
				m_ip++;
				
				int retpos[MAX_FAKE_RETURN_NUM];

				for (int i = 0; i < retnum; i++)
				{
					assert(CHECK_STACK_POS(*m_fb, m_ip) || CHECK_CONTAINER_POS(*m_fb, m_ip));
					retpos[i] = m_ip;
					m_ip++;
				}
				
				int argnum = COMMAND_CODE(GET_CMD(*m_fb, m_ip));
				m_ip++;

				paramstack & ps = *getps(m_fk);
				PS_CLEAR(ps);
				for (int i = 0; i < argnum; i++)
				{
					variant * arg = 0;
					LOG_VARIANT(*m_fb, m_ip, "arg");
					GET_VARIANT(*m_fb, m_bp, arg, m_ip);
					m_ip++;

					variant * argdest = 0;
					PS_PUSH_AND_GET(ps, argdest);
					*argdest = *arg;
				}
				
				if (LIKE(calltype == CALL_NORMAL))
				{
					call(*callpos, retnum, retpos);
				}
				else if (LIKE(calltype == CALL_CLASSMEM))
				{
					void * classptr = 0;
					const char * classprefix = 0;

					// prefix
					variant * classvar;
					PS_GET(ps, classvar, PS_SIZE(ps) - 1);
					V_GET_POINTER(classvar, classptr, classprefix);

					if (UNLIKE(err))
					{
						break;
					}

					// mem func name
					const char * funcname = 0;
					V_GET_STRING(callpos, funcname);
					
					if (UNLIKE(err))
					{
						break;
					}

					if (UNLIKE(!classptr))
					{
						err = true;
						seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "interpreter class mem call error, the class ptr is null, type %s", classprefix);
						break;
					}

					// whole name
					char wholename[MAX_FAKE_REG_FUNC_NAME_LEN];
					if (UNLIKE(classvar->data.ponter->typesz + callpos->data.str->sz >= MAX_FAKE_REG_FUNC_NAME_LEN))
					{
						err = true;
						seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "interpreter class mem call error, the name is too long, func %s %s", classprefix, funcname);
						break;
					}
					memcpy(wholename, classprefix, classvar->data.ponter->typesz);
					memcpy(wholename + classvar->data.ponter->typesz, funcname, callpos->data.str->sz);
					wholename[classvar->data.ponter->typesz + callpos->data.str->sz] = 0;

					// call it
					variant tmp;
					V_SET_STRING(&tmp, wholename);

					call(tmp, retnum, retpos);
				}
				else
				{
					m_processor->start_routine(*callpos, retnum, retpos);
				}
			}
			break;
		case OPCODE_RETURN:
			{
				int returnnum = COMMAND_CODE(GET_CMD(*m_fb, m_ip));
				if (UNLIKE(!returnnum))
				{
					FKLOG("return empty");
					m_ip = (*m_fb).m_size;
					break;
				}
				m_ip++;

				// 塞给ret
				for (int i = 0; i < returnnum; i++)
				{
					const variant * ret = 0;
					LOG_VARIANT(*m_fb, m_ip, "ret");
					GET_VARIANT(*m_fb, m_bp, ret, m_ip);
					m_ip++;

					m_ret[i] = *ret;

					FKLOG("return %s", (vartostring(&m_ret[i])).c_str());
				}
				
				m_ip = (*m_fb).m_size;
			}
			break;
		case OPCODE_SLEEP:
			{
				const variant * time = 0;
				LOG_VARIANT(*m_fb, m_ip, "time");
				GET_VARIANT(*m_fb, m_bp, time, m_ip);
				m_ip++;

				uint32_t sleeptime = 0;
				V_GET_REAL(time, sleeptime);

				m_wakeuptime = fkgetmstick() + sleeptime;
				m_sleeping = true;
				return i + 1;
			}
			break;
		case OPCODE_YIELD:
			{
				const variant * time = 0;
				LOG_VARIANT(*m_fb, m_ip, "time");
				GET_VARIANT(*m_fb, m_bp, time, m_ip);
				m_ip++;

				V_GET_REAL(time, m_yieldtime);
				m_sleeping = true;
				return i + 1;
			}
			break;
		default:
			assert(0);
			FKERR("next err code %d %s", code, OpCodeStr(code));
			break;
		}
		
		if (UNLIKE(err))
		{
			// 发生错误
			m_isend = true;

			// 清除当前栈上函数的使用标记
			{
				int ip = m_ip;
				int bp = m_bp;
				const func_binary * fb = m_fb;

				while (!BP_END(bp))
				{
					// 标记
					FUNC_BINARY_USE(*fb)--;
					
					// 更新
					if (UNLIKE(!FUNC_BINARY_USE(*fb) && FUNC_BINARY_BACKUP(*fb)))
					{
						FUNC_BINARY_BACKUP_MOVE(*fb);
					}
					
					BP_GET_FB(bp, fb);
					BP_GET_IP(bp, ip);
					int callbp = 0;
					BP_GET_BP(bp, callbp);
					bp = callbp;
					if (BP_END(bp))
					{
						break;
					}
				}
			}
		}

		if (UNLIKE(m_isend))
		{
			break;
		}
		
		i++;
		
		if (UNLIKE(i >= cmdnum))
		{
			break;
		}
	}
	
	return i;
}
예제 #10
0
void interpreter::call(const variant & func)
{
    fake * fk = m_fk;
	const funcunion * f = m_fk->fm.get_func(func);
	if (UNLIKE(!f))
	{
		FKERR("fkrun no func %s fail", vartostring(&func).c_str());
		seterror(m_fk, efk_run_no_func_error, "fkrun no func %s fail", vartostring(&func).c_str());
		m_isend = true;
		return;
	}

	// 常规函数
	if (f->havefb)
	{
		const func_binary * fb = &f->fb;

		// 空函数处理
		if (UNLIKE(!FUNC_BINARY_CMDSIZE(*fb)))
		{
			// 所有都完
			if (ARRAY_EMPTY(m_stack_list))
			{
				FKLOG("call stack empty end");
				m_isend = true;
			}
			return;
		}

		// 压栈
		if (UNLIKE(ARRAY_SIZE(m_stack_list) >= ARRAY_MAX_SIZE(m_stack_list)))
		{
			int newsize = ARRAY_MAX_SIZE(m_stack_list) + 1 + ARRAY_MAX_SIZE(m_stack_list) * m_fk->cfg.array_grow_speed / 100;
			ARRAY_GROW(m_stack_list, newsize, stack);
		}
		ARRAY_PUSH_BACK(m_stack_list);
		stack & s = ARRAY_BACK(m_stack_list);
		m_cur_stack = &s;
		STACK_INI(s, m_fk, fb);
		if (UNLIKE(FUNC_BINARY_MAX_STACK(*fb) > (int)ARRAY_MAX_SIZE(s.m_stack_variant_list)))
		{
			ARRAY_GROW(s.m_stack_variant_list, FUNC_BINARY_MAX_STACK(*fb), variant);
		}

		// 记录profile
		beginfuncprofile();
		
		paramstack * ps = getps(m_fk);

		if (UNLIKE((int)ps->m_variant_list_num != FUNC_BINARY_PARAMNUM(*fb)))
		{
			FKERR("call func %s param not match", vartostring(&func).c_str());
			seterror(m_fk, efk_run_param_error, "call func %s param not match", vartostring(&func).c_str());
			m_isend = true;
			return;
		}

		assert(FUNC_BINARY_PARAMNUM(*fb) <= (int)ARRAY_MAX_SIZE(s.m_stack_variant_list));

		// 分配栈空间
		for (int i = 0; i < (int)FUNC_BINARY_PARAMNUM(*fb); i++)
		{
			SET_STACK(&(ps->m_variant_list[i]), s, i);
			FKLOG("call set %s to pos %d", (vartostring(&(ps->m_variant_list[i]))).c_str(), i);
		}
		
		ps->clear();

		// 重置ret
		V_SET_NIL(&m_ret[0]);

		// 标记
		FUNC_BINARY_USE(*fb)++;

		return;
	}

	// 记录profile
	uint32_t s = 0;
	if (m_fk->pf.isopen())
	{
		s = fkgetmstick();
	}

	// 绑定函数
	if (f->haveff)
	{
		BIND_FUNC_CALL(f, this);
		FKLOG("call C func %s", vartostring(&func).c_str());
	}
	// 内置函数
	else if (f->havebif)
	{
		BUILDIN_FUNC_CALL(f, this);
		FKLOG("call buildin func %s", vartostring(&func).c_str());
	}
	else
	{
		assert(0);
		FKERR("fkrun no inter func %s fail", vartostring(&func).c_str());
		seterror(m_fk, efk_run_no_func_error, "fkrun no inter func %s fail", vartostring(&func).c_str());
		m_isend = true;
		return;
	}

	// 返回值
	paramstack * theps = getps(m_fk);
    bool err = false;
	USE(err);

	// 这种情况是直接跳过脚本调用了C函数
	if (UNLIKE(ARRAY_EMPTY(m_stack_list)))
	{
    	variant * cret;
    	PS_POP_AND_GET(*theps, cret);
		m_isend = true;
		// 直接塞返回值
		m_ret[0] = *cret;
	}
	// 否则塞到当前堆栈上
	else
	{
		// 塞返回值
		m_cur_stack = &ARRAY_BACK(m_stack_list);
		const func_binary & fb = *m_cur_stack->m_fb;
		for (int i = 0; i < m_cur_stack->m_retnum; i++)
		{
			variant * ret;
			GET_VARIANT(*m_cur_stack, fb, ret, m_cur_stack->m_retvpos[i]);
			
        	variant * cret;
        	PS_GET(*theps, cret, i);
        	
			*ret = *cret;
		}
	}
    if (UNLIKE(err))
    {
        m_isend = true;
    }
    
	if (m_fk->pf.isopen())
	{
	    bool err = false;
		const char * name = 0;
		V_GET_STRING(&func, name);
		m_fk->pf.add_func_sample(name, fkgetmstick() - s);
	}

	return;
}
예제 #11
0
파일: debug.c 프로젝트: shenzhe/bspd
static void _dump_value(BSP_VALUE *val, int layer)
{
    if (!val)
    {
        fprintf(stderr, "\033[1;35m### NO VALUE ###\033[0m\n");

        return;
    }

    BSP_STRING *str = NULL;
    BSP_OBJECT *sub_obj = NULL;
    switch (val->type)
    {
        case BSP_VALUE_NULL : 
            fprintf(stderr, "\033[1;31m(NULL)\033[0m\n");
            break;
        case BSP_VALUE_INT8 : 
        case BSP_VALUE_INT16 : 
        case BSP_VALUE_INT32 : 
        case BSP_VALUE_INT64 : 
        case BSP_VALUE_INT29 : 
        case BSP_VALUE_INT : 
            fprintf(stderr, "\033[1;33m(INTEGER)\033[0m : %lld\n", (long long int) (V_GET_INT(val)));
            break;
        case BSP_VALUE_UINT8 : 
        case BSP_VALUE_UINT16 : 
        case BSP_VALUE_UINT32 : 
        case BSP_VALUE_UINT64 : 
            fprintf(stderr, "\033[1;33m(UNSIGNED INTEGER)\033[0m : %llu\n", (unsigned long long int) (V_GET_INT(val)));
            break;
        case BSP_VALUE_FLOAT : 
        case BSP_VALUE_DOUBLE : 
            fprintf(stderr, "\033[1;33m(FLOAT)\033[0m : %g\n", (double) V_GET_FLOAT(val));
            break;
        case BSP_VALUE_BOOLEAN : 
            fprintf(stderr, "\033[1;33m(BOOLEAN)\033[0m : %s\n", (BSP_TRUE == V_GET_BOOLEAN(val)) ? "true" : "false");
            break;
        case BSP_VALUE_STRING : 
            fprintf(stderr, "\033[1;32m(STRING)\033[0m : ");
            str = V_GET_STRING(val);
            if (str && STR_STR(str))
            {
                write(STDERR_FILENO, STR_STR(str), STR_LEN(str));
            }
            else
            {
                fprintf(stderr, "\033[1;31m### NULL_STRING ###\033[0m");
            }

            fprintf(stderr, "\n");
            break;
        case BSP_VALUE_OBJECT : 
            fprintf(stderr, "\033[1;36m(OBJECT)\033[0m : ");
            sub_obj = V_GET_OBJECT(val);
            _dump_object(sub_obj, layer + 1);
            break;
        case BSP_VALUE_POINTER : 
            fprintf(stderr, "\033[1;36m(POINTER)\033[0m : %p\n", V_GET_POINTER(val));
            break;
        case BSP_VALUE_UNKNOWN : 
        default : 
            fprintf(stderr, "\033[1;31m(NOTHING)\033[0m\n");
            break;
    }

    return;
}