The unified diff between revisions [8482057d..] and [81f2a8bb..] is displayed below. It can also be downloaded as a raw diff.

This diff has been restricted to the following files: 'src/lsi/vm.c'

#
# old_revision [8482057dd1a991674bb30b63b9397a3c5d069df9]
# new_revision [81f2a8bbe94638a22f5651ee07112ceabd50285c]
#
# patch "src/lsi/vm.c"
#  from [2c18e65f543e306db2ca1023e8ef82724829f4a7]
#    to [e2e905076968e53dd131de512d042191f64d91bf]
#
============================================================
--- src/lsi/vm.c	2c18e65f543e306db2ca1023e8ef82724829f4a7
+++ src/lsi/vm.c	e2e905076968e53dd131de512d042191f64d91bf
@@ -11,6 +11,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <math.h>
+#include <stdarg.h>
 
 #include "vm.h"
 #include "code.h"
@@ -21,6 +22,8 @@
 #include "beatdetect.h"
 #include "map3d.h"
 #include "mouse.h"
+#include "cmdsocket.h"
+#include "sql.h"
 
 #define DEBUG 0
 
@@ -41,6 +44,9 @@ struct vm_thread {
 
 #define ARRAYBLOCKSIZE	512
 
+#define SLEEPTIME_SEC	60
+#define SLEEPTIME_NSEC	0
+
 struct pollfd vm_pollfd[VM_MAXPOLLFD];
 int vm_pollfdqueue[VM_MAXPOLLFD];
 
@@ -55,6 +61,7 @@ size_t vm_codesize = 0;
 
 instr *vm_codearea = NULL;
 size_t vm_codesize = 0;
+int vm_threads = 0;
 
 struct hashentry *fnhash[HASHSIZE];
 struct hashentry *globhash[HASHSIZE];
@@ -84,7 +91,7 @@ void stack_pokereal(struct vm_thread *th
 void stack_poke(struct vm_thread *thread, int count, stkentry value);
 void stack_pokereal(struct vm_thread *thread, int count, float value);
 
-int vm_intfn_nop(void)
+int vm_intfn___nop(void)
 {
 	/* Do nothing */
 	return 1;
@@ -95,7 +102,7 @@ int vm_intfn_nop(void)
  * The compiler does not allocate space for a return value.
  * They also change the stack pointer.
  */
-int vm_intfn_global_store(void)
+int vm_intfn___global_store(void)
 {
 	int len, next, value;
 	struct hashentry *hashptr;
@@ -130,7 +137,7 @@ gstoreout:
 	return 1;
 }
 
-int vm_intfn_global_load(void)
+int vm_intfn___global_load(void)
 {
 	int len, next, value;
 	struct hashentry *hashptr;
@@ -163,7 +170,7 @@ gloadout:
 	return 1;
 }
 
-int vm_intfn_global_array_store(void)
+int vm_intfn___global_array_store(void)
 {
 	int len, next, value, index;
 	struct hashentry *hashptr;
@@ -210,7 +217,7 @@ gstorearrayout:
 	return 1;
 }
 
-int vm_intfn_global_array_load(void)
+int vm_intfn___global_array_load(void)
 {
 	int len, next, value, index;
 	struct hashentry *hashptr;
@@ -418,6 +425,285 @@ int vm_intfn_mouse_read(void)
 	return 0;
 }
 
+int vm_intfn_cmdsocket_listen(void)
+{
+	stack_poke(vm_current, 0,
+	    cmdsocket_listen(stack_get(vm_current, 1)));
+	return 1;
+}
+
+int vm_intfn_cmdsocket_prefix(void)
+{
+	char buf[VM_STRING_MAX];
+	int len = stack_get(vm_current, 1);
+
+	strncpy(buf, stack_getstr(vm_current, len, 1), len);
+	buf[len] = '\0';
+
+	cmdsocket_prefix(buf);
+
+	return 1;
+}
+
+int vm_intfn_cmdsocket_accept(void)
+{
+	if (!cmdsocket_accept()) {
+	    vm_queue(vm_current, VM_CMDLISTENQ);
+	    vm_current = NULL;
+	    return 0;
+	}
+	return 1;
+}
+
+int vm_intfn_cmdsocket_read(void)
+{
+	if (!cmdsocket_read()) {
+		vm_queue(vm_current, VM_CMDREADQ);
+		vm_current = NULL;
+		return 0;
+	}
+	return 1;
+}
+
+int vm_intfn_cmdsocket_write(void)
+{
+	int off = stack_get(vm_current, 1);
+	int len = stack_get(vm_current, 2);
+	char *buffer = stack_getstr(vm_current, len, 2);
+	int newoff;
+
+	printf("cmdsocket_write in vm\n");
+
+	newoff = cmdsocket_write(buffer, len, off);
+	stack_poke(vm_current, 1, newoff);
+
+	if (newoff != len) {
+		printf("cmdsocket_write sleeping\n");
+		vm_queue(vm_current, VM_CMDWRITEQ);
+		vm_current = NULL;
+		return 0;
+	}
+	printf("cmdsocket_write success\n");
+	return 1;
+}
+
+#ifdef NOT_YET
+
+#define MIN(a, b) ((a < b) ? a : b)
+
+#define MORE_QUERY_N(x, n) do {						\
+		off = strncpy(buf+off, (x), MIN(VM_STRING_MAX-off, (n)) - buf;\
+		if (off >= VM_STRING_MAX) {				\
+		    printf("Excessive string length - can't perform query\n"); \
+		    return 1;						\
+		}							\
+	} while (0)
+
+#define MORE_QUERY(x) MORE_QUERY_N((x), VM_STRING_MAX)
+
+int vm_intfn_sql_query(void)
+{
+	int nargs = stack_get(vm_current, 1);
+	int len = stack_get(vm_current, nargs+1);
+	char *fmt = stack_getstr(vm_current, len, nargs+1);
+	char buf1[VM_STRING_MAX];
+	char buf2[VM_STRING_MAX];
+	char buf[VM_STRING_MAX];
+	int off = 0;
+	int result;
+	int next;
+	char *p, *p1;
+
+	if (len > VM_STRING_MAX) {
+		printf("Excessive string length - can't perform query\n");
+		return 1;
+	}
+	strncpy(buf1, fmt, len);
+	buf1[len] = '\0';
+	
+	p = buf1;
+	while (p1 = strchr(p, '%') {
+		if (p1) {
+		    *p1 = 0;
+		}
+		if (p != buf1) {
+			switch(*p) {
+			case '%':
+			    MORE_QUERY("%");
+			    break;
+			case 's':
+			    next = (len + sizeof(stkentry)-1) / sizeof(stkentry) + 1;
+
+			    MORE_QUERY_N(stack_getstr(vm_current, slen, nargs));
+			}
+		}
+		MORE_QUERY(p);
+		if (p1)
+		    p = p1;
+		else
+		    break;
+	}
+
+	sql_query(buffer, len, &result);
+	/* XXX what to do with an error here? */
+	stack_poke(vm_current, 0, result); /* return value */
+	return 1;
+}
+#else
+int vm_intfn_sql_query(void)
+{
+	int len = stack_get(vm_current, 1);
+	char *query = stack_getstr(vm_current, len, 1);
+	int result;
+
+	sql_query(query, len, &result);
+	/* XXX what to do with an error here? */
+	stack_poke(vm_current, 0, result); /* return value */
+	return 1;
+}
+
+int vm_intfn_sql_query_1s(void)
+{
+	int len1, len2;
+	char buf1[VM_STRING_MAX];
+	char buf2[VM_STRING_MAX];
+	char query[VM_STRING_MAX];
+	char *arg1;
+	char *arg2;
+	int result;
+	int next;
+
+	next = 1;
+
+	len2 = stack_get(vm_current, next);
+	arg2 = stack_getstr(vm_current, len2, next);
+
+	next += (len2 + sizeof(stkentry)-1) / sizeof(stkentry) + 1;
+
+	len1 = stack_get(vm_current, next);
+	arg1 = stack_getstr(vm_current, len1, next);
+
+	if ((len1 > VM_STRING_MAX) || (len2 > VM_STRING_MAX)) {
+		printf("Excessive string length - can't perform query\n");
+		return 1;
+	}
+	strncpy(buf1, arg1, len1);
+	buf1[len1] = '\0';
+	strncpy(buf2, arg2, len2);
+	buf2[len2] = '\0';
+
+	snprintf(query, VM_STRING_MAX, buf1, buf2);
+
+	sql_query(query, strlen(query), &result);
+
+	/* XXX what to do with an error here? */
+	stack_poke(vm_current, 0, result); /* return value */
+	return 1;
+}
+
+int vm_intfn_sql_getvar(void)
+{
+	int len;
+	char buf[VM_STRING_MAX];
+	char query[VM_STRING_MAX];
+	int result;
+
+	len = stack_get(vm_current, 1);
+
+	if (len >= VM_STRING_MAX) {
+		printf("Excessive string length - can't perform query\n");
+		return 1;
+	}
+
+	snprintf(buf, len+1, stack_getstr(vm_current, len, 1));
+	snprintf(query, VM_STRING_MAX, "SELECT value FROM vars WHERE name=\"%s\"", buf);
+
+	if (sql_query(query, strlen(query), &result) != 2)
+		result = -1;
+
+	/* XXX what to do with an error here? */
+	stack_poke(vm_current, 0, result); /* return value */
+	return 1;
+}
+
+int vm_intfn_sql_getvar_array(void)
+{
+	int len, off;
+	char buf[VM_STRING_MAX];
+	char query[VM_STRING_MAX];
+	int result;
+
+	off = stack_get(vm_current, 1);
+	len = stack_get(vm_current, 2);
+
+	if (len >= VM_STRING_MAX) {
+		printf("Excessive string length - can't perform query\n");
+		return 1;
+	}
+
+	snprintf(buf, len+1, stack_getstr(vm_current, len, 2));
+	snprintf(query, VM_STRING_MAX, "SELECT value FROM vars WHERE name=\"%s[%d]\"", buf, off);
+
+	if (sql_query(query, strlen(query), &result) != 2)
+		result = -1;
+
+	/* XXX what to do with an error here? */
+	stack_poke(vm_current, 0, result); /* return value */
+	return 1;
+}
+
+int vm_intfn_sql_setvar(void)
+{
+	int len, val;
+	char buf[VM_STRING_MAX];
+	char query[VM_STRING_MAX];
+	int result;
+
+	val = stack_get(vm_current, 1);
+	len = stack_get(vm_current, 2);
+
+	if (len >= VM_STRING_MAX) {
+		printf("Excessive string length - can't perform query\n");
+		return 1;
+	}
+
+	snprintf(buf, len+1, stack_getstr(vm_current, len, 2));
+	snprintf(query, VM_STRING_MAX, "INSERT OR REPLACE INTO vars VALUES(\"%s\", %d)", buf, val);
+
+	sql_query(query, strlen(query), &result);
+
+	/* XXX what to do with an error here? */
+	stack_poke(vm_current, 0, result); /* return value */
+	return 1;
+}
+
+int vm_intfn_sql_setvar_array(void)
+{
+	int len, off, val;
+	char buf[VM_STRING_MAX];
+	char query[VM_STRING_MAX];
+	int result;
+
+	val = stack_get(vm_current, 1);
+	off = stack_get(vm_current, 2);
+	len = stack_get(vm_current, 3);
+
+	if (len >= VM_STRING_MAX) {
+		printf("Excessive string length - can't perform query\n");
+		return 1;
+	}
+
+	snprintf(buf, len+1, stack_getstr(vm_current, len, 3));
+	snprintf(query, VM_STRING_MAX, "INSERT OR REPLACE INTO vars VALUES(\"%s[%d]\", %d)", buf, off, val);
+
+	sql_query(query, strlen(query), &result);
+
+	/* XXX what to do with an error here? */
+	stack_poke(vm_current, 0, result); /* return value */
+	return 1;
+}
+#endif
+
 int vm_intfn_beatdetect_read(void)
 {
 	if (!beatdetect_read()) {
@@ -570,6 +856,7 @@ void vm_init(void)
 	vm_npollfds = 0;
 	vm_caughtsignal = 0;
 	signal(SIGIO, vm_sighandler);
+	signal(SIGPIPE, SIG_IGN);
 }
 
 void vm_load_file(char *filename)
@@ -609,6 +896,11 @@ void vm_init_functions(void)
 	assert(vm_codearea[2] == VERSION1);
 	assert(vm_codearea[3] == VERSION2);
 
+	assert(GETINT(vm_codearea, 8) == vm_abiversion1);
+	assert(GETINT(vm_codearea, 12) == vm_abiversion2);
+	assert(GETINT(vm_codearea, 16) == vm_abiversion3);
+	assert(GETINT(vm_codearea, 20) == vm_abiversion4);
+	assert(GETINT(vm_codearea, 24) == vm_abiversion5);
 
 	/* Now, get the function table pointer */
 	t = GETINT(vm_codearea, 4);
@@ -668,10 +960,11 @@ void vm_queue(struct vm_thread *thread, 
 	vm_queues[queue] = thread;
 }
 
-int vm_spawn(char *fn)
+int vm_spawn_args(char *fn, int n, ...)
 {
 	struct vm_thread *newt;
 	struct hashentry *ptr;
+	va_list ap;
 
 	ptr = hash_lookup(fnhash, fn, 0);
 	if (ptr == NULL) {
@@ -697,25 +990,46 @@ int vm_spawn(char *fn)
 		return 0;
 	}
 	newt->sp = newt->stackbase;
+
+	stack_push(newt, 0); 	/* Return value */
+
+	/* Push optional arguments */
+	va_start(ap, n);
+	while (n--) {
+	    int a = va_arg(ap, int);
+//	    printf("arg is %d\n", a);
+	    stack_push(newt, a);
+	}
+	va_end(ap);
+
 	/* Push return address here, to point to some special thread exit
 	   routine */
-
-	stack_push(newt, 0); 	/* Return value */
 	stack_push(newt, 0);	/* Return address */
 
 	/* Insert into head of run queue */
 	newt->prev = NULL;
 	newt->queue = VM_NOQUEUE;
 	vm_queue(newt, VM_RUNQ);
+	vm_threads++;
 
 	return 1;
 }
 
+int vm_spawn(char *fn)
+{
+	return vm_spawn_args(fn, 0);
+}
+
 void vm_destroy(struct vm_thread *thread)
 {
 	vm_unqueue(thread);
 	free(thread->stackbase);
 	free(thread);
+	vm_threads--;
+	if (vm_threads == 0) {
+		printf("No threads left\n");
+		exit(0);
+	}
 }
 
 int vm_runnable(struct vm_thread *thread)
@@ -752,18 +1066,19 @@ void vm_sched(void)
 		struct timespec ts;
 		int rv;
 
-		if (vm_queues[VM_TIMEQ] == NULL) {
-			printf("No runnable thread, and no waiting thread\n");
-			exit(0);
-		}
 //		printf("No runnable thread - sleeping\n");
-		gettimeofday(&tv, NULL);
-		timersub(&vm_queues[VM_TIMEQ]->time, &tv, &tv);
-		if ((tv.tv_sec < 0) || (tv.tv_usec < 0)) {
-			tv.tv_sec = 0;
-			tv.tv_usec = 0;
+		if (vm_queues[VM_TIMEQ]) {
+		    gettimeofday(&tv, NULL);
+		    timersub(&vm_queues[VM_TIMEQ]->time, &tv, &tv);
+		    if ((tv.tv_sec < 0) || (tv.tv_usec < 0)) {
+			    tv.tv_sec = 0;
+			    tv.tv_usec = 0;
+		    }
+		    TIMEVAL_TO_TIMESPEC(&tv, &ts);
+		} else {
+		    ts.tv_sec = SLEEPTIME_SEC;
+		    ts.tv_nsec = SLEEPTIME_NSEC;
 		}
-		TIMEVAL_TO_TIMESPEC(&tv, &ts);
 //		nanosleep(&ts, NULL);
 		rv = pollts(vm_pollfd, vm_npollfds, &ts, NULL);
 		if ((rv == -1) && (errno != EINTR))
@@ -786,6 +1101,20 @@ void vm_register_signal_fd(int fd, int q
 	rv = fcntl(fd, F_SETFL, O_NONBLOCK | O_ASYNC);
 }
 
+void vm_unregister_signal_fd(int fd)
+{
+	int i;
+
+	for (i = 0; i < vm_npollfds; i++) {
+	    if (fd == vm_pollfd[i].fd) {
+		memmove(&vm_pollfd[i], &vm_pollfd[i+1],
+		    sizeof(struct pollfd) * (vm_npollfds-i-1));
+		vm_npollfds--;
+		return;
+	    }
+	}
+}
+
 void stack_push(struct vm_thread *thread, stkentry e)
 {
 	thread->sp++;