| #include	"mk.h" | 
 |  | 
 | static	int	bquote(Biobuf*, Bufblock*); | 
 |  | 
 | /* | 
 |  *	Assemble a line skipping blank lines, comments, and eliding | 
 |  *	escaped newlines | 
 |  */ | 
 | int | 
 | assline(Biobuf *bp, Bufblock *buf) | 
 | { | 
 | 	int c; | 
 | 	int lastc; | 
 |  | 
 | 	buf->current=buf->start; | 
 | 	while ((c = nextrune(bp, 1)) >= 0){ | 
 | 		switch(c) | 
 | 		{ | 
 | 		case '\r':		/* consumes CRs for Win95 */ | 
 | 			continue; | 
 | 		case '\n': | 
 | 			if (buf->current != buf->start) { | 
 | 				insert(buf, 0); | 
 | 				return 1; | 
 | 			} | 
 | 			break;		/* skip empty lines */ | 
 | 		case '\\': | 
 | 		case '\'': | 
 | 		case '"': | 
 | 			rinsert(buf, c); | 
 | 			if (shellt->escapetoken(bp, buf, 1, c) == 0) | 
 | 				Exit(); | 
 | 			break; | 
 | 		case '`': | 
 | 			if (bquote(bp, buf) == 0) | 
 | 				Exit(); | 
 | 			break; | 
 | 		case '#': | 
 | 			lastc = '#'; | 
 | 			while ((c = Bgetc(bp)) != '\n') { | 
 | 				if (c < 0) | 
 | 					goto eof; | 
 | 				if(c != '\r') | 
 | 					lastc = c; | 
 | 			} | 
 | 			mkinline++; | 
 | 			if (lastc == '\\') | 
 | 				break;		/* propagate escaped newlines??*/ | 
 | 			if (buf->current != buf->start) { | 
 | 				insert(buf, 0); | 
 | 				return 1; | 
 | 			} | 
 | 			break; | 
 | 		default: | 
 | 			rinsert(buf, c); | 
 | 			break; | 
 | 		} | 
 | 	} | 
 | eof: | 
 | 	insert(buf, 0); | 
 | 	return *buf->start != 0; | 
 | } | 
 |  | 
 | /* | 
 |  *	assemble a back-quoted shell command into a buffer | 
 |  */ | 
 | static int | 
 | bquote(Biobuf *bp, Bufblock *buf) | 
 | { | 
 | 	int c, line, term; | 
 | 	int start; | 
 |  | 
 | 	line = mkinline; | 
 | 	while((c = Bgetrune(bp)) == ' ' || c == '\t') | 
 | 			; | 
 | 	if(c == '{'){ | 
 | 		term = '}';		/* rc style */ | 
 | 		while((c = Bgetrune(bp)) == ' ' || c == '\t') | 
 | 			; | 
 | 	} else | 
 | 		term = '`';		/* sh style */ | 
 |  | 
 | 	start = buf->current-buf->start; | 
 | 	for(;c > 0; c = nextrune(bp, 0)){ | 
 | 		if(c == term){ | 
 | 			insert(buf, '\n'); | 
 | 			insert(buf,0); | 
 | 			buf->current = buf->start+start; | 
 | 			execinit(); | 
 | 			execsh(0, buf->current, buf, envy, shellt, shellcmd); | 
 | 			return 1; | 
 | 		} | 
 | 		if(c == '\n') | 
 | 			break; | 
 | 		if(c == '\'' || c == '"' || c == '\\'){ | 
 | 			insert(buf, c); | 
 | 			if(!shellt->escapetoken(bp, buf, 1, c)) | 
 | 				return 0; | 
 | 			continue; | 
 | 		} | 
 | 		rinsert(buf, c); | 
 | 	} | 
 | 	SYNERR(line); | 
 | 	fprint(2, "missing closing %c after `\n", term); | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* | 
 |  *	get next character stripping escaped newlines | 
 |  *	the flag specifies whether escaped newlines are to be elided or | 
 |  *	replaced with a blank. | 
 |  */ | 
 | int | 
 | nextrune(Biobuf *bp, int elide) | 
 | { | 
 | 	int c, c2; | 
 | 	static int savec; | 
 |  | 
 | 	if(savec){ | 
 | 		c = savec; | 
 | 		savec = 0; | 
 | 		return c; | 
 | 	} | 
 |  | 
 | 	for (;;) { | 
 | 		c = Bgetrune(bp); | 
 | 		if (c == '\\') { | 
 | 			c2 = Bgetrune(bp); | 
 | 			if(c2 == '\r'){ | 
 | 				savec = c2; | 
 | 				c2 = Bgetrune(bp); | 
 | 			} | 
 | 			if (c2 == '\n') { | 
 | 				savec = 0; | 
 | 				mkinline++; | 
 | 				if (elide) | 
 | 					continue; | 
 | 				return ' '; | 
 | 			} | 
 | 			Bungetrune(bp); | 
 | 		} | 
 | 		if (c == '\n') | 
 | 			mkinline++; | 
 | 		return c; | 
 | 	} | 
 | } |