Blob


1 #include "mk.h"
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 */
9 /*
10 * skip a token in single quotes.
11 */
12 static char *
13 squote(char *cp)
14 {
15 Rune r;
16 int n;
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 }
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;
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 }
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 }
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 }
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)
109 int c, line;
111 if(esc != '\'')
112 return 1;
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;
127 rinsert(buf, c);
129 SYNERR(line); fprint(2, "missing closing %c\n", esc);
130 return 0;
133 /*
134 * copy a single-quoted string; s points to char after opening quote
135 */
136 static char *
137 copysingle(char *s, Bufblock *buf)
139 Rune r;
141 while(*s){
142 s += chartorune(&r, s);
143 rinsert(buf, r);
144 if(r == '\'')
145 break;
147 return s;
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)
156 if(q == '\'') /* copy quoted string */
157 return copysingle(s, buf);
159 if(q != '`') /* not quoted */
160 return s;
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 */
170 return s;
173 static int
174 rcmatchname(char *name)
176 char *p;
178 if((p = strrchr(name, '/')) != nil)
179 name = p+1;
180 if(name[0] == 'r' && name[1] == 'c')
181 return 1;
182 return 0;
185 Shell rcshell = {
186 "rc",
187 "'= \t",
188 '\1',
189 rccharin,
190 rcexpandquote,
191 rcescapetoken,
192 rccopyq,
193 rcmatchname
194 };