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/planix-v0/sys/src/cmd/sam/cmd.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 "sam.h"
2
#include "parse.h"
3
 
4
static char	linex[]="\n";
5
static char	wordx[]=" \t\n";
6
Cmdtab cmdtab[]={
7
/*	cmdc	text	regexp	addr	defcmd	defaddr	count	token	 fn	*/
8
	'\n',	0,	0,	0,	0,	aDot,	0,	0,	nl_cmd,
9
	'a',	1,	0,	0,	0,	aDot,	0,	0,	a_cmd,
10
	'b',	0,	0,	0,	0,	aNo,	0,	linex,	b_cmd,
11
	'B',	0,	0,	0,	0,	aNo,	0,	linex,	b_cmd,
12
	'c',	1,	0,	0,	0,	aDot,	0,	0,	c_cmd,
13
	'd',	0,	0,	0,	0,	aDot,	0,	0,	d_cmd,
14
	'D',	0,	0,	0,	0,	aNo,	0,	linex,	D_cmd,
15
	'e',	0,	0,	0,	0,	aNo,	0,	wordx,	e_cmd,
16
	'f',	0,	0,	0,	0,	aNo,	0,	wordx,	f_cmd,
17
	'g',	0,	1,	0,	'p',	aDot,	0,	0,	g_cmd,
18
	'i',	1,	0,	0,	0,	aDot,	0,	0,	i_cmd,
19
	'k',	0,	0,	0,	0,	aDot,	0,	0,	k_cmd,
20
	'm',	0,	0,	1,	0,	aDot,	0,	0,	m_cmd,
21
	'n',	0,	0,	0,	0,	aNo,	0,	0,	n_cmd,
22
	'p',	0,	0,	0,	0,	aDot,	0,	0,	p_cmd,
23
	'q',	0,	0,	0,	0,	aNo,	0,	0,	q_cmd,
24
	'r',	0,	0,	0,	0,	aDot,	0,	wordx,	e_cmd,
25
	's',	0,	1,	0,	0,	aDot,	1,	0,	s_cmd,
26
	't',	0,	0,	1,	0,	aDot,	0,	0,	m_cmd,
27
	'u',	0,	0,	0,	0,	aNo,	2,	0,	u_cmd,
28
	'v',	0,	1,	0,	'p',	aDot,	0,	0,	g_cmd,
29
	'w',	0,	0,	0,	0,	aAll,	0,	wordx,	w_cmd,
30
	'x',	0,	1,	0,	'p',	aDot,	0,	0,	x_cmd,
31
	'y',	0,	1,	0,	'p',	aDot,	0,	0,	x_cmd,
32
	'X',	0,	1,	0,	'f',	aNo,	0,	0,	X_cmd,
33
	'Y',	0,	1,	0,	'f',	aNo,	0,	0,	X_cmd,
34
	'!',	0,	0,	0,	0,	aNo,	0,	linex,	plan9_cmd,
35
	'>',	0,	0,	0,	0,	aDot,	0,	linex,	plan9_cmd,
36
	'<',	0,	0,	0,	0,	aDot,	0,	linex,	plan9_cmd,
37
	'|',	0,	0,	0,	0,	aDot,	0,	linex,	plan9_cmd,
38
	'=',	0,	0,	0,	0,	aDot,	0,	linex,	eq_cmd,
39
	'c'|0x100,0,	0,	0,	0,	aNo,	0,	wordx,	cd_cmd,
40
	0,	0,	0,	0,	0,	0,	0,	0,
41
};
42
Cmd	*parsecmd(int);
43
Addr	*compoundaddr(void);
44
Addr	*simpleaddr(void);
45
void	freecmd(void);
46
void	okdelim(int);
47
 
48
Rune	line[BLOCKSIZE];
49
Rune	termline[BLOCKSIZE];
50
Rune	*linep = line;
51
Rune	*terminp = termline;
52
Rune	*termoutp = termline;
53
 
