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
execute(uchar * file)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
match(uchar * expbuf,int gf)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
advance(uchar * alp,uchar * aep)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
substitute(union reptr * ipc)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
dosub(uchar * rhsbuf)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 *
place(uchar * asp,uchar * al1,uchar * al2)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
command(union reptr * ipc)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 *
gline(uchar * addr)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
ecmp(uchar * a,uchar * b,int count)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
arout(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 *
lformat(int c,uchar * p)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
720