The unified diff between revisions [9a6e8df1..] and [a81fe555..] is displayed below. It can also be downloaded as a raw diff.

#
# old_revision [9a6e8df1d6b102f467702e274d53d90f9151e2c8]
# new_revision [a81fe5550c21fa983b4e344e07c29b9cecdf75ea]
#
# patch "src/lsc/ast.c"
#  from [38d7a1613ebd1088ccb91c4fc2c7c711467cdd57]
#    to [d0c7066749da60adc317b58c4630de00a072a23f]
# 
# patch "src/lsc/ast.h"
#  from [3c28d1b6a01e8e99c8f9485c9771e5f9df66ec83]
#    to [c16257876c942379840ba94428e4bbbc807d8216]
# 
# patch "src/lsc/codegen.c"
#  from [3f17dcc09e552288f4a68b0ac58692cffd524364]
#    to [59287d90158eaceceb9a87f9fe6f6c45059c6cb6]
# 
# patch "src/lsc/lexer.l"
#  from [88be4de3325822fc6a95e81cc8c615a6c70078bf]
#    to [abb8ad18ba69e18853d003ba9da3ab968f58d165]
# 
# patch "src/lsc/parser.y"
#  from [a3d3372576329c2dc4221d54c0a05238eb86dece]
#    to [2e92a218e99f7522cbd4a48694ec2202d575e0d2]
# 
# patch "src/lsc/types.h"
#  from [0934f3373a49335fb48fc8fb0d9be2350c843533]
#    to [b169b733d6297c1e15359d339d187ae7e5798f9b]
# 
# patch "src/lsi/Makefile"
#  from [609a07c3b2f5a6dcc33cb70112821fa46ab8ade0]
#    to [78a1f906a0569af4ace0697000ac5411211fcc1c]
# 
# patch "src/lsi/abi.h"
#  from [f5ff3bd7144f8020da012ea0158aa51d862f888e]
#    to [0553ade9748fed1e6808e874fa67020a6dd52a22]
# 
# patch "src/lsi/abispec"
#  from [e8cad560a662c1abc9da835eedd7dddafa77d03f]
#    to [14bb48cc77b6f36777d424e8a354f629082b14e8]
# 
# patch "src/lsi/makeabi"
#  from [af04da9852be189b121ae5a7e48a4664afc10c7d]
#    to [54d8bf7ee907e67849843b113a8c6f5039ec020b]
# 
# patch "src/lsi/mouse.c"
#  from [410738f63d15db286b591fff6040fcdfe9e1cfa6]
#    to [51f025fd4be11edf4936c00a3316e4d1ee31b9a5]
# 
# patch "src/lsi/plugins.c"
#  from [d1249e7348b4b02e2405e3374b7e6609ff982875]
#    to [f3e7cb50a5258da029d27c67f148fba7845fc552]
# 
# patch "src/lsi/vm.c"
#  from [0d1a3539301653c5f5cad4792072a3f87ee17d29]
#    to [c29bc86ce0d4170f8a0229735384ea9eea76763f]
#
============================================================
--- src/lsc/ast.c	38d7a1613ebd1088ccb91c4fc2c7c711467cdd57
+++ src/lsc/ast.c	d0c7066749da60adc317b58c4630de00a072a23f
@@ -110,6 +110,21 @@ ast *make_fndefint(char *identifier, lon
 	return elem;
 }
 
