📄 eval.cc
字号:
} else { switch (*q) { case '+': case '-': case '#': case ' ': break; default: /* FIXME: invalid format */ break; } } q++; } if ((unsigned int)t.len>sizeof buf-1) t.len=sizeof buf-1; t.value[t.len]=0; ht_snprintf(buf, sizeof buf, cfmt, t.value); sprintf_puts(b, blimit, buf); string_destroy(&t); return 1; } case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': { eval_float f; scalar_context_float(s, &f); ht_snprintf(buf, sizeof buf, cfmt, f.value); sprintf_puts(b, blimit, buf); return 1; } case '%': sprintf_puts(b, blimit, "%"); return 1; } (*fmt)++; (*fmtl)--; ci++; } return 0;}int func_sprintf(eval_scalar *r, const eval_str *format, const eval_scalarlist *scalars){ char buf[512]; /* FIXME: possible buffer overflow */ char *b=buf; char *fmt; int fmtl; eval_scalar *s=scalars->scalars; fmt=format->value; fmtl=format->len; while (fmtl) { if (fmt[0]=='%') { fmt++; fmtl--; if (!fmtl) break; if (fmt[0]!='%') { if (s-scalars->scalars >= scalars->count) { DEBUG_DUMP("too few parameters"); return 0; } if (!sprintf_percent(&fmt, &fmtl, &b, buf+sizeof buf, s)) return 0; s++; } else { *b++=fmt[0]; if (b-buf>=512) break; } } else { *b++=fmt[0]; if (b-buf>=512) break; } fmt++; fmtl--; } *b=0; r->type=SCALAR_STR; r->scalar.str.value=ht_strdup(buf); r->scalar.str.len=strlen(r->scalar.str.value); return 1;}/* * FUNCTIONS */int func_eval(eval_scalar *r, eval_str *p){ char *q = ht_malloc(p->len+1); int x; memcpy(q, p->value, p->len); q[p->len] = 0; x = eval(r, q, g_eval_func_handler, g_eval_symbol_handler, eval_context); free(q);/* if (get_eval_error(NULL, NULL)) { eval_error_pos+=lex_current_buffer_pos(); }*/ return x;}int func_error(eval_scalar *r, eval_str *s){ char c[1024]; bin2str(c, s->value, MIN((unsigned int)s->len, sizeof c)); set_eval_error(c); return 0;}int func_help_helper(eval_scalar *r, eval_str *s){ if (s->len > MAX_FUNCNAME_LEN) return 0; char b[MAX_FUNCNAME_LEN+1]; bin2str(b, s->value, s->len); set_helpmode(1, b); eval_scalar str; scalar_create_str_c(&str, "NaF()"); scalar_create_str_c(&helpstring, ""); func_eval(r, &str.scalar.str); *r = helpstring; scalar_destroy(&str); set_helpmode(0, NULL); return 1;}int func_whatis(eval_scalar *r, eval_str *s){ int t = 0; if (s->len != 0) t = func_help_helper(r, s); if ((s->len == 0) || (r->scalar.str.len == 0)) { char n[MAX_FUNCNAME_LEN+1]; bin2str(n, s->value, s->len); set_eval_error("no such function \"%s\"", n); return 0; } return t;}int func_help(eval_scalar *r){ eval_scalar str; scalar_create_str_c(&str, ""); int t = func_help_helper(r, &str.scalar.str); scalar_destroy(&str); return t;}eval_func builtin_evalfuncs[]= {/* eval */ { "eval", (void*)&func_eval, {SCALAR_STR}, "evaluate string" },/* help */ { "help", (void*)&func_help, {}, "get help on all functions"}, { "whatis", (void*)&func_whatis, {SCALAR_STR}, "get help on specific function"},/* type juggling */ { "int", (void*)&func_int, {SCALAR_INT}, "converts to integer" }, { "string", (void*)&func_string, {SCALAR_STR}, "converts to string" }, { "float", (void*)&func_float, {SCALAR_FLOAT}, "converts to float" }, { "byte", (void*)&func_byte, {SCALAR_INT}, "converts to byte (1 bytes)" }, { "word", (void*)&func_word, {SCALAR_INT}, "converts to uint16 (2 bytes unsigned)" }, { "dword", (void*)&func_dword, {SCALAR_INT}, "converts to uint32 (4 bytes unsigned)" }, { "sbyte", (void*)&func_sbyte, {SCALAR_INT}, "converts to signed byte (1 bytes signed)" }, { "short", (void*)&func_short, {SCALAR_INT}, "converts to short (2 bytes signed)" }, { "long", (void*)&func_long, {SCALAR_INT}, "converts to long (4 bytes signed)" }, { "typeof", (void*)&func_typeof, {SCALAR_ANY}, "returns \"int\", \"string\" or \"float\"" }, { "is_int", (void*)&func_is_int, {SCALAR_ANY}, "returns non-zero if param is an integer" }, { "is_string", (void*)&func_is_string, {SCALAR_ANY}, "returns non-zero if param is a string" }, { "is_float", (void*)&func_is_float, {SCALAR_ANY}, "returns non-zero if param is a float" },/* general */ { "error", (void*)&func_error, {SCALAR_STR}, "abort with error" },/* string functions */ { "char", (void*)&func_char, {SCALAR_INT}, "return the ascii character (1-char string) specified by p1" }, { "ord", (void*)&func_ord, {SCALAR_STR}, "return the ordinal value of p1" }, { "sprintf", (void*)&func_sprintf, {SCALAR_STR, SCALAR_VARARGS}, "returns formatted string" }, { "strchr", (void*)&func_strchr, {SCALAR_STR, SCALAR_STR}, "returns position of first occurrence of character param2 in param1" }, { "strcmp", (void*)&func_strcmp, {SCALAR_STR, SCALAR_STR}, "returns zero for equality, positive number for str1 > str2 and negative number for str1 < str2" }, { "strlen", (void*)&func_strlen, {SCALAR_STR}, "returns length of string" }, { "strncmp", (void*)&func_strncmp, {SCALAR_STR, SCALAR_STR, SCALAR_INT}, "like strcmp, but considers a maximum of param3 characters" }, { "strstr", (void*)&func_strchr, {SCALAR_STR, SCALAR_STR}, "returns position of first occurrence of string param2 in param1" }, { "substr", (void*)&func_substr, {SCALAR_STR, SCALAR_INT, SCALAR_INT}, "returns substring from param1, start param2, length param3" },/* { "stricmp", (void*)&func_stricmp, {SCALAR_STR, SCALAR_STR}, "like strcmp but case-insensitive" }, { "strnicmp", (void*)&func_strnicmp, {SCALAR_STR, SCALAR_STR}, "" }, *//* math */ { "pow", (void*)&func_pow, {SCALAR_FLOAT, SCALAR_FLOAT}, 0 }, { "sqrt", (void*)&func_sqrt, {SCALAR_FLOAT}, 0 }, { "fmin", (void*)&func_fmin, {SCALAR_FLOAT, SCALAR_FLOAT}, 0 }, { "fmax", (void*)&func_fmax, {SCALAR_FLOAT, SCALAR_FLOAT}, 0 }, { "min", (void*)&func_min, {SCALAR_INT, SCALAR_INT}, 0 }, { "max", (void*)&func_max, {SCALAR_INT, SCALAR_INT}, 0 }, { "random", (void*)&func_random, {SCALAR_INT}, "returns a random integer between 0 and param1-1" }, { "rnd", (void*)&func_rnd, {}, "returns a random bit as integer (0 or 1)" }, { "exp", (void*)&func_exp, {SCALAR_FLOAT}, 0 }, { "log", (void*)&func_log, {SCALAR_FLOAT}, 0 }, { "ceil", (void*)&func_ceil, {SCALAR_FLOAT}, 0 }, { "floor", (void*)&func_floor, {SCALAR_FLOAT}, 0 }, { "round", (void*)&func_round, {SCALAR_FLOAT}, 0 }, { "trunc", (void*)&func_trunc, {SCALAR_FLOAT}, 0 }, { "sin", (void*)&func_sin, {SCALAR_FLOAT}, 0 }, { "cos", (void*)&func_cos, {SCALAR_FLOAT}, 0 }, { "tan", (void*)&func_tan, {SCALAR_FLOAT}, 0 }, { "asin", (void*)&func_asin, {SCALAR_FLOAT}, 0 }, { "acos", (void*)&func_acos, {SCALAR_FLOAT}, 0 }, { "atan", (void*)&func_atan, {SCALAR_FLOAT}, 0 }, { "sinh", (void*)&func_sinh, {SCALAR_FLOAT}, 0 }, { "cosh", (void*)&func_cosh, {SCALAR_FLOAT}, 0 }, { "tanh", (void*)&func_tanh, {SCALAR_FLOAT}, 0 }, #ifdef HAVE_ASINH { "asinh", (void*)&func_asinh, {SCALAR_FLOAT}, 0 },#endif#ifdef HAVE_ACOSH { "acosh", (void*)&func_acosh, {SCALAR_FLOAT}, 0 },#endif#ifdef HAVE_ATANH { "atanh", (void*)&func_atanh, {SCALAR_FLOAT}, 0 },#endif { NULL, NULL }};eval_protomatch match_evalfunc_proto(char *name, eval_scalarlist *params, eval_func *proto){ int j; int protoparams=0; if (strcmp(name, proto->name)!=0) return PROTOMATCH_NAME_FAIL; for (j=0; j<MAX_EVALFUNC_PARAMS; j++) { if (proto->ptype[j]==SCALAR_NULL) break; if (proto->ptype[j]==SCALAR_VARARGS) { if (params->count > protoparams) protoparams=params->count; break; } protoparams++; } return (protoparams==params->count) ? PROTOMATCH_OK : PROTOMATCH_PARAM_FAIL;}int exec_evalfunc(eval_scalar *r, eval_scalarlist *params, eval_func *proto){ int j; int retv; eval_scalar sc[MAX_EVALFUNC_PARAMS]; void *pptrs[MAX_EVALFUNC_PARAMS]; int protoparams=0; eval_scalarlist *sclist=0; const char *errmsg; int errpos; for (j=0; j<MAX_EVALFUNC_PARAMS; j++) { sc[j].type=SCALAR_NULL; pptrs[j]=NULL; } DEBUG_DUMP("%s:", proto->name); for (j=0; j<MAX_EVALFUNC_PARAMS; j++) { int term=0; if (proto->ptype[j]==SCALAR_NULL) break; switch (proto->ptype[j]) { case SCALAR_INT: protoparams++; if (params->count<protoparams) return 0; sc[j].type=SCALAR_INT; scalar_context_int(¶ms->scalars[j], &sc[j].scalar.integer); pptrs[j]=&sc[j].scalar.integer; DEBUG_DUMP_SCALAR(&sc[j], "param %d: int=", j); break; case SCALAR_STR: protoparams++; if (params->count<protoparams) return 0; sc[j].type=SCALAR_STR; scalar_context_str(¶ms->scalars[j], &sc[j].scalar.str); pptrs[j]=&sc[j].scalar.str; DEBUG_DUMP_SCALAR(&sc[j], "param %d: str=", j); break; case SCALAR_FLOAT: protoparams++; if (params->count<protoparams) return 0; sc[j].type=SCALAR_FLOAT; scalar_context_float(¶ms->scalars[j], &sc[j].scalar.floatnum); pptrs[j]=&sc[j].scalar.floatnum; DEBUG_DUMP_SCALAR(&sc[j], "param %d: float=", j); break; case SCALAR_ANY: { protoparams++; if (params->count<protoparams) return 0; scalar_clone(&sc[j], ¶ms->scalars[j]); pptrs[j] = &sc[j]; DEBUG_DUMP_SCALAR(&sc[j], "param %d: vararg=", j); break; } case SCALAR_VARARGS: { sclist = ht_malloc(sizeof (eval_scalarlist)); sclist->count=params->count-j; if (sclist->count) { sclist->scalars=(eval_scalar*)malloc(sizeof (eval_scalar) * sclist->count); memcpy(sclist->scalars, ¶ms->scalars[j], sizeof (eval_scalar) * sclist->count); } else { sclist->scalars=NULL; } pptrs[j]=sclist; protoparams = params->count; term=1; DEBUG_DUMP_SCALARLIST(params, "param %d: varargs=", j); break; } default: set_eval_error("internal error (%s:%d)", __FILE__, __LINE__); return 0; } if (term) break; } if (params->count == protoparams) { DEBUG_DUMP_INDENT_IN; retv=((int(*)(eval_scalar*,void*,void*,void*,void*,void*,void*,void*,void*))proto->func)(r, pptrs[0], pptrs[1], pptrs[2], pptrs[3], pptrs[4], pptrs[5], pptrs[6], pptrs[7]); DEBUG_DUMP_INDENT_OUT; } else { retv=0; } if (retv) { DEBUG_DUMP_SCALAR(r, "returns "); } else { DEBUG_DUMP("fails..."); } if (sclist) { scalarlist_destroy_gentle(sclist); free(sclist); } for (j=0; j<MAX_EVALFUNC_PARAMS; j++) { if (sc[j].type!=SCALAR_NULL) { scalar_destroy(&sc[j]); } } if (!get_eval_error(NULL, NULL) && !retv) { set_eval_error("?"); } if (get_eval_error(&errmsg, &errpos)) { char ee[MAX_ERRSTR_LEN+1]; ee[MAX_ERRSTR_LEN]=0; ht_strlcpy(ee, proto->name, sizeof ee); ht_strlcat(ee, "(): ", sizeof ee); ht_strlcat(ee, errmsg, sizeof ee); set_eval_error_ex(errpos, "%s", ee); } return retv;}int evalsymbol(eval_scalar *r, char *sname){ int s=0; if (g_eval_symbol_handler) s = g_eval_symbol_handler(r, sname); if (!get_eval_error(NULL, NULL) && !s) { char sname_short[MAX_SYMBOLNAME_LEN+1]; ht_strlcpy(sname_short, sname, sizeof sname_short); set_eval_error("unknown symbol: %s", sname_short); } return s;}static const char *type2str(eval_scalartype t){ switch (t) { case SCALAR_INT: return "INT"; break; case SCALAR_STR: return "STRING"; break; case SCALAR_FLOAT: return "FLOAT"; break; case SCALAR_ANY: return "ANY"; break; case SCALAR_VARARGS: return "..."; break; default: return 0; break; }}static void proto_dump(char *buf, int bufsize, eval_func *proto, int full, const char *separator){// FIXME: buffer safety/possible buffer overflow strcpy(buf, proto->name); strcat(buf, "("); for (int j=0; j<MAX_EVALFUNC_PARAMS; j++) { if (proto->ptype[j]==SCALAR_NULL) break; if (j) strcat(buf, ", "); strcat(buf, type2str(proto->ptype[j])); if (proto->ptype[j] == SCALAR_VARARGS) break; } strcat(buf, ")"); if (full && proto->desc) { strcat(buf, separator); strcat(buf, proto->desc); }}int std_eval_func_handler(eval_scalar *result, char *fname, eval_scalarlist *params, eval_func *protos){ if (strlen(fname) > MAX_FUNCNAME_LEN) { set_eval_error("invalid function, function name too long"); return 0; } if (helpmode) { while (protos->name) { char buf[256]; if ((!*helpname) || (*helpname && (strcmp(helpname, protos->name)==0))) { if (protos->func) { proto_dump(buf, sizeof buf, protos, 1, "\n"); } else { strcpy(buf, protos->name); strcat(buf, " : "); strcat(buf, type2str(protos->ptype[0])); strcat(buf, "\n"); strcat(buf, protos->desc); } strcat(buf, "\n\n"); eval_scalar s; scalar_create_str_c(&s, buf); eval_scalar r; scalar_concat(&r, &helpstring, &s); scalar_destroy(&helpstring); scalar_destroy(&s); helpstring = r; } protos++; } } else { while (protos->name) { if (protos->func) switch (match_evalfunc_proto(fname, params, protos)) { case PROTOMATCH_OK: return exec_evalfunc(result, params, protos); case PROTOMATCH_PARAM_FAIL: { char b[256]; proto_dump(b, sizeof b, protos, 0, ""); set_eval_error("invalid params to function %s, declaration is: %s", protos->name, b); return 0; } default: {} } protos++; } } return 0;}int evalfunc(eval_scalar *r, char *fname, eval_scalarlist *params){ if (strlen(fname) > MAX_FUNCNAME_LEN) { set_eval_error("invalid function, function name too long"); return 0; } int s; if (g_eval_func_handler) { s = g_eval_func_handler(r, fname, params); if (get_eval_error(NULL, NULL)) return 0; if (s) return s; } s = std_eval_func_handler(r, fname, params, builtin_evalfuncs); if (get_eval_error(NULL, NULL)) return 0; if (s) return s; if (!helpmode) { set_eval_error("unknown function %s", fname); return 0; } else return 1;}void *eval_get_context(){ return eval_context;}void eval_set_context(void *context){ eval_context = context;}void eval_set_func_handler(eval_func_handler func_handler){ g_eval_func_handler = func_handler;}void eval_set_symbol_handler(eval_symbol_handler symbol_handler){ g_eval_symbol_handler = symbol_handler;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -