diff options
Diffstat (limited to 'utils')
| -rw-r--r-- | utils/sed/sed.c | 1307 |
1 files changed, 669 insertions, 638 deletions
diff --git a/utils/sed/sed.c b/utils/sed/sed.c index e275b8f4..eb43364a 100644 --- a/utils/sed/sed.c +++ b/utils/sed/sed.c @@ -1,7 +1,5 @@ /* - * sed -- stream editor - * - * + * sed -- stream editor */ #include <lib9.h> #include <bio.h> @@ -13,35 +11,37 @@ enum { ADDSIZE = 10000, /* size of add & read buffer */ MAXADDS = 20, /* max pending adds and reads */ LBSIZE = 8192, /* input line size */ - LABSIZE = 50, /* max label name size */ + LABSIZE = 50, /* max number of labels */ MAXSUB = 10, /* max number of sub reg exp */ - MAXFILES = 120, /* max output files */ + MAXFILES = 120 /* max output files */ }; - /* An address is a line #, a R.E., "$", a reference to the last - * R.E., or nothing. - */ -typedef struct { + +/* + * An address is a line #, a R.E., "$", a reference to the last + * R.E., or nothing. + */ +typedef struct { enum { A_NONE, A_DOL, A_LINE, A_RE, - A_LAST, + A_LAST }type; - union { - long line; /* Line # */ - Reprog *rp; /* Compiled R.E. */ - }; +/* union { */ + long line; /* Line # */ + Reprog *rp; /* Compiled R.E. */ +/* }; */ } Addr; typedef struct SEDCOM { Addr ad1; /* optional start address */ Addr ad2; /* optional end address */ - union { +/* union { */ Reprog *re1; /* compiled R.E. */ Rune *text; /* added text or file name */ struct SEDCOM *lb1; /* destination command of branch */ - }; +/* }; */ Rune *rhs; /* Right-hand side of substitution */ Biobuf* fcode; /* File ID for read and write */ char command; /* command code -see below */ @@ -51,7 +51,7 @@ typedef struct SEDCOM { char negfl; /* negation flag */ } SedCom; - /* Command Codes for field SedCom.command */ +/* Command Codes for field SedCom.command */ #define ACOM 01 #define BCOM 020 #define CCOM 02 @@ -80,16 +80,15 @@ typedef struct SEDCOM { #define YCOM 026 #define XCOM 033 - typedef struct label { /* Label symbol table */ - Rune asc[9]; /* Label name */ + Rune uninm[9]; /* Label name */ SedCom *chain; SedCom *address; /* Command associated with label */ } Label; typedef struct FILE_CACHE { /* Data file control block */ struct FILE_CACHE *next; /* Forward Link */ - char *name; /* Name of file */ + char *name; /* Name of file */ } FileCache; SedCom pspace[MAXCMDS]; /* Command storage */ @@ -106,14 +105,14 @@ SedCom *abuf[MAXADDS]; /* Queue of pending adds & reads */ SedCom **aptr = abuf; struct { /* Sed program input control block */ - enum PTYPE /* Either on command line or in file */ - { P_ARG, - P_FILE - } type; - union PCTL { /* Pointer to data */ + enum PTYPE { /* Either on command line or in file */ + P_ARG, + P_FILE + } type; +/* union PCTL { */ /* Pointer to data */ Biobuf *bp; char *curr; - }; +/* }; */ } prog; Rune genbuf[LBSIZE]; /* Miscellaneous buffer */ @@ -127,7 +126,7 @@ Rune seof; /* Pattern delimiter char */ Rune linebuf[LBSIZE+1]; /* Input data buffer */ Rune *lbend = linebuf+LBSIZE; /* End of buffer */ -Rune *spend = linebuf; /* End of input data */ +Rune *spend = linebuf; /* End of input data */ Rune *cp; /* Current scan point in linebuf */ Rune holdsp[LBSIZE+1]; /* Hold buffer */ @@ -149,7 +148,7 @@ Biobuf *fcode[MAXFILES]; /* File ID cache */ int nfiles = 0; /* Cache fill point */ Biobuf fout; /* Output stream */ -Biobuf stdin; /* Default input */ +Biobuf bstdin; /* Default input */ Biobuf* f = 0; /* Input data */ Label ltab[LABSIZE]; /* Label name symbol table */ @@ -162,7 +161,7 @@ Rune bad; /* Dummy err ptr reference */ Rune *badp = &bad; -char CGMES[] = "Command garbled: %S"; +char CGMES[] = "command garbled: %S"; char TMMES[] = "Too much text: %S"; char LTL[] = "Label too long: %S"; char AD0MES[] = "No addresses allowed: %S"; @@ -190,7 +189,7 @@ void newfile(enum PTYPE, char *); int opendata(void); Biobuf *open_file(char *); Rune *place(Rune *, Rune *, Rune *); -void quit(char *, char *); +void quit(char *, ...); int rline(Rune *, Rune *); Label *search(Label *); int substitute(SedCom *); @@ -203,7 +202,7 @@ void putline(Biobuf *bp, Rune *buf, int n); void main(int argc, char **argv) { - int compfl; + int compfl; lnum = 0; Binit(&fout, 1, OWRITE); @@ -213,40 +212,40 @@ main(int argc, char **argv) if(argc == 1) exits(0); ARGBEGIN{ - case 'n': - nflag++; - continue; - case 'f': - if(argc <= 1) - quit("no pattern-file", 0); - newfile(P_FILE, ARGF()); - fcomp(); - compfl = 1; - continue; - case 'e': - if (argc <= 1) - quit("missing pattern", 0); - newfile(P_ARG, ARGF()); - fcomp(); - compfl = 1; - continue; - case 'g': - gflag++; - continue; - default: - fprint(2, "sed: Unknown flag: %c\n", ARGC()); - continue; + case 'e': + if (argc <= 1) + quit("missing pattern"); + newfile(P_ARG, ARGF()); + fcomp(); + compfl = 1; + continue; + case 'f': + if(argc <= 1) + quit("no pattern-file"); + newfile(P_FILE, ARGF()); + fcomp(); + compfl = 1; + continue; + case 'g': + gflag++; + continue; + case 'n': + nflag++; + continue; + default: + fprint(2, "sed: Unknown flag: %c\n", ARGC()); + continue; } ARGEND if(compfl == 0) { if (--argc < 0) - quit("missing pattern", 0); + quit("missing pattern"); newfile(P_ARG, *argv++); fcomp(); } if(depth) - quit("Too many {'s", 0); + quit("Too many {'s"); ltab[0].address = rep; @@ -254,20 +253,20 @@ main(int argc, char **argv) if(argc <= 0) enroll(0); /* Add stdin to cache */ - else while(--argc >= 0) { - enroll(*argv++); - } + else + while(--argc >= 0) + enroll(*argv++); execute(); exits(0); } + void fcomp(void) { - Rune *tp; - SedCom *pt, *pt1; int i; Label *lpt; - + Rune *tp; + SedCom *pt, *pt1; static Rune *p = addspace; static SedCom **cmpend[DEPTH]; /* stack of {} operations */ @@ -287,7 +286,7 @@ comploop: if (rep->ad1.type != A_NONE) { if (rep->ad1.type == A_LAST) { if (!lastre) - quit("First RE may not be null", 0); + quit("First RE may not be null"); rep->ad1.type = A_RE; rep->ad1.rp = lastre; } @@ -295,7 +294,7 @@ comploop: cp++; address(&rep->ad2); if (rep->ad2.type == A_LAST) { - rep->ad1.type = A_RE; + rep->ad2.type = A_RE; rep->ad2.rp = lastre; } } else @@ -306,306 +305,319 @@ comploop: swit: switch(*cp++) { + default: + quit("Unrecognized command: %S", linebuf); + + case '!': + rep->negfl = 1; + goto swit; + + case '{': + rep->command = BCOM; + rep->negfl = !rep->negfl; + cmpend[depth++] = &rep->lb1; + if(++rep >= pend) + quit("Too many commands: %S", linebuf); + if(*cp == '\0') + continue; + goto comploop; - default: - quit("Unrecognized command: %S", (char *)linebuf); - - case '!': - rep->negfl = 1; - goto swit; + case '}': + if(rep->ad1.type != A_NONE) + quit(AD0MES, linebuf); + if(--depth < 0) + quit("Too many }'s"); + *cmpend[depth] = rep; + if(*cp == 0) + continue; + goto comploop; - case '{': - rep->command = BCOM; - rep->negfl = !(rep->negfl); - cmpend[depth++] = &rep->lb1; - if(++rep >= pend) - quit("Too many commands: %S", (char *) linebuf); - if(*cp == '\0') continue; - goto comploop; + case '=': + rep->command = EQCOM; + if(rep->ad2.type != A_NONE) + quit(AD1MES, linebuf); + break; - case '}': - if(rep->ad1.type != A_NONE) - quit(AD0MES, (char *) linebuf); - if(--depth < 0) - quit("Too many }'s", 0); - *cmpend[depth] = rep; - if(*cp == 0) continue; - goto comploop; + case ':': + if(rep->ad1.type != A_NONE) + quit(AD0MES, linebuf); - case '=': - rep->command = EQCOM; - if(rep->ad2.type != A_NONE) - quit(AD1MES, (char *) linebuf); - break; + while(*cp == ' ') + cp++; + tp = lab->uninm; + while (*cp && *cp != ';' && *cp != ' ' && + *cp != '\t' && *cp != '#') { + *tp++ = *cp++; + if(tp >= &lab->uninm[8]) + quit(LTL, linebuf); + } + *tp = '\0'; - case ':': - if(rep->ad1.type != A_NONE) - quit(AD0MES, (char *) linebuf); - - while(*cp == ' ') - cp++; - tp = lab->asc; - while (*cp && *cp != ';' && *cp != ' ' && *cp != '\t' && *cp != '#') { - *tp++ = *cp++; - if(tp >= &(lab->asc[8])) - quit(LTL, (char *) linebuf); - } - *tp = '\0'; - - if(lpt = search(lab)) { - if(lpt->address) - quit("Duplicate labels: %S", (char *) linebuf); - } else { - lab->chain = 0; - lpt = lab; - if(++lab >= labend) - quit("Too many labels: %S", (char *) linebuf); - } - lpt->address = rep; - if (*cp == '#') - continue; - rep--; /* reuse this slot */ - break; + if (*lab->uninm == '\0') /* no label? */ + quit(CGMES, linebuf); + if(lpt = search(lab)) { + if(lpt->address) + quit("Duplicate labels: %S", linebuf); + } else { + lab->chain = 0; + lpt = lab; + if(++lab >= labend) + quit("Too many labels: %S", linebuf); + } + lpt->address = rep; + if (*cp == '#') + continue; + rep--; /* reuse this slot */ + break; - case 'a': - rep->command = ACOM; - if(rep->ad2.type != A_NONE) - quit(AD1MES, (char *) linebuf); - if(*cp == '\\') cp++; - if(*cp++ != '\n') - quit(CGMES, (char *) linebuf); - rep->text = p; - p = stext(p, addend); - break; - case 'c': - rep->command = CCOM; - if(*cp == '\\') cp++; - if(*cp++ != '\n') - quit(CGMES, (char *) linebuf); - rep->text = p; - p = stext(p, addend); - break; - case 'i': - rep->command = ICOM; - if(rep->ad2.type != A_NONE) - quit(AD1MES, (char *) linebuf); - if(*cp == '\\') cp++; - if(*cp++ != '\n') - quit(CGMES, (char *) linebuf); - rep->text = p; - p = stext(p, addend); - break; + case 'a': + rep->command = ACOM; + if(rep->ad2.type != A_NONE) + quit(AD1MES, linebuf); + if(*cp == '\\') + cp++; + if(*cp++ != '\n') + quit(CGMES, linebuf); + rep->text = p; + p = stext(p, addend); + break; + case 'c': + rep->command = CCOM; + if(*cp == '\\') + cp++; + if(*cp++ != '\n') + quit(CGMES, linebuf); + rep->text = p; + p = stext(p, addend); + break; + case 'i': + rep->command = ICOM; + if(rep->ad2.type != A_NONE) + quit(AD1MES, linebuf); + if(*cp == '\\') + cp++; + if(*cp++ != '\n') + quit(CGMES, linebuf); + rep->text = p; + p = stext(p, addend); + break; - case 'g': - rep->command = GCOM; - break; + case 'g': + rep->command = GCOM; + break; - case 'G': - rep->command = CGCOM; - break; + case 'G': + rep->command = CGCOM; + break; - case 'h': - rep->command = HCOM; - break; + case 'h': + rep->command = HCOM; + break; - case 'H': - rep->command = CHCOM; - break; + case 'H': + rep->command = CHCOM; + break; - case 't': - rep->command = TCOM; - goto jtcommon; + case 't': + rep->command = TCOM; + goto jtcommon; - case 'b': - rep->command = BCOM; + case 'b': + rep->command = BCOM; jtcommon: - while(*cp == ' ')cp++; - if(*cp == '\0') { - if(pt = ltab[0].chain) { - while(pt1 = pt->lb1) - pt = pt1; - pt->lb1 = rep; - } else - ltab[0].chain = rep; - break; - } - tp = lab->asc; - while((*tp++ = *cp++)) - if(tp >= &(lab->asc[8])) - quit(LTL, (char *) linebuf); - cp--; - tp[-1] = '\0'; - - if(lpt = search(lab)) { - if(lpt->address) { - rep->lb1 = lpt->address; - } else { - pt = lpt->chain; - while(pt1 = pt->lb1) - pt = pt1; + while(*cp == ' ') + cp++; + if(*cp == '\0' || *cp == ';') { + /* no label; jump to end */ + if(pt = ltab[0].chain) { + while((pt1 = pt->lb1) != nil) + pt = pt1; + pt->lb1 = rep; + } else + ltab[0].chain = rep; + break; + } + + /* copy label into lab->uninm */ + tp = lab->uninm; + while((*tp = *cp++) != '\0' && *tp != ';') + if(++tp >= &lab->uninm[8]) + quit(LTL, linebuf); + cp--; + *tp = '\0'; + + if (*lab->uninm == '\0') + /* shouldn't get here */ + quit(CGMES, linebuf); + if((lpt = search(lab)) != nil) { + if(lpt->address) + rep->lb1 = lpt->address; + else { + for(pt = lpt->chain; pt != nil && + (pt1 = pt->lb1) != nil; pt = pt1) + ; + if (pt) pt->lb1 = rep; - } - } else { - lab->chain = rep; - lab->address = 0; - if(++lab >= labend) - quit("Too many labels: %S", - (char *) linebuf); } - break; + } else { /* add new label */ + lab->chain = rep; + lab->address = 0; + if(++lab >= labend) + quit("Too many labels: %S", linebuf); + } + break; - case 'n': - rep->command = NCOM; - break; + case 'n': + rep->command = NCOM; + break; - case 'N': - rep->command = CNCOM; - break; + case 'N': + rep->command = CNCOM; + break; - case 'p': - rep->command = PCOM; - break; + case 'p': + rep->command = PCOM; + break; - case 'P': - rep->command = CPCOM; - break; + case 'P': + rep->command = CPCOM; + break; - case 'r': - rep->command = RCOM; - if(rep->ad2.type != A_NONE) - quit(AD1MES, (char *) linebuf); - if(*cp++ != ' ') - quit(CGMES, (char *) linebuf); - rep->text = p; - p = stext(p, addend); - break; + case 'r': + rep->command = RCOM; + if(rep->ad2.type != A_NONE) + quit(AD1MES, linebuf); + if(*cp++ != ' ') + quit(CGMES, linebuf); + rep->text = p; + p = stext(p, addend); + break; - case 'd': - rep->command = DCOM; - break; + case 'd': + rep->command = DCOM; + break; - case 'D': - rep->command = CDCOM; - rep->lb1 = pspace; - break; + case 'D': + rep->command = CDCOM; + rep->lb1 = pspace; + break; - case 'q': - rep->command = QCOM; - if(rep->ad2.type != A_NONE) - quit(AD1MES, (char *) linebuf); - break; + case 'q': + rep->command = QCOM; + if(rep->ad2.type != A_NONE) + quit(AD1MES, linebuf); + break; - case 'l': - rep->command = LCOM; - break; + case 'l': + rep->command = LCOM; + break; - case 's': - rep->command = SCOM; - seof = *cp++; - if ((rep->re1 = compile()) == 0) { - if(!lastre) - quit("First RE may not be null.", 0); - rep->re1 = lastre; - } - rep->rhs = p; - if((p = compsub(p, addend)) == 0) - quit(CGMES, (char *) linebuf); - if(*cp == 'g') { - cp++; - rep->gfl++; - } else if(gflag) - rep->gfl++; - - if(*cp == 'p') { - cp++; - rep->pfl = 1; - } + case 's': + rep->command = SCOM; + seof = *cp++; + if ((rep->re1 = compile()) == 0) { + if(!lastre) + quit("First RE may not be null."); + rep->re1 = lastre; + } + rep->rhs = p; + if((p = compsub(p, addend)) == 0) + quit(CGMES, linebuf); + if(*cp == 'g') { + cp++; + rep->gfl++; + } else if(gflag) + rep->gfl++; - if(*cp == 'P') { - cp++; - rep->pfl = 2; - } + if(*cp == 'p') { + cp++; + rep->pfl = 1; + } - if(*cp == 'w') { - cp++; - if(*cp++ != ' ') - quit(CGMES, (char *) linebuf); - text(fname[nfiles]); - for(i = nfiles - 1; i >= 0; i--) - if(cmp(fname[nfiles],fname[i]) == 0) { - rep->fcode = fcode[i]; - goto done; - } - if(nfiles >= MAXFILES) - quit("Too many files in w commands 1", 0); - rep->fcode = open_file(fname[nfiles]); - } - break; + if(*cp == 'P') { + cp++; + rep->pfl = 2; + } - case 'w': - rep->command = WCOM; - if(*cp++ != ' ') - quit(CGMES, (char *) linebuf); + if(*cp == 'w') { + cp++; + if(*cp++ != ' ') + quit(CGMES, linebuf); text(fname[nfiles]); for(i = nfiles - 1; i >= 0; i--) if(cmp(fname[nfiles], fname[i]) == 0) { rep->fcode = fcode[i]; goto done; } - if(nfiles >= MAXFILES){ - fprint(2, "sed: Too many files in w commands 2 \n"); - fprint(2, "nfiles = %d; MAXF = %d\n", nfiles, MAXFILES); - errexit(); - } + if(nfiles >= MAXFILES) + quit("Too many files in w commands 1"); rep->fcode = open_file(fname[nfiles]); - break; + } + break; - case 'x': - rep->command = XCOM; - break; + case 'w': + rep->command = WCOM; + if(*cp++ != ' ') + quit(CGMES, linebuf); + text(fname[nfiles]); + for(i = nfiles - 1; i >= 0; i--) + if(cmp(fname[nfiles], fname[i]) == 0) { + rep->fcode = fcode[i]; + goto done; + } + if(nfiles >= MAXFILES){ + fprint(2, "sed: Too many files in w commands 2 \n"); + fprint(2, "nfiles = %d; MAXF = %d\n", + nfiles, MAXFILES); + errexit(); + } + rep->fcode = open_file(fname[nfiles]); + break; - case 'y': - rep->command = YCOM; - seof = *cp++; - if (ycomp(rep) == 0) - quit(CGMES, (char *) linebuf); - break; + case 'x': + rep->command = XCOM; + break; + + case 'y': + rep->command = YCOM; + seof = *cp++; + if (ycomp(rep) == 0) + quit(CGMES, linebuf); + break; } done: if(++rep >= pend) - quit("Too many commands, last: %S", (char *) linebuf); - + quit("Too many commands, last: %S", linebuf); if(*cp++ != '\0') { if(cp[-1] == ';') goto comploop; - quit(CGMES, (char *) linebuf); + quit(CGMES, linebuf); } - } } Biobuf * open_file(char *name) { - Biobuf *bp; int fd; + Biobuf *bp; if ((bp = malloc(sizeof(Biobuf))) == 0) - quit("Out of memory", 0); + quit("Out of memory"); if ((fd = open(name, OWRITE)) < 0 && - (fd = create(name, OWRITE, 0666)) < 0) - quit("Cannot create %s", name); + (fd = create(name, OWRITE, 0666)) < 0) + quit("Cannot create %s", name); Binit(bp, fd, OWRITE); Bseek(bp, 0, 2); fcode[nfiles++] = bp; return bp; } -Rune * +Rune * compsub(Rune *rhs, Rune *end) { - Rune r; + Rune r; while ((r = *cp++) != '\0') { if(r == '\\') { @@ -627,9 +639,8 @@ compsub(Rune *rhs, Rune *end) } if (rhs < end) *rhs++ = r; - else + else return 0; - } return 0; } @@ -645,17 +656,17 @@ compile(void) return 0; ep = expbuf; do { - if (c == 0 || c == '\n') - quit(TMMES, (char *) linebuf); + if (c == '\0' || c == '\n') + quit(TMMES, linebuf); if (c == '\\') { if (ep >= expbuf+sizeof(expbuf)) - quit(TMMES, (char *) linebuf); + quit(TMMES, linebuf); ep += runetochar(ep, &c); if ((c = *cp++) == 'n') c = '\n'; } - if (ep >= expbuf+sizeof(expbuf)) - quit(TMMES, (char *) linebuf); + if (ep >= expbuf + sizeof(expbuf)) + quit(TMMES, linebuf); ep += runetochar(ep, &c); } while ((c = *cp++) != seof); *ep = 0; @@ -666,7 +677,7 @@ void regerror(char *s) { USED(s); - quit(CGMES, (char *) linebuf); + quit(CGMES, linebuf); } void @@ -700,21 +711,21 @@ rline(Rune *buf, Rune *end) r = c; } else if (r == '\n') { *buf = '\0'; - return(1); + return 1; } if (buf <= end) *buf++ = r; } *buf = '\0'; - return(-1); + return -1; } long getrune(void) { - char *p; long c; Rune r; + char *p; if (prog.type == P_ARG) { if ((p = prog.curr) != 0) { @@ -725,10 +736,10 @@ getrune(void) c = '\n'; /* fake an end-of-line */ prog.curr = 0; } - } else + } else c = -1; } else if ((c = Bgetrune(prog.bp)) < 0) - Bterm(prog.bp); + Bterm(prog.bp); return c; } @@ -736,7 +747,7 @@ void address(Addr *ap) { int c; - long lno; + long lno; if((c = *cp++) == '$') ap->type = A_DOL; @@ -748,9 +759,9 @@ address(Addr *ap) ap->type = A_LAST; } else if (c >= '0' && c <= '9') { - lno = c-'0'; + lno = c - '0'; while ((c = *cp) >= '0' && c <= '9') - lno = lno*10 + *cp++-'0'; + lno = lno*10 + *cp++ - '0'; if(!lno) quit("line number 0 is illegal",0); ap->type = A_LINE; @@ -766,33 +777,34 @@ cmp(char *a, char *b) /* compare characters */ { while(*a == *b++) if (*a == '\0') - return(0); - else a++; - return(1); + return 0; + else + a++; + return 1; } rcmp(Rune *a, Rune *b) /* compare runes */ { while(*a == *b++) if (*a == '\0') - return(0); - else a++; - return(1); + return 0; + else + a++; + return 1; } char * text(char *p) /* extract character string */ { - Rune r; + Rune r; - while(*cp == '\t' || *cp == ' ') - cp++; + while(*cp == ' ' || *cp == '\t') + cp++; while (*cp) { - if ((r = *cp++) == '\\') - if ((r = *cp++) == 0) - break;; + if ((r = *cp++) == '\\' && (r = *cp++) == '\0') + break; if (r == '\n') - while (*cp == '\t' || *cp == ' ') - cp++; + while (*cp == ' ' || *cp == '\t') + cp++; p += runetochar(p, &r); } *p++ = '\0'; @@ -802,17 +814,16 @@ text(char *p) /* extract character string */ Rune * stext(Rune *p, Rune *end) /* extract rune string */ { - while(*cp == '\t' || *cp == ' ') + while(*cp == ' ' || *cp == '\t') cp++; while (*cp) { - if (*cp == '\\') - if (*++cp == 0) - break; + if (*cp == '\\' && *++cp == '\0') + break; if (p >= end-1) - quit(TMMES, (char *) linebuf); + quit(TMMES, linebuf); if ((*p++ = *cp++) == '\n') - while(*cp == '\t' || *cp == ' ') - cp++; + while(*cp == ' ' || *cp == '\t') + cp++; } *p++ = 0; return p; @@ -820,12 +831,12 @@ stext(Rune *p, Rune *end) /* extract rune string */ Label * -search (Label *ptr) +search(Label *ptr) { Label *rp; for (rp = ltab; rp < ptr; rp++) - if(rcmp(rp->asc, ptr->asc) == 0) + if(rcmp(rp->uninm, ptr->uninm) == 0) return(rp); return(0); } @@ -837,13 +848,11 @@ dechain(void) SedCom *rptr, *trptr; for(lptr = ltab; lptr < lab; lptr++) { - if(lptr->address == 0) - quit("Undefined label: %S", (char *) lptr->asc); - + quit("Undefined label: %S", lptr->uninm); if(lptr->chain) { rptr = lptr->chain; - while(trptr = rptr->lb1) { + while((trptr = rptr->lb1) != nil) { rptr->lb1 = lptr->address; rptr = trptr; } @@ -855,22 +864,22 @@ dechain(void) int ycomp(SedCom *r) { - int i; - Rune *rp; - Rune c, *tsp, highc; - Rune *sp; + int i; + Rune *rp, *sp, *tsp; + Rune c, highc; highc = 0; for(tsp = cp; *tsp != seof; tsp++) { if(*tsp == '\\') tsp++; if(*tsp == '\n' || *tsp == '\0') - return(0); - if (*tsp > highc) highc = *tsp; + return 0; + if (*tsp > highc) + highc = *tsp; } tsp++; - if ((rp = r->text = (Rune *) malloc(sizeof(Rune)*(highc+2))) == 0) - quit("Out of memory", 0); + if ((rp = r->text = (Rune *)malloc(sizeof(Rune) * (highc+2))) == nil) + quit("Out of memory"); *rp++ = highc; /* save upper bound */ for (i = 0; i <= highc; i++) rp[i] = i; @@ -885,18 +894,18 @@ ycomp(SedCom *r) tsp++; } if(rp[c] == seof || rp[c] == '\0') { - free(r->re1); - r->re1 = 0; - return(0); + free(r->text); + r->text = nil; + return 0; } } if(*tsp != seof) { - free(r->re1); - r->re1 = 0; - return(0); + free(r->text); + r->text = nil; + return 0; } cp = tsp+1; - return(1); + return 1; } void @@ -914,24 +923,22 @@ execute(void) if(delflag) break; - if(jflag) { jflag = 0; if((ipc = ipc->lb1) == 0) break; } else ipc++; - } if(!nflag && !delflag) - putline(&fout, linebuf, spend-linebuf); - if(aptr > abuf) { + putline(&fout, linebuf, spend - linebuf); + if(aptr > abuf) arout(); - } delflag = 0; } } - /* determine if a statement should be applied to an input line */ + +/* determine if a statement should be applied to an input line */ int executable(SedCom *ipc) { @@ -939,51 +946,53 @@ executable(SedCom *ipc) if (ipc->active == 1) /* Second line */ ipc->active = 2; switch(ipc->ad2.type) { - case A_NONE: /* No second addr; use first */ - ipc->active = 0; - break; - case A_DOL: /* Accept everything */ - return !ipc->negfl; - case A_LINE: /* Line at end of range? */ - if (lnum <= ipc->ad2.line) { - if (ipc->ad2.line == lnum) - ipc->active = 0; - return !ipc->negfl; - } - ipc->active = 0; /* out of range */ - return ipc->negfl; - case A_RE: /* Check for matching R.E. */ - if (match(ipc->ad2.rp, linebuf)) + case A_NONE: /* No second addr; use first */ + ipc->active = 0; + break; + case A_DOL: /* Accept everything */ + return !ipc->negfl; + case A_LINE: /* Line at end of range? */ + if (lnum <= ipc->ad2.line) { + if (ipc->ad2.line == lnum) ipc->active = 0; return !ipc->negfl; - default: /* internal error */ - quit("Internal error", 0); + } + ipc->active = 0; /* out of range */ + return ipc->negfl; + case A_RE: /* Check for matching R.E. */ + if (match(ipc->ad2.rp, linebuf)) + ipc->active = 0; + return !ipc->negfl; + default: + quit("Internal error"); } } switch (ipc->ad1.type) { /* Check first address */ - case A_NONE: /* Everything matches */ + case A_NONE: /* Everything matches */ + return !ipc->negfl; + case A_DOL: /* Only last line */ + if (dolflag) return !ipc->negfl; - case A_DOL: /* Only last line */ - if (dolflag) - return !ipc->negfl; - break; - case A_LINE: /* Check line number */ - if (ipc->ad1.line == lnum) { - ipc->active = 1; /* In range */ - return !ipc->negfl; - } - break; - case A_RE: /* Check R.E. */ - if (match(ipc->ad1.rp, linebuf)) { - ipc->active = 1; /* In range */ - return !ipc->negfl; - } - break; - default: - quit("Internal error", 0); + break; + case A_LINE: /* Check line number */ + if (ipc->ad1.line == lnum) { + ipc->active = 1; /* In range */ + return !ipc->negfl; + } + break; + case A_RE: /* Check R.E. */ + if (match(ipc->ad1.rp, linebuf)) { + ipc->active = 1; /* In range */ + return !ipc->negfl; + } + break; + default: + quit("Internal error"); } return ipc->negfl; } + +int match(Reprog *pattern, Rune *buf) { if (!pattern) @@ -998,34 +1007,42 @@ match(Reprog *pattern, Rune *buf) loc1 = loc2 = 0; return 0; } + +int substitute(SedCom *ipc) { - if(match(ipc->re1, linebuf)) { - sflag = 1; + int len; + + if(!match(ipc->re1, linebuf)) + return 0; + + /* + * we have at least one match. some patterns, e.g. '$' or '^', can + * produce 0-length matches, so during a global substitute we must + * bump to the character after a 0-length match to keep from looping. + */ + sflag = 1; + if(ipc->gfl == 0) /* single substitution */ dosub(ipc->rhs); - if(!ipc->gfl) - return 1; - while (match(ipc->re1, loc2)) { - if (loc2-loc1 == 0){ /* NULL R.E. match */ - if (*loc2++ == 0) - break; - } else { - dosub(ipc->rhs); - if(*loc2 == 0) - break; - } - } - return 1; - } - return 0; + else + do{ /* global substitution */ + len = loc2 - loc1; /* length of match */ + dosub(ipc->rhs); /* dosub moves loc2 */ + if(*loc2 == 0) /* end of string */ + break; + if(len == 0) /* zero-length R.E. match */ + loc2++; /* bump over 0-length match */ + if(*loc2 == 0) /* end of string */ + break; + } while(match(ipc->re1, loc2)); + return 1; } void dosub(Rune *rhsbuf) { - Rune *lp, *sp; - Rune *rp; int c, n; + Rune *lp, *sp, *rp; lp = linebuf; sp = genbuf; @@ -1037,7 +1054,7 @@ dosub(Rune *rhsbuf) sp = place(sp, loc1, loc2); continue; } - if (c == 0xFFFF && (c = *rp++) >= '1' && c <= MAXSUB+'0') { + if (c == 0xFFFF && (c = *rp++) >= '1' && c < MAXSUB + '0') { n = c-'0'; if (subexp[n].s.rsp && subexp[n].e.rep) { sp = place(sp, subexp[n].s.rsp, subexp[n].e.rep); @@ -1061,7 +1078,7 @@ dosub(Rune *rhsbuf) sp = genbuf; while (*lp++ = *sp++) ; - spend = lp-1; + spend = lp - 1; } Rune * @@ -1072,7 +1089,7 @@ place(Rune *sp, Rune *l1, Rune *l2) if (sp >= &genbuf[LBSIZE]) fprint(2, "sed: Output line too long.\n"); } - return(sp); + return sp; } char * @@ -1082,16 +1099,16 @@ trans(int c) static char hex[] = "0123456789abcdef"; switch(c) { - case '\b': - return "\\b"; - case '\n': - return "\\n"; - case '\r': - return "\\r"; - case '\t': - return "\\t"; - case '\\': - return "\\\\"; + case '\b': + return "\\b"; + case '\n': + return "\\n"; + case '\r': + return "\\r"; + case '\t': + return "\\t"; + case '\\': + return "\\\\"; } buf[2] = hex[(c>>12)&0xF]; buf[3] = hex[(c>>8)&0xF]; @@ -1103,201 +1120,200 @@ trans(int c) void command(SedCom *ipc) { - int i, c; - Rune *p1, *p2; - char *ucp; - Rune *rp; - Rune *execp; + int i, c; + char *ucp; + Rune *execp, *p1, *p2, *rp; switch(ipc->command) { - - case ACOM: - *aptr++ = ipc; - if(aptr >= abuf+MAXADDS) { - quit("sed: Too many appends after line %ld\n", - (char *) lnum); - } - *aptr = 0; - break; - case CCOM: - delflag = 1; - if(ipc->active == 1) { - for(rp = ipc->text; *rp; rp++) - Bputrune(&fout, *rp); - Bputc(&fout, '\n'); - } - 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: - Bprint(&fout, "%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: + case ACOM: + *aptr++ = ipc; + if(aptr >= abuf+MAXADDS) + quit("sed: Too many appends after line %ld\n", + (char *)lnum); + *aptr = 0; + break; + case CCOM: + delflag = 1; + if(ipc->active == 1) { for(rp = ipc->text; *rp; rp++) Bputrune(&fout, *rp); Bputc(&fout, '\n'); - break; - case BCOM: - jflag = 1; - break; - case LCOM: - c = 0; - for (i = 0, rp = linebuf; *rp; rp++) { - c = *rp; - if(c >= 0x20 && c < 0x7F && c != '\\') { + } + 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: + Bprint(&fout, "%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(rp = ipc->text; *rp; rp++) + Bputrune(&fout, *rp); + Bputc(&fout, '\n'); + break; + case BCOM: + jflag = 1; + break; + case LCOM: + c = 0; + for (i = 0, rp = linebuf; *rp; rp++) { + c = *rp; + if(c >= 0x20 && c < 0x7F && c != '\\') { + Bputc(&fout, c); + if(i++ > 71) { + Bprint(&fout, "\\\n"); + i = 0; + } + } else { + for (ucp = trans(*rp); *ucp; ucp++){ + c = *ucp; Bputc(&fout, c); if(i++ > 71) { Bprint(&fout, "\\\n"); i = 0; } - } else { - for (ucp = trans(*rp); *ucp; ucp++){ - c = *ucp; - Bputc(&fout, c); - if(i++ > 71) { - Bprint(&fout, "\\\n"); - i = 0; - } - } } } - if(c == ' ') - Bprint(&fout, "\\n"); - Bputc(&fout, '\n'); - break; - case NCOM: - if(!nflag) - putline(&fout, linebuf, spend-linebuf); + } + if(c == ' ') + Bprint(&fout, "\\n"); + Bputc(&fout, '\n'); + break; + case NCOM: + if(!nflag) + putline(&fout, linebuf, spend-linebuf); - if(aptr > abuf) - arout(); - if((execp = gline(linebuf)) == 0) { - delflag = 1; - break; - } - spend = execp; + if(aptr > abuf) + arout(); + if((execp = gline(linebuf)) == 0) { + delflag = 1; break; - case CNCOM: - if(aptr > abuf) - arout(); - *spend++ = '\n'; - if((execp = gline(spend)) == 0) { - delflag = 1; - break; - } - spend = execp; + } + spend = execp; + break; + case CNCOM: + if(aptr > abuf) + arout(); + *spend++ = '\n'; + if((execp = gline(spend)) == 0) { + delflag = 1; break; - case PCOM: + } + spend = execp; + break; + case PCOM: + putline(&fout, linebuf, spend-linebuf); + break; + case CPCOM: +cpcom: + for(rp = linebuf; *rp && *rp != '\n'; rp++) + Bputc(&fout, *rp); + Bputc(&fout, '\n'); + break; + case QCOM: + if(!nflag) putline(&fout, linebuf, spend-linebuf); - break; - case CPCOM: - cpcom: - for(rp = linebuf; *rp && *rp != '\n'; rp++) - Bputc(&fout, *rp); - Bputc(&fout, '\n'); - break; - case QCOM: - if(!nflag) + if(aptr > abuf) + arout(); + exits(0); + case RCOM: + *aptr++ = ipc; + if(aptr >= &abuf[MAXADDS]) + quit("sed: Too many reads after line %ld\n", + (char *)lnum); + *aptr = 0; + break; + case SCOM: + i = substitute(ipc); + if(i && ipc->pfl) + if(ipc->pfl == 1) putline(&fout, linebuf, spend-linebuf); - if(aptr > abuf) - arout(); - exits(0); - case RCOM: - *aptr++ = ipc; - if(aptr >= &abuf[MAXADDS]) - quit("sed: Too many reads after line %ld\n", - (char *) lnum); - *aptr = 0; - break; - case SCOM: - i = substitute(ipc); - if(i && ipc->pfl) - if(ipc->pfl == 1) - putline(&fout, linebuf, spend-linebuf); - else - goto cpcom; - if(i && ipc->fcode) - goto wcom; - break; + else + goto cpcom; + if(i && ipc->fcode) + goto wcom; + break; - case TCOM: - if(sflag == 0) break; + case TCOM: + if(sflag) { sflag = 0; jflag = 1; - break; - - wcom: - case WCOM: - putline(ipc->fcode,linebuf, spend-linebuf); - 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->text; - for (i = *p2++; *p1; p1++){ - if (*p1 <= i) *p1 = p2[*p1]; - } - break; + } + break; + + case WCOM: +wcom: + putline(ipc->fcode,linebuf, spend - linebuf); + 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->text; + for (i = *p2++; *p1; p1++) + if (*p1 <= i) + *p1 = p2[*p1]; + break; } - } void @@ -1310,18 +1326,19 @@ putline(Biobuf *bp, Rune *buf, int n) ecmp(Rune *a, Rune *b, int count) { while(count--) - if(*a++ != *b++) return(0); - return(1); + if(*a++ != *b++) + return 0; + return 1; } void arout(void) { - Rune *p1; - Biobuf *fi; int c; char *s; char buf[128]; + Rune *p1; + Biobuf *fi; for (aptr = abuf; *aptr; aptr++) { if((*aptr)->command == ACOM) { @@ -1329,8 +1346,8 @@ arout(void) Bputrune(&fout, *p1); Bputc(&fout, '\n'); } else { - for(s = buf, p1= (*aptr)->text; *p1; p1++) - s += runetochar(s, p1); + for(s = buf, p1 = (*aptr)->text; *p1; p1++) + s += runetochar(s, p1); *s = '\0'; if((fi = Bopen(buf, OREAD)) == 0) continue; @@ -1350,20 +1367,27 @@ errexit(void) } void -quit (char *msg, char *arg) +quit(char *fmt, ...) { - fprint(2, "sed: "); - fprint(2, msg, arg); - fprint(2, "\n"); + char *p, *ep; + char msg[256]; + va_list arg; + + ep = msg + sizeof msg; + p = seprint(msg, ep, "sed: "); + va_start(arg, fmt); + p = vseprint(p, ep, fmt, arg); + va_end(arg); + p = seprint(p, ep, "\n"); + write(2, msg, p - msg); errexit(); } Rune * gline(Rune *addr) { - long c; + long c; Rune *p; - static long peekc = 0; if (f == 0 && opendata() < 0) @@ -1373,55 +1397,62 @@ gline(Rune *addr) /* Bflush(&fout);********* dumped 4/30/92 - bobf****/ do { p = addr; - for (c = (peekc ? peekc : Bgetrune(f)); c >= 0; c = Bgetrune(f)) { + for (c = (peekc? peekc: Bgetrune(f)); c >= 0; c = Bgetrune(f)) { if (c == '\n') { - if ((peekc = Bgetrune(f)) < 0) { - Bterm(f); - if (fhead == 0) - dolflag = 1; - } + if ((peekc = Bgetrune(f)) < 0 && fhead == 0) + dolflag = 1; *p = '\0'; return p; } if (c && p < lbend) *p++ = c; } + /* return partial final line, adding implicit newline */ + if(p != addr) { + *p = '\0'; + peekc = -1; + if (fhead == 0) + dolflag = 1; + return p; + } peekc = 0; - } while (opendata() > 0); /* Switch to next stream */ + Bterm(f); + } while (opendata() > 0); /* Switch to next stream */ f = 0; return 0; } - /* Data file input section - the intent is to transparently - * catenate all data input streams. - */ +/* + * Data file input section - the intent is to transparently + * catenate all data input streams. + */ void enroll(char *filename) /* Add a file to the input file cache */ { FileCache *fp; - if ((fp = (FileCache *) malloc(sizeof (FileCache))) == 0) - quit("Out of memory", 0); - if (ftail == 0) + if ((fp = (FileCache *)malloc(sizeof (FileCache))) == nil) + quit("Out of memory"); + if (ftail == nil) fhead = fp; else ftail->next = fp; ftail = fp; - fp->next = 0; - fp->name = filename; /* 0 => stdin */ + fp->next = nil; + fp->name = filename; /* 0 => stdin */ } int opendata(void) { - if (fhead == 0) + if (fhead == nil) return -1; if (fhead->name) { - if ((f = Bopen(fhead->name, OREAD)) == 0) + if ((f = Bopen(fhead->name, OREAD)) == nil) quit("Can't open %s", fhead->name); } else { - Binit(&stdin, 0, OREAD); - f = &stdin; + Binit(&bstdin, 0, OREAD); + f = &bstdin; } fhead = fhead->next; return 1; |
