xref: /plan9/sys/src/lib9p/parse.c (revision 7c70c028d2d46a27a61ae88e6df0eb0935d9da7a)
13ff48bf5SDavid du Colombier #include <u.h>
23ff48bf5SDavid du Colombier #include <libc.h>
33ff48bf5SDavid du Colombier #include <fcall.h>
43ff48bf5SDavid du Colombier #include <thread.h>
53ff48bf5SDavid du Colombier #include <9p.h>
63ff48bf5SDavid du Colombier 
73ff48bf5SDavid du Colombier /*
83ff48bf5SDavid du Colombier  * Generous estimate of number of fields, including terminal nil pointer
93ff48bf5SDavid du Colombier  */
103ff48bf5SDavid du Colombier static int
ncmdfield(char * p,int n)113ff48bf5SDavid du Colombier ncmdfield(char *p, int n)
123ff48bf5SDavid du Colombier {
133ff48bf5SDavid du Colombier 	int white, nwhite;
143ff48bf5SDavid du Colombier 	char *ep;
153ff48bf5SDavid du Colombier 	int nf;
163ff48bf5SDavid du Colombier 
173ff48bf5SDavid du Colombier 	if(p == nil)
183ff48bf5SDavid du Colombier 		return 1;
193ff48bf5SDavid du Colombier 
203ff48bf5SDavid du Colombier 	nf = 0;
213ff48bf5SDavid du Colombier 	ep = p+n;
223ff48bf5SDavid du Colombier 	white = 1;	/* first text will start field */
233ff48bf5SDavid du Colombier 	while(p < ep){
243ff48bf5SDavid du Colombier 		nwhite = (strchr(" \t\r\n", *p++ & 0xFF) != 0);	/* UTF is irrelevant */
253ff48bf5SDavid du Colombier 		if(white && !nwhite)	/* beginning of field */
263ff48bf5SDavid du Colombier 			nf++;
273ff48bf5SDavid du Colombier 		white = nwhite;
283ff48bf5SDavid du Colombier 	}
293ff48bf5SDavid du Colombier 	return nf+1;	/* +1 for nil */
303ff48bf5SDavid du Colombier }
313ff48bf5SDavid du Colombier 
323ff48bf5SDavid du Colombier /*
333ff48bf5SDavid du Colombier  *  parse a command written to a device
343ff48bf5SDavid du Colombier  */
353ff48bf5SDavid du Colombier Cmdbuf*
parsecmd(char * p,int n)363ff48bf5SDavid du Colombier parsecmd(char *p, int n)
373ff48bf5SDavid du Colombier {
383ff48bf5SDavid du Colombier 	Cmdbuf *cb;
393ff48bf5SDavid du Colombier 	int nf;
403ff48bf5SDavid du Colombier 	char *sp;
413ff48bf5SDavid du Colombier 
423ff48bf5SDavid du Colombier 	nf = ncmdfield(p, n);
433ff48bf5SDavid du Colombier 
443ff48bf5SDavid du Colombier 	/* allocate Cmdbuf plus string pointers plus copy of string including \0 */
453ff48bf5SDavid du Colombier 	sp = emalloc9p(sizeof(*cb) + nf * sizeof(char*) + n + 1);
463ff48bf5SDavid du Colombier 	cb = (Cmdbuf*)sp;
473ff48bf5SDavid du Colombier 	cb->f = (char**)(&cb[1]);
483ff48bf5SDavid du Colombier 	cb->buf = (char*)(&cb->f[nf]);
493ff48bf5SDavid du Colombier 
503ff48bf5SDavid du Colombier 	memmove(cb->buf, p, n);
513ff48bf5SDavid du Colombier 
523ff48bf5SDavid du Colombier 	/* dump new line and null terminate */
533ff48bf5SDavid du Colombier 	if(n > 0 && cb->buf[n-1] == '\n')
543ff48bf5SDavid du Colombier 		n--;
553ff48bf5SDavid du Colombier 	cb->buf[n] = '\0';
563ff48bf5SDavid du Colombier 
573ff48bf5SDavid du Colombier 	cb->nf = tokenize(cb->buf, cb->f, nf-1);
583ff48bf5SDavid du Colombier 	cb->f[cb->nf] = nil;
593ff48bf5SDavid du Colombier 
603ff48bf5SDavid du Colombier 	return cb;
613ff48bf5SDavid du Colombier }
623ff48bf5SDavid du Colombier 
633ff48bf5SDavid du Colombier /*
643ff48bf5SDavid du Colombier  * Reconstruct original message, for error diagnostic
653ff48bf5SDavid du Colombier  */
663ff48bf5SDavid du Colombier void
respondcmderror(Req * r,Cmdbuf * cb,char * fmt,...)673ff48bf5SDavid du Colombier respondcmderror(Req *r, Cmdbuf *cb, char *fmt, ...)
683ff48bf5SDavid du Colombier {
693ff48bf5SDavid du Colombier 	int i;
703ff48bf5SDavid du Colombier 	va_list arg;
713ff48bf5SDavid du Colombier 	char *p, *e;
723ff48bf5SDavid du Colombier 	char err[ERRMAX];
733ff48bf5SDavid du Colombier 
743ff48bf5SDavid du Colombier 	e = err+ERRMAX-10;
753ff48bf5SDavid du Colombier 	va_start(arg, fmt);
763ff48bf5SDavid du Colombier 	p = vseprint(err, e, fmt, arg);
773ff48bf5SDavid du Colombier 	va_end(arg);
783ff48bf5SDavid du Colombier 	p = seprint(p, e, ": \"");
79*7c70c028SDavid du Colombier 	quotefmtinstall();	/* just in case */
803ff48bf5SDavid du Colombier 	for(i=0; i<cb->nf; i++){
813ff48bf5SDavid du Colombier 		if(i > 0)
823ff48bf5SDavid du Colombier 			p = seprint(p, e, " ");
833ff48bf5SDavid du Colombier 		p = seprint(p, e, "%q", cb->f[i]);
843ff48bf5SDavid du Colombier 	}
853ff48bf5SDavid du Colombier 	strcpy(p, "\"");
863ff48bf5SDavid du Colombier 	respond(r, err);
873ff48bf5SDavid du Colombier }
883ff48bf5SDavid du Colombier 
893ff48bf5SDavid du Colombier /*
903ff48bf5SDavid du Colombier  * Look up entry in table
913ff48bf5SDavid du Colombier  */
923ff48bf5SDavid du Colombier Cmdtab*
lookupcmd(Cmdbuf * cb,Cmdtab * ctab,int nctab)933ff48bf5SDavid du Colombier lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab)
943ff48bf5SDavid du Colombier {
953ff48bf5SDavid du Colombier 	int i;
963ff48bf5SDavid du Colombier 	Cmdtab *ct;
973ff48bf5SDavid du Colombier 
983ff48bf5SDavid du Colombier 	if(cb->nf == 0){
993ff48bf5SDavid du Colombier 		werrstr("empty control message");
1003ff48bf5SDavid du Colombier 		return nil;
1013ff48bf5SDavid du Colombier 	}
1023ff48bf5SDavid du Colombier 
1033ff48bf5SDavid du Colombier 	for(ct = ctab, i=0; i<nctab; i++, ct++){
1043ff48bf5SDavid du Colombier 		if(strcmp(ct->cmd, "*") !=0)	/* wildcard always matches */
1053ff48bf5SDavid du Colombier 		if(strcmp(ct->cmd, cb->f[0]) != 0)
1063ff48bf5SDavid du Colombier 			continue;
1073ff48bf5SDavid du Colombier 		if(ct->narg != 0 && ct->narg != cb->nf){
1083ff48bf5SDavid du Colombier 			werrstr("bad # args to command");
1093ff48bf5SDavid du Colombier 			return nil;
1103ff48bf5SDavid du Colombier 		}
1113ff48bf5SDavid du Colombier 		return ct;
1123ff48bf5SDavid du Colombier 	}
1133ff48bf5SDavid du Colombier 
1143ff48bf5SDavid du Colombier 	werrstr("unknown control message");
1153ff48bf5SDavid du Colombier 	return nil;
1163ff48bf5SDavid du Colombier }
117