plan 9 kernel history: overview | file list | diff list

2001/0405/port/parse.c (diff list | history)

1999/0316/sys/src/9/port/parse.c:5,272000/0308/sys/src/9/port/parse.c:5,10 (short | long)
Replace parsefields with new library function getfields, now that getfields is thread-safe.
rsc Fri Mar 4 12:44:25 2005
1999/0316    
#include	"fns.h" 
#include	"../port/error.h" 
 
int 
parsefields(char *lp, char **fields, int n, char *sep) 
{ 
	int i; 
                 
	for(i=0; lp && *lp && i<n; i++){ 
		while(*lp && strchr(sep, *lp) != 0) 
			*lp++=0; 
		if(*lp == 0) 
			break; 
		fields[i]=lp; 
		while(*lp && strchr(sep, *lp) == 0) 
			lp++; 
	} 
	return i; 
} 
                 
/* 
 *  parse a command written to a device 
 */ 
1999/0316/sys/src/9/port/parse.c:38,442000/0308/sys/src/9/port/parse.c:21,27
1999/0316    
	if(n > 0 && cb->buf[n-1] == '\n') 
		n--; 
	cb->buf[n] = '\0'; 
	cb->nf = parsefields(cb->buf, cb->f, nelem(cb->f), " "); 
2000/0308    
	cb->nf = getfields(cb->buf, cb->f, nelem(cb->f), 1, " "); 
1999/0316    
	return cb; 
} 
 
