// 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); } }
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; }
// 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); } }
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; }
// 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, ""); } }
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; }
// 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; }
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; }
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; }
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; }
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; }