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 <stdlib.h>
2
#include <sys/types.h>
3
#include <fcntl.h>
4
#include <unistd.h>
5
#include	<stdio.h>
6
#include "sed.h"
7
 
8
#define Read(f, buf, n)	(fflush(stdout), read(f, buf, n))
9
 
10
void
11
execute(uchar *file)
12
{
13
	uchar *p1, *p2;
14
	union reptr	*ipc;
15
	int	c;
16
	long	l;
17
	uchar	*execp;
18
 
19
	if (file) {
20
		if ((f = open((char*)file, O_RDONLY)) < 0) {
21
			fprintf(stderr, "sed: Can't open %s\n", file);
22
		}
23
	} else
24
		f = 0;
25
 
26
	ebp = ibuf;
27
	cbp = ibuf;
28
 
29
	if(pending) {
30
		ipc = pending;
31
		pending = 0;
32
		goto yes;
33
	}
34
 
35
	for(;;) {
36
		if((execp = gline(linebuf)) == badp) {
37
			close(f);
38
			return;
39
		}
40
		spend = execp;
41
 
42
		for(ipc = ptrspace; ipc->r1.command; ) {
43
 
44
			p1 = ipc->r1.ad1;
45
			p2 = ipc->r1.ad2;
46
 
47
			if(p1) {
48
 
49
				if(ipc->r1.inar) {
50
					if(*p2 == CEND) {
51
						p1 = 0;
52
					} else if(*p2 == CLNUM) {
53
						l = p2[1]&0377
54
							| ((p2[2]&0377)<<8)
55
							| ((p2[3]&0377)<<16)
56
							| ((p2[4]&0377)<<24);
57
						if(lnum > l) {
58
							ipc->r1.inar = 0;
59
							if(ipc->r1.negfl)
60
								goto yes;
61
							ipc++;
62
							continue;
63
						}
64
						if(lnum == l) {
65
							ipc->r1.inar = 0;
66
						}
67
					} else if(match(p2, 0)) {
68
						ipc->r1.inar = 0;
69
					}
70
				} else if(*p1 == CEND) {
71
					if(!dolflag) {
72
						if(ipc->r1.negfl)
73
							goto yes;
74
						ipc++;
75
						continue;
76
					}
77
 
78
				} else if(*p1 == CLNUM) {
79
					l = p1[1]&0377
80
						| ((p1[2]&0377)<<8)
81
						| ((p1[3]&0377)<<16)
82
						| ((p1[4]&0377)<<24);
83
					if(lnum != l) {
84
						if(ipc->r1.negfl)
85
							goto yes;
86
						ipc++;
87
						continue;
88
					}
89
					if(p2)
90
						ipc->r1.inar = 1;
91
				} else if(match(p1, 0)) {
92
					if(p2)
93
						ipc->r1.inar = 1;
94
				} else {
95
					if(ipc->r1.negfl)
96
						goto yes;
97
					ipc++;
98
					continue;
99
				}
100
			}
101
 
102
			if(ipc->r1.negfl) {
103
				ipc++;
104
				continue;
105
			}
106
	yes:
107
			command(ipc);
108
 
109
			if(delflag)
110
				break;
111
 
112
			if(jflag) {
113
				jflag = 0;
114
				if((ipc = ipc->r2.lb1) == 0) {
115
					ipc = ptrspace;
116
					break;
117
				}
118
			} else
119
				ipc++;
120
 
121
		}
122
		if(!nflag && !delflag) {
123
			for(p1 = linebuf; p1 < spend; p1++)
124
				putc(*p1, stdout);
125
			putc('\n', stdout);
126
		}
127
 
128
		if(aptr > abuf) {
129
			arout();
130
		}
131
 
132
		delflag = 0;
133
 
134
	}
135
}
136
int
137
match(uchar *expbuf, int gf)
138
{
139
	uchar	*p1, *p2;
140
	int c;
141
 
142
	if(gf) {
143
		if(*expbuf)	return(0);
144
		p1 = linebuf;
145
		p2 = genbuf;
146
		while(*p1++ = *p2++);
147
		locs = p1 = loc2;
148
	} else {
149
		p1 = linebuf;
150
		locs = 0;
151
	}
152
 
153
	p2 = expbuf;
154
	if(*p2++) {
155
		loc1 = p1;
156
		if(*p2 == CCHR && p2[1] != *p1)
157
			return(0);
158
		return(advance(p1, p2));
159
	}
160
 
161
	/* fast check for first character */
162
 
163
	if(*p2 == CCHR) {
164
		c = p2[1];
165
		do {
166
			if(*p1 != c)
167
				continue;
168
			if(advance(p1, p2)) {
169
				loc1 = p1;
170
				return(1);
171
			}
172
		} while(*p1++);
173
		return(0);
174
	}
175
 
176
	do {
177
		if(advance(p1, p2)) {
178
			loc1 = p1;
179
			return(1);
180
		}
181
	} while(*p1++);
182
	return(0);
183
}
184
int
185
advance(uchar *alp, uchar *aep)
186
{
187
	uchar *lp, *ep, *curlp;
188
	uchar	c;
189
	uchar *bbeg;
190
	int	ct;
191
 
192
/*fprintf(stderr, "*lp = %c, %o\n*ep = %c, %o\n", *lp, *lp, *ep, *ep);	/*DEBUG*/
193
 
194
	lp = alp;
195
	ep = aep;
196
	for (;;) switch (*ep++) {
197
 
198
	case CCHR:
199
		if (*ep++ == *lp++)
200
			continue;
201
		return(0);
202
 
203
	case CDOT:
204
		if (*lp++)
205
			continue;
206
		return(0);
207
 
208
	case CNL:
209
	case CDOL:
210
		if (*lp == 0)
211
			continue;
212
		return(0);
213
 
214
	case CEOF:
215
		loc2 = lp;
216
		return(1);
217
 
218
	case CCL:
219
		c = *lp++;
220
		if(ep[c>>3] & bittab[c & 07]) {
221
			ep += 32;
222
			continue;
223
		}
224
		return(0);
225
 
226
	case CBRA:
227
		braslist[*ep++] = lp;
228
		continue;
229
 
230
	case CKET:
231
		braelist[*ep++] = lp;
232
		continue;
233
 
234
	case CBACK:
235
		bbeg = braslist[*ep];
236
		ct = braelist[*ep++] - bbeg;
237
 
238
		if(ecmp(bbeg, lp, ct)) {
239
			lp += ct;
240
			continue;
241
		}
242
		return(0);
243
 
244
	case CBACK|STAR:
245
		bbeg = braslist[*ep];
246
		ct = braelist[*ep++] - bbeg;
247
		curlp = lp;
248
		while(ecmp(bbeg, lp, ct))
249
			lp += ct;
250
 
251
		while(lp >= curlp) {
252
			if(advance(lp, ep))	return(1);
253
			lp -= ct;
254
		}
255
		return(0);
256
 
257
 
258
	case CDOT|STAR:
259
		curlp = lp;
260
		while (*lp++);
261
		goto star;
262
 
263
	case CCHR|STAR:
264
		curlp = lp;
265
		while (*lp++ == *ep);
266
		ep++;
267
		goto star;
268
 
269
	case CCL|STAR:
270
		curlp = lp;
271
		do {
272
			c = *lp++;
273
		} while(ep[c>>3] & bittab[c & 07]);
274
		ep += 32;
275
		goto star;
276
 
277
	star:
278
		if(--lp == curlp) {
279
			continue;
280
		}
281
 
282
		if(*ep == CCHR) {
283
			c = ep[1];
284
			do {
285
				if(*lp != c)
286
					continue;
287
				if(advance(lp, ep))
288
					return(1);
289
			} while(lp-- > curlp);
290
			return(0);
291
		}
292
 
293
		if(*ep == CBACK) {
294
			c = *(braslist[ep[1]]);
295
			do {
296
				if(*lp != c)
297
					continue;
298
				if(advance(lp, ep))
299
					return(1);
300
			} while(lp-- > curlp);
301
			return(0);
302
		}
303
 
304
		do {
305
			if(lp == locs)	break;
306
			if (advance(lp, ep))
307
				return(1);
308
		} while (lp-- > curlp);
309
		return(0);
310
 
311
	default:
312
		fprintf(stderr, "sed:  RE botch, %o\n", *--ep);
313
		exit(1);
314
	}
315
}
316
int
317
substitute(union reptr *ipc)
318
{
319
	uchar	*oloc2;
320
 
321
	if(match(ipc->r1.re1, 0)) {
322
 
323
		sflag = 1;
324
		if(!ipc->r1.gfl) {
325
			dosub(ipc->r1.rhs);
326
			return(1);
327
		}
328
 
329
		oloc2 = NULL;
330
		do {
331
			if(oloc2 == loc2) {
332
				loc2++;
333
				continue;
334
			} else {
335
				dosub(ipc->r1.rhs);
336
				if(*loc2 == 0)
337
					break;
338
				oloc2 = loc2;
339
			}
340
		} while(match(ipc->r1.re1, 1));
341
		return(1);
342
	}
343
	return(0);
344
}
345
 
