/* from Unix 7th Edition sed */ /* Sccsid @(#)sed1.c 1.42 (gritter) 2/6/05> */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * Redistributions of source code and documentation must retain the * above copyright notice, this list of conditions and the following * disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed or owned by Caldera * International, Inc. * Neither the name of Caldera International, Inc. nor the names of * other contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "sed.h" #if !defined (SUS) && !defined (SU3) && !defined(S42) #define INIT extern char *cp, *badp; \ register char *sp = cp; #define GETC() (*sp++) #define PEEKC() (*sp) #define UNGETC(c) (--sp) #define RETURN(c) { cp = sp; return ep; } #define ERROR(c) { cp = sp; return badp; } #define regexp_h_malloc(n) smalloc(n) #include #endif /* !SUS && !SU3 && !S42 */ #ifndef CCEOF #ifdef CEOF #define CCEOF CEOF #else /* !CEOF */ #define CCEOF 22 #endif /* !CEOF */ #endif /* !CCEOF */ int ceof = CCEOF; #if !defined (SUS) && !defined (SU3) static const char *trans[] = { "\\00", "\\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" }; #endif /* !SUS, !SU3 */ static char *cbp; static char *ebp; static int dolflag; static int sflag; static int jflag; static int delflag; static long long lnum; static char ibuf[512]; static int ibrd; static int mflag; static int f = -1; static int spend; static int genend; static int hspend; static void command(struct reptr *); static int match(char *, int, int); static int substitute(struct reptr *); static void dosub(char *); static int place(int, int, int); static int gline(int); static void arout(void); static void lcom(wint_t, int); static void oout(int); static void mout(const char *); static void nout(wint_t); static void wout(wint_t); static void lout(int); #if defined (SUS) || defined (SU3) || defined (S42) #define NBRA 9 int sed; int nbra; int circf; static char *braslist[NBRA]; static char *braelist[NBRA]; static char *loc1, *loc2, *locs; static int step(char *line, char *pattern) { struct re_emu *re = (struct re_emu *)&pattern[-1]; regmatch_t bralist[NBRA+1]; int eflag = 0; int res; int i, nsub; if (circf == 2) /* empty pattern */ return 0; if (locs) eflag |= REG_NOTBOL; /* * Don't fetch more match locations than necessary since this * might prevent use of DFA. */ nsub = mflag; if ((res = regexec(&re->r_preg, line, nsub, bralist, eflag)) == 0) { if (nsub > 0) { loc1 = line + bralist[0].rm_so; loc2 = line + bralist[0].rm_eo; for (i = 1; i < nsub; i++) { if (bralist[i].rm_so != -1) { braslist[i-1] = line + bralist[i].rm_so; braelist[i-1] = line + bralist[i].rm_eo; } else braslist[i-1] = braelist[i-1] = NULL; } } } return res == 0; } #endif /* SUS || SU3 || S42 */ static int lcomlen; static int Braslist[NBRA]; static int Braelist[NBRA]; static int Loc1, Loc2; void execute(const char *file) { register char *p1, *p2; register struct reptr *ipc; int c; int execc; if (f >= 0) close(f); if (file) { if ((f = open(file, O_RDONLY)) < 0) { nonfatal("Can't open %s", file); return; } } else f = 0; ebp = ibuf; cbp = ibuf; if(pending) { ipc = pending; pending = 0; goto yes; } for(;;) { if((execc = gline(0)) < 0) { if (f >= 0) { close(f); f = -1; } return; } spend = execc; for(ipc = ptrspace; ipc->command; ) { p1 = ipc->ad1; p2 = ipc->ad2; if(p1) { if(ipc->inar) { if(*p2 == CEND) { p1 = 0; } else if(*p2 == CLNUM) { c = glno(&p2[1]); if(lnum > tlno[c]) { ipc->inar = 0; if(ipc->negfl) goto yes; ipc++; continue; } if(lnum == tlno[c]) { ipc->inar = 0; } } else if(match(p2, 0, 0)) { ipc->inar = 0; } } else if(*p1 == CEND) { if(!dolflag) { if(ipc->negfl) goto yes; ipc++; continue; } } else if(*p1 == CLNUM) { c = glno(&p1[1]); if(lnum != tlno[c]) { if(ipc->negfl) goto yes; ipc++; continue; } if(p2) { ipc->inar = 1; #if defined (SUS) || defined (SU3) goto ichk; #endif /* SUS, SU3 */ } } else if(match(p1, 0, 0)) { if(p2) { ipc->inar = 1; #if defined (SUS) || defined (SU3) ichk: if (*p2 == CLNUM) { c = glno(&p2[1]); if (lnum >= tlno[c]) ipc->inar = 0; } #endif /* SUS, SU3 */ } } else { if(ipc->negfl) goto yes; ipc++; continue; } } if(ipc->negfl) { ipc++; continue; } yes: command(ipc); if(delflag) break; if(jflag) { jflag = 0; if((ipc = P(ipc->bptr.lb1)) == 0) { ipc = ptrspace; break; } } else ipc++; } if(!nflag && !delflag) { for(p1 = linebuf; p1 < &linebuf[spend]; p1++) putc(*p1&0377, stdout); putc('\n', stdout); } if(A(aptr) > abuf) { arout(); } delflag = 0; } } static int match(char *expbuf, int gf, int needloc) { register char *p1; int i, val; if(gf) { if(*expbuf) return(0); #if defined (SUS) || defined (SU3) || defined (S42) if (loc1 == loc2) { int n; wchar_t wc; if (multibyte && (n = mbtowc(&wc, &linebuf[Loc2], MB_LEN_MAX)) > 0) Loc2 += n; else Loc2++; } #endif locs = p1 = loc2 = &linebuf[Loc2]; } else { p1 = linebuf; locs = 0; } mflag = needloc; circf = *expbuf++; val = step(p1, expbuf); for (i = 0; i < NBRA; i++) { Braslist[i] = braslist[i] - linebuf; Braelist[i] = braelist[i] - linebuf; } Loc1 = loc1 - linebuf; Loc2 = loc2 - linebuf; return val; } static int substitute(struct reptr *ipc) { int matchcnt = 1; if (match(ipc->bptr.re1, 0, ipc->nsub + 1) == 0) return(0); sflag = 0; if (ipc->gfl >= -1 && ipc->gfl <= 1) dosub(ipc->rhs); if(ipc->gfl != 0) { while(linebuf[Loc2]) { if(match(ipc->bptr.re1, 1, ipc->nsub + 1) == 0) break; matchcnt++; if (ipc->gfl == -1 || ipc->gfl == matchcnt) dosub(ipc->rhs); } } return(1); } static void dosub(char *rhsbuf) { register int lc, sc; register char *rp; int c; sflag = 1; lc = 0; /*linebuf*/ sc = 0; /*genbuf*/ rp = rhsbuf; while (lc < Loc1) genbuf[sc++] = linebuf[lc++]; while((c = *rp++) != 0) { if (c == '&') { sc = place(sc, Loc1, Loc2); continue; } else if (c == '\\') { c = *rp++; if (c >= '1' && c < NBRA+'1') { sc = place(sc, Braslist[c-'1'], Braelist[c-'1']); continue; } } if (sc >= gbend) growsp("output line too long."); genbuf[sc++] = (char)c; } lc = Loc2; Loc2 = sc; do { if (sc >= gbend) growsp("Output line too long."); } while (genbuf[sc++] = linebuf[lc++], lc <= spend); genend = sc-1; lc = 0; /*linebuf*/ sc = 0; /*genbuf*/ while (linebuf[lc++] = genbuf[sc++], sc <= genend); spend = lc-1; } static int place(int asc, int al1, int al2) { register int sc; register int l1, l2; sc = asc; l1 = al1; l2 = al2; while (l1 < l2) { if (sc >= gbend) growsp("Output line too long."); genbuf[sc++] = linebuf[l1++]; } return(sc); } static void command(struct reptr *ipc) { register int i; wint_t c; register char *p1, *p2; int k1, k2, k3; char *lp; int execc; switch(ipc->command) { case ACOM: *A(aptr) = ipc; aptr_inc(); *A(aptr) = 0; break; case CCOM: delflag = 1; if(!ipc->inar || dolflag) { for(p1 = ipc->bptr.re1; *p1; ) { putc(*p1&0377, stdout); p1++; } putc('\n', stdout); } break; case DCOM: delflag++; break; case CDCOM: p1 = p2 = linebuf; while(*p1 != '\n') { if(p1++ == &linebuf[spend]) { delflag++; return; } } p1++; while(*p2++ = *p1++, p1 <= &linebuf[spend]); spend = p2-1 - linebuf; jflag++; break; case EQCOM: fprintf(stdout, "%lld\n", lnum); break; case GCOM: p1 = linebuf; p2 = holdsp; while(*p1++ = *p2++, p2 <= &holdsp[hspend]); spend = p1-1 - linebuf; break; case CGCOM: linebuf[spend++] = '\n'; k1 = spend; k2 = 0; /*holdsp*/ do { if(k1 >= lbend) growsp(NULL); } while(linebuf[k1++] = holdsp[k2++], k2 <= hspend); spend = k1-1; break; case HCOM: p1 = holdsp; p2 = linebuf; while(*p1++ = *p2++, p2 <= &linebuf[spend]); hspend = p1-1 - holdsp; break; case CHCOM: holdsp[hspend++] = '\n'; k1 = hspend; k2 = 0; /*linebuf*/ do { if(k1 >= hend) growsp("\1hold space overflow !"); } while(holdsp[k1++] = linebuf[k2++], k2 <= spend); hspend = k1-1; break; case ICOM: for(p1 = ipc->bptr.re1; *p1; ) { putc(*p1&0377, stdout); p1++; } putc('\n', stdout); break; case BCOM: jflag = 1; break; case LCOM: lp = linebuf; lcomlen = 0; while (lp < &linebuf[spend]) { c = fetch(&lp); lcom(c, invchar == 0); } #if defined (SUS) || defined (SU3) putc('$', stdout); #endif /* SUS, SU3 */ putc('\n', stdout); break; case NCOM: if(!nflag) { for(p1 = linebuf; p1 < &linebuf[spend]; p1++) putc(*p1&0377, stdout); putc('\n', stdout); } if(A(aptr) > abuf) arout(); if((execc = gline(0)) < 0) { pending = ipc; delflag = 1; break; } spend = execc; break; case CNCOM: if(A(aptr) > abuf) arout(); linebuf[spend++] = '\n'; if((execc = gline(spend)) < 0) { pending = ipc; delflag = 1; break; } spend = execc; break; case PCOM: for(p1 = linebuf; p1 < &linebuf[spend]; p1++) putc(*p1&0377, stdout); putc('\n', stdout); break; case CPCOM: cpcom: for(p1 = linebuf; *p1 != '\n' && p1<&linebuf[spend]; ) { putc(*p1&0377, stdout); p1++; } putc('\n', stdout); break; case QCOM: if(!nflag) { for(p1 = linebuf; p1 < &linebuf[spend]; p1++) putc(*p1&0377, stdout); putc('\n', stdout); } if(A(aptr) > abuf) arout(); fclose(stdout); if (ibrd > 0) lseek(f, -ibrd, SEEK_CUR); exit(0); case RCOM: *A(aptr) = ipc; aptr_inc(); *A(aptr) = 0; break; case SCOM: i = substitute(ipc); if(ipc->pfl && i) if(ipc->pfl == 1) { for(p1 = linebuf; p1 < &linebuf[spend]; p1++) putc(*p1&0377, stdout); putc('\n', stdout); } else goto cpcom; if(i && ipc->fcode) goto wcom; break; case TCOM: if(sflag == 0) break; sflag = 0; jflag = 1; break; wcom: case WCOM: fprintf(ipc->fcode, "%s\n", linebuf); break; case XCOM: p1 = linebuf; p2 = genbuf; while(*p2++ = *p1++, p1 <= &linebuf[spend]); genend = p2-1 - genbuf; p1 = holdsp; p2 = linebuf; while(*p2++ = *p1++, p1 <= &holdsp[hspend]); spend = p2-1 - linebuf; p1 = genbuf; p2 = holdsp; while(*p2++ = *p1++, p1 <= &genbuf[genend]); hspend = p2-1 - holdsp; break; case YCOM: if (multibyte) { struct yitem **yt, *yp; yt = (struct yitem **)ipc->bptr.re1; k1 = 0; /*linebuf*/ k2 = 0; /*genbuf*/ do { k3 = k1; lp = &linebuf[k1]; c = fetch(&lp); k1 = lp - linebuf; if (invchar == 0 && (yp = ylook(c, yt, 0)) != NULL) { k3 = 0; /*yp->y_mc*/ do { if (k2 >= gbend) growsp("output " "line too " "long."); genbuf[k2] = yp->y_mc[k3++]; } while (genbuf[k2++] != '\0'); k2--; } else { while (k3 < k1) { if (k2 >= gbend) growsp("output " "line too " "long."); genbuf[k2++] = linebuf[k3++]; } } } while (k1 <= spend); genend = k2-1; p1 = linebuf; p2 = genbuf; while (*p1++ = *p2++, p2 <= &genbuf[genend]); spend = p1-1 - linebuf; } else { p1 = linebuf; p2 = ipc->bptr.re1; while((*p1 = p2[*p1 & 0377]) != 0) p1++; } break; case COCOM: case ECOM: case FCOM: case CWCOM: ; } } static int gline(int addr) { register char *p2; register int c; register int c1; c1 = addr; p2 = cbp; for (;;) { if (p2 >= ebp) { if (f < 0 || (c = read(f, ibuf, sizeof ibuf)) <= 0) { if (c1 > addr && dolflag == 0) { c = 1; ibuf[0] = '\n'; close(f); f = -1; } else return(-1); } else ibrd += c; p2 = ibuf; ebp = ibuf+c; } if ((c = *p2++ & 0377) == '\n') { ibrd--; if(needdol && p2 >= ebp) { if(f<0||(c = read(f, ibuf, sizeof ibuf)) <= 0) { close(f); f = -1; if(eargc == 0) dolflag = 1; } else ibrd += c; p2 = ibuf; ebp = ibuf + c; } break; } if(c1 >= lbend) growsp(NULL); linebuf[c1++] = (char)c; ibrd--; } lnum++; if(c1 >= lbend) growsp(NULL); linebuf[c1] = 0; cbp = p2; sflag = 0; return(c1); } static void arout(void) { register char *p1; struct reptr **a; FILE *fi; char c; int t; for (a = abuf; *a; a++) { if((*a)->command == ACOM) { for(p1 = (*a)->bptr.re1; *p1; ) { putc(*p1&0377, stdout); p1++; } putc('\n', stdout); } else { if((fi = fopen((*a)->bptr.re1, "r")) == NULL) continue; while((t = getc(fi)) != EOF) { c = t; putc(c&0377, stdout); } fclose(fi); } } aptr = 1; *A(aptr) = 0; } static void lcom(wint_t c, int valid) { if (!valid) { oout(c); return; } #if defined (SUS) || defined (SU3) switch (c) { case '\\': mout("\\\\"); return; case '\a': mout("\\a"); return; case '\b': mout("\\b"); return; case '\f': mout("\\f"); return; case '\r': mout("\\r"); return; case '\t': mout("\\t"); return; case '\v': mout("\\v"); return; } #else /* !SUS, !SU3 */ if (c < 040) { mout(trans[c]); return; } #endif /* !SUS, !SU3 */ if (multibyte) { if (iswprint(c)) wout(c); else nout(c); } else { if (isprint(c)) lout(c); else oout(c); } } static void oout(int c) { char lbuf[5], *p; int d; const char *nums = "01234567"; p = lbuf; *p++ = '\\'; *p++ = nums[(c & ~077) >> 6]; c &= 077; d = c & 07; *p++ = c > d ? nums[(c-d)>>3] : nums[0]; *p++ = nums[d]; *p = '\0'; mout(lbuf); } static void mout(const char *p) { while (*p != '\0') { lout(*p & 0377); p++; } } static void nout(wint_t c) { char mb[MB_LEN_MAX+1]; char *p; int i; if ((i = wctomb(mb, c)) > 0) { mb[i] = '\0'; for (p = mb; *p; p++) oout(*p & 0377); } } static void lout(int c) { if (lcomlen++ > 70) { putc('\\', stdout); putc('\n', stdout); lcomlen = 1; } putc(c, stdout); } static void wout(wint_t c) { char mb[MB_LEN_MAX+1], *p; int i, w; if ((i = wctomb(mb, c)) > 0) { w = wcwidth(c); if (lcomlen + w > 70) { putc('\\', stdout); putc('\n', stdout); lcomlen = 0; } mb[i] = '\0'; for (p = mb; *p; p++) putc(*p & 0377, stdout); lcomlen += w; } }