1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984 AT&T */
28 /* All Rights Reserved */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include "sed.h"
36 #include <regexp.h>
37
38 union reptr *abuf[ABUFSIZE+1];
39 union reptr **aptr;
40 char ibuf[BUFSIZ];
41 char *cbp;
42 char *ebp;
43 char genbuf[LBSIZE+1];
44 char *lcomend;
45 int dolflag;
46 int sflag;
47 int jflag;
48 int delflag;
49 long long lnum;
50 char holdsp[LBSIZE+1];
51 char *spend;
52 char *hspend;
53 int nflag;
54 long long tlno[NLINES];
55 int f;
56 char *ifname;
57 int numpass;
58 union reptr *pending;
59 char *trans[040] = {
60 "\\01",
61 "\\02",
62 "\\03",
63 "\\04",
64 "\\05",
65 "\\06",
66 "\\07",
67 "-<",
68 "->",
69 "\n",
70 "\\13",
71 "\\14",
72 "\\15",
73 "\\16",
74 "\\17",
75 "\\20",
76 "\\21",
77 "\\22",
78 "\\23",
79 "\\24",
80 "\\25",
81 "\\26",
82 "\\27",
83 "\\30",
84 "\\31",
85 "\\32",
86 "\\33",
87 "\\34",
88 "\\35",
89 "\\36",
90 "\\37"
91 };
92 char rub[] = {"\\177"};
93
94 extern char TMMES[];
95
96 static int match(char *expbuf, int gf);
97 static int substitute(union reptr *ipc);
98 static void dosub(char *rhsbuf, int n);
99 static void command(union reptr *ipc);
100 static void arout(void);
101
102 void
execute(char * file)103 execute(char *file)
104 {
105 char *p1, *p2;
106 union reptr *ipc;
107 int c;
108 char *execp;
109
110 if (file) {
111 if ((f = open(file, 0)) < 0) {
112 (void) fprintf(stderr, "sed: ");
113 perror(file);
114 }
115 ifname = file;
116 } else {
117 f = 0;
118 ifname = "standard input";
119 }
120
121 ebp = ibuf;
122 cbp = ibuf;
123
124 if(pending) {
125 ipc = pending;
126 pending = 0;
127 goto yes;
128 }
129
130 for(;;) {
131 if((execp = gline(linebuf)) == 0) {
132 (void) close(f);
133 return;
134 }
135 spend = execp;
136
137 for(ipc = ptrspace; ipc->r1.command; ) {
138
139 p1 = ipc->r1.ad1;
140 p2 = ipc->r1.ad2;
141
142 if(p1) {
143
144 if(ipc->r1.inar) {
145 if(*p2 == CEND) {
146 p1 = 0;
147 } else if(*p2 == CLNUM) {
148 c = (unsigned char)p2[1];
149 if(lnum > tlno[c]) {
150 ipc->r1.inar = 0;
151 if(ipc->r1.negfl)
152 goto yes;
153 ipc++;
154 continue;
155 }
156 if(lnum == tlno[c]) {
157 ipc->r1.inar = 0;
158 }
159 } else if(match(p2, 0)) {
160 ipc->r1.inar = 0;
161 }
162 } else if(*p1 == CEND) {
163 if(!dolflag) {
164 if(ipc->r1.negfl)
165 goto yes;
166 ipc++;
167 continue;
168 }
169
170 } else if(*p1 == CLNUM) {
171 c = (unsigned char)p1[1];
172 if(lnum != tlno[c]) {
173 if(ipc->r1.negfl)
174 goto yes;
175 ipc++;
176 continue;
177 }
178 if(p2)
179 ipc->r1.inar = 1;
180 } else if(match(p1, 0)) {
181 if(p2)
182 ipc->r1.inar = 1;
183 } else {
184 if(ipc->r1.negfl)
185 goto yes;
186 ipc++;
187 continue;
188 }
189 }
190
191 if(ipc->r1.negfl) {
192 ipc++;
193 continue;
194 }
195 yes:
196 command(ipc);
197
198 if(delflag)
199 break;
200
201 if(jflag) {
202 jflag = 0;
203 if((ipc = ipc->r2.lb1) == 0) {
204 ipc = ptrspace;
205 break;
206 }
207 } else
208 ipc++;
209
210 }
211 if(!nflag && !delflag) {
212 for(p1 = linebuf; p1 < spend; p1++)
213 (void) putc(*p1, stdout);
214 (void) putc('\n', stdout);
215 }
216
217 if(aptr > abuf) {
218 arout();
219 }
220
221 delflag = 0;
222
223 }
224 }
225
226 static int
match(char * expbuf,int gf)227 match(char *expbuf, int gf)
228 {
229 char *p1;
230
231 if(gf) {
232 if(*expbuf) return(0);
233 locs = p1 = loc2;
234 } else {
235 p1 = linebuf;
236 locs = 0;
237 }
238
239 circf = *expbuf++;
240 return(step(p1, expbuf));
241 }
242
243 static int
substitute(union reptr * ipc)244 substitute(union reptr *ipc)
245 {
246 if(match(ipc->r1.re1, 0) == 0) return(0);
247
248 numpass = 0;
249 sflag = 0; /* Flags if any substitution was made */
250 dosub(ipc->r1.rhs, ipc->r1.gfl);
251
252 if(ipc->r1.gfl) {
253 while(*loc2) {
254 if(match(ipc->r1.re1, 1) == 0) break;
255 dosub(ipc->r1.rhs, ipc->r1.gfl);
256 }
257 }
258 return(sflag);
259 }
260
261 static void
dosub(char * rhsbuf,int n)262 dosub(char *rhsbuf, int n)
263 {
264 char *lp, *sp, *rp;
265 int c;
266
267 if(n > 0 && n < 999)
268 {numpass++;
269 if(n != numpass) return;
270 }
271 sflag = 1;
272 lp = linebuf;
273 sp = genbuf;
274 rp = rhsbuf;
275 while (lp < loc1)
276 *sp++ = *lp++;
277 while(c = *rp++) {
278 if (c == '&')
279 sp = place(sp, loc1, loc2);
280 else if (c == '\\') {
281 c = *rp++;
282 if (c >= '1' && c < NBRA+'1')
283 sp = place(sp, braslist[c-'1'], braelist[c-'1']);
284 else
285 *sp++ = c;
286 } else
287 *sp++ = c;
288 if (sp == &genbuf[LBSIZE+1]) {
289 (void) fprintf(stderr, "Output line too long.\n");
290 *--sp = '\0';
291 goto out;
292 }
293 }
294 lp = loc2;
295 loc2 = sp - genbuf + linebuf;
296 while(*sp++ = *lp++)
297 if (sp == &genbuf[LBSIZE+1]) {
298 (void) fprintf(stderr, "Output line too long.\n");
299 *--sp = '\0';
300 break;
301 }
302 out:
303 lp = linebuf;
304 sp = genbuf;
305 while (*lp++ = *sp++);
306 spend = lp-1;
307 }
308
place(asp,al1,al2)309 char *place(asp, al1, al2)
310 char *asp, *al1, *al2;
311 {
312 char *sp, *l1, *l2;
313
314 sp = asp;
315 l1 = al1;
316 l2 = al2;
317 while (l1 < l2) {
318 *sp++ = *l1++;
319 if (sp == &genbuf[LBSIZE+1])
320 break;
321 }
322 return(sp);
323 }
324
325 static void
command(union reptr * ipc)326 command(union reptr *ipc)
327 {
328 int i;
329 char *p1, *p2, *p3;
330 char *execp;
331
332
333 switch(ipc->r1.command) {
334
335 case ACOM:
336 if(aptr >= &abuf[ABUFSIZE]) {
337 (void) fprintf(stderr, "Too many appends or reads after line %lld\n",
338 lnum);
339 } else {
340 *aptr++ = ipc;
341 *aptr = 0;
342 }
343 break;
344
345 case CCOM:
346 delflag = 1;
347 if(!ipc->r1.inar || dolflag) {
348 for(p1 = ipc->r1.re1; *p1; )
349 (void) putc(*p1++, stdout);
350 (void) putc('\n', stdout);
351 }
352 break;
353 case DCOM:
354 delflag++;
355 break;
356 case CDCOM:
357 p1 = p2 = linebuf;
358
359 while(*p1 != '\n') {
360 if(*p1++ == 0) {
361 delflag++;
362 return;
363 }
364 }
365
366 p1++;
367 while(*p2++ = *p1++);
368 spend = p2-1;
369 jflag++;
370 break;
371
372 case EQCOM:
373 (void) fprintf(stdout, "%lld\n", lnum);
374 break;
375
376 case GCOM:
377 p1 = linebuf;
378 p2 = holdsp;
379 while(*p1++ = *p2++);
380 spend = p1-1;
381 break;
382
383 case CGCOM:
384 *spend++ = '\n';
385 p1 = spend;
386 p2 = holdsp;
387 do {
388 if (p1 == &linebuf[LBSIZE+1]) {
389 (void) fprintf(stderr, "Output line too long.\n");
390 *--p1 = '\0';
391 }
392 } while(*p1++ = *p2++);
393 spend = p1-1;
394 break;
395
396 case HCOM:
397 p1 = holdsp;
398 p2 = linebuf;
399 while(*p1++ = *p2++);
400 hspend = p1-1;
401 break;
402
403 case CHCOM:
404 *hspend++ = '\n';
405 p1 = hspend;
406 p2 = linebuf;
407 do {
408 if (p1 == &holdsp[LBSIZE+1]) {
409 (void) fprintf(stderr, "Hold space overflowed.\n");
410 *--p1 = '\0';
411 }
412 } while(*p1++ = *p2++);
413 hspend = p1-1;
414 break;
415
416 case ICOM:
417 for(p1 = ipc->r1.re1; *p1; )
418 (void) putc(*p1++, stdout);
419 (void) putc('\n', stdout);
420 break;
421
422 case BCOM:
423 jflag = 1;
424 break;
425
426
427 case LCOM:
428 p1 = linebuf;
429 p2 = genbuf;
430 genbuf[72] = 0;
431 while(*p1)
432 if((unsigned char)*p1 >= 040) {
433 if(*p1 == 0177) {
434 p3 = rub;
435 while(*p2++ = *p3++)
436 if(p2 >= lcomend) {
437 *p2 = '\\';
438 (void) fprintf(stdout, "%s\n", genbuf);
439 p2 = genbuf;
440 }
441 p2--;
442 p1++;
443 continue;
444 }
445 if(!isprint(*p1 & 0377)) {
446 *p2++ = '\\';
447 if(p2 >= lcomend) {
448 *p2 = '\\';
449 (void) fprintf(stdout, "%s\n", genbuf);
450 p2 = genbuf;
451 }
452 *p2++ = (*p1 >> 6) + '0';
453 if(p2 >= lcomend) {
454 *p2 = '\\';
455 (void) fprintf(stdout, "%s\n", genbuf);
456 p2 = genbuf;
457 }
458 *p2++ = ((*p1 >> 3) & 07) + '0';
459 if(p2 >= lcomend) {
460 *p2 = '\\';
461 (void) fprintf(stdout, "%s\n", genbuf);
462 p2 = genbuf;
463 }
464 *p2++ = (*p1++ & 07) + '0';
465 if(p2 >= lcomend) {
466 *p2 = '\\';
467 (void) fprintf(stdout, "%s\n", genbuf);
468 p2 = genbuf;
469 }
470 } else {
471 *p2++ = *p1++;
472 if(p2 >= lcomend) {
473 *p2 = '\\';
474 (void) fprintf(stdout, "%s\n", genbuf);
475 p2 = genbuf;
476 }
477 }
478 } else {
479 p3 = trans[(unsigned char)*p1-1];
480 while(*p2++ = *p3++)
481 if(p2 >= lcomend) {
482 *p2 = '\\';
483 (void) fprintf(stdout, "%s\n", genbuf);
484 p2 = genbuf;
485 }
486 p2--;
487 p1++;
488 }
489 *p2 = 0;
490 (void) fprintf(stdout, "%s\n", genbuf);
491 break;
492
493 case NCOM:
494 if(!nflag) {
495 for(p1 = linebuf; p1 < spend; p1++)
496 (void) putc(*p1, stdout);
497 (void) putc('\n', stdout);
498 }
499
500 if(aptr > abuf)
501 arout();
502 if((execp = gline(linebuf)) == 0) {
503 pending = ipc;
504 delflag = 1;
505 break;
506 }
507 spend = execp;
508
509 break;
510 case CNCOM:
511 if(aptr > abuf)
512 arout();
513 *spend++ = '\n';
514 if((execp = gline(spend)) == 0) {
515 pending = ipc;
516 delflag = 1;
517 break;
518 }
519 spend = execp;
520 break;
521
522 case PCOM:
523 for(p1 = linebuf; p1 < spend; p1++)
524 (void) putc(*p1, stdout);
525 (void) putc('\n', stdout);
526 break;
527 case CPCOM:
528 cpcom:
529 for(p1 = linebuf; *p1 != '\n' && *p1 != '\0'; )
530 (void) putc(*p1++, stdout);
531 (void) putc('\n', stdout);
532 break;
533
534 case QCOM:
535 if(!nflag) {
536 for(p1 = linebuf; p1 < spend; p1++)
537 (void) putc(*p1, stdout);
538 (void) putc('\n', stdout);
539 }
540 if(aptr > abuf) arout();
541 (void) fclose(stdout);
542 exit(0);
543 case RCOM:
544 if(aptr >= &abuf[ABUFSIZE]) {
545 (void) fprintf(stderr, "Too many appends or reads after line %lld\n",
546 lnum);
547 } else {
548 *aptr++ = ipc;
549 *aptr = 0;
550 }
551 break;
552
553 case SCOM:
554 i = substitute(ipc);
555 if(ipc->r1.pfl && nflag && i)
556 if(ipc->r1.pfl == 1) {
557 for(p1 = linebuf; p1 < spend; p1++)
558 (void) putc(*p1, stdout);
559 (void) putc('\n', stdout);
560 }
561 else
562 goto cpcom;
563 if(i && ipc->r1.fcode)
564 goto wcom;
565 break;
566
567 case TCOM:
568 if(sflag == 0) break;
569 sflag = 0;
570 jflag = 1;
571 break;
572
573 wcom:
574 case WCOM:
575 (void) fprintf(ipc->r1.fcode, "%s\n", linebuf);
576 (void) fflush(ipc->r1.fcode);
577 break;
578 case XCOM:
579 p1 = linebuf;
580 p2 = genbuf;
581 while(*p2++ = *p1++);
582 p1 = holdsp;
583 p2 = linebuf;
584 while(*p2++ = *p1++);
585 spend = p2 - 1;
586 p1 = genbuf;
587 p2 = holdsp;
588 while(*p2++ = *p1++);
589 hspend = p2 - 1;
590 break;
591
592 case YCOM:
593 p1 = linebuf;
594 p2 = ipc->r1.re1;
595 while(*p1 = p2[(unsigned char)*p1]) p1++;
596 break;
597 }
598
599 }
600
gline(addr)601 char *gline(addr)
602 char *addr;
603 {
604 char *p1, *p2;
605 int c;
606 sflag = 0;
607 p1 = addr;
608 p2 = cbp;
609 for (;;) {
610 if (p2 >= ebp) {
611 if(f < 0 || (c = read(f, ibuf, BUFSIZ)) == 0) {
612 return(0);
613 }
614 if(c < 0) {
615 (void) fprintf(stderr, "sed: error reading ");
616 perror(ifname);
617 exit(2);
618 }
619 p2 = ibuf;
620 ebp = ibuf+c;
621 }
622 if ((c = *p2++) == '\n') {
623 if(p2 >= ebp) {
624 if(f < 0 || (c = read(f, ibuf, BUFSIZ)) == 0) {
625 if(f >= 0) {
626 (void) close(f);
627 f = -1;
628 }
629 if(eargc == 0)
630 dolflag = 1;
631 }
632 if(c < 0) {
633 (void) fprintf(stderr, "sed: error reading ");
634 perror(ifname);
635 exit(2);
636 }
637
638 p2 = ibuf;
639 ebp = ibuf + c;
640 }
641 break;
642 }
643 if(c)
644 if(p1 < &linebuf[LBSIZE])
645 *p1++ = c;
646 }
647 lnum++;
648 *p1 = 0;
649 cbp = p2;
650
651 return(p1);
652 }
653
comple(x1,ep,x3,x4)654 char *comple(x1, ep, x3, x4)
655 char *x1, *x3;
656 char x4;
657 char *ep;
658 {
659 char *p;
660
661 p = compile(x1, ep + 1, x3, x4);
662 if(p == ep + 1)
663 return(ep);
664 *ep = circf;
665 return(p);
666 }
667
668 void
regerr(int err)669 regerr(int err)
670 {
671 switch(err) {
672
673 case 11:
674 comperr("Range endpoint too large: %s");
675 break;
676
677 case 16:
678 comperr("Bad number: %s");
679 break;
680
681 case 25:
682 comperr("``\\digit'' out of range: %s");
683 break;
684
685 case 36:
686 comperr("Illegal or missing delimiter: %s");
687 break;
688
689 case 41:
690 comperr("No remembered search string: %s");
691 break;
692
693 case 42:
694 comperr("\\( \\) imbalance: %s");
695 break;
696
697 case 43:
698 comperr("Too many \\(: %s");
699 break;
700
701 case 44:
702 comperr("More than 2 numbers given in \\{ \\}: %s");
703 break;
704
705 case 45:
706 comperr("} expected after \\: %s");
707 break;
708
709 case 46:
710 comperr("First number exceeds second in \\{ \\}: %s");
711 break;
712
713 case 49:
714 comperr("[ ] imbalance: %s");
715 break;
716
717 case 50:
718 comperr(TMMES);
719 break;
720
721 default:
722 (void) fprintf(stderr, "Unknown regexp error code %d: %s\n",
723 err, linebuf);
724 exit(2);
725 break;
726 }
727 }
728
729 static void
arout(void)730 arout(void)
731 {
732 char *p1;
733 FILE *fi;
734 char c;
735 int t;
736
737 aptr = abuf - 1;
738 while(*++aptr) {
739 if((*aptr)->r1.command == ACOM) {
740 for(p1 = (*aptr)->r1.re1; *p1; )
741 (void) putc(*p1++, stdout);
742 (void) putc('\n', stdout);
743 } else {
744 if((fi = fopen((*aptr)->r1.re1, "r")) == NULL)
745 continue;
746 while((t = getc(fi)) != EOF) {
747 c = t;
748 (void) putc(c, stdout);
749 }
750 (void) fclose(fi);
751 }
752 }
753 aptr = abuf;
754 *aptr = 0;
755 }
756