346
void
347
dosub(uchar *rhsbuf)
348
{
349
	uchar *lp, *sp, *rp;
350
	int c;
351
 
352
	lp = linebuf;
353
	sp = genbuf;
354
	rp = rhsbuf;
355
	while (lp < loc1)
356
		*sp++ = *lp++;
357
	while(c = *rp++) {
358
		if (c == '\\') {
359
			c = *rp++;
360
			if (c >= '1' && c < NBRA+'1') {
361
				sp = place(sp, braslist[c-'1'], braelist[c-'1']);
362
				continue;
363
			}
364
		} else if(c == '&') {
365
				sp = place(sp, loc1, loc2);
366
				continue;
367
		}
368
		*sp++ = c;
369
		if (sp >= &genbuf[LBSIZE])
370
			fprintf(stderr, "sed: Output line too long.\n");
371
	}
372
	lp = loc2;
373
	loc2 = sp - genbuf + linebuf;
374
	while (*sp++ = *lp++)
375
		if (sp >= &genbuf[LBSIZE]) {
376
			fprintf(stderr, "sed: Output line too long.\n");
377
		}
378
	lp = linebuf;
379
	sp = genbuf;
380
	while (*lp++ = *sp++);
381
	spend = lp-1;
382
}
383
uchar *
384
place(uchar *asp, uchar *al1, uchar *al2)
385
{
386
	uchar *sp, *l1, *l2;
387
 
388
	sp = asp;
389
	l1 = al1;
390
	l2 = al2;
391
	while (l1 < l2) {
392
		*sp++ = *l1++;
393
		if (sp >= &genbuf[LBSIZE])
394
			fprintf(stderr, "sed: Output line too long.\n");
395
	}
396
	return(sp);
397
}
398
 
