Parser
This commit is contained in:
parent
8246b97f56
commit
882d0ed4f7
@ -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) {
|
||||||
|
@ -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
26
src/control_parser.h
Normal 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
89
src/control_parser.rl
Normal 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;
|
||||||
|
}
|
@ -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):
|
||||||
|
2
wscript
2
wscript
@ -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):
|
||||||
|
Loading…
Reference in New Issue
Block a user