First cut at sql support via sqlite3. Including preliminary varargs support

for internal functions, and returning values from functions in the compiler.
This commit is contained in:
2007-12-24 11:18:15 +00:00
parent 8251351a2e
commit df2e38a3e9
13 changed files with 207 additions and 19 deletions

View File

@@ -110,6 +110,21 @@ ast *make_fndefint(char *identifier, long num)
return elem; 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 *make_constant(char *identifier, long num)
{ {
ast *elem = safe_malloc(sizeof(ast)); ast *elem = safe_malloc(sizeof(ast));
@@ -297,13 +312,13 @@ ast *make_case_statement_number(long num)
return elem; return elem;
} }
ast *make_return_statement(void) ast *make_return_statement(ast *expression)
{ {
ast *elem = safe_malloc(sizeof(ast)); ast *elem = safe_malloc(sizeof(ast));
elem->tag = node_ast; elem->tag = node_ast;
elem->info.node.tag = stmt_return; elem->info.node.tag = stmt_return;
elem->info.node.head = NULL; elem->info.node.head = make_list(expression, NULL);
elem->lineno = yylineno; elem->lineno = yylineno;
return elem; return elem;

View File

@@ -5,6 +5,7 @@ ast_list *reverse_list(ast_list *);
ast *make_list_node(ast_list *); ast *make_list_node(ast_list *);
ast *make_function(char *, ast_list *, ast_list *); ast *make_function(char *, ast_list *, ast_list *);
ast *make_fndefint(char *, long); ast *make_fndefint(char *, long);
ast *make_fndefint_v(char *, long);
ast *make_constant(char *, long); ast *make_constant(char *, long);
ast *make_realconstant(char *, float); ast *make_realconstant(char *, float);
ast *make_fndefext(char *); ast *make_fndefext(char *);
@@ -22,6 +23,6 @@ ast *make_case_statement_number(long);
ast *make_case_statement_variable(char *); ast *make_case_statement_variable(char *);
ast *make_break_statement(); ast *make_break_statement();
ast *make_default_statement(); ast *make_default_statement();
ast *make_return_statement(); ast *make_return_statement(ast *);
void ast_dump(ast *); void ast_dump(ast *);

View File

@@ -95,10 +95,14 @@ struct instr *instr_tail = NULL;
#define VAR_ARG 1 #define VAR_ARG 1
#define VAR_REAL 2 #define VAR_REAL 2
#define FN_TYPE_BASE 0xff
#define FN_INT 1 #define FN_INT 1
#define FN_STR 2 #define FN_STR 2
#define FN_LOCAL 3 #define FN_LOCAL 3
#define FN_VARARGS 0x100
int fnconst; int fnconst;
int nargs; int nargs;
int local_variable_count = -1; int local_variable_count = -1;
@@ -146,7 +150,7 @@ void output_functions_action(struct hashentry *ptr)
{ {
int len, pad; int len, pad;
if (ptr->flags == FN_LOCAL) { if ((ptr->flags & FN_TYPE_BASE) == FN_LOCAL) {
len = strlen(ptr->name) + 1 + 16; len = strlen(ptr->name) + 1 + 16;
pad = (4 - (len % 4)) % 4; pad = (4 - (len % 4)) % 4;
output_int(len+pad); output_int(len+pad);
@@ -311,7 +315,7 @@ void create_function(char *fnname, int type, int num)
compiler_error("Function already exists"); compiler_error("Function already exists");
if (output_asm) { if (output_asm) {
switch (type) { switch (type & FN_TYPE_BASE) {
case FN_INT: case FN_INT:
printf("%%fnint %s %d\n", fnname, num); printf("%%fnint %s %d\n", fnname, num);
break; break;
@@ -644,12 +648,14 @@ void codegen(ast *node)
case node_ast: case node_ast:
switch (node->info.node.tag) { switch (node->info.node.tag) {
case kind_fndefint: case kind_fndefint:
case kind_fndefint_v:
assert(sp == 0); assert(sp == 0);
assert(node->info.node.head != NULL); assert(node->info.node.head != NULL);
assert(node->info.node.head->next != NULL); assert(node->info.node.head->next != NULL);
create_function(node->info.node.head->elem->info.string, 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); node->info.node.head->next->elem->info.integer);
break; break;
case kind_constant: case kind_constant:
@@ -771,20 +777,36 @@ void codegen(ast *node)
// printf("savedsp = %d\n", savedsp); // printf("savedsp = %d\n", savedsp);
nargs = 0;
/* Evaluate the arguments first */ /* Evaluate the arguments first */
for (ptr = for (ptr =
node->info.node.head->next->elem->info.node.head; node->info.node.head->next->elem->info.node.head;
ptr; ptr = ptr->next) { ptr; ptr = ptr->next) {
codegen(ptr->elem); codegen(ptr->elem);
nargs++;
} }
// printf("sp = %d\n", sp); // 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); emit_instr_immediate(OP_ALLOC, 1);
sp++; sp++;
if (!lookup_function(node->info.node.head->elem, &fn))
compiler_error("Function not found");
switch (fn.type) { switch (fn.type) {
case FN_INT: case FN_INT:
emit_instr_immediate(OP_CALLNUM, fn.num); emit_instr_immediate(OP_CALLNUM, fn.num);
@@ -1147,8 +1169,12 @@ void codegen(ast *node)
emit_instr_label(OP_B, breaklabel); emit_instr_label(OP_B, breaklabel);
break; break;
case stmt_return: 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_instr_imm_const(OP_POP, sp, fnconst);
emit_simple_instr(OP_RET); emit_simple_instr(OP_RET);
break; break;

View File

@@ -86,6 +86,7 @@ char *string_buf_ptr;
function return TOKFUNCTION; function return TOKFUNCTION;
fndefint return TOKFNDEFINT; fndefint return TOKFNDEFINT;
fndefint_v return TOKFNDEFINT_V;
fndefext return TOKFNDEFEXT; fndefext return TOKFNDEFEXT;
constant return TOKCONSTANT; constant return TOKCONSTANT;
while return TOKWHILE; while return TOKWHILE;

View File

@@ -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 TOKWHILE TOKIF TOKELSE TOKSWITCH TOKCASE TOKDEFAULT
%token TOKBREAK TOKRETURN TOKEQ TOKNE TOKAND TOKOR STRING %token TOKBREAK TOKRETURN TOKEQ TOKNE TOKAND TOKOR STRING
@@ -86,6 +86,7 @@ int main(int argc, char *argv[])
%type <Tast> fndefint %type <Tast> fndefint
%type <Tast> fndefext %type <Tast> fndefext
%type <Tast> statement %type <Tast> statement
%type <Tast> fndefint_v
%type <Tast> assignment %type <Tast> assignment
%type <Tast> expression %type <Tast> expression
%type <Tast> realconstant %type <Tast> realconstant
@@ -142,6 +143,7 @@ fn_list:
fn_list_inner: fn_list_inner:
fn_list_inner function { $$ = make_list($2, $1); } fn_list_inner function { $$ = make_list($2, $1); }
| fn_list_inner fndefint { $$ = 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 fndefext { $$ = make_list($2, $1); }
| fn_list_inner constant { $$ = make_list($2, $1); } | fn_list_inner constant { $$ = make_list($2, $1); }
| fn_list_inner realconstant { $$ = make_list($2, $1); } | fn_list_inner realconstant { $$ = make_list($2, $1); }
@@ -158,6 +160,11 @@ fndefint:
{ $$ = make_fndefint($2, $3); } { $$ = make_fndefint($2, $3); }
; ;
fndefint_v:
TOKFNDEFINT_V IDENTIFIER NUMBER ';'
{ $$ = make_fndefint_v($2, $3); }
;
constant: constant:
TOKCONSTANT IDENTIFIER NUMBER ';' TOKCONSTANT IDENTIFIER NUMBER ';'
{ $$ = make_constant($2, $3); } { $$ = make_constant($2, $3); }
@@ -319,8 +326,11 @@ statement_case:
; ;
statement_return: statement_return:
TOKRETURN expression
{ $$ = make_return_statement($2); }
|
TOKRETURN TOKRETURN
{ $$ = make_return_statement(); } { $$ = make_return_statement(NULL); }
; ;
statement_break: statement_break:

View File

@@ -2,8 +2,8 @@
typedef enum { typedef enum {
kind_fndef, kind_fndefint, kind_fndefext, kind_constant, kind_fndef, kind_fndefint, kind_fndefint_v, kind_fndefext,
kind_assign, kind_list, kind_call, kind_array, kind_constant, kind_assign, kind_list, kind_call, kind_array,
op_plus, op_minus, op_times, op_divide, op_plus, op_minus, op_times, op_divide,
op_gt, op_lt, op_ge, op_le, op_eq, op_ne, op_gt, op_lt, op_ge, op_le, op_eq, op_ne,

View File

@@ -3,9 +3,9 @@
PREFIX?= /usr/local PREFIX?= /usr/local
OBJS= main.o vm.o plugins.o dmx.o midi.o beatdetect.o fft.o map3d.o mouse.o \ 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 \ 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 OBJS+= abi.o
SRCS+= abi.c SRCS+= abi.c
@@ -14,10 +14,13 @@ COMMONOBJS= mem.o hash.o
COMMONDIR= ../common COMMONDIR= ../common
INCDIR= ../include INCDIR= ../include
SQLITEINCDIR= /usr/pkg/include
SQLITELIBDIR= /usr/pkg/lib
CFLAGS+= -Wall -Werror CFLAGS+= -Wall -Werror
CPPFLAGS+= -I${INCDIR} CPPFLAGS+= -I${INCDIR} -I${SQLITEINCDIR}
LDLIBS+= -lm LDFLAGS+= -L${SQLITELIBDIR} -Wl,-R${SQLITELIBDIR}
LDLIBS+= -lm -lsqlite3
PROGOBJS= ${OBJS} ${COMMONOBJS:S/^/${COMMONDIR}\//} PROGOBJS= ${OBJS} ${COMMONOBJS:S/^/${COMMONDIR}\//}

View File

@@ -49,3 +49,5 @@ int vm_intfn_cmdsocket_accept(void);
int vm_intfn_cmdsocket_read(void); int vm_intfn_cmdsocket_read(void);
int vm_intfn_cmdsocket_write(void); int vm_intfn_cmdsocket_write(void);
int vm_intfn_cmdsocket_prefix(void); int vm_intfn_cmdsocket_prefix(void);
int vm_intfn_sql_query(void);
int vm_intfn_sql_query_1s(void);

View File

@@ -38,6 +38,9 @@ function cmdsocket_accept
function cmdsocket_read function cmdsocket_read
function cmdsocket_write function cmdsocket_write
function cmdsocket_prefix 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 * The ABI should be identified by a SHA1 hash of this file

View File

@@ -37,6 +37,13 @@ do_function()
FNCOUNT=$((${FNCOUNT}+1)) FNCOUNT=$((${FNCOUNT}+1))
} }
do_function_v()
{
echo " vm_intfn_${ARG1}," >>${ABI}
echo "fndefint_v ${ARG1} ${FNCOUNT};" >>${HEADER}
FNCOUNT=$((${FNCOUNT}+1))
}
cat <<EOF >${ABI} cat <<EOF >${ABI}
/* abi.c */ /* abi.c */
/* autogenerated - do not edit */ /* autogenerated - do not edit */
@@ -69,6 +76,8 @@ do
case "$TYPE" in case "$TYPE" in
function) do_function function) do_function
;; ;;
function_v) do_function_v
;;
esac esac
done <${INFILE} done <${INFILE}

View File

@@ -10,7 +10,7 @@
#include <stdio.h> #include <stdio.h>
#include "vm.h" #include "vm.h"
#define MOUSEDEVICE "/dev/wsmouse" #define MOUSEDEVICE "/dev/wsmouse1"
char *events[] = { char *events[] = {
"undefined", "undefined",

View File

@@ -12,6 +12,7 @@
#include "beatdetect.h" #include "beatdetect.h"
#include "mouse.h" #include "mouse.h"
#include "cmdsocket.h" #include "cmdsocket.h"
#include "sql.h"
struct plugin plugins_table[] = { struct plugin plugins_table[] = {
{"midi", midi_init, midi_close, 0}, {"midi", midi_init, midi_close, 0},
@@ -19,6 +20,7 @@ struct plugin plugins_table[] = {
{"beatdetect", beatdetect_init, beatdetect_close, 0}, {"beatdetect", beatdetect_init, beatdetect_close, 0},
{"mouse", mouse_init, mouse_close, 0}, {"mouse", mouse_init, mouse_close, 0},
{"cmdsocket", cmdsocket_init, cmdsocket_close, 0}, {"cmdsocket", cmdsocket_init, cmdsocket_close, 0},
{"sql", sql_init, sql_close, 0},
}; };
int nplugins = (sizeof(plugins_table) / sizeof(struct plugin)); int nplugins = (sizeof(plugins_table) / sizeof(struct plugin));

View File

@@ -23,6 +23,7 @@
#include "map3d.h" #include "map3d.h"
#include "mouse.h" #include "mouse.h"
#include "cmdsocket.h" #include "cmdsocket.h"
#include "sql.h"
#define DEBUG 0 #define DEBUG 0
@@ -482,6 +483,121 @@ int vm_intfn_cmdsocket_write(void)
return 1; 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) int vm_intfn_beatdetect_read(void)
{ {
if (!beatdetect_read()) { if (!beatdetect_read()) {