Example #1
0
/**
	socket_select : read : 'socket array -> write : 'socket array -> others : 'socket array -> timeout:number? -> 'socket array array
	<doc>Perform the [select] operation. Timeout is in seconds or [null] if infinite</doc>
**/
static value socket_select( value rs, value ws, value es, value timeout ) {
	struct timeval tval;
	struct timeval *tt;
	SOCKET n = 0;
	fd_set rx, wx, ex;
	fd_set *ra, *wa, *ea;
	value r;
	POSIX_LABEL(select_again);
	ra = make_socket_array(rs,val_array_size(rs),&rx,&n);
	wa = make_socket_array(ws,val_array_size(ws),&wx,&n);
	ea = make_socket_array(es,val_array_size(es),&ex,&n);
	if( ra == &INVALID || wa == &INVALID || ea == &INVALID )
		neko_error();
	if( val_is_null(timeout) )
		tt = NULL;
	else {
		val_check(timeout,number);
		tt = &tval;
		init_timeval(val_number(timeout),tt);
	}
	if( select((int)(n+1),ra,wa,ea,tt) == SOCKET_ERROR ) {
		HANDLE_EINTR(select_again);
		neko_error();
	}
	r = alloc_array(3);
	val_array_ptr(r)[0] = make_array_result(rs,ra);
	val_array_ptr(r)[1] = make_array_result(ws,wa);
	val_array_ptr(r)[2] = make_array_result(es,ea);
	return r;
}
Example #2
0
File: main.c Project: robinp/neko
static void report( neko_vm *vm, value exc, int isexc ) {
	int i;
	buffer b = alloc_buffer(NULL);
	value st = neko_exc_stack(vm);
	for(i=0;i<val_array_size(st);i++) {
		value s = val_array_ptr(st)[i];
		buffer_append(b,"Called from ");
		if( val_is_null(s) )
			buffer_append(b,"a C function");
		else if( val_is_string(s) ) {
			buffer_append(b,val_string(s));
			buffer_append(b," (no debug available)");
		} else if( val_is_array(s) && val_array_size(s) == 2 && val_is_string(val_array_ptr(s)[0]) && val_is_int(val_array_ptr(s)[1]) ) {
			val_buffer(b,val_array_ptr(s)[0]);
			buffer_append(b," line ");
			val_buffer(b,val_array_ptr(s)[1]);
		} else
			val_buffer(b,s);
		buffer_append_char(b,'\n');
	}
	if( isexc )
		buffer_append(b,"Uncaught exception - ");
	val_buffer(b,exc);
#	ifdef NEKO_STANDALONE
	neko_standalone_error(val_string(buffer_to_string(b)));
#	else
	fprintf(stderr,"%s\n",val_string(buffer_to_string(b)));
#	endif
}
Example #3
0
/**
	socket_epoll_register : 'epoll -> 'socket -> int
	<doc>Register a socket with an epoll instance to be notified of events. Returns the socket's fd.</doc>
**/
static value socket_epoll_register(value e, value s, value events) {
	SOCKET sock;
	int event_types;
	epolldata *ep;
	val_check_kind(e,k_epoll);
	val_check_kind(s,k_socket);
	val_check(events,int);
	sock = val_sock(s);
	event_types = val_int(events);
	ep = val_epoll(e);
#ifndef HAS_EPOLL
	if (sock >= FD_SETSIZE)
		val_throw(alloc_string("Can't register file descriptor >= FD_SETSIZE"));
	if (event_types & EPOLLIN) {
		if (ep->rcount >= FD_SETSIZE)
			val_throw(alloc_string("Too many sockets (on non-Linux platforms, 'epoll' uses select)"));
		val_array_ptr(ep->read)[ep->rcount++] = s;
	}
	if (event_types & EPOLLOUT) {
		if (ep->wcount >= FD_SETSIZE)
			val_throw(alloc_string("Too many sockets (on non-Linux platforms, 'epoll' uses select)"));
		val_array_ptr(ep->write)[ep->wcount++] = s;
	}
#else
	struct epoll_event ev;
	ev.events = event_types;
	ev.data.fd = sock;
	int ret = epoll_ctl(ep->epollfd, EPOLL_CTL_ADD, sock, &ev);
	if (ret == -1)
		val_throw(alloc_int(errno));
#endif
	return alloc_int(sock);
}
Example #4
0
static void parse_get( value *p, const char *args ) {
	char *aand, *aeq, *asep;
	value tmp;
	while( true ) {
		aand = strchr(args,'&');
		if( aand == NULL ) {
			asep = strchr(args,';');
			aand = asep;
		} else {
			asep = strchr(args,';');
			if( asep != NULL && asep < aand )
				aand = asep;
		}
		if( aand != NULL )
			*aand = 0;
		aeq = strchr(args,'=');
		if( aeq != NULL ) {
			*aeq = 0;
			tmp = alloc_array(3);
			val_array_ptr(tmp)[0] = url_decode(args,(int)(aeq-args));
			val_array_ptr(tmp)[1] = url_decode(aeq+1,(int)strlen(aeq+1));
			val_array_ptr(tmp)[2] = *p;
			*p = tmp;
			*aeq = '=';
		}
		if( aand == NULL )
			break;
		*aand = (aand == asep)?';':'&';
		args = aand+1;
	}
}
Example #5
0
static value loader_loadprim( value prim, value nargs ) {
	value o = val_this();
	value libs;
	val_check(o,object);
	val_check(prim,string);
	val_check(nargs,int);
	libs = val_field(o,id_loader_libs);
	val_check_kind(libs,k_loader_libs);
	if( val_int(nargs) >= 10 || val_int(nargs) < -1 )
		neko_error();
	{
		neko_vm *vm = NEKO_VM();
		void *ptr = load_primitive(val_string(prim),val_int(nargs),val_field(o,id_path),(liblist**)(void*)&val_data(libs));
		vfunction *f;
		if( ptr == NULL ) {
			buffer b = alloc_buffer("Primitive not found : ");
			val_buffer(b,prim);
			buffer_append(b,"(");
			val_buffer(b,nargs);
			buffer_append(b,")");
			bfailure(b);
		}
		f = (vfunction*)alloc_function(ptr,val_int(nargs),val_string(copy_string(val_string(prim),val_strlen(prim))));
		if( vm->pstats && val_int(nargs) <= 6 ) {
			value env = alloc_array(2);
			val_array_ptr(env)[0] = f->module;
			val_array_ptr(env)[1] = (value)(((int_val)f->addr) | 1);
			f->addr = stats_proxy;
			f->env = env;
		}
		return (value)f;
	}
}
Example #6
0
/**
	$apply : function -> any* -> any
	<doc>
	Apply the function to several arguments.
	Return a function asking for more arguments or the function result if more args needed.
	</doc>
**/
static value builtin_apply( value *args, int nargs ) {
	value f, env;
	int fargs;
	int i;
	nargs--;
	args++;
	if( nargs < 0 )
		neko_error();
	f = args[-1];
	if( !val_is_function(f) )
		neko_error();
	if( nargs == 0 )
		return f;
	fargs = val_fun_nargs(f);
	if( fargs == nargs || fargs == VAR_ARGS )
		return val_callN(f,args,nargs);
	if( nargs > fargs )
		neko_error();
	env = alloc_array(fargs + 1);
	val_array_ptr(env)[0] = f;
	for(i=0;i<nargs;i++)
		val_array_ptr(env)[i+1] = args[i];
	while( i++ < fargs )
		val_array_ptr(env)[i] = val_null;
	return neko_alloc_apply(fargs-nargs,env);
}
Example #7
0
EXTERN value neko_select_file( value path, const char *file, const char *ext ) {
	struct stat s;
	value ff;
	buffer b = alloc_buffer(file);
	buffer_append(b,ext);
	ff = buffer_to_string(b);
	if( stat(val_string(ff),&s) == 0 ) {
		char *p = strchr(file,'/');
		if( p == NULL )
			p = strchr(file,'\\');
		if( p != NULL )
			return ff;
		b = alloc_buffer("./");
		buffer_append(b,file);
		buffer_append(b,ext);
		return buffer_to_string(b);
	}
	while( val_is_array(path) && val_array_size(path) == 2 ) {
		value p = val_array_ptr(path)[0];
		buffer b = alloc_buffer(NULL);
		path = val_array_ptr(path)[1];
		val_buffer(b,p);
		val_buffer(b,ff);
		p = buffer_to_string(b);
		if( stat(val_string(p),&s) == 0 )
			return p;
	}
	return ff;
}
Example #8
0
/**
	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);
}
Example #9
0
/**
	sys_env : void -> #list
	<doc>Return all the (key,value) pairs in the environment as a chained list</doc>
**/
static value sys_env() {
	value h = val_null;
	value cur = NULL, tmp, key;
	char **e = environ;
	while( *e ) {
		char *x = strchr(*e,'=');
		if( x == NULL ) {
			e++;
			continue;
		}
		tmp = alloc_array(3);
		key = alloc_empty_string((int)(x - *e));
		memcpy(val_string(key),*e,(int)(x - *e));
		val_array_ptr(tmp)[0] = key;
		val_array_ptr(tmp)[1] = alloc_string(x+1);
		val_array_ptr(tmp)[2] = val_null;
		if( cur )
			val_array_ptr(cur)[2] = tmp;
		else
			h = tmp;
		cur = tmp;
		e++;
	}
	return h;
}
Example #10
0
static value init_path( const char *path ) {
	value l = val_null, tmp;
	char *p, *p2;
	char *allocated = NULL;
#ifdef NEKO_WINDOWS
	char exe_path[MAX_PATH];
	if( path == NULL ) {
#		ifdef NEKO_STANDALONE
#			define SELF_DLL NULL
#		else
#			define SELF_DLL "neko.dll"
#		endif
		if( GetModuleFileName(GetModuleHandle(SELF_DLL),exe_path,MAX_PATH) == 0 )
			return val_null;
		p = strrchr(exe_path,'\\');
		if( p == NULL )
			return val_null;
		*p = 0;
		path = exe_path;
	}
#else
	if( path == NULL ) {
		allocated = strdup("/usr/local/lib/neko:/usr/lib/neko:/usr/local/bin:/usr/bin");
		path = allocated;
	}
#endif
	while( true ) {
		// windows drive letter (same behavior expected on all os)
		if( *path && path[1] == ':' ) {
			p = strchr(path+2,':');
			p2 = strchr(path+2,';');
		} else {
			p = strchr(path,':');
			p2 = strchr(path,';');
		}
		if( p == NULL || (p2 != NULL && p2 < p) )
			p = p2;
		if( p != NULL )
			*p = 0;
		tmp = alloc_array(2);
		if( (p && p[-1] != '/' && p[-1] != '\\') || (!p && path[strlen(path)-1] != '/' && path[strlen(path)-1] != '\\') ) {
			buffer b = alloc_buffer(path);
			char c = '/';
			buffer_append_sub(b,&c,1);
			val_array_ptr(tmp)[0] = buffer_to_string(b);
		} else
			val_array_ptr(tmp)[0] = alloc_string(path);
		val_array_ptr(tmp)[1] = l;
		l = tmp;
		if( p != NULL )
			*p = (p == p2)?';':':';
		else
			break;
		path = p+1;
	}
	if( allocated != NULL )
		free(allocated);
	return l;
}
Example #11
0
/**
	$acopy : array -> array
	<doc>Make a copy of an array</doc>
**/
static value builtin_acopy( value a ) {
	int i;
	value a2;
	val_check(a,array);
	a2 = alloc_array(val_array_size(a));
	for(i=0;i<val_array_size(a);i++)
		val_array_ptr(a2)[i] = val_array_ptr(a)[i];
	return a2;
}
Example #12
0
static value init_module() {
	neko_vm *vm = neko_vm_current();
	mcontext *ctx = CONTEXT();
	value env = vm->env;
	ctx->main = NULL;
	val_call1(val_array_ptr(env)[0],val_array_ptr(env)[1]);
	cache_module(ctx->r->filename,FTIME(ctx->r),ctx->main);
	return val_null;
}
Example #13
0
static value stats_proxy( value p1, value p2, value p3, value p4, value p5, value p6 ) {
	neko_vm *vm = NEKO_VM();
	value env = vm->env;
	value ret;
	if( vm->pstats ) vm->pstats(vm,val_string(val_array_ptr(env)[0]),1);
	ret = ((stats_callback)((int_val)val_array_ptr(vm->env)[1]&~1))(p1,p2,p3,p4,p5,p6);
	if( vm->pstats ) vm->pstats(vm,val_string(val_array_ptr(env)[0]),0);
	return ret;
}
Example #14
0
static value udpr_peer_address( value p ) {
	val_check_kind(p,k_udprpeer);
	ENetPeer* peer = (ENetPeer *)val_data(p);

	if(peer == NULL)
		neko_error();
    value rv = alloc_array(2);
    val_array_ptr(rv)[0] = alloc_int32(peer->address.host);
    val_array_ptr(rv)[1] = alloc_int(peer->address.port);
    return rv;
}
Example #15
0
static int store_table( void *r, const char *key, const char *val ) {
	value a;
	if( key == NULL || val == NULL )
		return 1;
	a = alloc_array(3);
	val_array_ptr(a)[0] = alloc_string(key);
	val_array_ptr(a)[1] = alloc_string(val);
	val_array_ptr(a)[2] = *(value*)r;
	*((value*)r) = a;
	return 1;
}
Example #16
0
/**
	socket_host : 'socket -> #address
	<doc>Return the socket local address composed of an (host,port) array</doc>
**/
static value socket_host( value o ) {
	struct sockaddr_in addr;
	unsigned int addrlen = sizeof(addr);
	value ret;
	val_check_kind(o,k_socket);
	if( getsockname(val_sock(o),(struct sockaddr*)&addr,&addrlen) == SOCKET_ERROR )
		neko_error();
	ret = alloc_array(2);
	val_array_ptr(ret)[0] = alloc_int32(*(int*)&addr.sin_addr);
	val_array_ptr(ret)[1] = alloc_int(ntohs(addr.sin_port));
	return ret;
}
Example #17
0
/**
	module_read : fread:(buf:string -> pos:int -> len:int -> int) -> loader:object -> 'module
	<doc>
	Read a module using the specified read function and the specified loader.
	</doc>
**/
static value module_read( value fread, value loader ) {
	value p;
	neko_module *m;
	val_check_function(fread,3);
	val_check(loader,object);
	p = alloc_array(2);
	val_array_ptr(p)[0] = fread;
	val_array_ptr(p)[1] = alloc_empty_string(READ_BUFSIZE);
	m = neko_read_module(read_proxy,p,loader);
	if( m == NULL )
		neko_error();
	m->name = alloc_string("");
	return alloc_abstract(neko_kind_module,m);
}
Example #18
0
/**
	same_closure : any -> any -> bool
	<doc>
	Compare two functions by checking that they refer to the same implementation and that their environments contains physically equal values.
	</doc>
**/
static value same_closure( value _f1, value _f2 ) {
	vfunction *f1 = (vfunction*)_f1;
	vfunction *f2 = (vfunction*)_f2;
	int i;
	if( !val_is_function(f1) || !val_is_function(f2) )
		return val_false;
	if( f1 == f2 )
		return val_true;
	if( f1->nargs != f2->nargs || f1->addr != f2->addr || f1->module != f2->module || val_array_size(f1->env) != val_array_size(f2->env) )
		return val_false;
	for(i=0;i<val_array_size(f1->env);i++)
		if( val_array_ptr(f1->env)[i] != val_array_ptr(f2->env)[i] )
			return val_false;
	return val_true;
}
Example #19
0
/**
	$ablit : dst:array -> dst_pos:int -> src:array -> src_pos:int -> len:int -> void
	<doc>
	Copy [len] elements from [src_pos] of [src] to [dst_pos] of [dst].
	An error occurs if out of arrays bounds.
	</doc>
**/
static value builtin_ablit( value dst, value dp, value src, value sp, value l ) {
	int dpp, spp, ll;
	val_check(dst,array);
	val_check(dp,int);
	val_check(src,array);
	val_check(sp,int);
	val_check(l,int);
	dpp = val_int(dp);
	spp = val_int(sp);
	ll = val_int(l);
	if( dpp < 0 || spp < 0 || ll < 0 || dpp + ll < 0 || spp + ll  < 0 || dpp + ll > val_array_size(dst) || spp + ll > val_array_size(src) )
		neko_error();
	memmove(val_array_ptr(dst)+dpp,val_array_ptr(src)+spp,ll * sizeof(value));
	return val_null;
}
Example #20
0
File: interp.c Project: robinp/neko
static value neko_flush_stack( int_val *cspup, int_val *csp, value old ) {
	int ncalls = (int)((cspup - csp) / 4);
	value stack_trace = alloc_array(ncalls + ((old == NULL)?0:val_array_size(old)));
	value *st = val_array_ptr(stack_trace);
	neko_module *m;
	while( csp != cspup ) {
		m = (neko_module*)csp[4];
		if( m ) {
			if( m->dbgidxs ) {
				int ppc = (int)((((int_val**)csp)[1]-2) - m->code);
				int idx = m->dbgidxs[ppc>>5].base + bitcount(m->dbgidxs[ppc>>5].bits >> (31 - (ppc & 31)));
				*st = val_array_ptr(m->dbgtbl)[idx];
			} else
				*st = m->name;
		} else
Example #21
0
static value apply1( value p1 ) {
	value env = NEKO_VM()->env;
	value *a = val_array_ptr(env) + 1;
	int n = val_array_size(env) - 1;
	a[n-1] = p1;
	return val_callN(a[-1],a,n);
}
Example #22
0
/**
	$array : any* -> array
	<doc>Create an array from a list of values</doc>
**/
static value builtin_array( value *args, int nargs ) {
	value a = alloc_array(nargs);
	int i;
	for(i=0;i<nargs;i++)
		val_array_ptr(a)[i] = args[i];
	return a;
}
Example #23
0
/**
	$objcall : o:any -> f:int -> args:array -> any
	<doc>Call the field [f] of [o] with [args] and return the value or [null] is [o] is not an object</doc>
**/
static value builtin_objcall( value o, value f, value args ) {
	if( !val_is_object(o) )
		return val_null; // keep dot-access semantics
	val_check(f,int);
	val_check(args,array);
	return val_ocallN(o,val_int(f),val_array_ptr(args),val_array_size(args));
}
Example #24
0
/**
	$asub : array -> p:int -> l:int -> array
	<doc>
	Return [l] elements starting at position [p] of an array.
	An error occurs if out of array bounds.
	</doc>
**/
static value builtin_asub( value a, value p, value l ) {
	value a2;
	int i;
	int pp, ll;
	val_check(a,array);
	val_check(p,int);
	val_check(l,int);
	pp = val_int(p);
	ll = val_int(l);
	if( pp < 0 || ll < 0 || pp+ll < 0 || pp+ll > val_array_size(a) )
		neko_error();
	a2 = alloc_array(ll);
	for(i=0;i<ll;i++)
		val_array_ptr(a2)[i] = val_array_ptr(a)[pp+i];
	return a2;
}
Example #25
0
static value make_array_result( value a, fd_set *tmp ) {
	value r;
	int i, len;
	int pos = 0;
	if( tmp == NULL )
		return val_null;
	len = val_array_size(a);
	r = alloc_array(len);
	for(i=0;i<len;i++) {
		value s = val_array_ptr(a)[i];
		if( FD_ISSET(val_sock(s),tmp) )
			val_array_ptr(r)[pos++] = s;
	}
	val_set_size(r,pos);
	return r;
}
Example #26
0
/**
	socket_poll : 'socket array -> 'poll -> timeout:float -> 'socket array
	<doc>
	Perform a polling for data available over a given set of sockets. This is similar to [socket_select]
	except that [socket_select] is limited to a given number of simultaneous sockets to check.
	</doc>
**/
static value socket_poll( value socks, value pdata, value timeout ) {
	polldata *p;
	value a;
	int i, rcount = 0;
	if( socket_poll_prepare(pdata,socks,alloc_array(0)) == NULL )
		neko_error();
	if( socket_poll_events(pdata,timeout) == NULL )
		neko_error();
	p = val_poll(pdata);
	while( val_array_ptr(p->ridx)[rcount] != alloc_int(-1) )
		rcount++;
	a = alloc_array(rcount);
	for(i=0;i<rcount;i++)
		val_array_ptr(a)[i] = val_array_ptr(socks)[val_int(val_array_ptr(p->ridx)[i])];
	return a;
}
Example #27
0
static value varargs_callback( value *args, int nargs ) {
	value f = NEKO_VM()->env;
	value a = alloc_array(nargs);
	int i;
	for(i=0;i<nargs;i++)
		val_array_ptr(a)[i] = args[i];
	return val_call1(f,a);
}
Example #28
0
static value apply3( value p1, value p2, value p3 ) {
	value env = NEKO_VM()->env;
	value *a = val_array_ptr(env) + 1;
	int n = val_array_size(env) - 1;
	a[n-3] = p1;
	a[n-2] = p2;
	a[n-1] = p3;
	return val_callN(a[-1],a,n);
}
Example #29
0
static int read_proxy( readp p, void *buf, int size ) {
	value fread = val_array_ptr(p)[0];
	value vbuf = val_array_ptr(p)[1];
	value ret;
	int len;
	if( size < 0 )
		return -1;
	if( size > READ_BUFSIZE )
		vbuf = alloc_empty_string(size);
	ret = val_call3(fread,vbuf,alloc_int(0),alloc_int(size));
	if( !val_is_int(ret) )
		return -1;
	len = val_int(ret);
	if( len < 0 || len > size )
		return -1;
	memcpy(buf,val_string(vbuf),len);
	return len;
}
Example #30
0
static void preload_module( const char *name, server_rec *serv ) {
	value exc = NULL;
	neko_vm *vm = neko_vm_alloc(NULL);
	value mload = neko_default_loader(NULL,0);
	value m, read_path, exec;
	time_t time = 0;
	neko_vm_select(vm);
	if( config.use_jit ) neko_vm_jit(vm,1);
	if( !exc ) {
		value args[] = { alloc_string("std@module_read_path"), alloc_int(3) };
		read_path = val_callEx(mload,val_field(mload,val_id("loadprim")),args,2,&exc);
	}
	if( !exc ) {
		value args[] = { alloc_string("std@module_exec"), alloc_int(1) };
		exec = val_callEx(mload,val_field(mload,val_id("loadprim")),args,2,&exc);
	}
	if( !exc ) {
		value args[] = { val_null, alloc_string(name), mload };
		char *p = strrchr(val_string(args[1]),'.');
		if( p != NULL ) *p = 0;
		m = val_callEx(mload,read_path,args,3,&exc);
	}
	if( !exc ) {
		struct stat t;
		if( stat(name,&t) )
			exc = alloc_string("failed to stat()");
		else
			time = t.st_mtime;
	}
	if( !exc ) {
		value f = alloc_function(init_module,0,"init_module");
		value env = alloc_array(2);
		val_array_ptr(env)[0] = exec;
		val_array_ptr(env)[1] = m;
		((vfunction*)f)->env = env;
		cache_module(name,time,f);
	}
	if( exc ) {
		buffer b = alloc_buffer(NULL);
		val_buffer(b,exc);
		ap_log_error(APLOG_MARK,APLOG_WARNING,LOG_SUCCESS serv,"Failed to preload module '%s' : %s",name,val_string(buffer_to_string(b)));
	}
	neko_vm_select(NULL);
}