예제 #1
0
파일: thread.c 프로젝트: ConstNW/neko
/**
	deque_create : void -> 'deque
	<doc>create a message queue for multithread access</doc>
**/
static value deque_create() {
	vdeque *q = (vdeque*)alloc(sizeof(vdeque));
	value v = alloc_abstract(k_deque,q);
	val_gc(v,free_deque);
	_deque_init(q);
	return v;
}
예제 #2
0
파일: ssl.c 프로젝트: jonasmalacofilho/neko
static value key_from_pem(value data, value pub, value pass){
	mbedtls_pk_context *pk;
	int r, len;
	value v;
	unsigned char *buf;
	val_check(data, string);
	val_check(pub, bool);
	if (!val_is_null(pass)) val_check(pass, string);
	len = val_strlen(data)+1;
	buf = (unsigned char *)alloc(len);
	memcpy(buf, val_string(data), len-1);
	buf[len-1] = '\0';
	pk = (mbedtls_pk_context *)alloc(sizeof(mbedtls_pk_context));
	mbedtls_pk_init(pk);
	if( val_bool(pub) )
		r = mbedtls_pk_parse_public_key( pk, buf, len );
	else if( val_is_null(pass) )
		r = mbedtls_pk_parse_key( pk, buf, len, NULL, 0 );
	else
		r = mbedtls_pk_parse_key( pk, buf, len, (const unsigned char*)val_string(pass), val_strlen(pass) );
	if( r != 0 ){
		mbedtls_pk_free(pk);
		return ssl_error(r);
	}
	v = alloc_abstract(k_pkey,pk);
	val_gc(v,free_pkey);
	return v;
}
예제 #3
0
파일: socket.c 프로젝트: motion-twin/neko
/**
	socket_poll_alloc : int -> 'poll
	<doc>Allocate memory to perform polling on a given number of sockets</doc>
**/
static value socket_poll_alloc( value nsocks ) {
	polldata *p;
	int i;
	val_check(nsocks,int);
	p = (polldata*)alloc(sizeof(polldata));
	p->max = val_int(nsocks);
	if( p->max < 0 || p->max > 1000000 )
		neko_error();
#	ifdef NEKO_WINDOWS
	{
		p->fdr = (fd_set*)alloc_private(FDSIZE(p->max));
		p->fdw = (fd_set*)alloc_private(FDSIZE(p->max));
		p->outr = (fd_set*)alloc_private(FDSIZE(p->max));
		p->outw = (fd_set*)alloc_private(FDSIZE(p->max));
		p->fdr->fd_count = 0;
		p->fdw->fd_count = 0;
	}
#	else
	p->fds = (struct pollfd*)alloc_private(sizeof(struct pollfd) * p->max);
	p->rcount = 0;
	p->wcount = 0;
#	endif
	p->ridx = alloc_array(p->max+1);
	p->widx = alloc_array(p->max+1);
	for(i=0;i<=p->max;i++) {
		val_array_ptr(p->ridx)[i] = alloc_int(-1);
		val_array_ptr(p->widx)[i] = alloc_int(-1);
	}
	return alloc_abstract(k_poll, p);
}
예제 #4
0
파일: Context.cpp 프로젝트: boorik/hxzmq
value hx_zmq_construct (value io_threads)
{
	if (!val_is_int(io_threads))
		return alloc_null();
		
	int _io_threads = val_int(io_threads);
	if (_io_threads <= 0) {
		val_throw(alloc_int(EINVAL));
		return alloc_null();
	}
	
	void *c = zmq_init (_io_threads);
	int err = zmq_errno();
	
	if (c == NULL) {
		val_throw (alloc_int(err));
		return alloc_null();
	}
	
	// See: http://nekovm.org/doc/ffi#abstracts_and_kinds
	value v =  alloc_abstract(k_zmq_context_handle,c);
	val_gc(v,finalize_context);		// finalize_context is called when the abstract value is garbage collected
	return v;
	
}
예제 #5
0
파일: module.c 프로젝트: exaphaser/neko_mod
/**
	module_read_path : string list -> name:string -> loader:object -> 'module
	<doc>
	Read a module using the specified search path.
	</doc>
**/
static value module_read_path( value path, value name, value loader ) {
	FILE *f;
	value fname;
	char *mname, *ext;
	neko_module *m;
	val_check(name,string);
	val_check(loader,object);
	mname = val_string(name);
	ext = strrchr(mname,'.');
	if( ext && ext[1] == 'n' && ext[2] == 0 )
		fname = neko_select_file(path,mname,"");
	else
		fname = neko_select_file(path,mname,".n");
	f = fopen(val_string(fname),"rb");
	if( f == NULL ) {
		buffer b = alloc_buffer("Module not found : ");
		buffer_append(b,mname);
		bfailure(b);
	}
	m = neko_read_module(neko_file_reader,f,loader);
	fclose(f);
	if( m == NULL ) {
		buffer b = alloc_buffer("Invalid module : ");
		val_buffer(b,name);
		bfailure(b);
	}
	m->name = alloc_string(val_string(name));
	return alloc_abstract(neko_kind_module,m);
}
예제 #6
0
	value lime_cffi_set_finalizer (value callback) {
		
		value abstract = alloc_abstract (k_finalizer, callback);
		val_gc (abstract, lime_cffi_finalizer);
		return abstract;
		
	}
