Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/rc/lex.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "rc.h"
2
#include "exec.h"
3
#include "io.h"
4
#include "getflags.h"
5
#include "fns.h"
6
int getnext(void);
7
 
8
int
9
wordchr(int c)
10
{
11
	return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF;
12
}
13
 
14
int
15
idchr(int c)
16
{
17
	/*
18
	 * Formerly:
19
	 * return 'a'<=c && c<='z' || 'A'<=c && c<='Z' || '0'<=c && c<='9'
20
	 *	|| c=='_' || c=='*';
21
	 */
22
	return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
23
}
24
int future = EOF;
25
int doprompt = 1;
26
int inquote;
27
int incomm;
28
/*
29
 * Look ahead in the input stream
30
 */
31
 
32
int
33
nextc(void)
34
{
35
	if(future==EOF)
36
		future = getnext();
37
	return future;
38
}
39
/*
40
 * Consume the lookahead character.
41
 */
42
 
43
int
44
advance(void)
45
{
46
	int c = nextc();
47
	lastc = future;
48
	future = EOF;
49
	return c;
50
}
51
/*
52
 * read a character from the input stream
53
 */	
54
 
55
int
56
getnext(void)
57
{
58
	int c;
59
	static int peekc = EOF;
60
	if(peekc!=EOF){
61
		c = peekc;
62
		peekc = EOF;
63
		return c;
64
	}
65
	if(runq->eof)
66
		return EOF;
67
	if(doprompt)
68
		pprompt();
69
	c = rchr(runq->cmdfd);
70
	if(!inquote && c=='\\'){
71
		c = rchr(runq->cmdfd);
72
		if(c=='\n' && !incomm){		/* don't continue a comment */
73
			doprompt = 1;
74
			c=' ';
75
		}
76
		else{
77
			peekc = c;
78
			c='\\';
79
		}
80
	}
81
	doprompt = doprompt || c=='\n' || c==EOF;
82
	if(c==EOF)
83
		runq->eof++;
84
	else if(flag['V'] || ndot>=2 && flag['v']) pchr(err, c);
85
	return c;
86
}
87
 
88
void
89
pprompt(void)
90
{
91
	var *prompt;
92
	if(runq->iflag){
93
		pstr(err, promptstr);
94
		flush(err);
95
		prompt = vlook("prompt");
96
		if(prompt->val && prompt->val->next)
97
			promptstr = prompt->val->next->word;
98
		else
99
			promptstr="\t";
100
	}
101
	runq->lineno++;
102
	doprompt = 0;
103
}
104
 
105
void
106
skipwhite(void)
107
{
108
	int c;
109
	for(;;){
110
		c = nextc();
111
		/* Why did this used to be  if(!inquote && c=='#') ?? */
112
		if(c=='#'){
113
			incomm = 1;
114
			for(;;){
115
				c = nextc();
116
				if(c=='\n' || c==EOF) {
117
					incomm = 0;
118
					break;
119
				}
120
				advance();
121
			}
122
		}
123
		if(c==' ' || c=='\t')
124
			advance();
125
		else return;
126
	}
127
}
128
 
129
void
130
skipnl(void)
131
{
132
	int c;
133
	for(;;){
134
		skipwhite();
135
		c = nextc();
136
		if(c!='\n')
137
			return;
138
		advance();
139
	}
140
}
141
 
142
int
143
nextis(int c)
144
{
145
	if(nextc()==c){
146
		advance();
147
		return 1;
148
	}
149
	return 0;
150
}
151
 
152
char*
153
addtok(char *p, int val)
154
{
155
	if(p==0)
156
		return 0;
157
	if(p >= &tok[NTOK]){
158
		*p = 0;
159
		yyerror("token buffer too short");
160
		return 0;
161
	}
162
	*p++=val;
163
	return p;
164
}
165
 
166
char*
167
addutf(char *p, int c)
168
{
169
	uchar b, m;
170
	int i;
171
 
172
	p = addtok(p, c);	/* 1-byte UTF runes are special */
173
	if(c < Runeself)
174
		return p;
175
 
176
	m = 0xc0;
177
	b = 0x80;
178
	for(i=1; i < UTFmax; i++){
179
		if((c&m) == b)
180
			break;
181
		p = addtok(p, advance());
182
		b = m;
183
		m = (m >> 1)|0x80;
184
	}
185
	return p;
186
}
187
 
188
int lastdol;	/* was the last token read '$' or '$#' or '"'? */
189
int lastword;	/* was the last token read a word or compound word terminator? */
190
 
