Blame


1 3940506b 2005-01-13 devnull /*
2 3940506b 2005-01-13 devnull * sed -- stream editor
3 3940506b 2005-01-13 devnull *
4 3940506b 2005-01-13 devnull *
5 3940506b 2005-01-13 devnull */
6 3940506b 2005-01-13 devnull #include <u.h>
7 3940506b 2005-01-13 devnull #include <libc.h>
8 3940506b 2005-01-13 devnull #include <bio.h>
9 3940506b 2005-01-13 devnull #include <regexp.h>
10 3940506b 2005-01-13 devnull
11 3940506b 2005-01-13 devnull enum {
12 3940506b 2005-01-13 devnull DEPTH = 20, /* max nesting depth of {} */
13 3940506b 2005-01-13 devnull MAXCMDS = 512, /* max sed commands */
14 3940506b 2005-01-13 devnull ADDSIZE = 10000, /* size of add & read buffer */
15 3940506b 2005-01-13 devnull MAXADDS = 20, /* max pending adds and reads */
16 3940506b 2005-01-13 devnull LBSIZE = 8192, /* input line size */
17 3940506b 2005-01-13 devnull LABSIZE = 50, /* max label name size */
18 3940506b 2005-01-13 devnull MAXSUB = 10, /* max number of sub reg exp */
19 cbeb0b26 2006-04-01 devnull MAXFILES = 120 /* max output files */
20 3940506b 2005-01-13 devnull };
21 3940506b 2005-01-13 devnull /* An address is a line #, a R.E., "$", a reference to the last
22 3940506b 2005-01-13 devnull * R.E., or nothing.
23 3940506b 2005-01-13 devnull */
24 3940506b 2005-01-13 devnull typedef struct {
25 3940506b 2005-01-13 devnull enum {
26 3940506b 2005-01-13 devnull A_NONE,
27 3940506b 2005-01-13 devnull A_DOL,
28 3940506b 2005-01-13 devnull A_LINE,
29 3940506b 2005-01-13 devnull A_RE,
30 cbeb0b26 2006-04-01 devnull A_LAST
31 3940506b 2005-01-13 devnull }type;
32 3940506b 2005-01-13 devnull union {
33 3940506b 2005-01-13 devnull long line; /* Line # */
34 3940506b 2005-01-13 devnull Reprog *rp; /* Compiled R.E. */
35 3940506b 2005-01-13 devnull } u;
36 3940506b 2005-01-13 devnull } Addr;
37 3940506b 2005-01-13 devnull
38 3940506b 2005-01-13 devnull typedef struct SEDCOM {
39 3940506b 2005-01-13 devnull Addr ad1; /* optional start address */
40 3940506b 2005-01-13 devnull Addr ad2; /* optional end address */
41 3940506b 2005-01-13 devnull union {
42 3940506b 2005-01-13 devnull Reprog *re1; /* compiled R.E. */
43 3940506b 2005-01-13 devnull Rune *text; /* added text or file name */
44 3940506b 2005-01-13 devnull struct SEDCOM *lb1; /* destination command of branch */
45 3940506b 2005-01-13 devnull } u;
46 3940506b 2005-01-13 devnull Rune *rhs; /* Right-hand side of substitution */
47 3940506b 2005-01-13 devnull Biobuf* fcode; /* File ID for read and write */
48 3940506b 2005-01-13 devnull char command; /* command code -see below */
49 3940506b 2005-01-13 devnull char gfl; /* 'Global' flag for substitutions */
50 3940506b 2005-01-13 devnull char pfl; /* 'print' flag for substitutions */
51 3940506b 2005-01-13 devnull char active; /* 1 => data between start and end */
52 3940506b 2005-01-13 devnull char negfl; /* negation flag */
53 3940506b 2005-01-13 devnull } SedCom;
54 3940506b 2005-01-13 devnull
55 3940506b 2005-01-13 devnull /* Command Codes for field SedCom.command */
56 3940506b 2005-01-13 devnull #define ACOM 01
57 3940506b 2005-01-13 devnull #define BCOM 020
58 3940506b 2005-01-13 devnull #define CCOM 02
59 3940506b 2005-01-13 devnull #define CDCOM 025
60 3940506b 2005-01-13 devnull #define CNCOM 022
61 3940506b 2005-01-13 devnull #define COCOM 017
62 3940506b 2005-01-13 devnull #define CPCOM 023
63 3940506b 2005-01-13 devnull #define DCOM 03
64 3940506b 2005-01-13 devnull #define ECOM 015
65 3940506b 2005-01-13 devnull #define EQCOM 013
66 3940506b 2005-01-13 devnull #define FCOM 016
67 3940506b 2005-01-13 devnull #define GCOM 027
68 3940506b 2005-01-13 devnull #define CGCOM 030
69 3940506b 2005-01-13 devnull #define HCOM 031
70 3940506b 2005-01-13 devnull #define CHCOM 032
71 3940506b 2005-01-13 devnull #define ICOM 04
72 3940506b 2005-01-13 devnull #define LCOM 05
73 3940506b 2005-01-13 devnull #define NCOM 012
74 3940506b 2005-01-13 devnull #define PCOM 010
75 3940506b 2005-01-13 devnull #define QCOM 011
76 3940506b 2005-01-13 devnull #define RCOM 06
77 3940506b 2005-01-13 devnull #define SCOM 07
78 3940506b 2005-01-13 devnull #define TCOM 021
79 3940506b 2005-01-13 devnull #define WCOM 014
80 3940506b 2005-01-13 devnull #define CWCOM 024
81 3940506b 2005-01-13 devnull #define YCOM 026
82 3940506b 2005-01-13 devnull #define XCOM 033
83 3940506b 2005-01-13 devnull
84 fa325e9b 2020-01-10 cross
85 3940506b 2005-01-13 devnull typedef struct label { /* Label symbol table */
86 3940506b 2005-01-13 devnull Rune asc[9]; /* Label name */
87 3940506b 2005-01-13 devnull SedCom *chain;
88 3940506b 2005-01-13 devnull SedCom *address; /* Command associated with label */
89 3940506b 2005-01-13 devnull } Label;
90 3940506b 2005-01-13 devnull
91 3940506b 2005-01-13 devnull typedef struct FILE_CACHE { /* Data file control block */
92 3940506b 2005-01-13 devnull struct FILE_CACHE *next; /* Forward Link */
93 3940506b 2005-01-13 devnull char *name; /* Name of file */
94 3940506b 2005-01-13 devnull } FileCache;
95 3940506b 2005-01-13 devnull
96 3940506b 2005-01-13 devnull SedCom pspace[MAXCMDS]; /* Command storage */
97 3940506b 2005-01-13 devnull SedCom *pend = pspace+MAXCMDS; /* End of command storage */
98 3940506b 2005-01-13 devnull SedCom *rep = pspace; /* Current fill point */
99 3940506b 2005-01-13 devnull
100 3940506b 2005-01-13 devnull Reprog *lastre = 0; /* Last regular expression */
101 3940506b 2005-01-13 devnull Resub subexp[MAXSUB]; /* sub-patterns of pattern match*/
102 3940506b 2005-01-13 devnull
103 3940506b 2005-01-13 devnull Rune addspace[ADDSIZE]; /* Buffer for a, c, & i commands */
104 3940506b 2005-01-13 devnull Rune *addend = addspace+ADDSIZE;
105 3940506b 2005-01-13 devnull
106 3940506b 2005-01-13 devnull SedCom *abuf[MAXADDS]; /* Queue of pending adds & reads */
107 3940506b 2005-01-13 devnull SedCom **aptr = abuf;
108 3940506b 2005-01-13 devnull
109 3940506b 2005-01-13 devnull struct { /* Sed program input control block */
110 3940506b 2005-01-13 devnull enum PTYPE /* Either on command line or in file */
111 3940506b 2005-01-13 devnull { P_ARG,
112 3940506b 2005-01-13 devnull P_FILE
113 3940506b 2005-01-13 devnull } type;
114 3940506b 2005-01-13 devnull union PCTL { /* Pointer to data */
115 3940506b 2005-01-13 devnull Biobuf *bp;
116 3940506b 2005-01-13 devnull char *curr;
117 3940506b 2005-01-13 devnull } pctl;
118 3940506b 2005-01-13 devnull } prog;
119 3940506b 2005-01-13 devnull
120 3940506b 2005-01-13 devnull Rune genbuf[LBSIZE]; /* Miscellaneous buffer */
121 3940506b 2005-01-13 devnull
122 3940506b 2005-01-13 devnull FileCache *fhead = 0; /* Head of File Cache Chain */
123 3940506b 2005-01-13 devnull FileCache *ftail = 0; /* Tail of File Cache Chain */
124 3940506b 2005-01-13 devnull
125 3940506b 2005-01-13 devnull Rune *loc1; /* Start of pattern match */
126 3940506b 2005-01-13 devnull Rune *loc2; /* End of pattern match */
127 3940506b 2005-01-13 devnull Rune seof; /* Pattern delimiter char */
128 3940506b 2005-01-13 devnull
129 3940506b 2005-01-13 devnull Rune linebuf[LBSIZE+1]; /* Input data buffer */
130 3940506b 2005-01-13 devnull Rune *lbend = linebuf+LBSIZE; /* End of buffer */
131 3940506b 2005-01-13 devnull Rune *spend = linebuf; /* End of input data */
132 3940506b 2005-01-13 devnull Rune *cp; /* Current scan point in linebuf */
133 3940506b 2005-01-13 devnull
134 3940506b 2005-01-13 devnull Rune holdsp[LBSIZE+1]; /* Hold buffer */
135 3940506b 2005-01-13 devnull Rune *hend = holdsp+LBSIZE; /* End of hold buffer */
136 3940506b 2005-01-13 devnull Rune *hspend = holdsp; /* End of hold data */
137 3940506b 2005-01-13 devnull
138 3940506b 2005-01-13 devnull int nflag; /* Command line flags */
139 3940506b 2005-01-13 devnull int gflag;
140 a09e8575 2006-06-26 devnull int lflag;
141 3940506b 2005-01-13 devnull
142 3940506b 2005-01-13 devnull int dolflag; /* Set when at true EOF */
143 3940506b 2005-01-13 devnull int sflag; /* Set when substitution done */
144 3940506b 2005-01-13 devnull int jflag; /* Set when jump required */
145 3940506b 2005-01-13 devnull int delflag; /* Delete current line when set */
146 3940506b 2005-01-13 devnull
147 3940506b 2005-01-13 devnull long lnum = 0; /* Input line count */
148 3940506b 2005-01-13 devnull
149 3940506b 2005-01-13 devnull char fname[MAXFILES][40]; /* File name cache */
150 3940506b 2005-01-13 devnull Biobuf *fcode[MAXFILES]; /* File ID cache */
151 3940506b 2005-01-13 devnull int nfiles = 0; /* Cache fill point */
152 3940506b 2005-01-13 devnull
153 3940506b 2005-01-13 devnull Biobuf fout; /* Output stream */
154 3940506b 2005-01-13 devnull Biobuf bstdin; /* Default input */
155 3940506b 2005-01-13 devnull Biobuf* f = 0; /* Input data */
156 3940506b 2005-01-13 devnull
157 3940506b 2005-01-13 devnull Label ltab[LABSIZE]; /* Label name symbol table */
158 3940506b 2005-01-13 devnull Label *labend = ltab+LABSIZE; /* End of label table */
159 3940506b 2005-01-13 devnull Label *lab = ltab+1; /* Current Fill point */
160 3940506b 2005-01-13 devnull
161 3940506b 2005-01-13 devnull int depth = 0; /* {} stack pointer */
162 3940506b 2005-01-13 devnull
163 3940506b 2005-01-13 devnull Rune bad; /* Dummy err ptr reference */
164 3940506b 2005-01-13 devnull Rune *badp = &bad;
165 3940506b 2005-01-13 devnull
166 3940506b 2005-01-13 devnull
167 3940506b 2005-01-13 devnull char CGMES[] = "Command garbled: %S";
168 3940506b 2005-01-13 devnull char TMMES[] = "Too much text: %S";
169 3940506b 2005-01-13 devnull char LTL[] = "Label too long: %S";
170 3940506b 2005-01-13 devnull char AD0MES[] = "No addresses allowed: %S";
171 3940506b 2005-01-13 devnull char AD1MES[] = "Only one address allowed: %S";
172 3940506b 2005-01-13 devnull
173 3940506b 2005-01-13 devnull void address(Addr *);
174 3940506b 2005-01-13 devnull void arout(void);
175 3940506b 2005-01-13 devnull int cmp(char *, char *);
176 3940506b 2005-01-13 devnull int rcmp(Rune *, Rune *);
177 3940506b 2005-01-13 devnull void command(SedCom *);
178 3940506b 2005-01-13 devnull Reprog *compile(void);
179 3940506b 2005-01-13 devnull Rune *compsub(Rune *, Rune *);
180 3940506b 2005-01-13 devnull void dechain(void);
181 3940506b 2005-01-13 devnull void dosub(Rune *);
182 3940506b 2005-01-13 devnull int ecmp(Rune *, Rune *, int);
183 3940506b 2005-01-13 devnull void enroll(char *);
184 3940506b 2005-01-13 devnull void errexit(void);
185 3940506b 2005-01-13 devnull int executable(SedCom *);
186 3940506b 2005-01-13 devnull void execute(void);
187 3940506b 2005-01-13 devnull void fcomp(void);
188 3940506b 2005-01-13 devnull long getrune(void);
189 3940506b 2005-01-13 devnull Rune *gline(Rune *);
190 3940506b 2005-01-13 devnull int match(Reprog *, Rune *);
191 3940506b 2005-01-13 devnull void newfile(enum PTYPE, char *);
192 3940506b 2005-01-13 devnull int opendata(void);
193 3940506b 2005-01-13 devnull Biobuf *open_file(char *);
194 3940506b 2005-01-13 devnull Rune *place(Rune *, Rune *, Rune *);
195 3940506b 2005-01-13 devnull void quit(char *, char *);
196 3940506b 2005-01-13 devnull int rline(Rune *, Rune *);
197 3940506b 2005-01-13 devnull Label *search(Label *);
198 3940506b 2005-01-13 devnull int substitute(SedCom *);
199 3940506b 2005-01-13 devnull char *text(char *);
200 3940506b 2005-01-13 devnull Rune *stext(Rune *, Rune *);
201 3940506b 2005-01-13 devnull int ycomp(SedCom *);
202 3940506b 2005-01-13 devnull char * trans(int c);
203 3940506b 2005-01-13 devnull void putline(Biobuf *bp, Rune *buf, int n);
204 3940506b 2005-01-13 devnull
205 3940506b 2005-01-13 devnull void
206 3940506b 2005-01-13 devnull main(int argc, char **argv)
207 3940506b 2005-01-13 devnull {
208 3940506b 2005-01-13 devnull int compfl;
209 3940506b 2005-01-13 devnull
210 3940506b 2005-01-13 devnull lnum = 0;
211 3940506b 2005-01-13 devnull Binit(&fout, 1, OWRITE);
212 3940506b 2005-01-13 devnull fcode[nfiles++] = &fout;
213 3940506b 2005-01-13 devnull compfl = 0;
214 3940506b 2005-01-13 devnull
215 3940506b 2005-01-13 devnull if(argc == 1)
216 3940506b 2005-01-13 devnull exits(0);
217 3940506b 2005-01-13 devnull ARGBEGIN{
218 3940506b 2005-01-13 devnull case 'n':
219 3940506b 2005-01-13 devnull nflag++;
220 3940506b 2005-01-13 devnull continue;
221 3940506b 2005-01-13 devnull case 'f':
222 3940506b 2005-01-13 devnull if(argc <= 1)
223 3940506b 2005-01-13 devnull quit("no pattern-file", 0);
224 3940506b 2005-01-13 devnull newfile(P_FILE, ARGF());
225 3940506b 2005-01-13 devnull fcomp();
226 3940506b 2005-01-13 devnull compfl = 1;
227 3940506b 2005-01-13 devnull continue;
228 3940506b 2005-01-13 devnull case 'e':
229 3940506b 2005-01-13 devnull if (argc <= 1)
230 3940506b 2005-01-13 devnull quit("missing pattern", 0);
231 3940506b 2005-01-13 devnull newfile(P_ARG, ARGF());
232 3940506b 2005-01-13 devnull fcomp();
233 3940506b 2005-01-13 devnull compfl = 1;
234 3940506b 2005-01-13 devnull continue;
235 3940506b 2005-01-13 devnull case 'g':
236 3940506b 2005-01-13 devnull gflag++;
237 a09e8575 2006-06-26 devnull continue;
238 a09e8575 2006-06-26 devnull case 'l':
239 a09e8575 2006-06-26 devnull lflag++;
240 3940506b 2005-01-13 devnull continue;
241 3940506b 2005-01-13 devnull default:
242 3940506b 2005-01-13 devnull fprint(2, "sed: Unknown flag: %c\n", ARGC());
243 3940506b 2005-01-13 devnull continue;
244 3940506b 2005-01-13 devnull } ARGEND
245 3940506b 2005-01-13 devnull
246 3940506b 2005-01-13 devnull if(compfl == 0) {
247 3940506b 2005-01-13 devnull if (--argc < 0)
248 3940506b 2005-01-13 devnull quit("missing pattern", 0);
249 3940506b 2005-01-13 devnull newfile(P_ARG, *argv++);
250 3940506b 2005-01-13 devnull fcomp();
251 3940506b 2005-01-13 devnull }
252 3940506b 2005-01-13 devnull
253 3940506b 2005-01-13 devnull if(depth)
254 3940506b 2005-01-13 devnull quit("Too many {'s", 0);
255 3940506b 2005-01-13 devnull
256 3940506b 2005-01-13 devnull ltab[0].address = rep;
257 3940506b 2005-01-13 devnull
258 3940506b 2005-01-13 devnull dechain();
259 3940506b 2005-01-13 devnull
260 3940506b 2005-01-13 devnull if(argc <= 0)
261 3940506b 2005-01-13 devnull enroll(0); /* Add stdin to cache */
262 3940506b 2005-01-13 devnull else while(--argc >= 0) {
263 3940506b 2005-01-13 devnull enroll(*argv++);
264 3940506b 2005-01-13 devnull }
265 3940506b 2005-01-13 devnull execute();
266 3940506b 2005-01-13 devnull exits(0);
267 3940506b 2005-01-13 devnull }
268 3940506b 2005-01-13 devnull void
269 3940506b 2005-01-13 devnull fcomp(void)
270 3940506b 2005-01-13 devnull {
271 3940506b 2005-01-13 devnull Rune *tp;
272 3940506b 2005-01-13 devnull SedCom *pt, *pt1;
273 3940506b 2005-01-13 devnull int i;
274 3940506b 2005-01-13 devnull Label *lpt;
275 3940506b 2005-01-13 devnull
276 3940506b 2005-01-13 devnull static Rune *p = addspace;
277 3940506b 2005-01-13 devnull static SedCom **cmpend[DEPTH]; /* stack of {} operations */
278 3940506b 2005-01-13 devnull
279 3940506b 2005-01-13 devnull while (rline(linebuf, lbend) >= 0) {
280 3940506b 2005-01-13 devnull cp = linebuf;
281 3940506b 2005-01-13 devnull comploop:
282 3940506b 2005-01-13 devnull while(*cp == ' ' || *cp == '\t')
283 3940506b 2005-01-13 devnull cp++;
284 3940506b 2005-01-13 devnull if(*cp == '\0' || *cp == '#')
285 3940506b 2005-01-13 devnull continue;
286 3940506b 2005-01-13 devnull if(*cp == ';') {
287 3940506b 2005-01-13 devnull cp++;
288 3940506b 2005-01-13 devnull goto comploop;
289 3940506b 2005-01-13 devnull }
290 3940506b 2005-01-13 devnull
291 3940506b 2005-01-13 devnull address(&rep->ad1);
292 3940506b 2005-01-13 devnull if (rep->ad1.type != A_NONE) {
293 3940506b 2005-01-13 devnull if (rep->ad1.type == A_LAST) {
294 3940506b 2005-01-13 devnull if (!lastre)
295 3940506b 2005-01-13 devnull quit("First RE may not be null", 0);
296 3940506b 2005-01-13 devnull rep->ad1.type = A_RE;
297 3940506b 2005-01-13 devnull rep->ad1.u.rp = lastre;
298 3940506b 2005-01-13 devnull }
299 3940506b 2005-01-13 devnull if(*cp == ',' || *cp == ';') {
300 3940506b 2005-01-13 devnull cp++;
301 3940506b 2005-01-13 devnull address(&rep->ad2);
302 3940506b 2005-01-13 devnull if (rep->ad2.type == A_LAST) {
303 3940506b 2005-01-13 devnull rep->ad1.type = A_RE;
304 3940506b 2005-01-13 devnull rep->ad2.u.rp = lastre;
305 3940506b 2005-01-13 devnull }
306 3940506b 2005-01-13 devnull } else
307 3940506b 2005-01-13 devnull rep->ad2.type = A_NONE;
308 3940506b 2005-01-13 devnull }
309 3940506b 2005-01-13 devnull while(*cp == ' ' || *cp == '\t')
310 3940506b 2005-01-13 devnull cp++;
311 3940506b 2005-01-13 devnull
312 3940506b 2005-01-13 devnull swit:
313 3940506b 2005-01-13 devnull switch(*cp++) {
314 3940506b 2005-01-13 devnull
315 3940506b 2005-01-13 devnull default:
316 3940506b 2005-01-13 devnull quit("Unrecognized command: %S", (char *)linebuf);
317 3940506b 2005-01-13 devnull
318 3940506b 2005-01-13 devnull case '!':
319 3940506b 2005-01-13 devnull rep->negfl = 1;
320 3940506b 2005-01-13 devnull goto swit;
321 3940506b 2005-01-13 devnull
322 3940506b 2005-01-13 devnull case '{':
323 3940506b 2005-01-13 devnull rep->command = BCOM;
324 3940506b 2005-01-13 devnull rep->negfl = !(rep->negfl);
325 3940506b 2005-01-13 devnull cmpend[depth++] = &rep->u.lb1;
326 3940506b 2005-01-13 devnull if(++rep >= pend)
327 3940506b 2005-01-13 devnull quit("Too many commands: %S", (char *) linebuf);
328 3940506b 2005-01-13 devnull if(*cp == '\0') continue;
329 3940506b 2005-01-13 devnull goto comploop;
330 3940506b 2005-01-13 devnull
331 3940506b 2005-01-13 devnull case '}':
332 3940506b 2005-01-13 devnull if(rep->ad1.type != A_NONE)
333 3940506b 2005-01-13 devnull quit(AD0MES, (char *) linebuf);
334 3940506b 2005-01-13 devnull if(--depth < 0)
335 3940506b 2005-01-13 devnull quit("Too many }'s", 0);
336 3940506b 2005-01-13 devnull *cmpend[depth] = rep;
337 3940506b 2005-01-13 devnull if(*cp == 0) continue;
338 3940506b 2005-01-13 devnull goto comploop;
339 3940506b 2005-01-13 devnull
340 3940506b 2005-01-13 devnull case '=':
341 3940506b 2005-01-13 devnull rep->command = EQCOM;
342 3940506b 2005-01-13 devnull if(rep->ad2.type != A_NONE)
343 3940506b 2005-01-13 devnull quit(AD1MES, (char *) linebuf);
344 3940506b 2005-01-13 devnull break;
345 3940506b 2005-01-13 devnull
346 3940506b 2005-01-13 devnull case ':':
347 3940506b 2005-01-13 devnull if(rep->ad1.type != A_NONE)
348 3940506b 2005-01-13 devnull quit(AD0MES, (char *) linebuf);
349 3940506b 2005-01-13 devnull
350 3940506b 2005-01-13 devnull while(*cp == ' ')
351 3940506b 2005-01-13 devnull cp++;
352 3940506b 2005-01-13 devnull tp = lab->asc;
353 3940506b 2005-01-13 devnull while (*cp && *cp != ';' && *cp != ' ' && *cp != '\t' && *cp != '#') {
354 3940506b 2005-01-13 devnull *tp++ = *cp++;
355 3940506b 2005-01-13 devnull if(tp >= &(lab->asc[8]))
356 3940506b 2005-01-13 devnull quit(LTL, (char *) linebuf);
357 3940506b 2005-01-13 devnull }
358 3940506b 2005-01-13 devnull *tp = '\0';
359 3940506b 2005-01-13 devnull
360 3940506b 2005-01-13 devnull if(lpt = search(lab)) {
361 3940506b 2005-01-13 devnull if(lpt->address)
362 3940506b 2005-01-13 devnull quit("Duplicate labels: %S", (char *) linebuf);
363 3940506b 2005-01-13 devnull } else {
364 3940506b 2005-01-13 devnull lab->chain = 0;
365 3940506b 2005-01-13 devnull lpt = lab;
366 3940506b 2005-01-13 devnull if(++lab >= labend)
367 3940506b 2005-01-13 devnull quit("Too many labels: %S", (char *) linebuf);
368 3940506b 2005-01-13 devnull }
369 3940506b 2005-01-13 devnull lpt->address = rep;
370 3940506b 2005-01-13 devnull if (*cp == '#')
371 3940506b 2005-01-13 devnull continue;
372 3940506b 2005-01-13 devnull rep--; /* reuse this slot */
373 3940506b 2005-01-13 devnull break;
374 3940506b 2005-01-13 devnull
375 3940506b 2005-01-13 devnull case 'a':
376 3940506b 2005-01-13 devnull rep->command = ACOM;
377 3940506b 2005-01-13 devnull if(rep->ad2.type != A_NONE)
378 3940506b 2005-01-13 devnull quit(AD1MES, (char *) linebuf);
379 3940506b 2005-01-13 devnull if(*cp == '\\') cp++;
380 3940506b 2005-01-13 devnull if(*cp++ != '\n')
381 3940506b 2005-01-13 devnull quit(CGMES, (char *) linebuf);
382 3940506b 2005-01-13 devnull rep->u.text = p;
383 3940506b 2005-01-13 devnull p = stext(p, addend);
384 3940506b 2005-01-13 devnull break;
385 3940506b 2005-01-13 devnull case 'c':
386 3940506b 2005-01-13 devnull rep->command = CCOM;
387 3940506b 2005-01-13 devnull if(*cp == '\\') cp++;
388 3940506b 2005-01-13 devnull if(*cp++ != '\n')
389 3940506b 2005-01-13 devnull quit(CGMES, (char *) linebuf);
390 3940506b 2005-01-13 devnull rep->u.text = p;
391 3940506b 2005-01-13 devnull p = stext(p, addend);
392 3940506b 2005-01-13 devnull break;
393 3940506b 2005-01-13 devnull case 'i':
394 3940506b 2005-01-13 devnull rep->command = ICOM;
395 3940506b 2005-01-13 devnull if(rep->ad2.type != A_NONE)
396 3940506b 2005-01-13 devnull quit(AD1MES, (char *) linebuf);
397 3940506b 2005-01-13 devnull if(*cp == '\\') cp++;
398 3940506b 2005-01-13 devnull if(*cp++ != '\n')
399 3940506b 2005-01-13 devnull quit(CGMES, (char *) linebuf);
400 3940506b 2005-01-13 devnull rep->u.text = p;
401 3940506b 2005-01-13 devnull p = stext(p, addend);
402 3940506b 2005-01-13 devnull break;
403 3940506b 2005-01-13 devnull
404 3940506b 2005-01-13 devnull case 'g':
405 3940506b 2005-01-13 devnull rep->command = GCOM;
406 3940506b 2005-01-13 devnull break;
407 3940506b 2005-01-13 devnull
408 3940506b 2005-01-13 devnull case 'G':
409 3940506b 2005-01-13 devnull rep->command = CGCOM;
410 3940506b 2005-01-13 devnull break;
411 3940506b 2005-01-13 devnull
412 3940506b 2005-01-13 devnull case 'h':
413 3940506b 2005-01-13 devnull rep->command = HCOM;
414 3940506b 2005-01-13 devnull break;
415 3940506b 2005-01-13 devnull
416 3940506b 2005-01-13 devnull case 'H':
417 3940506b 2005-01-13 devnull rep->command = CHCOM;
418 3940506b 2005-01-13 devnull break;
419 3940506b 2005-01-13 devnull
420 3940506b 2005-01-13 devnull case 't':
421 3940506b 2005-01-13 devnull rep->command = TCOM;
422 3940506b 2005-01-13 devnull goto jtcommon;
423 3940506b 2005-01-13 devnull
424 3940506b 2005-01-13 devnull case 'b':
425 3940506b 2005-01-13 devnull rep->command = BCOM;
426 3940506b 2005-01-13 devnull jtcommon:
427 3940506b 2005-01-13 devnull while(*cp == ' ')cp++;
428 3940506b 2005-01-13 devnull if(*cp == '\0') {
429 3940506b 2005-01-13 devnull if(pt = ltab[0].chain) {
430 3940506b 2005-01-13 devnull while(pt1 = pt->u.lb1)
431 3940506b 2005-01-13 devnull pt = pt1;
432 3940506b 2005-01-13 devnull pt->u.lb1 = rep;
433 3940506b 2005-01-13 devnull } else
434 3940506b 2005-01-13 devnull ltab[0].chain = rep;
435 3940506b 2005-01-13 devnull break;
436 3940506b 2005-01-13 devnull }
437 3940506b 2005-01-13 devnull tp = lab->asc;
438 3940506b 2005-01-13 devnull while((*tp++ = *cp++))
439 3940506b 2005-01-13 devnull if(tp >= &(lab->asc[8]))
440 3940506b 2005-01-13 devnull quit(LTL, (char *) linebuf);
441 3940506b 2005-01-13 devnull cp--;
442 3940506b 2005-01-13 devnull tp[-1] = '\0';
443 3940506b 2005-01-13 devnull
444 3940506b 2005-01-13 devnull if(lpt = search(lab)) {
445 3940506b 2005-01-13 devnull if(lpt->address) {
446 3940506b 2005-01-13 devnull rep->u.lb1 = lpt->address;
447 3940506b 2005-01-13 devnull } else {
448 3940506b 2005-01-13 devnull pt = lpt->chain;
449 3940506b 2005-01-13 devnull while(pt1 = pt->u.lb1)
450 3940506b 2005-01-13 devnull pt = pt1;
451 3940506b 2005-01-13 devnull pt->u.lb1 = rep;
452 3940506b 2005-01-13 devnull }
453 3940506b 2005-01-13 devnull } else {
454 3940506b 2005-01-13 devnull lab->chain = rep;
455 3940506b 2005-01-13 devnull lab->address = 0;
456 3940506b 2005-01-13 devnull if(++lab >= labend)
457 3940506b 2005-01-13 devnull quit("Too many labels: %S",
458 3940506b 2005-01-13 devnull (char *) linebuf);
459 3940506b 2005-01-13 devnull }
460 3940506b 2005-01-13 devnull break;
461 3940506b 2005-01-13 devnull
462 3940506b 2005-01-13 devnull case 'n':
463 3940506b 2005-01-13 devnull rep->command = NCOM;
464 3940506b 2005-01-13 devnull break;
465 3940506b 2005-01-13 devnull
466 3940506b 2005-01-13 devnull case 'N':
467 3940506b 2005-01-13 devnull rep->command = CNCOM;
468 3940506b 2005-01-13 devnull break;
469 3940506b 2005-01-13 devnull
470 3940506b 2005-01-13 devnull case 'p':
471 3940506b 2005-01-13 devnull rep->command = PCOM;
472 3940506b 2005-01-13 devnull break;
473 3940506b 2005-01-13 devnull
474 3940506b 2005-01-13 devnull case 'P':
475 3940506b 2005-01-13 devnull rep->command = CPCOM;
476 3940506b 2005-01-13 devnull break;
477 3940506b 2005-01-13 devnull
478 3940506b 2005-01-13 devnull case 'r':
479 3940506b 2005-01-13 devnull rep->command = RCOM;
480 3940506b 2005-01-13 devnull if(rep->ad2.type != A_NONE)
481 3940506b 2005-01-13 devnull quit(AD1MES, (char *) linebuf);
482 3940506b 2005-01-13 devnull if(*cp++ != ' ')
483 3940506b 2005-01-13 devnull quit(CGMES, (char *) linebuf);
484 3940506b 2005-01-13 devnull rep->u.text = p;
485 3940506b 2005-01-13 devnull p = stext(p, addend);
486 3940506b 2005-01-13 devnull break;
487 3940506b 2005-01-13 devnull
488 3940506b 2005-01-13 devnull case 'd':
489 3940506b 2005-01-13 devnull rep->command = DCOM;
490 3940506b 2005-01-13 devnull break;
491 3940506b 2005-01-13 devnull
492 3940506b 2005-01-13 devnull case 'D':
493 3940506b 2005-01-13 devnull rep->command = CDCOM;
494 3940506b 2005-01-13 devnull rep->u.lb1 = pspace;
495 3940506b 2005-01-13 devnull break;
496 3940506b 2005-01-13 devnull
497 3940506b 2005-01-13 devnull case 'q':
498 3940506b 2005-01-13 devnull rep->command = QCOM;
499 3940506b 2005-01-13 devnull if(rep->ad2.type != A_NONE)
500 3940506b 2005-01-13 devnull quit(AD1MES, (char *) linebuf);
501 3940506b 2005-01-13 devnull break;
502 3940506b 2005-01-13 devnull
503 3940506b 2005-01-13 devnull case 'l':
504 3940506b 2005-01-13 devnull rep->command = LCOM;
505 3940506b 2005-01-13 devnull break;
506 3940506b 2005-01-13 devnull
507 3940506b 2005-01-13 devnull case 's':
508 3940506b 2005-01-13 devnull rep->command = SCOM;
509 3940506b 2005-01-13 devnull seof = *cp++;
510 3940506b 2005-01-13 devnull if ((rep->u.re1 = compile()) == 0) {
511 3940506b 2005-01-13 devnull if(!lastre)
512 3940506b 2005-01-13 devnull quit("First RE may not be null.", 0);
513 3940506b 2005-01-13 devnull rep->u.re1 = lastre;
514 3940506b 2005-01-13 devnull }
515 3940506b 2005-01-13 devnull rep->rhs = p;
516 3940506b 2005-01-13 devnull if((p = compsub(p, addend)) == 0)
517 3940506b 2005-01-13 devnull quit(CGMES, (char *) linebuf);
518 3940506b 2005-01-13 devnull if(*cp == 'g') {
519 3940506b 2005-01-13 devnull cp++;
520 3940506b 2005-01-13 devnull rep->gfl++;
521 3940506b 2005-01-13 devnull } else if(gflag)
522 3940506b 2005-01-13 devnull rep->gfl++;
523 3940506b 2005-01-13 devnull
524 3940506b 2005-01-13 devnull if(*cp == 'p') {
525 3940506b 2005-01-13 devnull cp++;
526 3940506b 2005-01-13 devnull rep->pfl = 1;
527 3940506b 2005-01-13 devnull }
528 3940506b 2005-01-13 devnull
529 3940506b 2005-01-13 devnull if(*cp == 'P') {
530 3940506b 2005-01-13 devnull cp++;
531 3940506b 2005-01-13 devnull rep->pfl = 2;
532 3940506b 2005-01-13 devnull }
533 3940506b 2005-01-13 devnull
534 3940506b 2005-01-13 devnull if(*cp == 'w') {
535 3940506b 2005-01-13 devnull cp++;
536 3940506b 2005-01-13 devnull if(*cp++ != ' ')
537 3940506b 2005-01-13 devnull quit(CGMES, (char *) linebuf);
538 3940506b 2005-01-13 devnull text(fname[nfiles]);
539 3940506b 2005-01-13 devnull for(i = nfiles - 1; i >= 0; i--)
540 3940506b 2005-01-13 devnull if(cmp(fname[nfiles],fname[i]) == 0) {
541 3940506b 2005-01-13 devnull rep->fcode = fcode[i];
542 3940506b 2005-01-13 devnull goto done;
543 3940506b 2005-01-13 devnull }
544 3940506b 2005-01-13 devnull if(nfiles >= MAXFILES)
545 3940506b 2005-01-13 devnull quit("Too many files in w commands 1", 0);
546 3940506b 2005-01-13 devnull rep->fcode = open_file(fname[nfiles]);
547 3940506b 2005-01-13 devnull }
548 3940506b 2005-01-13 devnull break;
549 3940506b 2005-01-13 devnull
550 3940506b 2005-01-13 devnull case 'w':
551 3940506b 2005-01-13 devnull rep->command = WCOM;
552 3940506b 2005-01-13 devnull if(*cp++ != ' ')
553 3940506b 2005-01-13 devnull quit(CGMES, (char *) linebuf);
554 3940506b 2005-01-13 devnull text(fname[nfiles]);
555 3940506b 2005-01-13 devnull for(i = nfiles - 1; i >= 0; i--)
556 3940506b 2005-01-13 devnull if(cmp(fname[nfiles], fname[i]) == 0) {
557 3940506b 2005-01-13 devnull rep->fcode = fcode[i];
558 3940506b 2005-01-13 devnull goto done;
559 3940506b 2005-01-13 devnull }
560 3940506b 2005-01-13 devnull if(nfiles >= MAXFILES){
561 3940506b 2005-01-13 devnull fprint(2, "sed: Too many files in w commands 2 \n");
562 3940506b 2005-01-13 devnull fprint(2, "nfiles = %d; MAXF = %d\n", nfiles, MAXFILES);
563 3940506b 2005-01-13 devnull errexit();
564 3940506b 2005-01-13 devnull }
565 3940506b 2005-01-13 devnull rep->fcode = open_file(fname[nfiles]);
566 3940506b 2005-01-13 devnull break;
567 3940506b 2005-01-13 devnull
568 3940506b 2005-01-13 devnull case 'x':
569 3940506b 2005-01-13 devnull rep->command = XCOM;
570 3940506b 2005-01-13 devnull break;
571 3940506b 2005-01-13 devnull
572 3940506b 2005-01-13 devnull case 'y':
573 3940506b 2005-01-13 devnull rep->command = YCOM;
574 3940506b 2005-01-13 devnull seof = *cp++;
575 3940506b 2005-01-13 devnull if (ycomp(rep) == 0)
576 3940506b 2005-01-13 devnull quit(CGMES, (char *) linebuf);
577 3940506b 2005-01-13 devnull break;
578 3940506b 2005-01-13 devnull
579 3940506b 2005-01-13 devnull }
580 3940506b 2005-01-13 devnull done:
581 3940506b 2005-01-13 devnull if(++rep >= pend)
582 3940506b 2005-01-13 devnull quit("Too many commands, last: %S", (char *) linebuf);
583 3940506b 2005-01-13 devnull
584 3940506b 2005-01-13 devnull if(*cp++ != '\0') {
585 3940506b 2005-01-13 devnull if(cp[-1] == ';')
586 3940506b 2005-01-13 devnull goto comploop;
587 3940506b 2005-01-13 devnull quit(CGMES, (char *) linebuf);
588 3940506b 2005-01-13 devnull }
589 3940506b 2005-01-13 devnull
590 3940506b 2005-01-13 devnull }
591 3940506b 2005-01-13 devnull }
592 3940506b 2005-01-13 devnull
593 3940506b 2005-01-13 devnull Biobuf *
594 3940506b 2005-01-13 devnull open_file(char *name)
595 3940506b 2005-01-13 devnull {
596 3940506b 2005-01-13 devnull Biobuf *bp;
597 3940506b 2005-01-13 devnull int fd;
598 3940506b 2005-01-13 devnull
599 3940506b 2005-01-13 devnull if ((bp = malloc(sizeof(Biobuf))) == 0)
600 3940506b 2005-01-13 devnull quit("Out of memory", 0);
601 3940506b 2005-01-13 devnull if ((fd = open(name, OWRITE)) < 0 &&
602 3940506b 2005-01-13 devnull (fd = create(name, OWRITE, 0666)) < 0)
603 3940506b 2005-01-13 devnull quit("Cannot create %s", name);
604 3940506b 2005-01-13 devnull Binit(bp, fd, OWRITE);
605 3940506b 2005-01-13 devnull Bseek(bp, 0, 2);
606 3940506b 2005-01-13 devnull fcode[nfiles++] = bp;
607 3940506b 2005-01-13 devnull return bp;
608 3940506b 2005-01-13 devnull }
609 3940506b 2005-01-13 devnull
610 3940506b 2005-01-13 devnull Rune *
611 3940506b 2005-01-13 devnull compsub(Rune *rhs, Rune *end)
612 3940506b 2005-01-13 devnull {
613 3940506b 2005-01-13 devnull Rune r;
614 3940506b 2005-01-13 devnull
615 3940506b 2005-01-13 devnull while ((r = *cp++) != '\0') {
616 3940506b 2005-01-13 devnull if(r == '\\') {
617 3940506b 2005-01-13 devnull if (rhs < end)
618 0cadb430 2009-09-11 russcox *rhs++ = Runemax;
619 3940506b 2005-01-13 devnull else
620 3940506b 2005-01-13 devnull return 0;
621 3940506b 2005-01-13 devnull r = *cp++;
622 3940506b 2005-01-13 devnull if(r == 'n')
623 3940506b 2005-01-13 devnull r = '\n';
624 3940506b 2005-01-13 devnull } else {
625 3940506b 2005-01-13 devnull if(r == seof) {
626 3940506b 2005-01-13 devnull if (rhs < end)
627 3940506b 2005-01-13 devnull *rhs++ = '\0';
628 3940506b 2005-01-13 devnull else
629 3940506b 2005-01-13 devnull return 0;
630 3940506b 2005-01-13 devnull return rhs;
631 3940506b 2005-01-13 devnull }
632 3940506b 2005-01-13 devnull }
633 3940506b 2005-01-13 devnull if (rhs < end)
634 3940506b 2005-01-13 devnull *rhs++ = r;
635 fa325e9b 2020-01-10 cross else
636 3940506b 2005-01-13 devnull return 0;
637 3940506b 2005-01-13 devnull
638 3940506b 2005-01-13 devnull }
639 3940506b 2005-01-13 devnull return 0;
640 3940506b 2005-01-13 devnull }
641 3940506b 2005-01-13 devnull
642 3940506b 2005-01-13 devnull Reprog *
643 3940506b 2005-01-13 devnull compile(void)
644 3940506b 2005-01-13 devnull {
645 3940506b 2005-01-13 devnull Rune c;
646 3940506b 2005-01-13 devnull char *ep;
647 3940506b 2005-01-13 devnull char expbuf[512];
648 3940506b 2005-01-13 devnull
649 3940506b 2005-01-13 devnull if((c = *cp++) == seof) /* '//' */
650 3940506b 2005-01-13 devnull return 0;
651 3940506b 2005-01-13 devnull ep = expbuf;
652 3940506b 2005-01-13 devnull do {
653 3940506b 2005-01-13 devnull if (c == 0 || c == '\n')
654 3940506b 2005-01-13 devnull quit(TMMES, (char *) linebuf);
655 3940506b 2005-01-13 devnull if (c == '\\') {
656 3940506b 2005-01-13 devnull if (ep >= expbuf+sizeof(expbuf))
657 3940506b 2005-01-13 devnull quit(TMMES, (char *) linebuf);
658 3940506b 2005-01-13 devnull ep += runetochar(ep, &c);
659 3940506b 2005-01-13 devnull if ((c = *cp++) == 'n')
660 3940506b 2005-01-13 devnull c = '\n';
661 3940506b 2005-01-13 devnull }
662 3940506b 2005-01-13 devnull if (ep >= expbuf+sizeof(expbuf))
663 3940506b 2005-01-13 devnull quit(TMMES, (char *) linebuf);
664 3940506b 2005-01-13 devnull ep += runetochar(ep, &c);
665 3940506b 2005-01-13 devnull } while ((c = *cp++) != seof);
666 3940506b 2005-01-13 devnull *ep = 0;
667 3940506b 2005-01-13 devnull return lastre = regcomp(expbuf);
668 3940506b 2005-01-13 devnull }
669 3940506b 2005-01-13 devnull
670 3940506b 2005-01-13 devnull void
671 3940506b 2005-01-13 devnull regerror(char *s)
672 3940506b 2005-01-13 devnull {
673 3940506b 2005-01-13 devnull USED(s);
674 3940506b 2005-01-13 devnull quit(CGMES, (char *) linebuf);
675 3940506b 2005-01-13 devnull }
676 3940506b 2005-01-13 devnull
677 3940506b 2005-01-13 devnull void
678 3940506b 2005-01-13 devnull newfile(enum PTYPE type, char *name)
679 3940506b 2005-01-13 devnull {
680 3940506b 2005-01-13 devnull if (type == P_ARG)
681 3940506b 2005-01-13 devnull prog.pctl.curr = name;
682 3940506b 2005-01-13 devnull else if ((prog.pctl.bp = Bopen(name, OREAD)) == 0)
683 3940506b 2005-01-13 devnull quit("Cannot open pattern-file: %s\n", name);
684 3940506b 2005-01-13 devnull prog.type = type;
685 3940506b 2005-01-13 devnull }
686 3940506b 2005-01-13 devnull
687 3940506b 2005-01-13 devnull int
688 3940506b 2005-01-13 devnull rline(Rune *buf, Rune *end)
689 3940506b 2005-01-13 devnull {
690 3940506b 2005-01-13 devnull long c;
691 3940506b 2005-01-13 devnull Rune r;
692 3940506b 2005-01-13 devnull
693 3940506b 2005-01-13 devnull while ((c = getrune()) >= 0) {
694 3940506b 2005-01-13 devnull r = c;
695 3940506b 2005-01-13 devnull if (r == '\\') {
696 3940506b 2005-01-13 devnull if (buf <= end)
697 3940506b 2005-01-13 devnull *buf++ = r;
698 3940506b 2005-01-13 devnull if ((c = getrune()) < 0)
699 3940506b 2005-01-13 devnull break;
700 3940506b 2005-01-13 devnull r = c;
701 3940506b 2005-01-13 devnull } else if (r == '\n') {
702 3940506b 2005-01-13 devnull *buf = '\0';
703 3940506b 2005-01-13 devnull return(1);
704 3940506b 2005-01-13 devnull }
705 3940506b 2005-01-13 devnull if (buf <= end)
706 3940506b 2005-01-13 devnull *buf++ = r;
707 3940506b 2005-01-13 devnull }
708 3940506b 2005-01-13 devnull *buf = '\0';
709 3940506b 2005-01-13 devnull return(-1);
710 3940506b 2005-01-13 devnull }
711 3940506b 2005-01-13 devnull
712 3940506b 2005-01-13 devnull long
713 3940506b 2005-01-13 devnull getrune(void)
714 3940506b 2005-01-13 devnull {
715 3940506b 2005-01-13 devnull char *p;
716 3940506b 2005-01-13 devnull long c;
717 3940506b 2005-01-13 devnull Rune r;
718 3940506b 2005-01-13 devnull
719 3940506b 2005-01-13 devnull if (prog.type == P_ARG) {
720 3940506b 2005-01-13 devnull if ((p = prog.pctl.curr) != 0) {
721 3940506b 2005-01-13 devnull if (*p) {
722 3940506b 2005-01-13 devnull prog.pctl.curr += chartorune(&r, p);
723 3940506b 2005-01-13 devnull c = r;
724 3940506b 2005-01-13 devnull } else {
725 3940506b 2005-01-13 devnull c = '\n'; /* fake an end-of-line */
726 3940506b 2005-01-13 devnull prog.pctl.curr = 0;
727 3940506b 2005-01-13 devnull }
728 fa325e9b 2020-01-10 cross } else
729 3940506b 2005-01-13 devnull c = -1;
730 3940506b 2005-01-13 devnull } else if ((c = Bgetrune(prog.pctl.bp)) < 0)
731 3940506b 2005-01-13 devnull Bterm(prog.pctl.bp);
732 3940506b 2005-01-13 devnull return c;
733 3940506b 2005-01-13 devnull }
734 3940506b 2005-01-13 devnull
735 3940506b 2005-01-13 devnull void
736 3940506b 2005-01-13 devnull address(Addr *ap)
737 3940506b 2005-01-13 devnull {
738 3940506b 2005-01-13 devnull int c;
739 3940506b 2005-01-13 devnull long lno;
740 3940506b 2005-01-13 devnull
741 3940506b 2005-01-13 devnull if((c = *cp++) == '$')
742 3940506b 2005-01-13 devnull ap->type = A_DOL;
743 3940506b 2005-01-13 devnull else if(c == '/') {
744 3940506b 2005-01-13 devnull seof = c;
745 3940506b 2005-01-13 devnull if (ap->u.rp = compile())
746 3940506b 2005-01-13 devnull ap->type = A_RE;
747 3940506b 2005-01-13 devnull else
748 3940506b 2005-01-13 devnull ap->type = A_LAST;
749 3940506b 2005-01-13 devnull }
750 3940506b 2005-01-13 devnull else if (c >= '0' && c <= '9') {
751 3940506b 2005-01-13 devnull lno = c-'0';
752 3940506b 2005-01-13 devnull while ((c = *cp) >= '0' && c <= '9')
753 3940506b 2005-01-13 devnull lno = lno*10 + *cp++-'0';
754 3940506b 2005-01-13 devnull if(!lno)
755 3940506b 2005-01-13 devnull quit("line number 0 is illegal",0);
756 3940506b 2005-01-13 devnull ap->type = A_LINE;
757 3940506b 2005-01-13 devnull ap->u.line = lno;
758 3940506b 2005-01-13 devnull }
759 3940506b 2005-01-13 devnull else {
760 3940506b 2005-01-13 devnull cp--;
761 3940506b 2005-01-13 devnull ap->type = A_NONE;
762 3940506b 2005-01-13 devnull }
763 3940506b 2005-01-13 devnull }
764 3940506b 2005-01-13 devnull
765 3940506b 2005-01-13 devnull int
766 3940506b 2005-01-13 devnull cmp(char *a, char *b) /* compare characters */
767 3940506b 2005-01-13 devnull {
768 3940506b 2005-01-13 devnull while(*a == *b++)
769 3940506b 2005-01-13 devnull if (*a == '\0')
770 3940506b 2005-01-13 devnull return(0);
771 3940506b 2005-01-13 devnull else a++;
772 3940506b 2005-01-13 devnull return(1);
773 3940506b 2005-01-13 devnull }
774 3940506b 2005-01-13 devnull
775 3940506b 2005-01-13 devnull int
776 3940506b 2005-01-13 devnull rcmp(Rune *a, Rune *b) /* compare runes */
777 3940506b 2005-01-13 devnull {
778 3940506b 2005-01-13 devnull while(*a == *b++)
779 3940506b 2005-01-13 devnull if (*a == '\0')
780 3940506b 2005-01-13 devnull return(0);
781 3940506b 2005-01-13 devnull else a++;
782 3940506b 2005-01-13 devnull return(1);
783 3940506b 2005-01-13 devnull }
784 3940506b 2005-01-13 devnull
785 3940506b 2005-01-13 devnull char *
786 3940506b 2005-01-13 devnull text(char *p) /* extract character string */
787 3940506b 2005-01-13 devnull {
788 3940506b 2005-01-13 devnull Rune r;
789 3940506b 2005-01-13 devnull
790 3940506b 2005-01-13 devnull while(*cp == '\t' || *cp == ' ')
791 3940506b 2005-01-13 devnull cp++;
792 3940506b 2005-01-13 devnull while (*cp) {
793 3940506b 2005-01-13 devnull if ((r = *cp++) == '\\')
794 3940506b 2005-01-13 devnull if ((r = *cp++) == 0)
795 3940506b 2005-01-13 devnull break;;
796 3940506b 2005-01-13 devnull if (r == '\n')
797 3940506b 2005-01-13 devnull while (*cp == '\t' || *cp == ' ')
798 3940506b 2005-01-13 devnull cp++;
799 3940506b 2005-01-13 devnull p += runetochar(p, &r);
800 3940506b 2005-01-13 devnull }
801 3940506b 2005-01-13 devnull *p++ = '\0';
802 3940506b 2005-01-13 devnull return p;
803 3940506b 2005-01-13 devnull }
804 3940506b 2005-01-13 devnull
805 3940506b 2005-01-13 devnull Rune *
806 3940506b 2005-01-13 devnull stext(Rune *p, Rune *end) /* extract rune string */
807 3940506b 2005-01-13 devnull {
808 3940506b 2005-01-13 devnull while(*cp == '\t' || *cp == ' ')
809 3940506b 2005-01-13 devnull cp++;
810 3940506b 2005-01-13 devnull while (*cp) {
811 3940506b 2005-01-13 devnull if (*cp == '\\')
812 3940506b 2005-01-13 devnull if (*++cp == 0)
813 3940506b 2005-01-13 devnull break;
814 3940506b 2005-01-13 devnull if (p >= end-1)
815 3940506b 2005-01-13 devnull quit(TMMES, (char *) linebuf);
816 3940506b 2005-01-13 devnull if ((*p++ = *cp++) == '\n')
817 3940506b 2005-01-13 devnull while(*cp == '\t' || *cp == ' ')
818 3940506b 2005-01-13 devnull cp++;
819 3940506b 2005-01-13 devnull }
820 3940506b 2005-01-13 devnull *p++ = 0;
821 3940506b 2005-01-13 devnull return p;
822 3940506b 2005-01-13 devnull }
823 3940506b 2005-01-13 devnull
824 3940506b 2005-01-13 devnull
825 3940506b 2005-01-13 devnull Label *
826 3940506b 2005-01-13 devnull search (Label *ptr)
827 3940506b 2005-01-13 devnull {
828 3940506b 2005-01-13 devnull Label *rp;
829 3940506b 2005-01-13 devnull
830 3940506b 2005-01-13 devnull for (rp = ltab; rp < ptr; rp++)
831 3940506b 2005-01-13 devnull if(rcmp(rp->asc, ptr->asc) == 0)
832 3940506b 2005-01-13 devnull return(rp);
833 3940506b 2005-01-13 devnull return(0);
834 3940506b 2005-01-13 devnull }
835 3940506b 2005-01-13 devnull
836 3940506b 2005-01-13 devnull void
837 3940506b 2005-01-13 devnull dechain(void)
838 3940506b 2005-01-13 devnull {
839 3940506b 2005-01-13 devnull Label *lptr;
840 3940506b 2005-01-13 devnull SedCom *rptr, *trptr;
841 3940506b 2005-01-13 devnull
842 3940506b 2005-01-13 devnull for(lptr = ltab; lptr < lab; lptr++) {
843 3940506b 2005-01-13 devnull
844 3940506b 2005-01-13 devnull if(lptr->address == 0)
845 3940506b 2005-01-13 devnull quit("Undefined label: %S", (char *) lptr->asc);
846 3940506b 2005-01-13 devnull
847 3940506b 2005-01-13 devnull if(lptr->chain) {
848 3940506b 2005-01-13 devnull rptr = lptr->chain;
849 3940506b 2005-01-13 devnull while(trptr = rptr->u.lb1) {
850 3940506b 2005-01-13 devnull rptr->u.lb1 = lptr->address;
851 3940506b 2005-01-13 devnull rptr = trptr;
852 3940506b 2005-01-13 devnull }
853 3940506b 2005-01-13 devnull rptr->u.lb1 = lptr->address;
854 3940506b 2005-01-13 devnull }
855 3940506b 2005-01-13 devnull }
856 3940506b 2005-01-13 devnull }
857 3940506b 2005-01-13 devnull
858 3940506b 2005-01-13 devnull int
859 3940506b 2005-01-13 devnull ycomp(SedCom *r)
860 3940506b 2005-01-13 devnull {
861 3940506b 2005-01-13 devnull int i;
862 3940506b 2005-01-13 devnull Rune *rp;
863 3940506b 2005-01-13 devnull Rune c, *tsp, highc;
864 3940506b 2005-01-13 devnull Rune *sp;
865 3940506b 2005-01-13 devnull
866 3940506b 2005-01-13 devnull highc = 0;
867 3940506b 2005-01-13 devnull for(tsp = cp; *tsp != seof; tsp++) {
868 3940506b 2005-01-13 devnull if(*tsp == '\\')
869 3940506b 2005-01-13 devnull tsp++;
870 3940506b 2005-01-13 devnull if(*tsp == '\n' || *tsp == '\0')
871 3940506b 2005-01-13 devnull return(0);
872 3940506b 2005-01-13 devnull if (*tsp > highc) highc = *tsp;
873 3940506b 2005-01-13 devnull }
874 3940506b 2005-01-13 devnull tsp++;
875 3940506b 2005-01-13 devnull if ((rp = r->u.text = (Rune *) malloc(sizeof(Rune)*(highc+2))) == 0)
876 3940506b 2005-01-13 devnull quit("Out of memory", 0);
877 3940506b 2005-01-13 devnull *rp++ = highc; /* save upper bound */
878 3940506b 2005-01-13 devnull for (i = 0; i <= highc; i++)
879 3940506b 2005-01-13 devnull rp[i] = i;
880 3940506b 2005-01-13 devnull sp = cp;
881 3940506b 2005-01-13 devnull while((c = *sp++) != seof) {
882 3940506b 2005-01-13 devnull if(c == '\\' && *sp == 'n') {
883 3940506b 2005-01-13 devnull sp++;
884 3940506b 2005-01-13 devnull c = '\n';
885 3940506b 2005-01-13 devnull }
886 3940506b 2005-01-13 devnull if((rp[c] = *tsp++) == '\\' && *tsp == 'n') {
887 3940506b 2005-01-13 devnull rp[c] = '\n';
888 3940506b 2005-01-13 devnull tsp++;
889 3940506b 2005-01-13 devnull }
890 3940506b 2005-01-13 devnull if(rp[c] == seof || rp[c] == '\0') {
891 3940506b 2005-01-13 devnull free(r->u.re1);
892 3940506b 2005-01-13 devnull r->u.re1 = 0;
893 3940506b 2005-01-13 devnull return(0);
894 3940506b 2005-01-13 devnull }
895 3940506b 2005-01-13 devnull }
896 3940506b 2005-01-13 devnull if(*tsp != seof) {
897 3940506b 2005-01-13 devnull free(r->u.re1);
898 3940506b 2005-01-13 devnull r->u.re1 = 0;
899 3940506b 2005-01-13 devnull return(0);
900 3940506b 2005-01-13 devnull }
901 3940506b 2005-01-13 devnull cp = tsp+1;
902 3940506b 2005-01-13 devnull return(1);
903 3940506b 2005-01-13 devnull }
904 3940506b 2005-01-13 devnull
905 3940506b 2005-01-13 devnull void
906 3940506b 2005-01-13 devnull execute(void)
907 3940506b 2005-01-13 devnull {
908 3940506b 2005-01-13 devnull SedCom *ipc;
909 3940506b 2005-01-13 devnull
910 3940506b 2005-01-13 devnull while (spend = gline(linebuf)){
911 3940506b 2005-01-13 devnull for(ipc = pspace; ipc->command; ) {
912 3940506b 2005-01-13 devnull if (!executable(ipc)) {
913 3940506b 2005-01-13 devnull ipc++;
914 3940506b 2005-01-13 devnull continue;
915 3940506b 2005-01-13 devnull }
916 3940506b 2005-01-13 devnull command(ipc);
917 3940506b 2005-01-13 devnull
918 3940506b 2005-01-13 devnull if(delflag)
919 3940506b 2005-01-13 devnull break;
920 3940506b 2005-01-13 devnull if(jflag) {
921 3940506b 2005-01-13 devnull jflag = 0;
922 3940506b 2005-01-13 devnull if((ipc = ipc->u.lb1) == 0)
923 3940506b 2005-01-13 devnull break;
924 3940506b 2005-01-13 devnull } else
925 3940506b 2005-01-13 devnull ipc++;
926 3940506b 2005-01-13 devnull
927 3940506b 2005-01-13 devnull }
928 3940506b 2005-01-13 devnull if(!nflag && !delflag)
929 3940506b 2005-01-13 devnull putline(&fout, linebuf, spend-linebuf);
930 3940506b 2005-01-13 devnull if(aptr > abuf) {
931 3940506b 2005-01-13 devnull arout();
932 3940506b 2005-01-13 devnull }
933 3940506b 2005-01-13 devnull delflag = 0;
934 3940506b 2005-01-13 devnull }
935 3940506b 2005-01-13 devnull }
936 3940506b 2005-01-13 devnull /* determine if a statement should be applied to an input line */
937 3940506b 2005-01-13 devnull int
938 3940506b 2005-01-13 devnull executable(SedCom *ipc)
939 3940506b 2005-01-13 devnull {
940 3940506b 2005-01-13 devnull if (ipc->active) { /* Addr1 satisfied - accept until Addr2 */
941 3940506b 2005-01-13 devnull if (ipc->active == 1) /* Second line */
942 3940506b 2005-01-13 devnull ipc->active = 2;
943 3940506b 2005-01-13 devnull switch(ipc->ad2.type) {
944 3940506b 2005-01-13 devnull case A_NONE: /* No second addr; use first */
945 3940506b 2005-01-13 devnull ipc->active = 0;
946 3940506b 2005-01-13 devnull break;
947 3940506b 2005-01-13 devnull case A_DOL: /* Accept everything */
948 3940506b 2005-01-13 devnull return !ipc->negfl;
949 3940506b 2005-01-13 devnull case A_LINE: /* Line at end of range? */
950 3940506b 2005-01-13 devnull if (lnum <= ipc->ad2.u.line) {
951 3940506b 2005-01-13 devnull if (ipc->ad2.u.line == lnum)
952 3940506b 2005-01-13 devnull ipc->active = 0;
953 3940506b 2005-01-13 devnull return !ipc->negfl;
954 3940506b 2005-01-13 devnull }
955 3940506b 2005-01-13 devnull ipc->active = 0; /* out of range */
956 3940506b 2005-01-13 devnull return ipc->negfl;
957 3940506b 2005-01-13 devnull case A_RE: /* Check for matching R.E. */
958 3940506b 2005-01-13 devnull if (match(ipc->ad2.u.rp, linebuf))
959 3940506b 2005-01-13 devnull ipc->active = 0;
960 3940506b 2005-01-13 devnull return !ipc->negfl;
961 3940506b 2005-01-13 devnull default: /* internal error */
962 3940506b 2005-01-13 devnull quit("Internal error", 0);
963 3940506b 2005-01-13 devnull }
964 3940506b 2005-01-13 devnull }
965 3940506b 2005-01-13 devnull switch (ipc->ad1.type) { /* Check first address */
966 3940506b 2005-01-13 devnull case A_NONE: /* Everything matches */
967 3940506b 2005-01-13 devnull return !ipc->negfl;
968 3940506b 2005-01-13 devnull case A_DOL: /* Only last line */
969 3940506b 2005-01-13 devnull if (dolflag)
970 3940506b 2005-01-13 devnull return !ipc->negfl;
971 3940506b 2005-01-13 devnull break;
972 3940506b 2005-01-13 devnull case A_LINE: /* Check line number */
973 3940506b 2005-01-13 devnull if (ipc->ad1.u.line == lnum) {
974 3940506b 2005-01-13 devnull ipc->active = 1; /* In range */
975 3940506b 2005-01-13 devnull return !ipc->negfl;
976 3940506b 2005-01-13 devnull }
977 3940506b 2005-01-13 devnull break;
978 3940506b 2005-01-13 devnull case A_RE: /* Check R.E. */
979 3940506b 2005-01-13 devnull if (match(ipc->ad1.u.rp, linebuf)) {
980 3940506b 2005-01-13 devnull ipc->active = 1; /* In range */
981 3940506b 2005-01-13 devnull return !ipc->negfl;
982 3940506b 2005-01-13 devnull }
983 3940506b 2005-01-13 devnull break;
984 3940506b 2005-01-13 devnull default:
985 3940506b 2005-01-13 devnull quit("Internal error", 0);
986 3940506b 2005-01-13 devnull }
987 3940506b 2005-01-13 devnull return ipc->negfl;
988 3940506b 2005-01-13 devnull }
989 3940506b 2005-01-13 devnull
990 3940506b 2005-01-13 devnull int
991 3940506b 2005-01-13 devnull match(Reprog *pattern, Rune *buf)
992 3940506b 2005-01-13 devnull {
993 3940506b 2005-01-13 devnull if (!pattern)
994 3940506b 2005-01-13 devnull return 0;
995 fa325e9b 2020-01-10 cross subexp[0].s.rsp = buf;
996 3940506b 2005-01-13 devnull subexp[0].e.rep = 0;
997 ee85defd 2009-02-05 rsc if (rregexec(pattern, linebuf, subexp, MAXSUB) > 0) {
998 3940506b 2005-01-13 devnull loc1 = subexp[0].s.rsp;
999 3940506b 2005-01-13 devnull loc2 = subexp[0].e.rep;
1000 3940506b 2005-01-13 devnull return 1;
1001 3940506b 2005-01-13 devnull }
1002 3940506b 2005-01-13 devnull loc1 = loc2 = 0;
1003 3940506b 2005-01-13 devnull return 0;
1004 3940506b 2005-01-13 devnull }
1005 3940506b 2005-01-13 devnull
1006 3940506b 2005-01-13 devnull int
1007 3940506b 2005-01-13 devnull substitute(SedCom *ipc)
1008 3940506b 2005-01-13 devnull {
1009 3940506b 2005-01-13 devnull int len;
1010 3940506b 2005-01-13 devnull
1011 3940506b 2005-01-13 devnull if(!match(ipc->u.re1, linebuf))
1012 3940506b 2005-01-13 devnull return 0;
1013 3940506b 2005-01-13 devnull
1014 3940506b 2005-01-13 devnull /*
1015 3940506b 2005-01-13 devnull * we have at least one match. some patterns, e.g. '$' or '^', can
1016 3940506b 2005-01-13 devnull * produce zero-length matches, so during a global substitute we
1017 3940506b 2005-01-13 devnull * must bump to the character after a zero-length match to keep from looping.
1018 3940506b 2005-01-13 devnull */
1019 3940506b 2005-01-13 devnull sflag = 1;
1020 3940506b 2005-01-13 devnull if(ipc->gfl == 0) /* single substitution */
1021 3940506b 2005-01-13 devnull dosub(ipc->rhs);
1022 3940506b 2005-01-13 devnull else
1023 3940506b 2005-01-13 devnull do{ /* global substitution */
1024 3940506b 2005-01-13 devnull len = loc2-loc1; /* length of match */
1025 3940506b 2005-01-13 devnull dosub(ipc->rhs); /* dosub moves loc2 */
1026 3940506b 2005-01-13 devnull if(*loc2 == 0) /* end of string */
1027 3940506b 2005-01-13 devnull break;
1028 3940506b 2005-01-13 devnull if(len == 0) /* zero-length R.E. match */
1029 3940506b 2005-01-13 devnull loc2++; /* bump over zero-length match */
1030 3940506b 2005-01-13 devnull if(*loc2 == 0) /* end of string */
1031 3940506b 2005-01-13 devnull break;
1032 3940506b 2005-01-13 devnull } while(match(ipc->u.re1, loc2));
1033 3940506b 2005-01-13 devnull return 1;
1034 3940506b 2005-01-13 devnull }
1035 3940506b 2005-01-13 devnull
1036 3940506b 2005-01-13 devnull void
1037 3940506b 2005-01-13 devnull dosub(Rune *rhsbuf)
1038 3940506b 2005-01-13 devnull {
1039 3940506b 2005-01-13 devnull Rune *lp, *sp;
1040 3940506b 2005-01-13 devnull Rune *rp;
1041 3940506b 2005-01-13 devnull int c, n;
1042 3940506b 2005-01-13 devnull
1043 3940506b 2005-01-13 devnull lp = linebuf;
1044 3940506b 2005-01-13 devnull sp = genbuf;
1045 3940506b 2005-01-13 devnull rp = rhsbuf;
1046 3940506b 2005-01-13 devnull while (lp < loc1)
1047 3940506b 2005-01-13 devnull *sp++ = *lp++;
1048 3940506b 2005-01-13 devnull while(c = *rp++) {
1049 3940506b 2005-01-13 devnull if (c == '&') {
1050 3940506b 2005-01-13 devnull sp = place(sp, loc1, loc2);
1051 3940506b 2005-01-13 devnull continue;
1052 3940506b 2005-01-13 devnull }
1053 0cadb430 2009-09-11 russcox if (c == Runemax && (c = *rp++) >= '1' && c < MAXSUB+'0') {
1054 3940506b 2005-01-13 devnull n = c-'0';
1055 3940506b 2005-01-13 devnull if (subexp[n].s.rsp && subexp[n].e.rep) {
1056 3940506b 2005-01-13 devnull sp = place(sp, subexp[n].s.rsp, subexp[n].e.rep);
1057 3940506b 2005-01-13 devnull continue;
1058 3940506b 2005-01-13 devnull }
1059 3940506b 2005-01-13 devnull else {
1060 3940506b 2005-01-13 devnull fprint(2, "sed: Invalid back reference \\%d\n",n);
1061 3940506b 2005-01-13 devnull errexit();
1062 3940506b 2005-01-13 devnull }
1063 3940506b 2005-01-13 devnull }
1064 3940506b 2005-01-13 devnull *sp++ = c;
1065 3940506b 2005-01-13 devnull if (sp >= &genbuf[LBSIZE])
1066 3940506b 2005-01-13 devnull fprint(2, "sed: Output line too long.\n");
1067 3940506b 2005-01-13 devnull }
1068 3940506b 2005-01-13 devnull lp = loc2;
1069 3940506b 2005-01-13 devnull loc2 = sp - genbuf + linebuf;
1070 3940506b 2005-01-13 devnull while (*sp++ = *lp++)
1071 3940506b 2005-01-13 devnull if (sp >= &genbuf[LBSIZE])
1072 3940506b 2005-01-13 devnull fprint(2, "sed: Output line too long.\n");
1073 3940506b 2005-01-13 devnull lp = linebuf;
1074 3940506b 2005-01-13 devnull sp = genbuf;
1075 3940506b 2005-01-13 devnull while (*lp++ = *sp++)
1076 3940506b 2005-01-13 devnull ;
1077 3940506b 2005-01-13 devnull spend = lp-1;
1078 3940506b 2005-01-13 devnull }
1079 3940506b 2005-01-13 devnull
1080 3940506b 2005-01-13 devnull Rune *
1081 3940506b 2005-01-13 devnull place(Rune *sp, Rune *l1, Rune *l2)
1082 3940506b 2005-01-13 devnull {
1083 3940506b 2005-01-13 devnull while (l1 < l2) {
1084 3940506b 2005-01-13 devnull *sp++ = *l1++;
1085 3940506b 2005-01-13 devnull if (sp >= &genbuf[LBSIZE])
1086 3940506b 2005-01-13 devnull fprint(2, "sed: Output line too long.\n");
1087 3940506b 2005-01-13 devnull }
1088 3940506b 2005-01-13 devnull return(sp);
1089 3940506b 2005-01-13 devnull }
1090 3940506b 2005-01-13 devnull
1091 3940506b 2005-01-13 devnull char *
1092 3940506b 2005-01-13 devnull trans(int c)
1093 3940506b 2005-01-13 devnull {
1094 3940506b 2005-01-13 devnull static char buf[] = "\\x0000";
1095 3940506b 2005-01-13 devnull static char hex[] = "0123456789abcdef";
1096 3940506b 2005-01-13 devnull
1097 3940506b 2005-01-13 devnull switch(c) {
1098 3940506b 2005-01-13 devnull case '\b':
1099 3940506b 2005-01-13 devnull return "\\b";
1100 3940506b 2005-01-13 devnull case '\n':
1101 3940506b 2005-01-13 devnull return "\\n";
1102 3940506b 2005-01-13 devnull case '\r':
1103 3940506b 2005-01-13 devnull return "\\r";
1104 3940506b 2005-01-13 devnull case '\t':
1105 3940506b 2005-01-13 devnull return "\\t";
1106 3940506b 2005-01-13 devnull case '\\':
1107 3940506b 2005-01-13 devnull return "\\\\";
1108 3940506b 2005-01-13 devnull }
1109 3940506b 2005-01-13 devnull buf[2] = hex[(c>>12)&0xF];
1110 3940506b 2005-01-13 devnull buf[3] = hex[(c>>8)&0xF];
1111 3940506b 2005-01-13 devnull buf[4] = hex[(c>>4)&0xF];
1112 3940506b 2005-01-13 devnull buf[5] = hex[c&0xF];
1113 3940506b 2005-01-13 devnull return buf;
1114 3940506b 2005-01-13 devnull }
1115 3940506b 2005-01-13 devnull
1116 3940506b 2005-01-13 devnull void
1117 3940506b 2005-01-13 devnull command(SedCom *ipc)
1118 3940506b 2005-01-13 devnull {
1119 3940506b 2005-01-13 devnull int i, c;
1120 3940506b 2005-01-13 devnull Rune *p1, *p2;
1121 3940506b 2005-01-13 devnull char *ucp;
1122 3940506b 2005-01-13 devnull Rune *rp;
1123 3940506b 2005-01-13 devnull Rune *execp;
1124 3940506b 2005-01-13 devnull
1125 3940506b 2005-01-13 devnull switch(ipc->command) {
1126 3940506b 2005-01-13 devnull
1127 3940506b 2005-01-13 devnull case ACOM:
1128 3940506b 2005-01-13 devnull *aptr++ = ipc;
1129 3940506b 2005-01-13 devnull if(aptr >= abuf+MAXADDS) {
1130 3940506b 2005-01-13 devnull quit("sed: Too many appends after line %ld\n",
1131 3940506b 2005-01-13 devnull (char *) lnum);
1132 3940506b 2005-01-13 devnull }
1133 3940506b 2005-01-13 devnull *aptr = 0;
1134 3940506b 2005-01-13 devnull break;
1135 3940506b 2005-01-13 devnull case CCOM:
1136 3940506b 2005-01-13 devnull delflag = 1;
1137 3940506b 2005-01-13 devnull if(ipc->active == 1) {
1138 3940506b 2005-01-13 devnull for(rp = ipc->u.text; *rp; rp++)
1139 3940506b 2005-01-13 devnull Bputrune(&fout, *rp);
1140 3940506b 2005-01-13 devnull Bputc(&fout, '\n');
1141 3940506b 2005-01-13 devnull }
1142 3940506b 2005-01-13 devnull break;
1143 3940506b 2005-01-13 devnull case DCOM:
1144 3940506b 2005-01-13 devnull delflag++;
1145 3940506b 2005-01-13 devnull break;
1146 3940506b 2005-01-13 devnull case CDCOM:
1147 3940506b 2005-01-13 devnull p1 = p2 = linebuf;
1148 3940506b 2005-01-13 devnull while(*p1 != '\n') {
1149 3940506b 2005-01-13 devnull if(*p1++ == 0) {
1150 3940506b 2005-01-13 devnull delflag++;
1151 3940506b 2005-01-13 devnull return;
1152 3940506b 2005-01-13 devnull }
1153 3940506b 2005-01-13 devnull }
1154 3940506b 2005-01-13 devnull p1++;
1155 3940506b 2005-01-13 devnull while(*p2++ = *p1++)
1156 3940506b 2005-01-13 devnull ;
1157 3940506b 2005-01-13 devnull spend = p2-1;
1158 3940506b 2005-01-13 devnull jflag++;
1159 3940506b 2005-01-13 devnull break;
1160 3940506b 2005-01-13 devnull case EQCOM:
1161 3940506b 2005-01-13 devnull Bprint(&fout, "%ld\n", lnum);
1162 3940506b 2005-01-13 devnull break;
1163 3940506b 2005-01-13 devnull case GCOM:
1164 3940506b 2005-01-13 devnull p1 = linebuf;
1165 3940506b 2005-01-13 devnull p2 = holdsp;
1166 3940506b 2005-01-13 devnull while(*p1++ = *p2++)
1167 3940506b 2005-01-13 devnull ;
1168 3940506b 2005-01-13 devnull spend = p1-1;
1169 3940506b 2005-01-13 devnull break;
1170 3940506b 2005-01-13 devnull case CGCOM:
1171 3940506b 2005-01-13 devnull *spend++ = '\n';
1172 3940506b 2005-01-13 devnull p1 = spend;
1173 3940506b 2005-01-13 devnull p2 = holdsp;
1174 3940506b 2005-01-13 devnull while(*p1++ = *p2++)
1175 3940506b 2005-01-13 devnull if(p1 >= lbend)
1176 3940506b 2005-01-13 devnull break;
1177 3940506b 2005-01-13 devnull spend = p1-1;
1178 3940506b 2005-01-13 devnull break;
1179 3940506b 2005-01-13 devnull case HCOM:
1180 3940506b 2005-01-13 devnull p1 = holdsp;
1181 3940506b 2005-01-13 devnull p2 = linebuf;
1182 3940506b 2005-01-13 devnull while(*p1++ = *p2++);
1183 3940506b 2005-01-13 devnull hspend = p1-1;
1184 3940506b 2005-01-13 devnull break;
1185 3940506b 2005-01-13 devnull case CHCOM:
1186 3940506b 2005-01-13 devnull *hspend++ = '\n';
1187 3940506b 2005-01-13 devnull p1 = hspend;
1188 3940506b 2005-01-13 devnull p2 = linebuf;
1189 3940506b 2005-01-13 devnull while(*p1++ = *p2++)
1190 3940506b 2005-01-13 devnull if(p1 >= hend)
1191 3940506b 2005-01-13 devnull break;
1192 3940506b 2005-01-13 devnull hspend = p1-1;
1193 3940506b 2005-01-13 devnull break;
1194 3940506b 2005-01-13 devnull case ICOM:
1195 3940506b 2005-01-13 devnull for(rp = ipc->u.text; *rp; rp++)
1196 3940506b 2005-01-13 devnull Bputrune(&fout, *rp);
1197 3940506b 2005-01-13 devnull Bputc(&fout, '\n');
1198 3940506b 2005-01-13 devnull break;
1199 3940506b 2005-01-13 devnull case BCOM:
1200 3940506b 2005-01-13 devnull jflag = 1;
1201 3940506b 2005-01-13 devnull break;
1202 3940506b 2005-01-13 devnull case LCOM:
1203 3940506b 2005-01-13 devnull c = 0;
1204 3940506b 2005-01-13 devnull for (i = 0, rp = linebuf; *rp; rp++) {
1205 3940506b 2005-01-13 devnull c = *rp;
1206 3940506b 2005-01-13 devnull if(c >= 0x20 && c < 0x7F && c != '\\') {
1207 3940506b 2005-01-13 devnull Bputc(&fout, c);
1208 3940506b 2005-01-13 devnull if(i++ > 71) {
1209 3940506b 2005-01-13 devnull Bprint(&fout, "\\\n");
1210 3940506b 2005-01-13 devnull i = 0;
1211 3940506b 2005-01-13 devnull }
1212 3940506b 2005-01-13 devnull } else {
1213 3940506b 2005-01-13 devnull for (ucp = trans(*rp); *ucp; ucp++){
1214 3940506b 2005-01-13 devnull c = *ucp;
1215 3940506b 2005-01-13 devnull Bputc(&fout, c);
1216 3940506b 2005-01-13 devnull if(i++ > 71) {
1217 3940506b 2005-01-13 devnull Bprint(&fout, "\\\n");
1218 3940506b 2005-01-13 devnull i = 0;
1219 3940506b 2005-01-13 devnull }
1220 3940506b 2005-01-13 devnull }
1221 3940506b 2005-01-13 devnull }
1222 3940506b 2005-01-13 devnull }
1223 3940506b 2005-01-13 devnull if(c == ' ')
1224 3940506b 2005-01-13 devnull Bprint(&fout, "\\n");
1225 3940506b 2005-01-13 devnull Bputc(&fout, '\n');
1226 3940506b 2005-01-13 devnull break;
1227 3940506b 2005-01-13 devnull case NCOM:
1228 3940506b 2005-01-13 devnull if(!nflag)
1229 3940506b 2005-01-13 devnull putline(&fout, linebuf, spend-linebuf);
1230 3940506b 2005-01-13 devnull
1231 3940506b 2005-01-13 devnull if(aptr > abuf)
1232 3940506b 2005-01-13 devnull arout();
1233 3940506b 2005-01-13 devnull if((execp = gline(linebuf)) == 0) {
1234 3940506b 2005-01-13 devnull delflag = 1;
1235 3940506b 2005-01-13 devnull break;
1236 3940506b 2005-01-13 devnull }
1237 3940506b 2005-01-13 devnull spend = execp;
1238 3940506b 2005-01-13 devnull break;
1239 3940506b 2005-01-13 devnull case CNCOM:
1240 3940506b 2005-01-13 devnull if(aptr > abuf)
1241 3940506b 2005-01-13 devnull arout();
1242 3940506b 2005-01-13 devnull *spend++ = '\n';
1243 3940506b 2005-01-13 devnull if((execp = gline(spend)) == 0) {
1244 3940506b 2005-01-13 devnull delflag = 1;
1245 3940506b 2005-01-13 devnull break;
1246 3940506b 2005-01-13 devnull }
1247 3940506b 2005-01-13 devnull spend = execp;
1248 3940506b 2005-01-13 devnull break;
1249 3940506b 2005-01-13 devnull case PCOM:
1250 3940506b 2005-01-13 devnull putline(&fout, linebuf, spend-linebuf);
1251 3940506b 2005-01-13 devnull break;
1252 3940506b 2005-01-13 devnull case CPCOM:
1253 3940506b 2005-01-13 devnull cpcom:
1254 3940506b 2005-01-13 devnull for(rp = linebuf; *rp && *rp != '\n'; rp++)
1255 3940506b 2005-01-13 devnull Bputc(&fout, *rp);
1256 3940506b 2005-01-13 devnull Bputc(&fout, '\n');
1257 3940506b 2005-01-13 devnull break;
1258 3940506b 2005-01-13 devnull case QCOM:
1259 3940506b 2005-01-13 devnull if(!nflag)
1260 3940506b 2005-01-13 devnull putline(&fout, linebuf, spend-linebuf);
1261 3940506b 2005-01-13 devnull if(aptr > abuf)
1262 3940506b 2005-01-13 devnull arout();
1263 3940506b 2005-01-13 devnull exits(0);
1264 3940506b 2005-01-13 devnull case RCOM:
1265 3940506b 2005-01-13 devnull *aptr++ = ipc;
1266 3940506b 2005-01-13 devnull if(aptr >= &abuf[MAXADDS])
1267 3940506b 2005-01-13 devnull quit("sed: Too many reads after line %ld\n",
1268 3940506b 2005-01-13 devnull (char *) lnum);
1269 3940506b 2005-01-13 devnull *aptr = 0;
1270 3940506b 2005-01-13 devnull break;
1271 3940506b 2005-01-13 devnull case SCOM:
1272 3940506b 2005-01-13 devnull i = substitute(ipc);
1273 3940506b 2005-01-13 devnull if(i && ipc->pfl)
1274 3940506b 2005-01-13 devnull if(ipc->pfl == 1)
1275 3940506b 2005-01-13 devnull putline(&fout, linebuf, spend-linebuf);
1276 3940506b 2005-01-13 devnull else
1277 3940506b 2005-01-13 devnull goto cpcom;
1278 3940506b 2005-01-13 devnull if(i && ipc->fcode)
1279 3940506b 2005-01-13 devnull goto wcom;
1280 3940506b 2005-01-13 devnull break;
1281 3940506b 2005-01-13 devnull
1282 3940506b 2005-01-13 devnull case TCOM:
1283 3940506b 2005-01-13 devnull if(sflag == 0) break;
1284 3940506b 2005-01-13 devnull sflag = 0;
1285 3940506b 2005-01-13 devnull jflag = 1;
1286 3940506b 2005-01-13 devnull break;
1287 3940506b 2005-01-13 devnull
1288 3940506b 2005-01-13 devnull wcom:
1289 3940506b 2005-01-13 devnull case WCOM:
1290 3940506b 2005-01-13 devnull putline(ipc->fcode,linebuf, spend-linebuf);
1291 3940506b 2005-01-13 devnull break;
1292 3940506b 2005-01-13 devnull case XCOM:
1293 3940506b 2005-01-13 devnull p1 = linebuf;
1294 3940506b 2005-01-13 devnull p2 = genbuf;
1295 3940506b 2005-01-13 devnull while(*p2++ = *p1++);
1296 3940506b 2005-01-13 devnull p1 = holdsp;
1297 3940506b 2005-01-13 devnull p2 = linebuf;
1298 3940506b 2005-01-13 devnull while(*p2++ = *p1++);
1299 3940506b 2005-01-13 devnull spend = p2 - 1;
1300 3940506b 2005-01-13 devnull p1 = genbuf;
1301 3940506b 2005-01-13 devnull p2 = holdsp;
1302 3940506b 2005-01-13 devnull while(*p2++ = *p1++);
1303 3940506b 2005-01-13 devnull hspend = p2 - 1;
1304 3940506b 2005-01-13 devnull break;
1305 3940506b 2005-01-13 devnull case YCOM:
1306 3940506b 2005-01-13 devnull p1 = linebuf;
1307 3940506b 2005-01-13 devnull p2 = ipc->u.text;
1308 3940506b 2005-01-13 devnull for (i = *p2++; *p1; p1++){
1309 3940506b 2005-01-13 devnull if (*p1 <= i) *p1 = p2[*p1];
1310 3940506b 2005-01-13 devnull }
1311 3940506b 2005-01-13 devnull break;
1312 3940506b 2005-01-13 devnull }
1313 3940506b 2005-01-13 devnull
1314 3940506b 2005-01-13 devnull }
1315 3940506b 2005-01-13 devnull
1316 3940506b 2005-01-13 devnull void
1317 3940506b 2005-01-13 devnull putline(Biobuf *bp, Rune *buf, int n)
1318 3940506b 2005-01-13 devnull {
1319 3940506b 2005-01-13 devnull while (n--)
1320 3940506b 2005-01-13 devnull Bputrune(bp, *buf++);
1321 3940506b 2005-01-13 devnull Bputc(bp, '\n');
1322 a09e8575 2006-06-26 devnull if(lflag)
1323 a09e8575 2006-06-26 devnull Bflush(bp);
1324 3940506b 2005-01-13 devnull }
1325 3940506b 2005-01-13 devnull
1326 3940506b 2005-01-13 devnull int
1327 3940506b 2005-01-13 devnull ecmp(Rune *a, Rune *b, int count)
1328 3940506b 2005-01-13 devnull {
1329 3940506b 2005-01-13 devnull while(count--)
1330 3940506b 2005-01-13 devnull if(*a++ != *b++) return(0);
1331 3940506b 2005-01-13 devnull return(1);
1332 3940506b 2005-01-13 devnull }
1333 3940506b 2005-01-13 devnull
1334 3940506b 2005-01-13 devnull void
1335 3940506b 2005-01-13 devnull arout(void)
1336 3940506b 2005-01-13 devnull {
1337 3940506b 2005-01-13 devnull Rune *p1;
1338 3940506b 2005-01-13 devnull Biobuf *fi;
1339 3940506b 2005-01-13 devnull int c;
1340 3940506b 2005-01-13 devnull char *s;
1341 3940506b 2005-01-13 devnull char buf[128];
1342 3940506b 2005-01-13 devnull
1343 3940506b 2005-01-13 devnull for (aptr = abuf; *aptr; aptr++) {
1344 3940506b 2005-01-13 devnull if((*aptr)->command == ACOM) {
1345 3940506b 2005-01-13 devnull for(p1 = (*aptr)->u.text; *p1; p1++ )
1346 3940506b 2005-01-13 devnull Bputrune(&fout, *p1);
1347 3940506b 2005-01-13 devnull Bputc(&fout, '\n');
1348 3940506b 2005-01-13 devnull } else {
1349 3940506b 2005-01-13 devnull for(s = buf, p1= (*aptr)->u.text; *p1; p1++)
1350 3940506b 2005-01-13 devnull s += runetochar(s, p1);
1351 3940506b 2005-01-13 devnull *s = '\0';
1352 3940506b 2005-01-13 devnull if((fi = Bopen(buf, OREAD)) == 0)
1353 3940506b 2005-01-13 devnull continue;
1354 3940506b 2005-01-13 devnull while((c = Bgetc(fi)) >= 0)
1355 3940506b 2005-01-13 devnull Bputc(&fout, c);
1356 3940506b 2005-01-13 devnull Bterm(fi);
1357 3940506b 2005-01-13 devnull }
1358 3940506b 2005-01-13 devnull }
1359 3940506b 2005-01-13 devnull aptr = abuf;
1360 3940506b 2005-01-13 devnull *aptr = 0;
1361 3940506b 2005-01-13 devnull }
1362 3940506b 2005-01-13 devnull
1363 3940506b 2005-01-13 devnull void
1364 3940506b 2005-01-13 devnull errexit(void)
1365 3940506b 2005-01-13 devnull {
1366 3940506b 2005-01-13 devnull exits("error");
1367 3940506b 2005-01-13 devnull }
1368 3940506b 2005-01-13 devnull
1369 3940506b 2005-01-13 devnull void
1370 3940506b 2005-01-13 devnull quit (char *msg, char *arg)
1371 3940506b 2005-01-13 devnull {
1372 3940506b 2005-01-13 devnull fprint(2, "sed: ");
1373 3940506b 2005-01-13 devnull fprint(2, msg, arg);
1374 3940506b 2005-01-13 devnull fprint(2, "\n");
1375 3940506b 2005-01-13 devnull errexit();
1376 3940506b 2005-01-13 devnull }
1377 3940506b 2005-01-13 devnull
1378 3940506b 2005-01-13 devnull Rune *
1379 3940506b 2005-01-13 devnull gline(Rune *addr)
1380 3940506b 2005-01-13 devnull {
1381 3940506b 2005-01-13 devnull long c;
1382 3940506b 2005-01-13 devnull Rune *p;
1383 3940506b 2005-01-13 devnull
1384 3940506b 2005-01-13 devnull static long peekc = 0;
1385 3940506b 2005-01-13 devnull
1386 3940506b 2005-01-13 devnull if (f == 0 && opendata() < 0)
1387 3940506b 2005-01-13 devnull return 0;
1388 3940506b 2005-01-13 devnull sflag = 0;
1389 3940506b 2005-01-13 devnull lnum++;
1390 3940506b 2005-01-13 devnull /* Bflush(&fout);********* dumped 4/30/92 - bobf****/
1391 3940506b 2005-01-13 devnull do {
1392 3940506b 2005-01-13 devnull p = addr;
1393 3940506b 2005-01-13 devnull for (c = (peekc ? peekc : Bgetrune(f)); c >= 0; c = Bgetrune(f)) {
1394 3940506b 2005-01-13 devnull if (c == '\n') {
1395 3940506b 2005-01-13 devnull if ((peekc = Bgetrune(f)) < 0) {
1396 3940506b 2005-01-13 devnull if (fhead == 0)
1397 3940506b 2005-01-13 devnull dolflag = 1;
1398 3940506b 2005-01-13 devnull }
1399 3940506b 2005-01-13 devnull *p = '\0';
1400 3940506b 2005-01-13 devnull return p;
1401 3940506b 2005-01-13 devnull }
1402 3940506b 2005-01-13 devnull if (c && p < lbend)
1403 3940506b 2005-01-13 devnull *p++ = c;
1404 3940506b 2005-01-13 devnull }
1405 3940506b 2005-01-13 devnull /* return partial final line, adding implicit newline */
1406 3940506b 2005-01-13 devnull if(p != addr) {
1407 3940506b 2005-01-13 devnull *p = '\0';
1408 3940506b 2005-01-13 devnull peekc = -1;
1409 3940506b 2005-01-13 devnull if (fhead == 0)
1410 3940506b 2005-01-13 devnull dolflag = 1;
1411 3940506b 2005-01-13 devnull return p;
1412 3940506b 2005-01-13 devnull }
1413 3940506b 2005-01-13 devnull peekc = 0;
1414 3940506b 2005-01-13 devnull Bterm(f);
1415 3940506b 2005-01-13 devnull } while (opendata() > 0); /* Switch to next stream */
1416 3940506b 2005-01-13 devnull f = 0;
1417 3940506b 2005-01-13 devnull return 0;
1418 3940506b 2005-01-13 devnull }
1419 3940506b 2005-01-13 devnull
1420 3940506b 2005-01-13 devnull /* Data file input section - the intent is to transparently
1421 3940506b 2005-01-13 devnull * catenate all data input streams.
1422 3940506b 2005-01-13 devnull */
1423 3940506b 2005-01-13 devnull void
1424 3940506b 2005-01-13 devnull enroll(char *filename) /* Add a file to the input file cache */
1425 3940506b 2005-01-13 devnull {
1426 3940506b 2005-01-13 devnull FileCache *fp;
1427 3940506b 2005-01-13 devnull
1428 3940506b 2005-01-13 devnull if ((fp = (FileCache *) malloc(sizeof (FileCache))) == 0)
1429 3940506b 2005-01-13 devnull quit("Out of memory", 0);
1430 3940506b 2005-01-13 devnull if (ftail == 0)
1431 3940506b 2005-01-13 devnull fhead = fp;
1432 3940506b 2005-01-13 devnull else
1433 3940506b 2005-01-13 devnull ftail->next = fp;
1434 3940506b 2005-01-13 devnull ftail = fp;
1435 3940506b 2005-01-13 devnull fp->next = 0;
1436 3940506b 2005-01-13 devnull fp->name = filename; /* 0 => stdin */
1437 3940506b 2005-01-13 devnull }
1438 3940506b 2005-01-13 devnull
1439 3940506b 2005-01-13 devnull int
1440 3940506b 2005-01-13 devnull opendata(void)
1441 3940506b 2005-01-13 devnull {
1442 3940506b 2005-01-13 devnull if (fhead == 0)
1443 3940506b 2005-01-13 devnull return -1;
1444 3940506b 2005-01-13 devnull if (fhead->name) {
1445 3940506b 2005-01-13 devnull if ((f = Bopen(fhead->name, OREAD)) == 0)
1446 3940506b 2005-01-13 devnull quit("Can't open %s", fhead->name);
1447 3940506b 2005-01-13 devnull } else {
1448 3940506b 2005-01-13 devnull Binit(&bstdin, 0, OREAD);
1449 3940506b 2005-01-13 devnull f = &bstdin;
1450 3940506b 2005-01-13 devnull }
1451 3940506b 2005-01-13 devnull fhead = fhead->next;
1452 3940506b 2005-01-13 devnull return 1;
1453 3940506b 2005-01-13 devnull }