The unified diff between revisions [76aea49e..] and [e36d05ae..] is displayed below. It can also be downloaded as a raw diff.
# # old_revision [76aea49e8393c839b573eaac31eb8e2fb218d2d6] # new_revision [e36d05aec1b58ab05b8602bed8ed5faf304fe45f] # # add_file "src/lsi/cmdsocket.c" # content [855bbabd21448d3ac37ff460a412a951df7d226a] # # add_file "src/lsi/cmdsocket.h" # content [dd5bddfcec81de17a358ae36f8e2626e68430728] # # patch "src/lsc/codegen.c" # from [54841dc0395a35f38eeef2e81231366c4fed3015] # to [eadf986764263a936e4e1daa589e245ccee66212] # # patch "src/lsc/lexer.l" # from [c84e522ab7268008c572c8d1670438471d7287e1] # to [88be4de3325822fc6a95e81cc8c615a6c70078bf] # # patch "src/lsi/Makefile" # from [c00858097a6f271fbfea57ba936c38008c8d78dd] # to [3789100d1e544eb9428454484202427625f9e0c2] # # patch "src/lsi/abi.h" # from [5baace9e64fed6a7cb0eb3af2c188604cca63811] # to [2f5c3543b8ced2defbc5a1bea94b29392c7ee5b1] # # patch "src/lsi/abispec" # from [b0c3b84bd74ecfc93d8077780b8fd4e7a4bc569c] # to [bf8a0325aba2e8dd563c0c9dc0358989f130e20d] # # patch "src/lsi/mouse.c" # from [9a2d9211ec57222cfa1f1d2ef9749e698445d0e7] # to [410738f63d15db286b591fff6040fcdfe9e1cfa6] # # patch "src/lsi/plugins.c" # from [0f20069da015e07f58b0828acdc3644a197dc794] # to [d1249e7348b4b02e2405e3374b7e6609ff982875] # # patch "src/lsi/vm.c" # from [2f4df836fac21746563e434768e4f832c1ea3e15] # to [f74e79e92252eafbcbc81d3ee4ca5e2e3c79f4a9] # # patch "src/lsi/vm.h" # from [6ad84b9f243d5acff4ddeca82fc4a96caeb0930a] # to [4e84a410186bc2516c890aaedd6b6c3705d1f30a] # ============================================================ --- src/lsc/codegen.c 54841dc0395a35f38eeef2e81231366c4fed3015 +++ src/lsc/codegen.c eadf986764263a936e4e1daa589e245ccee66212 @@ -140,7 +140,7 @@ void output_functions_action(struct hash pad = (4 - (len % 4)) % 4; output_int(len+pad); output_int(0); /* type */ - output_int(get_label(ptr->value) + 8); + output_int(get_label(ptr->value) + 28); output_int(0); /* nargs */ output_string(ptr->name); output_byte(0); /* terminator */ @@ -1267,6 +1267,7 @@ void output_code(void) if (!lookup_constant_string(x, &abiver)) \ printf("%s not defined\n", x); \ output_int(abiver); \ + printf("ABIVERSION(%s) = %x\n", x, abiver); \ } while (0) pc = (pc + 3) & ~3; /* Align table */ ============================================================ --- src/lsc/lexer.l c84e522ab7268008c572c8d1670438471d7287e1 +++ src/lsc/lexer.l 88be4de3325822fc6a95e81cc8c615a6c70078bf @@ -105,8 +105,10 @@ return return TOKRETURN; [0-9]+ yylval.Tinteger = atoi(yytext); return NUMBER; -[0-9]+ yylval.Tinteger = atoi(yytext); return NUMBER; -0x[0-9]+ yylval.Tinteger = strtol(yytext+2, (char **)NULL, 16); return NUMBER; --0x[0-9]+ yylval.Tinteger = strtol(yytext+2, (char **)NULL, 16); return NUMBER; + /* Cater for the possibility that things might be signed or + unsigned. This is horrible and ugly, but might just work. */ +0x[0-9a-fA-F]+ yylval.Tinteger = strtoul(yytext+2, (char **)NULL, 16); return NUMBER; +-0x[0-9a-fA-F]+ yylval.Tinteger = strtol(yytext+2, (char **)NULL, 16); return NUMBER; [0-9]+\.[0-9]+ yylval.Treal = atof(yytext); return REAL; -[0-9]+\.[0-9]+ yylval.Treal = atof(yytext); return REAL; [_a-zA-Z0-9]+ yylval.Tstring = strdup(yytext); return IDENTIFIER; ============================================================ --- src/lsi/Makefile c00858097a6f271fbfea57ba936c38008c8d78dd +++ src/lsi/Makefile 3789100d1e544eb9428454484202427625f9e0c2 @@ -2,8 +2,10 @@ 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 -SRCS= main.c vm.c plugins.c dmx.c midi.c beatdetect.c fft.c map3d.c mouse.c +OBJS= main.o vm.o plugins.o dmx.o midi.o beatdetect.o fft.o map3d.o mouse.o \ + cmdsocket.o +SRCS= main.c vm.c plugins.c dmx.c midi.c beatdetect.c fft.c map3d.c mouse.c \ + cmdsocket.c OBJS+= abi.o SRCS+= abi.c ============================================================ --- src/lsi/abi.h 5baace9e64fed6a7cb0eb3af2c188604cca63811 +++ src/lsi/abi.h 2f5c3543b8ced2defbc5a1bea94b29392c7ee5b1 @@ -44,3 +44,7 @@ int vm_intfn_mouse_read(void); int vm_intfn_cos(void); int vm_intfn_random(void); int vm_intfn_mouse_read(void); +int vm_intfn_cmdsocket_listen(void); +int vm_intfn_cmdsocket_accept(void); +int vm_intfn_cmdsocket_read(void); +int vm_intfn_cmdsocket_prefix(void); ============================================================ --- src/lsi/abispec b0c3b84bd74ecfc93d8077780b8fd4e7a4bc569c +++ src/lsi/abispec bf8a0325aba2e8dd563c0c9dc0358989f130e20d @@ -33,6 +33,10 @@ function mouse_read function cos function random function mouse_read +function cmdsocket_listen +function cmdsocket_accept +function cmdsocket_read +function cmdsocket_prefix /* * The ABI should be identified by a SHA1 hash of this file ============================================================ --- /dev/null +++ src/lsi/cmdsocket.c 855bbabd21448d3ac37ff460a412a951df7d226a @@ -0,0 +1,204 @@ +/* cmdsocket.c */ + +#include <sys/time.h> +#include <dev/wscons/wsconsio.h> + +#include <fcntl.h> +#include <unistd.h> +#include <err.h> +#include <errno.h> +#include <stdio.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <string.h> +#include <stdlib.h> +#include "vm.h" + +#define PORT 15674 +#define CMD_MAXSIZE 1024 +#define PREFIX_MAXSIZE 1024 + +#define CMDSOCKET_BANNER "lightscript cmdsocket ready\r\n" + +int cmd_sock = 0; +int cmd_active = 0; +int cmd_ignore; +int cmd_bytes; +int cmdsocket_initialised = 0; +char cmd_buf[CMD_MAXSIZE]; +char cmd_prefix[PREFIX_MAXSIZE]; + +int cmdsocket_init(void) +{ + cmdsocket_initialised = 1; + cmd_bytes = 0; + cmd_ignore = 0; + cmd_prefix[0] = '\0'; + + return 1; +} + +void cmdsocket_close(void) +{ + if (cmd_active) + close(cmd_active); + if (cmd_sock) + close(cmd_sock); + cmdsocket_initialised = 0; +} + +void cmdsocket_prefix(char *prefix) +{ + if (!cmdsocket_initialised) + return; + if (strlen(prefix) >= PREFIX_MAXSIZE-1) + return; + strncpy(cmd_prefix, prefix, PREFIX_MAXSIZE); +} + +#define ERROR(x) do { warn((x)); goto error; } while (0) + +#define BACKLOG 0 + +int cmdsocket_listen(int port) { + int sockopt_on = 1; + struct sockaddr_in my_addr; + + cmd_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (cmd_sock == -1) + ERROR("can't open socket"); + if (setsockopt(cmd_sock, SOL_SOCKET, SO_REUSEADDR, &sockopt_on, + sizeof(int)) == -1) + ERROR("can't set socket options"); + memset((char *) &my_addr, 0, sizeof(my_addr)); + my_addr.sin_family = PF_INET; + my_addr.sin_port = htons(port); + my_addr.sin_addr.s_addr = htonl(INADDR_ANY); + if (bind(cmd_sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1) + ERROR("can't bind socket"); + if (listen(cmd_sock, BACKLOG) == -1) + ERROR("can't listen"); + vm_register_signal_fd(cmd_sock, VM_CMDLISTENQ); + + return 1; + +error: + if (cmd_sock) + close(cmd_sock); + cmd_sock = 0; + return 0; +} + + +int cmdsocket_accept(void) { + struct sockaddr_in client_addr; + socklen_t client_addr_size = sizeof(client_addr); + int c; + + if (!cmdsocket_initialised) + return 0; + if (cmd_sock == 0) + return 0; + + /* We only accept one active connection at a time */ + /* XXX can't just return here */ + if (cmd_active) + return 0; + + c = accept(cmd_sock, (struct sockaddr *)&client_addr, + &client_addr_size); + if (c == -1) { + if (errno == EAGAIN) + return 0; + warn("Error accepting connection"); + close(cmd_sock); + cmd_sock = 0; + return 0; + } + + cmd_active = c; + write(cmd_active, CMDSOCKET_BANNER, sizeof(CMDSOCKET_BANNER)); + + vm_register_signal_fd(cmd_active, VM_CMDREADQ); + vm_wakeup(VM_CMDREADQ); + return 1; +} + +void cmd_parse(char *cmd) { + char *sp; + int arg = 0; + char function[CMD_MAXSIZE + PREFIX_MAXSIZE]; + + *strchr(cmd, '\n') = '\0'; + printf("DEBUG: Received command: %s\n", cmd); + fflush(stdout); + + sp = strtok(cmd, " \t\r"); + sp = strtok(NULL, " \t\r"); + if (sp) { + arg = atoi(sp); + } + + /* cmd_prefix is guaranteed to be terminated */ + strcpy(function, cmd_prefix); + strncat(function, cmd, CMD_MAXSIZE); + + printf("DEBUG: function: %s, arg %d\n", function, arg); + fflush(stdout); + if (vm_spawn_args(function, 1, arg)) { + /* Write an ack here, once a proper function exists */ + } else { + /* Write an error, if it's possible. Don't worry about + missing characters and buffering for now, but we + should eventually */ + write(cmd_active, "ERROR\n", strlen("ERROR\n")); + } + + printf("Received command: %s\n", cmd); +} + +int cmdsocket_read(void) +{ + if (!cmdsocket_initialised) + return 0; + + while (1) { + int rv; + int left = sizeof(cmd_buf) - cmd_bytes; + char *p; + if (!cmd_active) + return 0; + + rv = recv(cmd_active, ((char *)&cmd_buf) + cmd_bytes, left, 0); + if (rv == -1) { + if (errno == EAGAIN) + return 0; + printf("Error reading from socket\n"); + vm_unregister_signal_fd(cmd_active); + close(cmd_active); + cmd_active = 0; + vm_wakeup(VM_CMDLISTENQ); + return 0; + } + if (rv == 0) { + vm_unregister_signal_fd(cmd_active); + close(cmd_active); + cmd_active = 0; + vm_wakeup(VM_CMDLISTENQ); + return 0; + } + cmd_bytes += rv; + if ((p = memchr(cmd_buf, '\n', cmd_bytes))) { + if (!cmd_ignore) + cmd_parse(cmd_buf); + memmove(cmd_buf, p+1, cmd_bytes - (p - cmd_buf - 1)); + cmd_bytes = 0; + cmd_ignore = 0; + } + if (cmd_bytes == sizeof(cmd_buf)) { + cmd_bytes = 0; + cmd_ignore = 1; + /* Overflow */ + } + } +} ============================================================ --- /dev/null +++ src/lsi/cmdsocket.h dd5bddfcec81de17a358ae36f8e2626e68430728 @@ -0,0 +1,8 @@ +/* cmdsocket.h */ + +int cmdsocket_init(void); +void cmdsocket_close(void); +int cmdsocket_listen(int port); +int cmdsocket_accept(void); +int cmdsocket_read(void); +int cmdsocket_prefix(char *); ============================================================ --- src/lsi/mouse.c 9a2d9211ec57222cfa1f1d2ef9749e698445d0e7 +++ src/lsi/mouse.c 410738f63d15db286b591fff6040fcdfe9e1cfa6 @@ -55,6 +55,7 @@ int mouse_init(void) mouse_x = 0; mouse_y = 0; mouse_z = 0; + mouse_bytes = 0; mouse_fd = open(MOUSEDEVICE, O_RDONLY); if (mouse_fd < 0) { ============================================================ --- src/lsi/plugins.c 0f20069da015e07f58b0828acdc3644a197dc794 +++ src/lsi/plugins.c d1249e7348b4b02e2405e3374b7e6609ff982875 @@ -11,12 +11,14 @@ #include "dmx.h" #include "beatdetect.h" #include "mouse.h" +#include "cmdsocket.h" struct plugin plugins_table[] = { {"midi", midi_init, midi_close, 0}, {"dmx", dmx_init, dmx_close, 0}, {"beatdetect", beatdetect_init, beatdetect_close, 0}, {"mouse", mouse_init, mouse_close, 0}, + {"cmdsocket", cmdsocket_init, cmdsocket_close, 0}, }; int nplugins = (sizeof(plugins_table) / sizeof(struct plugin)); ============================================================ --- src/lsi/vm.c 2f4df836fac21746563e434768e4f832c1ea3e15 +++ src/lsi/vm.c f74e79e92252eafbcbc81d3ee4ca5e2e3c79f4a9 @@ -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,7 @@ #include "beatdetect.h" #include "map3d.h" #include "mouse.h" +#include "cmdsocket.h" #define DEBUG 0 @@ -41,6 +43,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 +60,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]; @@ -418,6 +424,46 @@ 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_beatdetect_read(void) { if (!beatdetect_read()) { @@ -570,6 +616,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) @@ -673,10 +720,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) { @@ -705,6 +753,12 @@ int vm_spawn(char *fn) /* Push return address here, to point to some special thread exit routine */ + /* Push optional arguments */ + va_start(ap, n); + while (n--) + stack_push(newt, va_arg(ap, int)); + va_end(ap); + stack_push(newt, 0); /* Return value */ stack_push(newt, 0); /* Return address */ @@ -712,15 +766,26 @@ int vm_spawn(char *fn) 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) @@ -757,18 +822,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)) @@ -791,6 +857,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++; ============================================================ --- src/lsi/vm.h 6ad84b9f243d5acff4ddeca82fc4a96caeb0930a +++ src/lsi/vm.h 4e84a410186bc2516c890aaedd6b6c3705d1f30a @@ -3,8 +3,11 @@ int vm_spawn(char *); void vm_init(void); void vm_load(char *); int vm_spawn(char *); +int vm_spawn_args(char *, int, ...); void vm_run(void); void vm_register_signal_fd(int /* fd */, int /* queue */); +void vm_unregister_signal_fd(int /* fd */); +void vm_wakeup(int queue); #define VM_MAXQUEUES 512 #define VM_RUNQ 0 @@ -13,8 +16,9 @@ void vm_register_signal_fd(int /* fd */, #define VM_MOUSEQ 6 #define VM_BEATQ 7 #define VM_MIDIQ 8 -#define VM_SOCKQ 9 +#define VM_CMDLISTENQ 9 +#define VM_CMDREADQ 10 -#define VM_USERQMIN 10 +#define VM_USERQMIN 20 #define VM_NOQUEUE (-1)