This commit is contained in:
Stefan Bühler 2008-07-12 02:17:29 +02:00
parent 8246b97f56
commit 882d0ed4f7
6 changed files with 170 additions and 4 deletions

View File

@ -6,11 +6,14 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <poll.h>
static int opensocket(const char *hostname, const char *port) { static int opensocket(const char *hostname, const char *port) {
struct addrinfo *res = NULL, pref; struct addrinfo *res = NULL, pref;
int ret; int ret, s, val;
int s;
pref.ai_flags = 0; pref.ai_flags = 0;
pref.ai_family = PF_UNSPEC; pref.ai_family = PF_UNSPEC;
@ -35,9 +38,18 @@ static int opensocket(const char *hostname, const char *port) {
if (0 != connect(s, res->ai_addr, res->ai_addrlen)) { if (0 != connect(s, res->ai_addr, res->ai_addrlen)) {
fprintf(stderr, "Couldn't connect socket to '%s:%s': %s\n", hostname, port, strerror(errno)); fprintf(stderr, "Couldn't connect socket to '%s:%s': %s\n", hostname, port, strerror(errno));
freeaddrinfo(res); freeaddrinfo(res);
close(s);
return -1; return -1;
} }
val = 1;
if (0 != setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val))) {
fprintf(stderr, "Couldn't set socket option TCP_NODELAY: %s\n", strerror(errno));
freeaddrinfo(res);
close(s);
return -1;
}
freeaddrinfo(res); freeaddrinfo(res);
return s; return s;
} }
@ -82,10 +94,43 @@ void trial_wait_for_start(trial *t) {
} }
} }
static char buffer[16*1024];
void trial_check_input(trial *t) { void trial_check_input(trial *t) {
ssize_t len;
struct pollfd p;
p.fd = t->socket;
p.events = POLLIN;
switch (poll(&p, 1, 0)) {
case -1:
switch (errno) {
case EAGAIN:
case EINTR:
return;
}
fprintf(stderr, "poll error: %s\n", strerror(errno));
exit(127);
break;
case 0:
return;
}
len = read(t->socket, buffer, sizeof(buffer));
if (len < 0) {
fprintf(stderr, "read error: %s\n", strerror(errno));
exit(127);
}
g_string_append_len(t->parse_ctx->buffer, buffer, len);
control_parse(t);
} }
void trial_wait_for_input(trial *t) { void trial_wait_for_input(trial *t) {
ssize_t len = read(t->socket, buffer, sizeof(buffer));
if (len < 0) {
fprintf(stderr, "read error: %s\n", strerror(errno));
exit(127);
}
g_string_append_len(t->parse_ctx->buffer, buffer, len);
control_parse(t);
} }
void trial_free(trial *t) { void trial_free(trial *t) {

View File

@ -1,6 +1,8 @@
#ifndef _CONTROL_H #ifndef _CONTROL_H
#define _CONTROL_H #define _CONTROL_H
#include "config.h"
#include <unistd.h> #include <unistd.h>
#include <glib.h> #include <glib.h>
@ -29,7 +31,7 @@ typedef struct trial trial;
typedef unsigned int timestamp; typedef unsigned int timestamp;
#include "control_parser.h"
struct object { struct object {
object_t type; object_t type;
@ -67,6 +69,7 @@ struct trial {
/* internal */ /* internal */
int socket; int socket;
control_parser_ctx *parse_ctx;
}; };
/* trial */ /* trial */

26
src/control_parser.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef _CONTROL_PARSER_H
#define _CONTROL_PARSER_H
struct control_parser_ctx;
typedef struct control_parser_ctx control_parser_ctx;
typedef enum { RUN_ERROR, RUN_DONE, RUN_GO_ON } run_t;
#include "control.h"
struct control_parser_ctx {
int cs;
GString *buffer;
gsize read;
size_t mark;
GString *tmp;
double d;
};
void control_parser_new(trial *t);
void control_parser_reset(trial *t);
void control_parser_free(trial *t);
run_t control_parse(trial *t);
#endif

89
src/control_parser.rl Normal file
View File

@ -0,0 +1,89 @@
#include "control_parser.h"
#include <stdlib.h>
#include <stdio.h>
typedef control_parser_ctx context;
static void extract(context *ctx, char *fpc) {
gsize len = (fpc - ctx->buffer->str) - ctx->mark;
g_string_truncate(ctx->tmp, 0);
g_string_append_len(ctx->tmp, ctx->buffer->str + ctx->mark, len);
ctx->read += len;
}
%%{
machine control_parser;
variable cs ctx->cs;
action done { fbreak; }
action mark { ctx->mark = fpc - ctx->buffer->str; }
action parsedouble {
extract(ctx, fpc);
ctx->d = strtod(ctx->tmp->str, NULL);
}
sp = " ";
double = ( (digit | '.')* ) >mark %parsedouble;
init = "I" sp double sp double sp double sp double sp double sp double sp double sp double ";";
main := init @ done;
}%%
%% write data;
static int control_parser_has_error(context *ctx) {
return ctx->cs == control_parser_error;
}
static int control_parser_is_finished(context *ctx) {
return ctx->cs >= control_parser_first_final;
}
void control_parser_new(trial *t) {
context *ctx = t->parse_ctx = g_slice_new(context);
%% write init;
ctx->buffer = g_string_sized_new(0);
ctx->tmp = g_string_sized_new(0);
}
void control_parser_reset(trial *t) {
context *ctx = t->parse_ctx;
%% write init;
g_string_truncate(ctx->tmp, 0);
}
void control_parser_free(trial *t) {
g_string_free(t->parse_ctx->buffer, TRUE);
g_string_free(t->parse_ctx->tmp, TRUE);
g_slice_free(context, t->parse_ctx);
}
run_t control_parse(trial *t) {
context *ctx = t->parse_ctx;
gsize wehave;
if (0 < (wehave = ctx->buffer->len - ctx->read)) {
char *p, *pe;
p = ctx->buffer->str + ctx->read;
pe = p + wehave;
%% write exec;
g_string_erase(ctx->buffer, 0, ctx->read);
ctx->mark -= ctx->read;
ctx->read = 0;
}
if (control_parser_has_error(ctx)) {
fprintf(stderr, "Parse error\n");
return RUN_ERROR;
}
if (control_parser_is_finished(ctx)) return RUN_DONE;
return RUN_GO_ON;
}

View File

@ -6,6 +6,7 @@
main_source = ''' main_source = '''
main.c main.c
control.c control.c
control_parser.rl
''' '''
def build(bld): def build(bld):

View File

@ -78,6 +78,8 @@ def configure(conf):
incdir = conf.env['CPPPATH_glib'][0] incdir = conf.env['CPPPATH_glib'][0]
conf.env['CPPPATH_glib'] += [ incdir+'/glib-2.0/', incdir + '/glib-2.0/include/' ] conf.env['CPPPATH_glib'] += [ incdir+'/glib-2.0/', incdir + '/glib-2.0/include/' ]
CHECK_INCLUDE_FILES(conf, "glib.h", "HAVE_GLIB_H", uselib = 'glib', use = ['glib'], mandatory = 1) CHECK_INCLUDE_FILES(conf, "glib.h", "HAVE_GLIB_H", uselib = 'glib', use = ['glib'], mandatory = 1)
conf.write_config_header('src/config.h')
def build(bld): def build(bld):