13e12c5d1SDavid du Colombier /* 23e12c5d1SDavid du Colombier * sed -- stream editor 33e12c5d1SDavid du Colombier * 43e12c5d1SDavid du Colombier * 53e12c5d1SDavid du Colombier */ 63e12c5d1SDavid du Colombier #include <u.h> 73e12c5d1SDavid du Colombier #include <libc.h> 83e12c5d1SDavid du Colombier #include <bio.h> 93e12c5d1SDavid du Colombier #include <regexp.h> 103e12c5d1SDavid du Colombier 113e12c5d1SDavid du Colombier enum { 123e12c5d1SDavid du Colombier DEPTH = 20, /* max nesting depth of {} */ 133e12c5d1SDavid du Colombier MAXCMDS = 512, /* max sed commands */ 143e12c5d1SDavid du Colombier ADDSIZE = 10000, /* size of add & read buffer */ 153e12c5d1SDavid du Colombier MAXADDS = 20, /* max pending adds and reads */ 163e12c5d1SDavid du Colombier LBSIZE = 8192, /* input line size */ 173e12c5d1SDavid du Colombier LABSIZE = 50, /* max label name size */ 183e12c5d1SDavid du Colombier MAXSUB = 10, /* max number of sub reg exp */ 193e12c5d1SDavid du Colombier MAXFILES = 120, /* max output files */ 203e12c5d1SDavid du Colombier }; 213e12c5d1SDavid du Colombier /* An address is a line #, a R.E., "$", a reference to the last 223e12c5d1SDavid du Colombier * R.E., or nothing. 233e12c5d1SDavid du Colombier */ 243e12c5d1SDavid du Colombier typedef struct { 253e12c5d1SDavid du Colombier enum { 263e12c5d1SDavid du Colombier A_NONE, 273e12c5d1SDavid du Colombier A_DOL, 283e12c5d1SDavid du Colombier A_LINE, 293e12c5d1SDavid du Colombier A_RE, 303e12c5d1SDavid du Colombier A_LAST, 313e12c5d1SDavid du Colombier }type; 323e12c5d1SDavid du Colombier union { 333e12c5d1SDavid du Colombier long line; /* Line # */ 343e12c5d1SDavid du Colombier Reprog *rp; /* Compiled R.E. */ 353e12c5d1SDavid du Colombier }; 363e12c5d1SDavid du Colombier } Addr; 373e12c5d1SDavid du Colombier 383e12c5d1SDavid du Colombier typedef struct SEDCOM { 393e12c5d1SDavid du Colombier Addr ad1; /* optional start address */ 403e12c5d1SDavid du Colombier Addr ad2; /* optional end address */ 413e12c5d1SDavid du Colombier union { 423e12c5d1SDavid du Colombier Reprog *re1; /* compiled R.E. */ 433e12c5d1SDavid du Colombier Rune *text; /* added text or file name */ 443e12c5d1SDavid du Colombier struct SEDCOM *lb1; /* destination command of branch */ 453e12c5d1SDavid du Colombier }; 463e12c5d1SDavid du Colombier Rune *rhs; /* Right-hand side of substitution */ 473e12c5d1SDavid du Colombier Biobuf* fcode; /* File ID for read and write */ 483e12c5d1SDavid du Colombier char command; /* command code -see below */ 493e12c5d1SDavid du Colombier char gfl; /* 'Global' flag for substitutions */ 503e12c5d1SDavid du Colombier char pfl; /* 'print' flag for substitutions */ 513e12c5d1SDavid du Colombier char active; /* 1 => data between start and end */ 523e12c5d1SDavid du Colombier char negfl; /* negation flag */ 533e12c5d1SDavid du Colombier } SedCom; 543e12c5d1SDavid du Colombier 553e12c5d1SDavid du Colombier /* Command Codes for field SedCom.command */ 563e12c5d1SDavid du Colombier #define ACOM 01 573e12c5d1SDavid du Colombier #define BCOM 020 583e12c5d1SDavid du Colombier #define CCOM 02 593e12c5d1SDavid du Colombier #define CDCOM 025 603e12c5d1SDavid du Colombier #define CNCOM 022 613e12c5d1SDavid du Colombier #define COCOM 017 623e12c5d1SDavid du Colombier #define CPCOM 023 633e12c5d1SDavid du Colombier #define DCOM 03 643e12c5d1SDavid du Colombier #define ECOM 015 653e12c5d1SDavid du Colombier #define EQCOM 013 663e12c5d1SDavid du Colombier #define FCOM 016 673e12c5d1SDavid du Colombier #define GCOM 027 683e12c5d1SDavid du Colombier #define CGCOM 030 693e12c5d1SDavid du Colombier #define HCOM 031 703e12c5d1SDavid du Colombier #define CHCOM 032 713e12c5d1SDavid du Colombier #define ICOM 04 723e12c5d1SDavid du Colombier #define LCOM 05 733e12c5d1SDavid du Colombier #define NCOM 012 743e12c5d1SDavid du Colombier #define PCOM 010 753e12c5d1SDavid du Colombier #define QCOM 011 763e12c5d1SDavid du Colombier #define RCOM 06 773e12c5d1SDavid du Colombier #define SCOM 07 783e12c5d1SDavid du Colombier #define TCOM 021 793e12c5d1SDavid du Colombier #define WCOM 014 803e12c5d1SDavid du Colombier #define CWCOM 024 813e12c5d1SDavid du Colombier #define YCOM 026 823e12c5d1SDavid du Colombier #define XCOM 033 833e12c5d1SDavid du Colombier 843e12c5d1SDavid du Colombier 853e12c5d1SDavid du Colombier typedef struct label { /* Label symbol table */ 863e12c5d1SDavid du Colombier Rune asc[9]; /* Label name */ 873e12c5d1SDavid du Colombier SedCom *chain; 883e12c5d1SDavid du Colombier SedCom *address; /* Command associated with label */ 893e12c5d1SDavid du Colombier } Label; 903e12c5d1SDavid du Colombier 913e12c5d1SDavid du Colombier typedef struct FILE_CACHE { /* Data file control block */ 923e12c5d1SDavid du Colombier struct FILE_CACHE *next; /* Forward Link */ 933e12c5d1SDavid du Colombier char *name; /* Name of file */ 943e12c5d1SDavid du Colombier } FileCache; 953e12c5d1SDavid du Colombier 963e12c5d1SDavid du Colombier SedCom pspace[MAXCMDS]; /* Command storage */ 973e12c5d1SDavid du Colombier SedCom *pend = pspace+MAXCMDS; /* End of command storage */ 983e12c5d1SDavid du Colombier SedCom *rep = pspace; /* Current fill point */ 993e12c5d1SDavid du Colombier 1003e12c5d1SDavid du Colombier Reprog *lastre = 0; /* Last regular expression */ 1013e12c5d1SDavid du Colombier Resub subexp[MAXSUB]; /* sub-patterns of pattern match*/ 1023e12c5d1SDavid du Colombier 1033e12c5d1SDavid du Colombier Rune addspace[ADDSIZE]; /* Buffer for a, c, & i commands */ 1043e12c5d1SDavid du Colombier Rune *addend = addspace+ADDSIZE; 1053e12c5d1SDavid du Colombier 1063e12c5d1SDavid du Colombier SedCom *abuf[MAXADDS]; /* Queue of pending adds & reads */ 1073e12c5d1SDavid du Colombier SedCom **aptr = abuf; 1083e12c5d1SDavid du Colombier 1093e12c5d1SDavid du Colombier struct { /* Sed program input control block */ 1103e12c5d1SDavid du Colombier enum PTYPE /* Either on command line or in file */ 1113e12c5d1SDavid du Colombier { P_ARG, 1123e12c5d1SDavid du Colombier P_FILE 1133e12c5d1SDavid du Colombier } type; 1143e12c5d1SDavid du Colombier union PCTL { /* Pointer to data */ 1153e12c5d1SDavid du Colombier Biobuf *bp; 1163e12c5d1SDavid du Colombier char *curr; 1173e12c5d1SDavid du Colombier }; 1183e12c5d1SDavid du Colombier } prog; 1193e12c5d1SDavid du Colombier 1203e12c5d1SDavid du Colombier Rune genbuf[LBSIZE]; /* Miscellaneous buffer */ 1213e12c5d1SDavid du Colombier 1223e12c5d1SDavid du Colombier FileCache *fhead = 0; /* Head of File Cache Chain */ 1233e12c5d1SDavid du Colombier FileCache *ftail = 0; /* Tail of File Cache Chain */ 1243e12c5d1SDavid du Colombier 1253e12c5d1SDavid du Colombier Rune *loc1; /* Start of pattern match */ 1263e12c5d1SDavid du Colombier Rune *loc2; /* End of pattern match */ 1273e12c5d1SDavid du Colombier Rune seof; /* Pattern delimiter char */ 1283e12c5d1SDavid du Colombier 1293e12c5d1SDavid du Colombier Rune linebuf[LBSIZE+1]; /* Input data buffer */ 1303e12c5d1SDavid du Colombier Rune *lbend = linebuf+LBSIZE; /* End of buffer */ 1313e12c5d1SDavid du Colombier Rune *spend = linebuf; /* End of input data */ 1323e12c5d1SDavid du Colombier Rune *cp; /* Current scan point in linebuf */ 1333e12c5d1SDavid du Colombier 1343e12c5d1SDavid du Colombier Rune holdsp[LBSIZE+1]; /* Hold buffer */ 1353e12c5d1SDavid du Colombier Rune *hend = holdsp+LBSIZE; /* End of hold buffer */ 1363e12c5d1SDavid du Colombier Rune *hspend = holdsp; /* End of hold data */ 1373e12c5d1SDavid du Colombier 1383e12c5d1SDavid du Colombier int nflag; /* Command line flags */ 1393e12c5d1SDavid du Colombier int gflag; 1403e12c5d1SDavid du Colombier 1413e12c5d1SDavid du Colombier int dolflag; /* Set when at true EOF */ 1423e12c5d1SDavid du Colombier int sflag; /* Set when substitution done */ 1433e12c5d1SDavid du Colombier int jflag; /* Set when jump required */ 1443e12c5d1SDavid du Colombier int delflag; /* Delete current line when set */ 1453e12c5d1SDavid du Colombier 1463e12c5d1SDavid du Colombier long lnum = 0; /* Input line count */ 1473e12c5d1SDavid du Colombier 1483e12c5d1SDavid du Colombier char fname[MAXFILES][40]; /* File name cache */ 1493e12c5d1SDavid du Colombier Biobuf *fcode[MAXFILES]; /* File ID cache */ 1503e12c5d1SDavid du Colombier int nfiles = 0; /* Cache fill point */ 1513e12c5d1SDavid du Colombier 1523e12c5d1SDavid du Colombier Biobuf fout; /* Output stream */ 1533e12c5d1SDavid du Colombier Biobuf stdin; /* Default input */ 1543e12c5d1SDavid du Colombier Biobuf* f = 0; /* Input data */ 1553e12c5d1SDavid du Colombier 1563e12c5d1SDavid du Colombier Label ltab[LABSIZE]; /* Label name symbol table */ 1573e12c5d1SDavid du Colombier Label *labend = ltab+LABSIZE; /* End of label table */ 1583e12c5d1SDavid du Colombier Label *lab = ltab+1; /* Current Fill point */ 1593e12c5d1SDavid du Colombier 1603e12c5d1SDavid du Colombier int depth = 0; /* {} stack pointer */ 1613e12c5d1SDavid du Colombier 1623e12c5d1SDavid du Colombier Rune bad; /* Dummy err ptr reference */ 1633e12c5d1SDavid du Colombier Rune *badp = &bad; 1643e12c5d1SDavid du Colombier 1653e12c5d1SDavid du Colombier 1663e12c5d1SDavid du Colombier char CGMES[] = "Command garbled: %S"; 1673e12c5d1SDavid du Colombier char TMMES[] = "Too much text: %S"; 1683e12c5d1SDavid du Colombier char LTL[] = "Label too long: %S"; 1693e12c5d1SDavid du Colombier char AD0MES[] = "No addresses allowed: %S"; 1703e12c5d1SDavid du Colombier char AD1MES[] = "Only one address allowed: %S"; 1713e12c5d1SDavid du Colombier 1723e12c5d1SDavid du Colombier void address(Addr *); 1733e12c5d1SDavid du Colombier void arout(void); 1743e12c5d1SDavid du Colombier int cmp(char *, char *); 1753e12c5d1SDavid du Colombier int rcmp(Rune *, Rune *); 1763e12c5d1SDavid du Colombier void command(SedCom *); 1773e12c5d1SDavid du Colombier Reprog *compile(void); 1783e12c5d1SDavid du Colombier Rune *compsub(Rune *, Rune *); 1793e12c5d1SDavid du Colombier void dechain(void); 1803e12c5d1SDavid du Colombier void dosub(Rune *); 1813e12c5d1SDavid du Colombier int ecmp(Rune *, Rune *, int); 1823e12c5d1SDavid du Colombier void enroll(char *); 1833e12c5d1SDavid du Colombier void errexit(void); 1843e12c5d1SDavid du Colombier int executable(SedCom *); 1853e12c5d1SDavid du Colombier void execute(void); 1863e12c5d1SDavid du Colombier void fcomp(void); 1873e12c5d1SDavid du Colombier long getrune(void); 1883e12c5d1SDavid du Colombier Rune *gline(Rune *); 1893e12c5d1SDavid du Colombier int match(Reprog *, Rune *); 1903e12c5d1SDavid du Colombier void newfile(enum PTYPE, char *); 1913e12c5d1SDavid du Colombier int opendata(void); 1923e12c5d1SDavid du Colombier Biobuf *open_file(char *); 1933e12c5d1SDavid du Colombier Rune *place(Rune *, Rune *, Rune *); 1943e12c5d1SDavid du Colombier void quit(char *, char *); 1953e12c5d1SDavid du Colombier int rline(Rune *, Rune *); 1963e12c5d1SDavid du Colombier Label *search(Label *); 1973e12c5d1SDavid du Colombier int substitute(SedCom *); 1983e12c5d1SDavid du Colombier char *text(char *); 1993e12c5d1SDavid du Colombier Rune *stext(Rune *, Rune *); 2003e12c5d1SDavid du Colombier int ycomp(SedCom *); 2013e12c5d1SDavid du Colombier char * trans(int c); 2023e12c5d1SDavid du Colombier void putline(Biobuf *bp, Rune *buf, int n); 2033e12c5d1SDavid du Colombier 2043e12c5d1SDavid du Colombier void 2053e12c5d1SDavid du Colombier main(int argc, char **argv) 2063e12c5d1SDavid du Colombier { 2073e12c5d1SDavid du Colombier int compfl; 2083e12c5d1SDavid du Colombier 2093e12c5d1SDavid du Colombier lnum = 0; 2103e12c5d1SDavid du Colombier Binit(&fout, 1, OWRITE); 2113e12c5d1SDavid du Colombier fcode[nfiles++] = &fout; 2123e12c5d1SDavid du Colombier compfl = 0; 2133e12c5d1SDavid du Colombier 2143e12c5d1SDavid du Colombier if(argc == 1) 2153e12c5d1SDavid du Colombier exits(0); 2163e12c5d1SDavid du Colombier ARGBEGIN{ 2173e12c5d1SDavid du Colombier case 'n': 2183e12c5d1SDavid du Colombier nflag++; 2193e12c5d1SDavid du Colombier continue; 2203e12c5d1SDavid du Colombier case 'f': 2213e12c5d1SDavid du Colombier if(argc <= 1) 2223e12c5d1SDavid du Colombier quit("no pattern-file", 0); 2233e12c5d1SDavid du Colombier newfile(P_FILE, ARGF()); 2243e12c5d1SDavid du Colombier fcomp(); 2253e12c5d1SDavid du Colombier compfl = 1; 2263e12c5d1SDavid du Colombier continue; 2273e12c5d1SDavid du Colombier case 'e': 2283e12c5d1SDavid du Colombier if (argc <= 1) 2293e12c5d1SDavid du Colombier quit("missing pattern", 0); 2303e12c5d1SDavid du Colombier newfile(P_ARG, ARGF()); 2313e12c5d1SDavid du Colombier fcomp(); 2323e12c5d1SDavid du Colombier compfl = 1; 2333e12c5d1SDavid du Colombier continue; 2343e12c5d1SDavid du Colombier case 'g': 2353e12c5d1SDavid du Colombier gflag++; 2363e12c5d1SDavid du Colombier continue; 2373e12c5d1SDavid du Colombier default: 2383e12c5d1SDavid du Colombier fprint(2, "sed: Unknown flag: %c\n", ARGC()); 2393e12c5d1SDavid du Colombier continue; 2403e12c5d1SDavid du Colombier } ARGEND 2413e12c5d1SDavid du Colombier 2423e12c5d1SDavid du Colombier if(compfl == 0) { 2433e12c5d1SDavid du Colombier if (--argc < 0) 2443e12c5d1SDavid du Colombier quit("missing pattern", 0); 2453e12c5d1SDavid du Colombier newfile(P_ARG, *argv++); 2463e12c5d1SDavid du Colombier fcomp(); 2473e12c5d1SDavid du Colombier } 2483e12c5d1SDavid du Colombier 2493e12c5d1SDavid du Colombier if(depth) 2503e12c5d1SDavid du Colombier quit("Too many {'s", 0); 2513e12c5d1SDavid du Colombier 2523e12c5d1SDavid du Colombier ltab[0].address = rep; 2533e12c5d1SDavid du Colombier 2543e12c5d1SDavid du Colombier dechain(); 2553e12c5d1SDavid du Colombier 2563e12c5d1SDavid du Colombier if(argc <= 0) 2573e12c5d1SDavid du Colombier enroll(0); /* Add stdin to cache */ 2583e12c5d1SDavid du Colombier else while(--argc >= 0) { 2593e12c5d1SDavid du Colombier enroll(*argv++); 2603e12c5d1SDavid du Colombier } 2613e12c5d1SDavid du Colombier execute(); 2623e12c5d1SDavid du Colombier exits(0); 2633e12c5d1SDavid du Colombier } 2643e12c5d1SDavid du Colombier void 2653e12c5d1SDavid du Colombier fcomp(void) 2663e12c5d1SDavid du Colombier { 2673e12c5d1SDavid du Colombier Rune *tp; 2683e12c5d1SDavid du Colombier SedCom *pt, *pt1; 2693e12c5d1SDavid du Colombier int i; 2703e12c5d1SDavid du Colombier Label *lpt; 2713e12c5d1SDavid du Colombier 2723e12c5d1SDavid du Colombier static Rune *p = addspace; 2733e12c5d1SDavid du Colombier static SedCom **cmpend[DEPTH]; /* stack of {} operations */ 2743e12c5d1SDavid du Colombier 2753e12c5d1SDavid du Colombier while (rline(linebuf, lbend) >= 0) { 2763e12c5d1SDavid du Colombier cp = linebuf; 2773e12c5d1SDavid du Colombier comploop: 278*219b2ee8SDavid du Colombier while(*cp == ' ' || *cp == '\t') 279*219b2ee8SDavid du Colombier cp++; 280*219b2ee8SDavid du Colombier if(*cp == '\0' || *cp == '#') 281*219b2ee8SDavid du Colombier continue; 2823e12c5d1SDavid du Colombier if(*cp == ';') { 2833e12c5d1SDavid du Colombier cp++; 2843e12c5d1SDavid du Colombier goto comploop; 2853e12c5d1SDavid du Colombier } 2863e12c5d1SDavid du Colombier 2873e12c5d1SDavid du Colombier address(&rep->ad1); 2883e12c5d1SDavid du Colombier if (rep->ad1.type != A_NONE) { 2893e12c5d1SDavid du Colombier if (rep->ad1.type == A_LAST) { 2903e12c5d1SDavid du Colombier if (!lastre) 2913e12c5d1SDavid du Colombier quit("First RE may not be null", 0); 2923e12c5d1SDavid du Colombier rep->ad1.type = A_RE; 2933e12c5d1SDavid du Colombier rep->ad1.rp = lastre; 2943e12c5d1SDavid du Colombier } 2953e12c5d1SDavid du Colombier if(*cp == ',' || *cp == ';') { 2963e12c5d1SDavid du Colombier cp++; 2973e12c5d1SDavid du Colombier address(&rep->ad2); 2983e12c5d1SDavid du Colombier if (rep->ad2.type == A_LAST) { 2993e12c5d1SDavid du Colombier rep->ad1.type = A_RE; 3003e12c5d1SDavid du Colombier rep->ad2.rp = lastre; 3013e12c5d1SDavid du Colombier } 3023e12c5d1SDavid du Colombier } else 3033e12c5d1SDavid du Colombier rep->ad2.type = A_NONE; 3043e12c5d1SDavid du Colombier } 305*219b2ee8SDavid du Colombier while(*cp == ' ' || *cp == '\t') 306*219b2ee8SDavid du Colombier cp++; 3073e12c5d1SDavid du Colombier 3083e12c5d1SDavid du Colombier swit: 3093e12c5d1SDavid du Colombier switch(*cp++) { 3103e12c5d1SDavid du Colombier 3113e12c5d1SDavid du Colombier default: 3123e12c5d1SDavid du Colombier quit("Unrecognized command: %S", (char *)linebuf); 3133e12c5d1SDavid du Colombier 3143e12c5d1SDavid du Colombier case '!': 3153e12c5d1SDavid du Colombier rep->negfl = 1; 3163e12c5d1SDavid du Colombier goto swit; 3173e12c5d1SDavid du Colombier 3183e12c5d1SDavid du Colombier case '{': 3193e12c5d1SDavid du Colombier rep->command = BCOM; 3203e12c5d1SDavid du Colombier rep->negfl = !(rep->negfl); 3213e12c5d1SDavid du Colombier cmpend[depth++] = &rep->lb1; 3223e12c5d1SDavid du Colombier if(++rep >= pend) 3233e12c5d1SDavid du Colombier quit("Too many commands: %S", (char *) linebuf); 3243e12c5d1SDavid du Colombier if(*cp == '\0') continue; 3253e12c5d1SDavid du Colombier goto comploop; 3263e12c5d1SDavid du Colombier 3273e12c5d1SDavid du Colombier case '}': 3283e12c5d1SDavid du Colombier if(rep->ad1.type != A_NONE) 3293e12c5d1SDavid du Colombier quit(AD0MES, (char *) linebuf); 3303e12c5d1SDavid du Colombier if(--depth < 0) 3313e12c5d1SDavid du Colombier quit("Too many }'s", 0); 3323e12c5d1SDavid du Colombier *cmpend[depth] = rep; 3333e12c5d1SDavid du Colombier if(*cp == 0) continue; 3343e12c5d1SDavid du Colombier goto comploop; 3353e12c5d1SDavid du Colombier 3363e12c5d1SDavid du Colombier case '=': 3373e12c5d1SDavid du Colombier rep->command = EQCOM; 3383e12c5d1SDavid du Colombier if(rep->ad2.type != A_NONE) 3393e12c5d1SDavid du Colombier quit(AD1MES, (char *) linebuf); 3403e12c5d1SDavid du Colombier break; 3413e12c5d1SDavid du Colombier 3423e12c5d1SDavid du Colombier case ':': 3433e12c5d1SDavid du Colombier if(rep->ad1.type != A_NONE) 3443e12c5d1SDavid du Colombier quit(AD0MES, (char *) linebuf); 3453e12c5d1SDavid du Colombier 346*219b2ee8SDavid du Colombier while(*cp == ' ') 347*219b2ee8SDavid du Colombier cp++; 3483e12c5d1SDavid du Colombier tp = lab->asc; 349*219b2ee8SDavid du Colombier while (*cp && *cp != ';' && *cp != ' ' && *cp != '\t' && *cp != '#') { 350*219b2ee8SDavid du Colombier *tp++ = *cp++; 3513e12c5d1SDavid du Colombier if(tp >= &(lab->asc[8])) 3523e12c5d1SDavid du Colombier quit(LTL, (char *) linebuf); 353*219b2ee8SDavid du Colombier } 354*219b2ee8SDavid du Colombier *tp = '\0'; 3553e12c5d1SDavid du Colombier 3563e12c5d1SDavid du Colombier if(lpt = search(lab)) { 3573e12c5d1SDavid du Colombier if(lpt->address) 3583e12c5d1SDavid du Colombier quit("Duplicate labels: %S", (char *) linebuf); 3593e12c5d1SDavid du Colombier } else { 3603e12c5d1SDavid du Colombier lab->chain = 0; 3613e12c5d1SDavid du Colombier lpt = lab; 3623e12c5d1SDavid du Colombier if(++lab >= labend) 3633e12c5d1SDavid du Colombier quit("Too many labels: %S", (char *) linebuf); 3643e12c5d1SDavid du Colombier } 3653e12c5d1SDavid du Colombier lpt->address = rep; 366*219b2ee8SDavid du Colombier if (*cp == '#') 3673e12c5d1SDavid du Colombier continue; 368*219b2ee8SDavid du Colombier rep--; /* reuse this slot */ 369*219b2ee8SDavid du Colombier break; 3703e12c5d1SDavid du Colombier 3713e12c5d1SDavid du Colombier case 'a': 3723e12c5d1SDavid du Colombier rep->command = ACOM; 3733e12c5d1SDavid du Colombier if(rep->ad2.type != A_NONE) 3743e12c5d1SDavid du Colombier quit(AD1MES, (char *) linebuf); 3753e12c5d1SDavid du Colombier if(*cp == '\\') cp++; 3763e12c5d1SDavid du Colombier if(*cp++ != '\n') 3773e12c5d1SDavid du Colombier quit(CGMES, (char *) linebuf); 3783e12c5d1SDavid du Colombier rep->text = p; 3793e12c5d1SDavid du Colombier p = stext(p, addend); 3803e12c5d1SDavid du Colombier break; 3813e12c5d1SDavid du Colombier case 'c': 3823e12c5d1SDavid du Colombier rep->command = CCOM; 3833e12c5d1SDavid du Colombier if(*cp == '\\') cp++; 3843e12c5d1SDavid du Colombier if(*cp++ != '\n') 3853e12c5d1SDavid du Colombier quit(CGMES, (char *) linebuf); 3863e12c5d1SDavid du Colombier rep->text = p; 3873e12c5d1SDavid du Colombier p = stext(p, addend); 3883e12c5d1SDavid du Colombier break; 3893e12c5d1SDavid du Colombier case 'i': 3903e12c5d1SDavid du Colombier rep->command = ICOM; 3913e12c5d1SDavid du Colombier if(rep->ad2.type != A_NONE) 3923e12c5d1SDavid du Colombier quit(AD1MES, (char *) linebuf); 3933e12c5d1SDavid du Colombier if(*cp == '\\') cp++; 3943e12c5d1SDavid du Colombier if(*cp++ != '\n') 3953e12c5d1SDavid du Colombier quit(CGMES, (char *) linebuf); 3963e12c5d1SDavid du Colombier rep->text = p; 3973e12c5d1SDavid du Colombier p = stext(p, addend); 3983e12c5d1SDavid du Colombier break; 3993e12c5d1SDavid du Colombier 4003e12c5d1SDavid du Colombier case 'g': 4013e12c5d1SDavid du Colombier rep->command = GCOM; 4023e12c5d1SDavid du Colombier break; 4033e12c5d1SDavid du Colombier 4043e12c5d1SDavid du Colombier case 'G': 4053e12c5d1SDavid du Colombier rep->command = CGCOM; 4063e12c5d1SDavid du Colombier break; 4073e12c5d1SDavid du Colombier 4083e12c5d1SDavid du Colombier case 'h': 4093e12c5d1SDavid du Colombier rep->command = HCOM; 4103e12c5d1SDavid du Colombier break; 4113e12c5d1SDavid du Colombier 4123e12c5d1SDavid du Colombier case 'H': 4133e12c5d1SDavid du Colombier rep->command = CHCOM; 4143e12c5d1SDavid du Colombier break; 4153e12c5d1SDavid du Colombier 4163e12c5d1SDavid du Colombier case 't': 4173e12c5d1SDavid du Colombier rep->command = TCOM; 4183e12c5d1SDavid du Colombier goto jtcommon; 4193e12c5d1SDavid du Colombier 4203e12c5d1SDavid du Colombier case 'b': 4213e12c5d1SDavid du Colombier rep->command = BCOM; 4223e12c5d1SDavid du Colombier jtcommon: 4233e12c5d1SDavid du Colombier while(*cp == ' ')cp++; 4243e12c5d1SDavid du Colombier if(*cp == '\0') { 4253e12c5d1SDavid du Colombier if(pt = ltab[0].chain) { 4263e12c5d1SDavid du Colombier while(pt1 = pt->lb1) 4273e12c5d1SDavid du Colombier pt = pt1; 4283e12c5d1SDavid du Colombier pt->lb1 = rep; 4293e12c5d1SDavid du Colombier } else 4303e12c5d1SDavid du Colombier ltab[0].chain = rep; 4313e12c5d1SDavid du Colombier break; 4323e12c5d1SDavid du Colombier } 4333e12c5d1SDavid du Colombier tp = lab->asc; 4343e12c5d1SDavid du Colombier while((*tp++ = *cp++)) 4353e12c5d1SDavid du Colombier if(tp >= &(lab->asc[8])) 4363e12c5d1SDavid du Colombier quit(LTL, (char *) linebuf); 4373e12c5d1SDavid du Colombier cp--; 4383e12c5d1SDavid du Colombier tp[-1] = '\0'; 4393e12c5d1SDavid du Colombier 4403e12c5d1SDavid du Colombier if(lpt = search(lab)) { 4413e12c5d1SDavid du Colombier if(lpt->address) { 4423e12c5d1SDavid du Colombier rep->lb1 = lpt->address; 4433e12c5d1SDavid du Colombier } else { 4443e12c5d1SDavid du Colombier pt = lpt->chain; 4453e12c5d1SDavid du Colombier while(pt1 = pt->lb1) 4463e12c5d1SDavid du Colombier pt = pt1; 4473e12c5d1SDavid du Colombier pt->lb1 = rep; 4483e12c5d1SDavid du Colombier } 4493e12c5d1SDavid du Colombier } else { 4503e12c5d1SDavid du Colombier lab->chain = rep; 4513e12c5d1SDavid du Colombier lab->address = 0; 4523e12c5d1SDavid du Colombier if(++lab >= labend) 4533e12c5d1SDavid du Colombier quit("Too many labels: %S", 4543e12c5d1SDavid du Colombier (char *) linebuf); 4553e12c5d1SDavid du Colombier } 4563e12c5d1SDavid du Colombier break; 4573e12c5d1SDavid du Colombier 4583e12c5d1SDavid du Colombier case 'n': 4593e12c5d1SDavid du Colombier rep->command = NCOM; 4603e12c5d1SDavid du Colombier break; 4613e12c5d1SDavid du Colombier 4623e12c5d1SDavid du Colombier case 'N': 4633e12c5d1SDavid du Colombier rep->command = CNCOM; 4643e12c5d1SDavid du Colombier break; 4653e12c5d1SDavid du Colombier 4663e12c5d1SDavid du Colombier case 'p': 4673e12c5d1SDavid du Colombier rep->command = PCOM; 4683e12c5d1SDavid du Colombier break; 4693e12c5d1SDavid du Colombier 4703e12c5d1SDavid du Colombier case 'P': 4713e12c5d1SDavid du Colombier rep->command = CPCOM; 4723e12c5d1SDavid du Colombier break; 4733e12c5d1SDavid du Colombier 4743e12c5d1SDavid du Colombier case 'r': 4753e12c5d1SDavid du Colombier rep->command = RCOM; 4763e12c5d1SDavid du Colombier if(rep->ad2.type != A_NONE) 4773e12c5d1SDavid du Colombier quit(AD1MES, (char *) linebuf); 4783e12c5d1SDavid du Colombier if(*cp++ != ' ') 4793e12c5d1SDavid du Colombier quit(CGMES, (char *) linebuf); 4803e12c5d1SDavid du Colombier rep->text = p; 4813e12c5d1SDavid du Colombier p = stext(p, addend); 4823e12c5d1SDavid du Colombier break; 4833e12c5d1SDavid du Colombier 4843e12c5d1SDavid du Colombier case 'd': 4853e12c5d1SDavid du Colombier rep->command = DCOM; 4863e12c5d1SDavid du Colombier break; 4873e12c5d1SDavid du Colombier 4883e12c5d1SDavid du Colombier case 'D': 4893e12c5d1SDavid du Colombier rep->command = CDCOM; 4903e12c5d1SDavid du Colombier rep->lb1 = pspace; 4913e12c5d1SDavid du Colombier break; 4923e12c5d1SDavid du Colombier 4933e12c5d1SDavid du Colombier case 'q': 4943e12c5d1SDavid du Colombier rep->command = QCOM; 4953e12c5d1SDavid du Colombier if(rep->ad2.type != A_NONE) 4963e12c5d1SDavid du Colombier quit(AD1MES, (char *) linebuf); 4973e12c5d1SDavid du Colombier break; 4983e12c5d1SDavid du Colombier 4993e12c5d1SDavid du Colombier case 'l': 5003e12c5d1SDavid du Colombier rep->command = LCOM; 5013e12c5d1SDavid du Colombier break; 5023e12c5d1SDavid du Colombier 5033e12c5d1SDavid du Colombier case 's': 5043e12c5d1SDavid du Colombier rep->command = SCOM; 5053e12c5d1SDavid du Colombier seof = *cp++; 5063e12c5d1SDavid du Colombier if ((rep->re1 = compile()) == 0) { 5073e12c5d1SDavid du Colombier if(!lastre) 5083e12c5d1SDavid du Colombier quit("First RE may not be null.", 0); 5093e12c5d1SDavid du Colombier rep->re1 = lastre; 5103e12c5d1SDavid du Colombier } 5113e12c5d1SDavid du Colombier rep->rhs = p; 5123e12c5d1SDavid du Colombier if((p = compsub(p, addend)) == 0) 5133e12c5d1SDavid du Colombier quit(CGMES, (char *) linebuf); 5143e12c5d1SDavid du Colombier if(*cp == 'g') { 5153e12c5d1SDavid du Colombier cp++; 5163e12c5d1SDavid du Colombier rep->gfl++; 5173e12c5d1SDavid du Colombier } else if(gflag) 5183e12c5d1SDavid du Colombier rep->gfl++; 5193e12c5d1SDavid du Colombier 5203e12c5d1SDavid du Colombier if(*cp == 'p') { 5213e12c5d1SDavid du Colombier cp++; 5223e12c5d1SDavid du Colombier rep->pfl = 1; 5233e12c5d1SDavid du Colombier } 5243e12c5d1SDavid du Colombier 5253e12c5d1SDavid du Colombier if(*cp == 'P') { 5263e12c5d1SDavid du Colombier cp++; 5273e12c5d1SDavid du Colombier rep->pfl = 2; 5283e12c5d1SDavid du Colombier } 5293e12c5d1SDavid du Colombier 5303e12c5d1SDavid du Colombier if(*cp == 'w') { 5313e12c5d1SDavid du Colombier cp++; 5323e12c5d1SDavid du Colombier if(*cp++ != ' ') 5333e12c5d1SDavid du Colombier quit(CGMES, (char *) linebuf); 5343e12c5d1SDavid du Colombier text(fname[nfiles]); 5353e12c5d1SDavid du Colombier for(i = nfiles - 1; i >= 0; i--) 5363e12c5d1SDavid du Colombier if(cmp(fname[nfiles],fname[i]) == 0) { 5373e12c5d1SDavid du Colombier rep->fcode = fcode[i]; 5383e12c5d1SDavid du Colombier goto done; 5393e12c5d1SDavid du Colombier } 5403e12c5d1SDavid du Colombier if(nfiles >= MAXFILES) 5413e12c5d1SDavid du Colombier quit("Too many files in w commands 1", 0); 5423e12c5d1SDavid du Colombier rep->fcode = open_file(fname[nfiles]); 5433e12c5d1SDavid du Colombier } 5443e12c5d1SDavid du Colombier break; 5453e12c5d1SDavid du Colombier 5463e12c5d1SDavid du Colombier case 'w': 5473e12c5d1SDavid du Colombier rep->command = WCOM; 5483e12c5d1SDavid du Colombier if(*cp++ != ' ') 5493e12c5d1SDavid du Colombier quit(CGMES, (char *) linebuf); 5503e12c5d1SDavid du Colombier text(fname[nfiles]); 5513e12c5d1SDavid du Colombier for(i = nfiles - 1; i >= 0; i--) 5523e12c5d1SDavid du Colombier if(cmp(fname[nfiles], fname[i]) == 0) { 5533e12c5d1SDavid du Colombier rep->fcode = fcode[i]; 5543e12c5d1SDavid du Colombier goto done; 5553e12c5d1SDavid du Colombier } 5563e12c5d1SDavid du Colombier if(nfiles >= MAXFILES){ 5573e12c5d1SDavid du Colombier fprint(2, "sed: Too many files in w commands 2 \n"); 5583e12c5d1SDavid du Colombier fprint(2, "nfiles = %d; MAXF = %d\n", nfiles, MAXFILES); 5593e12c5d1SDavid du Colombier errexit(); 5603e12c5d1SDavid du Colombier } 5613e12c5d1SDavid du Colombier rep->fcode = open_file(fname[nfiles]); 5623e12c5d1SDavid du Colombier break; 5633e12c5d1SDavid du Colombier 5643e12c5d1SDavid du Colombier case 'x': 5653e12c5d1SDavid du Colombier rep->command = XCOM; 5663e12c5d1SDavid du Colombier break; 5673e12c5d1SDavid du Colombier 5683e12c5d1SDavid du Colombier case 'y': 5693e12c5d1SDavid du Colombier rep->command = YCOM; 5703e12c5d1SDavid du Colombier seof = *cp++; 5713e12c5d1SDavid du Colombier if (ycomp(rep) == 0) 5723e12c5d1SDavid du Colombier quit(CGMES, (char *) linebuf); 5733e12c5d1SDavid du Colombier break; 5743e12c5d1SDavid du Colombier 5753e12c5d1SDavid du Colombier } 5763e12c5d1SDavid du Colombier done: 5773e12c5d1SDavid du Colombier if(++rep >= pend) 5783e12c5d1SDavid du Colombier quit("Too many commands, last: %S", (char *) linebuf); 5793e12c5d1SDavid du Colombier 5803e12c5d1SDavid du Colombier if(*cp++ != '\0') { 5813e12c5d1SDavid du Colombier if(cp[-1] == ';') 5823e12c5d1SDavid du Colombier goto comploop; 5833e12c5d1SDavid du Colombier quit(CGMES, (char *) linebuf); 5843e12c5d1SDavid du Colombier } 5853e12c5d1SDavid du Colombier 5863e12c5d1SDavid du Colombier } 5873e12c5d1SDavid du Colombier } 5883e12c5d1SDavid du Colombier 5893e12c5d1SDavid du Colombier Biobuf * 5903e12c5d1SDavid du Colombier open_file(char *name) 5913e12c5d1SDavid du Colombier { 5923e12c5d1SDavid du Colombier Biobuf *bp; 5933e12c5d1SDavid du Colombier int fd; 5943e12c5d1SDavid du Colombier 5953e12c5d1SDavid du Colombier if ((bp = malloc(sizeof(Biobuf))) == 0) 5963e12c5d1SDavid du Colombier quit("Out of memory", 0); 5973e12c5d1SDavid du Colombier if ((fd = open(name, OWRITE)) < 0 && 5983e12c5d1SDavid du Colombier (fd = create(name, OWRITE, 0666)) < 0) 5993e12c5d1SDavid du Colombier quit("Cannot create %s", name); 6003e12c5d1SDavid du Colombier Binit(bp, fd, OWRITE); 6013e12c5d1SDavid du Colombier Bseek(bp, 0, 2); 6023e12c5d1SDavid du Colombier fcode[nfiles++] = bp; 6033e12c5d1SDavid du Colombier return bp; 6043e12c5d1SDavid du Colombier } 6053e12c5d1SDavid du Colombier 6063e12c5d1SDavid du Colombier Rune * 6073e12c5d1SDavid du Colombier compsub(Rune *rhs, Rune *end) 6083e12c5d1SDavid du Colombier { 6093e12c5d1SDavid du Colombier Rune r; 6103e12c5d1SDavid du Colombier 6113e12c5d1SDavid du Colombier while ((r = *cp++) != '\0') { 6123e12c5d1SDavid du Colombier if(r == '\\') { 6133e12c5d1SDavid du Colombier if (rhs < end) 6143e12c5d1SDavid du Colombier *rhs++ = 0xFFFF; 6153e12c5d1SDavid du Colombier else 6163e12c5d1SDavid du Colombier return 0; 6173e12c5d1SDavid du Colombier r = *cp++; 6183e12c5d1SDavid du Colombier if(r == 'n') 6193e12c5d1SDavid du Colombier r = '\n'; 6203e12c5d1SDavid du Colombier } else { 6213e12c5d1SDavid du Colombier if(r == seof) { 6223e12c5d1SDavid du Colombier if (rhs < end) 6233e12c5d1SDavid du Colombier *rhs++ = '\0'; 6243e12c5d1SDavid du Colombier else 6253e12c5d1SDavid du Colombier return 0; 6263e12c5d1SDavid du Colombier return rhs; 6273e12c5d1SDavid du Colombier } 6283e12c5d1SDavid du Colombier } 6293e12c5d1SDavid du Colombier if (rhs < end) 6303e12c5d1SDavid du Colombier *rhs++ = r; 6313e12c5d1SDavid du Colombier else 6323e12c5d1SDavid du Colombier return 0; 6333e12c5d1SDavid du Colombier 6343e12c5d1SDavid du Colombier } 6353e12c5d1SDavid du Colombier return 0; 6363e12c5d1SDavid du Colombier } 6373e12c5d1SDavid du Colombier 6383e12c5d1SDavid du Colombier Reprog * 6393e12c5d1SDavid du Colombier compile(void) 6403e12c5d1SDavid du Colombier { 6413e12c5d1SDavid du Colombier Rune c; 6423e12c5d1SDavid du Colombier char *ep; 6433e12c5d1SDavid du Colombier char expbuf[512]; 6443e12c5d1SDavid du Colombier 6453e12c5d1SDavid du Colombier if((c = *cp++) == seof) /* '//' */ 6463e12c5d1SDavid du Colombier return 0; 6473e12c5d1SDavid du Colombier ep = expbuf; 6483e12c5d1SDavid du Colombier do { 6493e12c5d1SDavid du Colombier if (c == 0 || c == '\n') 6503e12c5d1SDavid du Colombier quit(TMMES, (char *) linebuf); 6513e12c5d1SDavid du Colombier if (c == '\\') { 6523e12c5d1SDavid du Colombier if (ep >= expbuf+sizeof(expbuf)) 6533e12c5d1SDavid du Colombier quit(TMMES, (char *) linebuf); 6543e12c5d1SDavid du Colombier ep += runetochar(ep, &c); 6553e12c5d1SDavid du Colombier if ((c = *cp++) == 'n') 6563e12c5d1SDavid du Colombier c = '\n'; 6573e12c5d1SDavid du Colombier } 6583e12c5d1SDavid du Colombier if (ep >= expbuf+sizeof(expbuf)) 6593e12c5d1SDavid du Colombier quit(TMMES, (char *) linebuf); 6603e12c5d1SDavid du Colombier ep += runetochar(ep, &c); 6613e12c5d1SDavid du Colombier } while ((c = *cp++) != seof); 6623e12c5d1SDavid du Colombier *ep = 0; 6633e12c5d1SDavid du Colombier return lastre = regcomp(expbuf); 6643e12c5d1SDavid du Colombier } 6653e12c5d1SDavid du Colombier 6663e12c5d1SDavid du Colombier void 6673e12c5d1SDavid du Colombier regerror(char *s) 6683e12c5d1SDavid du Colombier { 6693e12c5d1SDavid du Colombier USED(s); 6703e12c5d1SDavid du Colombier quit(CGMES, (char *) linebuf); 6713e12c5d1SDavid du Colombier } 6723e12c5d1SDavid du Colombier 6733e12c5d1SDavid du Colombier void 6743e12c5d1SDavid du Colombier newfile(enum PTYPE type, char *name) 6753e12c5d1SDavid du Colombier { 6763e12c5d1SDavid du Colombier if (type == P_ARG) 6773e12c5d1SDavid du Colombier prog.curr = name; 6783e12c5d1SDavid du Colombier else if ((prog.bp = Bopen(name, OREAD)) == 0) 6793e12c5d1SDavid du Colombier quit("Cannot open pattern-file: %s\n", name); 6803e12c5d1SDavid du Colombier prog.type = type; 6813e12c5d1SDavid du Colombier } 6823e12c5d1SDavid du Colombier 6833e12c5d1SDavid du Colombier int 6843e12c5d1SDavid du Colombier rline(Rune *buf, Rune *end) 6853e12c5d1SDavid du Colombier { 6863e12c5d1SDavid du Colombier long c; 6873e12c5d1SDavid du Colombier Rune r; 6883e12c5d1SDavid du Colombier 6893e12c5d1SDavid du Colombier while ((c = getrune()) >= 0) { 6903e12c5d1SDavid du Colombier r = c; 6913e12c5d1SDavid du Colombier if (r == '\\') { 6923e12c5d1SDavid du Colombier if (buf <= end) 6933e12c5d1SDavid du Colombier *buf++ = r; 6943e12c5d1SDavid du Colombier if ((c = getrune()) < 0) 6953e12c5d1SDavid du Colombier break; 6963e12c5d1SDavid du Colombier r = c; 6973e12c5d1SDavid du Colombier } else if (r == '\n') { 6983e12c5d1SDavid du Colombier *buf = '\0'; 6993e12c5d1SDavid du Colombier return(1); 7003e12c5d1SDavid du Colombier } 7013e12c5d1SDavid du Colombier if (buf <= end) 7023e12c5d1SDavid du Colombier *buf++ = r; 7033e12c5d1SDavid du Colombier } 7043e12c5d1SDavid du Colombier *buf = '\0'; 7053e12c5d1SDavid du Colombier return(-1); 7063e12c5d1SDavid du Colombier } 7073e12c5d1SDavid du Colombier 7083e12c5d1SDavid du Colombier long 7093e12c5d1SDavid du Colombier getrune(void) 7103e12c5d1SDavid du Colombier { 7113e12c5d1SDavid du Colombier char *p; 7123e12c5d1SDavid du Colombier long c; 7133e12c5d1SDavid du Colombier Rune r; 7143e12c5d1SDavid du Colombier 7153e12c5d1SDavid du Colombier if (prog.type == P_ARG) { 7163e12c5d1SDavid du Colombier if ((p = prog.curr) != 0) { 7173e12c5d1SDavid du Colombier if (*p) { 7183e12c5d1SDavid du Colombier prog.curr += chartorune(&r, p); 7193e12c5d1SDavid du Colombier c = r; 7203e12c5d1SDavid du Colombier } else { 7213e12c5d1SDavid du Colombier c = '\n'; /* fake an end-of-line */ 7223e12c5d1SDavid du Colombier prog.curr = 0; 7233e12c5d1SDavid du Colombier } 7243e12c5d1SDavid du Colombier } else 7253e12c5d1SDavid du Colombier c = -1; 7263e12c5d1SDavid du Colombier } else if ((c = Bgetrune(prog.bp)) < 0) 727*219b2ee8SDavid du Colombier Bterm(prog.bp); 7283e12c5d1SDavid du Colombier return c; 7293e12c5d1SDavid du Colombier } 7303e12c5d1SDavid du Colombier 7313e12c5d1SDavid du Colombier void 7323e12c5d1SDavid du Colombier address(Addr *ap) 7333e12c5d1SDavid du Colombier { 7343e12c5d1SDavid du Colombier int c; 7353e12c5d1SDavid du Colombier long lno; 7363e12c5d1SDavid du Colombier 7373e12c5d1SDavid du Colombier if((c = *cp++) == '$') 7383e12c5d1SDavid du Colombier ap->type = A_DOL; 7393e12c5d1SDavid du Colombier else if(c == '/') { 7403e12c5d1SDavid du Colombier seof = c; 7413e12c5d1SDavid du Colombier if (ap->rp = compile()) 7423e12c5d1SDavid du Colombier ap->type = A_RE; 7433e12c5d1SDavid du Colombier else 7443e12c5d1SDavid du Colombier ap->type = A_LAST; 7453e12c5d1SDavid du Colombier } 7463e12c5d1SDavid du Colombier else if (c >= '0' && c <= '9') { 7473e12c5d1SDavid du Colombier lno = c-'0'; 7483e12c5d1SDavid du Colombier while ((c = *cp) >= '0' && c <= '9') 7493e12c5d1SDavid du Colombier lno = lno*10 + *cp++-'0'; 7503e12c5d1SDavid du Colombier if(!lno) 7513e12c5d1SDavid du Colombier quit("line number 0 is illegal",0); 7523e12c5d1SDavid du Colombier ap->type = A_LINE; 7533e12c5d1SDavid du Colombier ap->line = lno; 7543e12c5d1SDavid du Colombier } 7553e12c5d1SDavid du Colombier else { 7563e12c5d1SDavid du Colombier cp--; 7573e12c5d1SDavid du Colombier ap->type = A_NONE; 7583e12c5d1SDavid du Colombier } 7593e12c5d1SDavid du Colombier } 7603e12c5d1SDavid du Colombier 7613e12c5d1SDavid du Colombier cmp(char *a, char *b) /* compare characters */ 7623e12c5d1SDavid du Colombier { 7633e12c5d1SDavid du Colombier while(*a == *b++) 7643e12c5d1SDavid du Colombier if (*a == '\0') 7653e12c5d1SDavid du Colombier return(0); 7663e12c5d1SDavid du Colombier else a++; 7673e12c5d1SDavid du Colombier return(1); 7683e12c5d1SDavid du Colombier } 7693e12c5d1SDavid du Colombier rcmp(Rune *a, Rune *b) /* compare runes */ 7703e12c5d1SDavid du Colombier { 7713e12c5d1SDavid du Colombier while(*a == *b++) 7723e12c5d1SDavid du Colombier if (*a == '\0') 7733e12c5d1SDavid du Colombier return(0); 7743e12c5d1SDavid du Colombier else a++; 7753e12c5d1SDavid du Colombier return(1); 7763e12c5d1SDavid du Colombier } 7773e12c5d1SDavid du Colombier 7783e12c5d1SDavid du Colombier char * 7793e12c5d1SDavid du Colombier text(char *p) /* extract character string */ 7803e12c5d1SDavid du Colombier { 7813e12c5d1SDavid du Colombier Rune r; 7823e12c5d1SDavid du Colombier 7833e12c5d1SDavid du Colombier while(*cp == '\t' || *cp == ' ') 7843e12c5d1SDavid du Colombier cp++; 7853e12c5d1SDavid du Colombier while (*cp) { 7863e12c5d1SDavid du Colombier if ((r = *cp++) == '\\') 7873e12c5d1SDavid du Colombier if ((r = *cp++) == 0) 7883e12c5d1SDavid du Colombier break;; 7893e12c5d1SDavid du Colombier if (r == '\n') 7903e12c5d1SDavid du Colombier while (*cp == '\t' || *cp == ' ') 7913e12c5d1SDavid du Colombier cp++; 7923e12c5d1SDavid du Colombier p += runetochar(p, &r); 7933e12c5d1SDavid du Colombier } 7943e12c5d1SDavid du Colombier *p++ = '\0'; 7953e12c5d1SDavid du Colombier return p; 7963e12c5d1SDavid du Colombier } 7973e12c5d1SDavid du Colombier 7983e12c5d1SDavid du Colombier Rune * 7993e12c5d1SDavid du Colombier stext(Rune *p, Rune *end) /* extract rune string */ 8003e12c5d1SDavid du Colombier { 8013e12c5d1SDavid du Colombier while(*cp == '\t' || *cp == ' ') 8023e12c5d1SDavid du Colombier cp++; 8033e12c5d1SDavid du Colombier while (*cp) { 8043e12c5d1SDavid du Colombier if (*cp == '\\') 8053e12c5d1SDavid du Colombier if (*++cp == 0) 8063e12c5d1SDavid du Colombier break; 8073e12c5d1SDavid du Colombier if (p >= end-1) 8083e12c5d1SDavid du Colombier quit(TMMES, (char *) linebuf); 8093e12c5d1SDavid du Colombier if ((*p++ = *cp++) == '\n') 8103e12c5d1SDavid du Colombier while(*cp == '\t' || *cp == ' ') 8113e12c5d1SDavid du Colombier cp++; 8123e12c5d1SDavid du Colombier } 8133e12c5d1SDavid du Colombier *p++ = 0; 8143e12c5d1SDavid du Colombier return p; 8153e12c5d1SDavid du Colombier } 8163e12c5d1SDavid du Colombier 8173e12c5d1SDavid du Colombier 8183e12c5d1SDavid du Colombier Label * 8193e12c5d1SDavid du Colombier search (Label *ptr) 8203e12c5d1SDavid du Colombier { 8213e12c5d1SDavid du Colombier Label *rp; 8223e12c5d1SDavid du Colombier 8233e12c5d1SDavid du Colombier for (rp = ltab; rp < ptr; rp++) 8243e12c5d1SDavid du Colombier if(rcmp(rp->asc, ptr->asc) == 0) 8253e12c5d1SDavid du Colombier return(rp); 8263e12c5d1SDavid du Colombier return(0); 8273e12c5d1SDavid du Colombier } 8283e12c5d1SDavid du Colombier 8293e12c5d1SDavid du Colombier void 8303e12c5d1SDavid du Colombier dechain(void) 8313e12c5d1SDavid du Colombier { 8323e12c5d1SDavid du Colombier Label *lptr; 8333e12c5d1SDavid du Colombier SedCom *rptr, *trptr; 8343e12c5d1SDavid du Colombier 8353e12c5d1SDavid du Colombier for(lptr = ltab; lptr < lab; lptr++) { 8363e12c5d1SDavid du Colombier 8373e12c5d1SDavid du Colombier if(lptr->address == 0) 8383e12c5d1SDavid du Colombier quit("Undefined label: %S", (char *) lptr->asc); 8393e12c5d1SDavid du Colombier 8403e12c5d1SDavid du Colombier if(lptr->chain) { 8413e12c5d1SDavid du Colombier rptr = lptr->chain; 8423e12c5d1SDavid du Colombier while(trptr = rptr->lb1) { 8433e12c5d1SDavid du Colombier rptr->lb1 = lptr->address; 8443e12c5d1SDavid du Colombier rptr = trptr; 8453e12c5d1SDavid du Colombier } 8463e12c5d1SDavid du Colombier rptr->lb1 = lptr->address; 8473e12c5d1SDavid du Colombier } 8483e12c5d1SDavid du Colombier } 8493e12c5d1SDavid du Colombier } 8503e12c5d1SDavid du Colombier 8513e12c5d1SDavid du Colombier int 8523e12c5d1SDavid du Colombier ycomp(SedCom *r) 8533e12c5d1SDavid du Colombier { 8543e12c5d1SDavid du Colombier int i; 8553e12c5d1SDavid du Colombier Rune *rp; 8563e12c5d1SDavid du Colombier Rune c, *tsp, highc; 8573e12c5d1SDavid du Colombier Rune *sp; 8583e12c5d1SDavid du Colombier 8593e12c5d1SDavid du Colombier highc = 0; 8603e12c5d1SDavid du Colombier for(tsp = cp; *tsp != seof; tsp++) { 8613e12c5d1SDavid du Colombier if(*tsp == '\\') 8623e12c5d1SDavid du Colombier tsp++; 8633e12c5d1SDavid du Colombier if(*tsp == '\n' || *tsp == '\0') 8643e12c5d1SDavid du Colombier return(0); 8653e12c5d1SDavid du Colombier if (*tsp > highc) highc = *tsp; 8663e12c5d1SDavid du Colombier } 8673e12c5d1SDavid du Colombier tsp++; 8683e12c5d1SDavid du Colombier if ((rp = r->text = (Rune *) malloc(sizeof(Rune)*(highc+2))) == 0) 8693e12c5d1SDavid du Colombier quit("Out of memory", 0); 8703e12c5d1SDavid du Colombier *rp++ = highc; /* save upper bound */ 8713e12c5d1SDavid du Colombier for (i = 0; i <= highc; i++) 8723e12c5d1SDavid du Colombier rp[i] = i; 8733e12c5d1SDavid du Colombier sp = cp; 8743e12c5d1SDavid du Colombier while((c = *sp++) != seof) { 8753e12c5d1SDavid du Colombier if(c == '\\' && *sp == 'n') { 8763e12c5d1SDavid du Colombier sp++; 8773e12c5d1SDavid du Colombier c = '\n'; 8783e12c5d1SDavid du Colombier } 8793e12c5d1SDavid du Colombier if((rp[c] = *tsp++) == '\\' && *tsp == 'n') { 8803e12c5d1SDavid du Colombier rp[c] = '\n'; 8813e12c5d1SDavid du Colombier tsp++; 8823e12c5d1SDavid du Colombier } 8833e12c5d1SDavid du Colombier if(rp[c] == seof || rp[c] == '\0') { 8843e12c5d1SDavid du Colombier free(r->re1); 8853e12c5d1SDavid du Colombier r->re1 = 0; 8863e12c5d1SDavid du Colombier return(0); 8873e12c5d1SDavid du Colombier } 8883e12c5d1SDavid du Colombier } 8893e12c5d1SDavid du Colombier if(*tsp != seof) { 8903e12c5d1SDavid du Colombier free(r->re1); 8913e12c5d1SDavid du Colombier r->re1 = 0; 8923e12c5d1SDavid du Colombier return(0); 8933e12c5d1SDavid du Colombier } 8943e12c5d1SDavid du Colombier cp = tsp+1; 8953e12c5d1SDavid du Colombier return(1); 8963e12c5d1SDavid du Colombier } 8973e12c5d1SDavid du Colombier 8983e12c5d1SDavid du Colombier void 8993e12c5d1SDavid du Colombier execute(void) 9003e12c5d1SDavid du Colombier { 9013e12c5d1SDavid du Colombier SedCom *ipc; 9023e12c5d1SDavid du Colombier 9033e12c5d1SDavid du Colombier while (spend = gline(linebuf)){ 9043e12c5d1SDavid du Colombier for(ipc = pspace; ipc->command; ) { 9053e12c5d1SDavid du Colombier if (!executable(ipc)) { 9063e12c5d1SDavid du Colombier ipc++; 9073e12c5d1SDavid du Colombier continue; 9083e12c5d1SDavid du Colombier } 9093e12c5d1SDavid du Colombier command(ipc); 910*219b2ee8SDavid du Colombier 911*219b2ee8SDavid du Colombier if(ipc->ad2.type == A_RE && match(ipc->ad2.rp, linebuf)) 912*219b2ee8SDavid du Colombier ipc->active = 0; 913*219b2ee8SDavid du Colombier 9143e12c5d1SDavid du Colombier if(delflag) 9153e12c5d1SDavid du Colombier break; 9163e12c5d1SDavid du Colombier 9173e12c5d1SDavid du Colombier if(jflag) { 9183e12c5d1SDavid du Colombier jflag = 0; 9193e12c5d1SDavid du Colombier if((ipc = ipc->lb1) == 0) 9203e12c5d1SDavid du Colombier break; 9213e12c5d1SDavid du Colombier } else 9223e12c5d1SDavid du Colombier ipc++; 9233e12c5d1SDavid du Colombier 9243e12c5d1SDavid du Colombier } 9253e12c5d1SDavid du Colombier if(!nflag && !delflag) 9263e12c5d1SDavid du Colombier putline(&fout, linebuf, spend-linebuf); 9273e12c5d1SDavid du Colombier if(aptr > abuf) { 9283e12c5d1SDavid du Colombier arout(); 9293e12c5d1SDavid du Colombier } 9303e12c5d1SDavid du Colombier delflag = 0; 9313e12c5d1SDavid du Colombier } 9323e12c5d1SDavid du Colombier } 9333e12c5d1SDavid du Colombier /* determine if a statement should be applied to an input line */ 9343e12c5d1SDavid du Colombier int 9353e12c5d1SDavid du Colombier executable(SedCom *ipc) 9363e12c5d1SDavid du Colombier { 9373e12c5d1SDavid du Colombier if (ipc->active) { /* Addr1 satisfied - accept until Addr2 */ 9383e12c5d1SDavid du Colombier if (ipc->active == 1) /* Second line */ 9393e12c5d1SDavid du Colombier ipc->active = 2; 9403e12c5d1SDavid du Colombier switch(ipc->ad2.type) { 9413e12c5d1SDavid du Colombier case A_NONE: /* No second addr; use first */ 9423e12c5d1SDavid du Colombier ipc->active = 0; 9433e12c5d1SDavid du Colombier break; 9443e12c5d1SDavid du Colombier case A_DOL: /* Accept everything */ 9453e12c5d1SDavid du Colombier return !ipc->negfl; 9463e12c5d1SDavid du Colombier case A_LINE: /* Line at end of range? */ 9473e12c5d1SDavid du Colombier if (lnum <= ipc->ad2.line) { 9483e12c5d1SDavid du Colombier if (ipc->ad2.line == lnum) 9493e12c5d1SDavid du Colombier ipc->active = 0; 9503e12c5d1SDavid du Colombier return !ipc->negfl; 9513e12c5d1SDavid du Colombier } 9523e12c5d1SDavid du Colombier ipc->active = 0; /* out of range */ 9533e12c5d1SDavid du Colombier return ipc->negfl; 9543e12c5d1SDavid du Colombier case A_RE: /* Check for matching R.E. */ 9553e12c5d1SDavid du Colombier if (match(ipc->ad2.rp, linebuf)) 9563e12c5d1SDavid du Colombier ipc->active = 0; 9573e12c5d1SDavid du Colombier return !ipc->negfl; 9583e12c5d1SDavid du Colombier default: /* internal error */ 9593e12c5d1SDavid du Colombier quit("Internal error", 0); 9603e12c5d1SDavid du Colombier } 9613e12c5d1SDavid du Colombier } 9623e12c5d1SDavid du Colombier switch (ipc->ad1.type) { /* Check first address */ 9633e12c5d1SDavid du Colombier case A_NONE: /* Everything matches */ 9643e12c5d1SDavid du Colombier return !ipc->negfl; 9653e12c5d1SDavid du Colombier case A_DOL: /* Only last line */ 9663e12c5d1SDavid du Colombier if (dolflag) 9673e12c5d1SDavid du Colombier return !ipc->negfl; 9683e12c5d1SDavid du Colombier break; 9693e12c5d1SDavid du Colombier case A_LINE: /* Check line number */ 9703e12c5d1SDavid du Colombier if (ipc->ad1.line == lnum) { 9713e12c5d1SDavid du Colombier ipc->active = 1; /* In range */ 9723e12c5d1SDavid du Colombier return !ipc->negfl; 9733e12c5d1SDavid du Colombier } 9743e12c5d1SDavid du Colombier break; 9753e12c5d1SDavid du Colombier case A_RE: /* Check R.E. */ 9763e12c5d1SDavid du Colombier if (match(ipc->ad1.rp, linebuf)) { 9773e12c5d1SDavid du Colombier ipc->active = 1; /* In range */ 9783e12c5d1SDavid du Colombier return !ipc->negfl; 9793e12c5d1SDavid du Colombier } 9803e12c5d1SDavid du Colombier break; 9813e12c5d1SDavid du Colombier default: 9823e12c5d1SDavid du Colombier quit("Internal error", 0); 9833e12c5d1SDavid du Colombier } 9843e12c5d1SDavid du Colombier return ipc->negfl; 9853e12c5d1SDavid du Colombier } 9863e12c5d1SDavid du Colombier match(Reprog *pattern, Rune *buf) 9873e12c5d1SDavid du Colombier { 9883e12c5d1SDavid du Colombier if (!pattern) 9893e12c5d1SDavid du Colombier return 0; 9903e12c5d1SDavid du Colombier subexp[0].rsp = buf; 9913e12c5d1SDavid du Colombier subexp[0].ep = 0; 9923e12c5d1SDavid du Colombier if (rregexec(pattern, linebuf, subexp, MAXSUB)) { 9933e12c5d1SDavid du Colombier loc1 = subexp[0].rsp; 9943e12c5d1SDavid du Colombier loc2 = subexp[0].rep; 9953e12c5d1SDavid du Colombier return 1; 9963e12c5d1SDavid du Colombier } 9973e12c5d1SDavid du Colombier loc1 = loc2 = 0; 9983e12c5d1SDavid du Colombier return 0; 9993e12c5d1SDavid du Colombier } 10003e12c5d1SDavid du Colombier substitute(SedCom *ipc) 10013e12c5d1SDavid du Colombier { 10023e12c5d1SDavid du Colombier if(match(ipc->re1, linebuf)) { 10033e12c5d1SDavid du Colombier sflag = 1; 10043e12c5d1SDavid du Colombier dosub(ipc->rhs); 10053e12c5d1SDavid du Colombier if(!ipc->gfl) 10063e12c5d1SDavid du Colombier return 1; 10073e12c5d1SDavid du Colombier while (match(ipc->re1, loc2)) { 10083e12c5d1SDavid du Colombier if (loc2-loc1 == 0){ /* NULL R.E. match */ 10093e12c5d1SDavid du Colombier if (*loc2++ == 0) 10103e12c5d1SDavid du Colombier break; 10113e12c5d1SDavid du Colombier } else { 10123e12c5d1SDavid du Colombier dosub(ipc->rhs); 10133e12c5d1SDavid du Colombier if(*loc2 == 0) 10143e12c5d1SDavid du Colombier break; 10153e12c5d1SDavid du Colombier } 10163e12c5d1SDavid du Colombier } 10173e12c5d1SDavid du Colombier return 1; 10183e12c5d1SDavid du Colombier } 10193e12c5d1SDavid du Colombier return 0; 10203e12c5d1SDavid du Colombier } 10213e12c5d1SDavid du Colombier 10223e12c5d1SDavid du Colombier void 10233e12c5d1SDavid du Colombier dosub(Rune *rhsbuf) 10243e12c5d1SDavid du Colombier { 10253e12c5d1SDavid du Colombier Rune *lp, *sp; 10263e12c5d1SDavid du Colombier Rune *rp; 10273e12c5d1SDavid du Colombier int c, n; 10283e12c5d1SDavid du Colombier 10293e12c5d1SDavid du Colombier lp = linebuf; 10303e12c5d1SDavid du Colombier sp = genbuf; 10313e12c5d1SDavid du Colombier rp = rhsbuf; 10323e12c5d1SDavid du Colombier while (lp < loc1) 10333e12c5d1SDavid du Colombier *sp++ = *lp++; 10343e12c5d1SDavid du Colombier while(c = *rp++) { 10353e12c5d1SDavid du Colombier if (c == '&') { 10363e12c5d1SDavid du Colombier sp = place(sp, loc1, loc2); 10373e12c5d1SDavid du Colombier continue; 10383e12c5d1SDavid du Colombier } 10393e12c5d1SDavid du Colombier if (c == 0xFFFF && (c = *rp++) >= '1' && c <= MAXSUB+'0') { 10403e12c5d1SDavid du Colombier n = c-'0'; 10413e12c5d1SDavid du Colombier if (subexp[n].rsp && subexp[n].rep) { 10423e12c5d1SDavid du Colombier sp = place(sp, subexp[n].rsp, subexp[n].rep); 10433e12c5d1SDavid du Colombier continue; 10443e12c5d1SDavid du Colombier } 10453e12c5d1SDavid du Colombier else { 10463e12c5d1SDavid du Colombier fprint(2, "sed: Invalid back reference \\%d\n",n); 10473e12c5d1SDavid du Colombier errexit(); 10483e12c5d1SDavid du Colombier } 10493e12c5d1SDavid du Colombier } 10503e12c5d1SDavid du Colombier *sp++ = c; 10513e12c5d1SDavid du Colombier if (sp >= &genbuf[LBSIZE]) 10523e12c5d1SDavid du Colombier fprint(2, "sed: Output line too long.\n"); 10533e12c5d1SDavid du Colombier } 10543e12c5d1SDavid du Colombier lp = loc2; 10553e12c5d1SDavid du Colombier loc2 = sp - genbuf + linebuf; 10563e12c5d1SDavid du Colombier while (*sp++ = *lp++) 10573e12c5d1SDavid du Colombier if (sp >= &genbuf[LBSIZE]) 10583e12c5d1SDavid du Colombier fprint(2, "sed: Output line too long.\n"); 10593e12c5d1SDavid du Colombier lp = linebuf; 10603e12c5d1SDavid du Colombier sp = genbuf; 10613e12c5d1SDavid du Colombier while (*lp++ = *sp++) 10623e12c5d1SDavid du Colombier ; 10633e12c5d1SDavid du Colombier spend = lp-1; 10643e12c5d1SDavid du Colombier } 10653e12c5d1SDavid du Colombier 10663e12c5d1SDavid du Colombier Rune * 10673e12c5d1SDavid du Colombier place(Rune *sp, Rune *l1, Rune *l2) 10683e12c5d1SDavid du Colombier { 10693e12c5d1SDavid du Colombier while (l1 < l2) { 10703e12c5d1SDavid du Colombier *sp++ = *l1++; 10713e12c5d1SDavid du Colombier if (sp >= &genbuf[LBSIZE]) 10723e12c5d1SDavid du Colombier fprint(2, "sed: Output line too long.\n"); 10733e12c5d1SDavid du Colombier } 10743e12c5d1SDavid du Colombier return(sp); 10753e12c5d1SDavid du Colombier } 10763e12c5d1SDavid du Colombier 10773e12c5d1SDavid du Colombier char * 10783e12c5d1SDavid du Colombier trans(int c) 10793e12c5d1SDavid du Colombier { 10803e12c5d1SDavid du Colombier static char buf[] = "\\x0000"; 10813e12c5d1SDavid du Colombier static char hex[] = "0123456789abcdef"; 10823e12c5d1SDavid du Colombier 10833e12c5d1SDavid du Colombier switch(c) { 10843e12c5d1SDavid du Colombier case '\b': 10853e12c5d1SDavid du Colombier return "\\b"; 10863e12c5d1SDavid du Colombier case '\n': 10873e12c5d1SDavid du Colombier return "\\n"; 10883e12c5d1SDavid du Colombier case '\r': 10893e12c5d1SDavid du Colombier return "\\r"; 10903e12c5d1SDavid du Colombier case '\t': 10913e12c5d1SDavid du Colombier return "\\t"; 10923e12c5d1SDavid du Colombier case '\\': 10933e12c5d1SDavid du Colombier return "\\\\"; 10943e12c5d1SDavid du Colombier } 10953e12c5d1SDavid du Colombier buf[2] = hex[(c>>12)&0xF]; 10963e12c5d1SDavid du Colombier buf[3] = hex[(c>>8)&0xF]; 10973e12c5d1SDavid du Colombier buf[4] = hex[(c>>4)&0xF]; 10983e12c5d1SDavid du Colombier buf[5] = hex[c&0xF]; 10993e12c5d1SDavid du Colombier return buf; 11003e12c5d1SDavid du Colombier } 11013e12c5d1SDavid du Colombier 11023e12c5d1SDavid du Colombier void 11033e12c5d1SDavid du Colombier command(SedCom *ipc) 11043e12c5d1SDavid du Colombier { 11053e12c5d1SDavid du Colombier int i, c; 11063e12c5d1SDavid du Colombier Rune *p1, *p2; 11073e12c5d1SDavid du Colombier char *ucp; 11083e12c5d1SDavid du Colombier Rune *rp; 11093e12c5d1SDavid du Colombier Rune *execp; 11103e12c5d1SDavid du Colombier 11113e12c5d1SDavid du Colombier switch(ipc->command) { 11123e12c5d1SDavid du Colombier 11133e12c5d1SDavid du Colombier case ACOM: 11143e12c5d1SDavid du Colombier *aptr++ = ipc; 11153e12c5d1SDavid du Colombier if(aptr >= abuf+MAXADDS) { 11163e12c5d1SDavid du Colombier quit("sed: Too many appends after line %ld\n", 11173e12c5d1SDavid du Colombier (char *) lnum); 11183e12c5d1SDavid du Colombier } 11193e12c5d1SDavid du Colombier *aptr = 0; 11203e12c5d1SDavid du Colombier break; 11213e12c5d1SDavid du Colombier case CCOM: 11223e12c5d1SDavid du Colombier delflag = 1; 11233e12c5d1SDavid du Colombier if(ipc->active == 1) { 11243e12c5d1SDavid du Colombier for(rp = ipc->text; *rp; rp++) 11253e12c5d1SDavid du Colombier Bputrune(&fout, *rp); 11263e12c5d1SDavid du Colombier Bputc(&fout, '\n'); 11273e12c5d1SDavid du Colombier } 11283e12c5d1SDavid du Colombier break; 11293e12c5d1SDavid du Colombier case DCOM: 11303e12c5d1SDavid du Colombier delflag++; 11313e12c5d1SDavid du Colombier break; 11323e12c5d1SDavid du Colombier case CDCOM: 11333e12c5d1SDavid du Colombier p1 = p2 = linebuf; 11343e12c5d1SDavid du Colombier while(*p1 != '\n') { 11353e12c5d1SDavid du Colombier if(*p1++ == 0) { 11363e12c5d1SDavid du Colombier delflag++; 11373e12c5d1SDavid du Colombier return; 11383e12c5d1SDavid du Colombier } 11393e12c5d1SDavid du Colombier } 11403e12c5d1SDavid du Colombier p1++; 11413e12c5d1SDavid du Colombier while(*p2++ = *p1++) 11423e12c5d1SDavid du Colombier ; 11433e12c5d1SDavid du Colombier spend = p2-1; 11443e12c5d1SDavid du Colombier jflag++; 11453e12c5d1SDavid du Colombier break; 11463e12c5d1SDavid du Colombier case EQCOM: 11473e12c5d1SDavid du Colombier Bprint(&fout, "%ld\n", lnum); 11483e12c5d1SDavid du Colombier break; 11493e12c5d1SDavid du Colombier case GCOM: 11503e12c5d1SDavid du Colombier p1 = linebuf; 11513e12c5d1SDavid du Colombier p2 = holdsp; 11523e12c5d1SDavid du Colombier while(*p1++ = *p2++) 11533e12c5d1SDavid du Colombier ; 11543e12c5d1SDavid du Colombier spend = p1-1; 11553e12c5d1SDavid du Colombier break; 11563e12c5d1SDavid du Colombier case CGCOM: 11573e12c5d1SDavid du Colombier *spend++ = '\n'; 11583e12c5d1SDavid du Colombier p1 = spend; 11593e12c5d1SDavid du Colombier p2 = holdsp; 11603e12c5d1SDavid du Colombier while(*p1++ = *p2++) 11613e12c5d1SDavid du Colombier if(p1 >= lbend) 11623e12c5d1SDavid du Colombier break; 11633e12c5d1SDavid du Colombier spend = p1-1; 11643e12c5d1SDavid du Colombier break; 11653e12c5d1SDavid du Colombier case HCOM: 11663e12c5d1SDavid du Colombier p1 = holdsp; 11673e12c5d1SDavid du Colombier p2 = linebuf; 11683e12c5d1SDavid du Colombier while(*p1++ = *p2++); 11693e12c5d1SDavid du Colombier hspend = p1-1; 11703e12c5d1SDavid du Colombier break; 11713e12c5d1SDavid du Colombier case CHCOM: 11723e12c5d1SDavid du Colombier *hspend++ = '\n'; 11733e12c5d1SDavid du Colombier p1 = hspend; 11743e12c5d1SDavid du Colombier p2 = linebuf; 11753e12c5d1SDavid du Colombier while(*p1++ = *p2++) 11763e12c5d1SDavid du Colombier if(p1 >= hend) 11773e12c5d1SDavid du Colombier break; 11783e12c5d1SDavid du Colombier hspend = p1-1; 11793e12c5d1SDavid du Colombier break; 11803e12c5d1SDavid du Colombier case ICOM: 11813e12c5d1SDavid du Colombier for(rp = ipc->text; *rp; rp++) 11823e12c5d1SDavid du Colombier Bputrune(&fout, *rp); 11833e12c5d1SDavid du Colombier Bputc(&fout, '\n'); 11843e12c5d1SDavid du Colombier break; 11853e12c5d1SDavid du Colombier case BCOM: 11863e12c5d1SDavid du Colombier jflag = 1; 11873e12c5d1SDavid du Colombier break; 11883e12c5d1SDavid du Colombier case LCOM: 11893e12c5d1SDavid du Colombier c = 0; 11903e12c5d1SDavid du Colombier for (i = 0, rp = linebuf; *rp; rp++) { 11913e12c5d1SDavid du Colombier c = *rp; 11923e12c5d1SDavid du Colombier if(c >= 0x20 && c < 0x7F && c != '\\') { 11933e12c5d1SDavid du Colombier Bputc(&fout, c); 11943e12c5d1SDavid du Colombier if(i++ > 71) { 11953e12c5d1SDavid du Colombier Bprint(&fout, "\\\n"); 11963e12c5d1SDavid du Colombier i = 0; 11973e12c5d1SDavid du Colombier } 11983e12c5d1SDavid du Colombier } else { 11993e12c5d1SDavid du Colombier for (ucp = trans(*rp); *ucp; ucp++){ 12003e12c5d1SDavid du Colombier c = *ucp; 12013e12c5d1SDavid du Colombier Bputc(&fout, c); 12023e12c5d1SDavid du Colombier if(i++ > 71) { 12033e12c5d1SDavid du Colombier Bprint(&fout, "\\\n"); 12043e12c5d1SDavid du Colombier i = 0; 12053e12c5d1SDavid du Colombier } 12063e12c5d1SDavid du Colombier } 12073e12c5d1SDavid du Colombier } 12083e12c5d1SDavid du Colombier } 12093e12c5d1SDavid du Colombier if(c == ' ') 12103e12c5d1SDavid du Colombier Bprint(&fout, "\\n"); 12113e12c5d1SDavid du Colombier Bputc(&fout, '\n'); 12123e12c5d1SDavid du Colombier break; 12133e12c5d1SDavid du Colombier case NCOM: 12143e12c5d1SDavid du Colombier if(!nflag) 12153e12c5d1SDavid du Colombier putline(&fout, linebuf, spend-linebuf); 12163e12c5d1SDavid du Colombier 12173e12c5d1SDavid du Colombier if(aptr > abuf) 12183e12c5d1SDavid du Colombier arout(); 12193e12c5d1SDavid du Colombier if((execp = gline(linebuf)) == 0) { 12203e12c5d1SDavid du Colombier delflag = 1; 12213e12c5d1SDavid du Colombier break; 12223e12c5d1SDavid du Colombier } 12233e12c5d1SDavid du Colombier spend = execp; 12243e12c5d1SDavid du Colombier break; 12253e12c5d1SDavid du Colombier case CNCOM: 12263e12c5d1SDavid du Colombier if(aptr > abuf) 12273e12c5d1SDavid du Colombier arout(); 12283e12c5d1SDavid du Colombier *spend++ = '\n'; 12293e12c5d1SDavid du Colombier if((execp = gline(spend)) == 0) { 12303e12c5d1SDavid du Colombier delflag = 1; 12313e12c5d1SDavid du Colombier break; 12323e12c5d1SDavid du Colombier } 12333e12c5d1SDavid du Colombier spend = execp; 12343e12c5d1SDavid du Colombier break; 12353e12c5d1SDavid du Colombier case PCOM: 12363e12c5d1SDavid du Colombier putline(&fout, linebuf, spend-linebuf); 12373e12c5d1SDavid du Colombier break; 12383e12c5d1SDavid du Colombier case CPCOM: 12393e12c5d1SDavid du Colombier cpcom: 12403e12c5d1SDavid du Colombier for(rp = linebuf; *rp && *rp != '\n'; rp++) 12413e12c5d1SDavid du Colombier Bputc(&fout, *rp); 12423e12c5d1SDavid du Colombier Bputc(&fout, '\n'); 12433e12c5d1SDavid du Colombier break; 12443e12c5d1SDavid du Colombier case QCOM: 12453e12c5d1SDavid du Colombier if(!nflag) 12463e12c5d1SDavid du Colombier putline(&fout, linebuf, spend-linebuf); 12473e12c5d1SDavid du Colombier if(aptr > abuf) 12483e12c5d1SDavid du Colombier arout(); 12493e12c5d1SDavid du Colombier exits(0); 12503e12c5d1SDavid du Colombier case RCOM: 12513e12c5d1SDavid du Colombier *aptr++ = ipc; 12523e12c5d1SDavid du Colombier if(aptr >= &abuf[MAXADDS]) 12533e12c5d1SDavid du Colombier quit("sed: Too many reads after line %ld\n", 12543e12c5d1SDavid du Colombier (char *) lnum); 12553e12c5d1SDavid du Colombier *aptr = 0; 12563e12c5d1SDavid du Colombier break; 12573e12c5d1SDavid du Colombier case SCOM: 12583e12c5d1SDavid du Colombier i = substitute(ipc); 12593e12c5d1SDavid du Colombier if(i && ipc->pfl) 12603e12c5d1SDavid du Colombier if(ipc->pfl == 1) 12613e12c5d1SDavid du Colombier putline(&fout, linebuf, spend-linebuf); 12623e12c5d1SDavid du Colombier else 12633e12c5d1SDavid du Colombier goto cpcom; 12643e12c5d1SDavid du Colombier if(i && ipc->fcode) 12653e12c5d1SDavid du Colombier goto wcom; 12663e12c5d1SDavid du Colombier break; 12673e12c5d1SDavid du Colombier 12683e12c5d1SDavid du Colombier case TCOM: 12693e12c5d1SDavid du Colombier if(sflag == 0) break; 12703e12c5d1SDavid du Colombier sflag = 0; 12713e12c5d1SDavid du Colombier jflag = 1; 12723e12c5d1SDavid du Colombier break; 12733e12c5d1SDavid du Colombier 12743e12c5d1SDavid du Colombier wcom: 12753e12c5d1SDavid du Colombier case WCOM: 12763e12c5d1SDavid du Colombier putline(ipc->fcode,linebuf, spend-linebuf); 12773e12c5d1SDavid du Colombier break; 12783e12c5d1SDavid du Colombier case XCOM: 12793e12c5d1SDavid du Colombier p1 = linebuf; 12803e12c5d1SDavid du Colombier p2 = genbuf; 12813e12c5d1SDavid du Colombier while(*p2++ = *p1++); 12823e12c5d1SDavid du Colombier p1 = holdsp; 12833e12c5d1SDavid du Colombier p2 = linebuf; 12843e12c5d1SDavid du Colombier while(*p2++ = *p1++); 12853e12c5d1SDavid du Colombier spend = p2 - 1; 12863e12c5d1SDavid du Colombier p1 = genbuf; 12873e12c5d1SDavid du Colombier p2 = holdsp; 12883e12c5d1SDavid du Colombier while(*p2++ = *p1++); 12893e12c5d1SDavid du Colombier hspend = p2 - 1; 12903e12c5d1SDavid du Colombier break; 12913e12c5d1SDavid du Colombier case YCOM: 12923e12c5d1SDavid du Colombier p1 = linebuf; 12933e12c5d1SDavid du Colombier p2 = ipc->text; 12943e12c5d1SDavid du Colombier for (i = *p2++; *p1; p1++){ 12953e12c5d1SDavid du Colombier if (*p1 <= i) *p1 = p2[*p1]; 12963e12c5d1SDavid du Colombier } 12973e12c5d1SDavid du Colombier break; 12983e12c5d1SDavid du Colombier } 12993e12c5d1SDavid du Colombier 13003e12c5d1SDavid du Colombier } 13013e12c5d1SDavid du Colombier 13023e12c5d1SDavid du Colombier void 13033e12c5d1SDavid du Colombier putline(Biobuf *bp, Rune *buf, int n) 13043e12c5d1SDavid du Colombier { 13053e12c5d1SDavid du Colombier while (n--) 13063e12c5d1SDavid du Colombier Bputrune(bp, *buf++); 13073e12c5d1SDavid du Colombier Bputc(bp, '\n'); 13083e12c5d1SDavid du Colombier } 13093e12c5d1SDavid du Colombier ecmp(Rune *a, Rune *b, int count) 13103e12c5d1SDavid du Colombier { 13113e12c5d1SDavid du Colombier while(count--) 13123e12c5d1SDavid du Colombier if(*a++ != *b++) return(0); 13133e12c5d1SDavid du Colombier return(1); 13143e12c5d1SDavid du Colombier } 13153e12c5d1SDavid du Colombier 13163e12c5d1SDavid du Colombier void 13173e12c5d1SDavid du Colombier arout(void) 13183e12c5d1SDavid du Colombier { 13193e12c5d1SDavid du Colombier Rune *p1; 13203e12c5d1SDavid du Colombier Biobuf *fi; 13213e12c5d1SDavid du Colombier int c; 13223e12c5d1SDavid du Colombier char *s; 13233e12c5d1SDavid du Colombier char buf[128]; 13243e12c5d1SDavid du Colombier 13253e12c5d1SDavid du Colombier for (aptr = abuf; *aptr; aptr++) { 13263e12c5d1SDavid du Colombier if((*aptr)->command == ACOM) { 13273e12c5d1SDavid du Colombier for(p1 = (*aptr)->text; *p1; p1++ ) 13283e12c5d1SDavid du Colombier Bputrune(&fout, *p1); 13293e12c5d1SDavid du Colombier Bputc(&fout, '\n'); 13303e12c5d1SDavid du Colombier } else { 13313e12c5d1SDavid du Colombier for(s = buf, p1= (*aptr)->text; *p1; p1++) 13323e12c5d1SDavid du Colombier s += runetochar(s, p1); 13333e12c5d1SDavid du Colombier *s = '\0'; 13343e12c5d1SDavid du Colombier if((fi = Bopen(buf, OREAD)) == 0) 13353e12c5d1SDavid du Colombier continue; 13363e12c5d1SDavid du Colombier while((c = Bgetc(fi)) >= 0) 13373e12c5d1SDavid du Colombier Bputc(&fout, c); 1338*219b2ee8SDavid du Colombier Bterm(fi); 13393e12c5d1SDavid du Colombier } 13403e12c5d1SDavid du Colombier } 13413e12c5d1SDavid du Colombier aptr = abuf; 13423e12c5d1SDavid du Colombier *aptr = 0; 13433e12c5d1SDavid du Colombier } 13443e12c5d1SDavid du Colombier 13453e12c5d1SDavid du Colombier void 13463e12c5d1SDavid du Colombier errexit(void) 13473e12c5d1SDavid du Colombier { 13483e12c5d1SDavid du Colombier exits("error"); 13493e12c5d1SDavid du Colombier } 13503e12c5d1SDavid du Colombier 13513e12c5d1SDavid du Colombier void 13523e12c5d1SDavid du Colombier quit (char *msg, char *arg) 13533e12c5d1SDavid du Colombier { 13543e12c5d1SDavid du Colombier fprint(2, "sed: "); 13553e12c5d1SDavid du Colombier fprint(2, msg, arg); 13563e12c5d1SDavid du Colombier fprint(2, "\n"); 13573e12c5d1SDavid du Colombier errexit(); 13583e12c5d1SDavid du Colombier } 13593e12c5d1SDavid du Colombier 13603e12c5d1SDavid du Colombier Rune * 13613e12c5d1SDavid du Colombier gline(Rune *addr) 13623e12c5d1SDavid du Colombier { 13633e12c5d1SDavid du Colombier long c; 13643e12c5d1SDavid du Colombier Rune *p; 13653e12c5d1SDavid du Colombier 13663e12c5d1SDavid du Colombier static long peekc = 0; 13673e12c5d1SDavid du Colombier 13683e12c5d1SDavid du Colombier if (f == 0 && opendata() < 0) 13693e12c5d1SDavid du Colombier return 0; 13703e12c5d1SDavid du Colombier sflag = 0; 13713e12c5d1SDavid du Colombier lnum++; 13723e12c5d1SDavid du Colombier /* Bflush(&fout);********* dumped 4/30/92 - bobf****/ 13733e12c5d1SDavid du Colombier do { 13743e12c5d1SDavid du Colombier p = addr; 1375*219b2ee8SDavid du Colombier for (c = (peekc ? peekc : Bgetrune(f)); c >= 0; c = Bgetrune(f)) { 13763e12c5d1SDavid du Colombier if (c == '\n') { 13773e12c5d1SDavid du Colombier if ((peekc = Bgetrune(f)) < 0) { 1378*219b2ee8SDavid du Colombier Bterm(f); 13793e12c5d1SDavid du Colombier if (fhead == 0) 13803e12c5d1SDavid du Colombier dolflag = 1; 13813e12c5d1SDavid du Colombier } 13823e12c5d1SDavid du Colombier *p = '\0'; 13833e12c5d1SDavid du Colombier return p; 13843e12c5d1SDavid du Colombier } 13853e12c5d1SDavid du Colombier if (c && p < lbend) 13863e12c5d1SDavid du Colombier *p++ = c; 13873e12c5d1SDavid du Colombier } 13883e12c5d1SDavid du Colombier peekc = 0; 13893e12c5d1SDavid du Colombier } while (opendata() > 0); /* Switch to next stream */ 13903e12c5d1SDavid du Colombier return 0; 13913e12c5d1SDavid du Colombier } 13923e12c5d1SDavid du Colombier 13933e12c5d1SDavid du Colombier /* Data file input section - the intent is to transparently 13943e12c5d1SDavid du Colombier * catenate all data input streams. 13953e12c5d1SDavid du Colombier */ 13963e12c5d1SDavid du Colombier void 13973e12c5d1SDavid du Colombier enroll(char *filename) /* Add a file to the input file cache */ 13983e12c5d1SDavid du Colombier { 13993e12c5d1SDavid du Colombier FileCache *fp; 14003e12c5d1SDavid du Colombier 14013e12c5d1SDavid du Colombier if ((fp = (FileCache *) malloc(sizeof (FileCache))) == 0) 14023e12c5d1SDavid du Colombier quit("Out of memory", 0); 14033e12c5d1SDavid du Colombier if (ftail == 0) 14043e12c5d1SDavid du Colombier fhead = fp; 14053e12c5d1SDavid du Colombier else 14063e12c5d1SDavid du Colombier ftail->next = fp; 14073e12c5d1SDavid du Colombier ftail = fp; 14083e12c5d1SDavid du Colombier fp->next = 0; 14093e12c5d1SDavid du Colombier fp->name = filename; /* 0 => stdin */ 14103e12c5d1SDavid du Colombier } 14113e12c5d1SDavid du Colombier 14123e12c5d1SDavid du Colombier int 14133e12c5d1SDavid du Colombier opendata(void) 14143e12c5d1SDavid du Colombier { 14153e12c5d1SDavid du Colombier if (fhead == 0) 14163e12c5d1SDavid du Colombier return -1; 14173e12c5d1SDavid du Colombier if (fhead->name) { 14183e12c5d1SDavid du Colombier if ((f = Bopen(fhead->name, OREAD)) == 0) 14193e12c5d1SDavid du Colombier quit("Can't open %s", fhead->name); 14203e12c5d1SDavid du Colombier } else { 14213e12c5d1SDavid du Colombier Binit(&stdin, 0, OREAD); 14223e12c5d1SDavid du Colombier f = &stdin; 14233e12c5d1SDavid du Colombier } 14243e12c5d1SDavid du Colombier fhead = fhead->next; 14253e12c5d1SDavid du Colombier return 1; 14263e12c5d1SDavid du Colombier } 1427