aboutsummaryrefslogtreecommitdiff
path: root/parse.c
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2023-09-21 16:49:11 +0000
committerrodri <rgl@antares-labs.eu>2023-09-21 16:49:11 +0000
commit497acdd8860d629ba24ed9976fd47eeb743b74ab (patch)
tree7e8db0be276527ccc0b3d173290655653c8cdd64 /parse.c
parent33de2d046acfc7ee42fb71b1804b091f671b098a (diff)
downloadbattleship-497acdd8860d629ba24ed9976fd47eeb743b74ab.tar.gz
battleship-497acdd8860d629ba24ed9976fd47eeb743b74ab.tar.bz2
battleship-497acdd8860d629ba24ed9976fd47eeb743b74ab.zip
add parsecmd to the server.
modified it to allow for commands with the same name but different nargs. now each match list entry is preceded by an 'm', to simplify its processing. note that this breaks the client. the next commit will fix that.
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/parse.c b/parse.c
new file mode 100644
index 0000000..30671c4
--- /dev/null
+++ b/parse.c
@@ -0,0 +1,96 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <geometry.h>
+#include "dat.h"
+#include "fns.h"
+
+
+/*
+ * Generous estimate of number of fields, including terminal nil pointer
+ */
+static int
+ncmdfield(char *p, int n)
+{
+ int white, nwhite;
+ char *ep;
+ int nf;
+
+ if(p == nil)
+ return 1;
+
+ nf = 0;
+ ep = p+n;
+ white = 1; /* first text will start field */
+ while(p < ep){
+ nwhite = (strchr(" \t\r\n", *p++ & 0xFF) != 0); /* UTF is irrelevant */
+ if(white && !nwhite) /* beginning of field */
+ nf++;
+ white = nwhite;
+ }
+ return nf+1; /* +1 for nil */
+}
+
+/*
+ * parse a command written to a device
+ */
+Cmdbuf *
+parsecmd(char *p, int n)
+{
+ Cmdbuf *cb;
+ int nf;
+ char *sp;
+
+ nf = ncmdfield(p, n);
+
+ /* allocate Cmdbuf plus string pointers plus copy of string including \0 */
+ sp = emalloc(sizeof(*cb) + nf * sizeof(char*) + n + 1);
+ cb = (Cmdbuf*)sp;
+ cb->f = (char**)(&cb[1]);
+ cb->buf = (char*)(&cb->f[nf]);
+
+ memmove(cb->buf, p, n);
+
+ /* dump new line and null terminate */
+ if(n > 0 && cb->buf[n-1] == '\n')
+ n--;
+ cb->buf[n] = '\0';
+
+ cb->nf = tokenize(cb->buf, cb->f, nf-1);
+ cb->f[cb->nf] = nil;
+
+ return cb;
+}
+
+/*
+ * Look up entry in table
+ */
+Cmdtab *
+lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab)
+{
+ int i;
+ Cmdtab *ct;
+
+ if(cb->nf == 0){
+ werrstr("empty command");
+ return nil;
+ }
+
+ for(ct = ctab, i=0; i<nctab; i++, ct++){
+ if(strcmp(ct->cmd, cb->f[0]) != 0)
+ continue;
+ if(ct->narg != 0 && ct->narg != cb->nf){
+// werrstr("wrong #args in command");
+// return nil;
+ /* allow the same cmd name for different commands */
+ continue;
+ }
+ return ct;
+ }
+
+ werrstr("unknown command");
+ return nil;
+}