Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "sam.h"
2
#include "parse.h"
3
 
4
int	Glooping;
5
int	nest;
6
 
7
int	append(File*, Cmd*, Posn);
8
int	display(File*);
9
void	looper(File*, Cmd*, int);
10
void	filelooper(Cmd*, int);
11
void	linelooper(File*, Cmd*);
12
 
13
void
14
resetxec(void)
15
{
16
	Glooping = nest = 0;
17
}
18
 
19
int
20
cmdexec(File *f, Cmd *cp)
21
{
22
	int i;
23
	Addr *ap;
24
	Address a;
25
 
26
	if(f && f->unread)
27
		load(f);
28
	if(f==0 && (cp->addr==0 || cp->addr->type!='"') &&
29
	    !utfrune("bBnqUXY!", cp->cmdc) &&
30
	    cp->cmdc!=('c'|0x100) && !(cp->cmdc=='D' && cp->ctext))
31
		error(Enofile);
32
	i = lookup(cp->cmdc);
33
	if(i >= 0 && cmdtab[i].defaddr != aNo){
34
		if((ap=cp->addr)==0 && cp->cmdc!='\n'){
35
			cp->addr = ap = newaddr();
36
			ap->type = '.';
37
			if(cmdtab[i].defaddr == aAll)
38
				ap->type = '*';
39
		}else if(ap && ap->type=='"' && ap->next==0 && cp->cmdc!='\n'){
40
			ap->next = newaddr();
41
			ap->next->type = '.';
42
			if(cmdtab[i].defaddr == aAll)
43
				ap->next->type = '*';
44
		}
45
		if(cp->addr){	/* may be false for '\n' (only) */
46
			static Address none = {0,0,0};
47
			if(f)
48
				addr = address(ap, f->dot, 0);
49
			else	/* a " */
50
				addr = address(ap, none, 0);
51
			f = addr.f;
52
		}
53
	}
54
	current(f);
55
	switch(cp->cmdc){
56
	case '{':
57
		a = cp->addr? address(cp->addr, f->dot, 0): f->dot;
58
		for(cp = cp->ccmd; cp; cp = cp->next){
59
			a.f->dot = a;
60
			cmdexec(a.f, cp);
61
		}
62
		break;
63
	default:
64
		i=(*cmdtab[i].fn)(f, cp);
65
		return i;
66
	}
67
	return 1;
68
}
69
 
70
 
71
int
72
a_cmd(File *f, Cmd *cp)
73
{
74
	return append(f, cp, addr.r.p2);
75
}
76
 
77
int
78
b_cmd(File *f, Cmd *cp)
79
{
80
	USED(f);
81
	f = cp->cmdc=='b'? tofile(cp->ctext) : getfile(cp->ctext);
82
	if(f->unread)
83
		load(f);
84
	else if(nest == 0)
85
		filename(f);
86
	return TRUE;
87
}
88
 
89
int
90
c_cmd(File *f, Cmd *cp)
91
{
92
	logdelete(f, addr.r.p1, addr.r.p2);
93
	f->ndot.r.p1 = f->ndot.r.p2 = addr.r.p2;
94
	return append(f, cp, addr.r.p2);
95
}
96
 
97
int
98
d_cmd(File *f, Cmd *cp)
99
{
100
	USED(cp);
101
	logdelete(f, addr.r.p1, addr.r.p2);
102
	f->ndot.r.p1 = f->ndot.r.p2 = addr.r.p1;
103
	return TRUE;
104
}
105
 
106
int
107
D_cmd(File *f, Cmd *cp)
108
{
109
	closefiles(f, cp->ctext);
110
	return TRUE;
111
}
112
 
113
int
114
e_cmd(File *f, Cmd *cp)
115
{
116
	if(getname(f, cp->ctext, cp->cmdc=='e')==0)
117
		error(Enoname);
118
	edit(f, cp->cmdc);
119
	return TRUE;
120
}
121
 
122
int
123
f_cmd(File *f, Cmd *cp)
124
{
125
	getname(f, cp->ctext, TRUE);
126
	filename(f);
127
	return TRUE;
128
}
129
 
