Пример #1
0
/*
 *   allocate a new page 
 */
void CTcDataStream::alloc_page()
{
    /* 
     *   if we're coming back to a page that was previously allocated, we
     *   need merely re-establish the existing page 
     */
    if (page_cur_ + 1 < page_cnt_)
    {
        /* move to the next page */
        ++page_cur_;

        /* start writing at the start of the page */
        wp_ = pages_[page_cur_];
        rem_ = TCCS_PAGE_SIZE;

        /* we're done */
        return;
    }

    /* 
     *   if we don't have room for a new page in the page array, expand
     *   the page array 
     */
    if (page_cnt_ >= page_slots_)
    {
        /* increase the page slot count */
        page_slots_ += 100;

        /* allocate or reallocate the page array */
        if (pages_ == 0)
            pages_ = (char **)t3malloc(page_slots_ * sizeof(pages_[0]));
        else
            pages_ = (char **)t3realloc(pages_,
                                        page_slots_ * sizeof(pages_[0]));

        /* if that failed, throw an error */
        if (pages_ == 0)
            err_throw(TCERR_CODEGEN_NO_MEM);
    }

    /* allocate the new page */
    pages_[page_cnt_] = (char *)t3malloc(TCCS_PAGE_SIZE);

    /* throw an error if we couldn't allocate the page */
    if (pages_[page_cnt_] == 0)
        err_throw(TCERR_CODEGEN_NO_MEM);

    /* start writing at the start of the new page */
    wp_ = pages_[page_cnt_];

    /* the entire page is free */
    rem_ = TCCS_PAGE_SIZE;

    /* make the new page the current page */
    page_cur_ = page_cnt_;

    /* count the new page */
    ++page_cnt_;
}
Пример #2
0
/* 
 *   assign an indexed value: this sets a variable's value by index
 */
int CVmObjFrameRef::set_index_val_q(VMG_ vm_val_t *new_container,
                                    vm_obj_id_t self,
                                    const vm_val_t *index_val,
                                    const vm_val_t *new_val)
{
    /* get our extension */
    vm_frameref_ext *ext = get_ext();

    /* check the type */
    if (index_val->typ == VM_INT)
    {
        /* 
         *   It's a direct index into the frame.  Make sure the value is in
         *   range.  
         */
        int n = index_val->val.intval;
        if (n < 0 || n >= ext->nlocals + ext->nparams)
            err_throw(VMERR_INDEX_OUT_OF_RANGE);

        /*  
         *   If we have an active stack frame, read the value from the stack;
         *   otherwise read it from the snapshot array.  
         */
        if (ext->fp != 0)
        {
            /* get it from the stack frame */
            if (n < ext->nlocals)
            {
                /* it's in the local variable range */
                *G_interpreter->get_local_from_frame(vmg_ ext->fp, n) =
                    *new_val;
            }
            else
            {
                /* it's in the parameter range */
                *G_interpreter->get_param_from_frame(
                    vmg_ ext->fp, n - ext->nlocals) = *new_val;
            }
        }
        else
        {
            /* there's no frame - get it from the snapshot array */
            ext->vars[n] = *new_val;
        }
    }
    else
    {
        /* invalid index type */
        err_throw(VMERR_INDEX_OUT_OF_RANGE);
    }

    /* the container doesn't change */
    new_container->set_obj(self);

    /* handled */
    return TRUE;
}
Пример #3
0
/*
 *   Empty a local directory 
 */
