xref: /plan9/sys/src/cmd/mk/lex.c (revision b85a83648eec38fe82b6f00adfd7828ceec5ee8d)
1 #include	"mk.h"
2 
3 static	int	bquote(Biobuf*, Bufblock*);
4 
5 /*
6  *	Assemble a line skipping blank lines, comments, and eliding
7  *	escaped newlines
8  */
9 int
assline(Biobuf * bp,Bufblock * buf)10 assline(Biobuf *bp, Bufblock *buf)
11 {
12 	int c;
13 	int lastc;
14 
15 	buf->current=buf->start;
16 	while ((c = nextrune(bp, 1)) >= 0){
17 		switch(c)
18 		{
19 		case '\r':		/* consumes CRs for Win95 */
20 			continue;
21 		case '\n':
22 			if (buf->current != buf->start) {
23 				insert(buf, 0);
24 				return 1;
25 			}
26 			break;		/* skip empty lines */
27 		case '\\':
28 		case '\'':
29 		case '"':
30 			rinsert(buf, c);
31 			if (escapetoken(bp, buf, 1, c) == 0)
32 				Exit();
33 			break;
34 		case '`':
35 			if (bquote(bp, buf) == 0)
36 				Exit();
37 			break;
38 		case '#':
39 			lastc = '#';
40 			while ((c = Bgetc(bp)) != '\n') {
41 				if (c < 0)
42 					goto eof;
43 				if(c != '\r')
44 					lastc = c;
45 			}
46 			mkinline++;
47 			if (lastc == '\\')
48 				break;		/* propagate escaped newlines??*/
49 			if (buf->current != buf->start) {
50 				insert(buf, 0);
51 				return 1;
52 			}
53 			break;
54 		default:
55 			rinsert(buf, c);
56 			break;
57 		}
58 	}
59 eof:
60 	insert(buf, 0);
61 	return *buf->start != 0;
62 }
63 
64 /*
65  *	assemble a back-quoted shell command into a buffer
66  */
67 static int
bquote(Biobuf * bp,Bufblock * buf)68 bquote(Biobuf *bp, Bufblock *buf)
69 {
70 	int c, line, term;
71 	int start;
72 
73 	line = mkinline;
74 	while((c = Bgetrune(bp)) == ' ' || c == '\t')
75 			;
76 	if(c == '{'){
77 		term = '}';		/* rc style */
78 		while((c = Bgetrune(bp)) == ' ' || c == '\t')
79 			;
80 	} else
81 		term = '`';		/* sh style */
82 
83 	start = buf->current-buf->start;
84 	for(;c > 0; c = nextrune(bp, 0)){
85 		if(c == term){
86 			insert(buf, '\n');
87 			insert(buf,0);
88 			buf->current = buf->start+start;
89 			execinit();
90 			execsh(0, buf->current, buf, envy);
91 			return 1;
92 		}
93 		if(c == '\n')
94 			break;
95 		if(c == '\'' || c == '"' || c == '\\'){
96 			insert(buf, c);
97 			if(!escapetoken(bp, buf, 1, c))
98 				return 0;
99 			continue;
100 		}
101 		rinsert(buf, c);
102 	}
103 	SYNERR(line);
104 	fprint(2, "missing closing %c after `\n", term);
105 	return 0;
106 }
107 
108 /*
109  *	get next character stripping escaped newlines
110  *	the flag specifies whether escaped newlines are to be elided or
111  *	replaced with a blank.
112  */
113 int
nextrune(Biobuf * bp,int elide)114 nextrune(Biobuf *bp, int elide)
115 {
116 	int c;
117 
118 	for (;;) {
119 		c = Bgetrune(bp);
120 		if (c == '\\') {
121 			if (Bgetrune(bp) == '\n') {
122 				mkinline++;
123 				if (elide)
124 					continue;
125 				return ' ';
126 			}
127 			Bungetrune(bp);
128 		}
129 		if (c == '\n')
130 			mkinline++;
131 		return c;
132 	}
133 }
134