130
int
131
g_cmd(File *f, Cmd *cp)
132
{
133
	if(f!=addr.f)panic("g_cmd f!=addr.f");
134
	compile(cp->re);
135
	if(execute(f, addr.r.p1, addr.r.p2) ^ cp->cmdc=='v'){
136
		f->dot = addr;
137
		return cmdexec(f, cp->ccmd);
138
	}
139
	return TRUE;
140
}
141
 
142
int
143
i_cmd(File *f, Cmd *cp)
144
{
145
	return append(f, cp, addr.r.p1);
146
}
147
 
148
int
149
k_cmd(File *f, Cmd *cp)
150
{
151
	USED(cp);
152
	f->mark = addr.r;
153
	return TRUE;
154
}
155
 
156
int
157
m_cmd(File *f, Cmd *cp)
158
{
159
	Address addr2;
160
 
161
	addr2 = address(cp->caddr, f->dot, 0);
162
	if(cp->cmdc=='m')
163
		move(f, addr2);
164
	else
165
		copy(f, addr2);
166
	return TRUE;
167
}
168
 
169
int
170
n_cmd(File *f, Cmd *cp)
171
{
172
	int i;
173
	USED(f);
174
	USED(cp);
175
	for(i = 0; i<file.nused; i++){
176
		if(file.filepptr[i] == cmd)
177
			continue;
178
		f = file.filepptr[i];
179
		Strduplstr(&genstr, &f->name);
180
		filename(f);
181
	}
182
	return TRUE;
183
}
184
 
185
int
186
p_cmd(File *f, Cmd *cp)
187
{
188
	USED(cp);
189
	return display(f);
190
}
191
 
192
int
193
q_cmd(File *f, Cmd *cp)
194
{
195
	USED(cp);
196
	USED(f);
197
	trytoquit();
198
	if(downloaded){
199
		outT0(Hexit);
200
		return TRUE;
201
	}
202
	return FALSE;
203
}
204
 
205
int
206
s_cmd(File *f, Cmd *cp)
207
{
208
	int i, j, c, n;
209
	Posn p1, op, didsub = 0, delta = 0;
210
 
211
	n = cp->num;
212
	op= -1;
213
	compile(cp->re);
214
	for(p1 = addr.r.p1; p1<=addr.r.p2 && execute(f, p1, addr.r.p2); ){
215
		if(sel.p[0].p1==sel.p[0].p2){	/* empty match? */
216
			if(sel.p[0].p1==op){
217
				p1++;
218
				continue;
219
			}
220
			p1 = sel.p[0].p2+1;
221
		}else
222
			p1 = sel.p[0].p2;
223
		op = sel.p[0].p2;
224
		if(--n>0)
225
			continue;
226
		Strzero(&genstr);
227
		for(i = 0; i<cp->ctext->n; i++)
228
			if((c = cp->ctext->s[i])=='\\' && i<cp->ctext->n-1){
229
				c = cp->ctext->s[++i];
230
				if('1'<=c && c<='9') {
231
					j = c-'0';
232
					if(sel.p[j].p2-sel.p[j].p1>BLOCKSIZE)
233
						error(Elongtag);
234
					bufread(f, sel.p[j].p1, genbuf, sel.p[j].p2-sel.p[j].p1);
235
					Strinsert(&genstr, tmprstr(genbuf, (sel.p[j].p2-sel.p[j].p1)), genstr.n);
236
				}else
237
				 	Straddc(&genstr, c);
238
			}else if(c!='&')
239
				Straddc(&genstr, c);
240
			else{
241
				if(sel.p[0].p2-sel.p[0].p1>BLOCKSIZE)
242
					error(Elongrhs);
243
				bufread(f, sel.p[0].p1, genbuf, sel.p[0].p2-sel.p[0].p1);
244
				Strinsert(&genstr,
245
					tmprstr(genbuf, (int)(sel.p[0].p2-sel.p[0].p1)),
246
					genstr.n);
247
			}
248
		if(sel.p[0].p1!=sel.p[0].p2){
249
			logdelete(f, sel.p[0].p1, sel.p[0].p2);
250
			delta-=sel.p[0].p2-sel.p[0].p1;
251
		}
252
		if(genstr.n){
253
			loginsert(f, sel.p[0].p2, genstr.s, genstr.n);
254
			delta+=genstr.n;
255
		}
256
		didsub = 1;
257
		if(!cp->flag)
258
			break;
259
	}
260
	if(!didsub && nest==0)
261
		error(Enosub);
262
	f->ndot.r.p1 = addr.r.p1, f->ndot.r.p2 = addr.r.p2+delta;
263
	return TRUE;
264
}
265
 