54
List	cmdlist = { 'p' };
55
List	addrlist = { 'p' };
56
List	relist = { 'p' };
57
List	stringlist = { 'p' };
58
 
59
int	eof;
60
 
61
void
62
resetcmd(void)
63
{
64
	linep = line;
65
	*linep = 0;
66
	terminp = termoutp = termline;
67
	freecmd();
68
}
69
 
70
int
71
inputc(void)
72
{
73
	int n, nbuf;
74
	char buf[UTFmax];
75
	Rune r;
76
 
77
    Again:
78
	nbuf = 0;
79
	if(downloaded){
80
		while(termoutp == terminp){
81
			cmdupdate();
82
			if(patset)
83
				tellpat();
84
			while(termlocked > 0){
85
				outT0(Hunlock);
86
				termlocked--;
87
			}
88
			if(rcv() == 0)
89
				return -1;
90
		}
91
		r = *termoutp++;
92
		if(termoutp == terminp)
93
			terminp = termoutp = termline;
94
	}else{
95
   		do{
96
			n = read(0, buf+nbuf, 1);
97
			if(n <= 0)
98
				return -1;
99
			nbuf += n;
100
		}while(!fullrune(buf, nbuf));
101
		chartorune(&r, buf);
102
	}
103
	if(r == 0){
104
		warn(Wnulls);
105
		goto Again;
106
	}
107
	return r;
108
}
109
 
110
int
111
inputline(void)
112
{
113
	int i, c, start;
114
 
115
	/*
116
	 * Could set linep = line and i = 0 here and just
117
	 * error(Etoolong) below, but this way we keep
118
	 * old input buffer history around for a while.
119
	 * This is useful only for debugging.
120
	 */
121
	i = linep - line;
122
	do{
123
		if((c = inputc())<=0)
124
			return -1;
125
		if(i == nelem(line)-1){
126
			if(linep == line)
127
				error(Etoolong);
128
			start = linep - line;
129
			runemove(line, linep, i-start);
130
			i -= start;
131
			linep = line;
132
		}
133
	}while((line[i++]=c) != '\n');
134
	line[i] = 0;
135
	return 1;
136
}
137
 
138
int
139
getch(void)
140
{
141
	if(eof)
142
		return -1;
143
	if(*linep==0 && inputline()<0){
144
		eof = TRUE;
145
		return -1;
146
	}
147
	return *linep++;
148
}
149
 
150
int
151
nextc(void)
152
{
153
	if(*linep == 0)
154
		return -1;
155
	return *linep;
156
}
157
 
158
void
159
ungetch(void)
160
{
161
	if(--linep < line)
162
		panic("ungetch");
163
}
164
 
165
Posn
166
getnum(int signok)
167
{
168
	Posn n=0;
169
	int c, sign;
170
 
171
	sign = 1;
172
	if(signok>1 && nextc()=='-'){
173
		sign = -1;
174
		getch();
175
	}
176
	if((c=nextc())<'0' || '9'<c)	/* no number defaults to 1 */
177
		return sign;
178
	while('0'<=(c=getch()) && c<='9')
179
		n = n*10 + (c-'0');
180
	ungetch();
181
	return sign*n;
182
}
183
 
184
int
185
skipbl(void)
186
{
187
	int c;
188
	do
189
		c = getch();
190
	while(c==' ' || c=='\t');
191
	if(c >= 0)
192
		ungetch();
193
	return c;
194
}
195
 
196
void
197
termcommand(void)
198
{
199
	Posn p;
200
 
201
	for(p=cmdpt; p<cmd->nc; p++){
202
		if(terminp >= termline+nelem(termline)){
203
			cmdpt = cmd->nc;
204
			error(Etoolong);
205
		}
206
		*terminp++ = filereadc(cmd, p);
207
	}
208
	cmdpt = cmd->nc;
209
}
210
 
