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