tsh.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
tsh.c (3426B) | |
--- | |
1 #include "mk.h" | |
2 | |
3 /* | |
4 * This file contains functions that depend on the shell's syntax… | |
5 * of the routines extract strings observing the shell's escape c… | |
6 */ | |
7 | |
8 | |
9 /* | |
10 * skip a token in quotes. | |
11 */ | |
12 static char * | |
13 squote(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 */ | |
33 static char * | |
34 shcharin(char *cp, char *pat) | |
35 { | |
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-qu… | |
79 * double-quote,and backslash. | |
80 */ | |
81 static char* | |
82 shexpandquote(char *s, Rune esc, Bufblock *b) | |
83 { | |
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-quot… | |
107 * double-quote and backslash. | |
108 */ | |
109 static int | |
110 shescapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc) | |
111 { | |
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 */ | |
150 static char * | |
151 copysingle(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… | |
165 * s points to char after opening quote, q. | |
166 */ | |
167 static char * | |
168 shcopyq(char *s, Rune q, Bufblock *buf) | |
169 { | |
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 str… | |
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… | |
183 } | |
184 return s; | |
185 } | |
186 | |
187 static int | |
188 shmatchname(char *name) | |
189 { | |
190 USED(name); | |
191 | |
192 return 1; | |
193 } | |
194 | |
195 | |
196 Shell shshell = { | |
197 "sh", | |
198 "\"'= \t", /*used in parse.c to isolate assignment attrib… | |
199 ' ', /* inter-word separator in env */ | |
200 shcharin, | |
201 shexpandquote, | |
202 shescapetoken, | |
203 shcopyq, | |
204 shmatchname | |
205 }; |