17dd7cddfSDavid du Colombier #include "u.h"
27dd7cddfSDavid du Colombier #include "../port/lib.h"
37dd7cddfSDavid du Colombier #include "mem.h"
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier #include "fns.h"
67dd7cddfSDavid du Colombier #include "../port/error.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier /*
9*9a747e4fSDavid du Colombier * Generous estimate of number of fields, including terminal nil pointer
10*9a747e4fSDavid du Colombier */
11*9a747e4fSDavid du Colombier static int
ncmdfield(char * p,int n)12*9a747e4fSDavid du Colombier ncmdfield(char *p, int n)
13*9a747e4fSDavid du Colombier {
14*9a747e4fSDavid du Colombier int white, nwhite;
15*9a747e4fSDavid du Colombier char *ep;
16*9a747e4fSDavid du Colombier int nf;
17*9a747e4fSDavid du Colombier
18*9a747e4fSDavid du Colombier if(p == nil)
19*9a747e4fSDavid du Colombier return 1;
20*9a747e4fSDavid du Colombier
21*9a747e4fSDavid du Colombier nf = 0;
22*9a747e4fSDavid du Colombier ep = p+n;
23*9a747e4fSDavid du Colombier white = 1; /* first text will start field */
24*9a747e4fSDavid du Colombier while(p < ep){
25*9a747e4fSDavid du Colombier nwhite = (strchr(" \t\r\n", *p++ & 0xFF) != 0); /* UTF is irrelevant */
26*9a747e4fSDavid du Colombier if(white && !nwhite) /* beginning of field */
27*9a747e4fSDavid du Colombier nf++;
28*9a747e4fSDavid du Colombier white = nwhite;
29*9a747e4fSDavid du Colombier }
30*9a747e4fSDavid du Colombier return nf+1; /* +1 for nil */
31*9a747e4fSDavid du Colombier }
32*9a747e4fSDavid du Colombier
33*9a747e4fSDavid du Colombier /*
347dd7cddfSDavid du Colombier * parse a command written to a device
357dd7cddfSDavid du Colombier */
367dd7cddfSDavid du Colombier Cmdbuf*
parsecmd(char * p,int n)377dd7cddfSDavid du Colombier parsecmd(char *p, int n)
387dd7cddfSDavid du Colombier {
39*9a747e4fSDavid du Colombier Cmdbuf *volatile cb;
40*9a747e4fSDavid du Colombier int nf;
41*9a747e4fSDavid du Colombier char *sp;
427dd7cddfSDavid du Colombier
43*9a747e4fSDavid du Colombier nf = ncmdfield(p, n);
447dd7cddfSDavid du Colombier
45*9a747e4fSDavid du Colombier /* allocate Cmdbuf plus string pointers plus copy of string including \0 */
46*9a747e4fSDavid du Colombier sp = smalloc(sizeof(*cb) + nf * sizeof(char*) + n + 1);
47*9a747e4fSDavid du Colombier cb = (Cmdbuf*)sp;
48*9a747e4fSDavid du Colombier cb->f = (char**)(&cb[1]);
49*9a747e4fSDavid du Colombier cb->buf = (char*)(&cb->f[nf]);
50*9a747e4fSDavid du Colombier
51*9a747e4fSDavid du Colombier if(up!=nil && waserror()){
52*9a747e4fSDavid du Colombier free(cb);
53*9a747e4fSDavid du Colombier nexterror();
54*9a747e4fSDavid du Colombier }
557dd7cddfSDavid du Colombier memmove(cb->buf, p, n);
56*9a747e4fSDavid du Colombier if(up != nil)
57*9a747e4fSDavid du Colombier poperror();
58*9a747e4fSDavid du Colombier
59*9a747e4fSDavid du Colombier /* dump new line and null terminate */
607dd7cddfSDavid du Colombier if(n > 0 && cb->buf[n-1] == '\n')
617dd7cddfSDavid du Colombier n--;
627dd7cddfSDavid du Colombier cb->buf[n] = '\0';
63*9a747e4fSDavid du Colombier
64*9a747e4fSDavid du Colombier cb->nf = tokenize(cb->buf, cb->f, nf-1);
65*9a747e4fSDavid du Colombier cb->f[cb->nf] = nil;
66*9a747e4fSDavid du Colombier
677dd7cddfSDavid du Colombier return cb;
687dd7cddfSDavid du Colombier }
697dd7cddfSDavid du Colombier
70*9a747e4fSDavid du Colombier /*
71*9a747e4fSDavid du Colombier * Reconstruct original message, for error diagnostic
72*9a747e4fSDavid du Colombier */
73*9a747e4fSDavid du Colombier void
cmderror(Cmdbuf * cb,char * s)74*9a747e4fSDavid du Colombier cmderror(Cmdbuf *cb, char *s)
75*9a747e4fSDavid du Colombier {
76*9a747e4fSDavid du Colombier int i;
77*9a747e4fSDavid du Colombier char *p, *e;
78*9a747e4fSDavid du Colombier
79*9a747e4fSDavid du Colombier p = up->genbuf;
80*9a747e4fSDavid du Colombier e = p+ERRMAX-10;
81*9a747e4fSDavid du Colombier p = seprint(p, e, "%s \"", s);
82*9a747e4fSDavid du Colombier for(i=0; i<cb->nf; i++){
83*9a747e4fSDavid du Colombier if(i > 0)
84*9a747e4fSDavid du Colombier p = seprint(p, e, " ");
85*9a747e4fSDavid du Colombier p = seprint(p, e, "%q", cb->f[i]);
86*9a747e4fSDavid du Colombier }
87*9a747e4fSDavid du Colombier strcpy(p, "\"");
88*9a747e4fSDavid du Colombier error(up->genbuf);
89*9a747e4fSDavid du Colombier }
90*9a747e4fSDavid du Colombier
91*9a747e4fSDavid du Colombier /*
92*9a747e4fSDavid du Colombier * Look up entry in table
93*9a747e4fSDavid du Colombier */
94*9a747e4fSDavid du Colombier Cmdtab*
lookupcmd(Cmdbuf * cb,Cmdtab * ctab,int nctab)95*9a747e4fSDavid du Colombier lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab)
96*9a747e4fSDavid du Colombier {
97*9a747e4fSDavid du Colombier int i;
98*9a747e4fSDavid du Colombier Cmdtab *ct;
99*9a747e4fSDavid du Colombier
100*9a747e4fSDavid du Colombier if(cb->nf == 0)
101*9a747e4fSDavid du Colombier error("empty control message");
102*9a747e4fSDavid du Colombier
103*9a747e4fSDavid du Colombier for(ct = ctab, i=0; i<nctab; i++, ct++){
104*9a747e4fSDavid du Colombier if(strcmp(ct->cmd, "*") !=0) /* wildcard always matches */
105*9a747e4fSDavid du Colombier if(strcmp(ct->cmd, cb->f[0]) != 0)
106*9a747e4fSDavid du Colombier continue;
107*9a747e4fSDavid du Colombier if(ct->narg != 0 && ct->narg != cb->nf)
108*9a747e4fSDavid du Colombier cmderror(cb, Ecmdargs);
109*9a747e4fSDavid du Colombier return ct;
110*9a747e4fSDavid du Colombier }
111*9a747e4fSDavid du Colombier
112*9a747e4fSDavid du Colombier cmderror(cb, "unknown control message");
113*9a747e4fSDavid du Colombier return nil;
114*9a747e4fSDavid du Colombier }
115