Browse Source

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

for internal functions, and returning values from functions in the compiler.
master
Gavan Fantom 17 years ago
parent
commit
df2e38a3e9
  1. 19
      src/lsc/ast.c
  2. 3
      src/lsc/ast.h
  3. 40
      src/lsc/codegen.c
  4. 1
      src/lsc/lexer.l
  5. 14
      src/lsc/parser.y
  6. 4
      src/lsc/types.h
  7. 11
      src/lsi/Makefile
  8. 2
      src/lsi/abi.h
  9. 3
      src/lsi/abispec
  10. 9
      src/lsi/makeabi
  11. 2
      src/lsi/mouse.c
  12. 2
      src/lsi/plugins.c
  13. 116
      src/lsi/vm.c

19
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;

3
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 *);

40
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;

1
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;

14
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 <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:
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:

4
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,

11
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}\//}

2
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);

3
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

9
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 <<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}

2
src/lsi/mouse.c

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

2
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));

116
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()) {

Loading…
Cancel
Save