예제 #7
0
파일: mysql.c 프로젝트: bsmr-haxe/neko
/**
	connect : { host => string, port => int, user => string, pass => string, socket => string? } -> 'connection
	<doc>Connect to a database using the connection informations</doc>
**/
static value connect_mysql( value params  ) {
	value host, port, user, pass, socket;
	val_check(params,object);
	host = val_field(params,val_id("host"));
	port = val_field(params,val_id("port"));
	user = val_field(params,val_id("user"));
	pass = val_field(params,val_id("pass"));
	socket = val_field(params,val_id("socket"));
	val_check(host,string);
	val_check(port,int);
	val_check(user,string);
	val_check(pass,string);
	if( !val_is_string(socket) && !val_is_null(socket) )
		neko_error();
	{
		connection *c = (connection*)alloc(sizeof(connection));		
		value v;
		c->m = mysql_init(NULL);
		c->conv_string = NULL;
		c->conv_date = NULL;
		c->conv_bytes = NULL;
		if( mysql_real_connect(c->m,val_string(host),val_string(user),val_string(pass),NULL,val_int(port),val_is_null(socket)?NULL:val_string(socket),0) == NULL ) {
			buffer b = alloc_buffer("Failed to connect to mysql server : ");
			buffer_append(b,mysql_error(c->m));
			mysql_close(c->m);
			bfailure(b);
		}
		v = alloc_abstract(k_connection,c);
		val_gc(v,free_connection);
		return v;
	}
}
예제 #8
0
static value socket_poll_alloc( value nsocks ) {
	polldata *p;
	int i;
	val_check(nsocks,int);
	p = (polldata*)malloc(sizeof(polldata));
	p->max = val_int(nsocks);
	if( p->max < 0 || p->max > 1000000 )
		return alloc_null();
#	ifdef NEKO_WINDOWS
	{
		p->fdr = (fd_set*)malloc(FDSIZE(p->max));
		p->fdw = (fd_set*)malloc(FDSIZE(p->max));
		p->outr = (fd_set*)malloc(FDSIZE(p->max));
		p->outw = (fd_set*)malloc(FDSIZE(p->max));
		p->fdr->fd_count = 0;
		p->fdw->fd_count = 0;
	}
#	else
	p->fds = (struct pollfd*)malloc(sizeof(struct pollfd) * p->max);
	p->rcount = 0;
	p->wcount = 0;
#	endif
	p->ridx = alloc_array(p->max+1);
	p->widx = alloc_array(p->max+1);
        val_gc_add_root(&p->ridx);
        val_gc_add_root(&p->widx);
	for(i=0;i<=p->max;i++) {
		val_array_set_i(p->ridx,i, alloc_int(-1));
		val_array_set_i(p->widx,i, alloc_int(-1));
	}
	value v = alloc_abstract(k_poll, p);
        val_gc(v,free_sock);
        return v;
}
예제 #9
0
/**
	Connect out from a server socket.
	Returns an ENetPeer *, which has not yet connected, or throws if connection fails.
**/
static value udpr_connect_out(value h, value ip, value port, value channels, value timeout) {
    ENetAddress address;
    ENetEvent event;
    ENetHost *host;
    ENetPeer *peer;
    int to;

	val_check_kind(h,k_udprhost);

	// checked in address population
	//val_check(ip,int);
	//val_check(port,int);
	val_check(channels,int);
	val_check(timeout,int);
	to = val_int(timeout);
	if(to < 0)
		to = 5000;

	host = (ENetHost *)val_data(h);
	if(populate_address(&address, ip, port) != val_true)
		val_throw(alloc_string("address"));
		//neko_error();

    // Initiate the connection with channels 0..channels-1
    peer = enet_host_connect (host, &address, (size_t)val_int(channels));
    if (peer == NULL)
    	//val_throw( alloc_string("Host not found") );
    	neko_error();

 	value v = alloc_abstract(k_udprpeer,peer);
	return v;
}
예제 #10
0
/**
 * Create a temporary file which will be destroyed automatically when it is closed
 * @return value file handle
 **/
