chiark / gitweb /
reorganised to be nicer and ready to add stuff
authorian <ian>
Mon, 30 May 2005 11:56:17 +0000 (11:56 +0000)
committerian <ian>
Mon, 30 May 2005 11:56:17 +0000 (11:56 +0000)
hostside/Makefile
hostside/client.c [new file with mode: 0644]
hostside/commands.c [new file with mode: 0644]
hostside/hostside.c
hostside/hostside.h
hostside/obc.c [new file with mode: 0644]
hostside/serialio.c

index 117bd491d59bebfd170b18647795303ec9f2bb61..465626706bddac167d0a6d3e9e9748962e72eab4 100644 (file)
@@ -10,7 +10,7 @@ all:          $(TARGETS)
 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
diff --git a/hostside/client.c b/hostside/client.c
new file mode 100644 (file)
index 0000000..e30f8c7
--- /dev/null
@@ -0,0 +1,127 @@
+/**/
+
+#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");
+}
diff --git a/hostside/commands.c b/hostside/commands.c
new file mode 100644 (file)
index 0000000..5610f90
--- /dev/null
@@ -0,0 +1,20 @@
+/**/
+
+#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 }
+};
index bd00f9bfc8695d3db1e31556e04aeb839408220c..5c14f66d835aeab50e01b0dbd9cf773b7a6a9b87 100644 (file)
@@ -6,9 +6,6 @@
 #include <string.h>
 #include <stdarg.h>
 
-#include <oop.h>
-#include <oop-read.h>
-
 #include "../layout/dlist.h"
 #include "hostside.h"
 
@@ -19,172 +16,13 @@ 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) {
-  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();
@@ -193,26 +31,20 @@ static void *serial_readable(oop_source *evts, int fd,
 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);
index 22c8cf44ff096c4b1e4e5b3569d30e8e21e2f4ac..d34fb3436d1dcbcf4aa8b4b25994d346b5bdd919 100644 (file)
@@ -5,31 +5,39 @@
 
 #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;
@@ -37,7 +45,6 @@ struct ParseState {
   int lthisword;
 };
 
-typedef struct CmdInfo CmdInfo;
 struct CmdInfo {
   const char *name;
   void (*fn)(ParseState *ps, const CmdInfo *ci);
@@ -50,6 +57,28 @@ void die(const char *fmt, ...) __attribute__((noreturn,format(printf,1,2)));
 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)
diff --git a/hostside/obc.c b/hostside/obc.c
new file mode 100644 (file)
index 0000000..7fb3c1a
--- /dev/null
@@ -0,0 +1,79 @@
+/**/
+
+#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);
+}
index 4497f691cd5f0dae05cd957d3a22981e8f49f104..952698d53e4169946b6fd6107f27021cdb609d40 100644 (file)
@@ -30,6 +30,14 @@ void diee(const char *fmt, ...)
 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);