211
void
212
cmdloop(void)
213
{
214
	Cmd *cmdp;
215
	File *ocurfile;
216
	int loaded;
217
 
218
	for(;;){
219
		if(!downloaded && curfile && curfile->unread)
220
			load(curfile);
221
		if((cmdp = parsecmd(0))==0){
222
			if(downloaded){
223
				rescue();
224
				exits("eof");
225
			}
226
			break;
227
		}
228
		ocurfile = curfile;
229
		loaded = curfile && !curfile->unread;
230
		if(cmdexec(curfile, cmdp) == 0)
231
			break;
232
		freecmd();
233
		cmdupdate();
234
		update();
235
		if(downloaded && curfile &&
236
		    (ocurfile!=curfile || (!loaded && !curfile->unread)))
237
			outTs(Hcurrent, curfile->tag);
238
			/* don't allow type ahead on files that aren't bound */
239
		if(downloaded && curfile && curfile->rasp == 0)
240
			terminp = termoutp;
241
	}
242
}
243
 
244
Cmd *
245
newcmd(void){
246
	Cmd *p;
247
 
248
	p = emalloc(sizeof(Cmd));
249
	inslist(&cmdlist, cmdlist.nused, p);
250
	return p;
251
}
252
 
253
Addr*
254
newaddr(void)
255
{
256
	Addr *p;
257
 
258
	p = emalloc(sizeof(Addr));
259
	inslist(&addrlist, addrlist.nused, p);
260
	return p;
261
}
262
 
263
String*
264
newre(void)
265
{
266
	String *p;
267
 
268
	p = emalloc(sizeof(String));
269
	inslist(&relist, relist.nused, p);
270
	Strinit(p);
271
	return p;
272
}
273
 
274
String*
275
newstring(void)
276
{
277
	String *p;
278
 
279
	p = emalloc(sizeof(String));
280
	inslist(&stringlist, stringlist.nused, p);
281
	Strinit(p);
282
	return p;
283
}
284
 
285
void
286
freecmd(void)
287
{
288
	int i;
289
 
290
	while(cmdlist.nused > 0)
291
		free(cmdlist.voidpptr[--cmdlist.nused]);
292
	while(addrlist.nused > 0)
293
		free(addrlist.voidpptr[--addrlist.nused]);
294
	while(relist.nused > 0){
295
		i = --relist.nused;
296
		Strclose(relist.stringpptr[i]);
297
		free(relist.stringpptr[i]);
298
	}
299
	while(stringlist.nused>0){
300
		i = --stringlist.nused;
301
		Strclose(stringlist.stringpptr[i]);
302
		free(stringlist.stringpptr[i]);
303
	}
304
}
305
 
306
int
307
lookup(int c)
308
{
309
	int i;
310
 
311
	for(i=0; cmdtab[i].cmdc; i++)
312
		if(cmdtab[i].cmdc == c)
313
			return i;
314
	return -1;
315
}
316
 
317
void
318
okdelim(int c)
319
{
320
	if(c=='\\' || ('a'<=c && c<='z')
321
	|| ('A'<=c && c<='Z') || ('0'<=c && c<='9'))
322
		error_c(Edelim, c);
323
}
324
 
325
void
326
atnl(void)
327
{
328
	skipbl();
329
	if(getch() != '\n')
330
		error(Enewline);
331
}
332
 
333
void
334
getrhs(String *s, int delim, int cmd)
335
{
336
	int c;
337
 
338
	while((c = getch())>0 && c!=delim && c!='\n'){
339
		if(c == '\\'){
340
			if((c=getch()) <= 0)
341
				error(Ebadrhs);
342
			if(c == '\n'){
343
				ungetch();
344
				c='\\';
345
			}else if(c == 'n')
346
				c='\n';
347
			else if(c!=delim && (cmd=='s' || c!='\\'))	/* s does its own */
348
				Straddc(s, '\\');
349
		}
350
		Straddc(s, c);
351
	}
352
	ungetch();	/* let client read whether delimeter, '\n' or whatever */
353
}
354
 
