xref: /inferno-os/emu/port/parse.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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