xref: /inferno-os/utils/mk/sh.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1 #include	"mk.h"
2 
3 char	*termchars = "\"'= \t";	/*used in parse.c to isolate assignment attribute*/
4 char	*shflags = 0;
5 int	IWS = ' ';		/* inter-word separator in env */
6 
7 /*
8  *	This file contains functions that depend on the shell's syntax.  Most
9  *	of the routines extract strings observing the shell's escape conventions.
10  */
11 
12 
13 /*
14  *	skip a token in quotes.
15  */
16 static char *
squote(char * cp,int c)17 squote(char *cp, int c)
18 {
19 	Rune r;
20 	int n;
21 
22 	while(*cp){
23 		n = chartorune(&r, cp);
24 		if(r == c)
25 			return cp;
26 		if(r == '\\')
27 			n += chartorune(&r, cp+n);
28 		cp += n;
29 	}
30 	SYNERR(-1);		/* should never occur */
31 	fprint(2, "missing closing '\n");
32 	return 0;
33 }
34 /*
35  *	search a string for unescaped characters in a pattern set
36  */
37 char *
charin(char * cp,char * pat)38 charin(char *cp, char *pat)
39 {
40 	Rune r;
41 	int n, vargen;
42 
43 	vargen = 0;
44 	while(*cp){
45 		n = chartorune(&r, cp);
46 		switch(r){
47 		case '\\':			/* skip escaped char */
48 			cp += n;
49 			n = chartorune(&r, cp);
50 			break;
51 		case '\'':			/* skip quoted string */
52 		case '"':
53 			cp = squote(cp+1, r);	/* n must = 1 */
54 			if(!cp)
55 				return 0;
56 			break;
57 		case '$':
58 			if(*(cp+1) == '{')
59 				vargen = 1;
60 			break;
61 		case '}':
62 			if(vargen)
63 				vargen = 0;
64 			else if(utfrune(pat, r))
65 				return cp;
66 			break;
67 		default:
68 			if(vargen == 0 && utfrune(pat, r))
69 				return cp;
70 			break;
71 		}
72 		cp += n;
73 	}
74 	if(vargen){
75 		SYNERR(-1);
76 		fprint(2, "missing closing } in pattern generator\n");
77 	}
78 	return 0;
79 }
80 
81 /*
82  *	extract an escaped token.  Possible escape chars are single-quote,
83  *	double-quote,and backslash.
84  */
85 char*
expandquote(char * s,Rune esc,Bufblock * b)86 expandquote(char *s, Rune esc, Bufblock *b)
87 {
88 	Rune r;
89 
90 	if (esc == '\\') {
91 		s += chartorune(&r, s);
92 		rinsert(b, r);
93 		return s;
94 	}
95 
96 	while(*s){
97 		s += chartorune(&r, s);
98 		if(r == esc)
99 			return s;
100 		if (r == '\\') {
101 			rinsert(b, r);
102 			s += chartorune(&r, s);
103 		}
104 		rinsert(b, r);
105 	}
106 	return 0;
107 }
108 
109 /*
110  *	Input an escaped token.  Possible escape chars are single-quote,
111  *	double-quote and backslash.
112  */
113 int
escapetoken(Biobuf * bp,Bufblock * buf,int preserve,int esc)114 escapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc)
115 {
116 	int c, line;
117 
118 	if(esc == '\\') {
119 		c = Bgetrune(bp);
120 		if(c == '\r')
121 			c = Bgetrune(bp);
122 		if (c == '\n')
123 			mkinline++;
124 		rinsert(buf, c);
125 		return 1;
126 	}
127 
128 	line = mkinline;
129 	while((c = nextrune(bp, 0)) >= 0){
130 		if(c == esc){
131 			if(preserve)
132 				rinsert(buf, c);
133 			return 1;
134 		}
135 		if(c == '\\') {
136 			rinsert(buf, c);
137 			c = Bgetrune(bp);
138 			if(c == '\r')
139 				c = Bgetrune(bp);
140 			if (c < 0)
141 				break;
142 			if (c == '\n')
143 				mkinline++;
144 		}
145 		rinsert(buf, c);
146 	}
147 	SYNERR(line); fprint(2, "missing closing %c\n", esc);
148 	return 0;
149 }
150 
151 /*
152  *	copy a quoted string; s points to char after opening quote
153  */
154 static char *
copysingle(char * s,Rune q,Bufblock * buf)155 copysingle(char *s, Rune q, Bufblock *buf)
156 {
157 	Rune r;
158 
159 	while(*s){
160 		s += chartorune(&r, s);
161 		rinsert(buf, r);
162 		if(r == q)
163 			break;
164 	}
165 	return s;
166 }
167 /*
168  *	check for quoted strings.  backquotes are handled here; single quotes above.
169  *	s points to char after opening quote, q.
170  */
171 char *
copyq(char * s,Rune q,Bufblock * buf)172 copyq(char *s, Rune q, Bufblock *buf)
173 {
174 	if(q == '\'' || q == '"')		/* copy quoted string */
175 		return copysingle(s, q, buf);
176 
177 	if(q != '`')				/* not quoted */
178 		return s;
179 
180 	while(*s){				/* copy backquoted string */
181 		s += chartorune(&q, s);
182 		rinsert(buf, q);
183 		if(q == '`')
184 			break;
185 		if(q == '\'' || q == '"')
186 			s = copysingle(s, q, buf);	/* copy quoted string */
187 	}
188 	return s;
189 }
190