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