static value fileext_tmpfile_open() {
	fio* f = new fio();
	if( !f->open_tmpfile() )
		fileext_error("Unable to create temporary file", f, true);

	value v = alloc_abstract(k_file_ext,f);
	val_gc(v, fileext_free_file);
	return v;
}
예제 #11
0
static value udpr_get_peer_pointer(value h, value idx) {
	val_check_kind(h,k_udprhost);
	val_check(idx,int);
	ENetPeerHandle hndPeer = (ENetPeerHandle)val_int(idx);
	ENetPeer *peer = enet_host_handle_to_peer((ENetHost *)val_data(h), (ENetPeerHandle)val_int(idx));
	if(peer == NULL)
		neko_error();
	value v = alloc_abstract(k_udprpeer,peer);
	return v;
}
예제 #12
0
파일: ssl.c 프로젝트: jonasmalacofilho/neko
static value ssl_get_peer_certificate( value ssl ){
	value v;
	const mbedtls_x509_crt *crt;
	val_check_kind(ssl,k_ssl);
	crt = mbedtls_ssl_get_peer_cert(val_ssl(ssl));
	if( crt == NULL )
		return val_null;
 	v = alloc_abstract( k_cert, (void *)crt );
	return v;
}
예제 #13
0
파일: sqlite.c 프로젝트: exaphaser/neko_mod
/**
	request : 'db -> sql:string -> 'result
	<doc>Executes the SQL request and returns its result</doc>
**/
static value request( value v, value sql ) {
	database *db;
	result *r;
	const char *tl;
	int i,j;
	val_check_kind(v,k_db);
	val_check(sql,string);
	db = val_db(v);
	r = (result*)alloc(sizeof(result));
	r->db = db;
	if( sqlite3_prepare(db->db,val_string(sql),val_strlen(sql),&r->r,&tl) != SQLITE_OK ) {
		buffer b = alloc_buffer("Sqlite error in ");
		val_buffer(b,sql);
		buffer_append(b," : ");
		buffer_append(b,sqlite3_errmsg(db->db));
		val_throw(buffer_to_string(b));
	}
	if( *tl ) {
		sqlite3_finalize(r->r);
		val_throw(alloc_string("Cannot execute several SQL requests at the same time"));
	}
	r->ncols = sqlite3_column_count(r->r);
	r->names = (field*)alloc_private(sizeof(field)*r->ncols);
	r->bools = (int*)alloc_private(sizeof(int)*r->ncols);
	r->first = 1;
	r->done = 0;
	for(i=0;i<r->ncols;i++) {
		field id = val_id(sqlite3_column_name(r->r,i));
		const char *dtype = sqlite3_column_decltype(r->r,i);
		for(j=0;j<i;j++)
			if( r->names[j] == id ) {
				if( strcmp(sqlite3_column_name(r->r,i),sqlite3_column_name(r->r,j)) == 0 ) {
					buffer b = alloc_buffer("Error, same field is two times in the request ");
					val_buffer(b,sql);
					sqlite3_finalize(r->r);
					val_throw(buffer_to_string(b));
				} else {
					buffer b = alloc_buffer("Error, same field ids for : ");
					buffer_append(b,sqlite3_column_name(r->r,i));
					buffer_append(b," and ");
					buffer_append(b,sqlite3_column_name(r->r,j));
					buffer_append_char(b,'.');
					sqlite3_finalize(r->r);
					val_throw(buffer_to_string(b));
				}
			}
		r->names[i] = id;
		r->bools[i] = dtype?(strcmp(dtype,"BOOL") == 0):0;
	}
	// changes in an update/delete
	if( db->last != NULL )
		finalize_result(val_result(db->last),0);
	db->last = alloc_abstract(k_result,r);
	return db->last;
}
예제 #14
0
파일: api.c 프로젝트: 0b1kn00b/xcross
static value os_winlog_new( value title, value f ) {
	window *w;	
	val_check(title,string);
	val_check_function(f,0);
	w = (window*)alloc(sizeof(window));
	w->click = f;
	w->p = sys_winlog_new(val_string(title),wnd_callback,w);
	if( w->p == NULL )		
		neko_error();	
	return alloc_abstract(k_winlog,w);
}
예제 #15
0
value hxfcgi_create_request() {
	try {
		hxfcgi::Request *req = new hxfcgi::Request();
		value ret = alloc_abstract(hxRequest,req);
		return ret;
	}
	catch (string error) {
		hx_failure(error.c_str());
	}
	return val_null;	
}
예제 #16
0
/*
@description	Returns a new pixel wand.
*/
value nMagick_pixel_new()
{
	value v;
	PixelWand  *pix;

	pix = NewPixelWand();

	v = alloc_abstract( k_pixel, pix );
	val_gc( v, nMagick_pixel_close );
	return v;
}
예제 #17
0
/**
	regexp_new_options : reg:string -> options:string -> 'regexp
	<doc>Build a new regexpr with the following options :
	<ul>
		<li>i : case insensitive matching</li>
		<li>s : . match anything including newlines</li>
		<li>m : treat the input as a multiline string</li>
		<li>u : run in utf8 mode</li>
		<li>g : turn off greedy behavior</li>
	</ul>
	</doc>
**/
static value regexp_new_options( value s, value opt ) {
	val_check(s,string);
	val_check(opt,string);
	{
		value v;
		const char *error;
		int err_offset;
		pcre *p;
		pcredata *pdata;
		const char *o = val_string(opt);
		int options = 0;
		while( *o ) {
			switch( *o++ ) {
			case 'i':
				options |= PCRE_CASELESS;
				break;
			case 's':
				options |= PCRE_DOTALL;
				break;
			case 'm':
				options |= PCRE_MULTILINE;
				break;
			case 'u':
				options |= PCRE_UTF8;
				break;
			case 'g':
				options |= PCRE_UNGREEDY;
				break;
			default:
				return alloc_null();
				break;
			}
		}
		p = pcre_compile(val_string(s),options,&error,&err_offset,NULL);
		if( p == NULL ) {
			buffer b = alloc_buffer("Regexp compilation error : ");
			buffer_append(b,error);
			buffer_append(b," in ");
			val_buffer(b,s);
			bfailure(b);
		}
		v = alloc_abstract(k_regexp,malloc(sizeof(pcredata)));
		pdata = PCRE(v);
		pdata->r = p;
		pdata->str = alloc_null();
                val_gc_add_root(&pdata->str);
		pdata->nmatchs = 0;
		pcre_fullinfo(p,NULL,PCRE_INFO_CAPTURECOUNT,&pdata->nmatchs);
		pdata->nmatchs++;
		pdata->matchs = (int*)malloc(sizeof(int) * 3 * pdata->nmatchs);
		val_gc(v,free_regexp);
		return v;
	}	
}
예제 #18
0
파일: ssl.c 프로젝트: jonasmalacofilho/neko
static value cert_get_next( value cert ){
	mbedtls_x509_crt *crt;
	value v;
	val_check_kind(cert,k_cert);
	crt = (mbedtls_x509_crt *)val_cert(cert);
	crt = crt->next;
	if( crt == NULL )
		return val_null;
	v = alloc_abstract(k_cert, crt);
	return v;
}
예제 #19
0
/*
@description	Returns a new pixel wand.
*/
value nMagick_draw_new()
{
	value v;
	DrawingWand *draw;

	draw = NewDrawingWand();

	v = alloc_abstract( k_draw, draw );
	val_gc( v, nMagick_draw_close );
	return v;
}
예제 #20
0
/**
	file_open : f:string -> r:string -> 'file
	<doc>
	Call the C function [fopen] with the file path and access rights. 
	Return the opened file or throw an exception if the file couldn't be open.
	</doc>
**/
static value file_open( value name, value r ) {
	fio *f;
	val_check(name,string);
	val_check(r,string);
	f = (fio*)alloc(sizeof(fio));
	f->name = alloc_string(val_string(name));
	f->io = fopen(val_string(name),val_string(r));
	if( f->io == NULL )
		file_error("file_open",f);
	return alloc_abstract(k_file,f);
}
예제 #21
0
static value socket_accept( value o ) {
	SOCKET sock = val_sock(o);
	struct sockaddr_in addr;
	SockLen addrlen = sizeof(addr);
	SOCKET s;
	gc_enter_blocking();
	s = accept(sock,(struct sockaddr*)&addr,&addrlen);
	if( s == INVALID_SOCKET )
		return block_error();
	gc_exit_blocking();
	return alloc_abstract(k_socket,(void *)(socket_int)s);
}
예제 #22
0
/**
 * Open a file
 * @param name File name including path
 * @param mode File mode (r, rw, w etc)
 * @return value file handle
 **/
