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