355
String *
356
collecttoken(char *end)
357
{
358
	String *s = newstring();
359
	int c;
360
 
361
	while((c=nextc())==' ' || c=='\t')
362
		Straddc(s, getch()); /* blanks significant for getname() */
363
	while((c=getch())>0 && utfrune(end, c)==0)
364
		Straddc(s, c);
365
	Straddc(s, 0);
366
	if(c != '\n')
367
		atnl();
368
	return s;
369
}
370
 
371
String *
372
collecttext(void)
373
{
374
	String *s = newstring();
375
	int begline, i, c, delim;
376
 
377
	if(skipbl()=='\n'){
378
		getch();
379
		i = 0;
380
		do{
381
			begline = i;
382
			while((c = getch())>0 && c!='\n')
383
				i++, Straddc(s, c);
384
			i++, Straddc(s, '\n');
385
			if(c < 0)
386
				goto Return;
387
		}while(s->s[begline]!='.' || s->s[begline+1]!='\n');
388
		Strdelete(s, s->n-2, s->n);
389
	}else{
390
		okdelim(delim = getch());
391
		getrhs(s, delim, 'a');
392
		if(nextc()==delim)
393
			getch();
394
		atnl();
395
	}
396
    Return:
397
	Straddc(s, 0);		/* JUST FOR CMDPRINT() */
398
	return s;
399
}
400
 
401
Cmd *
402
parsecmd(int nest)
403
{
404
	int i, c;
405
	Cmdtab *ct;
406
	Cmd *cp, *ncp;
407
	Cmd cmd;
408
 
409
	cmd.next = cmd.ccmd = 0;
410
	cmd.re = 0;
411
	cmd.flag = cmd.num = 0;
412
	cmd.addr = compoundaddr();
413
	if(skipbl() == -1)
414
		return 0;
415
	if((c=getch())==-1)
416
		return 0;
417
	cmd.cmdc = c;
418
	if(cmd.cmdc=='c' && nextc()=='d'){	/* sleazy two-character case */
419
		getch();		/* the 'd' */
420
		cmd.cmdc='c'|0x100;
421
	}
422
	i = lookup(cmd.cmdc);
423
	if(i >= 0){
424
		if(cmd.cmdc == '\n')
425
			goto Return;	/* let nl_cmd work it all out */
426
		ct = &cmdtab[i];
427
		if(ct->defaddr==aNo && cmd.addr)
428
			error(Enoaddr);
429
		if(ct->count)
430
			cmd.num = getnum(ct->count);
431
		if(ct->regexp){
432
			/* x without pattern -> .*\n, indicated by cmd.re==0 */
433
			/* X without pattern is all files */
434
			if((ct->cmdc!='x' && ct->cmdc!='X') ||
435
			   ((c = nextc())!=' ' && c!='\t' && c!='\n')){
436
				skipbl();
437
				if((c = getch())=='\n' || c<0)
438
					error(Enopattern);
439
				okdelim(c);
440
				cmd.re = getregexp(c);
441
				if(ct->cmdc == 's'){
442
					cmd.ctext = newstring();
443
					getrhs(cmd.ctext, c, 's');
444
					if(nextc() == c){
445
						getch();
446
						if(nextc() == 'g')
447
							cmd.flag = getch();
448
					}
449
 
450
				}
451
			}
452
		}
453
		if(ct->addr && (cmd.caddr=simpleaddr())==0)
454
			error(Eaddress);
455
		if(ct->defcmd){
456
			if(skipbl() == '\n'){
457
				getch();
458
				cmd.ccmd = newcmd();
459
				cmd.ccmd->cmdc = ct->defcmd;
460
			}else if((cmd.ccmd = parsecmd(nest))==0)
461
				panic("defcmd");
462
		}else if(ct->text)
463
			cmd.ctext = collecttext();
464
		else if(ct->token)
465
			cmd.ctext = collecttoken(ct->token);
466
		else
467
			atnl();
468
	}else
469
		switch(cmd.cmdc){
470
		case '{':
471
			cp = 0;
472
			do{
473
				if(skipbl()=='\n')
474
					getch();
475
				ncp = parsecmd(nest+1);
476
				if(cp)
477
					cp->next = ncp;
478
				else
479
					cmd.ccmd = ncp;
480
			}while(cp = ncp);
481
			break;
482
		case '}':
483
			atnl();
484
			if(nest==0)
485
				error(Enolbrace);
486
			return 0;
487
		default:
488
			error_c(Eunk, cmd.cmdc);
489
		}
490
    Return:
491
	cp = newcmd();
492
	*cp = cmd;
493
	return cp;
494
}
495
 