static value fileext_open(value name, value mode) {
	val_check(name, string);
	val_check(mode, string);
	fio* f = new fio();

	if(!f->open(name, mode))
		fileext_error("Unable to open file", f, true);

	value v = alloc_abstract(k_file_ext,f);
	val_gc(v, fileext_free_file);
	return v;
}
예제 #23
0
파일: ssl.c 프로젝트: jonasmalacofilho/neko
static value ssl_new( value config ) {
	int ret;
	mbedtls_ssl_context *ssl;
	val_check_kind(config,k_ssl_conf);
	ssl = (mbedtls_ssl_context *)alloc(sizeof(mbedtls_ssl_context));
	mbedtls_ssl_init(ssl);
	if( (ret = mbedtls_ssl_setup(ssl, val_conf(config))) != 0 ){
		mbedtls_ssl_free(ssl);
		return ssl_error(ret);
	}
	return alloc_abstract( k_ssl, ssl );
}
예제 #24
0
파일: thread.c 프로젝트: ConstNW/neko
/**
	tls_create : void -> 'tls
	<doc>
	Creates thread local storage. This is placeholder that can store a value that will
	be different depending on the local thread. You must set the tls value to [null]
	before exiting the thread or the memory will never be collected.
	</doc>
**/
static value tls_create() {
	value v;
	vtls *t = (vtls*)malloc(sizeof(vtls));
#	ifdef NEKO_WINDOWS
	t->tls = TlsAlloc();
	TlsSetValue(t->tls,NULL);
#	else
	pthread_key_create(&t->key,NULL);
#	endif
	v = alloc_abstract(k_tls,t);
	val_gc(v,free_tls);
	return v;
}
예제 #25
0
/*
@description	Returns an identical copy of the DrawingWand.
*/
value nMagick_draw_clone( value draw )
{
	value v;
	DrawingWand *drw;

	val_check_kind( draw, k_draw );

	drw = DRAW( draw );

	v = alloc_abstract( k_draw, CloneDrawingWand( drw ) );
	val_gc( v, nMagick_draw_close );
	return v;
}
예제 #26
0
파일: socket.c 프로젝트: motion-twin/neko
/**
	socket_accept : 'socket -> 'socket
	<doc>Accept an incoming connection request</doc>
**/
static value socket_accept( value o ) {
	struct sockaddr_in addr;
	unsigned int addrlen = sizeof(addr);
	SOCKET s;
	val_check_kind(o,k_socket);
	POSIX_LABEL(accept_again);
	s = accept(val_sock(o),(struct sockaddr*)&addr,&addrlen);
	if( s == INVALID_SOCKET ) {
		HANDLE_EINTR(accept_again);
		return block_error();
	}
	return alloc_abstract(k_socket,(value)(int_val)s);
}
예제 #27
0
파일: module.c 프로젝트: exaphaser/neko_mod
/**
	module_read_string : string -> loader:object -> 'module
	<doc>
	Read a module using the specified string datas.
	</doc>
**/
static value module_read_string( value str, value loader ) {
	neko_module *m;
	string_pos p;
	val_check(str,string);
	val_check(loader,object);
	p.p = val_string(str);
	p.len = val_strlen(str);
	m = neko_read_module(neko_string_reader,&p,loader);
	if( m == NULL )
		neko_error();
	m->name = alloc_string("");
	return alloc_abstract(neko_kind_module,m);
}
예제 #28
0
/**
	Returns the ENetPeer that generated an event, with the Event
	allocated pointer in Peer->data. The returned ENetPeer must not
	be destroyed, since it's a copy of an existing peer pointer.
	Timeout is float number of seconds (0.001 == 1 ms)
**/
static value udpr_poll(value h, value timeout)
{
	//ENetPeerHandle hndPeer = enet_host_peer_to_handle(host, event->peer);
    ENetEvent *event;
    int res;

	if( !val_is_abstract(h) || !val_is_kind(h,k_udprhost) )
		neko_error();

	val_check(timeout,number);
	enet_uint32 tout = (enet_uint32)(val_number(timeout)*1000);

	event = (ENetEvent *) enet_malloc (sizeof (ENetEvent));

    // Wait up to timeout milliseconds for an event.

    res = enet_host_service ((ENetHost *)val_data(h), event, tout);
    if(res <= 0) {
    	if(res == 0)
    		return val_null;
    	neko_error();
    }

	switch (event->type)
	{
	case ENET_EVENT_TYPE_NONE:
		//if(event->peer != NULL)
			//free_peer_event(event->peer);
		enet_free(event);
		return val_null;
		break;
	default:
		// auto frees any existing unhandled event, add this event.
#ifdef ENET_DEBUG_FULL
		if(event->type == ENET_EVENT_TYPE_RECEIVE)
			fprintf(stderr, "udpr_poll: event type %s %0.*s\n", event_to_string(event->type), event->packet->dataLength, event->packet->data);
		else
			fprintf(stderr, "udpr_poll: event type %s\n", event_to_string(event->type));
#endif
		break;
	}

	value v = alloc_abstract(k_udprevent,event);
	val_gc(v, destroy_enetevent);
	return v;
#ifdef ENET_DEBUG
	//fprintf(stderr, "udpr_poll: returning peer %x\n", event->peer);
#endif
	//value v = alloc_abstract(k_udprpeer, event->peer);
	//return v;
}
예제 #29
0
/**
	Returns an ENetPeer *, or throw if connection fails.
**/
static value udpr_connect(value h, value ip, value port, value channels, value timeout) {
    ENetAddress address;
    ENetEvent event;
    ENetHost *host;
    ENetPeer *peer;
    int to;

	if( !val_is_abstract(h) || !val_is_kind(h,k_udprhost) )
		neko_error();

	// checked in address population
	//val_check(ip,int);
	//val_check(port,int);
	val_check(channels,int);
	val_check(timeout,int);
	to = val_int(timeout);
	if(to < 0)
		to = 5000;

	host = (ENetHost *)val_data(h);
	if(populate_address(&address, ip, port) != val_true)
		neko_error();

    // Initiate the connection with channels 0..channels-1
    peer = enet_host_connect (host, &address, (size_t)val_int(channels));
    if (peer == NULL)
    	neko_error();

#ifdef ENET_DEBUG
		fprintf(stderr, "udpr_connect: waiting %d\n", to);
#endif
    /* Wait up to 5 seconds for the connection attempt to succeed. */
    if (enet_host_service (host, & event, to) > 0 &&
        event.type == ENET_EVENT_TYPE_CONNECT)
    {
    	// success
#ifdef ENET_DEBUG
		fprintf(stderr, "udpr_connect: returning peer %x\n", peer);
#endif
		value v = alloc_abstract(k_udprpeer,peer);
		//val_gc(v, destroy_enetpeer);
		return v;
    }

	// timeout has occurred or disconnect received.
#ifdef ENET_DEBUG
	fprintf(stderr, "udpr_connect: *** enet_peer_reset\n");
#endif
    enet_peer_reset (peer);
    neko_error();
}
예제 #30
0
파일: ssl.c 프로젝트: jonasmalacofilho/neko
static value cert_load_path(value path){
	int r;
	mbedtls_x509_crt *x;
	value v;
	val_check(path,string);
	x = (mbedtls_x509_crt *)alloc(sizeof(mbedtls_x509_crt));
	mbedtls_x509_crt_init( x );
	if( (r = mbedtls_x509_crt_parse_path(x, val_string(path))) != 0 ){
		return ssl_error(r);
	}
	v = alloc_abstract(k_cert, x);
	val_gc(v,free_cert);
	return v;
}