728 lines
12 KiB
C
728 lines
12 KiB
C
/* Copyright (c) 1984 AT&T */
|
||
/* All Rights Reserved */
|
||
|
||
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
|
||
/* The copyright notice above does not evidence any */
|
||
/* actual or intended publication of such source code. */
|
||
|
||
#ifndef lint
|
||
static char sccsid[] = "@(#)sed1.c 1.1 92/07/30 SMI"; /* from S5R3.1 1.7 */
|
||
#endif
|
||
|
||
#include <stdio.h>
|
||
#include "sed.h"
|
||
#include <regexp.h>
|
||
|
||
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 lnum;
|
||
char holdsp[LBSIZE+1];
|
||
char *spend;
|
||
char *hspend;
|
||
int nflag;
|
||
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[];
|
||
|
||
execute(file)
|
||
char *file;
|
||
{
|
||
register char *p1, *p2;
|
||
register 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;
|
||
|
||
}
|
||
}
|
||
match(expbuf, gf)
|
||
char *expbuf;
|
||
{
|
||
register char *p1;
|
||
|
||
if(gf) {
|
||
if(*expbuf) return(0);
|
||
locs = p1 = loc2;
|
||
} else {
|
||
p1 = linebuf;
|
||
locs = 0;
|
||
}
|
||
|
||
circf = *expbuf++;
|
||
return(step(p1, expbuf));
|
||
}
|
||
|
||
substitute(ipc)
|
||
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);
|
||
}
|
||
|
||
dosub(rhsbuf,n)
|
||
char *rhsbuf;
|
||
int n;
|
||
{
|
||
register 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;
|
||
{
|
||
register char *sp, *l1, *l2;
|
||
|
||
sp = asp;
|
||
l1 = al1;
|
||
l2 = al2;
|
||
while (l1 < l2) {
|
||
*sp++ = *l1++;
|
||
if (sp == &genbuf[LBSIZE+1])
|
||
break;
|
||
}
|
||
return(sp);
|
||
}
|
||
|
||
command(ipc)
|
||
union reptr *ipc;
|
||
{
|
||
register int i;
|
||
register 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 %ld\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, "%ld\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 %ld\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;
|
||
{
|
||
register char *p1, *p2;
|
||
register 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;
|
||
register char *ep;
|
||
{
|
||
register char *p;
|
||
|
||
p = compile(x1, ep + 1, x3, x4);
|
||
if(p == ep + 1)
|
||
return(ep);
|
||
*ep = circf;
|
||
return(p);
|
||
}
|
||
|
||
regerr(err)
|
||
register 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;
|
||
}
|
||
}
|
||
|
||
arout()
|
||
{
|
||
register 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;
|
||
}
|
||
|