+ast *make_fndefint_v(char *identifier, long num)
+{
+	ast *elem = safe_malloc(sizeof(ast));
+	ast_list *list = NULL;
+
+	elem->tag = node_ast;
+	elem->info.node.tag = kind_fndefint_v;
+	list = make_list(make_integer(num), list);
+	list = make_list(make_string(identifier), list);
+	elem->info.node.head = list;
+	elem->lineno = yylineno;
+
+	return elem;
+}
+
 ast *make_constant(char *identifier, long num)
 {
 	ast *elem = safe_malloc(sizeof(ast));
@@ -297,13 +312,13 @@ ast *make_case_statement_number(long num
 	return elem;
 }
 
-ast *make_return_statement(void)
+ast *make_return_statement(ast *expression)
 {
 	ast *elem = safe_malloc(sizeof(ast));
 
 	elem->tag = node_ast;
 	elem->info.node.tag = stmt_return;
-	elem->info.node.head = NULL;
+	elem->info.node.head = make_list(expression, NULL);
 	elem->lineno = yylineno;
 
 	return elem;
============================================================
--- src/lsc/ast.h	3c28d1b6a01e8e99c8f9485c9771e5f9df66ec83
+++ src/lsc/ast.h	c16257876c942379840ba94428e4bbbc807d8216
@@ -5,6 +5,7 @@ ast *make_fndefint(char *, long);
 ast *make_list_node(ast_list *);
 ast *make_function(char *, ast_list *, ast_list *);
 ast *make_fndefint(char *, long);
+ast *make_fndefint_v(char *, long);
 ast *make_constant(char *, long);
 ast *make_realconstant(char *, float);
 ast *make_fndefext(char *);
@@ -22,6 +23,6 @@ ast *make_default_statement();
 ast *make_case_statement_variable(char *);
 ast *make_break_statement();
 ast *make_default_statement();
-ast *make_return_statement();
+ast *make_return_statement(ast *);
 
 void ast_dump(ast *);
============================================================
--- src/lsc/codegen.c	3f17dcc09e552288f4a68b0ac58692cffd524364
+++ src/lsc/codegen.c	59287d90158eaceceb9a87f9fe6f6c45059c6cb6
@@ -95,10 +95,14 @@ struct instr *instr_tail = NULL;
 #define VAR_ARG 1
 #define VAR_REAL 2
 
+#define FN_TYPE_BASE 0xff
+
 #define FN_INT 1
 #define FN_STR 2
 #define FN_LOCAL 3
 
+#define FN_VARARGS 0x100
+
 int fnconst;
 int nargs;
 int local_variable_count = -1;
@@ -146,7 +150,7 @@ void output_functions_action(struct hash
 {
 	int len, pad;
 
-	if (ptr->flags == FN_LOCAL) {
+	if ((ptr->flags & FN_TYPE_BASE) == FN_LOCAL) {
 		len = strlen(ptr->name) + 1 + 16;
 		pad = (4 - (len % 4)) % 4;
 		output_int(len+pad);
@@ -311,7 +315,7 @@ void create_function(char *fnname, int t
 		compiler_error("Function already exists");
 
 	if (output_asm) {
-		switch (type) {
+		switch (type & FN_TYPE_BASE) {
 		case FN_INT:
 			printf("%%fnint %s %d\n", fnname, num);
 			break;
@@ -644,12 +648,14 @@ void codegen(ast *node)
 	case node_ast:
 		switch (node->info.node.tag) {
 		case kind_fndefint:
+		case kind_fndefint_v:
 			assert(sp == 0);
 			assert(node->info.node.head != NULL);
 			assert(node->info.node.head->next != NULL);
 
 			create_function(node->info.node.head->elem->info.string,
-			    FN_INT,
+			    FN_INT | ((node->info.node.tag ==
+				kind_fndefint_v) ? FN_VARARGS : 0),
 			    node->info.node.head->next->elem->info.integer);
 			break;
 		case kind_constant:
@@ -771,20 +777,36 @@ void codegen(ast *node)
 
 //			printf("savedsp = %d\n", savedsp);
 
+			nargs = 0;
+
 			/* Evaluate the arguments first */
 			for (ptr =
 			    node->info.node.head->next->elem->info.node.head;
 			    ptr; ptr = ptr->next) {
 				codegen(ptr->elem);
+				nargs++;
 			}
 
 //			printf("sp = %d\n", sp);
 
+			if (!lookup_function(node->info.node.head->elem, &fn))
+				compiler_error("Function not found");
+
+			if (fn.type & FN_VARARGS) {
+				/*
+				 * The last argument is the number of
+				 * arguments to expect in the case
+				 * of variable argument length.
+				 * This is something only supported for
+				 * builtin functions at present.
+				 */
+				emit_instr_immediate(OP_PUSH, nargs);
+				sp++;
+			}
+
 			emit_instr_immediate(OP_ALLOC, 1);
 			sp++;
 
-			if (!lookup_function(node->info.node.head->elem, &fn))
-				compiler_error("Function not found");
 			switch (fn.type) {
 			case FN_INT:
 				emit_instr_immediate(OP_CALLNUM, fn.num);
@@ -1147,8 +1169,12 @@ void codegen(ast *node)
 			emit_instr_label(OP_B, breaklabel);
 			break;
 		case stmt_return:
-			assert(node->info.node.head == NULL);
-
+			if (node->info.node.head) {
+				/* Return value */
+				codegen(node->info.node.head->elem);
+				emit_instr_imm_const(OP_STORE, sp, fnconst);
+				sp--;
+			}
 			emit_instr_imm_const(OP_POP, sp, fnconst);
 			emit_simple_instr(OP_RET);
 			break;
============================================================
--- src/lsc/lexer.l	88be4de3325822fc6a95e81cc8c615a6c70078bf
+++ src/lsc/lexer.l	abb8ad18ba69e18853d003ba9da3ab968f58d165
@@ -86,6 +86,7 @@ fndefint	return TOKFNDEFINT;
 
 function	return TOKFUNCTION;
 fndefint	return TOKFNDEFINT;
+fndefint_v	return TOKFNDEFINT_V;
 fndefext	return TOKFNDEFEXT;
 constant	return TOKCONSTANT;
 while		return TOKWHILE;
============================================================
--- src/lsc/parser.y	a3d3372576329c2dc4221d54c0a05238eb86dece
+++ src/lsc/parser.y	2e92a218e99f7522cbd4a48694ec2202d575e0d2
@@ -68,7 +68,7 @@ int main(int argc, char *argv[])
 
 %}
 
-%token TOKFUNCTION TOKFNDEFINT TOKFNDEFEXT TOKCONSTANT
+%token TOKFUNCTION TOKFNDEFINT TOKFNDEFINT_V TOKFNDEFEXT TOKCONSTANT
 %token TOKWHILE TOKIF TOKELSE TOKSWITCH TOKCASE TOKDEFAULT
 %token TOKBREAK TOKRETURN TOKEQ TOKNE TOKAND TOKOR STRING
 
@@ -86,6 +86,7 @@ int main(int argc, char *argv[])
 %type <Tast> fndefint
 %type <Tast> fndefext
 %type <Tast> statement
+%type <Tast> fndefint_v
 %type <Tast> assignment
 %type <Tast> expression
 %type <Tast> realconstant
@@ -142,6 +143,7 @@ fn_list_inner:
 fn_list_inner:
 	  fn_list_inner function	{ $$ = make_list($2, $1); }
 	| fn_list_inner fndefint	{ $$ = make_list($2, $1); }
+	| fn_list_inner fndefint_v	{ $$ = make_list($2, $1); }
 	| fn_list_inner fndefext	{ $$ = make_list($2, $1); }
 	| fn_list_inner constant	{ $$ = make_list($2, $1); }
 	| fn_list_inner realconstant	{ $$ = make_list($2, $1); }
@@ -158,6 +160,11 @@ fndefint:
 	{ $$ = make_fndefint($2, $3); }
 	;
 
+fndefint_v:
+	TOKFNDEFINT_V IDENTIFIER NUMBER ';'
+	{ $$ = make_fndefint_v($2, $3); }
+	;
+
 constant:
 	TOKCONSTANT IDENTIFIER NUMBER ';'
 	{ $$ = make_constant($2, $3); }
@@ -319,8 +326,11 @@ statement_return:
 	;
 
 statement_return:
+	TOKRETURN expression
+	{ $$ = make_return_statement($2); }
+	|
 	TOKRETURN
-	{ $$ = make_return_statement(); }
+	{ $$ = make_return_statement(NULL); }
 	;
 
 statement_break:
============================================================
--- src/lsc/types.h	0934f3373a49335fb48fc8fb0d9be2350c843533
+++ src/lsc/types.h	b169b733d6297c1e15359d339d187ae7e5798f9b
@@ -2,8 +2,8 @@ typedef enum {
 
 typedef enum {
 
-	kind_fndef, kind_fndefint, kind_fndefext, kind_constant,
-	kind_assign, kind_list, kind_call, kind_array,
+	kind_fndef, kind_fndefint, kind_fndefint_v, kind_fndefext,
+	kind_constant, kind_assign, kind_list, kind_call, kind_array,
 
 	op_plus, op_minus, op_times, op_divide,
 	op_gt, op_lt, op_ge, op_le, op_eq, op_ne,
============================================================
--- src/lsi/Makefile	609a07c3b2f5a6dcc33cb70112821fa46ab8ade0
+++ src/lsi/Makefile	78a1f906a0569af4ace0697000ac5411211fcc1c
@@ -3,9 +3,9 @@ OBJS=	main.o vm.o plugins.o dmx.o midi.o
 PREFIX?=	/usr/local
 
 OBJS=	main.o vm.o plugins.o dmx.o midi.o beatdetect.o fft.o map3d.o mouse.o \
-	cmdsocket.o
+	cmdsocket.o sql.o
 SRCS=	main.c vm.c plugins.c dmx.c midi.c beatdetect.c fft.c map3d.c mouse.c \
-	cmdsocket.c
+	cmdsocket.c sql.c
 
 OBJS+=	abi.o
 SRCS+=	abi.c
@@ -14,10 +14,13 @@ INCDIR=	../include
 COMMONDIR=	../common
 
 INCDIR=	../include
+SQLITEINCDIR= /usr/pkg/include
+SQLITELIBDIR= /usr/pkg/lib
 
 CFLAGS+=	-Wall -Werror
-CPPFLAGS+=	-I${INCDIR}
-LDLIBS+=	-lm
+CPPFLAGS+=	-I${INCDIR} -I${SQLITEINCDIR}
+LDFLAGS+=	-L${SQLITELIBDIR} -Wl,-R${SQLITELIBDIR}
+LDLIBS+=	-lm -lsqlite3
 
 PROGOBJS=	${OBJS} ${COMMONOBJS:S/^/${COMMONDIR}\//}
 
============================================================
--- src/lsi/abi.h	f5ff3bd7144f8020da012ea0158aa51d862f888e
+++ src/lsi/abi.h	0553ade9748fed1e6808e874fa67020a6dd52a22
@@ -49,3 +49,5 @@ int vm_intfn_cmdsocket_prefix(void);
 int vm_intfn_cmdsocket_read(void);
 int vm_intfn_cmdsocket_write(void);
 int vm_intfn_cmdsocket_prefix(void);
+int vm_intfn_sql_query(void);
+int vm_intfn_sql_query_1s(void);
============================================================
--- src/lsi/abispec	e8cad560a662c1abc9da835eedd7dddafa77d03f
+++ src/lsi/abispec	14bb48cc77b6f36777d424e8a354f629082b14e8
@@ -38,6 +38,9 @@ function cmdsocket_prefix
 function cmdsocket_read
 function cmdsocket_write
 function cmdsocket_prefix
+/* NOT_YET function_v sql_query */
+function sql_query
+function sql_query_1s
 
 /*
  * The ABI should be identified by a SHA1 hash of this file
============================================================
--- src/lsi/makeabi	af04da9852be189b121ae5a7e48a4664afc10c7d
+++ src/lsi/makeabi	54d8bf7ee907e67849843b113a8c6f5039ec020b
@@ -37,6 +37,13 @@ do_function()
 	FNCOUNT=$((${FNCOUNT}+1))
 }
 
+do_function_v()
+{
+	echo "	vm_intfn_${ARG1}," >>${ABI}
+	echo "fndefint_v ${ARG1} ${FNCOUNT};" >>${HEADER}
+	FNCOUNT=$((${FNCOUNT}+1))
+}
+
 cat <<EOF >${ABI}
 /* abi.c */
 /* autogenerated - do not edit */
@@ -69,6 +76,8 @@ do
 	case "$TYPE" in
 		function) do_function
 			;;
+		function_v) do_function_v
+			;;
 	esac
 done <${INFILE}
 
============================================================
--- src/lsi/mouse.c	410738f63d15db286b591fff6040fcdfe9e1cfa6
+++ src/lsi/mouse.c	51f025fd4be11edf4936c00a3316e4d1ee31b9a5
@@ -10,7 +10,7 @@
 #include <stdio.h>
 #include "vm.h"
 
-#define MOUSEDEVICE "/dev/wsmouse"
+#define MOUSEDEVICE "/dev/wsmouse1"
 
 char *events[] = {
 	"undefined",
============================================================
--- src/lsi/plugins.c	d1249e7348b4b02e2405e3374b7e6609ff982875
+++ src/lsi/plugins.c	f3e7cb50a5258da029d27c67f148fba7845fc552
@@ -12,6 +12,7 @@
 #include "beatdetect.h"
 #include "mouse.h"
 #include "cmdsocket.h"
+#include "sql.h"
 
 struct plugin plugins_table[] = {
 	{"midi", midi_init, midi_close, 0},
@@ -19,6 +20,7 @@ struct plugin plugins_table[] = {
 	{"beatdetect", beatdetect_init, beatdetect_close, 0},
 	{"mouse", mouse_init, mouse_close, 0},
 	{"cmdsocket", cmdsocket_init, cmdsocket_close, 0},
+	{"sql", sql_init, sql_close, 0},
 };
 
 int nplugins = (sizeof(plugins_table) / sizeof(struct plugin));
============================================================
--- src/lsi/vm.c	0d1a3539301653c5f5cad4792072a3f87ee17d29
+++ src/lsi/vm.c	c29bc86ce0d4170f8a0229735384ea9eea76763f
@@ -23,6 +23,7 @@
 #include "map3d.h"
 #include "mouse.h"
 #include "cmdsocket.h"
+#include "sql.h"
 
 #define DEBUG 0
 
@@ -482,6 +483,121 @@ int vm_intfn_cmdsocket_write(void)
 	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;
+}
+#endif
+
 int vm_intfn_beatdetect_read(void)
 {
 	if (!beatdetect_read()) {