// 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); } }
// typeof void buildin_typeof(fake * fk, interpreter * inter) { bool err = false; variant * v = 0; PS_POP_AND_GET(fk->ps, v); const char * name = vartypetostring(v->type); fkpspush<const char *>(fk, name); }
FAKE_API uint64_t fkpspopuint64(fake * fk) { bool err = false; uint64_t ret; variant * v = 0; PS_POP_AND_GET(fk->ps, v); V_GET_UUID(v, ret); CHECK_ERR(err); return ret; }
FAKE_API bool fkpspopbool(fake * fk) { bool err = false; bool ret; variant * v = 0; PS_POP_AND_GET(fk->ps, v); V_GET_REAL(v, ret); CHECK_ERR(err); return ret; }
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; }
FAKE_API unsigned int fkpspopuint(fake * fk) { bool err = false; unsigned int ret; variant * v = 0; PS_POP_AND_GET(fk->ps, v); V_GET_REAL(v, ret); CHECK_ERR(err); return ret; }
void debuging::resume(bool & isend) { fake * fk = m_fk; fkpsclear(fk); fkresumeps(fk, isend); variant * ret = 0; bool err = false; PS_POP_AND_GET(fk->ps, ret); m_ret = *ret; CHECK_ERR(err); }
// 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); } }
FAKE_API void fkpspoppointer(fake * fk, void * & p, const char * type) { bool err = false; const char * t = 0; variant * v = 0; PS_POP_AND_GET(fk->ps, v); V_GET_POINTER(v, p, t); if (UNLIKE((p != 0 && !err && strcmp(t, type) != 0))) { err = true; seterror(fk, efk_run_data_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "variant get pointer %s fail, the variant type is %s", type, t); p = 0; } CHECK_ERR(err); }
// tostring void buildin_tostring(fake * fk, interpreter * inter) { // container bool err = false; variant * v = 0; PS_POP_AND_GET(fk->ps, v); if (v) { fkpspush<const char *>(fk, vartostring(v).c_str()); } else { fkpspush<const char *>(fk, ""); } }
// tonumber void buildin_tonumber(fake * fk, interpreter * inter) { bool err = false; variant * v = 0; PS_POP_AND_GET(fk->ps, v); double ret = 0; if (v->type == variant::STRING) { ret = atof(v->data.str->s); } else if (v->type == variant::REAL) { ret = v->data.real; } else if (v->type == variant::UUID) { ret = (double)v->data.uuid; } fkpspush<double>(fk, ret); }
// size void buildin_size(fake * fk, interpreter * inter) { bool err = false; variant * v = 0; PS_POP_AND_GET(fk->ps, v); int len = 0; if (v->type == variant::STRING) { len = v->data.str->sz; } else if (v->type == variant::ARRAY) { len = ARRAY_SIZE(v->data.va->va); } else if (v->type == variant::MAP) { len = v->data.vm->vm.size(); } fkpspush<int>(fk, len); }
// 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, ""); } }
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; }
// range void buildin_range(fake * fk, interpreter * inter) { BIF_CHECK_ARG_NUM(2); // pos int pos = fkpspop<int>(fk); // container bool err = false; variant * v = 0; PS_POP_AND_GET(fk->ps, v); if (v->type == variant::STRING) { if (pos >= 0 && pos < (int)v->data.str->sz) { char data[2]; data[0] = v->data.str->s[pos]; data[1] = 0; fkpspush<const char *>(fk, data); } else { fkpspush<const char *>(fk, ""); } } else if (v->type == variant::ARRAY) { if (pos >= 0 && pos < (int)ARRAY_SIZE(v->data.va->va) && ARRAY_GET(v->data.va->va, pos)) { variant * ret = 0; PS_PUSH_AND_GET(fk->ps, ret); if (ARRAY_GET(v->data.va->va, pos)) { *ret = *(ARRAY_GET(v->data.va->va, pos)); } else { *ret = NILV; } } else { fkpspush<bool>(fk, false); } } else if (v->type == variant::MAP) { if (pos >= 0 && pos < (int)v->data.vm->vm.size()) { variant * key = 0; PS_PUSH_AND_GET(fk->ps, key); variant * value = 0; PS_PUSH_AND_GET(fk->ps, value); const fkhashmap<variant, variant *>::ele * e = v->data.vm->vm.at(pos); *key = e->k; *value = *(*e->t); } else { fkpspush<bool>(fk, false); fkpspush<bool>(fk, false); } } else { fkpspush<bool>(fk, false); } }
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; }