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