diff --git a/src/lsc/ast.c b/src/lsc/ast.c index 12ce3be..46d051d 100644 --- a/src/lsc/ast.c +++ b/src/lsc/ast.c @@ -110,6 +110,21 @@ ast *make_fndefint(char *identifier, long num) 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; diff --git a/src/lsc/ast.h b/src/lsc/ast.h index 01672b9..b27b307 100644 --- a/src/lsc/ast.h +++ b/src/lsc/ast.h @@ -5,6 +5,7 @@ ast_list *reverse_list(ast_list *); 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_case_statement_number(long); 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 *); diff --git a/src/lsc/codegen.c b/src/lsc/codegen.c index 7662f9b..0bbbc2c 100644 --- a/src/lsc/codegen.c +++ b/src/lsc/codegen.c @@ -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 hashentry *ptr) { 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 type, int num) 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; diff --git a/src/lsc/lexer.l b/src/lsc/lexer.l index 4998883..f71ede6 100644 --- a/src/lsc/lexer.l +++ b/src/lsc/lexer.l @@ -86,6 +86,7 @@ char *string_buf_ptr; function return TOKFUNCTION; fndefint return TOKFNDEFINT; +fndefint_v return TOKFNDEFINT_V; fndefext return TOKFNDEFEXT; constant return TOKCONSTANT; while return TOKWHILE; diff --git a/src/lsc/parser.y b/src/lsc/parser.y index 65c5425..8c0aa84 100644 --- a/src/lsc/parser.y +++ b/src/lsc/parser.y @@ -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 fndefint %type fndefext %type statement +%type fndefint_v %type assignment %type expression %type realconstant @@ -142,6 +143,7 @@ fn_list: 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_case: ; statement_return: + TOKRETURN expression + { $$ = make_return_statement($2); } + | TOKRETURN - { $$ = make_return_statement(); } + { $$ = make_return_statement(NULL); } ; statement_break: diff --git a/src/lsc/types.h b/src/lsc/types.h index fb8d3fc..e666199 100644 --- a/src/lsc/types.h +++ b/src/lsc/types.h @@ -2,8 +2,8 @@ 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, diff --git a/src/lsi/Makefile b/src/lsi/Makefile index 9f31ab2..c8c0284 100644 --- a/src/lsi/Makefile +++ b/src/lsi/Makefile @@ -3,9 +3,9 @@ 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 @@ COMMONOBJS= mem.o hash.o 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}\//} diff --git a/src/lsi/abi.h b/src/lsi/abi.h index 1c13a79..b5d07d3 100644 --- a/src/lsi/abi.h +++ b/src/lsi/abi.h @@ -49,3 +49,5 @@ int vm_intfn_cmdsocket_accept(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); diff --git a/src/lsi/abispec b/src/lsi/abispec index 634f603..313d9f2 100644 --- a/src/lsi/abispec +++ b/src/lsi/abispec @@ -38,6 +38,9 @@ function cmdsocket_accept 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 diff --git a/src/lsi/makeabi b/src/lsi/makeabi index 01098d7..086908e 100755 --- a/src/lsi/makeabi +++ b/src/lsi/makeabi @@ -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 <${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} diff --git a/src/lsi/mouse.c b/src/lsi/mouse.c index 8a743b0..9300e48 100644 --- a/src/lsi/mouse.c +++ b/src/lsi/mouse.c @@ -10,7 +10,7 @@ #include #include "vm.h" -#define MOUSEDEVICE "/dev/wsmouse" +#define MOUSEDEVICE "/dev/wsmouse1" char *events[] = { "undefined", diff --git a/src/lsi/plugins.c b/src/lsi/plugins.c index 1301165..5424896 100644 --- a/src/lsi/plugins.c +++ b/src/lsi/plugins.c @@ -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)); diff --git a/src/lsi/vm.c b/src/lsi/vm.c index 9f72b64..f482473 100644 --- a/src/lsi/vm.c +++ b/src/lsi/vm.c @@ -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()) {