sh.c (3427B)
1 #include "mk.h" 2 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 */ 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-quote, 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-quote, 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 quotes above. 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 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 } 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 attribute*/ 199 ' ', /* inter-word separator in env */ 200 shcharin, 201 shexpandquote, 202 shescapetoken, 203 shcopyq, 204 shmatchname 205 }; 206