Blame


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