191
int
192
yylex(void)
193
{
194
	int c, d = nextc();
195
	char *w = tok;
196
	struct tree *t;
197
	yylval.tree = 0;
198
	/*
199
	 * Embarassing sneakiness:  if the last token read was a quoted or unquoted
200
	 * WORD then we alter the meaning of what follows.  If the next character
201
	 * is `(', we return SUB (a subscript paren) and consume the `('.  Otherwise,
202
	 * if the next character is the first character of a simple or compound word,
203
	 * we insert a `^' before it.
204
	 */
205
	if(lastword){
206
		lastword = 0;
207
		if(d=='('){
208
			advance();
209
			strcpy(tok, "( [SUB]");
210
			return SUB;
211
		}
212
		if(wordchr(d) || d=='\'' || d=='`' || d=='$' || d=='"'){
213
			strcpy(tok, "^");
214
			return '^';
215
		}
216
	}
217
	inquote = 0;
218
	skipwhite();
219
	switch(c = advance()){
220
	case EOF:
221
		lastdol = 0;
222
		strcpy(tok, "EOF");
223
		return EOF;
224
	case '$':
225
		lastdol = 1;
226
		if(nextis('#')){
227
			strcpy(tok, "$#");
228
			return COUNT;
229
		}
230
		if(nextis('"')){
231
			strcpy(tok, "$\"");
232
			return '"';
233
		}
234
		strcpy(tok, "$");
235
		return '$';
236
	case '&':
237
		lastdol = 0;
238
		if(nextis('&')){
239
			skipnl();
240
			strcpy(tok, "&&");
241
			return ANDAND;
242
		}
243
		strcpy(tok, "&");
244
		return '&';
245
	case '|':
246
		lastdol = 0;
247
		if(nextis(c)){
248
			skipnl();
249
			strcpy(tok, "||");
250
			return OROR;
251
		}
252
	case '<':
253
	case '>':
254
		lastdol = 0;
255
		/*
256
		 * funny redirection tokens:
257
		 *	redir:	arrow | arrow '[' fd ']'
258
		 *	arrow:	'<' | '<<' | '>' | '>>' | '|'
259
		 *	fd:	digit | digit '=' | digit '=' digit
260
		 *	digit:	'0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'
261
		 * some possibilities are nonsensical and get a message.
262
		 */
263
		*w++=c;
264
		t = newtree();
265
		switch(c){
266
		case '|':
267
			t->type = PIPE;
268
			t->fd0 = 1;
269
			t->fd1 = 0;
270
			break;
271
		case '>':
272
			t->type = REDIR;
273
			if(nextis(c)){
274
				t->rtype = APPEND;
275
				*w++=c;
276
			}
277
			else t->rtype = WRITE;
278
			t->fd0 = 1;
279
			break;
280
		case '<':
281
			t->type = REDIR;
282
			if(nextis(c)){
283
				t->rtype = HERE;
284
				*w++=c;
285
			} else if (nextis('>')){
286
				t->rtype = RDWR;
287
				*w++=c;
288
			} else t->rtype = READ;
289
			t->fd0 = 0;
290
			break;
291
		}
292
		if(nextis('[')){
293
			*w++='[';
294
			c = advance();
295
			*w++=c;
296
			if(c<'0' || '9'<c){
297
			RedirErr:
298
				*w = 0;
299
				yyerror(t->type==PIPE?"pipe syntax"
300
						:"redirection syntax");
301
				return EOF;
302
			}
303
			t->fd0 = 0;
304
			do{
305
				t->fd0 = t->fd0*10+c-'0';
306
				*w++=c;
307
				c = advance();
308
			}while('0'<=c && c<='9');
309
			if(c=='='){
310
				*w++='=';
311
				if(t->type==REDIR)
312
					t->type = DUP;
313
				c = advance();
314
				if('0'<=c && c<='9'){
315
					t->rtype = DUPFD;
316
					t->fd1 = t->fd0;
317
					t->fd0 = 0;
318
					do{
319
						t->fd0 = t->fd0*10+c-'0';
320
						*w++=c;
321
						c = advance();
322
					}while('0'<=c && c<='9');
323
				}
324
				else{
325
					if(t->type==PIPE)
326
						goto RedirErr;
327
					t->rtype = CLOSE;
328
				}
329
			}
330
			if(c!=']'
331
			|| t->type==DUP && (t->rtype==HERE || t->rtype==APPEND))
332
				goto RedirErr;
333
			*w++=']';
334
		}
335
		*w='\0';
336
		yylval.tree = t;
337
		if(t->type==PIPE)
338
			skipnl();
339
		return t->type;
340
	case '\'':
341
		lastdol = 0;
342
		lastword = 1;
343
		inquote = 1;
344
		for(;;){
345
			c = advance();
346
			if(c==EOF)
347
				break;
348
			if(c=='\''){
349
				if(nextc()!='\'')
350
					break;
351
				advance();
352
			}
353
			w = addutf(w, c);
354
		}
355
		if(w!=0)
356
			*w='\0';
357
		t = token(tok, WORD);
358
		t->quoted = 1;
359
		yylval.tree = t;
360
		return t->type;
361
	}
362
	if(!wordchr(c)){
363
		lastdol = 0;
364
		tok[0] = c;
365
		tok[1]='\0';
366
		return c;
367
	}
368
	for(;;){
369
		if(c=='*' || c=='[' || c=='?' || c==GLOB)
370
			w = addtok(w, GLOB);
371
		w = addutf(w, c);
372
		c = nextc();
373
		if(lastdol?!idchr(c):!wordchr(c)) break;
374
		advance();
375
	}
376
 
377
	lastword = 1;
378
	lastdol = 0;
379
	if(w!=0)
380
		*w='\0';
381
	t = klook(tok);
382
	if(t->type!=WORD)
383
		lastword = 0;
384
	t->quoted = 0;
385
	yylval.tree = t;
386
	return t->type;
387
}