/* * Call the given function from the given function set. */ void CVmBifTable::call_func(VMG_ uint set_index, uint func_index, uint argc) { vm_bif_entry_t *entry; vm_bif_desc *desc; /* get the function set */ entry = table_[set_index]; /* if the function set is null, we can't call the function */ if (entry == 0) err_throw_a(VMERR_UNKNOWN_FUNC_SET, 1, ERR_TYPE_TEXTCHAR, names_[set_index]); /* get the function pointer */ desc = &entry->func[func_index]; /* if the function is null, we can't call it */ if (desc->func == 0) err_throw_a(VMERR_UNAVAIL_INTRINSIC, 2, ERR_TYPE_TEXTCHAR, names_[set_index], ERR_TYPE_INT, func_index); /* call the function */ (*desc->func)(vmg_ argc); }
/* * Add an entry to the table */ void CVmMetaTable::add_entry(const char *metaclass_id, size_t func_cnt, vm_prop_id_t min_prop, vm_prop_id_t max_prop) { vm_meta_reg_t *entry; uint idx; const char *vsn; size_t name_len; /* find the version suffix in the metaclass name, if any */ vsn = lib_find_vsn_suffix(metaclass_id, '/', "000000", &name_len); /* ensure we have space for one more entry */ ensure_space(count_ + 1, 5); /* look up the metaclass by name */ for (idx = 0, entry = G_meta_reg_table ; entry->meta != 0 ; ++entry, ++idx) { const char *entry_vsn; size_t entry_name_len; /* find the version number in this entry */ entry_vsn = lib_find_vsn_suffix((*entry->meta)->get_meta_name(), '/', "000000", &entry_name_len); /* see if this is a match */ if (name_len == entry_name_len && memcmp(metaclass_id, (*entry->meta)->get_meta_name(), name_len) == 0) { /* * make sure the version provided in the VM is at least as * high as the requested version */ if (strcmp(vsn, entry_vsn) > 0) err_throw_a(VMERR_METACLASS_TOO_OLD, 2, ERR_TYPE_TEXTCHAR, metaclass_id, ERR_TYPE_TEXTCHAR, entry_vsn); /* add this entry */ add_entry(metaclass_id, idx, func_cnt, min_prop, max_prop); /* we're done */ return; } } /* we didn't find it - throw an error */ err_throw_a(VMERR_UNKNOWN_METACLASS, 1, ERR_TYPE_TEXTCHAR, metaclass_id); }
/* * Handle adding a function set entry that's unresolvable at load-time */ void CVmBifTable::add_entry_unresolved(VMG_ const char *func_set_id) { /* this is the static-link version, so an unresolved entry is an error */ err_throw_a(VMERR_UNKNOWN_FUNC_SET, 3, ERR_TYPE_TEXTCHAR, func_set_id, ERR_TYPE_FUNCSET, func_set_id, ERR_TYPE_VERSION_FLAG); }
/* log an error */ virtual void log_error(int err) { /* throw an error */ err_throw_a(VMERR_INVAL_IMAGE_MACRO, 1, ERR_TYPE_INT, err); }
/* * Look up a named argument. If 'mandatory' is set, we throw an error if * we can't find a resolution. */ void CVmBifT3::get_named_arg(VMG_ uint argc) { /* check arguments */ check_argc_range(vmg_ argc, 1, 2); /* get the name we're looking for */ const char *name = G_stk->get(0)->get_as_string(vmg0_); if (name == 0) err_throw(VMERR_STRING_VAL_REQD); /* get the length and buffer pointer */ size_t namelen = vmb_get_len(name); name += VMB_LEN; /* * Scan the stack for named parameter tables. A named parameter table * is always in the calling frame at the stack slot just beyond the * last argument. */ for (vm_val_t *fp = G_interpreter->get_frame_ptr() ; fp != 0 ; fp = G_interpreter->get_enclosing_frame_ptr(vmg_ fp)) { /* check for a table in this frame */ vm_val_t *argp; const uchar *t = CVmRun::get_named_args_from_frame(vmg_ fp, &argp); if (t != 0) { /* get the number of table entries */ int n = osrp2(t); t += 2; /* scan the table for the name */ for (int i = 0 ; n >= 0 ; --n, i += 2, ++argp) { /* get this element's offset, and figure its length */ uint eofs = osrp2(t + i); uint elen = osrp2(t + i + 2) - eofs; /* check for a match */ if (elen == namelen && memcmp(name, t + eofs, elen) == 0) { /* found it - return the value */ retval(vmg_ argp); /* discard arguments and return */ G_stk->discard(argc); return; } } } } /* * The argument is undefined. If a default value was supplied, simply * return the default value. Otherwise throw an error. */ if (argc >= 2) { /* a default value was supplied - simply return it */ retval(vmg_ G_stk->get(1)); /* discard arguments */ G_stk->discard(argc); } else { /* no default value - throw an error */ err_throw_a(VMERR_MISSING_NAMED_ARG, 1, ERR_TYPE_TEXTCHAR_LEN, name, namelen); } }
/* * Handle adding a function set entry that's unresolvable at load-time */ void CVmBifTable::add_entry_unresolved(const char *func_set_id) { /* we can't load it - throw an error */ err_throw_a(VMERR_UNKNOWN_FUNC_SET, 1, ERR_TYPE_TEXTCHAR, func_set_id); }