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 ****************************************************************/
37 #define tempfree(x) if (istemp(x)) tfree(x); else
42 void tempfree(Cell *p) {
43 if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
44 WARNING("bad csub %d in Cell %d %s",
45 p->csub, p->ctype, p->sval);
52 /* do we really need these? */
54 /* #ifndef FOPEN_MAX */
55 /* #define FOPEN_MAX _NFILE */
59 /* #ifndef FOPEN_MAX */
60 /* #define FOPEN_MAX 40 */ /* max number of open files */
63 /* #ifndef RAND_MAX */
64 /* #define RAND_MAX 32767 */ /* all that ansi guarantees */
68 extern int pairstack
[];
69 extern Awkfloat srand_seed
;
71 Node
*winner
= NULL
; /* root of parse tree */
72 Cell
*tmps
; /* free temporary cells for execution */
74 static Cell truecell
={ OBOOL
, BTRUE
, 0, 0, 1.0, NUM
};
75 Cell
*True
= &truecell
;
76 static Cell falsecell
={ OBOOL
, BFALSE
, 0, 0, 0.0, NUM
};
77 Cell
*False
= &falsecell
;
78 static Cell breakcell
={ OJUMP
, JBREAK
, 0, 0, 0.0, NUM
};
79 Cell
*jbreak
= &breakcell
;
80 static Cell contcell
={ OJUMP
, JCONT
, 0, 0, 0.0, NUM
};
81 Cell
*jcont
= &contcell
;
82 static Cell nextcell
={ OJUMP
, JNEXT
, 0, 0, 0.0, NUM
};
83 Cell
*jnext
= &nextcell
;
84 static Cell nextfilecell
={ OJUMP
, JNEXTFILE
, 0, 0, 0.0, NUM
};
85 Cell
*jnextfile
= &nextfilecell
;
86 static Cell exitcell
={ OJUMP
, JEXIT
, 0, 0, 0.0, NUM
};
87 Cell
*jexit
= &exitcell
;
88 static Cell retcell
={ OJUMP
, JRET
, 0, 0, 0.0, NUM
};
89 Cell
*jret
= &retcell
;
90 static Cell tempcell
={ OCELL
, CTEMP
, 0, "", 0.0, NUM
|STR
|DONTFREE
};
92 Node
*curnode
= NULL
; /* the node being executed, for debugging */
94 /* buffer memory management */
95 int adjbuf(char **pbuf
, int *psiz
, int minlen
, int quantum
, char **pbptr
,
97 /* pbuf: address of pointer to buffer being managed
98 * psiz: address of buffer size variable
99 * minlen: minimum length of buffer needed
100 * quantum: buffer size quantum
101 * pbptr: address of movable pointer into buffer, or 0 if none
102 * whatrtn: name of the calling routine if failure should cause fatal error
104 * return 0 for realloc failure, !=0 for success
107 if (minlen
> *psiz
) {
109 int rminlen
= quantum
? minlen
% quantum
: 0;
110 int boff
= pbptr
? *pbptr
- *pbuf
: 0;
111 /* round up to next multiple of quantum */
113 minlen
+= quantum
- rminlen
;
114 tbuf
= (char *) realloc(*pbuf
, minlen
);
115 dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn
, *psiz
, minlen
, *pbuf
, tbuf
) );
118 FATAL("out of memory in %s", whatrtn
);
124 *pbptr
= tbuf
+ boff
;
129 void run(Node
*a
) /* execution of parse tree starts here */
131 extern void stdinit(void);
138 Cell
*execute(Node
*u
) /* execute a node of the parse tree */
140 Cell
*(*proc
)(Node
**, int);
146 for (a
= u
; ; a
= a
->nnext
) {
149 x
= (Cell
*) (a
->narg
[0]);
150 if (isfld(x
) && !donefld
)
152 else if (isrec(x
) && !donerec
)
156 if (notlegal(a
->nobj
)) /* probably a Cell* but too risky to print */
157 FATAL("illegal statement");
158 proc
= proctab
[a
->nobj
-FIRSTTOKEN
];
159 x
= (*proc
)(a
->narg
, a
->nobj
);
160 if (isfld(x
) && !donefld
)
162 else if (isrec(x
) && !donerec
)
168 if (a
->nnext
== NULL
)
175 Cell
*program(Node
**a
, int n
) /* execute an awk program */
176 { /* a[0] = BEGIN, a[1] = body, a[2] = END */
179 if (setjmp(env
) != 0)
181 if (a
[0]) { /* BEGIN */
186 FATAL("illegal break, continue, next or nextfile from BEGIN");
190 if (bio_fmt
> BIO_HDR
) bio_set_colnm();
191 while (getrec(&record
, &recsize
, 1) > 0) {
192 if (bio_skip_hdr(record
)) continue;
193 if (bio_fmt
== BIO_HDR
&& (int)(*NR
+ .499) == 1) bio_set_colnm();
201 if (setjmp(env
) != 0) /* handles exit within END */
203 if (a
[2]) { /* END */
205 if (isbreak(x
) || isnext(x
) || iscont(x
))
206 FATAL("illegal break, continue, next or nextfile from END");
213 struct Frame
{ /* stack frame for awk function calls */
214 int nargs
; /* number of arguments in this call */
215 Cell
*fcncell
; /* pointer to Cell for function */
216 Cell
**args
; /* pointer to array of arguments after execute */
217 Cell
*retval
; /* return value */
220 #define NARGS 50 /* max args in a call */
222 struct Frame
*frame
= NULL
; /* base of stack frames; dynamically allocated */
223 int nframe
= 0; /* number of frames allocated */
224 struct Frame
*fp
= NULL
; /* frame pointer. bottom level unused */
226 Cell
*call(Node
**a
, int n
) /* function call. very kludgy and fragile */
228 static Cell newcopycell
= { OCELL
, CCOPY
, 0, "", 0.0, NUM
|STR
|DONTFREE
};
230 int freed
= 0; /* handles potential double freeing when fcn & param share a tempcell */
232 Cell
*args
[NARGS
], *oargs
[NARGS
]; /* BUG: fixed size arrays */
236 fcn
= execute(a
[0]); /* the function itself */
239 FATAL("calling undefined function %s", s
);
241 fp
= frame
= (struct Frame
*) calloc(nframe
+= 100, sizeof(struct Frame
));
243 FATAL("out of space for stack frames calling %s", s
);
245 for (ncall
= 0, x
= a
[1]; x
!= NULL
; x
= x
->nnext
) /* args in call */
247 ndef
= (int) fcn
->fval
; /* args in defn */
248 dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s
, ncall
, ndef
, (int) (fp
-frame
)) );
250 WARNING("function %s called with %d args, uses only %d",
252 if (ncall
+ ndef
> NARGS
)
253 FATAL("function %s has %d arguments, limit %d", s
, ncall
+ndef
, NARGS
);
254 for (i
= 0, x
= a
[1]; x
!= NULL
; i
++, x
= x
->nnext
) { /* get call args */
255 dprintf( ("evaluate args[%d], fp=%d:\n", i
, (int) (fp
-frame
)) );
258 dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
259 i
, NN(y
->nval
), y
->fval
, isarr(y
) ? "(array)" : NN(y
->sval
), y
->tval
) );
261 FATAL("can't use function %s as argument in %s", y
->nval
, s
);
263 args
[i
] = y
; /* arrays by ref */
265 args
[i
] = copycell(y
);
268 for ( ; i
< ndef
; i
++) { /* add null args for ones not provided */
270 *args
[i
] = newcopycell
;
272 fp
++; /* now ok to up frame */
273 if (fp
>= frame
+ nframe
) {
274 int dfp
= fp
- frame
; /* old index */
275 frame
= (struct Frame
*)
276 realloc((char *) frame
, (nframe
+= 100) * sizeof(struct Frame
));
278 FATAL("out of space for stack frames in %s", s
);
283 fp
->nargs
= ndef
; /* number defined with (excess are locals) */
284 fp
->retval
= gettemp();
286 dprintf( ("start exec of %s, fp=%d\n", s
, (int) (fp
-frame
)) );
287 y
= execute((Node
*)(fcn
->sval
)); /* execute body */
288 dprintf( ("finished exec of %s, fp=%d\n", s
, (int) (fp
-frame
)) );
290 for (i
= 0; i
< ndef
; i
++) {
291 Cell
*t
= fp
->args
[i
];
293 if (t
->csub
== CCOPY
) {
299 oargs
[i
]->tval
= t
->tval
;
300 oargs
[i
]->tval
&= ~(STR
|NUM
|DONTFREE
);
301 oargs
[i
]->sval
= t
->sval
;
305 } else if (t
!= y
) { /* kludge to prevent freeing twice */
308 } else if (t
== y
&& t
->csub
== CCOPY
) {
315 if (isexit(y
) || isnext(y
))
318 tempfree(y
); /* don't free twice! */
320 z
= fp
->retval
; /* return value */
321 dprintf( ("%s returns %g |%s| %o\n", s
, getfval(z
), getsval(z
), z
->tval
) );
326 Cell
*copycell(Cell
*x
) /* make a copy of a cell in a temp */
331 y
->csub
= CCOPY
; /* prevents freeing until call is over */
332 y
->nval
= x
->nval
; /* BUG? */
334 y
->sval
= tostring(x
->sval
);
336 y
->tval
= x
->tval
& ~(CON
|FLD
|REC
|DONTFREE
); /* copy is not constant or field */
337 /* is DONTFREE right? */
341 Cell
*arg(Node
**a
, int n
) /* nth argument of a function */
344 n
= ptoi(a
[0]); /* argument number, counting from 0 */
345 dprintf( ("arg(%d), fp->nargs=%d\n", n
, fp
->nargs
) );
347 FATAL("argument #%d of function %s was not supplied",
348 n
+1, fp
->fcncell
->nval
);
352 Cell
*jump(Node
**a
, int n
) /* break, continue, next, nextfile, return */
360 errorflag
= (int) getfval(y
);
367 if ((y
->tval
& (STR
|NUM
)) == (STR
|NUM
)) {
368 setsval(fp
->retval
, getsval(y
));
369 fp
->retval
->fval
= getfval(y
);
370 fp
->retval
->tval
|= NUM
;
372 else if (y
->tval
& STR
)
373 setsval(fp
->retval
, getsval(y
));
374 else if (y
->tval
& NUM
)
375 setfval(fp
->retval
, getfval(y
));
376 else /* can't happen */
377 FATAL("bad type variable %d", y
->tval
);
390 default: /* can't happen */
391 FATAL("illegal jump type %d", n
);
393 return 0; /* not reached */
396 Cell
*awkgetline(Node
**a
, int n
) /* get next line from specific input */
397 { /* a[0] is variable, a[1] is operator, a[2] is filename */
399 extern Cell
**fldtab
;
402 int bufsize
= recsize
;
405 if ((buf
= (char *) malloc(bufsize
)) == NULL
)
406 FATAL("out of memory in getline");
408 fflush(stdout
); /* in case someone is waiting for a prompt */
410 if (a
[1] != NULL
) { /* getline < file */
411 x
= execute(a
[2]); /* filename */
413 if (mode
== '|') /* input pipe */
414 mode
= LE
; /* arbitrary flag */
415 fp
= openfile(mode
, getsval(x
));
420 n
= readrec(&buf
, &bufsize
, fp
);
423 } else if (a
[0] != NULL
) { /* getline var <file */
427 } else { /* getline <file */
428 setsval(fldtab
[0], buf
);
429 if (is_number(fldtab
[0]->sval
)) {
430 fldtab
[0]->fval
= atof(fldtab
[0]->sval
);
431 fldtab
[0]->tval
|= NUM
;
434 } else { /* bare getline; use current input */
435 if (a
[0] == NULL
) /* getline */
436 n
= getrec(&record
, &recsize
, 1);
437 else { /* getline var */
438 n
= getrec(&buf
, &bufsize
, 0);
444 setfval(r
, (Awkfloat
) n
);
449 Cell
*getnf(Node
**a
, int n
) /* get NF */
453 return (Cell
*) a
[0];
456 Cell
*array(Node
**a
, int n
) /* a[0] is symtab, a[1] is list of subscripts */
463 int nsub
= strlen(*SUBSEP
);
465 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
466 FATAL("out of memory in array");
468 x
= execute(a
[0]); /* Cell* for symbol table */
470 for (np
= a
[1]; np
; np
= np
->nnext
) {
471 y
= execute(np
); /* subscript */
473 if (!adjbuf(&buf
, &bufsz
, strlen(buf
)+strlen(s
)+nsub
+1, recsize
, 0, "array"))
474 FATAL("out of memory for %s[%s...]", x
->nval
, buf
);
477 strcat(buf
, *SUBSEP
);
481 dprintf( ("making %s into an array\n", NN(x
->nval
)) );
484 x
->tval
&= ~(STR
|NUM
|DONTFREE
);
486 x
->sval
= (char *) makesymtab(NSYMTAB
);
488 z
= setsymtab(buf
, "", 0.0, STR
|NUM
, (Array
*) x
->sval
);
496 Cell
*awkdelete(Node
**a
, int n
) /* a[0] is symtab, a[1] is list of subscripts */
501 int nsub
= strlen(*SUBSEP
);
503 x
= execute(a
[0]); /* Cell* for symbol table */
506 if (a
[1] == 0) { /* delete the elements, not the table */
510 x
->sval
= (char *) makesymtab(NSYMTAB
);
514 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
515 FATAL("out of memory in adelete");
517 for (np
= a
[1]; np
; np
= np
->nnext
) {
518 y
= execute(np
); /* subscript */
520 if (!adjbuf(&buf
, &bufsz
, strlen(buf
)+strlen(s
)+nsub
+1, recsize
, 0, "awkdelete"))
521 FATAL("out of memory deleting %s[%s...]", x
->nval
, buf
);
524 strcat(buf
, *SUBSEP
);
534 Cell
*intest(Node
**a
, int n
) /* a[0] is index (list), a[1] is symtab */
541 int nsub
= strlen(*SUBSEP
);
543 ap
= execute(a
[1]); /* array name */
545 dprintf( ("making %s into an array\n", ap
->nval
) );
548 ap
->tval
&= ~(STR
|NUM
|DONTFREE
);
550 ap
->sval
= (char *) makesymtab(NSYMTAB
);
552 if ((buf
= (char *) malloc(bufsz
)) == NULL
) {
553 FATAL("out of memory in intest");
556 for (p
= a
[0]; p
; p
= p
->nnext
) {
557 x
= execute(p
); /* expr */
559 if (!adjbuf(&buf
, &bufsz
, strlen(buf
)+strlen(s
)+nsub
+1, recsize
, 0, "intest"))
560 FATAL("out of memory deleting %s[%s...]", x
->nval
, buf
);
564 strcat(buf
, *SUBSEP
);
566 k
= lookup(buf
, (Array
*) ap
->sval
);
576 Cell
*matchop(Node
**a
, int n
) /* ~ and match() */
582 int (*mf
)(fa
*, const char *) = match
, mode
= 0;
588 x
= execute(a
[1]); /* a[1] = target text */
590 if (a
[0] == 0) /* a[1] == 0: already-compiled reg expr */
591 i
= (*mf
)((fa
*) a
[2], s
);
593 y
= execute(a
[2]); /* a[2] = regular expr */
595 pfa
= makedfa(t
, mode
);
601 int start
= patbeg
- s
+ 1;
604 setfval(rstartloc
, (Awkfloat
) start
);
605 setfval(rlengthloc
, (Awkfloat
) patlen
);
610 } else if ((n
== MATCH
&& i
== 1) || (n
== NOTMATCH
&& i
== 0))
617 Cell
*boolop(Node
**a
, int n
) /* a[0] || a[1], a[0] && a[1], !a[0] */
634 if ( !i
) return(False
);
641 if (i
) return(False
);
643 default: /* can't happen */
644 FATAL("unknown boolean operator %d", n
);
646 return 0; /*NOTREACHED*/
649 Cell
*relop(Node
**a
, int n
) /* a[0 < a[1], etc. */
657 if (x
->tval
&NUM
&& y
->tval
&NUM
) {
658 j
= x
->fval
- y
->fval
;
659 i
= j
<0? -1: (j
>0? 1: 0);
661 i
= strcmp(getsval(x
), getsval(y
));
666 case LT
: if (i
<0) return(True
);
668 case LE
: if (i
<=0) return(True
);
670 case NE
: if (i
!=0) return(True
);
672 case EQ
: if (i
== 0) return(True
);
674 case GE
: if (i
>=0) return(True
);
676 case GT
: if (i
>0) return(True
);
678 default: /* can't happen */
679 FATAL("unknown relational operator %d", n
);
681 return 0; /*NOTREACHED*/
684 void tfree(Cell
*a
) /* free a tempcell */
687 dprintf( ("freeing %s %s %o\n", NN(a
->nval
), NN(a
->sval
), a
->tval
) );
691 FATAL("tempcell list is curdled");
696 Cell
*gettemp(void) /* get a tempcell */
701 tmps
= (Cell
*) calloc(100, sizeof(Cell
));
703 FATAL("out of space for temporaries");
704 for(i
= 1; i
< 100; i
++)
705 tmps
[i
-1].cnext
= &tmps
[i
];
714 Cell
*indirect(Node
**a
, int n
) /* $( a[0] ) */
722 val
= getfval(x
); /* freebsd: defend against super large field numbers */
723 if ((Awkfloat
)INT_MAX
< val
)
724 FATAL("trying to access out of range field %s", x
->nval
);
726 if (m
== 0 && !is_number(s
= getsval(x
))) /* suspicion! */
727 FATAL("illegal field $(%s), name \"%s\"", s
, x
->nval
);
728 /* BUG: can x->nval ever be null??? */
731 x
->ctype
= OCELL
; /* BUG? why are these needed? */
736 Cell
*substr(Node
**a
, int nnn
) /* substr(a[0], a[1], a[2]) */
759 m
= (int) getfval(y
);
766 n
= (int) getfval(z
);
774 dprintf( ("substr: m=%d, n=%d, s=%s\n", m
, n
, s
) );
776 temp
= s
[n
+m
-1]; /* with thanks to John Linderman */
778 setsval(y
, s
+ m
- 1);
784 Cell
*sindex(Node
**a
, int nnn
) /* index(a[0], a[1]) */
787 char *s1
, *s2
, *p1
, *p2
, *q
;
796 for (p1
= s1
; *p1
!= '\0'; p1
++) {
797 for (q
=p1
, p2
=s2
; *p2
!= '\0' && *q
== *p2
; q
++, p2
++)
800 v
= (Awkfloat
) (p1
- s1
+ 1); /* origin 1 */
810 #define MAXNUMSIZE 50
812 int format(char **pbuf
, int *pbufsize
, const char *s
, Node
*a
) /* printf-like conversions */
819 int fmtwd
; /* format width */
822 int bufsize
= *pbufsize
;
826 if ((fmt
= (char *) malloc(fmtsz
)) == NULL
)
827 FATAL("out of memory in format()");
829 adjbuf(&buf
, &bufsize
, MAXNUMSIZE
+1+p
-buf
, recsize
, &p
, "format1");
839 /* have to be real careful in case this is a huge number, eg, %100000d */
843 adjbuf(&buf
, &bufsize
, fmtwd
+1+p
-buf
, recsize
, &p
, "format2");
844 for (t
= fmt
; (*t
++ = *s
) != '\0'; s
++) {
845 if (!adjbuf(&fmt
, &fmtsz
, MAXNUMSIZE
+1+t
-fmt
, recsize
, &t
, "format3"))
846 FATAL("format item %.30s... ran format() out of memory", os
);
847 if (isalpha((uschar
)*s
) && *s
!= 'l' && *s
!= 'h' && *s
!= 'L')
848 break; /* the ansi panoply */
852 sprintf(t
-1, "%d", fmtwd
=(int) getfval(x
));
855 adjbuf(&buf
, &bufsize
, fmtwd
+1+p
-buf
, recsize
, &p
, "format");
856 t
= fmt
+ strlen(fmt
);
863 adjbuf(&buf
, &bufsize
, fmtwd
+1+p
-buf
, recsize
, &p
, "format4");
866 case 'f': case 'e': case 'g': case 'E': case 'G':
871 if(*(s
-1) == 'l') break;
876 case 'o': case 'x': case 'X': case 'u':
877 flag
= *(s
-1) == 'l' ? 'd' : 'u';
886 WARNING("weird printf conversion %s", fmt
);
891 FATAL("not enough args in printf(%s)", os
);
897 adjbuf(&buf
, &bufsize
, 1+n
+p
-buf
, recsize
, &p
, "format5");
899 case '?': sprintf(p
, "%s", fmt
); /* unknown, so dump it too */
904 adjbuf(&buf
, &bufsize
, 1+strlen(p
)+n
+p
-buf
, recsize
, &p
, "format6");
908 case 'f': sprintf(p
, fmt
, getfval(x
)); break;
909 case 'd': sprintf(p
, fmt
, (long) getfval(x
)); break;
910 case 'u': sprintf(p
, fmt
, (int) getfval(x
)); break;
916 if (!adjbuf(&buf
, &bufsize
, 1+n
+p
-buf
, recsize
, &p
, "format7"))
917 FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n
, t
);
923 sprintf(p
, fmt
, (int) getfval(x
));
925 *p
++ = '\0'; /* explicit null byte */
926 *p
= '\0'; /* next output will start here */
929 sprintf(p
, fmt
, getsval(x
)[0]);
932 FATAL("can't happen: bad conversion %c in format()", flag
);
940 for ( ; a
; a
= a
->nnext
) /* evaluate any remaining args */
947 Cell
*awksprintf(Node
**a
, int n
) /* sprintf(a[0]) */
954 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
955 FATAL("out of memory in awksprintf");
958 if (format(&buf
, &bufsz
, getsval(x
), y
) == -1)
959 FATAL("sprintf string %.30s... too long. can't happen.", buf
);
967 Cell
*awkprintf(Node
**a
, int n
) /* printf */
968 { /* a[0] is list of args, starting with format string */
969 /* a[1] is redirection operator, a[2] is redirection file */
977 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
978 FATAL("out of memory in awkprintf");
981 if ((len
= format(&buf
, &bufsz
, getsval(x
), y
)) == -1)
982 FATAL("printf string %.30s... too long. can't happen.", buf
);
985 /* fputs(buf, stdout); */
986 fwrite(buf
, len
, 1, stdout
);
988 FATAL("write error on stdout");
990 fp
= redirect(ptoi(a
[1]), a
[2]);
991 /* fputs(buf, fp); */
992 fwrite(buf
, len
, 1, fp
);
995 FATAL("write error on %s", filename(fp
));
1001 Cell
*arith(Node
**a
, int n
) /* a[0] + a[1], etc. also -a[0] */
1028 FATAL("division by zero");
1033 FATAL("division by zero in mod");
1041 if (j
>= 0 && modf(j
, &v
) == 0.0) /* pos integer exponent */
1042 i
= ipow(i
, (int) j
);
1044 i
= errcheck(pow(i
, j
), "pow");
1046 default: /* can't happen */
1047 FATAL("illegal arithmetic operator %d", n
);
1053 double ipow(double x
, int n
) /* x**n. ought to be done by pow, but isn't always */
1066 Cell
*incrdecr(Node
**a
, int n
) /* a[0]++, etc. */
1074 k
= (n
== PREINCR
|| n
== POSTINCR
) ? 1 : -1;
1075 if (n
== PREINCR
|| n
== PREDECR
) {
1086 Cell
*assign(Node
**a
, int n
) /* a[0] = a[1], a[0] += a[1], etc. */
1087 { /* this is subtle; don't muck with it. */
1094 if (n
== ASSIGN
) { /* ordinary assignment */
1095 if (x
== y
&& !(x
->tval
& (FLD
|REC
))) /* self-assignment: */
1096 ; /* leave alone unless it's a field */
1097 else if ((y
->tval
& (STR
|NUM
)) == (STR
|NUM
)) {
1098 setsval(x
, getsval(y
));
1099 x
->fval
= getfval(y
);
1103 setsval(x
, getsval(y
));
1105 setfval(x
, getfval(y
));
1107 funnyvar(y
, "read value of");
1125 FATAL("division by zero in /=");
1130 FATAL("division by zero in %%=");
1135 if (yf
>= 0 && modf(yf
, &v
) == 0.0) /* pos integer exponent */
1136 xf
= ipow(xf
, (int) yf
);
1138 xf
= errcheck(pow(xf
, yf
), "pow");
1141 FATAL("illegal assignment operator %d", n
);
1149 Cell
*cat(Node
**a
, int q
) /* a[0] cat a[1] */
1159 n1
= strlen(x
->sval
);
1160 n2
= strlen(y
->sval
);
1161 s
= (char *) malloc(n1
+ n2
+ 1);
1163 FATAL("out of space concatenating %.15s... and %.15s...",
1166 strcpy(s
+n1
, y
->sval
);
1175 Cell
*pastat(Node
**a
, int n
) /* a[0] { a[1] } */
1191 Cell
*dopa2(Node
**a
, int n
) /* a[0], a[1] { a[2] } */
1197 if (pairstack
[pair
] == 0) {
1200 pairstack
[pair
] = 1;
1203 if (pairstack
[pair
] == 1) {
1206 pairstack
[pair
] = 0;
1214 Cell
*split(Node
**a
, int nnn
) /* split(a[0], a[1], a[2]); a[3] is type */
1216 Cell
*x
= 0, *y
, *ap
;
1219 char *t
, temp
, num
[50], *fs
= 0;
1220 int n
, tempstat
, arg3type
;
1222 y
= execute(a
[0]); /* source string */
1224 arg3type
= ptoi(a
[3]);
1225 if (a
[2] == 0) /* fs string */
1227 else if (arg3type
== STRING
) { /* split(str,arr,"string") */
1230 } else if (arg3type
== REGEXPR
)
1231 fs
= "(regexpr)"; /* split(str,arr,/regexpr/) */
1233 FATAL("illegal type of split");
1235 ap
= execute(a
[1]); /* array name */
1237 dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s
, NN(ap
->nval
), fs
) );
1240 ap
->sval
= (char *) makesymtab(NSYMTAB
);
1243 if (arg3type
== REGEXPR
&& strlen((char*)((fa
*)a
[2])->restr
) == 0) {
1244 /* split(s, a, //); have to arrange that it looks like empty sep */
1249 if (*s
!= '\0' && (strlen(fs
) > 1 || arg3type
== REGEXPR
)) { /* reg expr */
1251 if (arg3type
== REGEXPR
) { /* it's ready already */
1254 pfa
= makedfa(fs
, 1);
1256 if (nematch(pfa
,s
)) {
1257 tempstat
= pfa
->initstat
;
1261 sprintf(num
, "%d", n
);
1265 setsymtab(num
, s
, atof(s
), STR
|NUM
, (Array
*) ap
->sval
);
1267 setsymtab(num
, s
, 0.0, STR
, (Array
*) ap
->sval
);
1269 s
= patbeg
+ patlen
;
1270 if (*(patbeg
+patlen
-1) == 0 || *s
== 0) {
1272 sprintf(num
, "%d", n
);
1273 setsymtab(num
, "", 0.0, STR
, (Array
*) ap
->sval
);
1274 pfa
->initstat
= tempstat
;
1277 } while (nematch(pfa
,s
));
1278 pfa
->initstat
= tempstat
; /* bwk: has to be here to reset */
1279 /* cf gsub and refldbld */
1282 sprintf(num
, "%d", n
);
1284 setsymtab(num
, s
, atof(s
), STR
|NUM
, (Array
*) ap
->sval
);
1286 setsymtab(num
, s
, 0.0, STR
, (Array
*) ap
->sval
);
1289 } else if (sep
== ' ') {
1291 while (*s
== ' ' || *s
== '\t' || *s
== '\n')
1299 while (*s
!=' ' && *s
!='\t' && *s
!='\n' && *s
!='\0');
1302 sprintf(num
, "%d", n
);
1304 setsymtab(num
, t
, atof(t
), STR
|NUM
, (Array
*) ap
->sval
);
1306 setsymtab(num
, t
, 0.0, STR
, (Array
*) ap
->sval
);
1311 } else if (sep
== 0) { /* new: split(s, a, "") => 1 char/elem */
1312 for (n
= 0; *s
!= 0; s
++) {
1315 sprintf(num
, "%d", n
);
1318 if (isdigit((uschar
)buf
[0]))
1319 setsymtab(num
, buf
, atof(buf
), STR
|NUM
, (Array
*) ap
->sval
);
1321 setsymtab(num
, buf
, 0.0, STR
, (Array
*) ap
->sval
);
1323 } else if (*s
!= 0) {
1327 while (*s
!= sep
&& *s
!= '\n' && *s
!= '\0')
1331 sprintf(num
, "%d", n
);
1333 setsymtab(num
, t
, atof(t
), STR
|NUM
, (Array
*) ap
->sval
);
1335 setsymtab(num
, t
, 0.0, STR
, (Array
*) ap
->sval
);
1343 if (a
[2] != 0 && arg3type
== STRING
) {
1352 Cell
*condexpr(Node
**a
, int n
) /* a[0] ? a[1] : a[2] */
1367 Cell
*ifstat(Node
**a
, int n
) /* if (a[0]) a[1]; else a[2] */
1375 } else if (a
[2] != 0) {
1382 Cell
*whilestat(Node
**a
, int n
) /* while (a[0]) a[1] */
1396 if (isnext(x
) || isexit(x
) || isret(x
))
1402 Cell
*dostat(Node
**a
, int n
) /* do a[0]; while(a[1]) */
1410 if (isnext(x
) || isexit(x
) || isret(x
))
1420 Cell
*forstat(Node
**a
, int n
) /* for (a[0]; a[1]; a[2]) a[3] */
1429 if (!istrue(x
)) return(x
);
1433 if (isbreak(x
)) /* turn off break */
1435 if (isnext(x
) || isexit(x
) || isret(x
))
1443 Cell
*instat(Node
**a
, int n
) /* for (a[0] in a[1]) a[2] */
1445 Cell
*x
, *vp
, *arrayp
, *cp
, *ncp
;
1450 arrayp
= execute(a
[1]);
1451 if (!isarr(arrayp
)) {
1454 tp
= (Array
*) arrayp
->sval
;
1456 for (i
= 0; i
< tp
->size
; i
++) { /* this routine knows too much */
1457 for (cp
= tp
->tab
[i
]; cp
!= NULL
; cp
= ncp
) {
1458 setsval(vp
, cp
->nval
);
1465 if (isnext(x
) || isexit(x
) || isret(x
)) {
1475 Cell
*bltin(Node
**a
, int n
) /* builtin functions. a[0] is type, a[1] is arg list */
1484 void flush_all(void);
1488 nextarg
= a
[1]->nnext
;
1492 u
= ((Array
*) x
->sval
)->nelem
; /* GROT. should be function*/
1494 u
= strlen(getsval(x
));
1497 u
= errcheck(log(getfval(x
)), "log"); break;
1499 modf(getfval(x
), &u
); break;
1501 u
= errcheck(exp(getfval(x
)), "exp"); break;
1503 u
= errcheck(sqrt(getfval(x
)), "sqrt"); break;
1505 u
= sin(getfval(x
)); break;
1507 u
= cos(getfval(x
)); break;
1510 WARNING("atan2 requires two arguments; returning 1.0");
1513 y
= execute(a
[1]->nnext
);
1514 u
= atan2(getfval(x
), getfval(y
));
1516 nextarg
= nextarg
->nnext
;
1520 fflush(stdout
); /* in case something is buffered already */
1521 u
= (Awkfloat
) system(getsval(x
)) / 256; /* 256 is unix-dep */
1524 /* in principle, rand() returns something in 0..RAND_MAX */
1525 u
= (Awkfloat
) (rand() % RAND_MAX
) / RAND_MAX
;
1528 if (isrec(x
)) /* no argument provided */
1529 u
= time((time_t *)0);
1533 srand((unsigned int) u
);
1539 buf
= tostring(getsval(x
));
1540 if (t
== FTOUPPER
) {
1541 for (p
= buf
; *p
; p
++)
1542 if (islower((uschar
) *p
))
1543 *p
= toupper((uschar
)*p
);
1545 for (p
= buf
; *p
; p
++)
1546 if (isupper((uschar
) *p
))
1547 *p
= tolower((uschar
)*p
);
1555 if (isrec(x
) || strlen(getsval(x
)) == 0) {
1556 flush_all(); /* fflush() or fflush("") -> all */
1558 } else if ((fp
= openfile(FFLUSH
, getsval(x
))) == NULL
)
1563 default: /* can't happen */
1564 if ((y
= bio_func(t
, x
, a
)) != 0) {
1568 FATAL("illegal function type %d", t
);
1575 WARNING("warning: function has too many arguments");
1576 for ( ; nextarg
; nextarg
= nextarg
->nnext
)
1582 Cell
*printstat(Node
**a
, int n
) /* print a[0] */
1588 if (a
[1] == 0) /* a[1] is redirection operator, a[2] is file */
1591 fp
= redirect(ptoi(a
[1]), a
[2]);
1592 for (x
= a
[0]; x
!= NULL
; x
= x
->nnext
) {
1594 fputs(getpssval(y
), fp
);
1596 if (x
->nnext
== NULL
)
1604 FATAL("write error on %s", filename(fp
));
1608 Cell
*nullproc(Node
**a
, int n
)
1616 FILE *redirect(int a
, Node
*b
) /* set up all i/o redirections */
1624 fp
= openfile(a
, fname
);
1626 FATAL("can't open file %s", fname
);
1634 int mode
; /* '|', 'a', 'w' => LE/LT, GT */
1639 void stdinit(void) /* in case stdin, etc., are not constants */
1642 files
= calloc(nfiles
, sizeof(*files
));
1644 FATAL("can't allocate file memory for %u files", nfiles
);
1645 files
[0].fp
= stdin
;
1646 files
[0].fname
= "/dev/stdin";
1648 files
[1].fp
= stdout
;
1649 files
[1].fname
= "/dev/stdout";
1651 files
[2].fp
= stderr
;
1652 files
[2].fname
= "/dev/stderr";
1656 FILE *openfile(int a
, const char *us
)
1663 FATAL("null file name in print or getline");
1664 for (i
=0; i
< nfiles
; i
++)
1665 if (files
[i
].fname
&& strcmp(s
, files
[i
].fname
) == 0) {
1666 if (a
== files
[i
].mode
|| (a
==APPEND
&& files
[i
].mode
==GT
))
1671 if (a
== FFLUSH
) /* didn't find it, so don't create it! */
1674 for (i
=0; i
< nfiles
; i
++)
1675 if (files
[i
].fp
== 0)
1679 int nnf
= nfiles
+ FOPEN_MAX
;
1680 nf
= realloc(files
, nnf
* sizeof(*nf
));
1682 FATAL("cannot grow files for %s and %d files", s
, nnf
);
1683 memset(&nf
[nfiles
], 0, FOPEN_MAX
* sizeof(*nf
));
1687 fflush(stdout
); /* force a semblance of order */
1691 } else if (a
== APPEND
) {
1693 m
= GT
; /* so can mix > and >> */
1694 } else if (a
== '|') { /* output pipe */
1696 } else if (a
== LE
) { /* input pipe */
1698 } else if (a
== LT
) { /* getline <file */
1699 fp
= strcmp(s
, "-") == 0 ? stdin
: fopen(s
, "r"); /* "-" is stdin */
1700 } else /* can't happen */
1701 FATAL("illegal redirection %d", a
);
1703 files
[i
].fname
= tostring(s
);
1710 const char *filename(FILE *fp
)
1714 for (i
= 0; i
< nfiles
; i
++)
1715 if (fp
== files
[i
].fp
)
1716 return files
[i
].fname
;
1720 Cell
*closefile(Node
**a
, int n
)
1729 for (i
= 0; i
< nfiles
; i
++) {
1730 if (files
[i
].fname
&& strcmp(x
->sval
, files
[i
].fname
) == 0) {
1731 if (ferror(files
[i
].fp
))
1732 WARNING( "i/o error occurred on %s", files
[i
].fname
);
1733 if (files
[i
].mode
== '|' || files
[i
].mode
== LE
)
1734 stat
= pclose(files
[i
].fp
);
1736 stat
= fclose(files
[i
].fp
);
1738 WARNING( "i/o error occurred closing %s", files
[i
].fname
);
1739 if (i
> 2) /* don't do /dev/std... */
1740 xfree(files
[i
].fname
);
1741 files
[i
].fname
= NULL
; /* watch out for ref thru this */
1747 setfval(x
, (Awkfloat
) stat
);
1755 for (i
= 0; i
< FOPEN_MAX
; i
++) {
1757 if (ferror(files
[i
].fp
))
1758 WARNING( "i/o error occurred on %s", files
[i
].fname
);
1759 if (files
[i
].mode
== '|' || files
[i
].mode
== LE
)
1760 stat
= pclose(files
[i
].fp
);
1762 stat
= fclose(files
[i
].fp
);
1764 WARNING( "i/o error occurred while closing %s", files
[i
].fname
);
1769 void flush_all(void)
1773 for (i
= 0; i
< nfiles
; i
++)
1775 fflush(files
[i
].fp
);
1778 void backsub(char **pb_ptr
, char **sptr_ptr
);
1780 Cell
*sub(Node
**a
, int nnn
) /* substitute command */
1782 char *sptr
, *pb
, *q
;
1783 Cell
*x
, *y
, *result
;
1786 int bufsz
= recsize
;
1788 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
1789 FATAL("out of memory in sub");
1790 x
= execute(a
[3]); /* target string */
1792 if (a
[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1793 pfa
= (fa
*) a
[1]; /* regular expression */
1796 pfa
= makedfa(getsval(y
), 1);
1799 y
= execute(a
[2]); /* replacement string */
1801 if (pmatch(pfa
, t
)) {
1803 adjbuf(&buf
, &bufsz
, 1+patbeg
-sptr
, recsize
, 0, "sub");
1805 while (sptr
< patbeg
)
1808 while (*sptr
!= 0) {
1809 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "sub");
1810 if (*sptr
== '\\') {
1811 backsub(&pb
, &sptr
);
1812 } else if (*sptr
== '&') {
1814 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "sub");
1815 for (q
= patbeg
; q
< patbeg
+patlen
; )
1821 if (pb
> buf
+ bufsz
)
1822 FATAL("sub result1 %.30s too big; can't happen", buf
);
1823 sptr
= patbeg
+ patlen
;
1824 if ((patlen
== 0 && *patbeg
) || (patlen
&& *(sptr
-1))) {
1825 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "sub");
1826 while ((*pb
++ = *sptr
++) != 0)
1829 if (pb
> buf
+ bufsz
)
1830 FATAL("sub result2 %.30s too big; can't happen", buf
);
1831 setsval(x
, buf
); /* BUG: should be able to avoid copy */
1840 Cell
*gsub(Node
**a
, int nnn
) /* global substitute */
1843 char *rptr
, *sptr
, *t
, *pb
, *q
;
1846 int mflag
, tempstat
, num
;
1847 int bufsz
= recsize
;
1849 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
1850 FATAL("out of memory in gsub");
1851 mflag
= 0; /* if mflag == 0, can replace empty string */
1853 x
= execute(a
[3]); /* target string */
1855 if (a
[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1856 pfa
= (fa
*) a
[1]; /* regular expression */
1859 pfa
= makedfa(getsval(y
), 1);
1862 y
= execute(a
[2]); /* replacement string */
1863 if (pmatch(pfa
, t
)) {
1864 tempstat
= pfa
->initstat
;
1869 if (patlen
== 0 && *patbeg
!= 0) { /* matched empty string */
1870 if (mflag
== 0) { /* can replace empty */
1873 while (*sptr
!= 0) {
1874 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gsub");
1875 if (*sptr
== '\\') {
1876 backsub(&pb
, &sptr
);
1877 } else if (*sptr
== '&') {
1879 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gsub");
1880 for (q
= patbeg
; q
< patbeg
+patlen
; )
1886 if (*t
== 0) /* at end */
1888 adjbuf(&buf
, &bufsz
, 2+pb
-buf
, recsize
, &pb
, "gsub");
1890 if (pb
> buf
+ bufsz
) /* BUG: not sure of this test */
1891 FATAL("gsub result0 %.30s too big; can't happen", buf
);
1894 else { /* matched nonempty string */
1897 adjbuf(&buf
, &bufsz
, 1+(patbeg
-sptr
)+pb
-buf
, recsize
, &pb
, "gsub");
1898 while (sptr
< patbeg
)
1901 while (*sptr
!= 0) {
1902 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gsub");
1903 if (*sptr
== '\\') {
1904 backsub(&pb
, &sptr
);
1905 } else if (*sptr
== '&') {
1907 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gsub");
1908 for (q
= patbeg
; q
< patbeg
+patlen
; )
1913 t
= patbeg
+ patlen
;
1914 if (patlen
== 0 || *t
== 0 || *(t
-1) == 0)
1916 if (pb
> buf
+ bufsz
)
1917 FATAL("gsub result1 %.30s too big; can't happen", buf
);
1920 } while (pmatch(pfa
,t
));
1922 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "gsub");
1923 while ((*pb
++ = *sptr
++) != 0)
1925 done
: if (pb
< buf
+ bufsz
)
1927 else if (*(pb
-1) != '\0')
1928 FATAL("gsub result2 %.30s truncated; can't happen", buf
);
1929 setsval(x
, buf
); /* BUG: should be able to avoid copy + free */
1930 pfa
->initstat
= tempstat
;
1941 void backsub(char **pb_ptr
, char **sptr_ptr
) /* handle \\& variations */
1942 { /* sptr[0] == '\\' */
1943 char *pb
= *pb_ptr
, *sptr
= *sptr_ptr
;
1945 if (sptr
[1] == '\\') {
1946 if (sptr
[2] == '\\' && sptr
[3] == '&') { /* \\\& -> \& */
1950 } else if (sptr
[2] == '&') { /* \\& -> \ + matched */
1953 } else { /* \\x -> \\x */
1957 } else if (sptr
[1] == '&') { /* literal & */
1960 } else /* literal \ */