496
String*				/* BUGGERED */
497
getregexp(int delim)
498
{
499
	String *r = newre();
500
	int c;
501
 
502
	for(Strzero(&genstr); ; Straddc(&genstr, c))
503
		if((c = getch())=='\\'){
504
			if(nextc()==delim)
505
				c = getch();
506
			else if(nextc()=='\\'){
507
				Straddc(&genstr, c);
508
				c = getch();
509
			}
510
		}else if(c==delim || c=='\n')
511
			break;
512
	if(c!=delim && c)
513
		ungetch();
514
	if(genstr.n > 0){
515
		patset = TRUE;
516
		Strduplstr(&lastpat, &genstr);
517
		Straddc(&lastpat, '\0');
518
	}
519
	if(lastpat.n <= 1)
520
		error(Epattern);
521
	Strduplstr(r, &lastpat);
522
	return r;
523
}
524
 
525
Addr *
526
simpleaddr(void)
527
{
528
	Addr addr;
529
	Addr *ap, *nap;
530
 
531
	addr.next = 0;
532
	addr.left = 0;
533
	switch(skipbl()){
534
	case '#':
535
		addr.type = getch();
536
		addr.num = getnum(1);
537
		break;
538
	case '0': case '1': case '2': case '3': case '4':
539
	case '5': case '6': case '7': case '8': case '9': 
540
		addr.num = getnum(1);
541
		addr.type='l';
542
		break;
543
	case '/': case '?': case '"':
544
		addr.are = getregexp(addr.type = getch());
545
		break;
546
	case '.':
547
	case '$':
548
	case '+':
549
	case '-':
550
	case '\'':
551
		addr.type = getch();
552
		break;
553
	default:
554
		return 0;
555
	}
556
	if(addr.next = simpleaddr())
557
		switch(addr.next->type){
558
		case '.':
559
		case '$':
560
		case '\'':
561
			if(addr.type!='"')
562
		case '"':
563
				error(Eaddress);
564
			break;
565
		case 'l':
566
		case '#':
567
			if(addr.type=='"')
568
				break;
569
			/* fall through */
570
		case '/':
571
		case '?':
572
			if(addr.type!='+' && addr.type!='-'){
573
				/* insert the missing '+' */
574
				nap = newaddr();
575
				nap->type='+';
576
				nap->next = addr.next;
577
				addr.next = nap;
578
			}
579
			break;
580
		case '+':
581
		case '-':
582
			break;
583
		default:
584
			panic("simpleaddr");
585
		}
586
	ap = newaddr();
587
	*ap = addr;
588
	return ap;
589
}
590
 
591
Addr *
592
compoundaddr(void)
593
{
594
	Addr addr;
595
	Addr *ap, *next;
596
 
597
	addr.left = simpleaddr();
598
	if((addr.type = skipbl())!=',' && addr.type!=';')
599
		return addr.left;
600
	getch();
601
	next = addr.next = compoundaddr();
602
	if(next && (next->type==',' || next->type==';') && next->left==0)
603
		error(Eaddress);
604
	ap = newaddr();
605
	*ap = addr;
606
	return ap;
607
}