/*
// Full copyright information is available in the file ../doc/CREDITS
*/
#include "defs.h"
#include <ctype.h>
#include "cdc_pcode.h"
#include "operators.h"
#include "functions.h"
#include "util.h"
#define FDEF(_def_, _str_, _name_) { _def_, _str_, CAT(func_, _name_) },
#define NUM_OPERATORS (sizeof(op_info) / sizeof(*op_info))
Op_info op_table[LAST_TOKEN];
static Int first_function;
static Op_info op_info[] = {
{ COMMENT, "COMMENT", op_comment, STRING },
{ POP, "POP", op_pop },
{ SET_LOCAL, "SET_LOCAL", op_set_local, VAR },
{ SET_OBJ_VAR, "SET_OBJ_VAR", op_set_obj_var, IDENT },
{ IF, "IF", op_if, JUMP },
{ IF_ELSE, "IF_ELSE", op_if, JUMP },
{ ELSE, "ELSE", op_else, JUMP },
{ FOR_RANGE, "FOR_RANGE", op_for_range, JUMP, INTEGER },
{ FOR_LIST, "FOR_LIST", op_for_list, JUMP, INTEGER },
{ WHILE, "WHILE", op_while, JUMP, JUMP },
{ SWITCH, "SWITCH", op_switch, JUMP },
{ CASE_VALUE, "CASE_VALUE", op_case_value, JUMP },
{ CASE_RANGE, "CASE_RANGE", op_case_range, JUMP },
{ LAST_CASE_VALUE, "LAST_CASE_VALUE", op_last_case_value, JUMP },
{ LAST_CASE_RANGE, "LAST_CASE_RANGE", op_last_case_range, JUMP },
{ END_CASE, "END_CASE", op_end_case, JUMP },
{ DEFAULT, "DEFAULT", op_default },
{ END, "END", op_end, JUMP },
{ BREAK, "BREAK", op_break, JUMP, INTEGER },
{ CONTINUE, "CONTINUE", op_continue, JUMP, INTEGER },
{ RETURN, "RETURN", op_return },
{ RETURN_EXPR, "RETURN_EXPR", op_return_expr },
{ CATCH, "CATCH", op_catch, JUMP, T_ERROR },
{ CATCH_END, "CATCH_END", op_catch_end, JUMP },
{ HANDLER_END, "HANDLER_END", op_handler_end },
{ ZERO, "ZERO", op_zero },
{ ONE, "ONE", op_one },
{ INTEGER, "INTEGER", op_integer, INTEGER },
/* By the time it examines the arg, the FLOAT has already been
cast into an INTEGER, so we just need to let it know its an INT */
{ FLOAT, "FLOAT", op_float, INTEGER },
{ STRING, "STRING", op_string, STRING },
{ OBJNUM, "OBJNUM", op_objnum, INTEGER },
{ SYMBOL, "SYMBOL", op_symbol, IDENT },
{ T_ERROR, "ERROR", op_error, IDENT },
{ OBJNAME, "OBJNAME", op_objname, IDENT },
{ GET_LOCAL, "GET_LOCAL", op_get_local, VAR },
{ GET_OBJ_VAR, "GET_OBJ_VAR", op_get_obj_var, IDENT },
{ START_ARGS, "START_ARGS", op_start_args },
{ PASS, "PASS", op_pass },
{ CALL_METHOD, "CALL_METHOD", op_message, IDENT },
{ EXPR_CALL_METHOD, "EXPR_CALL_METHOD", op_expr_message },
{ LIST, "LIST", op_list },
{ DICT, "DICT", op_dict },
{ BUFFER, "BUFFER", op_buffer },
{ FROB, "FROB", op_frob },
{ OP_HANDLED_FROB, "FROB", op_handled_frob },
{ INDEX, "INDEX", op_index },
{ AND, "AND", op_and, JUMP },
{ OR, "OR", op_or, JUMP },
{ CONDITIONAL, "CONDITIONAL", op_if, JUMP },
{ OP_MAP, "OP_MAP", op_map, JUMP, VAR },
{ OP_MAP_RANGE, "OP_MAP_RANGE", op_map_range, JUMP, VAR },
{ OP_FIND, "OP_FIND", op_map, JUMP, VAR },
{ OP_FIND_RANGE, "OP_FIND_RANGE", op_map_range, JUMP, VAR },
{ OP_FILTER, "OP_FILTER", op_map, JUMP, VAR },
{ OP_FILTER_RANGE, "OP_FILTER_RANGE", op_map_range, JUMP, VAR },
{ OP_MAPHASH, "OP_MAPHASH", op_map, JUMP, VAR },
{ OP_MAPHASH_RANGE, "OP_MAPHASH_RANGE",op_map_range, JUMP, VAR },
{ SPLICE, "SPLICE", op_splice },
{ CRITICAL, "CRITICAL", op_critical, JUMP },
{ CRITICAL_END, "CRITICAL_END", op_critical_end },
{ PROPAGATE, "PROPAGATE", op_propagate, JUMP },
{ PROPAGATE_END, "PROPAGATE_END", op_propagate_end },
/* Arithmetic and relational operators (arithop.c). */
{ '!', "!", op_not },
{ NEG, "NEG", op_negate },
{ '*', "*", op_multiply },
{ '/', "/", op_divide },
{ '%', "%", op_modulo },
{ '+', "+", op_add },
{ SPLICE_ADD, "SPLICE_ADD", op_splice_add },
{ '-', "-", op_subtract },
{ EQ, "EQ", op_equal },
{ NE, "NE", op_not_equal },
{ '>', ">", op_greater },
{ GE, ">=", op_greater_or_equal },
{ '<', "<", op_less },
{ LE, "<=", op_less_or_equal },
{ OP_IN, "IN", op_in },
{ P_INCREMENT, "P_INCREMENT", op_p_increment },
{ P_DECREMENT, "P_DECREMENT", op_p_decrement },
{ INCREMENT, "INCREMENT", op_increment },
{ DECREMENT, "DECREMENT", op_decrement },
{ MULT_EQ, "MULT_EQ", op_doeq_multiply },
{ DIV_EQ, "DIV_EQ", op_doeq_divide },
{ PLUS_EQ, "PLUS_EQ", op_doeq_add },
{ MINUS_EQ, "MINUS_EQ", op_doeq_subtract },
{ OPTIONAL_ASSIGN, "OPTIONAL_ASSIGN", op_optional_assign, JUMP },
{ OPTIONAL_END, "OPTIONAL_END", op_optional_end },
{ SCATTER_START, "SCATTER_START", op_scatter_start },
{ SCATTER_END, "SCATTER_END", 0},
/* Object variable functions */
FDEF(F_ADD_VAR, "add_var", add_var)
FDEF(F_DEL_VAR, "del_var", del_var)
FDEF(F_SET_VAR, "set_var", set_var)
FDEF(F_GET_VAR, "get_var", get_var)
FDEF(F_INHERITED_VAR, "inherited_var", inherited_var)
FDEF(F_DEFAULT_VAR, "default_var", default_var)
FDEF(F_CLEAR_VAR, "clear_var", clear_var)
FDEF(F_VARIABLES, "variables", variables)
/* debugger */
FDEF(F_DEBUG_CALLERS, "debug_callers", debug_callers)
FDEF(F_CALL_TRACE, "call_trace", call_trace)
/* Object method functions */
FDEF(F_LIST_METHOD, "list_method", list_method)
FDEF(F_ADD_METHOD, "add_method", add_method)
FDEF(F_DEL_METHOD, "del_method", del_method)
FDEF(F_METHOD_BYTECODE, "method_bytecode", method_bytecode)
FDEF(F_RENAME_METHOD, "rename_method", rename_method)
FDEF(F_SET_METHOD_FLAGS, "set_method_flags", set_method_flags)
FDEF(F_SET_METHOD_ACCESS, "set_method_access", set_method_access)
FDEF(F_METHOD_INFO, "method_info", method_info)
FDEF(F_METHOD_FLAGS, "method_flags", method_flags)
FDEF(F_METHOD_ACCESS, "method_access", method_access)
FDEF(F_METHODS, "methods", methods)
FDEF(F_FIND_METHOD, "find_method", find_method)
FDEF(F_FIND_NEXT_METHOD, "find_next_method", find_next_method)
/* Object functions */
FDEF(F_PARENTS, "parents", parents)
FDEF(F_CHILDREN, "children", children)
FDEF(F_ANCESTORS, "ancestors", ancestors)
FDEF(F_HAS_ANCESTOR, "has_ancestor", has_ancestor)
FDEF(F_SIZE, "size", size)
FDEF(F_CREATE, "create", create)
FDEF(F_CHPARENTS, "chparents", chparents)
FDEF(F_DESTROY, "destroy", destroy)
FDEF(F_SET_OBJNAME, "set_objname", set_objname)
FDEF(F_DEL_OBJNAME, "del_objname", del_objname)
FDEF(F_OBJNAME, "objname", objname)
FDEF(F_OBJNUM, "objnum", objnum)
FDEF(F_LOOKUP, "lookup", lookup)
FDEF(F_DATA, "data", data)
/* System functions */
{ F_DBLOG, "dblog", func_dblog },
{ F_BACKUP, "backup", func_backup },
{ F_SHUTDOWN, "shutdown", func_shutdown },
{ F_SET_HEARTBEAT, "set_heartbeat", func_set_heartbeat },
/* Task/Frame functions */
{ F_TICK, "tick", func_tick },
{ F_RESUME, "resume", func_resume },
{ F_SUSPEND, "suspend", func_suspend },
{ F_TASKS, "tasks", func_tasks },
{ F_TASK_INFO, "task_info", func_task_info },
{ F_TASK_ID, "task_id", func_task_id },
{ F_CANCEL, "cancel", func_cancel },
{ F_PAUSE, "pause", func_pause },
{ F_REFRESH, "refresh", func_refresh },
{ F_TICKS_LEFT, "ticks_left", func_ticks_left },
{ F_METHODOP, "method", func_method },
{ F_THIS, "this", func_this },
{ F_DEFINER, "definer", func_definer },
{ F_SENDER, "sender", func_sender },
{ F_CALLER, "caller", func_caller },
{ F_STACK, "stack", func_stack },
{ F_ATOMIC, "atomic", func_atomic },
{ F_USER, "user", func_user },
{ F_SET_USER, "set_user", func_set_user },
/* Data/Conversion functions */
{ F_VALID, "valid", func_valid },
{ F_TYPE, "type", func_type },
{ F_CLASS, "class", /* devalued */ func_frob_class },
{ F_FROB_CLASS, "frob_class", func_frob_class },
{ F_VALUE, "frob_value", func_frob_value },
{ F_HANDLER, "frob_handler", func_frob_handler },
{ F_TOINT, "toint", func_toint },
{ F_TOFLOAT, "tofloat", func_tofloat },
{ F_TOSTR, "tostr", func_tostr },
{ F_TOLITERAL, "toliteral", func_toliteral },
{ F_FROMLITERAL, "fromliteral", func_fromliteral },
{ F_TOOBJNUM, "toobjnum", func_toobjnum },
{ F_TOSYM, "tosym", func_tosym },
{ F_TOERR, "toerr", func_toerr },
/* Exception functions */
{ F_ERROR_FUNC, "error", func_error },
{ F_TRACEBACK, "traceback", func_traceback },
{ F_THROW, "throw", func_throw },
{ F_RETHROW, "rethrow", func_rethrow },
/* Network control functions */
{ F_REASSIGN_CONNECTION,"reassign_connection",func_reassign_connection },
{ F_BIND_PORT, "bind_port", func_bind_port },
{ F_UNBIND_PORT, "unbind_port", func_unbind_port },
{ F_OPEN_CONNECTION, "open_connection", func_open_connection },
{ F_CLOSE_CONNECTION, "close_connection", func_close_connection },
{ F_CWRITE, "cwrite", func_cwrite },
{ F_CWRITEF, "cwritef", func_cwritef },
{ F_CONNECTION, "connection", func_connection },
/* File control functions */
{ F_EXECUTE, "execute", func_execute },
{ F_FSTAT, "fstat", func_fstat },
{ F_FREAD, "fread", func_fread },
{ F_FCHMOD, "fchmod", func_fchmod },
{ F_FMKDIR, "fmkdir", func_fmkdir },
{ F_FRMDIR, "frmdir", func_frmdir },
{ F_FILES, "files", func_files },
{ F_FREMOVE, "fremove", func_fremove },
{ F_FRENAME, "frename", func_frename },
{ F_FOPEN, "fopen", func_fopen },
{ F_FCLOSE, "fclose", func_fclose },
{ F_FSEEK, "fseek", func_fseek },
{ F_FEOF, "feof", func_feof },
{ F_FWRITE, "fwrite", func_fwrite },
{ F_FILE, "file", func_file },
{ F_FFLUSH, "fflush", func_fflush },
/* Miscellaneous functions */
{ F_FLUSH, "anticipate_assignment", func_anticipate_assignment},
{ F_LOCALTIME, "localtime", func_localtime },
{ F_TIME, "time", func_time },
{ F_MTIME, "mtime", func_mtime },
{ F_CTIME, "ctime", func_ctime },
{ F_BIND_FUNCTION, "bind_function", func_bind_function },
{ F_UNBIND_FUNCTION, "unbind_function", func_unbind_function },
{ F_CONFIG, "config", func_config },
{ F_RANDOM, "random", func_random },
{ F_MIN, "min", func_min },
{ F_MAX, "max", func_max },
{ F_ABS, "abs", func_abs },
{ F_SIN, "sin", func_sin },
{ F_EXP, "exp", func_exp },
{ F_LOG, "log", func_log },
{ F_COS, "cos", func_cos },
{ F_TAN, "tan", func_tan },
{ F_SQRT, "sqrt", func_sqrt },
{ F_ASIN, "asin", func_asin },
{ F_ACOS, "acos", func_acos },
{ F_ATAN, "atan", func_atan },
{ F_POW, "pow", func_pow },
{ F_ATAN2, "atan2", func_atan2 },
{ F_ROUND, "round", func_round },
/* Operations on strings (stringop.c). */
{ F_STRFMT, "strfmt", func_strfmt },
{ F_STRLEN, "strlen", func_strlen },
{ F_SUBSTR, "substr", func_substr },
{ F_EXPLODE, "explode", func_explode },
{ F_STRSUB, "strsub", func_strsub },
{ F_PAD, "pad", func_pad },
{ F_MATCH_BEGIN, "match_begin", func_match_begin },
{ F_MATCH_TEMPLATE, "match_template", func_match_template },
{ F_MATCH_PATTERN, "match_pattern", func_match_pattern },
{ F_MATCH_REGEXP, "match_regexp", func_match_regexp },
{ F_REGEXP, "regexp", func_regexp },
{ F_SPLIT, "split", func_split },
{ F_CRYPT, "crypt", func_crypt },
{ F_MATCH_CRYPTED, "match_crypted", func_match_crypted },
{ F_UPPERCASE, "uppercase", func_uppercase },
{ F_LOWERCASE, "lowercase", func_lowercase },
{ F_STRCMP, "strcmp", func_strcmp },
{ F_STRSED, "strsed", func_strsed },
{ F_STRGRAFT, "strgraft", func_strgraft },
{ F_STRIDX, "stridx", func_stridx },
/* List manipulation (listop.c). */
{ F_LISTLEN, "listlen", func_listlen },
{ F_SUBLIST, "sublist", func_sublist },
{ F_INSERT, "insert", func_insert },
{ F_REPLACE, "replace", func_replace },
{ F_DELETE, "delete", func_delete },
{ F_SETADD, "setadd", func_setadd },
{ F_SETREMOVE, "setremove", func_setremove },
{ F_UNION, "union", func_union },
{ F_LISTGRAFT, "listgraft", func_listgraft },
{ F_JOIN, "join", func_join },
{ F_LISTIDX, "listidx", func_listidx },
/* Dictionary manipulation (dictop.c). */
{ F_DICT_VALUES, "dict_values", func_dict_values },
{ F_DICT_KEYS, "dict_keys", func_dict_keys },
{ F_DICT_ADD, "dict_add", func_dict_add },
{ F_DICT_DEL, "dict_del", func_dict_del },
{ F_DICT_CONTAINS, "dict_contains", func_dict_contains },
{ F_DICT_UNION, "dict_union", func_dict_union },
/* Buffer manipulation (bufferop.c). */
{ F_BUFLEN, "buflen", func_buflen },
{ F_BUFIDX, "bufidx", func_bufidx },
{ F_BUF_REPLACE, "buf_replace", func_buf_replace },
{ F_BUF_TO_STRINGS, "buf_to_strings", func_buf_to_strings },
{ F_BUF_TO_STR, "buf_to_str", func_buf_to_str },
{ F_STRINGS_TO_BUF, "strings_to_buf", func_strings_to_buf },
{ F_STR_TO_BUF, "str_to_buf", func_str_to_buf },
{ F_SUBBUF, "subbuf", func_subbuf },
{ F_BUFGRAFT, "bufgraft", func_bufgraft },
};
void init_op_table(void) {
Int i;
for (i = 0; i < NUM_OPERATORS; i++) {
op_info[i].binding = INV_OBJNUM;
op_info[i].symbol = ident_get(op_info[i].name);
op_table[op_info[i].opcode] = op_info[i];
}
/* Look for first opcode with a lowercase name to find the first
* function. */
for (i = 0; i < NUM_OPERATORS; i++) {
if (islower(*op_info[i].name))
break;
}
first_function = i;
}
Int find_function(char *name) {
Int i;
for (i = first_function; i < NUM_OPERATORS; i++) {
if (strcmp(op_info[i].name, name) == 0)
return op_info[i].opcode;
}
return -1;
}