399
void
400
command(union reptr *ipc)
401
{
402
	int	i;
403
	uchar	*p1, *p2;
404
	uchar	*execp;
405
 
406
 
407
	switch(ipc->r1.command) {
408
 
409
		case ACOM:
410
			*aptr++ = ipc;
411
			if(aptr >= &abuf[ABUFSIZE]) {
412
				fprintf(stderr, "sed: Too many appends after line %ld\n",
413
					lnum);
414
			}
415
			*aptr = 0;
416
			break;
417
 
418
		case CCOM:
419
			delflag = 1;
420
			if(!ipc->r1.inar || dolflag) {
421
				for(p1 = ipc->r1.re1; *p1; )
422
					putc(*p1++, stdout);
423
				putc('\n', stdout);
424
			}
425
			break;
426
		case DCOM:
427
			delflag++;
428
			break;
429
		case CDCOM:
430
			p1 = p2 = linebuf;
431
 
432
			while(*p1 != '\n') {
433
				if(*p1++ == 0) {
434
					delflag++;
435
					return;
436
				}
437
			}
438
 
439
			p1++;
440
			while(*p2++ = *p1++);
441
			spend = p2-1;
442
			jflag++;
443
			break;
444
 
445
		case EQCOM:
446
			fprintf(stdout, "%ld\n", lnum);
447
			break;
448
 
449
		case GCOM:
450
			p1 = linebuf;
451
			p2 = holdsp;
452
			while(*p1++ = *p2++);
453
			spend = p1-1;
454
			break;
455
 
456
		case CGCOM:
457
			*spend++ = '\n';
458
			p1 = spend;
459
			p2 = holdsp;
460
			while(*p1++ = *p2++)
461
				if(p1 >= lbend)
462
					break;
463
			spend = p1-1;
464
			break;
465
 
466
		case HCOM:
467
			p1 = holdsp;
468
			p2 = linebuf;
469
			while(*p1++ = *p2++);
470
			hspend = p1-1;
471
			break;
472
 
473
		case CHCOM:
474
			*hspend++ = '\n';
475
			p1 = hspend;
476
			p2 = linebuf;
477
			while(*p1++ = *p2++)
478
				if(p1 >= hend)
479
					break;
480
			hspend = p1-1;
481
			break;
482
 
483
		case ICOM:
484
			for(p1 = ipc->r1.re1; *p1; )
485
				putc(*p1++, stdout);
486
			putc('\n', stdout);
487
			break;
488
 
489
		case BCOM:
490
			jflag = 1;
491
			break;
492
 
493
		case LCOM:
494
			p1 = linebuf;
495
			p2 = genbuf;
496
			while(*p1) {
497
				p2 = lformat(*p1++ & 0377, p2);
498
				if(p2>lcomend && *p1) {
499
					*p2 = 0;
500
					fprintf(stdout, "%s\\\n", genbuf);
501
					p2 = genbuf;
502
				}
503
			}
504
			if(p2>genbuf && (p1[-1]==' '||p1[-1]=='\n'))
505
					p2 = lformat('\n', p2);
506
			*p2 = 0;
507
			fprintf(stdout, "%s\n", genbuf);
508
			break;
509
 
510
		case NCOM:
511
			if(!nflag) {
512
				for(p1 = linebuf; p1 < spend; p1++)
513
					putc(*p1, stdout);
514
				putc('\n', stdout);
515
			}
516
 
517
			if(aptr > abuf)
518
				arout();
519
			if((execp = gline(linebuf)) == badp) {
520
				pending = ipc;
521
				delflag = 1;
522
				break;
523
			}
524
			spend = execp;
525
 
526
			break;
527
		case CNCOM:
528
			if(aptr > abuf)
529
				arout();
530
			*spend++ = '\n';
531
			if((execp = gline(spend)) == badp) {
532
				pending = ipc;
533
				delflag = 1;
534
				break;
535
			}
536
			spend = execp;
537
			break;
538
 
539
		case PCOM:
540
			for(p1 = linebuf; p1 < spend; p1++)
541
				putc(*p1, stdout);
542
			putc('\n', stdout);
543
			break;
544
		case CPCOM:
545
	cpcom:
546
			for(p1 = linebuf; *p1 != '\n' && *p1 != '\0'; )
547
				putc(*p1++, stdout);
548
			putc('\n', stdout);
549
			break;
550
 
551
		case QCOM:
552
			if(!nflag) {
553
				for(p1 = linebuf; p1 < spend; p1++)
554
					putc(*p1, stdout);
555
				putc('\n', stdout);
556
			}
557
			if(aptr > abuf)	arout();
558
			fclose(stdout);
559
			lseek(f,(long)(cbp-ebp),2);
560
			exit(0);
561
		case RCOM:
562
 
563
			*aptr++ = ipc;
564
			if(aptr >= &abuf[ABUFSIZE])
565
				fprintf(stderr, "sed: Too many reads after line%ld\n",
566
					lnum);
567
 
568
			*aptr = 0;
569
 
570
			break;
571
 
572
		case SCOM:
573
			i = substitute(ipc);
574
			if(ipc->r1.pfl && i)
575
				if(ipc->r1.pfl == 1) {
576
					for(p1 = linebuf; p1 < spend; p1++)
577
						putc(*p1, stdout);
578
					putc('\n', stdout);
579
				}
580
				else
581
					goto cpcom;
582
			if(i && ipc->r1.fcode)
583
				goto wcom;
584
			break;
585
 
586
		case TCOM:
587
			if(sflag == 0)	break;
588
			sflag = 0;
589
			jflag = 1;
590
			break;
591
 
592
		wcom:
593
		case WCOM:
594
			fprintf(ipc->r1.fcode, "%s\n", linebuf);
595
			fflush(ipc->r1.fcode);
596
			break;
597
		case XCOM:
598
			p1 = linebuf;
599
			p2 = genbuf;
600
			while(*p2++ = *p1++);
601
			p1 = holdsp;
602
			p2 = linebuf;
603
			while(*p2++ = *p1++);
604
			spend = p2 - 1;
605
			p1 = genbuf;
606
			p2 = holdsp;
607
			while(*p2++ = *p1++);
608
			hspend = p2 - 1;
609
			break;
610
 
611
		case YCOM:
612
			p1 = linebuf;
613
			p2 = ipc->r1.re1;
614
			while(*p1 = p2[*p1])	p1++;
615
			break;
616
	}
617
 
618
}
619
 
