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