oop_source *events;
FILE *dump_stream= 0;
-typedef struct OutBuffer OutBuffer;
-struct OutBuffer {
- OutBuffer *back, *next;
- char *m;
- int l;
-};
-typedef struct OutBufferChain OutBufferChain;
-struct OutBufferChain {
- const char *what;
- int fd;
- int done_of_head;
- struct { OutBuffer *head, *tail; } obs;
-};
-static OutBufferChain stdin_ochain= { "stdin", 0 };
-static OutBufferChain serial_ochain= { "serial", -1 };
+static void serial_error(OutBufferChain *ch, const char *e1, const char *e2) {
+ abort();
+}
+
+static void stdin_error(OutBufferChain *ch, const char *e1, const char *e2) {
+ if (!e1)
+ exit(0);
+ fprintf(stderr,"stdin: %s: %s\n", e1, e2);
+ exit(12);
+}
+
+static OutBufferChain serial_ochain= { (char*)"serial", -1, serial_error };
+static Client stdin_client= { { (char*)"stdin", 0, stdin_error } };
static void *ochain_writeable(oop_source *evts, int fd,
oop_event evt, void *ch_v) {
ob= ch->obs.head;
if (!ob) {
events->cancel_fd(events, fd, OOP_WRITE);
- events->cancel_fd(events, fd, OOP_EXCEPTION);
return OOP_CONTINUE;
}
if (ch->done_of_head == ob->l) {
if (r==-1) {
if (errno==EINTR) continue;
if (errno==EWOULDBLOCK) return OOP_CONTINUE;
- diee(ch->what);
+ ch->error(ch,"write",strerror(errno));
}
assert(r>=0);
ch->done_of_head += r;
}
}
-static void *ochain_exception(oop_source *evts, int fd,
- oop_event evt, void *ch_v) {
- OutBufferChain *ch= ch_v;
- die(ch->what);
+static void *client_exception(oop_source *evts, int fd,
+ oop_event evt, void *cl_v) {
+ Client *cl= cl_v;
+ cl->ch.error(&cl->ch,"comms error","exception");
+ return OOP_CONTINUE;
+}
+
+static void *serial_exception(oop_source *evts, int fd,
+ oop_event evt, void *cl_v) {
+ die("serial port - exception");
}
static void ochain_addlink(OutBufferChain *ch, OutBuffer *ob) {
- if (!ch->obs.head) {
+ if (!ch->obs.head)
events->on_fd(events, ch->fd, OOP_WRITE, ochain_writeable, ch);
- events->on_fd(events, ch->fd, OOP_EXCEPTION, ochain_exception, ch);
- }
LIST_LINK_TAIL(ch->obs, ob);
}
-static void ovprintf(const char *fmt, va_list al)
- __attribute__((format(printf,1,0)));
-static void ovprintf(const char *fmt, va_list al) {
+static void ovprintf(OutBufferChain *ch, const char *fmt, va_list al)
+ __attribute__((format(printf,2,0)));
+static void ovprintf(OutBufferChain *ch, const char *fmt, va_list al) {
OutBuffer *ob;
ob= malloc(sizeof(*ob)); if (!ob) diem();
ob->l= vasprintf(&ob->m, fmt, al); if (ob->l <= 0) diem();
- ochain_addlink(&stdin_ochain, ob);
+ ochain_addlink(&stdin_client.ch, ob);
}
-static void oprintf(const char *msg, ...) __attribute__((format(printf,1,2)));
-static void oprintf(const char *msg, ...) {
+static void oprintf(OutBufferChain *ch, const char *msg, ...)
+ __attribute__((format(printf,2,3)));
+static void oprintf(OutBufferChain *ch, const char *msg, ...) {
va_list al;
va_start(al,msg);
- ovprintf(msg,al);
+ ovprintf(ch,msg,al);
va_end(al);
}
-static void badcmd(const char *how) {
- oprintf("error %s\n",how);
+static void badcmd(ParseState *ps, const char *how) {
+ oprintf(&ps->cl->ch,"error %s\n",how);
}
static void cmd_noop(ParseState *ps, const CmdInfo *ci) {
- oprintf("noop successful\n");
+ oprintf(&ps->cl->ch,"noop successful\n");
}
static const CmdInfo toplevel_cmds[]= {
static int ps_needword(ParseState *ps) {
const char *space;
- if (!ps->remain) { badcmd("too few args"); return 0; }
+ if (!ps->remain) { badcmd(ps,"too few args"); return 0; }
space= strchr(ps->remain, ' ');
ps->thisword= ps->remain;
if (space) {
return ps_lookup(ps,infs);
}
-static void *stdin_iferr(oop_source *evts, oop_read *stdin_read,
- oop_rd_event evt, const char *errmsg, int errnoval,
- const char *data, size_t recsz, void *u0)
- __attribute__((noreturn));
-static void *stdin_iferr(oop_source *evts, oop_read *stdin_read,
- oop_rd_event evt, const char *errmsg, int errnoval,
- const char *data, size_t recsz, void *u0) {
- fprintf(stderr,"stdin %s\n",
- oop_rd_errmsg(stdin_read, evt, errnoval, OOP_RD_STYLE_GETLINE));
- exit(4);
+static void *client_iferr(oop_source *evts, oop_read *cl_read,
+ oop_rd_event evt, const char *errmsg, int errnoval,
+ const char *data, size_t recsz, void *cl_v) {
+ Client *cl= cl_v;
+
+ cl->ch.error(&cl->ch, "read",
+ oop_rd_errmsg(cl_read, evt,
+ errnoval, OOP_RD_STYLE_GETLINE));
+ return OOP_CONTINUE;
}
-static void *stdin_ifok(oop_source *evts, oop_read *stdin_read,
- oop_rd_event evt, const char *errmsg, int errnoval,
- const char *data, size_t recsz, void *u0) {
+static void *client_ifok(oop_source *evts, oop_read *cl_read,
+ oop_rd_event evt, const char *errmsg, int errnoval,
+ const char *data, size_t recsz, void *cl_v) {
+ Client *cl= cl_v;
ParseState ps;
const CmdInfo *ci;
- if (evt == OOP_RD_EOF)
- exit(0);
- if (evt != OOP_RD_OK)
- stdin_iferr(evts,stdin_read,evt,errmsg,errnoval,data,recsz,u0);
+ if (evt == OOP_RD_EOF) {
+ cl->ch.error(&cl->ch,0,0);
+ return OOP_CONTINUE;
+ }
+ if (evt != OOP_RD_OK)
+ return client_iferr(evts,cl_read,evt,errmsg,errnoval,data,recsz,cl_v);
+
+ ps.cl= cl;
ps.remain= data;
ci= ps_needword_lookup(&ps, toplevel_cmds);
- if (!ci) { badcmd("unknown command"); return OOP_CONTINUE; }
+ if (!ci) { badcmd(&ps,"unknown command"); return OOP_CONTINUE; }
ci->fn(&ps,ci);
return OOP_CONTINUE;
}
stdin_source= oop_rd_new_fd(events, 0, 0,0);
if (!stdin_source) diee("oop_rd_new_fd(,0,,)");
r= oop_rd_read(stdin_source, OOP_RD_STYLE_GETLINE, 1024,
- stdin_ifok, 0, stdin_iferr, 0);
+ client_ifok, 0, client_iferr, 0);
if (r) diee("oop_rd_read(stdin_source,...)");
+ events->on_fd(events, 0, OOP_EXCEPTION, client_exception, &stdin_client);
events->on_fd(events, serial_fd, OOP_READ, serial_readable, 0);
+ events->on_fd(events, serial_fd, OOP_EXCEPTION, serial_exception, 0);
oop_sys_run(sys_events);
abort();
}