2000/0308/sys/src/9/port/parse.c:11,232001/0331/sys/src/9/port/parse.c:11,30 (short | long)
Bug fix: guard against error in user to kernel memmove.
rsc Fri Mar 4 12:44:25 2005
1999/0316    
Cmdbuf* 
parsecmd(char *p, int n) 
{ 
	Cmdbuf *cb; 
2001/0331    
	Cmdbuf *volatile cb; 
1999/0316    
 
	cb = smalloc(sizeof(*cb)); 
	 
	if(n > sizeof(cb->buf)-1) 
		n = sizeof(cb->buf)-1; 
2001/0331    
 
	if(waserror()){ 
		free(cb); 
		nexterror(); 
	} 
1999/0316    
	memmove(cb->buf, p, n); 
2001/0331    
	poperror(); 
 
1999/0316    
	if(n > 0 && cb->buf[n-1] == '\n') 
		n--; 
	cb->buf[n] = '\0'; 
2001/0331/sys/src/9/port/parse.c:13,292001/0405/sys/src/9/port/parse.c:13,36 (short | long)
Bug fix: only call smalloc, waserror, poperror when running a user process.
rsc Fri Mar 4 12:44:25 2005
1999/0316    
{ 
2001/0331    
	Cmdbuf *volatile cb; 
1999/0316    
 
	cb = smalloc(sizeof(*cb)); 
2001/0405    
	if(up != nil) 
		cb = smalloc(sizeof(*cb)); 
	else{ 
		cb = malloc(sizeof(*cb)); 
		if(cb == nil) 
			return nil; 
	} 
1999/0316    
	 
	if(n > sizeof(cb->buf)-1) 
		n = sizeof(cb->buf)-1; 
2001/0331    
 
	if(waserror()){ 
2001/0405    
	if(up != nil && waserror()){ 
2001/0331    
		free(cb); 
		nexterror(); 
	} 
1999/0316    
	memmove(cb->buf, p, n); 
2001/0331    
	poperror(); 
2001/0405    
	if(up != nil) 
		poperror(); 
2001/0331    
 
1999/0316    
	if(n > 0 && cb->buf[n-1] == '\n') 
		n--; 
2001/0405/sys/src/9/port/parse.c:35,412001/0418/sys/src/9/port/parse.c:35,41 (short | long)
Change getfields to tokenize for quoted strings.
rsc Fri Mar 4 12:44:25 2005
1999/0316    
	if(n > 0 && cb->buf[n-1] == '\n') 
		n--; 
	cb->buf[n] = '\0'; 
2000/0308    
	cb->nf = getfields(cb->buf, cb->f, nelem(cb->f), 1, " "); 
2001/0418    
	cb->nf = tokenize(cb->buf, cb->f, nelem(cb->f)); 
1999/0316    
	return cb; 
} 
 
2001/0418/sys/src/9/port/parse.c:13,302001/0527/sys/src/9/port/parse.c:13,24 (short | long)
Change tokenize back to getfields to avoid quoted strings. Format edits. Bug: call smalloc always.
rsc Fri Mar 4 12:44:25 2005
1999/0316    
{ 
2001/0331    
	Cmdbuf *volatile cb; 
1999/0316    
 
2001/0405    
	if(up != nil) 
		cb = smalloc(sizeof(*cb)); 
	else{ 
		cb = malloc(sizeof(*cb)); 
		if(cb == nil) 
			return nil; 
	} 
2001/0527    
	cb = smalloc(sizeof(*cb)); 
1999/0316    
	 
	if(n > sizeof(cb->buf)-1) 
		n = sizeof(cb->buf)-1; 
2001/0331    
 
2001/0405    
	if(up != nil && waserror()){ 
2001/0527    
	if(up!=nil && waserror()){ 
2001/0331    
		free(cb); 
		nexterror(); 
	} 
2001/0418/sys/src/9/port/parse.c:35,412001/0527/sys/src/9/port/parse.c:29,35
1999/0316    
	if(n > 0 && cb->buf[n-1] == '\n') 
		n--; 
	cb->buf[n] = '\0'; 
2001/0418    
	cb->nf = tokenize(cb->buf, cb->f, nelem(cb->f)); 
2001/0527    
	cb->nf = getfields(cb->buf, cb->f, nelem(cb->f), 1, " "); 
1999/0316    
	return cb; 
} 
 
2001/0527/sys/src/9/port/parse.c:12,222001/1108/sys/src/9/port/parse.c:12,27 (short | long)
Avoid fixed field count; allocate enough for list of fields.
rsc Fri Mar 4 12:44:25 2005
1999/0316    
parsecmd(char *p, int n) 
{ 
2001/0331    
	Cmdbuf *volatile cb; 
2001/1108    
	int nf; 
	char *sp; 
1999/0316    
 
2001/0527    
	cb = smalloc(sizeof(*cb)); 
1999/0316    
	                 
	if(n > sizeof(cb->buf)-1) 
		n = sizeof(cb->buf)-1; 
2001/1108    
	/* count fields and allocate a big enough cmdbuf */ 
	for(nf = 1, sp = p; sp != nil && *sp; nf++, sp = strchr(sp+1, ' ')) 
		; 
	sp = smalloc(sizeof(*cb) + n + 1 + nf*sizeof(char*)); 
	cb = (Cmdbuf*)sp; 
	cb->buf = sp+sizeof(*cb); 
	cb->f = (char**)(cb->buf + n + 1); 
2001/0331    
 
2001/0527    
	if(up!=nil && waserror()){ 
2001/0331    
		free(cb); 
2001/0527/sys/src/9/port/parse.c:26,352001/1108/sys/src/9/port/parse.c:31,42
2001/0405    
	if(up != nil) 
		poperror(); 
2001/0331    
 
2001/1108    
	/* dump new line and null terminate */ 
1999/0316    
	if(n > 0 && cb->buf[n-1] == '\n') 
		n--; 
	cb->buf[n] = '\0'; 
2001/0527    
	cb->nf = getfields(cb->buf, cb->f, nelem(cb->f), 1, " "); 
2001/1108    
 
	cb->nf = getfields(cb->buf, cb->f, nf, 1, " "); 
1999/0316    
	return cb; 
} 
 
2001/1108/sys/src/9/port/parse.c:6,112001/1117/sys/src/9/port/parse.c:6,36 (short | long)
Reduce estimate of field count. Change back to tokenize.
rsc Fri Mar 4 12:44:25 2005
1999/0316    
#include	"../port/error.h" 
 
/* 
2001/1117    
 * Generous estimate of number of fields, including terminal nil pointer 
 */ 
static int 
ncmdfield(char *p, int n) 
{ 
	int white, nwhite; 
	char *ep; 
	int nf; 
 
	if(p == nil) 
		return 1; 
 
	nf = 0; 
	ep = p+n; 
	white = 1;	/* first text will start field */ 
	while(p < ep){ 
		nwhite = (strchr(" \t\r\n", *p++ & 0xFF) != 0);	/* UTF is irrelevant */ 
		if(white && !nwhite)	/* beginning of field */ 
			nf++; 
		white = nwhite; 
	} 
	return nf+1;	/* +1 for nil */ 
} 
 
/* 
1999/0316    
 *  parse a command written to a device 
 */ 
Cmdbuf* 
2001/1108/sys/src/9/port/parse.c:15,272001/1117/sys/src/9/port/parse.c:40,52
2001/1108    
	int nf; 
	char *sp; 
1999/0316    
 
2001/1108    
	/* count fields and allocate a big enough cmdbuf */ 
	for(nf = 1, sp = p; sp != nil && *sp; nf++, sp = strchr(sp+1, ' ')) 
		; 
	sp = smalloc(sizeof(*cb) + n + 1 + nf*sizeof(char*)); 
2001/1117    
	nf = ncmdfield(p, n); 
 
	/* allocate Cmdbuf plus string pointers plus copy of string including \0 */ 
	sp = smalloc(sizeof(*cb) + nf * sizeof(char*) + n + 1); 
2001/1108    
	cb = (Cmdbuf*)sp; 
	cb->buf = sp+sizeof(*cb); 
	cb->f = (char**)(cb->buf + n + 1); 
2001/1117    
	cb->f = (char**)(&cb[1]); 
	cb->buf = (char*)(&cb->f[nf]); 
2001/0331    
 
2001/0527    
	if(up!=nil && waserror()){ 
2001/0331    
		free(cb); 
2001/1108/sys/src/9/port/parse.c:36,422001/1117/sys/src/9/port/parse.c:61,69
1999/0316    
		n--; 
	cb->buf[n] = '\0'; 
2001/1108    
 
	cb->nf = getfields(cb->buf, cb->f, nf, 1, " "); 
2001/1117    
	cb->nf = tokenize(cb->buf, cb->f, nf-1); 
	cb->f[cb->nf] = nil; 
 
1999/0316    
	return cb; 
} 
 
2001/1117/sys/src/9/port/parse.c:67,692001/1118/sys/src/9/port/parse.c:67,90 (short | long)
Add lookupcmd.
rsc Fri Mar 4 12:44:25 2005
1999/0316    
	return cb; 
} 
 
2001/1118    
/* 
 * Look up entry in table 
 */ 
Cmdtab* 
lookupcmd(Cmdbuf *cb, Cmdtab *ct, int nct) 
{ 
	int i; 
 
	if(cb->nf == 0) 
		error(Ebadctl); 
 
	for(i=0; i<nct; i++, ct++){ 
		if(strcmp(cb->f[0], ct->cmd) != 0) 
			continue; 
		if(ct->narg!=0 && ct->narg!=cb->nf) 
			error(Eargctl); 
		return ct; 
	} 
	error(Ebadctl); 
	return nil; 
} 
2001/1118/sys/src/9/port/parse.c:68,902001/1120/sys/src/9/port/parse.c:68,114 (short | long)
Add wildcard command. Add cmderror. Better error strings.
rsc Fri Mar 4 12:44:25 2005
1999/0316    
} 
 
2001/1118    
/* 
2001/1120    
 * Reconstruct original message, for error diagnostic 
 */ 
void 
cmderror(Cmdbuf *cb, char *s) 
{ 
	int i; 
	char *p, *e; 
 
	p = up->genbuf; 
	e = p+ERRMAX-10; 
	p = seprint(p, e, "%s \"", s); 
	for(i=0; i<cb->nf; i++){ 
		if(i > 0) 
			p = seprint(p, e, " "); 
		p = seprint(p, e, "%q", cb->f[i]); 
	} 
	strcpy(p, "\""); 
	error(up->genbuf); 
} 
 
/* 
2001/1118    
 * Look up entry in table 
 */ 
Cmdtab* 
lookupcmd(Cmdbuf *cb, Cmdtab *ct, int nct) 
2001/1120    
lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab) 
2001/1118    
{ 
	int i; 
2001/1120    
	Cmdtab *ct; 
2001/1118    
 
	if(cb->nf == 0) 
		error(Ebadctl); 
2001/1120    
		error("empty control message"); 
2001/1118    
 
	for(i=0; i<nct; i++, ct++){ 
		if(strcmp(cb->f[0], ct->cmd) != 0) 
2001/1120    
	for(ct = ctab, i=0; i<nctab; i++, ct++){ 
		if(strcmp(ct->cmd, "*") !=0)	/* wildcard always matches */ 
		if(strcmp(ct->cmd, cb->f[0]) != 0) 
2001/1118    
			continue; 
		if(ct->narg!=0 && ct->narg!=cb->nf) 
			error(Eargctl); 
2001/1120    
		if(ct->narg != 0 && ct->narg != cb->nf) 
			cmderror(cb, Ecmdargs); 
2001/1118    
		return ct; 
	} 
	error(Ebadctl); 
2001/1120    
 
	cmderror(cb, "unknown control message"); 
2001/1118    
	return nil; 
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)