13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier * sed -- stream editor
33e12c5d1SDavid du Colombier */
43e12c5d1SDavid du Colombier #include <u.h>
53e12c5d1SDavid du Colombier #include <libc.h>
63e12c5d1SDavid du Colombier #include <bio.h>
73e12c5d1SDavid du Colombier #include <regexp.h>
83e12c5d1SDavid du Colombier
93e12c5d1SDavid du Colombier enum {
103e12c5d1SDavid du Colombier DEPTH = 20, /* max nesting depth of {} */
113e12c5d1SDavid du Colombier MAXCMDS = 512, /* max sed commands */
123e12c5d1SDavid du Colombier ADDSIZE = 10000, /* size of add & read buffer */
133e12c5d1SDavid du Colombier MAXADDS = 20, /* max pending adds and reads */
143e12c5d1SDavid du Colombier LBSIZE = 8192, /* input line size */
156c83e8f8SDavid du Colombier LABSIZE = 50, /* max number of labels */
163e12c5d1SDavid du Colombier MAXSUB = 10, /* max number of sub reg exp */
173e12c5d1SDavid du Colombier MAXFILES = 120, /* max output files */
183e12c5d1SDavid du Colombier };
196c83e8f8SDavid du Colombier
206c83e8f8SDavid du Colombier /*
216c83e8f8SDavid 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 typedef struct label { /* Label symbol table */
856c83e8f8SDavid du Colombier Rune uninm[9]; /* Label name */
863e12c5d1SDavid du Colombier SedCom *chain;
873e12c5d1SDavid du Colombier SedCom *address; /* Command associated with label */
883e12c5d1SDavid du Colombier } Label;
893e12c5d1SDavid du Colombier
903e12c5d1SDavid du Colombier typedef struct FILE_CACHE { /* Data file control block */
913e12c5d1SDavid du Colombier struct FILE_CACHE *next; /* Forward Link */
923e12c5d1SDavid du Colombier char *name; /* Name of file */
933e12c5d1SDavid du Colombier } FileCache;
943e12c5d1SDavid du Colombier
953e12c5d1SDavid du Colombier SedCom pspace[MAXCMDS]; /* Command storage */
963e12c5d1SDavid du Colombier SedCom *pend = pspace+MAXCMDS; /* End of command storage */
973e12c5d1SDavid du Colombier SedCom *rep = pspace; /* Current fill point */
983e12c5d1SDavid du Colombier
993e12c5d1SDavid du Colombier Reprog *lastre = 0; /* Last regular expression */
1003e12c5d1SDavid du Colombier Resub subexp[MAXSUB]; /* sub-patterns of pattern match*/
1013e12c5d1SDavid du Colombier
1023e12c5d1SDavid du Colombier Rune addspace[ADDSIZE]; /* Buffer for a, c, & i commands */
1033e12c5d1SDavid du Colombier Rune *addend = addspace+ADDSIZE;
1043e12c5d1SDavid du Colombier
1053e12c5d1SDavid du Colombier SedCom *abuf[MAXADDS]; /* Queue of pending adds & reads */
1063e12c5d1SDavid du Colombier SedCom **aptr = abuf;
1073e12c5d1SDavid du Colombier
1083e12c5d1SDavid du Colombier struct { /* Sed program input control block */
1096c83e8f8SDavid du Colombier enum PTYPE { /* Either on command line or in file */
1106c83e8f8SDavid du Colombier P_ARG,
1116c83e8f8SDavid du Colombier P_FILE,
1123e12c5d1SDavid du Colombier } type;
1133e12c5d1SDavid du Colombier union PCTL { /* Pointer to data */
1143e12c5d1SDavid du Colombier Biobuf *bp;
1153e12c5d1SDavid du Colombier char *curr;
1163e12c5d1SDavid du Colombier };
1173e12c5d1SDavid du Colombier } prog;
1183e12c5d1SDavid du Colombier
1193e12c5d1SDavid du Colombier Rune genbuf[LBSIZE]; /* Miscellaneous buffer */
1203e12c5d1SDavid du Colombier
1213e12c5d1SDavid du Colombier FileCache *fhead = 0; /* Head of File Cache Chain */
1223e12c5d1SDavid du Colombier FileCache *ftail = 0; /* Tail of File Cache Chain */
1233e12c5d1SDavid du Colombier
1243e12c5d1SDavid du Colombier Rune *loc1; /* Start of pattern match */
1253e12c5d1SDavid du Colombier Rune *loc2; /* End of pattern match */
1263e12c5d1SDavid du Colombier Rune seof; /* Pattern delimiter char */
1273e12c5d1SDavid du Colombier
1283e12c5d1SDavid du Colombier Rune linebuf[LBSIZE+1]; /* Input data buffer */
1293e12c5d1SDavid du Colombier Rune *lbend = linebuf+LBSIZE; /* End of buffer */
1303e12c5d1SDavid du Colombier Rune *spend = linebuf; /* End of input data */
1313e12c5d1SDavid du Colombier Rune *cp; /* Current scan point in linebuf */
1323e12c5d1SDavid du Colombier
1333e12c5d1SDavid du Colombier Rune holdsp[LBSIZE+1]; /* Hold buffer */
1343e12c5d1SDavid du Colombier Rune *hend = holdsp+LBSIZE; /* End of hold buffer */
1353e12c5d1SDavid du Colombier Rune *hspend = holdsp; /* End of hold data */
1363e12c5d1SDavid du Colombier
1373e12c5d1SDavid du Colombier int nflag; /* Command line flags */
1383e12c5d1SDavid du Colombier int gflag;
1393e12c5d1SDavid du Colombier
1403e12c5d1SDavid du Colombier int dolflag; /* Set when at true EOF */
1413e12c5d1SDavid du Colombier int sflag; /* Set when substitution done */
1423e12c5d1SDavid du Colombier int jflag; /* Set when jump required */
1433e12c5d1SDavid du Colombier int delflag; /* Delete current line when set */
1443e12c5d1SDavid du Colombier
1453e12c5d1SDavid du Colombier long lnum = 0; /* Input line count */
1463e12c5d1SDavid du Colombier
1473e12c5d1SDavid du Colombier char fname[MAXFILES][40]; /* File name cache */
1483e12c5d1SDavid du Colombier Biobuf *fcode[MAXFILES]; /* File ID cache */
1493e12c5d1SDavid du Colombier int nfiles = 0; /* Cache fill point */
1503e12c5d1SDavid du Colombier
1513e12c5d1SDavid du Colombier Biobuf fout; /* Output stream */
1523e12c5d1SDavid du Colombier Biobuf stdin; /* Default input */
1533e12c5d1SDavid du Colombier Biobuf* f = 0; /* Input data */
1543e12c5d1SDavid du Colombier
1553e12c5d1SDavid du Colombier Label ltab[LABSIZE]; /* Label name symbol table */
1563e12c5d1SDavid du Colombier Label *labend = ltab+LABSIZE; /* End of label table */
1573e12c5d1SDavid du Colombier Label *lab = ltab+1; /* Current Fill point */
1583e12c5d1SDavid du Colombier
1593e12c5d1SDavid du Colombier int depth = 0; /* {} stack pointer */
1603e12c5d1SDavid du Colombier
1613e12c5d1SDavid du Colombier Rune bad; /* Dummy err ptr reference */
1623e12c5d1SDavid du Colombier Rune *badp = &bad;
1633e12c5d1SDavid du Colombier
1643e12c5d1SDavid du Colombier
1656c83e8f8SDavid du Colombier char CGMES[] = "%S command garbled: %S";
1663e12c5d1SDavid du Colombier char TMMES[] = "Too much text: %S";
1673e12c5d1SDavid du Colombier char LTL[] = "Label too long: %S";
1683e12c5d1SDavid du Colombier char AD0MES[] = "No addresses allowed: %S";
1693e12c5d1SDavid du Colombier char AD1MES[] = "Only one address allowed: %S";
1703e12c5d1SDavid du Colombier
1713e12c5d1SDavid du Colombier void address(Addr *);
1723e12c5d1SDavid du Colombier void arout(void);
1733e12c5d1SDavid du Colombier int cmp(char *, char *);
1743e12c5d1SDavid du Colombier int rcmp(Rune *, Rune *);
1753e12c5d1SDavid du Colombier void command(SedCom *);
1763e12c5d1SDavid du Colombier Reprog *compile(void);
1773e12c5d1SDavid du Colombier Rune *compsub(Rune *, Rune *);
1783e12c5d1SDavid du Colombier void dechain(void);
1793e12c5d1SDavid du Colombier void dosub(Rune *);
1803e12c5d1SDavid du Colombier int ecmp(Rune *, Rune *, int);
1813e12c5d1SDavid du Colombier void enroll(char *);
1823e12c5d1SDavid du Colombier void errexit(void);
1833e12c5d1SDavid du Colombier int executable(SedCom *);
1843e12c5d1SDavid du Colombier void execute(void);
1853e12c5d1SDavid du Colombier void fcomp(void);
1863e12c5d1SDavid du Colombier long getrune(void);
1873e12c5d1SDavid du Colombier Rune *gline(Rune *);
1883e12c5d1SDavid du Colombier int match(Reprog *, Rune *);
1893e12c5d1SDavid du Colombier void newfile(enum PTYPE, char *);
1903e12c5d1SDavid du Colombier int opendata(void);
1913e12c5d1SDavid du Colombier Biobuf *open_file(char *);
1923e12c5d1SDavid du Colombier Rune *place(Rune *, Rune *, Rune *);
1936c83e8f8SDavid du Colombier void quit(char *, ...);
1943e12c5d1SDavid du Colombier int rline(Rune *, Rune *);
1953e12c5d1SDavid du Colombier Label *search(Label *);
1963e12c5d1SDavid du Colombier int substitute(SedCom *);
1973e12c5d1SDavid du Colombier char *text(char *);
1983e12c5d1SDavid du Colombier Rune *stext(Rune *, Rune *);
1993e12c5d1SDavid du Colombier int ycomp(SedCom *);
2003e12c5d1SDavid du Colombier char * trans(int c);
2013e12c5d1SDavid du Colombier void putline(Biobuf *bp, Rune *buf, int n);
2023e12c5d1SDavid du Colombier
2033e12c5d1SDavid du Colombier void
main(int argc,char ** argv)2043e12c5d1SDavid du Colombier main(int argc, char **argv)
2053e12c5d1SDavid du Colombier {
2063e12c5d1SDavid du Colombier int compfl;
2073e12c5d1SDavid du Colombier
2083e12c5d1SDavid du Colombier lnum = 0;
2093e12c5d1SDavid du Colombier Binit(&fout, 1, OWRITE);
2103e12c5d1SDavid du Colombier fcode[nfiles++] = &fout;
2113e12c5d1SDavid du Colombier compfl = 0;
2123e12c5d1SDavid du Colombier
2133e12c5d1SDavid du Colombier if(argc == 1)
2143e12c5d1SDavid du Colombier exits(0);
2153e12c5d1SDavid du Colombier ARGBEGIN{
2166c83e8f8SDavid du Colombier case 'e':
2173e12c5d1SDavid du Colombier if (argc <= 1)
2186c83e8f8SDavid du Colombier quit("missing pattern");
2196c83e8f8SDavid du Colombier newfile(P_ARG, ARGF());
2203e12c5d1SDavid du Colombier fcomp();
2213e12c5d1SDavid du Colombier compfl = 1;
2223e12c5d1SDavid du Colombier continue;
2236c83e8f8SDavid du Colombier case 'f':
2243e12c5d1SDavid du Colombier if(argc <= 1)
2256c83e8f8SDavid du Colombier quit("no pattern-file");
2266c83e8f8SDavid du Colombier newfile(P_FILE, ARGF());
2273e12c5d1SDavid du Colombier fcomp();
2283e12c5d1SDavid du Colombier compfl = 1;
2293e12c5d1SDavid du Colombier continue;
2303e12c5d1SDavid du Colombier case 'g':
2313e12c5d1SDavid du Colombier gflag++;
2323e12c5d1SDavid du Colombier continue;
2336c83e8f8SDavid du Colombier case 'n':
2346c83e8f8SDavid du Colombier nflag++;
2356c83e8f8SDavid du Colombier continue;
2363e12c5d1SDavid du Colombier default:
2373e12c5d1SDavid du Colombier fprint(2, "sed: Unknown flag: %c\n", ARGC());
2383e12c5d1SDavid du Colombier continue;
2393e12c5d1SDavid du Colombier } ARGEND
2403e12c5d1SDavid du Colombier
2413e12c5d1SDavid du Colombier if(compfl == 0) {
2423e12c5d1SDavid du Colombier if (--argc < 0)
2436c83e8f8SDavid du Colombier quit("missing pattern");
2443e12c5d1SDavid du Colombier newfile(P_ARG, *argv++);
2453e12c5d1SDavid du Colombier fcomp();
2463e12c5d1SDavid du Colombier }
2473e12c5d1SDavid du Colombier
2483e12c5d1SDavid du Colombier if(depth)
2496c83e8f8SDavid du Colombier quit("Too many {'s");
2503e12c5d1SDavid du Colombier
2513e12c5d1SDavid du Colombier ltab[0].address = rep;
2523e12c5d1SDavid du Colombier
2533e12c5d1SDavid du Colombier dechain();
2543e12c5d1SDavid du Colombier
2553e12c5d1SDavid du Colombier if(argc <= 0)
2563e12c5d1SDavid du Colombier enroll(0); /* Add stdin to cache */
2576c83e8f8SDavid du Colombier else
2586c83e8f8SDavid du Colombier while(--argc >= 0)
2593e12c5d1SDavid du Colombier enroll(*argv++);
2603e12c5d1SDavid du Colombier execute();
2613e12c5d1SDavid du Colombier exits(0);
2623e12c5d1SDavid du Colombier }
2636c83e8f8SDavid du Colombier
2643e12c5d1SDavid du Colombier void
fcomp(void)2653e12c5d1SDavid du Colombier fcomp(void)
2663e12c5d1SDavid du Colombier {
2673e12c5d1SDavid du Colombier int i;
2683e12c5d1SDavid du Colombier Label *lpt;
2696c83e8f8SDavid du Colombier Rune *tp;
2706c83e8f8SDavid du Colombier SedCom *pt, *pt1;
2713e12c5d1SDavid du Colombier static Rune *p = addspace;
2723e12c5d1SDavid du Colombier static SedCom **cmpend[DEPTH]; /* stack of {} operations */
2733e12c5d1SDavid du Colombier
2743e12c5d1SDavid du Colombier while (rline(linebuf, lbend) >= 0) {
2753e12c5d1SDavid du Colombier cp = linebuf;
2763e12c5d1SDavid du Colombier comploop:
2776c83e8f8SDavid du Colombier while(*cp == L' ' || *cp == L'\t')
278219b2ee8SDavid du Colombier cp++;
2796c83e8f8SDavid du Colombier if(*cp == L'\0' || *cp == L'#')
280219b2ee8SDavid du Colombier continue;
2816c83e8f8SDavid du Colombier if(*cp == L';') {
2823e12c5d1SDavid du Colombier cp++;
2833e12c5d1SDavid du Colombier goto comploop;
2843e12c5d1SDavid du Colombier }
2853e12c5d1SDavid du Colombier
2863e12c5d1SDavid du Colombier address(&rep->ad1);
2873e12c5d1SDavid du Colombier if (rep->ad1.type != A_NONE) {
2883e12c5d1SDavid du Colombier if (rep->ad1.type == A_LAST) {
2893e12c5d1SDavid du Colombier if (!lastre)
2906c83e8f8SDavid du Colombier quit("First RE may not be null");
2913e12c5d1SDavid du Colombier rep->ad1.type = A_RE;
2923e12c5d1SDavid du Colombier rep->ad1.rp = lastre;
2933e12c5d1SDavid du Colombier }
2946c83e8f8SDavid du Colombier if(*cp == L',' || *cp == L';') {
2953e12c5d1SDavid du Colombier cp++;
2963e12c5d1SDavid du Colombier address(&rep->ad2);
2973e12c5d1SDavid du Colombier if (rep->ad2.type == A_LAST) {
29838e40d02SDavid du Colombier rep->ad2.type = A_RE;
2993e12c5d1SDavid du Colombier rep->ad2.rp = lastre;
3003e12c5d1SDavid du Colombier }
3013e12c5d1SDavid du Colombier } else
3023e12c5d1SDavid du Colombier rep->ad2.type = A_NONE;
3033e12c5d1SDavid du Colombier }
3046c83e8f8SDavid du Colombier while(*cp == L' ' || *cp == L'\t')
305219b2ee8SDavid du Colombier cp++;
3063e12c5d1SDavid du Colombier
3073e12c5d1SDavid du Colombier swit:
3083e12c5d1SDavid du Colombier switch(*cp++) {
3093e12c5d1SDavid du Colombier default:
3106c83e8f8SDavid du Colombier quit("Unrecognized command: %S", linebuf);
3113e12c5d1SDavid du Colombier
3123e12c5d1SDavid du Colombier case '!':
3133e12c5d1SDavid du Colombier rep->negfl = 1;
3143e12c5d1SDavid du Colombier goto swit;
3153e12c5d1SDavid du Colombier
3163e12c5d1SDavid du Colombier case '{':
3173e12c5d1SDavid du Colombier rep->command = BCOM;
3186c83e8f8SDavid du Colombier rep->negfl = !rep->negfl;
3193e12c5d1SDavid du Colombier cmpend[depth++] = &rep->lb1;
3203e12c5d1SDavid du Colombier if(++rep >= pend)
3216c83e8f8SDavid du Colombier quit("Too many commands: %S", linebuf);
3226c83e8f8SDavid du Colombier if(*cp == '\0')
3236c83e8f8SDavid du Colombier continue;
3243e12c5d1SDavid du Colombier goto comploop;
3253e12c5d1SDavid du Colombier
3263e12c5d1SDavid du Colombier case '}':
3273e12c5d1SDavid du Colombier if(rep->ad1.type != A_NONE)
3286c83e8f8SDavid du Colombier quit(AD0MES, linebuf);
3293e12c5d1SDavid du Colombier if(--depth < 0)
3306c83e8f8SDavid du Colombier quit("Too many }'s");
3313e12c5d1SDavid du Colombier *cmpend[depth] = rep;
3326c83e8f8SDavid du Colombier if(*cp == 0)
3336c83e8f8SDavid du Colombier 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)
3396c83e8f8SDavid du Colombier quit(AD1MES, linebuf);
3403e12c5d1SDavid du Colombier break;
3413e12c5d1SDavid du Colombier
3423e12c5d1SDavid du Colombier case ':':
3433e12c5d1SDavid du Colombier if(rep->ad1.type != A_NONE)
3446c83e8f8SDavid du Colombier quit(AD0MES, linebuf);
3453e12c5d1SDavid du Colombier
3466c83e8f8SDavid du Colombier while(*cp == L' ')
347219b2ee8SDavid du Colombier cp++;
3486c83e8f8SDavid du Colombier tp = lab->uninm;
3496c83e8f8SDavid du Colombier while (*cp && *cp != L';' && *cp != L' ' &&
3506c83e8f8SDavid du Colombier *cp != L'\t' && *cp != L'#') {
351219b2ee8SDavid du Colombier *tp++ = *cp++;
3526c83e8f8SDavid du Colombier if(tp >= &lab->uninm[8])
3536c83e8f8SDavid du Colombier quit(LTL, linebuf);
354219b2ee8SDavid du Colombier }
3556c83e8f8SDavid du Colombier *tp = L'\0';
3563e12c5d1SDavid du Colombier
3576c83e8f8SDavid du Colombier if (*lab->uninm == L'\0') /* no label? */
3586c83e8f8SDavid du Colombier quit(CGMES, L":", linebuf);
3593e12c5d1SDavid du Colombier if(lpt = search(lab)) {
3603e12c5d1SDavid du Colombier if(lpt->address)
3616c83e8f8SDavid du Colombier quit("Duplicate labels: %S", linebuf);
3623e12c5d1SDavid du Colombier } else {
3633e12c5d1SDavid du Colombier lab->chain = 0;
3643e12c5d1SDavid du Colombier lpt = lab;
3653e12c5d1SDavid du Colombier if(++lab >= labend)
3666c83e8f8SDavid du Colombier quit("Too many labels: %S", linebuf);
3673e12c5d1SDavid du Colombier }
3683e12c5d1SDavid du Colombier lpt->address = rep;
3696c83e8f8SDavid du Colombier if (*cp == L'#')
3703e12c5d1SDavid du Colombier continue;
371219b2ee8SDavid du Colombier rep--; /* reuse this slot */
372219b2ee8SDavid du Colombier break;
3733e12c5d1SDavid du Colombier
3743e12c5d1SDavid du Colombier case 'a':
3753e12c5d1SDavid du Colombier rep->command = ACOM;
3763e12c5d1SDavid du Colombier if(rep->ad2.type != A_NONE)
3776c83e8f8SDavid du Colombier quit(AD1MES, linebuf);
3786c83e8f8SDavid du Colombier if(*cp == L'\\')
3796c83e8f8SDavid du Colombier cp++;
3806c83e8f8SDavid du Colombier if(*cp++ != L'\n')
3816c83e8f8SDavid du Colombier quit(CGMES, L"a", linebuf);
3823e12c5d1SDavid du Colombier rep->text = p;
3833e12c5d1SDavid du Colombier p = stext(p, addend);
3843e12c5d1SDavid du Colombier break;
3853e12c5d1SDavid du Colombier case 'c':
3863e12c5d1SDavid du Colombier rep->command = CCOM;
3876c83e8f8SDavid du Colombier if(*cp == L'\\')
3886c83e8f8SDavid du Colombier cp++;
3896c83e8f8SDavid du Colombier if(*cp++ != L'\n')
3906c83e8f8SDavid du Colombier quit(CGMES, L"c", linebuf);
3913e12c5d1SDavid du Colombier rep->text = p;
3923e12c5d1SDavid du Colombier p = stext(p, addend);
3933e12c5d1SDavid du Colombier break;
3943e12c5d1SDavid du Colombier case 'i':
3953e12c5d1SDavid du Colombier rep->command = ICOM;
3963e12c5d1SDavid du Colombier if(rep->ad2.type != A_NONE)
3976c83e8f8SDavid du Colombier quit(AD1MES, linebuf);
3986c83e8f8SDavid du Colombier if(*cp == L'\\')
3996c83e8f8SDavid du Colombier cp++;
4006c83e8f8SDavid du Colombier if(*cp++ != L'\n')
4016c83e8f8SDavid du Colombier quit(CGMES, L"i", linebuf);
4023e12c5d1SDavid du Colombier rep->text = p;
4033e12c5d1SDavid du Colombier p = stext(p, addend);
4043e12c5d1SDavid du Colombier break;
4053e12c5d1SDavid du Colombier
4063e12c5d1SDavid du Colombier case 'g':
4073e12c5d1SDavid du Colombier rep->command = GCOM;
4083e12c5d1SDavid du Colombier break;
4093e12c5d1SDavid du Colombier
4103e12c5d1SDavid du Colombier case 'G':
4113e12c5d1SDavid du Colombier rep->command = CGCOM;
4123e12c5d1SDavid du Colombier break;
4133e12c5d1SDavid du Colombier
4143e12c5d1SDavid du Colombier case 'h':
4153e12c5d1SDavid du Colombier rep->command = HCOM;
4163e12c5d1SDavid du Colombier break;
4173e12c5d1SDavid du Colombier
4183e12c5d1SDavid du Colombier case 'H':
4193e12c5d1SDavid du Colombier rep->command = CHCOM;
4203e12c5d1SDavid du Colombier break;
4213e12c5d1SDavid du Colombier
4223e12c5d1SDavid du Colombier case 't':
4233e12c5d1SDavid du Colombier rep->command = TCOM;
4243e12c5d1SDavid du Colombier goto jtcommon;
4253e12c5d1SDavid du Colombier
4263e12c5d1SDavid du Colombier case 'b':
4273e12c5d1SDavid du Colombier rep->command = BCOM;
4283e12c5d1SDavid du Colombier jtcommon:
4296c83e8f8SDavid du Colombier while(*cp == L' ')
4306c83e8f8SDavid du Colombier cp++;
4316c83e8f8SDavid du Colombier if(*cp == L'\0' || *cp == L';') {
4326c83e8f8SDavid du Colombier /* no label; jump to end */
4333e12c5d1SDavid du Colombier if(pt = ltab[0].chain) {
4346c83e8f8SDavid du Colombier while((pt1 = pt->lb1) != nil)
4353e12c5d1SDavid du Colombier pt = pt1;
4363e12c5d1SDavid du Colombier pt->lb1 = rep;
4373e12c5d1SDavid du Colombier } else
4383e12c5d1SDavid du Colombier ltab[0].chain = rep;
4393e12c5d1SDavid du Colombier break;
4403e12c5d1SDavid du Colombier }
4413e12c5d1SDavid du Colombier
4426c83e8f8SDavid du Colombier /* copy label into lab->uninm */
4436c83e8f8SDavid du Colombier tp = lab->uninm;
4446c83e8f8SDavid du Colombier while((*tp = *cp++) != L'\0' && *tp != L';')
4456c83e8f8SDavid du Colombier if(++tp >= &lab->uninm[8])
4466c83e8f8SDavid du Colombier quit(LTL, linebuf);
4476c83e8f8SDavid du Colombier cp--;
4486c83e8f8SDavid du Colombier *tp = L'\0';
4496c83e8f8SDavid du Colombier
4506c83e8f8SDavid du Colombier if (*lab->uninm == L'\0')
4516c83e8f8SDavid du Colombier /* shouldn't get here */
4526c83e8f8SDavid du Colombier quit(CGMES, L"b or t", linebuf);
4536c83e8f8SDavid du Colombier if((lpt = search(lab)) != nil) {
4546c83e8f8SDavid du Colombier if(lpt->address)
4553e12c5d1SDavid du Colombier rep->lb1 = lpt->address;
4566c83e8f8SDavid du Colombier else {
4576c83e8f8SDavid du Colombier for(pt = lpt->chain; pt != nil &&
4586c83e8f8SDavid du Colombier (pt1 = pt->lb1) != nil; pt = pt1)
4596c83e8f8SDavid du Colombier ;
4606c83e8f8SDavid du Colombier if (pt)
4613e12c5d1SDavid du Colombier pt->lb1 = rep;
4623e12c5d1SDavid du Colombier }
4636c83e8f8SDavid du Colombier } else { /* add new label */
4643e12c5d1SDavid du Colombier lab->chain = rep;
4653e12c5d1SDavid du Colombier lab->address = 0;
4663e12c5d1SDavid du Colombier if(++lab >= labend)
4676c83e8f8SDavid du Colombier quit("Too many labels: %S", linebuf);
4683e12c5d1SDavid du Colombier }
4693e12c5d1SDavid du Colombier break;
4703e12c5d1SDavid du Colombier
4713e12c5d1SDavid du Colombier case 'n':
4723e12c5d1SDavid du Colombier rep->command = NCOM;
4733e12c5d1SDavid du Colombier break;
4743e12c5d1SDavid du Colombier
4753e12c5d1SDavid du Colombier case 'N':
4763e12c5d1SDavid du Colombier rep->command = CNCOM;
4773e12c5d1SDavid du Colombier break;
4783e12c5d1SDavid du Colombier
4793e12c5d1SDavid du Colombier case 'p':
4803e12c5d1SDavid du Colombier rep->command = PCOM;
4813e12c5d1SDavid du Colombier break;
4823e12c5d1SDavid du Colombier
4833e12c5d1SDavid du Colombier case 'P':
4843e12c5d1SDavid du Colombier rep->command = CPCOM;
4853e12c5d1SDavid du Colombier break;
4863e12c5d1SDavid du Colombier
4873e12c5d1SDavid du Colombier case 'r':
4883e12c5d1SDavid du Colombier rep->command = RCOM;
4893e12c5d1SDavid du Colombier if(rep->ad2.type != A_NONE)
4906c83e8f8SDavid du Colombier quit(AD1MES, linebuf);
4916c83e8f8SDavid du Colombier if(*cp++ != L' ')
4926c83e8f8SDavid du Colombier quit(CGMES, L"r", linebuf);
4933e12c5d1SDavid du Colombier rep->text = p;
4943e12c5d1SDavid du Colombier p = stext(p, addend);
4953e12c5d1SDavid du Colombier break;
4963e12c5d1SDavid du Colombier
4973e12c5d1SDavid du Colombier case 'd':
4983e12c5d1SDavid du Colombier rep->command = DCOM;
4993e12c5d1SDavid du Colombier break;
5003e12c5d1SDavid du Colombier
5013e12c5d1SDavid du Colombier case 'D':
5023e12c5d1SDavid du Colombier rep->command = CDCOM;
5033e12c5d1SDavid du Colombier rep->lb1 = pspace;
5043e12c5d1SDavid du Colombier break;
5053e12c5d1SDavid du Colombier
5063e12c5d1SDavid du Colombier case 'q':
5073e12c5d1SDavid du Colombier rep->command = QCOM;
5083e12c5d1SDavid du Colombier if(rep->ad2.type != A_NONE)
5096c83e8f8SDavid du Colombier quit(AD1MES, linebuf);
5103e12c5d1SDavid du Colombier break;
5113e12c5d1SDavid du Colombier
5123e12c5d1SDavid du Colombier case 'l':
5133e12c5d1SDavid du Colombier rep->command = LCOM;
5143e12c5d1SDavid du Colombier break;
5153e12c5d1SDavid du Colombier
5163e12c5d1SDavid du Colombier case 's':
5173e12c5d1SDavid du Colombier rep->command = SCOM;
5183e12c5d1SDavid du Colombier seof = *cp++;
5193e12c5d1SDavid du Colombier if ((rep->re1 = compile()) == 0) {
5203e12c5d1SDavid du Colombier if(!lastre)
5216c83e8f8SDavid du Colombier quit("First RE may not be null.");
5223e12c5d1SDavid du Colombier rep->re1 = lastre;
5233e12c5d1SDavid du Colombier }
5243e12c5d1SDavid du Colombier rep->rhs = p;
5253e12c5d1SDavid du Colombier if((p = compsub(p, addend)) == 0)
5266c83e8f8SDavid du Colombier quit(CGMES, L"s", linebuf);
5276c83e8f8SDavid du Colombier if(*cp == L'g') {
5283e12c5d1SDavid du Colombier cp++;
5293e12c5d1SDavid du Colombier rep->gfl++;
5303e12c5d1SDavid du Colombier } else if(gflag)
5313e12c5d1SDavid du Colombier rep->gfl++;
5323e12c5d1SDavid du Colombier
5336c83e8f8SDavid du Colombier if(*cp == L'p') {
5343e12c5d1SDavid du Colombier cp++;
5353e12c5d1SDavid du Colombier rep->pfl = 1;
5363e12c5d1SDavid du Colombier }
5373e12c5d1SDavid du Colombier
5386c83e8f8SDavid du Colombier if(*cp == L'P') {
5393e12c5d1SDavid du Colombier cp++;
5403e12c5d1SDavid du Colombier rep->pfl = 2;
5413e12c5d1SDavid du Colombier }
5423e12c5d1SDavid du Colombier
5436c83e8f8SDavid du Colombier if(*cp == L'w') {
5443e12c5d1SDavid du Colombier cp++;
5456c83e8f8SDavid du Colombier if(*cp++ != L' ')
5466c83e8f8SDavid du Colombier quit(CGMES, L"s", linebuf);
5473e12c5d1SDavid du Colombier text(fname[nfiles]);
5483e12c5d1SDavid du Colombier for(i = nfiles - 1; i >= 0; i--)
5493e12c5d1SDavid du Colombier if(cmp(fname[nfiles], fname[i]) == 0) {
5503e12c5d1SDavid du Colombier rep->fcode = fcode[i];
5513e12c5d1SDavid du Colombier goto done;
5523e12c5d1SDavid du Colombier }
5533e12c5d1SDavid du Colombier if(nfiles >= MAXFILES)
5546c83e8f8SDavid du Colombier quit("Too many files in w commands 1");
5553e12c5d1SDavid du Colombier rep->fcode = open_file(fname[nfiles]);
5563e12c5d1SDavid du Colombier }
5573e12c5d1SDavid du Colombier break;
5583e12c5d1SDavid du Colombier
5593e12c5d1SDavid du Colombier case 'w':
5603e12c5d1SDavid du Colombier rep->command = WCOM;
5616c83e8f8SDavid du Colombier if(*cp++ != L' ')
5626c83e8f8SDavid du Colombier quit(CGMES, L"w", linebuf);
5633e12c5d1SDavid du Colombier text(fname[nfiles]);
5643e12c5d1SDavid du Colombier for(i = nfiles - 1; i >= 0; i--)
5653e12c5d1SDavid du Colombier if(cmp(fname[nfiles], fname[i]) == 0) {
5663e12c5d1SDavid du Colombier rep->fcode = fcode[i];
5673e12c5d1SDavid du Colombier goto done;
5683e12c5d1SDavid du Colombier }
5693e12c5d1SDavid du Colombier if(nfiles >= MAXFILES){
5703e12c5d1SDavid du Colombier fprint(2, "sed: Too many files in w commands 2 \n");
5716c83e8f8SDavid du Colombier fprint(2, "nfiles = %d; MAXF = %d\n",
5726c83e8f8SDavid du Colombier nfiles, MAXFILES);
5733e12c5d1SDavid du Colombier errexit();
5743e12c5d1SDavid du Colombier }
5753e12c5d1SDavid du Colombier rep->fcode = open_file(fname[nfiles]);
5763e12c5d1SDavid du Colombier break;
5773e12c5d1SDavid du Colombier
5783e12c5d1SDavid du Colombier case 'x':
5793e12c5d1SDavid du Colombier rep->command = XCOM;
5803e12c5d1SDavid du Colombier break;
5813e12c5d1SDavid du Colombier
5823e12c5d1SDavid du Colombier case 'y':
5833e12c5d1SDavid du Colombier rep->command = YCOM;
5843e12c5d1SDavid du Colombier seof = *cp++;
5853e12c5d1SDavid du Colombier if (ycomp(rep) == 0)
5866c83e8f8SDavid du Colombier quit(CGMES, L"y", linebuf);
5873e12c5d1SDavid du Colombier break;
5883e12c5d1SDavid du Colombier
5893e12c5d1SDavid du Colombier }
5903e12c5d1SDavid du Colombier done:
5913e12c5d1SDavid du Colombier if(++rep >= pend)
5926c83e8f8SDavid du Colombier quit("Too many commands, last: %S", linebuf);
5936c83e8f8SDavid du Colombier if(*cp++ != L'\0') {
5946c83e8f8SDavid du Colombier if(cp[-1] == L';')
5953e12c5d1SDavid du Colombier goto comploop;
5966c83e8f8SDavid du Colombier quit(CGMES, cp - 1, linebuf);
5973e12c5d1SDavid du Colombier }
5983e12c5d1SDavid du Colombier }
5993e12c5d1SDavid du Colombier }
6003e12c5d1SDavid du Colombier
6013e12c5d1SDavid du Colombier Biobuf *
open_file(char * name)6023e12c5d1SDavid du Colombier open_file(char *name)
6033e12c5d1SDavid du Colombier {
6043e12c5d1SDavid du Colombier int fd;
6056c83e8f8SDavid du Colombier Biobuf *bp;
6063e12c5d1SDavid du Colombier
6073e12c5d1SDavid du Colombier if ((bp = malloc(sizeof(Biobuf))) == 0)
6086c83e8f8SDavid du Colombier quit("Out of memory");
6093e12c5d1SDavid du Colombier if ((fd = open(name, OWRITE)) < 0 &&
6103e12c5d1SDavid du Colombier (fd = create(name, OWRITE, 0666)) < 0)
6113e12c5d1SDavid du Colombier quit("Cannot create %s", name);
6123e12c5d1SDavid du Colombier Binit(bp, fd, OWRITE);
6133e12c5d1SDavid du Colombier Bseek(bp, 0, 2);
6143e12c5d1SDavid du Colombier fcode[nfiles++] = bp;
6153e12c5d1SDavid du Colombier return bp;
6163e12c5d1SDavid du Colombier }
6173e12c5d1SDavid du Colombier
6183e12c5d1SDavid du Colombier Rune *
compsub(Rune * rhs,Rune * end)6193e12c5d1SDavid du Colombier compsub(Rune *rhs, Rune *end)
6203e12c5d1SDavid du Colombier {
6213e12c5d1SDavid du Colombier Rune r;
6223e12c5d1SDavid du Colombier
6233e12c5d1SDavid du Colombier while ((r = *cp++) != '\0') {
6243e12c5d1SDavid du Colombier if(r == '\\') {
6253e12c5d1SDavid du Colombier if (rhs < end)
626*82726826SDavid du Colombier *rhs++ = Runemax;
6273e12c5d1SDavid du Colombier else
6283e12c5d1SDavid du Colombier return 0;
6293e12c5d1SDavid du Colombier r = *cp++;
6303e12c5d1SDavid du Colombier if(r == 'n')
6313e12c5d1SDavid du Colombier r = '\n';
6323e12c5d1SDavid du Colombier } else {
6333e12c5d1SDavid du Colombier if(r == seof) {
6343e12c5d1SDavid du Colombier if (rhs < end)
6353e12c5d1SDavid du Colombier *rhs++ = '\0';
6363e12c5d1SDavid du Colombier else
6373e12c5d1SDavid du Colombier return 0;
6383e12c5d1SDavid du Colombier return rhs;
6393e12c5d1SDavid du Colombier }
6403e12c5d1SDavid du Colombier }
6413e12c5d1SDavid du Colombier if (rhs < end)
6423e12c5d1SDavid du Colombier *rhs++ = r;
6433e12c5d1SDavid du Colombier else
6443e12c5d1SDavid du Colombier return 0;
6453e12c5d1SDavid du Colombier }
6463e12c5d1SDavid du Colombier return 0;
6473e12c5d1SDavid du Colombier }
6483e12c5d1SDavid du Colombier
6493e12c5d1SDavid du Colombier Reprog *
compile(void)6503e12c5d1SDavid du Colombier compile(void)
6513e12c5d1SDavid du Colombier {
6523e12c5d1SDavid du Colombier Rune c;
6533e12c5d1SDavid du Colombier char *ep;
6543e12c5d1SDavid du Colombier char expbuf[512];
6553e12c5d1SDavid du Colombier
6566c83e8f8SDavid du Colombier if((c = *cp++) == seof) /* L'//' */
6573e12c5d1SDavid du Colombier return 0;
6583e12c5d1SDavid du Colombier ep = expbuf;
6593e12c5d1SDavid du Colombier do {
6606c83e8f8SDavid du Colombier if (c == L'\0' || c == L'\n')
6616c83e8f8SDavid du Colombier quit(TMMES, linebuf);
6626c83e8f8SDavid du Colombier if (c == L'\\') {
6633e12c5d1SDavid du Colombier if (ep >= expbuf+sizeof(expbuf))
6646c83e8f8SDavid du Colombier quit(TMMES, linebuf);
6653e12c5d1SDavid du Colombier ep += runetochar(ep, &c);
6666c83e8f8SDavid du Colombier if ((c = *cp++) == L'n')
6676c83e8f8SDavid du Colombier c = L'\n';
6683e12c5d1SDavid du Colombier }
6693e12c5d1SDavid du Colombier if (ep >= expbuf + sizeof(expbuf))
6706c83e8f8SDavid du Colombier quit(TMMES, linebuf);
6713e12c5d1SDavid du Colombier ep += runetochar(ep, &c);
6723e12c5d1SDavid du Colombier } while ((c = *cp++) != seof);
6733e12c5d1SDavid du Colombier *ep = 0;
6743e12c5d1SDavid du Colombier return lastre = regcomp(expbuf);
6753e12c5d1SDavid du Colombier }
6763e12c5d1SDavid du Colombier
6773e12c5d1SDavid du Colombier void
regerror(char * s)6783e12c5d1SDavid du Colombier regerror(char *s)
6793e12c5d1SDavid du Colombier {
6803e12c5d1SDavid du Colombier USED(s);
6816c83e8f8SDavid du Colombier quit(CGMES, L"r.e.-using", linebuf);
6823e12c5d1SDavid du Colombier }
6833e12c5d1SDavid du Colombier
6843e12c5d1SDavid du Colombier void
newfile(enum PTYPE type,char * name)6853e12c5d1SDavid du Colombier newfile(enum PTYPE type, char *name)
6863e12c5d1SDavid du Colombier {
6873e12c5d1SDavid du Colombier if (type == P_ARG)
6883e12c5d1SDavid du Colombier prog.curr = name;
6893e12c5d1SDavid du Colombier else if ((prog.bp = Bopen(name, OREAD)) == 0)
6903e12c5d1SDavid du Colombier quit("Cannot open pattern-file: %s\n", name);
6913e12c5d1SDavid du Colombier prog.type = type;
6923e12c5d1SDavid du Colombier }
6933e12c5d1SDavid du Colombier
6943e12c5d1SDavid du Colombier int
rline(Rune * buf,Rune * end)6953e12c5d1SDavid du Colombier rline(Rune *buf, Rune *end)
6963e12c5d1SDavid du Colombier {
6973e12c5d1SDavid du Colombier long c;
6983e12c5d1SDavid du Colombier Rune r;
6993e12c5d1SDavid du Colombier
7003e12c5d1SDavid du Colombier while ((c = getrune()) >= 0) {
7013e12c5d1SDavid du Colombier r = c;
7023e12c5d1SDavid du Colombier if (r == '\\') {
7033e12c5d1SDavid du Colombier if (buf <= end)
7043e12c5d1SDavid du Colombier *buf++ = r;
7053e12c5d1SDavid du Colombier if ((c = getrune()) < 0)
7063e12c5d1SDavid du Colombier break;
7073e12c5d1SDavid du Colombier r = c;
7083e12c5d1SDavid du Colombier } else if (r == '\n') {
7093e12c5d1SDavid du Colombier *buf = '\0';
7106c83e8f8SDavid du Colombier return 1;
7113e12c5d1SDavid du Colombier }
7123e12c5d1SDavid du Colombier if (buf <= end)
7133e12c5d1SDavid du Colombier *buf++ = r;
7143e12c5d1SDavid du Colombier }
7153e12c5d1SDavid du Colombier *buf = '\0';
7166c83e8f8SDavid du Colombier return -1;
7173e12c5d1SDavid du Colombier }
7183e12c5d1SDavid du Colombier
7193e12c5d1SDavid du Colombier long
getrune(void)7203e12c5d1SDavid du Colombier getrune(void)
7213e12c5d1SDavid du Colombier {
7223e12c5d1SDavid du Colombier long c;
7233e12c5d1SDavid du Colombier Rune r;
7246c83e8f8SDavid du Colombier char *p;
7253e12c5d1SDavid du Colombier
7263e12c5d1SDavid du Colombier if (prog.type == P_ARG) {
7273e12c5d1SDavid du Colombier if ((p = prog.curr) != 0) {
7283e12c5d1SDavid du Colombier if (*p) {
7293e12c5d1SDavid du Colombier prog.curr += chartorune(&r, p);
7303e12c5d1SDavid du Colombier c = r;
7313e12c5d1SDavid du Colombier } else {
7323e12c5d1SDavid du Colombier c = '\n'; /* fake an end-of-line */
7333e12c5d1SDavid du Colombier prog.curr = 0;
7343e12c5d1SDavid du Colombier }
7353e12c5d1SDavid du Colombier } else
7363e12c5d1SDavid du Colombier c = -1;
7373e12c5d1SDavid du Colombier } else if ((c = Bgetrune(prog.bp)) < 0)
738219b2ee8SDavid du Colombier Bterm(prog.bp);
7393e12c5d1SDavid du Colombier return c;
7403e12c5d1SDavid du Colombier }
7413e12c5d1SDavid du Colombier
7423e12c5d1SDavid du Colombier void
address(Addr * ap)7433e12c5d1SDavid du Colombier address(Addr *ap)
7443e12c5d1SDavid du Colombier {
7453e12c5d1SDavid du Colombier int c;
7463e12c5d1SDavid du Colombier long lno;
7473e12c5d1SDavid du Colombier
7483e12c5d1SDavid du Colombier if((c = *cp++) == '$')
7493e12c5d1SDavid du Colombier ap->type = A_DOL;
7503e12c5d1SDavid du Colombier else if(c == '/') {
7513e12c5d1SDavid du Colombier seof = c;
7523e12c5d1SDavid du Colombier if (ap->rp = compile())
7533e12c5d1SDavid du Colombier ap->type = A_RE;
7543e12c5d1SDavid du Colombier else
7553e12c5d1SDavid du Colombier ap->type = A_LAST;
7563e12c5d1SDavid du Colombier }
7573e12c5d1SDavid du Colombier else if (c >= '0' && c <= '9') {
7583e12c5d1SDavid du Colombier lno = c - '0';
7593e12c5d1SDavid du Colombier while ((c = *cp) >= '0' && c <= '9')
7603e12c5d1SDavid du Colombier lno = lno*10 + *cp++ - '0';
7613e12c5d1SDavid du Colombier if(!lno)
7623e12c5d1SDavid du Colombier quit("line number 0 is illegal",0);
7633e12c5d1SDavid du Colombier ap->type = A_LINE;
7643e12c5d1SDavid du Colombier ap->line = lno;
7653e12c5d1SDavid du Colombier }
7663e12c5d1SDavid du Colombier else {
7673e12c5d1SDavid du Colombier cp--;
7683e12c5d1SDavid du Colombier ap->type = A_NONE;
7693e12c5d1SDavid du Colombier }
7703e12c5d1SDavid du Colombier }
7713e12c5d1SDavid du Colombier
cmp(char * a,char * b)7723e12c5d1SDavid du Colombier cmp(char *a, char *b) /* compare characters */
7733e12c5d1SDavid du Colombier {
7743e12c5d1SDavid du Colombier while(*a == *b++)
7753e12c5d1SDavid du Colombier if (*a == '\0')
7766c83e8f8SDavid du Colombier return 0;
7776c83e8f8SDavid du Colombier else
7786c83e8f8SDavid du Colombier a++;
7796c83e8f8SDavid du Colombier return 1;
7803e12c5d1SDavid du Colombier }
rcmp(Rune * a,Rune * b)7813e12c5d1SDavid du Colombier rcmp(Rune *a, Rune *b) /* compare runes */
7823e12c5d1SDavid du Colombier {
7833e12c5d1SDavid du Colombier while(*a == *b++)
7843e12c5d1SDavid du Colombier if (*a == '\0')
7856c83e8f8SDavid du Colombier return 0;
7866c83e8f8SDavid du Colombier else
7876c83e8f8SDavid du Colombier a++;
7886c83e8f8SDavid du Colombier return 1;
7893e12c5d1SDavid du Colombier }
7903e12c5d1SDavid du Colombier
7913e12c5d1SDavid du Colombier char *
text(char * p)7923e12c5d1SDavid du Colombier text(char *p) /* extract character string */
7933e12c5d1SDavid du Colombier {
7943e12c5d1SDavid du Colombier Rune r;
7953e12c5d1SDavid du Colombier
7966c83e8f8SDavid du Colombier while(*cp == ' ' || *cp == '\t')
7973e12c5d1SDavid du Colombier cp++;
7983e12c5d1SDavid du Colombier while (*cp) {
7996c83e8f8SDavid du Colombier if ((r = *cp++) == '\\' && (r = *cp++) == '\0')
8006c83e8f8SDavid du Colombier break;
8013e12c5d1SDavid du Colombier if (r == '\n')
8026c83e8f8SDavid du Colombier while (*cp == ' ' || *cp == '\t')
8033e12c5d1SDavid du Colombier cp++;
8043e12c5d1SDavid du Colombier p += runetochar(p, &r);
8053e12c5d1SDavid du Colombier }
8063e12c5d1SDavid du Colombier *p++ = '\0';
8073e12c5d1SDavid du Colombier return p;
8083e12c5d1SDavid du Colombier }
8093e12c5d1SDavid du Colombier
8103e12c5d1SDavid du Colombier Rune *
stext(Rune * p,Rune * end)8113e12c5d1SDavid du Colombier stext(Rune *p, Rune *end) /* extract rune string */
8123e12c5d1SDavid du Colombier {
8136c83e8f8SDavid du Colombier while(*cp == L' ' || *cp == L'\t')
8143e12c5d1SDavid du Colombier cp++;
8153e12c5d1SDavid du Colombier while (*cp) {
8166c83e8f8SDavid du Colombier if (*cp == L'\\' && *++cp == L'\0')
8173e12c5d1SDavid du Colombier break;
8183e12c5d1SDavid du Colombier if (p >= end-1)
8196c83e8f8SDavid du Colombier quit(TMMES, linebuf);
8206c83e8f8SDavid du Colombier if ((*p++ = *cp++) == L'\n')
8216c83e8f8SDavid du Colombier while(*cp == L' ' || *cp == L'\t')
8223e12c5d1SDavid du Colombier cp++;
8233e12c5d1SDavid du Colombier }
8243e12c5d1SDavid du Colombier *p++ = 0;
8253e12c5d1SDavid du Colombier return p;
8263e12c5d1SDavid du Colombier }
8273e12c5d1SDavid du Colombier
8283e12c5d1SDavid du Colombier
8293e12c5d1SDavid du Colombier Label *
search(Label * ptr)8303e12c5d1SDavid du Colombier search(Label *ptr)
8313e12c5d1SDavid du Colombier {
8323e12c5d1SDavid du Colombier Label *rp;
8333e12c5d1SDavid du Colombier
8343e12c5d1SDavid du Colombier for (rp = ltab; rp < ptr; rp++)
8356c83e8f8SDavid du Colombier if(rcmp(rp->uninm, ptr->uninm) == 0)
8363e12c5d1SDavid du Colombier return(rp);
8373e12c5d1SDavid du Colombier return(0);
8383e12c5d1SDavid du Colombier }
8393e12c5d1SDavid du Colombier
8403e12c5d1SDavid du Colombier void
dechain(void)8413e12c5d1SDavid du Colombier dechain(void)
8423e12c5d1SDavid du Colombier {
8433e12c5d1SDavid du Colombier Label *lptr;
8443e12c5d1SDavid du Colombier SedCom *rptr, *trptr;
8453e12c5d1SDavid du Colombier
8463e12c5d1SDavid du Colombier for(lptr = ltab; lptr < lab; lptr++) {
8473e12c5d1SDavid du Colombier if(lptr->address == 0)
8486c83e8f8SDavid du Colombier quit("Undefined label: %S", lptr->uninm);
8493e12c5d1SDavid du Colombier if(lptr->chain) {
8503e12c5d1SDavid du Colombier rptr = lptr->chain;
8516c83e8f8SDavid du Colombier while((trptr = rptr->lb1) != nil) {
8523e12c5d1SDavid du Colombier rptr->lb1 = lptr->address;
8533e12c5d1SDavid du Colombier rptr = trptr;
8543e12c5d1SDavid du Colombier }
8553e12c5d1SDavid du Colombier rptr->lb1 = lptr->address;
8563e12c5d1SDavid du Colombier }
8573e12c5d1SDavid du Colombier }
8583e12c5d1SDavid du Colombier }
8593e12c5d1SDavid du Colombier
8603e12c5d1SDavid du Colombier int
ycomp(SedCom * r)8613e12c5d1SDavid du Colombier ycomp(SedCom *r)
8623e12c5d1SDavid du Colombier {
8633e12c5d1SDavid du Colombier int i;
8646c83e8f8SDavid du Colombier Rune *rp, *sp, *tsp;
8656c83e8f8SDavid du Colombier Rune c, highc;
8663e12c5d1SDavid du Colombier
8673e12c5d1SDavid du Colombier highc = 0;
8683e12c5d1SDavid du Colombier for(tsp = cp; *tsp != seof; tsp++) {
8696c83e8f8SDavid du Colombier if(*tsp == L'\\')
8703e12c5d1SDavid du Colombier tsp++;
8716c83e8f8SDavid du Colombier if(*tsp == L'\n' || *tsp == L'\0')
8726c83e8f8SDavid du Colombier return 0;
8736c83e8f8SDavid du Colombier if (*tsp > highc)
8746c83e8f8SDavid du Colombier highc = *tsp;
8753e12c5d1SDavid du Colombier }
8763e12c5d1SDavid du Colombier tsp++;
8776c83e8f8SDavid du Colombier if ((rp = r->text = (Rune *)malloc(sizeof(Rune) * (highc+2))) == nil)
8786c83e8f8SDavid du Colombier quit("Out of memory");
8793e12c5d1SDavid du Colombier *rp++ = highc; /* save upper bound */
8803e12c5d1SDavid du Colombier for (i = 0; i <= highc; i++)
8813e12c5d1SDavid du Colombier rp[i] = i;
8823e12c5d1SDavid du Colombier sp = cp;
8833e12c5d1SDavid du Colombier while((c = *sp++) != seof) {
8846c83e8f8SDavid du Colombier if(c == L'\\' && *sp == L'n') {
8853e12c5d1SDavid du Colombier sp++;
8866c83e8f8SDavid du Colombier c = L'\n';
8873e12c5d1SDavid du Colombier }
8886c83e8f8SDavid du Colombier if((rp[c] = *tsp++) == L'\\' && *tsp == L'n') {
8896c83e8f8SDavid du Colombier rp[c] = L'\n';
8903e12c5d1SDavid du Colombier tsp++;
8913e12c5d1SDavid du Colombier }
8926c83e8f8SDavid du Colombier if(rp[c] == seof || rp[c] == L'\0') {
8933e12c5d1SDavid du Colombier free(r->re1);
8946c83e8f8SDavid du Colombier r->re1 = nil;
8956c83e8f8SDavid du Colombier return 0;
8963e12c5d1SDavid du Colombier }
8973e12c5d1SDavid du Colombier }
8983e12c5d1SDavid du Colombier if(*tsp != seof) {
8993e12c5d1SDavid du Colombier free(r->re1);
9006c83e8f8SDavid du Colombier r->re1 = nil;
9016c83e8f8SDavid du Colombier return 0;
9023e12c5d1SDavid du Colombier }
9033e12c5d1SDavid du Colombier cp = tsp+1;
9046c83e8f8SDavid du Colombier return 1;
9053e12c5d1SDavid du Colombier }
9063e12c5d1SDavid du Colombier
9073e12c5d1SDavid du Colombier void
execute(void)9083e12c5d1SDavid du Colombier execute(void)
9093e12c5d1SDavid du Colombier {
9103e12c5d1SDavid du Colombier SedCom *ipc;
9113e12c5d1SDavid du Colombier
9123e12c5d1SDavid du Colombier while (spend = gline(linebuf)){
9133e12c5d1SDavid du Colombier for(ipc = pspace; ipc->command; ) {
9143e12c5d1SDavid du Colombier if (!executable(ipc)) {
9153e12c5d1SDavid du Colombier ipc++;
9163e12c5d1SDavid du Colombier continue;
9173e12c5d1SDavid du Colombier }
9183e12c5d1SDavid du Colombier command(ipc);
919219b2ee8SDavid du Colombier
9203e12c5d1SDavid du Colombier if(delflag)
9213e12c5d1SDavid du Colombier break;
9223e12c5d1SDavid du Colombier if(jflag) {
9233e12c5d1SDavid du Colombier jflag = 0;
9243e12c5d1SDavid du Colombier if((ipc = ipc->lb1) == 0)
9253e12c5d1SDavid du Colombier break;
9263e12c5d1SDavid du Colombier } else
9273e12c5d1SDavid du Colombier ipc++;
9283e12c5d1SDavid du Colombier }
9293e12c5d1SDavid du Colombier if(!nflag && !delflag)
9303e12c5d1SDavid du Colombier putline(&fout, linebuf, spend - linebuf);
9316c83e8f8SDavid du Colombier if(aptr > abuf)
9323e12c5d1SDavid du Colombier arout();
9333e12c5d1SDavid du Colombier delflag = 0;
9343e12c5d1SDavid du Colombier }
9353e12c5d1SDavid du Colombier }
9366c83e8f8SDavid du Colombier
9373e12c5d1SDavid du Colombier /* determine if a statement should be applied to an input line */
9383e12c5d1SDavid du Colombier int
executable(SedCom * ipc)9393e12c5d1SDavid du Colombier executable(SedCom *ipc)
9403e12c5d1SDavid du Colombier {
9413e12c5d1SDavid du Colombier if (ipc->active) { /* Addr1 satisfied - accept until Addr2 */
9423e12c5d1SDavid du Colombier if (ipc->active == 1) /* Second line */
9433e12c5d1SDavid du Colombier ipc->active = 2;
9443e12c5d1SDavid du Colombier switch(ipc->ad2.type) {
9453e12c5d1SDavid du Colombier case A_NONE: /* No second addr; use first */
9463e12c5d1SDavid du Colombier ipc->active = 0;
9473e12c5d1SDavid du Colombier break;
9483e12c5d1SDavid du Colombier case A_DOL: /* Accept everything */
9493e12c5d1SDavid du Colombier return !ipc->negfl;
9503e12c5d1SDavid du Colombier case A_LINE: /* Line at end of range? */
9513e12c5d1SDavid du Colombier if (lnum <= ipc->ad2.line) {
9523e12c5d1SDavid du Colombier if (ipc->ad2.line == lnum)
9533e12c5d1SDavid du Colombier ipc->active = 0;
9543e12c5d1SDavid du Colombier return !ipc->negfl;
9553e12c5d1SDavid du Colombier }
9563e12c5d1SDavid du Colombier ipc->active = 0; /* out of range */
9573e12c5d1SDavid du Colombier return ipc->negfl;
9583e12c5d1SDavid du Colombier case A_RE: /* Check for matching R.E. */
9593e12c5d1SDavid du Colombier if (match(ipc->ad2.rp, linebuf))
9603e12c5d1SDavid du Colombier ipc->active = 0;
9613e12c5d1SDavid du Colombier return !ipc->negfl;
9626c83e8f8SDavid du Colombier default:
9636c83e8f8SDavid du Colombier quit("Internal error");
9643e12c5d1SDavid du Colombier }
9653e12c5d1SDavid du Colombier }
9663e12c5d1SDavid du Colombier switch (ipc->ad1.type) { /* Check first address */
9673e12c5d1SDavid du Colombier case A_NONE: /* Everything matches */
9683e12c5d1SDavid du Colombier return !ipc->negfl;
9693e12c5d1SDavid du Colombier case A_DOL: /* Only last line */
9703e12c5d1SDavid du Colombier if (dolflag)
9713e12c5d1SDavid du Colombier return !ipc->negfl;
9723e12c5d1SDavid du Colombier break;
9733e12c5d1SDavid du Colombier case A_LINE: /* Check line number */
9743e12c5d1SDavid du Colombier if (ipc->ad1.line == lnum) {
9753e12c5d1SDavid du Colombier ipc->active = 1; /* In range */
9763e12c5d1SDavid du Colombier return !ipc->negfl;
9773e12c5d1SDavid du Colombier }
9783e12c5d1SDavid du Colombier break;
9793e12c5d1SDavid du Colombier case A_RE: /* Check R.E. */
9803e12c5d1SDavid du Colombier if (match(ipc->ad1.rp, linebuf)) {
9813e12c5d1SDavid du Colombier ipc->active = 1; /* In range */
9823e12c5d1SDavid du Colombier return !ipc->negfl;
9833e12c5d1SDavid du Colombier }
9843e12c5d1SDavid du Colombier break;
9853e12c5d1SDavid du Colombier default:
9866c83e8f8SDavid du Colombier quit("Internal error");
9873e12c5d1SDavid du Colombier }
9883e12c5d1SDavid du Colombier return ipc->negfl;
9893e12c5d1SDavid du Colombier }
9906c83e8f8SDavid du Colombier
9916c83e8f8SDavid du Colombier int
match(Reprog * pattern,Rune * buf)9923e12c5d1SDavid du Colombier match(Reprog *pattern, Rune *buf)
9933e12c5d1SDavid du Colombier {
9943e12c5d1SDavid du Colombier if (!pattern)
9953e12c5d1SDavid du Colombier return 0;
9963e12c5d1SDavid du Colombier subexp[0].rsp = buf;
9973e12c5d1SDavid du Colombier subexp[0].ep = 0;
9984eeb7838SDavid du Colombier if (rregexec(pattern, linebuf, subexp, MAXSUB) > 0) {
9993e12c5d1SDavid du Colombier loc1 = subexp[0].rsp;
10003e12c5d1SDavid du Colombier loc2 = subexp[0].rep;
10013e12c5d1SDavid du Colombier return 1;
10023e12c5d1SDavid du Colombier }
10033e12c5d1SDavid du Colombier loc1 = loc2 = 0;
10043e12c5d1SDavid du Colombier return 0;
10053e12c5d1SDavid du Colombier }
10066c83e8f8SDavid du Colombier
10076c83e8f8SDavid du Colombier int
substitute(SedCom * ipc)10083e12c5d1SDavid du Colombier substitute(SedCom *ipc)
10093e12c5d1SDavid du Colombier {
10107dd7cddfSDavid du Colombier int len;
10117dd7cddfSDavid du Colombier
10127dd7cddfSDavid du Colombier if(!match(ipc->re1, linebuf))
10133e12c5d1SDavid du Colombier return 0;
10147dd7cddfSDavid du Colombier
10157dd7cddfSDavid du Colombier /*
10167dd7cddfSDavid du Colombier * we have at least one match. some patterns, e.g. '$' or '^', can
10176c83e8f8SDavid du Colombier * produce 0-length matches, so during a global substitute we must
10186c83e8f8SDavid du Colombier * bump to the character after a 0-length match to keep from looping.
10197dd7cddfSDavid du Colombier */
10207dd7cddfSDavid du Colombier sflag = 1;
10217dd7cddfSDavid du Colombier if(ipc->gfl == 0) /* single substitution */
10227dd7cddfSDavid du Colombier dosub(ipc->rhs);
10237dd7cddfSDavid du Colombier else
10247dd7cddfSDavid du Colombier do{ /* global substitution */
10257dd7cddfSDavid du Colombier len = loc2 - loc1; /* length of match */
10267dd7cddfSDavid du Colombier dosub(ipc->rhs); /* dosub moves loc2 */
10277dd7cddfSDavid du Colombier if(*loc2 == 0) /* end of string */
10287dd7cddfSDavid du Colombier break;
10297dd7cddfSDavid du Colombier if(len == 0) /* zero-length R.E. match */
10306c83e8f8SDavid du Colombier loc2++; /* bump over 0-length match */
10317dd7cddfSDavid du Colombier if(*loc2 == 0) /* end of string */
10327dd7cddfSDavid du Colombier break;
10337dd7cddfSDavid du Colombier } while(match(ipc->re1, loc2));
10347dd7cddfSDavid du Colombier return 1;
10353e12c5d1SDavid du Colombier }
10363e12c5d1SDavid du Colombier
10373e12c5d1SDavid du Colombier void
dosub(Rune * rhsbuf)10383e12c5d1SDavid du Colombier dosub(Rune *rhsbuf)
10393e12c5d1SDavid du Colombier {
10403e12c5d1SDavid du Colombier int c, n;
10416c83e8f8SDavid du Colombier Rune *lp, *sp, *rp;
10423e12c5d1SDavid du Colombier
10433e12c5d1SDavid du Colombier lp = linebuf;
10443e12c5d1SDavid du Colombier sp = genbuf;
10453e12c5d1SDavid du Colombier rp = rhsbuf;
10463e12c5d1SDavid du Colombier while (lp < loc1)
10473e12c5d1SDavid du Colombier *sp++ = *lp++;
10483e12c5d1SDavid du Colombier while(c = *rp++) {
10493e12c5d1SDavid du Colombier if (c == '&') {
10503e12c5d1SDavid du Colombier sp = place(sp, loc1, loc2);
10513e12c5d1SDavid du Colombier continue;
10523e12c5d1SDavid du Colombier }
1053*82726826SDavid du Colombier if (c == Runemax && (c = *rp++) >= '1' && c < MAXSUB + '0') {
10543e12c5d1SDavid du Colombier n = c-'0';
10553e12c5d1SDavid du Colombier if (subexp[n].rsp && subexp[n].rep) {
10563e12c5d1SDavid du Colombier sp = place(sp, subexp[n].rsp, subexp[n].rep);
10573e12c5d1SDavid du Colombier continue;
10583e12c5d1SDavid du Colombier }
10593e12c5d1SDavid du Colombier else {
10603e12c5d1SDavid du Colombier fprint(2, "sed: Invalid back reference \\%d\n",n);
10613e12c5d1SDavid du Colombier errexit();
10623e12c5d1SDavid du Colombier }
10633e12c5d1SDavid du Colombier }
10643e12c5d1SDavid du Colombier *sp++ = c;
10653e12c5d1SDavid du Colombier if (sp >= &genbuf[LBSIZE])
10663e12c5d1SDavid du Colombier fprint(2, "sed: Output line too long.\n");
10673e12c5d1SDavid du Colombier }
10683e12c5d1SDavid du Colombier lp = loc2;
10693e12c5d1SDavid du Colombier loc2 = sp - genbuf + linebuf;
10703e12c5d1SDavid du Colombier while (*sp++ = *lp++)
10713e12c5d1SDavid du Colombier if (sp >= &genbuf[LBSIZE])
10723e12c5d1SDavid du Colombier fprint(2, "sed: Output line too long.\n");
10733e12c5d1SDavid du Colombier lp = linebuf;
10743e12c5d1SDavid du Colombier sp = genbuf;
10753e12c5d1SDavid du Colombier while (*lp++ = *sp++)
10763e12c5d1SDavid du Colombier ;
10773e12c5d1SDavid du Colombier spend = lp - 1;
10783e12c5d1SDavid du Colombier }
10793e12c5d1SDavid du Colombier
10803e12c5d1SDavid du Colombier Rune *
place(Rune * sp,Rune * l1,Rune * l2)10813e12c5d1SDavid du Colombier place(Rune *sp, Rune *l1, Rune *l2)
10823e12c5d1SDavid du Colombier {
10833e12c5d1SDavid du Colombier while (l1 < l2) {
10843e12c5d1SDavid du Colombier *sp++ = *l1++;
10853e12c5d1SDavid du Colombier if (sp >= &genbuf[LBSIZE])
10863e12c5d1SDavid du Colombier fprint(2, "sed: Output line too long.\n");
10873e12c5d1SDavid du Colombier }
10886c83e8f8SDavid du Colombier return sp;
10893e12c5d1SDavid du Colombier }
10903e12c5d1SDavid du Colombier
10913e12c5d1SDavid du Colombier char *
trans(int c)10923e12c5d1SDavid du Colombier trans(int c)
10933e12c5d1SDavid du Colombier {
10943e12c5d1SDavid du Colombier static char buf[] = "\\x0000";
10953e12c5d1SDavid du Colombier static char hex[] = "0123456789abcdef";
10963e12c5d1SDavid du Colombier
10973e12c5d1SDavid du Colombier switch(c) {
10983e12c5d1SDavid du Colombier case '\b':
10993e12c5d1SDavid du Colombier return "\\b";
11003e12c5d1SDavid du Colombier case '\n':
11013e12c5d1SDavid du Colombier return "\\n";
11023e12c5d1SDavid du Colombier case '\r':
11033e12c5d1SDavid du Colombier return "\\r";
11043e12c5d1SDavid du Colombier case '\t':
11053e12c5d1SDavid du Colombier return "\\t";
11063e12c5d1SDavid du Colombier case '\\':
11073e12c5d1SDavid du Colombier return "\\\\";
11083e12c5d1SDavid du Colombier }
11093e12c5d1SDavid du Colombier buf[2] = hex[(c>>12)&0xF];
11103e12c5d1SDavid du Colombier buf[3] = hex[(c>>8)&0xF];
11113e12c5d1SDavid du Colombier buf[4] = hex[(c>>4)&0xF];
11123e12c5d1SDavid du Colombier buf[5] = hex[c&0xF];
11133e12c5d1SDavid du Colombier return buf;
11143e12c5d1SDavid du Colombier }
11153e12c5d1SDavid du Colombier
11163e12c5d1SDavid du Colombier void
command(SedCom * ipc)11173e12c5d1SDavid du Colombier command(SedCom *ipc)
11183e12c5d1SDavid du Colombier {
11193e12c5d1SDavid du Colombier int i, c;
11203e12c5d1SDavid du Colombier char *ucp;
11216c83e8f8SDavid du Colombier Rune *execp, *p1, *p2, *rp;
11223e12c5d1SDavid du Colombier
11233e12c5d1SDavid du Colombier switch(ipc->command) {
11243e12c5d1SDavid du Colombier case ACOM:
11253e12c5d1SDavid du Colombier *aptr++ = ipc;
11266c83e8f8SDavid du Colombier if(aptr >= abuf+MAXADDS)
11273e12c5d1SDavid du Colombier quit("sed: Too many appends after line %ld\n",
11283e12c5d1SDavid du Colombier (char *)lnum);
11293e12c5d1SDavid du Colombier *aptr = 0;
11303e12c5d1SDavid du Colombier break;
11313e12c5d1SDavid du Colombier case CCOM:
11323e12c5d1SDavid du Colombier delflag = 1;
11333e12c5d1SDavid du Colombier if(ipc->active == 1) {
11343e12c5d1SDavid du Colombier for(rp = ipc->text; *rp; rp++)
11353e12c5d1SDavid du Colombier Bputrune(&fout, *rp);
11363e12c5d1SDavid du Colombier Bputc(&fout, '\n');
11373e12c5d1SDavid du Colombier }
11383e12c5d1SDavid du Colombier break;
11393e12c5d1SDavid du Colombier case DCOM:
11403e12c5d1SDavid du Colombier delflag++;
11413e12c5d1SDavid du Colombier break;
11423e12c5d1SDavid du Colombier case CDCOM:
11433e12c5d1SDavid du Colombier p1 = p2 = linebuf;
11443e12c5d1SDavid du Colombier while(*p1 != '\n') {
11453e12c5d1SDavid du Colombier if(*p1++ == 0) {
11463e12c5d1SDavid du Colombier delflag++;
11473e12c5d1SDavid du Colombier return;
11483e12c5d1SDavid du Colombier }
11493e12c5d1SDavid du Colombier }
11503e12c5d1SDavid du Colombier p1++;
11513e12c5d1SDavid du Colombier while(*p2++ = *p1++)
11523e12c5d1SDavid du Colombier ;
11533e12c5d1SDavid du Colombier spend = p2 - 1;
11543e12c5d1SDavid du Colombier jflag++;
11553e12c5d1SDavid du Colombier break;
11563e12c5d1SDavid du Colombier case EQCOM:
11573e12c5d1SDavid du Colombier Bprint(&fout, "%ld\n", lnum);
11583e12c5d1SDavid du Colombier break;
11593e12c5d1SDavid du Colombier case GCOM:
11603e12c5d1SDavid du Colombier p1 = linebuf;
11613e12c5d1SDavid du Colombier p2 = holdsp;
11623e12c5d1SDavid du Colombier while(*p1++ = *p2++)
11633e12c5d1SDavid du Colombier ;
11643e12c5d1SDavid du Colombier spend = p1 - 1;
11653e12c5d1SDavid du Colombier break;
11663e12c5d1SDavid du Colombier case CGCOM:
11673e12c5d1SDavid du Colombier *spend++ = '\n';
11683e12c5d1SDavid du Colombier p1 = spend;
11693e12c5d1SDavid du Colombier p2 = holdsp;
11703e12c5d1SDavid du Colombier while(*p1++ = *p2++)
11713e12c5d1SDavid du Colombier if(p1 >= lbend)
11723e12c5d1SDavid du Colombier break;
11733e12c5d1SDavid du Colombier spend = p1 - 1;
11743e12c5d1SDavid du Colombier break;
11753e12c5d1SDavid du Colombier case HCOM:
11763e12c5d1SDavid du Colombier p1 = holdsp;
11773e12c5d1SDavid du Colombier p2 = linebuf;
11783e12c5d1SDavid du Colombier while(*p1++ = *p2++);
11793e12c5d1SDavid du Colombier hspend = p1 - 1;
11803e12c5d1SDavid du Colombier break;
11813e12c5d1SDavid du Colombier case CHCOM:
11823e12c5d1SDavid du Colombier *hspend++ = '\n';
11833e12c5d1SDavid du Colombier p1 = hspend;
11843e12c5d1SDavid du Colombier p2 = linebuf;
11853e12c5d1SDavid du Colombier while(*p1++ = *p2++)
11863e12c5d1SDavid du Colombier if(p1 >= hend)
11873e12c5d1SDavid du Colombier break;
11883e12c5d1SDavid du Colombier hspend = p1 - 1;
11893e12c5d1SDavid du Colombier break;
11903e12c5d1SDavid du Colombier case ICOM:
11913e12c5d1SDavid du Colombier for(rp = ipc->text; *rp; rp++)
11923e12c5d1SDavid du Colombier Bputrune(&fout, *rp);
11933e12c5d1SDavid du Colombier Bputc(&fout, '\n');
11943e12c5d1SDavid du Colombier break;
11953e12c5d1SDavid du Colombier case BCOM:
11963e12c5d1SDavid du Colombier jflag = 1;
11973e12c5d1SDavid du Colombier break;
11983e12c5d1SDavid du Colombier case LCOM:
11993e12c5d1SDavid du Colombier c = 0;
12003e12c5d1SDavid du Colombier for (i = 0, rp = linebuf; *rp; rp++) {
12013e12c5d1SDavid du Colombier c = *rp;
12023e12c5d1SDavid du Colombier if(c >= 0x20 && c < 0x7F && c != '\\') {
12033e12c5d1SDavid du Colombier Bputc(&fout, c);
12043e12c5d1SDavid du Colombier if(i++ > 71) {
12053e12c5d1SDavid du Colombier Bprint(&fout, "\\\n");
12063e12c5d1SDavid du Colombier i = 0;
12073e12c5d1SDavid du Colombier }
12083e12c5d1SDavid du Colombier } else {
12093e12c5d1SDavid du Colombier for (ucp = trans(*rp); *ucp; ucp++){
12103e12c5d1SDavid du Colombier c = *ucp;
12113e12c5d1SDavid du Colombier Bputc(&fout, c);
12123e12c5d1SDavid du Colombier if(i++ > 71) {
12133e12c5d1SDavid du Colombier Bprint(&fout, "\\\n");
12143e12c5d1SDavid du Colombier i = 0;
12153e12c5d1SDavid du Colombier }
12163e12c5d1SDavid du Colombier }
12173e12c5d1SDavid du Colombier }
12183e12c5d1SDavid du Colombier }
12193e12c5d1SDavid du Colombier if(c == ' ')
12203e12c5d1SDavid du Colombier Bprint(&fout, "\\n");
12213e12c5d1SDavid du Colombier Bputc(&fout, '\n');
12223e12c5d1SDavid du Colombier break;
12233e12c5d1SDavid du Colombier case NCOM:
12243e12c5d1SDavid du Colombier if(!nflag)
12253e12c5d1SDavid du Colombier putline(&fout, linebuf, spend-linebuf);
12263e12c5d1SDavid du Colombier
12273e12c5d1SDavid du Colombier if(aptr > abuf)
12283e12c5d1SDavid du Colombier arout();
12293e12c5d1SDavid du Colombier if((execp = gline(linebuf)) == 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 CNCOM:
12363e12c5d1SDavid du Colombier if(aptr > abuf)
12373e12c5d1SDavid du Colombier arout();
12383e12c5d1SDavid du Colombier *spend++ = '\n';
12393e12c5d1SDavid du Colombier if((execp = gline(spend)) == 0) {
12403e12c5d1SDavid du Colombier delflag = 1;
12413e12c5d1SDavid du Colombier break;
12423e12c5d1SDavid du Colombier }
12433e12c5d1SDavid du Colombier spend = execp;
12443e12c5d1SDavid du Colombier break;
12453e12c5d1SDavid du Colombier case PCOM:
12463e12c5d1SDavid du Colombier putline(&fout, linebuf, spend-linebuf);
12473e12c5d1SDavid du Colombier break;
12483e12c5d1SDavid du Colombier case CPCOM:
12493e12c5d1SDavid du Colombier cpcom:
12503e12c5d1SDavid du Colombier for(rp = linebuf; *rp && *rp != '\n'; rp++)
12513e12c5d1SDavid du Colombier Bputc(&fout, *rp);
12523e12c5d1SDavid du Colombier Bputc(&fout, '\n');
12533e12c5d1SDavid du Colombier break;
12543e12c5d1SDavid du Colombier case QCOM:
12553e12c5d1SDavid du Colombier if(!nflag)
12563e12c5d1SDavid du Colombier putline(&fout, linebuf, spend-linebuf);
12573e12c5d1SDavid du Colombier if(aptr > abuf)
12583e12c5d1SDavid du Colombier arout();
12593e12c5d1SDavid du Colombier exits(0);
12603e12c5d1SDavid du Colombier case RCOM:
12613e12c5d1SDavid du Colombier *aptr++ = ipc;
12623e12c5d1SDavid du Colombier if(aptr >= &abuf[MAXADDS])
12633e12c5d1SDavid du Colombier quit("sed: Too many reads after line %ld\n",
12643e12c5d1SDavid du Colombier (char *)lnum);
12653e12c5d1SDavid du Colombier *aptr = 0;
12663e12c5d1SDavid du Colombier break;
12673e12c5d1SDavid du Colombier case SCOM:
12683e12c5d1SDavid du Colombier i = substitute(ipc);
12693e12c5d1SDavid du Colombier if(i && ipc->pfl)
12703e12c5d1SDavid du Colombier if(ipc->pfl == 1)
12713e12c5d1SDavid du Colombier putline(&fout, linebuf, spend-linebuf);
12723e12c5d1SDavid du Colombier else
12733e12c5d1SDavid du Colombier goto cpcom;
12743e12c5d1SDavid du Colombier if(i && ipc->fcode)
12753e12c5d1SDavid du Colombier goto wcom;
12763e12c5d1SDavid du Colombier break;
12773e12c5d1SDavid du Colombier
12783e12c5d1SDavid du Colombier case TCOM:
12796c83e8f8SDavid du Colombier if(sflag) {
12803e12c5d1SDavid du Colombier sflag = 0;
12813e12c5d1SDavid du Colombier jflag = 1;
12826c83e8f8SDavid du Colombier }
12833e12c5d1SDavid du Colombier break;
12843e12c5d1SDavid du Colombier
12853e12c5d1SDavid du Colombier case WCOM:
12866c83e8f8SDavid du Colombier wcom:
12873e12c5d1SDavid du Colombier putline(ipc->fcode,linebuf, spend - linebuf);
12883e12c5d1SDavid du Colombier break;
12893e12c5d1SDavid du Colombier case XCOM:
12903e12c5d1SDavid du Colombier p1 = linebuf;
12913e12c5d1SDavid du Colombier p2 = genbuf;
12926c83e8f8SDavid du Colombier while(*p2++ = *p1++)
12936c83e8f8SDavid du Colombier ;
12943e12c5d1SDavid du Colombier p1 = holdsp;
12953e12c5d1SDavid du Colombier p2 = linebuf;
12966c83e8f8SDavid du Colombier while(*p2++ = *p1++)
12976c83e8f8SDavid du Colombier ;
12983e12c5d1SDavid du Colombier spend = p2 - 1;
12993e12c5d1SDavid du Colombier p1 = genbuf;
13003e12c5d1SDavid du Colombier p2 = holdsp;
13016c83e8f8SDavid du Colombier while(*p2++ = *p1++)
13026c83e8f8SDavid du Colombier ;
13033e12c5d1SDavid du Colombier hspend = p2 - 1;
13043e12c5d1SDavid du Colombier break;
13053e12c5d1SDavid du Colombier case YCOM:
13063e12c5d1SDavid du Colombier p1 = linebuf;
13073e12c5d1SDavid du Colombier p2 = ipc->text;
13086c83e8f8SDavid du Colombier for (i = *p2++; *p1; p1++)
13096c83e8f8SDavid du Colombier if (*p1 <= i)
13106c83e8f8SDavid du Colombier *p1 = p2[*p1];
13113e12c5d1SDavid du Colombier break;
13123e12c5d1SDavid du Colombier }
13133e12c5d1SDavid du Colombier }
13143e12c5d1SDavid du Colombier
13153e12c5d1SDavid du Colombier void
putline(Biobuf * bp,Rune * buf,int n)13163e12c5d1SDavid du Colombier putline(Biobuf *bp, Rune *buf, int n)
13173e12c5d1SDavid du Colombier {
13183e12c5d1SDavid du Colombier while (n--)
13193e12c5d1SDavid du Colombier Bputrune(bp, *buf++);
13203e12c5d1SDavid du Colombier Bputc(bp, '\n');
13213e12c5d1SDavid du Colombier }
ecmp(Rune * a,Rune * b,int count)13223e12c5d1SDavid du Colombier ecmp(Rune *a, Rune *b, int count)
13233e12c5d1SDavid du Colombier {
13243e12c5d1SDavid du Colombier while(count--)
13256c83e8f8SDavid du Colombier if(*a++ != *b++)
13266c83e8f8SDavid du Colombier return 0;
13276c83e8f8SDavid du Colombier return 1;
13283e12c5d1SDavid du Colombier }
13293e12c5d1SDavid du Colombier
13303e12c5d1SDavid du Colombier void
arout(void)13313e12c5d1SDavid du Colombier arout(void)
13323e12c5d1SDavid du Colombier {
13333e12c5d1SDavid du Colombier int c;
13343e12c5d1SDavid du Colombier char *s;
13353e12c5d1SDavid du Colombier char buf[128];
13366c83e8f8SDavid du Colombier Rune *p1;
13376c83e8f8SDavid du Colombier Biobuf *fi;
13383e12c5d1SDavid du Colombier
13393e12c5d1SDavid du Colombier for (aptr = abuf; *aptr; aptr++) {
13403e12c5d1SDavid du Colombier if((*aptr)->command == ACOM) {
13413e12c5d1SDavid du Colombier for(p1 = (*aptr)->text; *p1; p1++ )
13423e12c5d1SDavid du Colombier Bputrune(&fout, *p1);
13433e12c5d1SDavid du Colombier Bputc(&fout, '\n');
13443e12c5d1SDavid du Colombier } else {
13453e12c5d1SDavid du Colombier for(s = buf, p1 = (*aptr)->text; *p1; p1++)
13463e12c5d1SDavid du Colombier s += runetochar(s, p1);
13473e12c5d1SDavid du Colombier *s = '\0';
13483e12c5d1SDavid du Colombier if((fi = Bopen(buf, OREAD)) == 0)
13493e12c5d1SDavid du Colombier continue;
13503e12c5d1SDavid du Colombier while((c = Bgetc(fi)) >= 0)
13513e12c5d1SDavid du Colombier Bputc(&fout, c);
1352219b2ee8SDavid du Colombier Bterm(fi);
13533e12c5d1SDavid du Colombier }
13543e12c5d1SDavid du Colombier }
13553e12c5d1SDavid du Colombier aptr = abuf;
13563e12c5d1SDavid du Colombier *aptr = 0;
13573e12c5d1SDavid du Colombier }
13583e12c5d1SDavid du Colombier
13593e12c5d1SDavid du Colombier void
errexit(void)13603e12c5d1SDavid du Colombier errexit(void)
13613e12c5d1SDavid du Colombier {
13623e12c5d1SDavid du Colombier exits("error");
13633e12c5d1SDavid du Colombier }
13643e12c5d1SDavid du Colombier
13653e12c5d1SDavid du Colombier void
quit(char * fmt,...)13666c83e8f8SDavid du Colombier quit(char *fmt, ...)
13673e12c5d1SDavid du Colombier {
13686c83e8f8SDavid du Colombier char *p, *ep;
13696c83e8f8SDavid du Colombier char msg[256];
13706c83e8f8SDavid du Colombier va_list arg;
13716c83e8f8SDavid du Colombier
13726c83e8f8SDavid du Colombier ep = msg + sizeof msg;
13736c83e8f8SDavid du Colombier p = seprint(msg, ep, "sed: ");
13746c83e8f8SDavid du Colombier va_start(arg, fmt);
13756c83e8f8SDavid du Colombier p = vseprint(p, ep, fmt, arg);
13766c83e8f8SDavid du Colombier va_end(arg);
13776c83e8f8SDavid du Colombier p = seprint(p, ep, "\n");
13786c83e8f8SDavid du Colombier write(2, msg, p - msg);
13793e12c5d1SDavid du Colombier errexit();
13803e12c5d1SDavid du Colombier }
13813e12c5d1SDavid du Colombier
13823e12c5d1SDavid du Colombier Rune *
gline(Rune * addr)13833e12c5d1SDavid du Colombier gline(Rune *addr)
13843e12c5d1SDavid du Colombier {
13853e12c5d1SDavid du Colombier long c;
13863e12c5d1SDavid du Colombier Rune *p;
13873e12c5d1SDavid du Colombier static long peekc = 0;
13883e12c5d1SDavid du Colombier
13893e12c5d1SDavid du Colombier if (f == 0 && opendata() < 0)
13903e12c5d1SDavid du Colombier return 0;
13913e12c5d1SDavid du Colombier sflag = 0;
13923e12c5d1SDavid du Colombier lnum++;
13933e12c5d1SDavid du Colombier /* Bflush(&fout);********* dumped 4/30/92 - bobf****/
13943e12c5d1SDavid du Colombier do {
13953e12c5d1SDavid du Colombier p = addr;
1396219b2ee8SDavid du Colombier for (c = (peekc? peekc: Bgetrune(f)); c >= 0; c = Bgetrune(f)) {
13973e12c5d1SDavid du Colombier if (c == '\n') {
13986c83e8f8SDavid du Colombier if ((peekc = Bgetrune(f)) < 0 && fhead == 0)
13993e12c5d1SDavid du Colombier dolflag = 1;
14003e12c5d1SDavid du Colombier *p = '\0';
14013e12c5d1SDavid du Colombier return p;
14023e12c5d1SDavid du Colombier }
14033e12c5d1SDavid du Colombier if (c && p < lbend)
14043e12c5d1SDavid du Colombier *p++ = c;
14053e12c5d1SDavid du Colombier }
140659cc4ca5SDavid du Colombier /* return partial final line, adding implicit newline */
140759cc4ca5SDavid du Colombier if(p != addr) {
140859cc4ca5SDavid du Colombier *p = '\0';
140959cc4ca5SDavid du Colombier peekc = -1;
141059cc4ca5SDavid du Colombier if (fhead == 0)
141159cc4ca5SDavid du Colombier dolflag = 1;
141259cc4ca5SDavid du Colombier return p;
141359cc4ca5SDavid du Colombier }
14143e12c5d1SDavid du Colombier peekc = 0;
141559cc4ca5SDavid du Colombier Bterm(f);
14163e12c5d1SDavid du Colombier } while (opendata() > 0); /* Switch to next stream */
14177dd7cddfSDavid du Colombier f = 0;
14183e12c5d1SDavid du Colombier return 0;
14193e12c5d1SDavid du Colombier }
14203e12c5d1SDavid du Colombier
14216c83e8f8SDavid du Colombier /*
14226c83e8f8SDavid du Colombier * Data file input section - the intent is to transparently
14233e12c5d1SDavid du Colombier * catenate all data input streams.
14243e12c5d1SDavid du Colombier */
14253e12c5d1SDavid du Colombier void
enroll(char * filename)14263e12c5d1SDavid du Colombier enroll(char *filename) /* Add a file to the input file cache */
14273e12c5d1SDavid du Colombier {
14283e12c5d1SDavid du Colombier FileCache *fp;
14293e12c5d1SDavid du Colombier
14306c83e8f8SDavid du Colombier if ((fp = (FileCache *)malloc(sizeof (FileCache))) == nil)
14316c83e8f8SDavid du Colombier quit("Out of memory");
14326c83e8f8SDavid du Colombier if (ftail == nil)
14333e12c5d1SDavid du Colombier fhead = fp;
14343e12c5d1SDavid du Colombier else
14353e12c5d1SDavid du Colombier ftail->next = fp;
14363e12c5d1SDavid du Colombier ftail = fp;
14376c83e8f8SDavid du Colombier fp->next = nil;
14383e12c5d1SDavid du Colombier fp->name = filename; /* 0 => stdin */
14393e12c5d1SDavid du Colombier }
14403e12c5d1SDavid du Colombier
14413e12c5d1SDavid du Colombier int
opendata(void)14423e12c5d1SDavid du Colombier opendata(void)
14433e12c5d1SDavid du Colombier {
14446c83e8f8SDavid du Colombier if (fhead == nil)
14453e12c5d1SDavid du Colombier return -1;
14463e12c5d1SDavid du Colombier if (fhead->name) {
14476c83e8f8SDavid du Colombier if ((f = Bopen(fhead->name, OREAD)) == nil)
14483e12c5d1SDavid du Colombier quit("Can't open %s", fhead->name);
14493e12c5d1SDavid du Colombier } else {
14503e12c5d1SDavid du Colombier Binit(&stdin, 0, OREAD);
14513e12c5d1SDavid du Colombier f = &stdin;
14523e12c5d1SDavid du Colombier }
14533e12c5d1SDavid du Colombier fhead = fhead->next;
14543e12c5d1SDavid du Colombier return 1;
14553e12c5d1SDavid du Colombier }
1456