266
int
267
u_cmd(File *f, Cmd *cp)
268
{
269
	int n;
270
 
271
	USED(f);
272
	USED(cp);
273
	n = cp->num;
274
	if(n >= 0)
275
		while(n-- && undo(TRUE))
276
			;
277
	else
278
		while(n++ && undo(FALSE))
279
			;
280
	return TRUE;
281
}
282
 
283
int
284
w_cmd(File *f, Cmd *cp)
285
{
286
	int fseq;
287
 
288
	fseq = f->seq;
289
	if(getname(f, cp->ctext, FALSE)==0)
290
		error(Enoname);
291
	if(fseq == seq)
292
		error_s(Ewseq, genc);
293
	writef(f);
294
	return TRUE;
295
}
296
 
297
int
298
x_cmd(File *f, Cmd *cp)
299
{
300
	if(cp->re)
301
		looper(f, cp, cp->cmdc=='x');
302
	else
303
		linelooper(f, cp);
304
	return TRUE;
305
}
306
 
307
int
308
X_cmd(File *f, Cmd *cp)
309
{
310
	USED(f);
311
	filelooper(cp, cp->cmdc=='X');
312
	return TRUE;
313
}
314
 
315
int
316
plan9_cmd(File *f, Cmd *cp)
317
{
318
	plan9(f, cp->cmdc, cp->ctext, nest);
319
	return TRUE;
320
}
321
 
322
int
323
eq_cmd(File *f, Cmd *cp)
324
{
325
	int charsonly;
326
 
327
	switch(cp->ctext->n){
328
	case 1:
329
		charsonly = FALSE;
330
		break;
331
	case 2:
332
		if(cp->ctext->s[0]=='#'){
333
			charsonly = TRUE;
334
			break;
335
		}
336
	default:
337
		SET(charsonly);
338
		error(Enewline);
339
	}
340
	printposn(f, charsonly);
341
	return TRUE;
342
}
343
 
344
int
345
nl_cmd(File *f, Cmd *cp)
346
{
347
	Address a;
348
 
349
	if(cp->addr == 0){
350
		/* First put it on newline boundaries */
351
		addr = lineaddr((Posn)0, f->dot, -1);
352
		a = lineaddr((Posn)0, f->dot, 1);
353
		addr.r.p2 = a.r.p2;
354
		if(addr.r.p1==f->dot.r.p1 && addr.r.p2==f->dot.r.p2)
355
			addr = lineaddr((Posn)1, f->dot, 1);
356
		display(f);
357
	}else if(downloaded)
358
		moveto(f, addr.r);
359
	else
360
		display(f);
361
	return TRUE;
362
}
363
 
364
int
365
cd_cmd(File *f, Cmd *cp)
366
{
367
	USED(f);
368
	cd(cp->ctext);
369
	return TRUE;
370
}
371
 
372
int
373
append(File *f, Cmd *cp, Posn p)
374
{
375
	if(cp->ctext->n>0 && cp->ctext->s[cp->ctext->n-1]==0)
376
		--cp->ctext->n;
377
	if(cp->ctext->n>0)
378
		loginsert(f, p, cp->ctext->s, cp->ctext->n);
379
	f->ndot.r.p1 = p;
380
	f->ndot.r.p2 = p+cp->ctext->n;
381
	return TRUE;
382
}
383
 
