xref: /plan9-contrib/sys/src/cmd/mk/lex.c (revision b85a83648eec38fe82b6f00adfd7828ceec5ee8d)
13e12c5d1SDavid du Colombier #include	"mk.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier static	int	bquote(Biobuf*, Bufblock*);
43e12c5d1SDavid du Colombier 
53e12c5d1SDavid du Colombier /*
63e12c5d1SDavid du Colombier  *	Assemble a line skipping blank lines, comments, and eliding
73e12c5d1SDavid du Colombier  *	escaped newlines
83e12c5d1SDavid du Colombier  */
93e12c5d1SDavid du Colombier int
assline(Biobuf * bp,Bufblock * buf)103e12c5d1SDavid du Colombier assline(Biobuf *bp, Bufblock *buf)
113e12c5d1SDavid du Colombier {
123e12c5d1SDavid du Colombier 	int c;
133e12c5d1SDavid du Colombier 	int lastc;
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier 	buf->current=buf->start;
163e12c5d1SDavid du Colombier 	while ((c = nextrune(bp, 1)) >= 0){
17219b2ee8SDavid du Colombier 		switch(c)
18219b2ee8SDavid du Colombier 		{
19*7dd7cddfSDavid du Colombier 		case '\r':		/* consumes CRs for Win95 */
20*7dd7cddfSDavid du Colombier 			continue;
213e12c5d1SDavid du Colombier 		case '\n':
223e12c5d1SDavid du Colombier 			if (buf->current != buf->start) {
233e12c5d1SDavid du Colombier 				insert(buf, 0);
243e12c5d1SDavid du Colombier 				return 1;
253e12c5d1SDavid du Colombier 			}
263e12c5d1SDavid du Colombier 			break;		/* skip empty lines */
27*7dd7cddfSDavid du Colombier 		case '\\':
283e12c5d1SDavid du Colombier 		case '\'':
29*7dd7cddfSDavid du Colombier 		case '"':
303e12c5d1SDavid du Colombier 			rinsert(buf, c);
31*7dd7cddfSDavid du Colombier 			if (escapetoken(bp, buf, 1, c) == 0)
323e12c5d1SDavid du Colombier 				Exit();
333e12c5d1SDavid du Colombier 			break;
343e12c5d1SDavid du Colombier 		case '`':
35*7dd7cddfSDavid du Colombier 			if (bquote(bp, buf) == 0)
363e12c5d1SDavid du Colombier 				Exit();
373e12c5d1SDavid du Colombier 			break;
383e12c5d1SDavid du Colombier 		case '#':
393e12c5d1SDavid du Colombier 			lastc = '#';
403e12c5d1SDavid du Colombier 			while ((c = Bgetc(bp)) != '\n') {
413e12c5d1SDavid du Colombier 				if (c < 0)
423e12c5d1SDavid du Colombier 					goto eof;
43*7dd7cddfSDavid du Colombier 				if(c != '\r')
443e12c5d1SDavid du Colombier 					lastc = c;
453e12c5d1SDavid du Colombier 			}
46*7dd7cddfSDavid du Colombier 			mkinline++;
473e12c5d1SDavid du Colombier 			if (lastc == '\\')
483e12c5d1SDavid du Colombier 				break;		/* propagate escaped newlines??*/
493e12c5d1SDavid du Colombier 			if (buf->current != buf->start) {
503e12c5d1SDavid du Colombier 				insert(buf, 0);
513e12c5d1SDavid du Colombier 				return 1;
523e12c5d1SDavid du Colombier 			}
533e12c5d1SDavid du Colombier 			break;
543e12c5d1SDavid du Colombier 		default:
553e12c5d1SDavid du Colombier 			rinsert(buf, c);
563e12c5d1SDavid du Colombier 			break;
573e12c5d1SDavid du Colombier 		}
583e12c5d1SDavid du Colombier 	}
593e12c5d1SDavid du Colombier eof:
603e12c5d1SDavid du Colombier 	insert(buf, 0);
613e12c5d1SDavid du Colombier 	return *buf->start != 0;
623e12c5d1SDavid du Colombier }
633e12c5d1SDavid du Colombier 
643e12c5d1SDavid du Colombier /*
65*7dd7cddfSDavid du Colombier  *	assemble a back-quoted shell command into a buffer
663e12c5d1SDavid du Colombier  */
673e12c5d1SDavid du Colombier static int
bquote(Biobuf * bp,Bufblock * buf)683e12c5d1SDavid du Colombier bquote(Biobuf *bp, Bufblock *buf)
693e12c5d1SDavid du Colombier {
70*7dd7cddfSDavid du Colombier 	int c, line, term;
713e12c5d1SDavid du Colombier 	int start;
723e12c5d1SDavid du Colombier 
73*7dd7cddfSDavid du Colombier 	line = mkinline;
74219b2ee8SDavid du Colombier 	while((c = Bgetrune(bp)) == ' ' || c == '\t')
75219b2ee8SDavid du Colombier 			;
76*7dd7cddfSDavid du Colombier 	if(c == '{'){
77*7dd7cddfSDavid du Colombier 		term = '}';		/* rc style */
78*7dd7cddfSDavid du Colombier 		while((c = Bgetrune(bp)) == ' ' || c == '\t')
79*7dd7cddfSDavid du Colombier 			;
80*7dd7cddfSDavid du Colombier 	} else
81*7dd7cddfSDavid du Colombier 		term = '`';		/* sh style */
82*7dd7cddfSDavid du Colombier 
833e12c5d1SDavid du Colombier 	start = buf->current-buf->start;
84*7dd7cddfSDavid du Colombier 	for(;c > 0; c = nextrune(bp, 0)){
85*7dd7cddfSDavid du Colombier 		if(c == term){
863e12c5d1SDavid du Colombier 			insert(buf, '\n');
873e12c5d1SDavid du Colombier 			insert(buf,0);
883e12c5d1SDavid du Colombier 			buf->current = buf->start+start;
893e12c5d1SDavid du Colombier 			execinit();
90*7dd7cddfSDavid du Colombier 			execsh(0, buf->current, buf, envy);
913e12c5d1SDavid du Colombier 			return 1;
92*7dd7cddfSDavid du Colombier 		}
93*7dd7cddfSDavid du Colombier 		if(c == '\n')
94*7dd7cddfSDavid du Colombier 			break;
95*7dd7cddfSDavid du Colombier 		if(c == '\'' || c == '"' || c == '\\'){
963e12c5d1SDavid du Colombier 			insert(buf, c);
97*7dd7cddfSDavid du Colombier 			if(!escapetoken(bp, buf, 1, c))
983e12c5d1SDavid du Colombier 				return 0;
993e12c5d1SDavid du Colombier 			continue;
1003e12c5d1SDavid du Colombier 		}
1013e12c5d1SDavid du Colombier 		rinsert(buf, c);
1023e12c5d1SDavid du Colombier 	}
1033e12c5d1SDavid du Colombier 	SYNERR(line);
104*7dd7cddfSDavid du Colombier 	fprint(2, "missing closing %c after `\n", term);
1053e12c5d1SDavid du Colombier 	return 0;
1063e12c5d1SDavid du Colombier }
1073e12c5d1SDavid du Colombier 
1083e12c5d1SDavid du Colombier /*
1093e12c5d1SDavid du Colombier  *	get next character stripping escaped newlines
1103e12c5d1SDavid du Colombier  *	the flag specifies whether escaped newlines are to be elided or
1113e12c5d1SDavid du Colombier  *	replaced with a blank.
1123e12c5d1SDavid du Colombier  */
113*7dd7cddfSDavid du Colombier int
nextrune(Biobuf * bp,int elide)1143e12c5d1SDavid du Colombier nextrune(Biobuf *bp, int elide)
1153e12c5d1SDavid du Colombier {
1163e12c5d1SDavid du Colombier 	int c;
1173e12c5d1SDavid du Colombier 
1183e12c5d1SDavid du Colombier 	for (;;) {
1193e12c5d1SDavid du Colombier 		c = Bgetrune(bp);
1203e12c5d1SDavid du Colombier 		if (c == '\\') {
1213e12c5d1SDavid du Colombier 			if (Bgetrune(bp) == '\n') {
122*7dd7cddfSDavid du Colombier 				mkinline++;
1233e12c5d1SDavid du Colombier 				if (elide)
1243e12c5d1SDavid du Colombier 					continue;
1253e12c5d1SDavid du Colombier 				return ' ';
1263e12c5d1SDavid du Colombier 			}
1273e12c5d1SDavid du Colombier 			Bungetrune(bp);
1283e12c5d1SDavid du Colombier 		}
1293e12c5d1SDavid du Colombier 		if (c == '\n')
130*7dd7cddfSDavid du Colombier 			mkinline++;
1313e12c5d1SDavid du Colombier 		return c;
1323e12c5d1SDavid du Colombier 	}
1333e12c5d1SDavid du Colombier }
134