| #include	"mk.h" | 
 |  | 
 | /* | 
 |  *	This file contains functions that depend on the shell's syntax.  Most | 
 |  *	of the routines extract strings observing the shell's escape conventions. | 
 |  */ | 
 |  | 
 |  | 
 | /* | 
 |  *	skip a token in quotes. | 
 |  */ | 
 | static char * | 
 | squote(char *cp, int c) | 
 | { | 
 | 	Rune r; | 
 | 	int n; | 
 |  | 
 | 	while(*cp){ | 
 | 		n = chartorune(&r, cp); | 
 | 		if(r == c) | 
 | 			return cp; | 
 | 		if(r == '\\') | 
 | 			n += chartorune(&r, cp+n); | 
 | 		cp += n; | 
 | 	} | 
 | 	SYNERR(-1);		/* should never occur */ | 
 | 	fprint(2, "missing closing '\n"); | 
 | 	return 0; | 
 | } | 
 | /* | 
 |  *	search a string for unescaped characters in a pattern set | 
 |  */ | 
 | static char * | 
 | shcharin(char *cp, char *pat) | 
 | { | 
 | 	Rune r; | 
 | 	int n, vargen; | 
 |  | 
 | 	vargen = 0; | 
 | 	while(*cp){ | 
 | 		n = chartorune(&r, cp); | 
 | 		switch(r){ | 
 | 		case '\\':			/* skip escaped char */ | 
 | 			cp += n; | 
 | 			n = chartorune(&r, cp); | 
 | 			break; | 
 | 		case '\'':			/* skip quoted string */ | 
 | 		case '"': | 
 | 			cp = squote(cp+1, r);	/* n must = 1 */ | 
 | 			if(!cp) | 
 | 				return 0; | 
 | 			break; | 
 | 		case '$': | 
 | 			if(*(cp+1) == '{') | 
 | 				vargen = 1; | 
 | 			break; | 
 | 		case '}': | 
 | 			if(vargen) | 
 | 				vargen = 0; | 
 | 			else if(utfrune(pat, r)) | 
 | 				return cp; | 
 | 			break; | 
 | 		default: | 
 | 			if(vargen == 0 && utfrune(pat, r)) | 
 | 				return cp; | 
 | 			break; | 
 | 		} | 
 | 		cp += n; | 
 | 	} | 
 | 	if(vargen){ | 
 | 		SYNERR(-1); | 
 | 		fprint(2, "missing closing } in pattern generator\n"); | 
 | 	} | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* | 
 |  *	extract an escaped token.  Possible escape chars are single-quote, | 
 |  *	double-quote,and backslash. | 
 |  */ | 
 | static char* | 
 | shexpandquote(char *s, Rune esc, Bufblock *b) | 
 | { | 
 | 	Rune r; | 
 |  | 
 | 	if (esc == '\\') { | 
 | 		s += chartorune(&r, s); | 
 | 		rinsert(b, r); | 
 | 		return s; | 
 | 	} | 
 |  | 
 | 	while(*s){ | 
 | 		s += chartorune(&r, s); | 
 | 		if(r == esc) | 
 | 			return s; | 
 | 		if (r == '\\') { | 
 | 			rinsert(b, r); | 
 | 			s += chartorune(&r, s); | 
 | 		} | 
 | 		rinsert(b, r); | 
 | 	} | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* | 
 |  *	Input an escaped token.  Possible escape chars are single-quote, | 
 |  *	double-quote and backslash. | 
 |  */ | 
 | static int | 
 | shescapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc) | 
 | { | 
 | 	int c, line; | 
 |  | 
 | 	if(esc == '\\') { | 
 | 		c = Bgetrune(bp); | 
 | 		if(c == '\r') | 
 | 			c = Bgetrune(bp); | 
 | 		if (c == '\n') | 
 | 			mkinline++; | 
 | 		rinsert(buf, c); | 
 | 		return 1; | 
 | 	} | 
 |  | 
 | 	line = mkinline; | 
 | 	while((c = nextrune(bp, 0)) >= 0){ | 
 | 		if(c == esc){ | 
 | 			if(preserve) | 
 | 				rinsert(buf, c); | 
 | 			return 1; | 
 | 		} | 
 | 		if(c == '\\') { | 
 | 			rinsert(buf, c); | 
 | 			c = Bgetrune(bp); | 
 | 			if(c == '\r') | 
 | 				c = Bgetrune(bp); | 
 | 			if (c < 0) | 
 | 				break; | 
 | 			if (c == '\n') | 
 | 				mkinline++; | 
 | 		} | 
 | 		rinsert(buf, c); | 
 | 	} | 
 | 	SYNERR(line); fprint(2, "missing closing %c\n", esc); | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* | 
 |  *	copy a quoted string; s points to char after opening quote | 
 |  */ | 
 | static char * | 
 | copysingle(char *s, Rune q, Bufblock *buf) | 
 | { | 
 | 	Rune r; | 
 |  | 
 | 	while(*s){ | 
 | 		s += chartorune(&r, s); | 
 | 		rinsert(buf, r); | 
 | 		if(r == q) | 
 | 			break; | 
 | 	} | 
 | 	return s; | 
 | } | 
 | /* | 
 |  *	check for quoted strings.  backquotes are handled here; single quotes above. | 
 |  *	s points to char after opening quote, q. | 
 |  */ | 
 | static char * | 
 | shcopyq(char *s, Rune q, Bufblock *buf) | 
 | { | 
 | 	if(q == '\'' || q == '"')		/* copy quoted string */ | 
 | 		return copysingle(s, q, buf); | 
 |  | 
 | 	if(q != '`')				/* not quoted */ | 
 | 		return s; | 
 |  | 
 | 	while(*s){				/* copy backquoted string */ | 
 | 		s += chartorune(&q, s); | 
 | 		rinsert(buf, q); | 
 | 		if(q == '`') | 
 | 			break; | 
 | 		if(q == '\'' || q == '"') | 
 | 			s = copysingle(s, q, buf);	/* copy quoted string */ | 
 | 	} | 
 | 	return s; | 
 | } | 
 |  | 
 | static int | 
 | shmatchname(char *name) | 
 | { | 
 | 	USED(name); | 
 |  | 
 | 	return 1; | 
 | } | 
 |  | 
 |  | 
 | Shell shshell = { | 
 | 	"sh", | 
 | 	"\"'= \t",	/*used in parse.c to isolate assignment attribute*/ | 
 | 	' ',	/* inter-word separator in env */ | 
 | 	shcharin, | 
 | 	shexpandquote, | 
 | 	shescapetoken, | 
 | 	shcopyq, | 
 | 	shmatchname | 
 | }; | 
 |  |