620
uchar *
621
gline(uchar *addr)
622
{
623
	uchar	*p1, *p2;
624
	int	c;
625
	sflag = 0;
626
	p1 = addr;
627
	p2 = cbp;
628
	for (;;) {
629
		if (p2 >= ebp) {
630
			if ((c = Read(f, ibuf, 512)) <= 0) {
631
				return(badp);
632
			}
633
			p2 = ibuf;
634
			ebp = ibuf+c;
635
		}
636
		if ((c = *p2++) == '\n') {
637
			if(p2 >=  ebp) {
638
				if((c = Read(f, ibuf, 512)) <= 0) {
639
					close(f);
640
					if(eargc == 0)
641
							dolflag = 1;
642
				}
643
 
644
				p2 = ibuf;
645
				ebp = ibuf + c;
646
			}
647
			break;
648
		}
649
		if(c)
650
		if(p1 < lbend)
651
			*p1++ = c;
652
	}
653
	lnum++;
654
	*p1 = 0;
655
	cbp = p2;
656
 
657
	return(p1);
658
}
659
int
660
ecmp(uchar *a, uchar *b, int count)
661
{
662
	while(count--)
663
		if(*a++ != *b++)	return(0);
664
	return(1);
665
}
666
 
667
void
668
arout(void)
669
{
670
	uchar	*p1;
671
	FILE	*fi;
672
	uchar	c;
673
	int	t;
674
 
675
	aptr = abuf - 1;
676
	while(*++aptr) {
677
		if((*aptr)->r1.command == ACOM) {
678
			for(p1 = (*aptr)->r1.re1; *p1; )
679
				putc(*p1++, stdout);
680
			putc('\n', stdout);
681
		} else {
682
			if((fi = fopen((char*)((*aptr)->r1.re1), "r")) == NULL)
683
				continue;
684
			while((t = getc(fi)) != EOF) {
685
				c = t;
686
				putc(c, stdout);
687
			}
688
			fclose(fi);
689
		}
690
	}
691
	aptr = abuf;
692
	*aptr = 0;
693
}
694
 
695
uchar *
696
lformat(int c, uchar *p)
697
{
698
	int trans = 
699
		c=='\b'? 'b':
700
		c=='\t'? 't':
701
		c=='\n'? 'n':
702
		c=='\v'? 'v':
703
		c=='\f'? 'f':
704
		c=='\r'? 'r':
705
		c=='\\'? '\\':
706
		0;
707
	if(trans) {
708
		*p++ = '\\';
709
		*p++ = trans;
710
	} else if(c<040 || c>=0177) {
711
		*p++ = '\\';
712
		*p++ = ((c>>6)&07) + '0';
713
		*p++ = ((c>>3)&07) + '0';
714
		*p++ = (c&07) + '0';
715
	} else
716
		*p++ = c;
717
	return p;
718
}
719