1
/****************************************************************
2
Copyright (C) Lucent Technologies 1997
5
Permission to use, copy, modify, and distribute this software and
6
its documentation for any purpose and without fee is hereby
7
granted, provided that the above copyright notice appear in all
8
copies and that both that the copyright notice and this
9
permission notice and warranty disclaimer appear in supporting
10
documentation, and that the name Lucent Technologies or any of
11
its entities not be used in advertising or publicity pertaining
12
to distribution of the software without specific, written prior
15
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
23
****************************************************************/
36
#define tempfree(x) if (istemp(x)) tfree(x); else
41
void tempfree(Cell *p) {
42
if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
43
WARNING("bad csub %d in Cell %d %s",
44
p->csub, p->ctype, p->sval);
53
#define FOPEN_MAX _NFILE
58
#define FOPEN_MAX 40 /* max number of open files */
62
#define RAND_MAX 32767 /* all that ansi guarantees */
66
extern int pairstack[];
68
Node *winner = NULL; /* root of parse tree */
69
Cell *tmps; /* free temporary cells for execution */
71
static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
72
Cell *True = &truecell;
73
static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
74
Cell *False = &falsecell;
75
static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
76
Cell *jbreak = &breakcell;
77
static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM };
78
Cell *jcont = &contcell;
79
static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
80
Cell *jnext = &nextcell;
81
static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
82
Cell *jnextfile = &nextfilecell;
83
static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
84
Cell *jexit = &exitcell;
85
static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM };
86
Cell *jret = &retcell;
87
static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE };
89
Node *curnode = NULL; /* the node being executed, for debugging */
91
/* buffer memory management */
92
int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
94
/* pbuf: address of pointer to buffer being managed
95
* psiz: address of buffer size variable
96
* minlen: minimum length of buffer needed
97
* quantum: buffer size quantum
98
* pbptr: address of movable pointer into buffer, or 0 if none
99
* whatrtn: name of the calling routine if failure should cause fatal error
101
* return 0 for realloc failure, !=0 for success
104
if (minlen > *psiz) {
106
int rminlen = quantum ? minlen % quantum : 0;
107
int boff = pbptr ? *pbptr - *pbuf : 0;
108
/* round up to next multiple of quantum */
110
minlen += quantum - rminlen;
111
tbuf = (char *) realloc(*pbuf, minlen);
114
FATAL("out of memory in %s", whatrtn);
120
*pbptr = tbuf + boff;
125
void run(Node *a) /* execution of parse tree starts here */
127
extern void stdinit(void);
134
Cell *execute(Node *u) /* execute a node of the parse tree */
136
Cell *(*proc)(Node **, int);
142
for (a = u; ; a = a->nnext) {
145
x = (Cell *) (a->narg[0]);
146
if (isfld(x) && !donefld)
148
else if (isrec(x) && !donerec)
152
if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */
153
FATAL("illegal statement");
154
proc = proctab[a->nobj-FIRSTTOKEN];
155
x = (*proc)(a->narg, a->nobj);
156
if (isfld(x) && !donefld)
158
else if (isrec(x) && !donerec)
164
if (a->nnext == NULL)
171
Cell *program(Node **a, int n) /* execute an awk program */
172
{ /* a[0] = BEGIN, a[1] = body, a[2] = END */
175
if (setjmp(env) != 0)
177
if (a[0]) { /* BEGIN */
182
FATAL("illegal break, continue, next or nextfile from BEGIN");
186
while (getrec(&record, &recsize, 1) > 0) {
193
if (setjmp(env) != 0) /* handles exit within END */
195
if (a[2]) { /* END */
197
if (isbreak(x) || isnext(x) || iscont(x))
198
FATAL("illegal break, continue, next or nextfile from END");
205
struct Frame { /* stack frame for awk function calls */
206
int nargs; /* number of arguments in this call */
207
Cell *fcncell; /* pointer to Cell for function */
208
Cell **args; /* pointer to array of arguments after execute */
209
Cell *retval; /* return value */
212
#define NARGS 50 /* max args in a call */
214
struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
215
int nframe = 0; /* number of frames allocated */
216
struct Frame *fp = NULL; /* frame pointer. bottom level unused */
218
Cell *call(Node **a, int n) /* function call. very kludgy and fragile */
220
static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
223
Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */
227
fcn = execute(a[0]); /* the function itself */
230
FATAL("calling undefined function %s", s);
232
fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
234
FATAL("out of space for stack frames calling %s", s);
236
for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
238
ndef = (int) fcn->fval; /* args in defn */
239
dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
241
WARNING("function %s called with %d args, uses only %d",
243
if (ncall + ndef > NARGS)
244
FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
245
for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */
246
dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
249
dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
250
i, y->nval, y->fval, isarr(y) ? "(array)" : y->sval, y->tval) );
252
FATAL("can't use function %s as argument in %s", y->nval, s);
254
args[i] = y; /* arrays by ref */
256
args[i] = copycell(y);
259
for ( ; i < ndef; i++) { /* add null args for ones not provided */
261
*args[i] = newcopycell;
263
fp++; /* now ok to up frame */
264
if (fp >= frame + nframe) {
265
int dfp = fp - frame; /* old index */
266
frame = (struct Frame *)
267
realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
269
FATAL("out of space for stack frames in %s", s);
274
fp->nargs = ndef; /* number defined with (excess are locals) */
275
fp->retval = gettemp();
277
dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
278
y = execute((Node *)(fcn->sval)); /* execute body */
279
dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
281
for (i = 0; i < ndef; i++) {
282
Cell *t = fp->args[i];
284
if (t->csub == CCOPY) {
290
oargs[i]->tval = t->tval;
291
oargs[i]->tval &= ~(STR|NUM|DONTFREE);
292
oargs[i]->sval = t->sval;
296
} else if (t != y) { /* kludge to prevent freeing twice */
302
if (isexit(y) || isnext(y) || isnextfile(y))
304
tempfree(y); /* this can free twice! */
305
z = fp->retval; /* return value */
306
dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
311
Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
316
y->csub = CCOPY; /* prevents freeing until call is over */
317
y->nval = x->nval; /* BUG? */
318
y->sval = x->sval ? tostring(x->sval) : NULL;
320
y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */
321
/* is DONTFREE right? */
325
Cell *arg(Node **a, int n) /* nth argument of a function */
328
n = ptoi(a[0]); /* argument number, counting from 0 */
329
dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
331
FATAL("argument #%d of function %s was not supplied",
332
n+1, fp->fcncell->nval);
336
Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */
344
errorflag = (int) getfval(y);
351
if ((y->tval & (STR|NUM)) == (STR|NUM)) {
352
setsval(fp->retval, getsval(y));
353
fp->retval->fval = getfval(y);
354
fp->retval->tval |= NUM;
356
else if (y->tval & STR)
357
setsval(fp->retval, getsval(y));
358
else if (y->tval & NUM)
359
setfval(fp->retval, getfval(y));
360
else /* can't happen */
361
FATAL("bad type variable %d", y->tval);
374
default: /* can't happen */
375
FATAL("illegal jump type %d", n);
377
return 0; /* not reached */
380
Cell *getline(Node **a, int n) /* get next line from specific input */
381
{ /* a[0] is variable, a[1] is operator, a[2] is filename */
383
extern Cell **fldtab;
386
int bufsize = recsize;
389
if ((buf = (char *) malloc(bufsize)) == NULL)
390
FATAL("out of memory in getline");
392
fflush(stdout); /* in case someone is waiting for a prompt */
394
if (a[1] != NULL) { /* getline < file */
395
x = execute(a[2]); /* filename */
397
if (mode == '|') /* input pipe */
398
mode = LE; /* arbitrary flag */
399
fp = openfile(mode, getsval(x));
404
n = readrec(&buf, &bufsize, fp);
407
} else if (a[0] != NULL) { /* getline var <file */
411
} else { /* getline <file */
412
setsval(fldtab[0], buf);
413
if (is_number(fldtab[0]->sval)) {
414
fldtab[0]->fval = atof(fldtab[0]->sval);
415
fldtab[0]->tval |= NUM;
418
} else { /* bare getline; use current input */
419
if (a[0] == NULL) /* getline */
420
n = getrec(&record, &recsize, 1);
421
else { /* getline var */
422
n = getrec(&buf, &bufsize, 0);
428
setfval(r, (Awkfloat) n);
433
Cell *getnf(Node **a, int n) /* get NF */
437
return (Cell *) a[0];
440
Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
447
int nsub = strlen(*SUBSEP);
449
if ((buf = (char *) malloc(bufsz)) == NULL)
450
FATAL("out of memory in array");
452
x = execute(a[0]); /* Cell* for symbol table */
454
for (np = a[1]; np; np = np->nnext) {
455
y = execute(np); /* subscript */
457
if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
458
FATAL("out of memory for %s[%s...]", x->nval, buf);
461
strcat(buf, *SUBSEP);
465
dprintf( ("making %s into an array\n", x->nval) );
468
x->tval &= ~(STR|NUM|DONTFREE);
470
x->sval = (char *) makesymtab(NSYMTAB);
472
z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
480
Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
485
int nsub = strlen(*SUBSEP);
487
x = execute(a[0]); /* Cell* for symbol table */
490
if (a[1] == 0) { /* delete the elements, not the table */
494
x->sval = (char *) makesymtab(NSYMTAB);
498
if ((buf = (char *) malloc(bufsz)) == NULL)
499
FATAL("out of memory in adelete");
501
for (np = a[1]; np; np = np->nnext) {
502
y = execute(np); /* subscript */
504
if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
505
FATAL("out of memory deleting %s[%s...]", x->nval, buf);
508
strcat(buf, *SUBSEP);
518
Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
525
int nsub = strlen(*SUBSEP);
527
ap = execute(a[1]); /* array name */
529
dprintf( ("making %s into an array\n", ap->nval) );
532
ap->tval &= ~(STR|NUM|DONTFREE);
534
ap->sval = (char *) makesymtab(NSYMTAB);
536
if ((buf = (char *) malloc(bufsz)) == NULL) {
537
FATAL("out of memory in intest");
540
for (p = a[0]; p; p = p->nnext) {
541
x = execute(p); /* expr */
543
if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
544
FATAL("out of memory deleting %s[%s...]", x->nval, buf);
548
strcat(buf, *SUBSEP);
550
k = lookup(buf, (Array *) ap->sval);
560
Cell *matchop(Node **a, int n) /* ~ and match() */
567
x = execute(a[1]); /* a[1] = target text */
569
if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */
572
y = execute(a[2]); /* a[2] = regular expr */
583
int start = countposn(s, patbeg-s)+1;
586
setfval(rstartloc, (Awkfloat) start);
587
setfval(rlengthloc, (Awkfloat) countposn(patbeg, patlen));
592
} else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
599
Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
616
if ( !i ) return(False);
623
if (i) return(False);
625
default: /* can't happen */
626
FATAL("unknown boolean operator %d", n);
628
return 0; /*NOTREACHED*/
631
Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */
639
if (x->tval&NUM && y->tval&NUM) {
640
j = x->fval - y->fval;
641
i = j<0? -1: (j>0? 1: 0);
643
i = strcmp(getsval(x), getsval(y));
648
case LT: if (i<0) return(True);
650
case LE: if (i<=0) return(True);
652
case NE: if (i!=0) return(True);
654
case EQ: if (i == 0) return(True);
656
case GE: if (i>=0) return(True);
658
case GT: if (i>0) return(True);
660
default: /* can't happen */
661
FATAL("unknown relational operator %d", n);
663
return 0; /*NOTREACHED*/
666
void tfree(Cell *a) /* free a tempcell */
669
dprintf( ("freeing %s %s %o\n", a->nval, a->sval, a->tval) );
673
FATAL("tempcell list is curdled");
678
Cell *gettemp(void) /* get a tempcell */
683
tmps = (Cell *) calloc(100, sizeof(Cell));
685
FATAL("out of space for temporaries");
686
for(i = 1; i < 100; i++)
687
tmps[i-1].cnext = &tmps[i];
696
Cell *indirect(Node **a, int n) /* $( a[0] ) */
703
m = (int) getfval(x);
704
if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
705
FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
706
/* BUG: can x->nval ever be null??? */
709
x->ctype = OCELL; /* BUG? why are these needed? */
714
Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
726
k = countposn(s, strlen(s)) + 1;
736
m = (int) getfval(y);
743
n = (int) getfval(z);
751
dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
755
for (p = s; *p && n--; p += mblen(p, k))
757
temp = *p; /* with thanks to John Linderman */
765
Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */
768
char *s1, *s2, *p1, *p2, *q;
777
for (p1 = s1; *p1 != '\0'; p1++) {
778
for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
781
v = (Awkfloat) countposn(s1, p1-s1) + 1; /* origin 1 */
791
#define MAXNUMSIZE 50
793
int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversions */
799
int fmtwd; /* format width */
802
int bufsize = *pbufsize;
806
if ((fmt = (char *) malloc(fmtsz)) == NULL)
807
FATAL("out of memory in format()");
809
adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format");
819
/* have to be real careful in case this is a huge number, eg, %100000d */
823
adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
824
for (t = fmt; (*t++ = *s) != '\0'; s++) {
825
if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, 0))
826
FATAL("format item %.30s... ran format() out of memory", os);
827
if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L')
828
break; /* the ansi panoply */
832
sprintf(t-1, "%d", fmtwd=(int) getfval(x));
835
adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
836
t = fmt + strlen(fmt);
843
adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
846
case 'f': case 'e': case 'g': case 'E': case 'G':
851
if(*(s-1) == 'l') break;
856
case 'o': case 'x': case 'X': case 'u':
857
flag = *(s-1) == 'l' ? 2 : 3;
866
WARNING("weird printf conversion %s", fmt);
871
FATAL("not enough args in printf(%s)", os);
877
adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format");
879
case 0: sprintf(p, "%s", fmt); /* unknown, so dump it too */
884
adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format");
888
case 1: sprintf(p, fmt, getfval(x)); break;
889
case 2: sprintf(p, fmt, (long) getfval(x)); break;
890
case 3: sprintf(p, fmt, (int) getfval(x)); break;
896
if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, 0))
897
FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
903
sprintf(p, fmt, (int) getfval(x));
907
sprintf(p, fmt, getsval(x)[0]);
916
for ( ; a; a = a->nnext) /* evaluate any remaining args */
923
Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */
930
if ((buf = (char *) malloc(bufsz)) == NULL)
931
FATAL("out of memory in awksprintf");
934
if (format(&buf, &bufsz, getsval(x), y) == -1)
935
FATAL("sprintf string %.30s... too long. can't happen.", buf);
943
Cell *awkprintf(Node **a, int n) /* printf */
944
{ /* a[0] is list of args, starting with format string */
945
/* a[1] is redirection operator, a[2] is redirection file */
953
if ((buf = (char *) malloc(bufsz)) == NULL)
954
FATAL("out of memory in awkprintf");
957
if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
958
FATAL("printf string %.30s... too long. can't happen.", buf);
961
/* fputs(buf, stdout); */
962
fwrite(buf, len, 1, stdout);
964
FATAL("write error on stdout");
966
fp = redirect(ptoi(a[1]), a[2]);
967
/* fputs(buf, fp); */
968
fwrite(buf, len, 1, fp);
971
FATAL("write error on %s", filename(fp));
977
Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
1004
FATAL("division by zero");
1009
FATAL("division by zero in mod");
1017
if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
1018
i = ipow(i, (int) j);
1020
i = errcheck(pow(i, j), "pow");
1022
default: /* can't happen */
1023
FATAL("illegal arithmetic operator %d", n);
1029
double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
1042
Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */
1050
k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1051
if (n == PREINCR || n == PREDECR) {
1062
Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
1063
{ /* this is subtle; don't muck with it. */
1070
if (n == ASSIGN) { /* ordinary assignment */
1071
if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */
1072
; /* leave alone unless it's a field */
1073
else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1074
setsval(x, getsval(y));
1075
x->fval = getfval(y);
1079
setsval(x, getsval(y));
1081
setfval(x, getfval(y));
1083
funnyvar(y, "read value of");
1101
FATAL("division by zero in /=");
1106
FATAL("division by zero in %%=");
1111
if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
1112
xf = ipow(xf, (int) yf);
1114
xf = errcheck(pow(xf, yf), "pow");
1117
FATAL("illegal assignment operator %d", n);
1125
Cell *cat(Node **a, int q) /* a[0] cat a[1] */
1135
n1 = strlen(x->sval);
1136
n2 = strlen(y->sval);
1137
s = (char *) malloc(n1 + n2 + 1);
1139
FATAL("out of space concatenating %.15s... and %.15s...",
1142
strcpy(s+n1, y->sval);
1151
Cell *pastat(Node **a, int n) /* a[0] { a[1] } */
1167
Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
1173
if (pairstack[pair] == 0) {
1176
pairstack[pair] = 1;
1179
if (pairstack[pair] == 1) {
1182
pairstack[pair] = 0;
1190
Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
1192
Cell *x = 0, *y, *ap;
1195
char *t, temp, num[50], *fs = 0;
1198
y = execute(a[0]); /* source string */
1200
arg3type = ptoi(a[3]);
1201
if (a[2] == 0) /* fs string */
1203
else if (arg3type == STRING) { /* split(str,arr,"string") */
1206
} else if (arg3type == REGEXPR)
1207
fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
1209
FATAL("illegal type of split");
1211
ap = execute(a[1]); /* array name */
1213
dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) );
1216
ap->sval = (char *) makesymtab(NSYMTAB);
1219
if ((*s != '\0' && strlen(fs) > 1) || arg3type == REGEXPR) { /* reg expr */
1221
if (arg3type == REGEXPR) { /* it's ready already */
1227
if (nematch(p,s,t)) {
1230
sprintf(num, "%d", n);
1234
setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1236
setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1238
t = patbeg + patlen;
1239
if (t[-1] == 0 || *t == 0) {
1241
sprintf(num, "%d", n);
1242
setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1245
} while (nematch(p,s,t));
1248
sprintf(num, "%d", n);
1250
setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1252
setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1255
} else if (sep == ' ') {
1257
while (*s == ' ' || *s == '\t' || *s == '\n')
1265
while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1268
sprintf(num, "%d", n);
1270
setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1272
setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1277
} else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
1278
for (n = 0; *s != 0; s++) {
1281
sprintf(num, "%d", n);
1284
if (isdigit(buf[0]))
1285
setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1287
setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1289
} else if (*s != 0) {
1293
while (*s != sep && *s != '\n' && *s != '\0')
1297
sprintf(num, "%d", n);
1299
setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1301
setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1309
if (a[2] != 0 && arg3type == STRING)
1317
Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
1332
Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
1340
} else if (a[2] != 0) {
1347
Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
1361
if (isnext(x) || isexit(x) || isret(x))
1367
Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
1375
if (isnext(x) || isnextfile(x) || isexit(x) || isret(x))
1385
Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
1394
if (!istrue(x)) return(x);
1398
if (isbreak(x)) /* turn off break */
1400
if (isnext(x) || isexit(x) || isret(x))
1408
Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1410
Cell *x, *vp, *arrayp, *cp, *ncp;
1415
arrayp = execute(a[1]);
1416
if (!isarr(arrayp)) {
1419
tp = (Array *) arrayp->sval;
1421
for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1422
for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1423
setsval(vp, cp->nval);
1430
if (isnext(x) || isexit(x) || isret(x)) {
1440
Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
1453
nextarg = a[1]->nnext;
1457
u = (Awkfloat) countposn(p, strlen(p)); break;
1459
u = errcheck(log(getfval(x)), "log"); break;
1461
modf(getfval(x), &u); break;
1463
u = errcheck(exp(getfval(x)), "exp"); break;
1465
u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1467
u = sin(getfval(x)); break;
1469
u = cos(getfval(x)); break;
1472
WARNING("atan2 requires two arguments; returning 1.0");
1475
y = execute(a[1]->nnext);
1476
u = atan2(getfval(x), getfval(y));
1478
nextarg = nextarg->nnext;
1482
fflush(stdout); /* in case something is buffered already */
1483
u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */
1486
/* in principle, rand() returns something in 0..RAND_MAX */
1487
u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX;
1490
if (isrec(x)) /* no argument provided */
1491
u = time((time_t *)0);
1494
srand((unsigned int) u);
1498
buf = tostring(getsval(x));
1499
if (t == FTOUPPER) {
1500
for (p = buf; *p; p++)
1504
for (p = buf; *p; p++)
1514
if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1520
wc = (int)getfval(x);
1521
mbc[wctomb(mbc, wc)] = 0;
1526
default: /* can't happen */
1527
FATAL("illegal function type %d", t);
1534
WARNING("warning: function has too many arguments");
1535
for ( ; nextarg; nextarg = nextarg->nnext)
1541
Cell *printstat(Node **a, int n) /* print a[0] */
1547
if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */
1550
fp = redirect(ptoi(a[1]), a[2]);
1551
for (x = a[0]; x != NULL; x = x->nnext) {
1553
fputs(getsval(y), fp);
1555
if (x->nnext == NULL)
1563
FATAL("write error on %s", filename(fp));
1567
Cell *nullproc(Node **a, int n)
1575
FILE *redirect(int a, Node *b) /* set up all i/o redirections */
1583
fp = openfile(a, fname);
1585
FATAL("can't open file %s", fname);
1593
int mode; /* '|', 'a', 'w' => LE/LT, GT */
1594
} files[FOPEN_MAX] ={
1595
{ NULL, "/dev/stdin", LT }, /* watch out: don't free this! */
1596
{ NULL, "/dev/stdout", GT },
1597
{ NULL, "/dev/stderr", GT }
1600
void stdinit(void) /* in case stdin, etc., are not constants */
1602
files[0].fp = stdin;
1603
files[1].fp = stdout;
1604
files[2].fp = stderr;
1607
FILE *openfile(int a, char *us)
1614
FATAL("null file name in print or getline");
1615
for (i=0; i < FOPEN_MAX; i++)
1616
if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1617
if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1622
if (a == FFLUSH) /* didn't find it, so don't create it! */
1625
for (i=0; i < FOPEN_MAX; i++)
1626
if (files[i].fp == 0)
1629
FATAL("%s makes too many open files", s);
1630
fflush(stdout); /* force a semblance of order */
1634
} else if (a == APPEND) {
1636
m = GT; /* so can mix > and >> */
1637
} else if (a == '|') { /* output pipe */
1639
} else if (a == LE) { /* input pipe */
1641
} else if (a == LT) { /* getline <file */
1642
fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */
1643
} else /* can't happen */
1644
FATAL("illegal redirection %d", a);
1646
files[i].fname = tostring(s);
1653
char *filename(FILE *fp)
1657
for (i = 0; i < FOPEN_MAX; i++)
1658
if (fp == files[i].fp)
1659
return files[i].fname;
1663
Cell *closefile(Node **a, int n)
1671
for (i = 0; i < FOPEN_MAX; i++)
1672
if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1673
if (ferror(files[i].fp))
1674
WARNING( "i/o error occurred on %s", files[i].fname );
1675
if (files[i].mode == '|' || files[i].mode == LE)
1676
stat = pclose(files[i].fp);
1678
stat = fclose(files[i].fp);
1680
WARNING( "i/o error occurred closing %s", files[i].fname );
1681
if (i > 2) /* don't do /dev/std... */
1682
xfree(files[i].fname);
1683
files[i].fname = NULL; /* watch out for ref thru this */
1694
for (i = 0; i < FOPEN_MAX; i++)
1696
if (ferror(files[i].fp))
1697
WARNING( "i/o error occurred on %s", files[i].fname );
1698
if (files[i].mode == '|' || files[i].mode == LE)
1699
stat = pclose(files[i].fp);
1701
stat = fclose(files[i].fp);
1703
WARNING( "i/o error occurred while closing %s", files[i].fname );
1707
void backsub(char **pb_ptr, char **sptr_ptr);
1709
Cell *sub(Node **a, int nnn) /* substitute command */
1711
char *sptr, *pb, *q;
1712
Cell *x, *y, *result;
1715
int bufsz = recsize;
1717
if ((buf = (char *) malloc(bufsz)) == NULL)
1718
FATAL("out of memory in sub");
1719
x = execute(a[3]); /* target string */
1721
if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1722
p = (void *) a[1]; /* regular expression */
1725
p = compre(getsval(y));
1728
y = execute(a[2]); /* replacement string */
1730
if (pmatch(p, t, t)) {
1732
adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1734
while (sptr < patbeg)
1737
while (*sptr != 0) {
1738
adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1739
if (*sptr == '\\') {
1740
backsub(&pb, &sptr);
1741
} else if (*sptr == '&') {
1743
adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1744
for (q = patbeg; q < patbeg+patlen; )
1750
if (pb > buf + bufsz)
1751
FATAL("sub result1 %.30s too big; can't happen", buf);
1752
sptr = patbeg + patlen;
1753
if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1754
adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1755
while ((*pb++ = *sptr++) != 0)
1758
if (pb > buf + bufsz)
1759
FATAL("sub result2 %.30s too big; can't happen", buf);
1760
setsval(x, buf); /* BUG: should be able to avoid copy */
1769
Cell *gsub(Node **a, int nnn) /* global substitute */
1772
char *rptr, *sptr, *t, *pb, *c;
1776
int bufsz = recsize;
1778
if ((buf = (char *)malloc(bufsz)) == NULL)
1779
FATAL("out of memory in gsub");
1780
mflag = 0; /* if mflag == 0, can replace empty string */
1782
x = execute(a[3]); /* target string */
1784
if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1785
p = (void *) a[1]; /* regular expression */
1788
p = compre(getsval(y));
1791
y = execute(a[2]); /* replacement string */
1792
if (pmatch(p, t, c)) {
1796
if (patlen == 0 && *patbeg != 0) { /* matched empty string */
1797
if (mflag == 0) { /* can replace empty */
1800
while (*sptr != 0) {
1801
adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1802
if (*sptr == '\\') {
1803
backsub(&pb, &sptr);
1804
} else if (*sptr == '&') {
1807
adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1808
for (q = patbeg; q < patbeg+patlen; )
1814
if (*c == 0) /* at end */
1816
adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
1818
if (pb > buf + bufsz) /* BUG: not sure of this test */
1819
FATAL("gsub result0 %.30s too big; can't happen", buf);
1822
else { /* matched nonempty string */
1825
adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
1826
while (sptr < patbeg)
1829
while (*sptr != 0) {
1830
adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1831
if (*sptr == '\\') {
1832
backsub(&pb, &sptr);
1833
} else if (*sptr == '&') {
1836
adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1837
for (q = patbeg; q < patbeg+patlen; )
1842
c = patbeg + patlen;
1843
if ((c[-1] == 0) || (*c == 0))
1845
if (pb > buf + bufsz)
1846
FATAL("gsub result1 %.30s too big; can't happen", buf);
1849
} while (pmatch(p, t, c));
1851
adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
1852
while ((*pb++ = *sptr++) != 0)
1854
done: if (pb > buf + bufsz)
1855
FATAL("gsub result2 %.30s too big; can't happen", buf);
1857
setsval(x, buf); /* BUG: should be able to avoid copy + free */
1868
void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */
1869
{ /* sptr[0] == '\\' */
1870
char *pb = *pb_ptr, *sptr = *sptr_ptr;
1872
if (sptr[1] == '\\') {
1873
if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
1877
} else if (sptr[2] == '&') { /* \\& -> \ + matched */
1880
} else { /* \\x -> \\x */
1884
} else if (sptr[1] == '&') { /* literal & */
1887
} else /* literal \ */