hostside-old: serialio.o nmra.o main.o encode.o
$(LINK)
-hostside: hostside.o serialio.o -loop
+hostside: hostside.o serialio.o client.o obc.o commands.c -loop
$(LINK)
layoutinfo.h: ../layout/ours.layout-data.c Makefile
--- /dev/null
+/**/
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "hostside.h"
+
+void vbadcmd(ParseState *ps, const char *fmt, va_list al) {
+ oprintf(&ps->cl->ch,"error ");
+ ovprintf(&ps->cl->ch,fmt,al);
+ owrite(&ps->cl->ch,"\n",1);
+}
+
+void badcmd(ParseState *ps, const char *fmt, ...) {
+ va_list al;
+ va_start(al,fmt);
+ vbadcmd(ps,fmt,al);
+ va_end(al);
+}
+
+int ps_needword(ParseState *ps) {
+ const char *space;
+ if (!ps->remain) { badcmd(ps,"too few args"); return 0; }
+ space= strchr(ps->remain, ' ');
+ ps->thisword= ps->remain;
+ if (space) {
+ ps->lthisword= space - ps->thisword;
+ ps->remain= space + 1;
+ } else {
+ ps->lthisword= strlen(ps->remain);
+ ps->remain= 0;
+ }
+ return 1;
+}
+
+const CmdInfo *ps_lookup(ParseState *ps, const CmdInfo *inf) {
+ for (;
+ inf->name;
+ inf++)
+ if (ps->lthisword == strlen(inf->name) &&
+ !memcmp(ps->thisword, inf->name, ps->lthisword))
+ return inf;
+ return 0;
+}
+
+const CmdInfo *ps_needword_lookup(ParseState *ps, const CmdInfo *infs) {
+ if (!ps_needword(ps)) return 0;
+ return ps_lookup(ps,infs);
+}
+
+void ps_callword(ParseState *ps, const CmdInfo *infs, const char *what) {
+ const CmdInfo *ci;
+ ci= ps_needword_lookup(ps,infs);
+ if (!ci) { badcmd(ps,"unknown %s",what); return; }
+ ci->fn(ps,ci);
+}
+
+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 *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;
+
+ 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;
+ ps_callword(&ps, toplevel_cmds, "command");
+ return OOP_CONTINUE;
+}
+
+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 new_client(int fd, OutBufferError error, char *desc) {
+ Client *cl;
+ int r;
+
+ cl= mmalloc(sizeof(*cl));
+
+ cl->ch.desc= desc;
+ cl->ch.fd= fd;
+ cl->ch.error= error;
+ obc_init(&cl->ch);
+
+ events->on_fd(events, fd, OOP_EXCEPTION, client_exception, cl);
+
+ cl->rd= oop_rd_new_fd(events, fd, 0,0);
+ if (!cl->rd) diee("oop_rd_new_fd");
+ r= oop_rd_read(cl->rd, OOP_RD_STYLE_GETLINE, 1024,
+ client_ifok, cl,
+ client_iferr, cl);
+ if (r) diee("oop_rd_read");
+}
+
+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);
+}
+
+void stdin_client(void) {
+ new_client(0, stdin_error, (char*)"stdin");
+}
--- /dev/null
+/**/
+
+#include "hostside.h"
+
+static void cmd_noop(ParseState *ps, const CmdInfo *ci) {
+ oprintf(&ps->cl->ch,"noop successful\n");
+}
+
+const CmdInfo toplevel_cmds[]= {
+#if 0
+ { "nmra-x", cmd_nmra_x },
+ { "nmra-1", cmd_nmra_1 },
+ { "xmit-x", cmd_xmit_x },
+ { "xmit-1", cmd_xmit_1 },
+ { "pic", cmd_pic },
+ { "raw", cmd_raw },
+#endif
+ { "noop", cmd_noop },
+ { 0 }
+};
#include <string.h>
#include <stdarg.h>
-#include <oop.h>
-#include <oop-read.h>
-
#include "../layout/dlist.h"
#include "hostside.h"
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) {
- OutBufferChain *ch= ch_v;
- OutBuffer *ob;
- int r;
-
- assert(fd == ch->fd);
- assert(evt == OOP_WRITE);
-
- for (;;) {
- ob= ch->obs.head;
- if (!ob) {
- events->cancel_fd(events, fd, OOP_WRITE);
- return OOP_CONTINUE;
- }
- if (ch->done_of_head == ob->l) {
- LIST_UNLINK(ch->obs, ob);
- free(ob);
- free(ob->m);
- ch->done_of_head= 0;
- continue;
- }
- r= write(ch->fd, ob->m + ch->done_of_head, ob->l - ch->done_of_head);
- if (r==-1) {
- if (errno==EINTR) continue;
- if (errno==EWOULDBLOCK) return OOP_CONTINUE;
- ch->error(ch,"write",strerror(errno));
- }
- assert(r>=0);
- ch->done_of_head += r;
- assert(ch->done_of_head <= ob->l);
- }
-}
-
-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)
- events->on_fd(events, ch->fd, OOP_WRITE, ochain_writeable, ch);
- LIST_LINK_TAIL(ch->obs, ob);
-}
-
-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_client.ch, ob);
-}
-
-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(ch,msg,al);
- va_end(al);
-}
-
-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(&ps->cl->ch,"noop successful\n");
-}
-
-static const CmdInfo toplevel_cmds[]= {
-#if 0
- { "nmra-x", cmd_nmra_x },
- { "nmra-1", cmd_nmra_1 },
- { "xmit-x", cmd_xmit_x },
- { "xmit-1", cmd_xmit_1 },
- { "pic", cmd_pic },
- { "raw", cmd_raw },
-#endif
- { "noop", cmd_noop },
- { 0 }
-};
-
-static int ps_needword(ParseState *ps) {
- const char *space;
- if (!ps->remain) { badcmd(ps,"too few args"); return 0; }
- space= strchr(ps->remain, ' ');
- ps->thisword= ps->remain;
- if (space) {
- ps->lthisword= space - ps->thisword;
- ps->remain= space + 1;
- } else {
- ps->lthisword= strlen(ps->remain);
- ps->remain= 0;
- }
- return 1;
-}
-
-static const CmdInfo *ps_lookup(ParseState *ps, const CmdInfo *inf) {
- for (;
- inf->name;
- inf++)
- if (ps->lthisword == strlen(inf->name) &&
- !memcmp(ps->thisword, inf->name, ps->lthisword))
- return inf;
- return 0;
-}
-
-static const CmdInfo *ps_needword_lookup(ParseState *ps, const CmdInfo *infs) {
- if (!ps_needword(ps)) return 0;
- return ps_lookup(ps,infs);
-}
-
-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 *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) {
- 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(&ps,"unknown command"); return OOP_CONTINUE; }
- ci->fn(&ps,ci);
- return OOP_CONTINUE;
-}
-
static void *serial_readable(oop_source *evts, int fd,
oop_event evt, void *u0) {
abort();
const char *device;
int main(int argc, const char **argv) {
- oop_read *stdin_source;
oop_source_sys *sys_events;
int r;
device= argv[1];
if (!device) device= "/dev/ttyS0";
+
+ sys_events= oop_sys_new(); if (!sys_events) diee("oop_sys_new");
+ events= oop_sys_source(sys_events); assert(events);
serial_open(device);
r= oop_fd_nonblock(serial_fd, 1); if (r) diee("nonblock(serial_fd,1)");
serial_ochain.fd= serial_fd;
- sys_events= oop_sys_new(); if (!sys_events) diee("oop_sys_new");
- events= oop_sys_source(sys_events); assert(events);
-
- 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,
- 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);
+ stdin_client();
events->on_fd(events, serial_fd, OOP_READ, serial_readable, 0);
events->on_fd(events, serial_fd, OOP_EXCEPTION, serial_exception, 0);
#include <stdio.h>
#include <oop.h>
+#include <oop-read.h>
typedef unsigned char Byte;
typedef struct OutBuffer OutBuffer;
+typedef struct OutBufferChain OutBufferChain;
+typedef struct Client Client;
+typedef struct ParseState ParseState;
+typedef struct CmdInfo CmdInfo;
+
struct OutBuffer {
OutBuffer *back, *next;
char *m;
int l;
};
-typedef struct OutBufferChain OutBufferChain;
+typedef void OutBufferError(OutBufferChain*, const char *e1, const char *e2);
+
struct OutBufferChain {
+ /* set by user: */
char *desc;
int fd;
- void (*error)(OutBufferChain *obc, const char *e1, const char *e2);
+ OutBufferError *error;
+ /* set/used by obc_..., oprintf, etc., only */
int done_of_head;
struct { OutBuffer *head, *tail; } obs;
};
-typedef struct Client Client;
struct Client {
OutBufferChain ch;
+ oop_read *rd;
};
-typedef struct ParseState ParseState;
struct ParseState {
Client *cl;
const char *remain;
int lthisword;
};
-typedef struct CmdInfo CmdInfo;
struct CmdInfo {
const char *name;
void (*fn)(ParseState *ps, const CmdInfo *ci);
void diee(const char *fmt, ...) __attribute__((noreturn,format(printf,1,2)));
void diem(void) __attribute__((noreturn));
+void vbadcmd(ParseState *ps, const char *fmt, va_list al)
+ __attribute__((format(printf,2,0)));
+void badcmd(ParseState *ps, const char *fmt, ...)
+ __attribute__((format(printf,2,3)));
+int ps_needword(ParseState *ps);
+const CmdInfo *ps_lookup(ParseState *ps, const CmdInfo *inf);
+const CmdInfo *ps_needword_lookup(ParseState *ps, const CmdInfo *infs);
+void ps_callword(ParseState *ps, const CmdInfo *infs, const char *what);
+
+extern const CmdInfo toplevel_cmds[];
+void stdin_client(void);
+
+
+void obc_init(OutBufferChain *ch);
+void ovprintf(OutBufferChain *ch, const char *fmt, va_list al)
+ __attribute__((format(printf,2,0)));
+void oprintf(OutBufferChain *ch, const char *msg, ...)
+ __attribute__((format(printf,2,3)));
+void owrite(OutBufferChain *ch, const char *data, int l);
+
+void *mmalloc(size_t sz);
+
#define COMMAND_ENCODED_MAX 16
#define NMRA_PACKET_MAX ((COMMAND_ENCODED_MAX*7 - 14) / 8)
--- /dev/null
+/**/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "hostside.h"
+#include "../layout/dlist.h"
+
+static void *writeable(oop_source *evts, int fd,
+ oop_event evt, void *ch_v) {
+ OutBufferChain *ch= ch_v;
+ OutBuffer *ob;
+ int r;
+
+ assert(fd == ch->fd);
+ assert(evt == OOP_WRITE);
+
+ for (;;) {
+ ob= ch->obs.head;
+ if (!ob) {
+ events->cancel_fd(events, fd, OOP_WRITE);
+ return OOP_CONTINUE;
+ }
+ if (ch->done_of_head == ob->l) {
+ LIST_UNLINK(ch->obs, ob);
+ free(ob);
+ free(ob->m);
+ ch->done_of_head= 0;
+ continue;
+ }
+ r= write(ch->fd, ob->m + ch->done_of_head, ob->l - ch->done_of_head);
+ if (r==-1) {
+ if (errno==EINTR) continue;
+ if (errno==EWOULDBLOCK) return OOP_CONTINUE;
+ ch->error(ch,"write",strerror(errno));
+ }
+ assert(r>=0);
+ ch->done_of_head += r;
+ assert(ch->done_of_head <= ob->l);
+ }
+}
+
+static void addlink(OutBufferChain *ch, OutBuffer *ob) {
+ if (!ch->obs.head)
+ events->on_fd(events, ch->fd, OOP_WRITE, writeable, ch);
+ LIST_LINK_TAIL(ch->obs, ob);
+}
+
+void obc_init(OutBufferChain *ch) {
+ ch->done_of_head= 0;
+ LIST_INIT(ch->obs);
+}
+
+void ovprintf(OutBufferChain *ch, const char *fmt, va_list al) {
+ OutBuffer *ob;
+
+ ob= mmalloc(sizeof(*ob));
+ ob->l= vasprintf(&ob->m, fmt, al); if (ob->l <= 0) diem();
+ addlink(ch, ob);
+}
+
+void oprintf(OutBufferChain *ch, const char *msg, ...) {
+ va_list al;
+ va_start(al,msg);
+ ovprintf(ch,msg,al);
+ va_end(al);
+}
+
+void owrite(OutBufferChain *ch, const char *data, int l) {
+ OutBuffer *ob;
+ ob= mmalloc(sizeof(*ob));
+ ob->l= l;
+ ob->m= mmalloc(l);
+ memcpy(ob->m, data, l);
+ addlink(ch,ob);
+}
void diem(void)
{ diee("malloc failed"); }
+void *mmalloc(size_t sz) {
+ void *p;
+ if (!sz) return 0;
+ p= malloc(sz);
+ if (!p) diem();
+ return p;
+}
+
void serial_open(const char *device) {
assert(serial_fd==-1);