Пример #1
0
/*
 *   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);
}
Пример #2
0
/*
 *   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);
}
Пример #3
0
/*
 *   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);
}
Пример #4
0
 /* log an error */
 virtual void log_error(int err)
 {
     /* throw an error */
     err_throw_a(VMERR_INVAL_IMAGE_MACRO, 1, ERR_TYPE_INT, err);
 }
Пример #5
0
/*
 *   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);
    }
}
Пример #6
0
/*
 *   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);
}