123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719 |
- #include <stdlib.h>
- #include <sys/types.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <stdio.h>
- #include "sed.h"
- #define Read(f, buf, n) (fflush(stdout), read(f, buf, n))
- void
- execute(uchar *file)
- {
- uchar *p1, *p2;
- union reptr *ipc;
- int c;
- long l;
- uchar *execp;
- if (file) {
- if ((f = open((char*)file, O_RDONLY)) < 0) {
- fprintf(stderr, "sed: Can't open %s\n", file);
- }
- } else
- f = 0;
- ebp = ibuf;
- cbp = ibuf;
- if(pending) {
- ipc = pending;
- pending = 0;
- goto yes;
- }
- for(;;) {
- if((execp = gline(linebuf)) == badp) {
- 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) {
- l = p2[1]&0377
- | ((p2[2]&0377)<<8)
- | ((p2[3]&0377)<<16)
- | ((p2[4]&0377)<<24);
- if(lnum > l) {
- ipc->r1.inar = 0;
- if(ipc->r1.negfl)
- goto yes;
- ipc++;
- continue;
- }
- if(lnum == l) {
- 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) {
- l = p1[1]&0377
- | ((p1[2]&0377)<<8)
- | ((p1[3]&0377)<<16)
- | ((p1[4]&0377)<<24);
- if(lnum != l) {
- 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++)
- putc(*p1, stdout);
- putc('\n', stdout);
- }
- if(aptr > abuf) {
- arout();
- }
- delflag = 0;
- }
- }
- int
- match(uchar *expbuf, int gf)
- {
- uchar *p1, *p2;
- int c;
- if(gf) {
- if(*expbuf) return(0);
- p1 = linebuf;
- p2 = genbuf;
- while(*p1++ = *p2++);
- locs = p1 = loc2;
- } else {
- p1 = linebuf;
- locs = 0;
- }
- p2 = expbuf;
- if(*p2++) {
- loc1 = p1;
- if(*p2 == CCHR && p2[1] != *p1)
- return(0);
- return(advance(p1, p2));
- }
- /* fast check for first character */
- if(*p2 == CCHR) {
- c = p2[1];
- do {
- if(*p1 != c)
- continue;
- if(advance(p1, p2)) {
- loc1 = p1;
- return(1);
- }
- } while(*p1++);
- return(0);
- }
- do {
- if(advance(p1, p2)) {
- loc1 = p1;
- return(1);
- }
- } while(*p1++);
- return(0);
- }
- int
- advance(uchar *alp, uchar *aep)
- {
- uchar *lp, *ep, *curlp;
- uchar c;
- uchar *bbeg;
- int ct;
- /*fprintf(stderr, "*lp = %c, %o\n*ep = %c, %o\n", *lp, *lp, *ep, *ep); /*DEBUG*/
- lp = alp;
- ep = aep;
- for (;;) switch (*ep++) {
- case CCHR:
- if (*ep++ == *lp++)
- continue;
- return(0);
- case CDOT:
- if (*lp++)
- continue;
- return(0);
- case CNL:
- case CDOL:
- if (*lp == 0)
- continue;
- return(0);
- case CEOF:
- loc2 = lp;
- return(1);
- case CCL:
- c = *lp++;
- if(ep[c>>3] & bittab[c & 07]) {
- ep += 32;
- continue;
- }
- return(0);
- case CBRA:
- braslist[*ep++] = lp;
- continue;
- case CKET:
- braelist[*ep++] = lp;
- continue;
- case CBACK:
- bbeg = braslist[*ep];
- ct = braelist[*ep++] - bbeg;
- if(ecmp(bbeg, lp, ct)) {
- lp += ct;
- continue;
- }
- return(0);
- case CBACK|STAR:
- bbeg = braslist[*ep];
- ct = braelist[*ep++] - bbeg;
- curlp = lp;
- while(ecmp(bbeg, lp, ct))
- lp += ct;
- while(lp >= curlp) {
- if(advance(lp, ep)) return(1);
- lp -= ct;
- }
- return(0);
- case CDOT|STAR:
- curlp = lp;
- while (*lp++);
- goto star;
- case CCHR|STAR:
- curlp = lp;
- while (*lp++ == *ep);
- ep++;
- goto star;
- case CCL|STAR:
- curlp = lp;
- do {
- c = *lp++;
- } while(ep[c>>3] & bittab[c & 07]);
- ep += 32;
- goto star;
- star:
- if(--lp == curlp) {
- continue;
- }
- if(*ep == CCHR) {
- c = ep[1];
- do {
- if(*lp != c)
- continue;
- if(advance(lp, ep))
- return(1);
- } while(lp-- > curlp);
- return(0);
- }
- if(*ep == CBACK) {
- c = *(braslist[ep[1]]);
- do {
- if(*lp != c)
- continue;
- if(advance(lp, ep))
- return(1);
- } while(lp-- > curlp);
- return(0);
- }
- do {
- if(lp == locs) break;
- if (advance(lp, ep))
- return(1);
- } while (lp-- > curlp);
- return(0);
- default:
- fprintf(stderr, "sed: RE botch, %o\n", *--ep);
- exit(1);
- }
- }
- int
- substitute(union reptr *ipc)
- {
- uchar *oloc2;
- if(match(ipc->r1.re1, 0)) {
- sflag = 1;
- if(!ipc->r1.gfl) {
- dosub(ipc->r1.rhs);
- return(1);
- }
- oloc2 = NULL;
- do {
- if(oloc2 == loc2) {
- loc2++;
- continue;
- } else {
- dosub(ipc->r1.rhs);
- if(*loc2 == 0)
- break;
- oloc2 = loc2;
- }
- } while(match(ipc->r1.re1, 1));
- return(1);
- }
- return(0);
- }
- void
- dosub(uchar *rhsbuf)
- {
- uchar *lp, *sp, *rp;
- int c;
- lp = linebuf;
- sp = genbuf;
- rp = rhsbuf;
- while (lp < loc1)
- *sp++ = *lp++;
- while(c = *rp++) {
- if (c == '\\') {
- c = *rp++;
- if (c >= '1' && c < NBRA+'1') {
- sp = place(sp, braslist[c-'1'], braelist[c-'1']);
- continue;
- }
- } else if(c == '&') {
- sp = place(sp, loc1, loc2);
- continue;
- }
- *sp++ = c;
- if (sp >= &genbuf[LBSIZE])
- fprintf(stderr, "sed: Output line too long.\n");
- }
- lp = loc2;
- loc2 = sp - genbuf + linebuf;
- while (*sp++ = *lp++)
- if (sp >= &genbuf[LBSIZE]) {
- fprintf(stderr, "sed: Output line too long.\n");
- }
- lp = linebuf;
- sp = genbuf;
- while (*lp++ = *sp++);
- spend = lp-1;
- }
- uchar *
- place(uchar *asp, uchar *al1, uchar *al2)
- {
- uchar *sp, *l1, *l2;
- sp = asp;
- l1 = al1;
- l2 = al2;
- while (l1 < l2) {
- *sp++ = *l1++;
- if (sp >= &genbuf[LBSIZE])
- fprintf(stderr, "sed: Output line too long.\n");
- }
- return(sp);
- }
- void
- command(union reptr *ipc)
- {
- int i;
- uchar *p1, *p2;
- uchar *execp;
- switch(ipc->r1.command) {
- case ACOM:
- *aptr++ = ipc;
- if(aptr >= &abuf[ABUFSIZE]) {
- fprintf(stderr, "sed: Too many appends after line %ld\n",
- lnum);
- }
- *aptr = 0;
- break;
- case CCOM:
- delflag = 1;
- if(!ipc->r1.inar || dolflag) {
- for(p1 = ipc->r1.re1; *p1; )
- putc(*p1++, stdout);
- 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:
- 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;
- while(*p1++ = *p2++)
- if(p1 >= lbend)
- break;
- 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;
- while(*p1++ = *p2++)
- if(p1 >= hend)
- break;
- hspend = p1-1;
- break;
- case ICOM:
- for(p1 = ipc->r1.re1; *p1; )
- putc(*p1++, stdout);
- putc('\n', stdout);
- break;
- case BCOM:
- jflag = 1;
- break;
- case LCOM:
- p1 = linebuf;
- p2 = genbuf;
- while(*p1) {
- p2 = lformat(*p1++ & 0377, p2);
- if(p2>lcomend && *p1) {
- *p2 = 0;
- fprintf(stdout, "%s\\\n", genbuf);
- p2 = genbuf;
- }
- }
- if(p2>genbuf && (p1[-1]==' '||p1[-1]=='\n'))
- p2 = lformat('\n', p2);
- *p2 = 0;
- fprintf(stdout, "%s\n", genbuf);
- break;
- case NCOM:
- if(!nflag) {
- for(p1 = linebuf; p1 < spend; p1++)
- putc(*p1, stdout);
- putc('\n', stdout);
- }
- if(aptr > abuf)
- arout();
- if((execp = gline(linebuf)) == badp) {
- pending = ipc;
- delflag = 1;
- break;
- }
- spend = execp;
- break;
- case CNCOM:
- if(aptr > abuf)
- arout();
- *spend++ = '\n';
- if((execp = gline(spend)) == badp) {
- pending = ipc;
- delflag = 1;
- break;
- }
- spend = execp;
- break;
- case PCOM:
- for(p1 = linebuf; p1 < spend; p1++)
- putc(*p1, stdout);
- putc('\n', stdout);
- break;
- case CPCOM:
- cpcom:
- for(p1 = linebuf; *p1 != '\n' && *p1 != '\0'; )
- putc(*p1++, stdout);
- putc('\n', stdout);
- break;
- case QCOM:
- if(!nflag) {
- for(p1 = linebuf; p1 < spend; p1++)
- putc(*p1, stdout);
- putc('\n', stdout);
- }
- if(aptr > abuf) arout();
- fclose(stdout);
- lseek(f,(long)(cbp-ebp),2);
- exit(0);
- case RCOM:
- *aptr++ = ipc;
- if(aptr >= &abuf[ABUFSIZE])
- fprintf(stderr, "sed: Too many reads after line%ld\n",
- lnum);
- *aptr = 0;
- break;
- case SCOM:
- i = substitute(ipc);
- if(ipc->r1.pfl && i)
- if(ipc->r1.pfl == 1) {
- for(p1 = linebuf; p1 < spend; p1++)
- putc(*p1, stdout);
- 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:
- fprintf(ipc->r1.fcode, "%s\n", linebuf);
- 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[*p1]) p1++;
- break;
- }
- }
- uchar *
- gline(uchar *addr)
- {
- uchar *p1, *p2;
- int c;
- sflag = 0;
- p1 = addr;
- p2 = cbp;
- for (;;) {
- if (p2 >= ebp) {
- if ((c = Read(f, ibuf, 512)) <= 0) {
- return(badp);
- }
- p2 = ibuf;
- ebp = ibuf+c;
- }
- if ((c = *p2++) == '\n') {
- if(p2 >= ebp) {
- if((c = Read(f, ibuf, 512)) <= 0) {
- close(f);
- if(eargc == 0)
- dolflag = 1;
- }
- p2 = ibuf;
- ebp = ibuf + c;
- }
- break;
- }
- if(c)
- if(p1 < lbend)
- *p1++ = c;
- }
- lnum++;
- *p1 = 0;
- cbp = p2;
- return(p1);
- }
- int
- ecmp(uchar *a, uchar *b, int count)
- {
- while(count--)
- if(*a++ != *b++) return(0);
- return(1);
- }
- void
- arout(void)
- {
- uchar *p1;
- FILE *fi;
- uchar c;
- int t;
- aptr = abuf - 1;
- while(*++aptr) {
- if((*aptr)->r1.command == ACOM) {
- for(p1 = (*aptr)->r1.re1; *p1; )
- putc(*p1++, stdout);
- putc('\n', stdout);
- } else {
- if((fi = fopen((char*)((*aptr)->r1.re1), "r")) == NULL)
- continue;
- while((t = getc(fi)) != EOF) {
- c = t;
- putc(c, stdout);
- }
- fclose(fi);
- }
- }
- aptr = abuf;
- *aptr = 0;
- }
- uchar *
- lformat(int c, uchar *p)
- {
- int trans =
- c=='\b'? 'b':
- c=='\t'? 't':
- c=='\n'? 'n':
- c=='\v'? 'v':
- c=='\f'? 'f':
- c=='\r'? 'r':
- c=='\\'? '\\':
- 0;
- if(trans) {
- *p++ = '\\';
- *p++ = trans;
- } else if(c<040 || c>=0177) {
- *p++ = '\\';
- *p++ = ((c>>6)&07) + '0';
- *p++ = ((c>>3)&07) + '0';
- *p++ = (c&07) + '0';
- } else
- *p++ = c;
- return p;
- }
|