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