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