/* 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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <wchar.h>
#include <wctype.h>
#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 <regexp.h>
#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;
}
}
syntax highlighted by Code2HTML, v. 0.9.1