9070 Remove wanboot from gate
[unleashed.git] / usr / src / ucbcmd / sed / sed1.c
blobc5f5d89144d7377f9e4c602483f87ae561e5d116
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984 AT&T */
28 /* All Rights Reserved */
31 #pragma ident "%Z%%M% %I% %E% SMI"
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>
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 "-\b<",
70 "-\b>",
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"
94 char rub[] = {"\\177"};
96 extern char TMMES[];
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);
104 void
105 execute(char *file)
107 char *p1, *p2;
108 union reptr *ipc;
109 int c;
110 char *execp;
112 if (file) {
113 if ((f = open(file, 0)) < 0) {
114 (void) fprintf(stderr, "sed: ");
115 perror(file);
117 ifname = file;
118 } else {
119 f = 0;
120 ifname = "standard input";
123 ebp = ibuf;
124 cbp = ibuf;
126 if(pending) {
127 ipc = pending;
128 pending = 0;
129 goto yes;
132 for(;;) {
133 if((execp = gline(linebuf)) == 0) {
134 (void) close(f);
135 return;
137 spend = execp;
139 for(ipc = ptrspace; ipc->r1.command; ) {
141 p1 = ipc->r1.ad1;
142 p2 = ipc->r1.ad2;
144 if(p1) {
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;
158 if(lnum == tlno[c]) {
159 ipc->r1.inar = 0;
161 } else if(match(p2, 0)) {
162 ipc->r1.inar = 0;
164 } else if(*p1 == CEND) {
165 if(!dolflag) {
166 if(ipc->r1.negfl)
167 goto yes;
168 ipc++;
169 continue;
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;
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;
193 if(ipc->r1.negfl) {
194 ipc++;
195 continue;
197 yes:
198 command(ipc);
200 if(delflag)
201 break;
203 if(jflag) {
204 jflag = 0;
205 if((ipc = ipc->r2.lb1) == 0) {
206 ipc = ptrspace;
207 break;
209 } else
210 ipc++;
213 if(!nflag && !delflag) {
214 for(p1 = linebuf; p1 < spend; p1++)
215 (void) putc(*p1, stdout);
216 (void) putc('\n', stdout);
219 if(aptr > abuf) {
220 arout();
223 delflag = 0;
228 static int
229 match(char *expbuf, int gf)
231 char *p1;
233 if(gf) {
234 if(*expbuf) return(0);
235 locs = p1 = loc2;
236 } else {
237 p1 = linebuf;
238 locs = 0;
241 circf = *expbuf++;
242 return(step(p1, expbuf));
245 static int
246 substitute(union reptr *ipc)
248 if(match(ipc->r1.re1, 0) == 0) return(0);
250 numpass = 0;
251 sflag = 0; /* Flags if any substitution was made */
252 dosub(ipc->r1.rhs, ipc->r1.gfl);
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);
260 return(sflag);
263 static void
264 dosub(char *rhsbuf, int n)
266 char *lp, *sp, *rp;
267 int c;
269 if(n > 0 && n < 999)
270 {numpass++;
271 if(n != numpass) return;
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;
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;
304 out:
305 lp = linebuf;
306 sp = genbuf;
307 while (*lp++ = *sp++);
308 spend = lp-1;
311 char *place(asp, al1, al2)
312 char *asp, *al1, *al2;
314 char *sp, *l1, *l2;
316 sp = asp;
317 l1 = al1;
318 l2 = al2;
319 while (l1 < l2) {
320 *sp++ = *l1++;
321 if (sp == &genbuf[LBSIZE+1])
322 break;
324 return(sp);
327 static void
328 command(union reptr *ipc)
330 int i;
331 char *p1, *p2, *p3;
332 char *execp;
335 switch(ipc->r1.command) {
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;
345 break;
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);
354 break;
355 case DCOM:
356 delflag++;
357 break;
358 case CDCOM:
359 p1 = p2 = linebuf;
361 while(*p1 != '\n') {
362 if(*p1++ == 0) {
363 delflag++;
364 return;
368 p1++;
369 while(*p2++ = *p1++);
370 spend = p2-1;
371 jflag++;
372 break;
374 case EQCOM:
375 (void) fprintf(stdout, "%lld\n", lnum);
376 break;
378 case GCOM:
379 p1 = linebuf;
380 p2 = holdsp;
381 while(*p1++ = *p2++);
382 spend = p1-1;
383 break;
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';
394 } while(*p1++ = *p2++);
395 spend = p1-1;
396 break;
398 case HCOM:
399 p1 = holdsp;
400 p2 = linebuf;
401 while(*p1++ = *p2++);
402 hspend = p1-1;
403 break;
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';
414 } while(*p1++ = *p2++);
415 hspend = p1-1;
416 break;
418 case ICOM:
419 for(p1 = ipc->r1.re1; *p1; )
420 (void) putc(*p1++, stdout);
421 (void) putc('\n', stdout);
422 break;
424 case BCOM:
425 jflag = 1;
426 break;
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;
443 p2--;
444 p1++;
445 continue;
447 if(!isprint(*p1 & 0377)) {
448 *p2++ = '\\';
449 if(p2 >= lcomend) {
450 *p2 = '\\';
451 (void) fprintf(stdout, "%s\n", genbuf);
452 p2 = genbuf;
454 *p2++ = (*p1 >> 6) + '0';
455 if(p2 >= lcomend) {
456 *p2 = '\\';
457 (void) fprintf(stdout, "%s\n", genbuf);
458 p2 = genbuf;
460 *p2++ = ((*p1 >> 3) & 07) + '0';
461 if(p2 >= lcomend) {
462 *p2 = '\\';
463 (void) fprintf(stdout, "%s\n", genbuf);
464 p2 = genbuf;
466 *p2++ = (*p1++ & 07) + '0';
467 if(p2 >= lcomend) {
468 *p2 = '\\';
469 (void) fprintf(stdout, "%s\n", genbuf);
470 p2 = genbuf;
472 } else {
473 *p2++ = *p1++;
474 if(p2 >= lcomend) {
475 *p2 = '\\';
476 (void) fprintf(stdout, "%s\n", genbuf);
477 p2 = genbuf;
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;
488 p2--;
489 p1++;
491 *p2 = 0;
492 (void) fprintf(stdout, "%s\n", genbuf);
493 break;
495 case NCOM:
496 if(!nflag) {
497 for(p1 = linebuf; p1 < spend; p1++)
498 (void) putc(*p1, stdout);
499 (void) putc('\n', stdout);
502 if(aptr > abuf)
503 arout();
504 if((execp = gline(linebuf)) == 0) {
505 pending = ipc;
506 delflag = 1;
507 break;
509 spend = execp;
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;
521 spend = execp;
522 break;
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;
536 case QCOM:
537 if(!nflag) {
538 for(p1 = linebuf; p1 < spend; p1++)
539 (void) putc(*p1, stdout);
540 (void) putc('\n', stdout);
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;
553 break;
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);
563 else
564 goto cpcom;
565 if(i && ipc->r1.fcode)
566 goto wcom;
567 break;
569 case TCOM:
570 if(sflag == 0) break;
571 sflag = 0;
572 jflag = 1;
573 break;
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;
594 case YCOM:
595 p1 = linebuf;
596 p2 = ipc->r1.re1;
597 while(*p1 = p2[(unsigned char)*p1]) p1++;
598 break;
603 char *gline(addr)
604 char *addr;
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);
616 if(c < 0) {
617 (void) fprintf(stderr, "sed: error reading ");
618 perror(ifname);
619 exit(2);
621 p2 = ibuf;
622 ebp = ibuf+c;
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;
631 if(eargc == 0)
632 dolflag = 1;
634 if(c < 0) {
635 (void) fprintf(stderr, "sed: error reading ");
636 perror(ifname);
637 exit(2);
640 p2 = ibuf;
641 ebp = ibuf + c;
643 break;
645 if(c)
646 if(p1 < &linebuf[LBSIZE])
647 *p1++ = c;
649 lnum++;
650 *p1 = 0;
651 cbp = p2;
653 return(p1);
656 char *comple(x1, ep, x3, x4)
657 char *x1, *x3;
658 char x4;
659 char *ep;
661 char *p;
663 p = compile(x1, ep + 1, x3, x4);
664 if(p == ep + 1)
665 return(ep);
666 *ep = circf;
667 return(p);
671 regerr(int err)
673 switch(err) {
675 case 11:
676 comperr("Range endpoint too large: %s");
677 break;
679 case 16:
680 comperr("Bad number: %s");
681 break;
683 case 25:
684 comperr("``\\digit'' out of range: %s");
685 break;
687 case 36:
688 comperr("Illegal or missing delimiter: %s");
689 break;
691 case 41:
692 comperr("No remembered search string: %s");
693 break;
695 case 42:
696 comperr("\\( \\) imbalance: %s");
697 break;
699 case 43:
700 comperr("Too many \\(: %s");
701 break;
703 case 44:
704 comperr("More than 2 numbers given in \\{ \\}: %s");
705 break;
707 case 45:
708 comperr("} expected after \\: %s");
709 break;
711 case 46:
712 comperr("First number exceeds second in \\{ \\}: %s");
713 break;
715 case 49:
716 comperr("[ ] imbalance: %s");
717 break;
719 case 50:
720 comperr(TMMES);
721 break;
723 default:
724 (void) fprintf(stderr, "Unknown regexp error code %d: %s\n",
725 err, linebuf);
726 exit(2);
727 break;
729 return (0);
732 static void
733 arout(void)
735 char *p1;
736 FILE *fi;
737 char c;
738 int t;
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);
753 (void) fclose(fi);
756 aptr = abuf;
757 *aptr = 0;