Blob


1 #include "mk.h"
3 /*
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 */
9 /*
10 * skip a token in quotes.
11 */
12 static char *
13 squote(char *cp, int c)
14 {
15 Rune r;
16 int n;
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;
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 }
77 /*
78 * extract an escaped token. Possible escape chars are single-quote,
79 * double-quote,and backslash.
80 */
81 static char*
82 shexpandquote(char *s, Rune esc, Bufblock *b)
83 {
84 Rune r;
86 if (esc == '\\') {
87 s += chartorune(&r, s);
88 rinsert(b, r);
89 return s;
90 }
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);
102 return 0;
105 /*
106 * Input an escaped token. Possible escape chars are single-quote,
107 * double-quote and backslash.
108 */
109 static int
110 shescapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc)
112 int c, line;
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;
124 line = mkinline;
125 while((c = nextrune(bp, 0)) >= 0){
126 if(c == esc){
127 if(preserve)
128 rinsert(buf, c);
129 return 1;
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++;
141 rinsert(buf, c);
143 SYNERR(line); fprint(2, "missing closing %c\n", esc);
144 return 0;
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)
153 Rune r;
155 while(*s){
156 s += chartorune(&r, s);
157 rinsert(buf, r);
158 if(r == q)
159 break;
161 return s;
163 /*
164 * check for quoted strings. backquotes are handled here; single quotes above.
165 * s points to char after opening quote, q.
166 */
167 static char *
168 shcopyq(char *s, Rune q, Bufblock *buf)
170 if(q == '\'' || q == '"') /* copy quoted string */
171 return copysingle(s, q, buf);
173 if(q != '`') /* not quoted */
174 return s;
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 */
184 return s;
187 static int
188 shmatchname(char *name)
190 USED(name);
192 return 1;
196 Shell 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,
204 shmatchname
205 };