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