diff options
| author | Charles.Forsyth <devnull@localhost> | 2009-03-25 15:55:14 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2009-03-25 15:55:14 +0000 |
| commit | dfd1934d5e1ddbeb326f77fc0e52307c801a1a3e (patch) | |
| tree | f1e8b23278caae95e01d88b00421d6c3642357ef /emu/port/parse.c | |
| parent | 78dfdcbd59dc8f36975e7695933e3f753957474c (diff) | |
x20090325-1554
Diffstat (limited to 'emu/port/parse.c')
| -rw-r--r-- | emu/port/parse.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/emu/port/parse.c b/emu/port/parse.c new file mode 100644 index 00000000..fc84d17b --- /dev/null +++ b/emu/port/parse.c @@ -0,0 +1,111 @@ +#include "dat.h" +#include "fns.h" +#include "error.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 *volatile cb; + int nf; + char *sp; + + nf = ncmdfield(p, n); + + /* allocate Cmdbuf plus string pointers plus copy of string including \0 */ + sp = smalloc(sizeof(*cb) + nf * sizeof(char*) + n + 1); + cb = (Cmdbuf*)sp; + cb->f = (char**)(&cb[1]); + cb->buf = (char*)(&cb->f[nf]); + + if(up!=nil && waserror()){ + free(cb); + nexterror(); + } + memmove(cb->buf, p, n); + if(up != nil) + poperror(); + + /* 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; +} + +/* + * Reconstruct original message, for error diagnostic + */ +void +cmderror(Cmdbuf *cb, char *s) +{ + int i; + char *p, *e; + + p = up->genbuf; + e = p+ERRMAX-10; + p = seprint(p, e, "%s \"", s); + for(i=0; i<cb->nf; i++){ + if(i > 0) + p = seprint(p, e, " "); + p = seprint(p, e, "%q", cb->f[i]); + } + strcpy(p, "\""); + error(up->genbuf); +} + +/* + * Look up entry in table + */ +Cmdtab* +lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab) +{ + int i; + Cmdtab *ct; + + if(cb->nf == 0) + error("empty control message"); + + for(ct = ctab, i=0; i<nctab; i++, ct++){ + if(strcmp(ct->cmd, "*") !=0) /* wildcard always matches */ + if(strcmp(ct->cmd, cb->f[0]) != 0) + continue; + if(ct->narg != 0 && ct->narg != cb->nf) + cmderror(cb, Ecmdargs); + return ct; + } + + cmderror(cb, "unknown control message"); + return nil; +} |
