/* * 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; }
/* * create */ vm_obj_id_t CVmObjFrameDesc::create( VMG_ vm_obj_id_t fref, int frame_idx, uint ret_ofs) { /* allocate an object ID */ vm_obj_id_t id = vm_new_id(vmg_ FALSE, TRUE, FALSE); /* instantiate the new object */ new (vmg_ id) CVmObjFrameDesc(vmg_ fref, frame_idx, ret_ofs); /* return the new object's ID */ return id; }
/* * create */ vm_obj_id_t CVmObjFrameRef::create( VMG_ vm_val_t *fp, const uchar *entry) { /* allocate an object ID */ vm_obj_id_t id = vm_new_id(vmg_ FALSE, TRUE, FALSE); /* instantiate the new object */ new (vmg_ id) CVmObjFrameRef(vmg_ fp, entry); /* return the new object's ID */ return id; }
/* * create with a given dependency index */ vm_obj_id_t CVmObjClass::create_dyn(VMG_ uint meta_idx) { vm_obj_id_t id = vm_new_id(vmg_ FALSE, TRUE, FALSE); new (vmg_ id) CVmObjClass(vmg_ FALSE, meta_idx, id); return id; }
/* * create with no initial contents */ vm_obj_id_t CVmObjClass::create(VMG_ int in_root_set) { vm_obj_id_t id = vm_new_id(vmg_ in_root_set, TRUE, FALSE); new (vmg_ id) CVmObjClass(); return id; }
/* * create dynamically using stack arguments */ vm_obj_id_t CVmObjHTTPServer::create_from_stack( VMG_ const uchar **pc_ptr, uint argc) { vm_obj_id_t id; const char *errmsg; /* * parse arguments - new HTTPServer(addr?, port?) */ if (argc > 3) err_throw(VMERR_WRONG_NUM_OF_ARGS); /* check for the address - use "localhost" by default */ char addr[256] = "localhost"; if (argc >= 1) { /* get the address - this must be a string or nil */ if (G_stk->get(0)->typ == VM_NIL) G_stk->discard(); else CVmBif::pop_str_val_buf(vmg_ addr, sizeof(addr)); } /* check for a port - use 0 by default */ int port = 0; if (argc >= 2) { /* get the port number - this must be an integer or nil */ if (G_stk->get(0)->typ == VM_NIL) G_stk->discard(); else port = CVmBif::pop_int_val(vmg0_); } /* check for an upload size limit */ int32_t ulim; if (argc >= 3) { if (G_stk->get(0)->typ == VM_NIL) G_stk->discard(); else ulim = CVmBif::pop_long_val(vmg0_); } /* get the network safety level, to determine if this is allowed */ int client_level, server_level; G_host_ifc->get_net_safety(&client_level, &server_level); /* check the network server safety level */ switch (server_level) { case VM_NET_SAFETY_MINIMUM: /* all access allowed - proceed */ break; case VM_NET_SAFETY_LOCALHOST: /* * localhost only - if the host isn't 'localhost' or '127.0.0.1', * don't allow it */ if (stricmp(addr, "localhost") != 0 && stricmp(addr, "127.0.0.1") != 0) goto access_error; /* allow it */ break; case VM_NET_SAFETY_MAXIMUM: access_error: /* no access allowed */ errmsg = "prohibited network access"; G_interpreter->push_string(vmg_ errmsg); G_interpreter->throw_new_class(vmg_ G_predef->net_safety_exception, 1, errmsg); AFTER_ERR_THROW(break;) } /* * allocate the object ID - this type of construction never creates a * root object */ id = vm_new_id(vmg_ FALSE, FALSE, FALSE); /* http servers are inherently transient */ G_obj_table->set_obj_transient(id); /* create the object */ CVmObjHTTPServer *l = new (vmg_ id) CVmObjHTTPServer(vmg_ TRUE); /* get the extension */ vm_httpsrv_ext *ext = l->get_ext(); /* create the listener thread object */ TadsHttpListenerThread *ht = new TadsHttpListenerThread( id, G_net_queue, ulim); /* launch the listener */ ext->l = TadsListener::launch(addr, (ushort)port, ht); /* we're done with the thread object (the listener took it over) */ ht->release_ref(); /* if the launch failed, throw an error */ if (ext->l == 0) { /* throw a network error */ const char *errmsg = "Unable to start HTTP server"; G_interpreter->push_string(vmg_ errmsg); G_interpreter->throw_new_class(vmg_ G_predef->net_exception, 1, errmsg); } /* remember my requested binding address */ ext->addr = lib_copy_str(addr); /* return the new ID */ return id; }