static void empty_dir(VMG_ const char *dir)
{
    /* open the directory search */
    osdirhdl_t dirhdl;
    if (os_open_dir(dir, &dirhdl))
    {
        err_try
        {
            /* keep going until we're out of files */
            char fname[OSFNMAX];
            while (os_read_dir(dirhdl, fname, sizeof(fname)))
            {
                /* get the full path */
                char path[OSFNMAX];
                os_build_full_path(path, sizeof(path), dir, fname);

                /* get the mode */
                unsigned long fmode;
                unsigned long fattr;
                if (osfmode(path, FALSE, &fmode, &fattr))
                {
                    /* check whether it's a directory or an ordinary file */
                    if ((fmode & OSFMODE_DIR) != 0)
                    {
                        /* 
                         *   directory - skip the special '.' and '..' links,
                         *   since they'd get us stuck in a loop 
                         */
                        os_specfile_t st = os_is_special_file(fname);
                        if (st != OS_SPECFILE_SELF && st != OS_SPECFILE_PARENT)
                        {
                            /* recursively empty the directory */
                            empty_dir(vmg_ path);
                            
                            /* remove this directory */
                            if (!os_rmdir(path))
                                err_throw(VMERR_DELETE_FILE);
                        }
                    }
                    else
                    {
                        /* ordinary file - delete it */
                        if (osfdel(path))
                            err_throw(VMERR_DELETE_FILE);
                    }
                }
            }
        }
        err_finally
        {
            /* close the directory search handle */
            os_close_dir(dirhdl);
        }
        err_end;
    }
Пример #4
0
/*
 *   create from stack arguments
 */
vm_obj_id_t CVmObjAnonFn::create_from_stack(VMG_ const uchar **pc_ptr,
                                            uint argc)
{
    vm_obj_id_t id;
    vm_val_t funcptr;
    CVmObjAnonFn *new_obj;
    uint idx;
    
    /* at least one argument is required (the function pointer) */
    if (argc < 1)
        err_throw(VMERR_WRONG_NUM_OF_ARGS);

    /* retrieve our function pointer argument */
    G_stk->pop(&funcptr);
    if (funcptr.typ == VM_FUNCPTR)
    {
        /* it's a regular function pointer - accept it */
    }
    else if (funcptr.typ == VM_OBJ
             && vm_objp(vmg_ funcptr.val.obj)->get_invoker(vmg_ 0))
    {
        /* it's a pointer to an invokable object - accept it */
    }
    else
    {
        /* it's not a valid function pointer */
        err_throw(VMERR_FUNCPTR_VAL_REQD);
    }

    /* create the new object */
    id = vm_new_id(vmg_ FALSE, TRUE, FALSE);

    /* create the new object, giving it one slot per constructor argument */
    new_obj = new (vmg_ id) CVmObjAnonFn(vmg_ argc);

    /* set the first element to our function pointer */
    new_obj->set_element(0, &funcptr);

    /* set the remaining elements to the context objects */
    for (idx = 1 ; idx < argc ; ++idx)
    {
        vm_val_t val;
        
        /* pop this value */
        G_stk->pop(&val);

        /* set the element */
        new_obj->set_element(idx, &val);
    }

    /* return the new object ID */
    return id;
}
Пример #5
0
/**
 * execute a procedure
 */
int sblmgr_procexec(int lib_id, int index) {
#if defined(LNX_EXTLIB) || defined(WIN_EXTLIB)
  slib_t *lib;
  var_t ret;
  slib_par_t *ptable = NULL;
  int (*pexec) (int, int, slib_par_t *, var_t *);
  int pcount = 0;
  int success = 0;

  if (lib_id < 0 || lib_id >= slib_count) {
    return 0;
  }

  lib = &slib_table[lib_id];
  pexec = slib_getoptptr(lib, "sblib_proc_exec");
  if (pexec == NULL) {
    return 0;
  }

  // build parameter table
  ptable = malloc(sizeof(slib_par_t) * MAX_PARAM);
  pcount = slib_build_ptable(ptable);
  if (prog_error) {
    slib_free_ptable(ptable, pcount);
    free(ptable);
    return 0;
  }

  // exec
  v_init(&ret);
  success = pexec(index - lib->first_proc, pcount, ptable, &ret);

  // error
  if (!success) {
    if (ret.type == V_STR) {
      err_throw("lib:%s: %s\n", lib->name, ret.v.p.ptr);
    } else {
      err_throw("lib:%s: Unspecified error\n", lib->name);
    }
  }
  // clean-up
  if (ptable) {
    slib_free_ptable(ptable, pcount);
    free(ptable);
  }

  v_free(&ret);
  return success;
#else
  return 0;
#endif
}
Пример #6
0
/*
 *   Rename a file
 */
void CVmNetFile::rename_to_local(VMG_ CVmNetFile *newname)
{
    /* if the new name isn't local, this isn't supported */
    if (newname->is_net_file())
        err_throw(VMERR_RENAME_FILE);

    /* if the destination file already exists, it's an error */
    if (!osfacc(newname->lclfname))
        err_throw(VMERR_RENAME_FILE);

    /* do the rename */
    if (!os_rename_file(lclfname, newname->lclfname))
        err_throw(VMERR_RENAME_FILE);
}
Пример #7
0
/*
 *   Allocate a new label object 
 */
CTcCodeLabel *CTcCodeStream::alloc_label()
{
    CTcCodeLabel *ret;
    
    /* if there's anything in the free list, use it */
    if (free_lbl_ != 0)
    {
        /* take the first one off the free list */
        ret = free_lbl_;

        /* unlink it from the list */
        free_lbl_ = free_lbl_->nxt;
    }
    else
    {
        /* allocate a new label */
        ret = new (allocator_) CTcCodeLabel;

        /* throw an error if allocation failed */
        if (ret == 0)
            err_throw(TCERR_CODEGEN_NO_MEM);
    }

    /* add the label to the active list */
    ret->nxt = active_lbl_;
    active_lbl_ = ret;

    /* return the allocated label */
    return ret;
}
Пример #8
0
/* 
 *   create dynamically using stack arguments 
 */
vm_obj_id_t CVmObjClass::create_from_stack(VMG_ const uchar **pc_ptr,
                                           uint argc)
{
    /* it is illegal to create this type of object dynamically */
    err_throw(VMERR_ILLEGAL_NEW);
    AFTER_ERR_THROW(return VM_INVALID_OBJ;)
}
Пример #9
0
/* load image data */
void CVmObjClass::load_image_data(VMG_ vm_obj_id_t self,
                                  const char *ptr, size_t siz)
{
    /* make sure the length is valid */
    if (siz < 8)
        err_throw(VMERR_INVAL_METACLASS_DATA);

    /* allocate or reallocate the extension */
    vm_intcls_ext *ext = alloc_ext(vmg0_);

    /* 
     *   read the metaclass index and modifier object ID; note that modifier
     *   objects are always root set objects, so there's no need to worry
     *   about fixups 
     */
    ext->meta_idx = osrp2(ptr+2);
    ext->mod_obj = (vm_obj_id_t)t3rp4u(ptr+4);

    /* if we have a class state value, read it */
    ext->class_state.set_nil();
    if (siz >= 2+4+VMB_DATAHOLDER)
        vmb_get_dh(ptr+8, &ext->class_state);
        
    /* register myself */
    register_meta(vmg_ self);
}
Пример #10
0
/*
 *   Debug Trace 
 */
void CVmBifT3::debug_trace(VMG_ uint argc)
{
    /* make sure we have at least one argument */
    if (argc < 1)
        err_throw(VMERR_WRONG_NUM_OF_ARGS);
    
    /* pop the flags and see what we're being asked to do */
    switch(pop_int_val(vmg0_))
    {
    case T3DBG_CHECK:
        /* check arguments */
        check_argc(vmg_ argc, 1);
        
        /* we're just being asked if the debugger is present - it is */
        retval_true(vmg0_);
        break;

    case T3DBG_BREAK:
        /* check arguments */
        check_argc(vmg_ argc, 1);

        /* tell the debugger to activate debug-trace mode */
        G_debugger->set_debug_trace();

        /* tell the caller we were successful */
        retval_true(vmg0_);
        break;

    default:
        /* anything else just returns nil, to allow for future expansion */
        G_stk->discard(argc - 1);
        retval_nil(vmg0_);
        break;
    }
}
Пример #11
0
/* 
 *   set a property 
 */
void CVmObjHTTPServer::set_prop(VMG_ class CVmUndo *undo,
                                vm_obj_id_t self, vm_prop_id_t prop,
                                const vm_val_t *val)
{
    /* no settable properties - throw an error */
    err_throw(VMERR_INVALID_SETPROP);
}
Пример #12
0
/*
 *   Allocate a new fixup object
 */
CTcLabelFixup *CTcCodeStream::alloc_fixup()
{
    CTcLabelFixup *ret;

    /* if there's anything in the free list, use it */
    if (free_fixup_ != 0)
    {
        /* take the first one off the free list */
        ret = free_fixup_;

        /* unlink it from the list */
        free_fixup_ = free_fixup_->nxt;
    }
    else
    {
        /* allocate a new fixup */
        ret = new (allocator_) CTcLabelFixup;

        /* throw an error if allocation failed */
        if (ret == 0)
            err_throw(TCERR_CODEGEN_NO_MEM);
    }

    /* return the allocated fixup */
    return ret;
}
Пример #13
0
/*
 *   open for reading 
 */
void CVmFile::open_read(const char *fname, os_filetype_t typ)
{
    /* try opening the underlying OS file for binary reading */
    fp_ = osfoprb(fname, typ);

    /* if that failed, throw an error */
    if (fp_ == 0)
        err_throw(VMERR_FILE_NOT_FOUND);
}
Пример #14
0
/*
 *   open for writing 
 */
void CVmFile::open_write(const char *fname, os_filetype_t typ)
{
    /* try opening the underlying OS file for binary writing */
    fp_ = osfopwb(fname, typ);

    /* if that failed, throw an error */
    if (fp_ == 0)
        err_throw(VMERR_CREATE_FILE);
}
Пример #15
0
/*
 *   Invoke the VM-stack-based constructor for the metaclass at the given
 *   index 
 */
vm_obj_id_t CVmMetaTable::create_from_stack(VMG_ const uchar **pc_ptr,
                                            uint idx, uint argc)
{
    /* make sure the entry is defined */
    if (idx >= count_)
        err_throw(VMERR_BAD_METACLASS_INDEX);
    
    /* invoke the appropriate constructor */
    return table_[idx].meta_->create_from_stack(vmg_ pc_ptr, argc);
}
Пример #16
0
/*
 *   Call a static property in the metaclass at the given index 
 */
int CVmMetaTable::call_static_prop(VMG_ vm_val_t *result,
                                   const uchar **pc_ptr, uint idx,
                                   uint *argc, vm_prop_id_t prop)
{
    /* make sure the entry is defined */
    if (idx >= count_)
        err_throw(VMERR_BAD_METACLASS_INDEX);

    /* invoke the appropriate static property evaluator */
    return table_[idx].meta_->call_stat_prop(vmg_ result, pc_ptr, argc, prop);
}
Пример #17
0
/* 
 *   index the frame: this looks up a variable's value by name 
 */
int CVmObjFrameDesc::index_val_q(VMG_ vm_val_t *result,
                                 vm_obj_id_t self,
                                 const vm_val_t *index_val)
{
    /* check the index type */
    if (index_val->get_as_string(vmg0_))
    {
        /* it's a string - look up the value by name */
        if (!get_local_val(vmg_ result, index_val))
            err_throw(VMERR_INDEX_OUT_OF_RANGE);
    }
    else
    {
        /* invalid index type */
        err_throw(VMERR_INDEX_OUT_OF_RANGE);
    }

    /* handled */
    return TRUE;
}
Пример #18
0
size_t utf_length(str_t s, int enc) {
	size_t res = 0;
	str_it_t i = str_begin(s);
	str_it_t e = str_end(s);
	while(i<e) {
		int cl = CHAR_LEN(i, enc);
		res++;
		i += cl;
		if(i>e)
			err_throw(e_utf_conversion);
	}
	return res;
}
Пример #19
0
/*
 *   Create an object of the given metaclass with the given ID, in
 *   preparation for restoring the object's data from saved state
 *   information.  This doesn't fill in the object with the saved state
 *   data, but merely creates the object.
 *   
 *   The caller is responsible for having allocated the object ID before
 *   calling this function.  
 */
void CVmMetaTable::create_for_restore(VMG_ uint idx, vm_obj_id_t id)
{
    /* make sure the entry is defined in our table of metaclasses */
    if (idx >= count_)
        err_throw(VMERR_BAD_METACLASS_INDEX);
    
    /* 
     *   Invoke the appropriate constructor.  Note that the caller must
     *   already have allocated the object ID, so we simply use the given ID
     *   without further consideration.  
     */
    table_[idx].meta_->create_for_restore(vmg_ id);
}
Пример #20
0
/*
 *   find a local variable in our frame by name, given a VM string value 
 */
int CVmObjFrameDesc::find_local(VMG_ const vm_val_t *nval,
                               CVmDbgFrameSymPtr *symp)
{
    /* make sure the name is a string */
    const char *name = nval->get_as_string(vmg0_);
    if (name == 0)
        err_throw(VMERR_BAD_TYPE_BIF);

    /* parse the length */
    size_t namelen = vmb_get_len(name);
    name += VMB_LEN;

    /* look up the symbol */
    return find_local(vmg_ name, namelen, symp);
}
Пример #21
0
/* 
 *   assign an indexed value: this sets a variable's value by name 
 */
int CVmObjFrameDesc::set_index_val_q(VMG_ vm_val_t *new_container,
                                    vm_obj_id_t self,
                                    const vm_val_t *index_val,
                                    const vm_val_t *new_val)
{
    /* check the index type */
    if (index_val->get_as_string(vmg0_))
    {
        /* it's a string - look up the value by name */
        if (!set_local_val(vmg_ index_val, new_val))
            err_throw(VMERR_INDEX_OUT_OF_RANGE);
    }
    else
    {
        /* invalid index type */
        err_throw(VMERR_INDEX_OUT_OF_RANGE);
    }

    /* the container doesn't change */
    new_container->set_obj(self);

    /* handled */
    return TRUE;
}
Пример #22
0
/*
 *   Create an object with the given ID and load the object from the image
 *   file. 
 */
void CVmMetaTable::create_from_image(VMG_ uint idx, vm_obj_id_t id,
                                     const char *ptr, size_t siz)
{
    /* make sure the entry is defined */
    if (idx >= count_)
        err_throw(VMERR_BAD_METACLASS_INDEX);

    /* create the object table entry in the memory manager */
    G_obj_table->alloc_obj_with_id(id, TRUE);

    /* invoke the appropriate constructor */
    table_[idx].meta_->create_for_image_load(vmg_ id);

    /* load the object */
    vm_objp(vmg_ id)->load_from_image(vmg_ id, ptr, siz);
}
Пример #23
0
/*
 *   Set the value of a local given the variable descriptor 
 */
void CVmObjFrameRef::set_local_val(VMG_ const CVmDbgFrameSymPtr *sym,
                                   const vm_val_t *new_val)
{
    /* 
     *   if we have an active stack frame, get the value from the frame;
     *   otherwise get the value from our local snapshot 
     */
    vm_frameref_ext *ext = get_ext();
    if (ext->fp != 0)
    {
        /* we have a frame - get the value from the frame */
        G_interpreter->set_local_in_frame(vmg_ new_val, ext->fp, sym);
    }
    else
    {
        /* 
         *   There's no frame, so we must retrieve the value from the
         *   snapshot.  First, get the value of the local or parameter.  Our
         *   snapshot array consists of all of the locals followed by all of
         *   the parameters, so local N is at vars[N] and parameter N is at
         *   vars[nlocals + N].  
         */
        vm_val_t *v = &ext->vars[sym->get_var_num()
                                 + (sym->is_param() ? ext->nlocals : 0)];

        /* 
         *   If it's a context local, index the local by the context index.
         *   Otherwise the value is simply the value in the snapshot array.  
         */
        if (sym->is_ctx_local())
        {
            vm_val_t cont;
            vm_val_t ival;
            ival.set_int(sym->get_ctx_arr_idx());

            if (v->typ == VM_OBJ)
                vm_objp(vmg_ v->val.obj)->set_index_val_ov(
                    vmg_ &cont, v->val.obj, &ival, new_val);
            else
                err_throw(VMERR_CANNOT_INDEX_TYPE);
        }
        else
            *v = *new_val;
    }
}
Пример #24
0
/*
 *   compare two vm_val_t values 
 */
int CVmQSortVal::compare(VMG_ size_t a, size_t b)
{
    int result;
    vm_val_t val_a;
    vm_val_t val_b;

    /* get the two values */
    get_ele(vmg_ a, &val_a);
    get_ele(vmg_ b, &val_b);

    /* check for an explicit comparison function */
    if (compare_fn_.typ != VM_NIL)
    {
        vm_val_t val;

        /* push the values (in reverse order) */
        G_stk->push(&val_b);
        G_stk->push(&val_a);

        /* invoke the callback */
        G_interpreter->call_func_ptr(vmg_ &compare_fn_, 2, &rc, 0);

        /* get the result */
        val = *G_interpreter->get_r0();

        /* if it's not an integer, it's a problem */
        if (val.typ != VM_INT)
            err_throw(VMERR_INT_VAL_REQD);

        /* get the result value */
        result = val.val.intval;
    }
    else
    {
        /* compare the values */
        result = val_a.compare_to(vmg_ &val_b);
    }

    /* if we're sorting in descending order, reverse the result */
    if (descending_)
        result = -result;

    /* return the result */
    return result;
}
Пример #25
0
/* get the storage server URL */
void CVmBifNet::get_storage_url(VMG_ uint oargc)
{
    /* check arguments */
    check_argc(vmg_ oargc, 1);

    /* set a default nil return in case we can't build the path */
    retval_nil(vmg0_);

    /* get the resource name */
    const char *page = G_stk->get(0)->get_as_string(vmg0_);
    if (page == 0)
        err_throw(VMERR_STRING_VAL_REQD);

    /* get the resource name length and buffer pointer */
    size_t pagelen = vmb_get_len(page);
    page += VMB_LEN;

    /* if there's a network configuration, build the resource path */
    const char *host = 0, *rootpath = 0;
    if (G_net_config != 0)
    {
        /* get the storage server host name and root path */
        host = G_net_config->get("storage.domain");
        rootpath = G_net_config->get("storage.rootpath", "/");
    }

    /* we must have a host name to proceed */
    if (host != 0)
    {
        /* build the full string */
        G_interpreter->push_stringf(vmg_ "http://%s%s%.*s",
                                    host, rootpath,
                                    (int)pagelen, page);

        /* pop it into R0 */
        G_stk->pop(G_interpreter->get_r0());
    }

    /* discard arguments */
    G_stk->discard();
}
Пример #26
0
/*
 *   Check the current error count against the maximum error limit, and throw
 *   a fatal error if we've reached the limit.  
 */
void CTcMain::check_error_limit()
{
    /* check the error count against the limit */
    if (error_count_ > max_error_count_)
    {
        /* 
         *   raise the maximum error count a bit so that we don't encounter
         *   another maximum error situation and loop on flagging the
         *   too-many-errors error while trying to display a too-many-errors
         *   error 
         */
        max_error_count_ = error_count_ + 100;

        /* display a message explaining the problem */
        log_error(G_tok->get_last_desc(), G_tok->get_last_linenum(),
                  TC_SEV_FATAL, TCERR_TOO_MANY_ERRORS);

        /* throw the generic fatal error, since we've logged this */
        err_throw(TCERR_FATAL_ERROR);
    }
}
Пример #27
0
/* set a property */
void CVmObjClass::set_prop(VMG_ CVmUndo *undo,
                           vm_obj_id_t self, vm_prop_id_t prop,
                           const vm_val_t *val)
{
    /* try treating the request as a static property of the metaclass */
    vm_meta_entry_t *entry = get_meta_entry(vmg0_);
    if (entry != 0
        && entry->meta_->set_stat_prop(
            vmg_ undo, self, &get_ext()->class_state, prop, val))
        return;

    /* the class doesn't handle it, so check for a modifier object */
    vm_obj_id_t mod_obj = get_mod_obj();
    if (mod_obj != VM_INVALID_OBJ)
    {
        /* we have a modifier - set the property in the modifier */
        vm_objp(vmg_ mod_obj)->set_prop(vmg_ undo, mod_obj, prop, val);
    }
    else
    {
        /* if we don't have a modifier, we can't set the property */
        err_throw(VMERR_INVALID_SETPROP);
    }
}
Пример #28
0
/*
 *   Execute an image file.  If an exception occurs, we'll display a
 *   message on the console, and we'll return the error code; we'll return
 *   zero on success.  If an error occurs, we'll fill in 'errbuf' with a
 *   message describing the problem.  
 */
int vm_run_image(CVmMainClientIfc *clientifc,
                 const char *image_file_name,
                 class CVmHostIfc *hostifc,
                 const char *const *prog_argv, int prog_argc,
                 const char *script_file, int script_quiet,
                 const char *log_file, const char *cmd_log_file,
                 int load_from_exe, int show_banner,
                 const char *charset, const char *log_charset,
                 const char *saved_state, const char *res_dir)
{
    CVmFile *fp = 0;
    CVmImageLoader *volatile loader = 0;
    CVmImageFile *volatile imagefp = 0;
    unsigned long image_file_base = 0;
    int retval;
    vm_globals *vmg__;

    /* presume we will return success */
    retval = 0;

    /* create the file object */
    fp = new CVmFile();

    /* initialize the VM */
    vm_init_options opts(hostifc, clientifc, charset, log_charset);
    vm_initialize(&vmg__, &opts);

    /* tell the client system to initialize */
    clientifc->client_init(VMGLOB_ADDR, script_file, script_quiet,
                           log_file, cmd_log_file,
                           show_banner ? T3VM_BANNER_STRING : 0);

    /* catch any errors that occur during loading and running */
    err_try
    {
        /* remember the name of the byte-code file */
        strncpy(G_os_gamename, image_file_name, sizeof(G_os_gamename));
        G_os_gamename[sizeof(G_os_gamename) - 1] = '\0';

        if (load_from_exe)
        {
            osfildef *exe_fp;

            /* find the image within the executable */
            exe_fp = os_exeseek(image_file_name, "TGAM");
            if (exe_fp == 0)
                err_throw(VMERR_NO_IMAGE_IN_EXE);

            /* 
             *   set up to read from the executable at the location of the
             *   embedded image file that we just found 
             */
            image_file_base = osfpos(exe_fp);
            fp->set_file(exe_fp, image_file_base);
        }
        else
        {
            /* reading from a normal file - open the file */
            fp->open_read(image_file_name, OSFTT3IMG);
        }

        /* create the loader */
        imagefp = new CVmImageFileExt(fp);
        loader = new CVmImageLoader(imagefp, image_file_name,
                                    image_file_base);

        /* load the image */
        loader->load(vmg0_);

        /* if we have a resource root path, tell the host interface */
        if (res_dir != 0)
            hostifc->set_res_dir(res_dir);

        /* let the client prepare for execution */
        clientifc->pre_exec(VMGLOB_ADDR);

        /* run the program from the main entrypoint */
        loader->run(vmg_ prog_argv, prog_argc, 0, saved_state);

        /* tell the client we're done with execution */
        clientifc->post_exec(VMGLOB_ADDR);
    }
    err_catch(exc)
    {
        char errbuf[512];

        /* tell the client execution failed due to an error */
        clientifc->post_exec_err(VMGLOB_ADDR);

        /* note the error code for returning to the caller */
        retval = exc->get_error_code();

        /* get the message for the error */
        CVmRun::get_exc_message(vmg_ exc, errbuf, sizeof(errbuf), TRUE);
        
        /* display the message */
        clientifc->display_error(VMGLOB_ADDR, errbuf, FALSE);
    }
    err_end;

    /* unload the image */
    if (loader != 0)
        loader->unload(vmg0_);

    /* delete the loader and the image file object */
    if (loader != 0)
        delete loader;
    if (imagefp != 0)
        delete imagefp;

    /* notify the client */
    clientifc->client_terminate(VMGLOB_ADDR);

    /* terminate the VM */
    vm_terminate(vmg__, clientifc);

    /* delete the file */
    if (fp != 0)
        delete fp;

    /* return the status code */
    return retval;
}
Пример #29
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);
    }
}
Пример #30
0
void CVmBifT3::set_say(VMG_ uint argc)
{
    vm_val_t *arg = G_stk->get(0);
    vm_val_t val;
    
    /* one argument is required */
    check_argc(vmg_ argc, 1);

    /* check to see if we're setting the default display method */
    if (arg->typ == VM_PROP
        || (arg->typ == VM_INT && arg->val.intval == SETSAY_NO_METHOD))
    {
        vm_prop_id_t prop;
        
        /* 
         *   the return value is the old property pointer (or
         *   SETSAY_NO_METHOD if there was no valid property set previously) 
         */
        prop = G_interpreter->get_say_method();
        if (prop != VM_INVALID_PROP)
            retval_prop(vmg_ prop);
        else
            retval_int(vmg_ SETSAY_NO_METHOD);

        /* get the new value */
        G_stk->pop(&val);

        /* if it's SETSAY_NO_METHOD, set it to the invalid prop ID */
        if (val.typ == VM_INT)
            val.set_propid(VM_INVALID_PROP);

        /* set the method */
        G_interpreter->set_say_method(val.val.prop);
    }
    else if (arg->typ == VM_FUNCPTR
             || arg->typ == VM_OBJ
             || arg->typ == VM_BIFPTR
             || (arg->typ == VM_INT && arg->val.intval == SETSAY_NO_FUNC))
    {
        /* 
         *   the return value is the old function (or SETSAY_NO_FUNC if the
         *   old function was nil) 
         */
        G_interpreter->get_say_func(&val);
        if (val.typ != VM_NIL)
            retval(vmg_ &val);
        else
            retval_int(vmg_ SETSAY_NO_FUNC);

        /* get the new function value */
        G_stk->pop(&val);

        /* if it's SETSAY_NO_FUNC, set the function to nil */
        if (val.typ == VM_INT)
            val.set_nil();

        /* set the new function */
        G_interpreter->set_say_func(vmg_ &val);
    }
    else
    {
        /* invalid type */
        err_throw(VMERR_BAD_TYPE_BIF);
    }
}