Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/re/sed2.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1995-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
#include "sed.h"
23
24
#include <ctype.h>
25
26
#define ustrchr(p, c) (unsigned char*)strchr((char*)(p), c)
27
28
int selected(unsigned char*, Text*);
29
30
#define Re Ie
31
#define Ce Ie
32
#define Se Ie
33
#define re ae
34
35
#define IBUG "interpreter bug %d"
36
char *stdouterr = "writing standard output";
37
38
Text hold;
39
40
void
41
cputchar(int c)
42
{
43
if(sfputc(sfstdout, c) == EOF)
44
error(ERROR_SYSTEM|3, stdouterr);
45
}
46
47
void
48
writeline(Text *data)
49
{
50
word n = data->w - data->s;
51
if(sfwrite(sfstdout, data->s, n) != n)
52
error(ERROR_SYSTEM|3, stdouterr);
53
cputchar('\n');
54
}
55
56
/* return 1 if action is to be taken on current line,
57
-1 if (numeric) address has been passed,
58
0 otherwise*/
59
int
60
sel1(word addr, Text *data)
61
{
62
if(addr & REGADR)
63
return reexec(readdr(addr), (char*)data->s, data->w - data->s, 0, 0, 0) == 0;
64
if(addr == recno)
65
return 1;
66
if(addr == DOLLAR)
67
return ateof();
68
if(addr < recno)
69
return -1;
70
return 0;
71
}
72
73
/* return 2 on non-final line of a selected range,
74
1 on any other selected line,
75
0 on non-selected lines
76
(the 1-2 distinction matters only for 'c' commands) */
77
78
int
79
selected(unsigned char *pc, Text *data)
80
{
81
int active;
82
word *ipc = (word*)pc; /* points to address words */
83
word *q = instr(pc); /* points to instruction word */
84
int neg = !!(*q & NEG);
85
switch(q - ipc) {
86
case 0: /* 0 address */
87
return !neg;
88
case 1: /* 1 address */
89
return neg ^ (sel1(ipc[0], data)==1);
90
case 2:
91
error(ERROR_PANIC|4, IBUG,1);
92
case 3: /* 2 address */
93
q--; /* points to activity indicator */
94
active = !(*q & INACT);
95
if((*q&AMASK) < recno) {
96
switch(sel1(ipc[active], data)) {
97
case 0:
98
if((active&ateof()) == 0)
99
break;
100
case 1:
101
*q = recno;
102
if(active)
103
*q |= INACT;
104
return (neg^1) << (!active&!ateof());
105
case -1:
106
if(active) {
107
*q = recno | INACT;
108
return neg;
109
}
110
}
111
}
112
return (neg^active) << 1;
113
default:
114
error(ERROR_PANIC|4, IBUG,2);
115
return 0; /* dummy */
116
}
117
}
118
119
void
120
vacate(Text *t)
121
{
122
assure(t, 1);
123
t->w = t->s;
124
*t->w = 0;
125
}
126
127
void
128
tcopy(Text *from, Text *to)
129
{
130
word n = from->w - from->s;
131
assure(to, n+1);
132
memmove(to->w, from->s, n);
133
to->w += n;
134
*to->w = 0;
135
}
136
137
138
/* EASY COMMANDS */
139
140
unsigned char *
141
vv(Text *script, unsigned char *pc, Text *data)
142
{
143
script = script;
144
pc = pc;
145
data = data;
146
error(ERROR_PANIC|4, IBUG,3);
147
return 0; /* dummy */
148
}
149
150
unsigned char *
151
be(Text *script, unsigned char *pc, Text *data)
152
{
153
script = script;
154
data = data;
155
return script->s + instr(pc)[1];
156
}
157
158
unsigned char *
159
de(Text *script, unsigned char *pc, Text *data)
160
{
161
NoP(script);
162
pc = pc;
163
vacate(data);
164
return 0;
165
}
166
167
unsigned char *
168
De(Text *script, unsigned char *pc, Text *data)
169
{
170
word n;
171
unsigned char *end = (unsigned char*)ustrchr(data->s, '\n');
172
if(end == 0)
173
return de(script, pc, data);
174
end++;
175
n = data->w - end;
176
memmove(data->s, end, n+1);
177
data->w = data->s + n;
178
return script->s;
179
}
180
181
unsigned char *
182
Ee(Text *script, unsigned char *pc, Text *data)
183
{
184
script = script;
185
data = data;
186
if(sfprintf(sfstdout, "%d\n", recno) <= 0)
187
error(ERROR_SYSTEM|3, stdouterr);
188
return nexti(pc);
189
}
190
191
unsigned char *
192
Ge(Text *script, unsigned char *pc, Text *data)
193
{
194
script = script;
195
if(hold.s == 0)
196
vacate(&hold);
197
*data->w++ = '\n';
198
tcopy(&hold, data);
199
return nexti(pc);
200
}
201
202
unsigned char *
203
ge(Text *script, unsigned char *pc, Text *data)
204
{
205
vacate(data);
206
script = script;
207
if(hold.s == 0)
208
vacate(&hold);
209
if(data->w > data->s)
210
*data->w++ = '\n';
211
tcopy(&hold, data);
212
return nexti(pc);
213
}
214
215
unsigned char *
216
He(Text *script, unsigned char *pc, Text *data)
217
{
218
script = script;
219
assure(&hold, 1);
220
*hold.w++ = '\n';
221
tcopy(data, &hold);
222
return nexti(pc);
223
}
224
225
unsigned char *
226
he(Text *script, unsigned char *pc, Text *data)
227
{
228
script = script;
229
vacate(&hold);
230
tcopy(data, &hold);
231
return nexti(pc);
232
}
233
234
unsigned char *
235
Ie(Text *script, unsigned char *pc, Text *data)
236
{
237
script = script;
238
data = data;
239
return nexti(pc);
240
}
241
242
unsigned char *
243
ie(Text *script, unsigned char *pc, Text *data)
244
{
245
script = script;
246
data = data;
247
if(sfprintf(sfstdout, "%s", (char*)(instr(pc)+1)) <= 0)
248
error(ERROR_SYSTEM|3, stdouterr);
249
return nexti(pc);
250
}
251
252
unsigned char *
253
Le(Text *script, unsigned char *pc, Text *data)
254
{
255
script = script;
256
data = data;
257
return (unsigned char*)(instr(pc)+1);
258
}
259
260
unsigned char *
261
Ne(Text *script, unsigned char *pc, Text *data)
262
{
263
assure(data, 1);
264
*data->w++ = '\n';
265
if(readline(data))
266
return nexti(pc);
267
*--data->w = 0;
268
return de(script, pc, data);
269
}
270
271
unsigned char *
272
ne(Text *script, unsigned char *pc, Text *data)
273
{
274
NoP(script);
275
if(!nflag)
276
writeline(data);
277
vacate(data);
278
if(readline(data))
279
return nexti(pc);
280
return 0;
281
}
282
283
unsigned char *
284
Pe(Text *script, unsigned char *pc, Text *data)
285
{
286
word n;
287
unsigned char *end = ustrchr(data->s, '\n');
288
if(end == 0)
289
n = data->w - data->s;
290
else
291
n = end - data->s;
292
if(sfwrite(sfstdout, data->s, n) != n)
293
error(ERROR_SYSTEM|3, stdouterr);
294
cputchar('\n');
295
script = script;
296
return nexti(pc);
297
}
298
299
unsigned char *
300
pe(Text *script, unsigned char *pc, Text *data)
301
{
302
writeline(data);
303
script = script;
304
return nexti(pc);
305
}
306
307
unsigned char *
308
qe(Text *script, unsigned char *pc, Text *data)
309
{
310
pc = pc;
311
data = data;
312
qflag++;
313
return script->w;
314
}
315
316
unsigned char *
317
te(Text *script, unsigned char *pc, Text *data)
318
{
319
int tflag = sflag;
320
sflag = 0;
321
if(tflag)
322
return be(script, pc, data);
323
else
324
return nexti(pc);
325
}
326
327
unsigned char *
328
ww(Text *script, unsigned char *pc, Text *data, word offset)
329
{
330
word *q = (word*)(files.s + offset);
331
Sfio_t *f = *(Sfio_t**)q;
332
word n = data->w - data->s;
333
assure(data, 1);
334
*data->w = '\n';
335
if(sfwrite(f, data->s, n+1) != n+1 ||
336
sfsync(f) == EOF) /* in case of subsequent r */
337
error(ERROR_SYSTEM|3, "%s: cannot write", (char*)(q+1));
338
*data->w = 0;
339
script = script;
340
return nexti(pc);
341
}
342
343
unsigned char *
344
we(Text *script, unsigned char *pc, Text *data)
345
{
346
return ww(script, pc, data, instr(pc)[1]);
347
}
348
349
unsigned char *
350
xe(Text *script, unsigned char *pc, Text *data)
351
{
352
unsigned char *t;
353
script = script;
354
if(hold.s == 0)
355
vacate(&hold);
356
exch(data->s, hold.s, t);
357
exch(data->e, hold.e, t);
358
exch(data->w, hold.w, t);
359
return nexti(pc);
360
}
361
362
unsigned char *
363
ye(Text *script, unsigned char *pc, Text *data)
364
{
365
unsigned char *s = (unsigned char*)data->s;
366
unsigned char *w = (unsigned char*)data->w;
367
unsigned char **m = (unsigned char**)(instr(pc)+1);
368
unsigned char *b;
369
unsigned int c, x;
370
int i, n;
371
Sfio_t *f;
372
if(x = (unsigned int)(*m++ - (unsigned char*)0)) {
373
if(!(f = sfstropen()))
374
error(ERROR_SYSTEM|3, "out of space");
375
while(s<w) {
376
b = s;
377
c = mbchar(s);
378
if(c < x && m[c]) {
379
n = m[c][0];
380
i = 0;
381
while(++i<=n)
382
sfputc(f, m[c][i]);
383
}
384
else
385
while(b<s)
386
sfputc(f, *b++);
387
}
388
x = (unsigned int)sfstrtell(f);
389
assure(data, x);
390
memcpy(data->s, sfstrbase(f), x);
391
data->w = data->s + x;
392
}
393
else
394
for(b = (unsigned char*)m; s<w; s++)
395
*s = b[*s];
396
script = script;
397
return nexti(pc);
398
}
399
400
/* MISCELLANY */
401
402
unsigned char *
403
se(Text *script, unsigned char *pc, Text *data)
404
{
405
word *q = instr(pc);
406
int flags = readdr(q[1])->re_sub->re_flags;
407
408
sflag = substitute(readdr(q[1]), data);
409
if(!sflag)
410
return nexti(pc);
411
if(flags & REG_SUB_PRINT)
412
pe(script, pc, data);
413
if(flags & REG_SUB_WRITE)
414
return ww(script, pc, data, ((word*)nexti(pc))[-1]);
415
return nexti(pc);
416
}
417
418
struct { char p, q; } digram[] = {
419
'\\', '\\',
420
'\a', 'a',
421
'\b', 'b',
422
'\f', 'f',
423
'\n', 'n',
424
'\r', 'r',
425
'\t', 't',
426
'\v', 'v',
427
};
428
429
#define LEMAX 72
430
#define CHMAX 4
431
432
unsigned char *
433
le(Text *script, unsigned char *pc, Text *data)
434
{
435
word n;
436
int j;
437
unsigned char *s;
438
unsigned char *b;
439
unsigned char *o;
440
unsigned char *e;
441
unsigned char buf[LEMAX+CHMAX+1];
442
script = script;
443
b = buf;
444
for(s=data->s; s<data->w; s++) {
445
o = b;
446
for(j=0; j<sizeof(digram)/sizeof(*digram); j++)
447
if(*s == digram[j].p) {
448
*b++ = '\\';
449
*b++ = digram[j].q;
450
goto hit;
451
}
452
if(!isprint(*s))
453
b += sfsprintf((char*)b, CHMAX+1, "\\%3.3o", *s);
454
else
455
*b++ = *s;
456
hit:
457
if((b - buf) >= LEMAX) {
458
n = o - buf;
459
if(sfwrite(sfstdout, buf, n) != n)
460
error(ERROR_SYSTEM|3, stdouterr);
461
cputchar('\\');
462
cputchar('\n');
463
e = b;
464
b = buf;
465
while(o < e)
466
*b++ = *o++;
467
}
468
}
469
*b++ = '$';
470
*b++ = '\n';
471
n = b - buf;
472
if(sfwrite(sfstdout, buf, n) != n)
473
error(ERROR_SYSTEM|3, stdouterr);
474
return nexti(pc);
475
}
476
477
/* END-OF-CYCLE STUFF */
478
479
Text todo;
480
481
unsigned char *
482
ae(Text *script, unsigned char *pc, Text *data)
483
{
484
script = script;
485
data = data;
486
assure(&todo, sizeof(unsigned char*));
487
*(unsigned char**)todo.w = pc;
488
todo.w += sizeof(unsigned char*);
489
return nexti(pc);
490
}
491
492
unsigned char *
493
ce(Text *script, unsigned char *pc, Text *data)
494
{
495
if(sfprintf(sfstdout, "%s", (char*)(instr(pc)+1)) <= 0)
496
error(ERROR_SYSTEM|3, stdouterr);
497
return de(script, pc, data);
498
}
499
500
void
501
coda(void)
502
{
503
word *q;
504
unsigned char *p;
505
Sfio_t *f;
506
if(todo.s == 0)
507
return;
508
for(p=todo.s; p<todo.w; p+=sizeof(word)) {
509
q = instr(*(unsigned char**)p);
510
switch(code(*q)) {
511
case 'a':
512
if(sfprintf(sfstdout, "%s", (char*)(q+1)) <= 0)
513
error(ERROR_SYSTEM|3, stdouterr);
514
continue;
515
case 'r':
516
f = sfopen(NiL, (char*)(files.s+q[1]+sizeof(word)), "r");
517
if(f == 0)
518
continue;
519
if (sfmove(f, sfstdout, SF_UNBOUND, -1) < 0 || sferror(sfstdout) || !sfeof(f))
520
error(ERROR_SYSTEM|3, stdouterr);
521
sfclose(f);
522
continue;
523
default:
524
error(ERROR_PANIC|4, IBUG,5);
525
}
526
}
527
vacate(&todo);
528
}
529
530
/* execution functions return pointer to next instruction */
531
532
typedef unsigned char* (*exef)(Text*, unsigned char *, Text*);
533
534
static const exef excom[128] = {
535
vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,Ie,vv,vv,vv,vv,vv,
536
vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,
537
vv,vv,vv,Ie,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv, /* # */
538
vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,Ce,Se,vv,Ee,vv,vv, /* :;= */
539
vv,vv,vv,vv,De,vv,vv,Ge,He,vv,vv,vv,vv,vv,Ne,vv, /* DGHN */
540
Pe,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv,vv, /* P */
541
vv,ae,be,ce,de,vv,vv,ge,he,ie,vv,vv,le,vv,ne,vv, /* a-n */
542
pe,qe,re,se,te,vv,vv,we,xe,ye,vv,Le,vv,Re,vv,vv /* p-y{} */
543
};
544
545
void
546
execute(Text *script, Text *data)
547
{
548
unsigned char *pc;
549
int sel;
550
for(pc = script->s; pc < script->w; ) {
551
sel = selected(pc, data);
552
if(sel) {
553
int cmd = code(*instr(pc));
554
if(sel==2 && cmd=='c')
555
cmd = 'd';
556
pc = (*excom[ccmapchr(map,cmd)])(script, pc, data);
557
if(pc == 0)
558
return;
559
} else
560
pc = nexti(pc);
561
}
562
if(!nflag)
563
writeline(data);
564
}
565
566