384
int
385
display(File *f)
386
{
387
	Posn p1, p2;
388
	int np;
389
	char *c;
390
 
391
	p1 = addr.r.p1;
392
	p2 = addr.r.p2;
393
	if(p2 > f->nc){
394
		fprint(2, "bad display addr p1=%ld p2=%ld f->nc=%d\n", p1, p2, f->nc); /*ZZZ should never happen, can remove */
395
		p2 = f->nc;
396
	}
397
	while(p1 < p2){
398
		np = p2-p1;
399
		if(np>BLOCKSIZE-1)
400
			np = BLOCKSIZE-1;
401
		bufread(f, p1, genbuf, np);
402
		genbuf[np] = 0;
403
		c = Strtoc(tmprstr(genbuf, np+1));
404
		if(downloaded)
405
			termwrite(c);
406
		else
407
			Write(1, c, strlen(c));
408
		free(c);
409
		p1 += np;
410
	}
411
	f->dot = addr;
412
	return TRUE;
413
}
414
 
415
void
416
looper(File *f, Cmd *cp, int xy)
417
{
418
	Posn p, op;
419
	Range r;
420
 
421
	r = addr.r;
422
	op= xy? -1 : r.p1;
423
	nest++;
424
	compile(cp->re);
425
	for(p = r.p1; p<=r.p2; ){
426
		if(!execute(f, p, r.p2)){ /* no match, but y should still run */
427
			if(xy || op>r.p2)
428
				break;
429
			f->dot.r.p1 = op, f->dot.r.p2 = r.p2;
430
			p = r.p2+1;	/* exit next loop */
431
		}else{
432
			if(sel.p[0].p1==sel.p[0].p2){	/* empty match? */
433
				if(sel.p[0].p1==op){
434
					p++;
435
					continue;
436
				}
437
				p = sel.p[0].p2+1;
438
			}else
439
				p = sel.p[0].p2;
440
			if(xy)
441
				f->dot.r = sel.p[0];
442
			else
443
				f->dot.r.p1 = op, f->dot.r.p2 = sel.p[0].p1;
444
		}
445
		op = sel.p[0].p2;
446
		cmdexec(f, cp->ccmd);
447
		compile(cp->re);
448
	}
449
	--nest;
450
}
451
 
452
void
453
linelooper(File *f, Cmd *cp)
454
{
455
	Posn p;
456
	Range r, linesel;
457
	Address a, a3;
458
 
459
	nest++;
460
	r = addr.r;
461
	a3.f = f;
462
	a3.r.p1 = a3.r.p2 = r.p1;
463
	for(p = r.p1; p<r.p2; p = a3.r.p2){
464
		a3.r.p1 = a3.r.p2;
465
/*pjw		if(p!=r.p1 || (linesel = lineaddr((Posn)0, a3, 1)).r.p2==p)*/
466
		if(p!=r.p1 || (a = lineaddr((Posn)0, a3, 1), linesel = a.r, linesel.p2==p)){
467
			a = lineaddr((Posn)1, a3, 1);
468
			linesel = a.r;
469
		}
470
		if(linesel.p1 >= r.p2)
471
			break;
472
		if(linesel.p2 >= r.p2)
473
			linesel.p2 = r.p2;
474
		if(linesel.p2 > linesel.p1)
475
			if(linesel.p1>=a3.r.p2 && linesel.p2>a3.r.p2){
476
				f->dot.r = linesel;
477
				cmdexec(f, cp->ccmd);
478
				a3.r = linesel;
479
				continue;
480
			}
481
		break;
482
	}
483
	--nest;
484
}
485
 
486
void
487
filelooper(Cmd *cp, int XY)
488
{
489
	File *f, *cur;
490
	int i;
491
 
492
	if(Glooping++)
493
		error(EnestXY);
494
	nest++;
495
	settempfile();
496
	cur = curfile;
497
	for(i = 0; i<tempfile.nused; i++){
498
		f = tempfile.filepptr[i];
499
		if(f==cmd)
500
			continue;
501
		if(cp->re==0 || filematch(f, cp->re)==XY)
502
			cmdexec(f, cp->ccmd);
503
	}
504
	if(cur && whichmenu(cur)>=0)	/* check that cur is still a file */
505
		current(cur);
506
	--Glooping;
507
	--nest;
508
}