/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984 AT&T */ /* All Rights Reserved */ #include #include #include #include #include #include "sed.h" #include union reptr *abuf[ABUFSIZE+1]; union reptr **aptr; char ibuf[BUFSIZ]; char *cbp; char *ebp; char genbuf[LBSIZE+1]; char *lcomend; int dolflag; int sflag; int jflag; int delflag; long long lnum; char holdsp[LBSIZE+1]; char *spend; char *hspend; int nflag; long long tlno[NLINES]; int f; char *ifname; int numpass; union reptr *pending; char *trans[040] = { "\\01", "\\02", "\\03", "\\04", "\\05", "\\06", "\\07", "-<", "->", "\n", "\\13", "\\14", "\\15", "\\16", "\\17", "\\20", "\\21", "\\22", "\\23", "\\24", "\\25", "\\26", "\\27", "\\30", "\\31", "\\32", "\\33", "\\34", "\\35", "\\36", "\\37" }; char rub[] = {"\\177"}; extern char TMMES[]; static int match(char *expbuf, int gf); static int substitute(union reptr *ipc); static void dosub(char *rhsbuf, int n); static void command(union reptr *ipc); static void arout(void); void execute(char *file) { char *p1, *p2; union reptr *ipc; int c; char *execp; if (file) { if ((f = open(file, 0)) < 0) { (void) fprintf(stderr, "sed: "); perror(file); } ifname = file; } else { f = 0; ifname = "standard input"; } ebp = ibuf; cbp = ibuf; if(pending) { ipc = pending; pending = 0; goto yes; } for(;;) { if((execp = gline(linebuf)) == 0) { (void) close(f); return; } spend = execp; for(ipc = ptrspace; ipc->r1.command; ) { p1 = ipc->r1.ad1; p2 = ipc->r1.ad2; if(p1) { if(ipc->r1.inar) { if(*p2 == CEND) { p1 = 0; } else if(*p2 == CLNUM) { c = (unsigned char)p2[1]; if(lnum > tlno[c]) { ipc->r1.inar = 0; if(ipc->r1.negfl) goto yes; ipc++; continue; } if(lnum == tlno[c]) { ipc->r1.inar = 0; } } else if(match(p2, 0)) { ipc->r1.inar = 0; } } else if(*p1 == CEND) { if(!dolflag) { if(ipc->r1.negfl) goto yes; ipc++; continue; } } else if(*p1 == CLNUM) { c = (unsigned char)p1[1]; if(lnum != tlno[c]) { if(ipc->r1.negfl) goto yes; ipc++; continue; } if(p2) ipc->r1.inar = 1; } else if(match(p1, 0)) { if(p2) ipc->r1.inar = 1; } else { if(ipc->r1.negfl) goto yes; ipc++; continue; } } if(ipc->r1.negfl) { ipc++; continue; } yes: command(ipc); if(delflag) break; if(jflag) { jflag = 0; if((ipc = ipc->r2.lb1) == 0) { ipc = ptrspace; break; } } else ipc++; } if(!nflag && !delflag) { for(p1 = linebuf; p1 < spend; p1++) (void) putc(*p1, stdout); (void) putc('\n', stdout); } if(aptr > abuf) { arout(); } delflag = 0; } } static int match(char *expbuf, int gf) { char *p1; if(gf) { if(*expbuf) return(0); locs = p1 = loc2; } else { p1 = linebuf; locs = 0; } circf = *expbuf++; return(step(p1, expbuf)); } static int substitute(union reptr *ipc) { if(match(ipc->r1.re1, 0) == 0) return(0); numpass = 0; sflag = 0; /* Flags if any substitution was made */ dosub(ipc->r1.rhs, ipc->r1.gfl); if(ipc->r1.gfl) { while(*loc2) { if(match(ipc->r1.re1, 1) == 0) break; dosub(ipc->r1.rhs, ipc->r1.gfl); } } return(sflag); } static void dosub(char *rhsbuf, int n) { char *lp, *sp, *rp; int c; if(n > 0 && n < 999) {numpass++; if(n != numpass) return; } sflag = 1; lp = linebuf; sp = genbuf; rp = rhsbuf; while (lp < loc1) *sp++ = *lp++; while(c = *rp++) { if (c == '&') sp = place(sp, loc1, loc2); else if (c == '\\') { c = *rp++; if (c >= '1' && c < NBRA+'1') sp = place(sp, braslist[c-'1'], braelist[c-'1']); else *sp++ = c; } else *sp++ = c; if (sp == &genbuf[LBSIZE+1]) { (void) fprintf(stderr, "Output line too long.\n"); *--sp = '\0'; goto out; } } lp = loc2; loc2 = sp - genbuf + linebuf; while(*sp++ = *lp++) if (sp == &genbuf[LBSIZE+1]) { (void) fprintf(stderr, "Output line too long.\n"); *--sp = '\0'; break; } out: lp = linebuf; sp = genbuf; while (*lp++ = *sp++); spend = lp-1; } char *place(asp, al1, al2) char *asp, *al1, *al2; { char *sp, *l1, *l2; sp = asp; l1 = al1; l2 = al2; while (l1 < l2) { *sp++ = *l1++; if (sp == &genbuf[LBSIZE+1]) break; } return(sp); } static void command(union reptr *ipc) { int i; char *p1, *p2, *p3; char *execp; switch(ipc->r1.command) { case ACOM: if(aptr >= &abuf[ABUFSIZE]) { (void) fprintf(stderr, "Too many appends or reads after line %lld\n", lnum); } else { *aptr++ = ipc; *aptr = 0; } break; case CCOM: delflag = 1; if(!ipc->r1.inar || dolflag) { for(p1 = ipc->r1.re1; *p1; ) (void) putc(*p1++, stdout); (void) putc('\n', stdout); } break; case DCOM: delflag++; break; case CDCOM: p1 = p2 = linebuf; while(*p1 != '\n') { if(*p1++ == 0) { delflag++; return; } } p1++; while(*p2++ = *p1++); spend = p2-1; jflag++; break; case EQCOM: (void) fprintf(stdout, "%lld\n", lnum); break; case GCOM: p1 = linebuf; p2 = holdsp; while(*p1++ = *p2++); spend = p1-1; break; case CGCOM: *spend++ = '\n'; p1 = spend; p2 = holdsp; do { if (p1 == &linebuf[LBSIZE+1]) { (void) fprintf(stderr, "Output line too long.\n"); *--p1 = '\0'; } } while(*p1++ = *p2++); spend = p1-1; break; case HCOM: p1 = holdsp; p2 = linebuf; while(*p1++ = *p2++); hspend = p1-1; break; case CHCOM: *hspend++ = '\n'; p1 = hspend; p2 = linebuf; do { if (p1 == &holdsp[LBSIZE+1]) { (void) fprintf(stderr, "Hold space overflowed.\n"); *--p1 = '\0'; } } while(*p1++ = *p2++); hspend = p1-1; break; case ICOM: for(p1 = ipc->r1.re1; *p1; ) (void) putc(*p1++, stdout); (void) putc('\n', stdout); break; case BCOM: jflag = 1; break; case LCOM: p1 = linebuf; p2 = genbuf; genbuf[72] = 0; while(*p1) if((unsigned char)*p1 >= 040) { if(*p1 == 0177) { p3 = rub; while(*p2++ = *p3++) if(p2 >= lcomend) { *p2 = '\\'; (void) fprintf(stdout, "%s\n", genbuf); p2 = genbuf; } p2--; p1++; continue; } if(!isprint(*p1 & 0377)) { *p2++ = '\\'; if(p2 >= lcomend) { *p2 = '\\'; (void) fprintf(stdout, "%s\n", genbuf); p2 = genbuf; } *p2++ = (*p1 >> 6) + '0'; if(p2 >= lcomend) { *p2 = '\\'; (void) fprintf(stdout, "%s\n", genbuf); p2 = genbuf; } *p2++ = ((*p1 >> 3) & 07) + '0'; if(p2 >= lcomend) { *p2 = '\\'; (void) fprintf(stdout, "%s\n", genbuf); p2 = genbuf; } *p2++ = (*p1++ & 07) + '0'; if(p2 >= lcomend) { *p2 = '\\'; (void) fprintf(stdout, "%s\n", genbuf); p2 = genbuf; } } else { *p2++ = *p1++; if(p2 >= lcomend) { *p2 = '\\'; (void) fprintf(stdout, "%s\n", genbuf); p2 = genbuf; } } } else { p3 = trans[(unsigned char)*p1-1]; while(*p2++ = *p3++) if(p2 >= lcomend) { *p2 = '\\'; (void) fprintf(stdout, "%s\n", genbuf); p2 = genbuf; } p2--; p1++; } *p2 = 0; (void) fprintf(stdout, "%s\n", genbuf); break; case NCOM: if(!nflag) { for(p1 = linebuf; p1 < spend; p1++) (void) putc(*p1, stdout); (void) putc('\n', stdout); } if(aptr > abuf) arout(); if((execp = gline(linebuf)) == 0) { pending = ipc; delflag = 1; break; } spend = execp; break; case CNCOM: if(aptr > abuf) arout(); *spend++ = '\n'; if((execp = gline(spend)) == 0) { pending = ipc; delflag = 1; break; } spend = execp; break; case PCOM: for(p1 = linebuf; p1 < spend; p1++) (void) putc(*p1, stdout); (void) putc('\n', stdout); break; case CPCOM: cpcom: for(p1 = linebuf; *p1 != '\n' && *p1 != '\0'; ) (void) putc(*p1++, stdout); (void) putc('\n', stdout); break; case QCOM: if(!nflag) { for(p1 = linebuf; p1 < spend; p1++) (void) putc(*p1, stdout); (void) putc('\n', stdout); } if(aptr > abuf) arout(); (void) fclose(stdout); exit(0); case RCOM: if(aptr >= &abuf[ABUFSIZE]) { (void) fprintf(stderr, "Too many appends or reads after line %lld\n", lnum); } else { *aptr++ = ipc; *aptr = 0; } break; case SCOM: i = substitute(ipc); if(ipc->r1.pfl && nflag && i) if(ipc->r1.pfl == 1) { for(p1 = linebuf; p1 < spend; p1++) (void) putc(*p1, stdout); (void) putc('\n', stdout); } else goto cpcom; if(i && ipc->r1.fcode) goto wcom; break; case TCOM: if(sflag == 0) break; sflag = 0; jflag = 1; break; wcom: case WCOM: (void) fprintf(ipc->r1.fcode, "%s\n", linebuf); (void) fflush(ipc->r1.fcode); break; case XCOM: p1 = linebuf; p2 = genbuf; while(*p2++ = *p1++); p1 = holdsp; p2 = linebuf; while(*p2++ = *p1++); spend = p2 - 1; p1 = genbuf; p2 = holdsp; while(*p2++ = *p1++); hspend = p2 - 1; break; case YCOM: p1 = linebuf; p2 = ipc->r1.re1; while(*p1 = p2[(unsigned char)*p1]) p1++; break; } } char *gline(addr) char *addr; { char *p1, *p2; int c; sflag = 0; p1 = addr; p2 = cbp; for (;;) { if (p2 >= ebp) { if(f < 0 || (c = read(f, ibuf, BUFSIZ)) == 0) { return(0); } if(c < 0) { (void) fprintf(stderr, "sed: error reading "); perror(ifname); exit(2); } p2 = ibuf; ebp = ibuf+c; } if ((c = *p2++) == '\n') { if(p2 >= ebp) { if(f < 0 || (c = read(f, ibuf, BUFSIZ)) == 0) { if(f >= 0) { (void) close(f); f = -1; } if(eargc == 0) dolflag = 1; } if(c < 0) { (void) fprintf(stderr, "sed: error reading "); perror(ifname); exit(2); } p2 = ibuf; ebp = ibuf + c; } break; } if(c) if(p1 < &linebuf[LBSIZE]) *p1++ = c; } lnum++; *p1 = 0; cbp = p2; return(p1); } char *comple(x1, ep, x3, x4) char *x1, *x3; char x4; char *ep; { char *p; p = compile(x1, ep + 1, x3, x4); if(p == ep + 1) return(ep); *ep = circf; return(p); } void regerr(int err) { switch(err) { case 11: comperr("Range endpoint too large: %s"); break; case 16: comperr("Bad number: %s"); break; case 25: comperr("``\\digit'' out of range: %s"); break; case 36: comperr("Illegal or missing delimiter: %s"); break; case 41: comperr("No remembered search string: %s"); break; case 42: comperr("\\( \\) imbalance: %s"); break; case 43: comperr("Too many \\(: %s"); break; case 44: comperr("More than 2 numbers given in \\{ \\}: %s"); break; case 45: comperr("} expected after \\: %s"); break; case 46: comperr("First number exceeds second in \\{ \\}: %s"); break; case 49: comperr("[ ] imbalance: %s"); break; case 50: comperr(TMMES); break; default: (void) fprintf(stderr, "Unknown regexp error code %d: %s\n", err, linebuf); exit(2); break; } } static void arout(void) { char *p1; FILE *fi; char c; int t; aptr = abuf - 1; while(*++aptr) { if((*aptr)->r1.command == ACOM) { for(p1 = (*aptr)->r1.re1; *p1; ) (void) putc(*p1++, stdout); (void) putc('\n', stdout); } else { if((fi = fopen((*aptr)->r1.re1, "r")) == NULL) continue; while((t = getc(fi)) != EOF) { c = t; (void) putc(c, stdout); } (void) fclose(fi); } } aptr = abuf; *aptr = 0; }