4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
27 * Copyright 1985, 1994 by Mortice Kern Systems Inc. All rights reserved.
29 * Based on MKS awk(1) ported to be /usr/xpg4/bin/awk with POSIX/XCU4 changes
35 static int dohash(wchar_t *name
);
36 static NODE
*arithmetic(NODE
*np
);
37 static NODE
*comparison(NODE
*np
);
38 static int type_of(NODE
*np
);
39 static NODE
*lfield(INT fieldno
, NODE
*value
);
40 static NODE
*rfield(INT fieldno
);
41 static NODE
*userfunc(NODE
*np
);
42 static wchar_t *lltoa(long long l
);
43 static NODE
*exprconcat(NODE
*np
, int len
);
44 static int s_if(NODE
*np
);
45 static int s_while(NODE
*np
);
46 static int s_for(NODE
*np
);
47 static int s_forin(NODE
*np
);
48 static void setrefield(NODE
*value
);
49 static void freetemps(void);
50 static int action(NODE
*np
);
51 static wchar_t *makeindex(NODE
*np
, wchar_t *array
, int tag
);
52 static int exprtest(NODE
*np
);
54 #define regmatch(rp, s) REGWEXEC(rp, s, 0, (REGWMATCH_T*)NULL, 0)
57 * This code allows for integers to be stored in longs (type INT) and
58 * only promoted to double precision floating point numbers (type REAL)
59 * when overflow occurs during +, -, or * operations. This is very
60 * non-portable if you desire such a speed optimisation. You may wish
61 * to put something here for your system. This "something" would likely
62 * include either an assembler "jump on overflow" instruction or a
63 * method to get traps on overflows from the hardware.
65 * This portable method works for ones and twos complement integer
66 * representations (which is, realistically) almost all machines.
69 #define addoverflow() asm jo overflow
70 #define suboverflow() asm jo overflow
73 * These are portable to two's complement integer machines
75 #define addoverflow() if ((i1^i2) >= 0 && (iresult^i1) < 0) goto overflow
76 #define suboverflow() if ((i1^i2) < 0 && (iresult^i2) >= 0) goto overflow
78 #define muloverflow() if (((short)i1 != i1 || (short)i2 != i2) && \
79 ((i2 != 0 && iresult/i2 != i1) || \
80 (i1 == LONG_MIN && i2 == -1))) goto overflow
82 static char notarray
[] = "scalar \"%s\" cannot be used as array";
83 static char badarray
[] = "array \"%s\" cannot be used as a scalar";
84 static char varnotfunc
[] = "variable \"%s\" cannot be used as a function";
85 static char tmfld
[] = "Too many fields (LIMIT: %d)";
86 static char toolong
[] = "Record too long (LIMIT: %d bytes)";
87 static char divzero
[] = "division (/ or %%) by zero";
88 static char toodeep
[] = "too deeply nested for in loop (LIMIT: %d)";
90 static wchar_t numbuf
[NUMSIZE
]; /* Used to convert INTs to strings */
91 static wchar_t *fields
[NFIELD
]; /* Cache of pointers into fieldbuf */
92 static wchar_t *fieldbuf
; /* '\0' separated copy of linebuf */
93 static NODE nodes
[NSNODE
]; /* Cache of quick access nodes */
94 static NODE
*fnodep
= &nodes
[0];
96 static wchar_t indexbuf
[NINDEXBUF
]; /* Used for simple array indices */
97 static int concflag
; /* In CONCAT operation (no frees) */
98 static NODE
*retval
; /* Last return value of a function */
101 * The following stack is used to store the next pointers for all nested
102 * for-in loops. This needs to be global so that delete can check to see
103 * if it is deleting the next node to be used by a loop.
105 #define NFORINLOOP 10
106 static NODE
* forindex
[NFORINLOOP
];
107 static NODE
** next_forin
= forindex
;
110 * Assign a string directly to a NODE without creating an intermediate
111 * NODE. This can handle either FALLOC, FSTATIC, FNOALLOC or FSENSE for
112 * "flags" argument. Also the NODE "np" must be reduced to an lvalue
113 * (PARM nodes are not acceptable).
116 strassign(NODE
*np
, STRING string
, int flags
, size_t length
)
118 if (np
->n_type
== FUNC
)
119 awkerr(gettext("attempt to redefine builtin function"));
120 else if (np
->n_type
== GETLINE
|| np
->n_type
== KEYWORD
)
121 awkerr(gettext("inadmissible use of reserved keyword"));
122 if (np
->n_flags
& FSPECIAL
) {
123 (void) nassign(np
, stringnode(string
, flags
, length
));
126 if (isastring(np
->n_flags
))
127 free((wchar_t *)np
->n_string
);
128 np
->n_strlen
= length
++;
129 if (flags
& FALLOC
) {
130 length
*= sizeof (wchar_t);
131 np
->n_string
= (STRING
) emalloc(length
);
132 (void) memcpy((void *)np
->n_string
, string
, length
);
134 np
->n_string
= string
;
135 if (flags
& FNOALLOC
) {
140 np
->n_flags
&= FSAVE
;
141 if (flags
& FSENSE
) {
143 flags
|= type_of(np
);
146 np
->n_flags
|= flags
;
150 * Assign to a variable node.
151 * LHS must be a VAR type and RHS must be reduced by now.
152 * To speed certain operations up, check for
153 * certain things here and do special assignments.
156 nassign(NODE
*np
, NODE
*value
)
158 register wchar_t *cp
;
161 /* short circuit assignment of a node to itself */
164 if (np
->n_flags
& FSPECIAL
) {
165 if (np
== varRS
|| np
== varFS
) {
166 if (isastring(np
->n_flags
))
167 free((void *)np
->n_string
);
168 len
= sizeof (wchar_t) * ((np
->n_strlen
=
169 wcslen(cp
= exprstring(value
)))+1);
170 np
->n_string
= emalloc(len
);
171 (void) memcpy((wchar_t *)np
->n_string
, cp
, len
);
172 np
->n_flags
= FALLOC
|FSTRING
|FSPECIAL
;
174 if (np
->n_string
[0] == '\n')
175 awkrecord
= defrecord
;
176 else if (np
->n_string
[0] == '\0')
177 awkrecord
= multirecord
;
179 awkrecord
= charrecord
;
180 } else if (np
== varFS
) {
181 if (resep
!= (REGEXP
)NULL
) {
183 resep
= (REGEXP
)NULL
;
185 if (wcslen((wchar_t *)np
->n_string
) > 1)
187 else if (np
->n_string
[0] == ' ')
188 awkfield
= whitefield
;
190 awkfield
= blackfield
;
195 if (isastring(np
->n_flags
))
196 free((wchar_t *)np
->n_string
);
197 if (isstring(value
->n_flags
)) {
198 np
->n_strlen
= value
->n_strlen
;
199 if (value
->n_flags
&FALLOC
|| value
->n_string
!= _null
) {
200 len
= (np
->n_strlen
+1) * sizeof (wchar_t);
201 np
->n_string
= emalloc(len
);
202 (void) memcpy(np
->n_string
, value
->n_string
, len
);
203 np
->n_flags
&= FSAVE
;
204 np
->n_flags
|= value
->n_flags
& ~FSAVE
;
205 np
->n_flags
|= FALLOC
;
208 np
->n_string
= value
->n_string
;
209 } else if (value
->n_flags
& FINT
)
210 np
->n_int
= value
->n_int
;
212 np
->n_real
= value
->n_real
;
213 np
->n_flags
&= FSAVE
;
214 np
->n_flags
|= value
->n_flags
& ~FSAVE
;
219 * Set regular expression FS value.
227 if ((n
= REGWCOMP(&re
, np
->n_string
)) != REG_OK
) {
228 REGWERROR(n
, &re
, (char *)linebuf
, sizeof (linebuf
));
229 awkerr(gettext("syntax error \"%s\" in /%s/\n"),
230 (char *)linebuf
, np
->n_string
);
237 * Assign to an l-value node.
240 assign(NODE
*left
, NODE
*right
)
242 if (isleaf(right
->n_flags
)) {
243 if (right
->n_type
== PARM
)
244 right
= right
->n_next
;
246 right
= exprreduce(right
);
248 switch (left
->n_type
) {
250 left
= exprreduce(left
);
253 return (nassign(left
, right
));
257 * If it's a parameter then link to the actual value node and
258 * do the checks again.
264 return (lfield(exprint(left
->n_left
), right
));
268 awkerr(gettext("cannot assign to function \"%s\""),
272 awkerr(gettext("lvalue required in assignment"));
279 * Compiled tree non-terminal node.
282 node(int type
, NODE
*left
, NODE
*right
)
286 np
= emptynode(type
, 0);
289 np
->n_lineno
= lineno
;
294 * Create an integer node.
301 np
= emptynode(CONSTANT
, 0);
302 np
->n_flags
= FINT
|FVINT
;
308 * Create a real number node.
315 np
= emptynode(CONSTANT
, 0);
316 np
->n_flags
= FREAL
|FVREAL
;
322 * Make a node for a string.
325 stringnode(STRING s
, int how
, size_t length
)
329 np
= emptynode(CONSTANT
, 0);
330 np
->n_strlen
= length
;
332 np
->n_string
= emalloc(length
= (length
+1) * sizeof (wchar_t));
333 (void) memcpy(np
->n_string
, s
, length
);
336 if (how
& FNOALLOC
) {
342 np
->n_flags
= type_of(np
);
345 np
->n_flags
= FSTRING
;
351 * Save a copy of a string.
354 strsave(wchar_t *old
)
359 new = (STRING
)emalloc(len
= (wcslen(old
)+1) * sizeof (wchar_t));
360 (void) memcpy(new, old
, len
);
365 * Allocate an empty node of given type.
366 * String space for the node is given by `length'.
369 emptynode(int type
, size_t length
)
373 if (length
== 0 && running
&& fnodep
< &nodes
[NSNODE
]) {
376 np
= (NODE
*)emalloc(sizeof (NODE
) +
377 (length
* sizeof (wchar_t)));
378 if (running
&& type
!= VAR
&& type
!= ARRAY
) {
379 np
->n_next
= freelist
;
383 np
->n_flags
= FNONTOK
;
396 if (isastring(np
->n_flags
))
397 free((wchar_t *)np
->n_string
);
398 else if (np
->n_type
== RE
) {
399 REGWFREE(np
->n_regexp
);
405 * Install a keyword of given `type'.
408 kinstall(LOCCHARP name
, int type
)
414 np
= emptynode(KEYWORD
, l
);
415 np
->n_keywtype
= type
;
416 (void) memcpy(np
->n_name
, name
, (l
+1) * sizeof (wchar_t));
421 * Install built-in function.
424 finstall(LOCCHARP name
, FUNCTION func
, int type
)
430 np
= emptynode(type
, l
);
431 np
->n_function
= func
;
432 (void) memcpy(np
->n_name
, name
, (l
+1) * sizeof (wchar_t));
438 * Lookup an identifier.
439 * nocreate contains the following flag values:
440 * 1 if no creation of a new NODE,
441 * 0 if ok to create new NODE
444 vlookup(wchar_t *name
, int nocreate
)
446 register ushort_t hash
;
449 np
= symtab
[hashbuck(hash
= dohash((wchar_t *)name
))];
450 while (np
!= NNULL
) {
451 if (np
->n_hash
== hash
&& wcscmp(name
, np
->n_name
) == 0)
458 np
= emptynode(VAR
, hash
= wcslen(name
));
459 np
->n_flags
= FSTRING
|FVINT
;
461 np
->n_string
= _null
;
462 (void) memcpy(np
->n_name
, name
,
463 (hash
+1) * sizeof (wchar_t));
470 * Add a symbol to the table.
477 np
->n_hash
= dohash((wchar_t *)np
->n_name
);
478 spp
= &symtab
[hashbuck(np
->n_hash
)];
484 * Delete the given node from the symbol table.
485 * If fflag is non-zero, also free the node space.
486 * This routine must also check the stack of forin loop pointers. If
487 * we are deleting the next item to be used, then the pointer must be
491 delsymtab(NODE
*np
, int fflag
)
494 register NODE
*prevp
;
495 register NODE
**sptr
;
502 h
= hashbuck(np
->n_hash
);
504 for (rnp
= symtab
[h
]; rnp
!= NNULL
; rnp
= rnp
->n_next
) {
507 * check all of the for-in loop pointers
508 * to see if any need to be advanced because
509 * this element is being deleted.
511 if (next_forin
!= forindex
) {
514 if (*--sptr
== rnp
) {
518 } while (sptr
!= forindex
);
521 symtab
[h
] = rnp
->n_next
; else
522 prevp
->n_next
= rnp
->n_next
;
535 dohash(wchar_t *name
)
537 register int hash
= 0;
539 while (*name
!= '\0')
545 * Top level executor for an awk programme.
546 * This will be passed: pattern, action or a list of these.
547 * The former function to evaluate a pattern has been
548 * subsumed into this function for speed.
552 * other expressions (including regular expressions)
566 while (wp
!= NNULL
) {
567 if (wp
->n_type
== COMMA
) {
574 if (np
->n_type
!= PACT
)
575 awkerr(interr
, "PACT");
577 * Save the parent node and evaluate the pattern.
578 * If it evaluates to false (0) just continue
579 * to the next pattern/action (PACT) pair.
586 } else if (phase
!= 0) {
587 if (np
->n_type
!= phase
)
589 } else if ((type
= np
->n_type
) == BEGIN
|| type
== END
) {
591 } else if (type
== COMMA
) {
593 * The grammar only allows expressions
594 * to be separated by the ',' operator
595 * for range patterns.
597 if (np
->n_flags
& FMATCH
) {
598 if (exprint(np
->n_right
) != 0)
599 np
->n_flags
&= ~FMATCH
;
600 } else if (exprint(np
->n_left
) != 0) {
601 if (exprint(np
->n_right
) == 0)
602 np
->n_flags
|= FMATCH
;
605 } else if (exprint(np
) == 0)
608 if (action(np
->n_right
)) {
613 if (freelist
!= NNULL
)
618 * Free all temporary nodes.
623 register NODE
*np
, *nnp
;
627 for (np
= &nodes
[0]; np
< fnodep
; np
++) {
628 if (isastring(np
->n_flags
)) {
629 free((wchar_t *)np
->n_string
);
630 } else if (np
->n_type
== RE
) {
631 REGWFREE(np
->n_regexp
);
635 for (np
= freelist
; np
!= NNULL
; np
= nnp
) {
643 * Do the given action.
644 * Actions are statements or expressions.
650 register int act
= 0;
653 while (wp
!= NNULL
) {
654 if (wp
->n_type
== COMMA
) {
661 if (freelist
!= NNULL
)
665 * Don't change order of these cases without
666 * changing order in awk.y declarations.
667 * The order is optimised.
669 switch (np
->n_type
) {
671 (void) assign(np
->n_left
, np
->n_right
);
683 if (np
->n_left
!= NNULL
)
684 act
= (int)exprint(np
->n_left
); else
691 awkerr(gettext("return outside of a function"));
692 np
= np
->n_left
!= NNULL
693 ? exprreduce(np
->n_left
)
695 retval
= emptynode(CONSTANT
, 0);
696 retval
->n_flags
= FINT
;
697 (void) nassign(retval
, np
);
708 if ((l
= np
->n_left
)->n_type
== PARM
) {
710 if (!(l
->n_flags
& FLARRAY
))
719 if ((np
= l
->n_left
)->n_type
== PARM
) {
721 if (!(np
->n_flags
& FLARRAY
))
725 * get pointer to the node for this array
726 * element using the hash key.
730 * now search linearly from the beginning of
731 * the list to find the element before the
732 * one being deleted. This must be done
733 * because arrays are singley-linked.
735 while (np
!= NNULL
) {
736 if (np
->n_alink
== l
) {
737 np
->n_alink
= l
->n_alink
;
746 if (isstring(l
->n_flags
) &&
747 l
->n_string
== _null
)
752 "may delete only array element or array"));
759 if ((act
= s_while(np
)) != 0)
764 if ((act
= s_for(np
)) != 0)
769 if ((act
= s_forin(np
)) != 0)
774 if ((act
= s_if(np
)) != 0)
779 (void) exprreduce(np
);
792 * Delete an entire array
801 while (nnp
!= NNULL
) {
809 * Return the INT value of an expression.
814 if (isleaf(np
->n_flags
)) {
815 if (np
->n_type
== PARM
)
820 switch (np
->n_type
) {
824 if (np
->n_flags
& FINT
)
826 if (np
->n_flags
& FREAL
)
827 return ((INT
)np
->n_real
);
828 return ((INT
)wcstoll(np
->n_string
, NULL
, 10));
831 awkerr(interr
, "exprint");
838 * Return a real number from an expression tree.
844 return ((REAL
)loopexit
);
845 if (isleaf(np
->n_flags
)) {
846 if (np
->n_type
== PARM
)
851 switch (np
->n_type
) {
855 if (np
->n_flags
& FREAL
)
857 if (np
->n_flags
& FINT
)
858 return ((REAL
)np
->n_int
);
859 return ((REAL
)wcstod((wchar_t *)np
->n_string
, (wchar_t **)0));
862 awkerr(interr
, "exprreal");
869 * Return a string from an expression tree.
874 if (isleaf(np
->n_flags
)) {
875 if (np
->n_type
== PARM
)
880 switch (np
->n_type
) {
884 if (isstring(np
->n_flags
))
885 return (np
->n_string
);
886 if (np
->n_flags
& FINT
)
887 return (STRING
)lltoa((long long)np
->n_int
);
890 (void) wsprintf(numbuf
,
891 (const char *) (tmp
= wcstombsdup(exprstring(varCONVFMT
))),
896 return ((STRING
)numbuf
);
899 awkerr(interr
, "exprstring");
906 * Convert number to string.
911 register wchar_t *p
= &numbuf
[NUMSIZE
];
914 static wchar_t zero
[] = M_MB_L("0");
920 neg
= 1, l
= -l
; else
922 if ((s
= (short)l
) == l
) {
935 return (wcscpy(numbuf
, p
));
939 * Return pointer to node with concatenation of operands of CONCAT node.
940 * In the interest of speed, a left recursive tree of CONCAT nodes
941 * is handled with a single malloc. The accumulated lengths of the
942 * right operands are passed down recursive invocations of this
943 * routine, which allocates a large enough string when the left
944 * operand is not a CONCAT node.
947 exprconcat(NODE
*np
, int len
)
949 /* we KNOW (np->n_type==CONCAT) */
950 register NODE
*lnp
= np
->n_left
;
951 register NODE
*rnp
= np
->n_right
;
956 wchar_t rnumbuf
[NUMSIZE
];
958 if (isleaf(rnp
->n_flags
) && rnp
->n_type
== PARM
)
960 if (isstring(rnp
->n_flags
)) {
962 rlen
= rnp
->n_strlen
;
964 rlen
= wcslen((wchar_t *)(rsp
= exprstring(rnp
)));
965 if (rsp
== numbuf
) { /* static, so save a copy */
966 (void) memcpy(rnumbuf
, (wchar_t *)rsp
,
967 (rlen
+1) * sizeof (wchar_t));
971 if (lnp
->n_type
== CONCAT
) {
972 lnp
= exprconcat(lnp
, len
);
974 llen
= lnp
->n_strlen
;
978 if (isleaf(lnp
->n_flags
) && lnp
->n_type
== PARM
)
980 if (isstring(lnp
->n_flags
)) {
982 llen
= lnp
->n_strlen
;
984 llen
= wcslen((wchar_t *)(lsp
= exprstring(lnp
)));
985 cp
= emalloc((llen
+len
+1) * sizeof (wchar_t));
986 (void) memcpy(cp
, (wchar_t *)lsp
, llen
* sizeof (wchar_t));
987 lnp
= stringnode(cp
, FNOALLOC
, llen
);
989 (void) memcpy(cp
+llen
, (wchar_t *)rsp
, (rlen
+1) * sizeof (wchar_t));
990 lnp
->n_strlen
+= rlen
;
995 * Reduce an expression to a terminal node.
1000 register wchar_t *cp
;
1005 register wchar_t *fname
;
1006 register wchar_t *aname
;
1009 * a var or constant is a leaf-node (no further reduction required)
1010 * so return immediately.
1012 if ((t
= np
->n_type
) == VAR
|| t
== CONSTANT
)
1015 * If it's a parameter then it is probably a leaf node but it
1016 * might be an array so we check.. If it is an array, then signal
1017 * an error as an array by itself cannot be used in this context.
1020 if ((np
= np
->n_next
)->n_type
== ARRAY
)
1021 awkerr(badarray
, np
->n_name
);
1025 * All the rest are non-leaf nodes.
1030 return (userfunc(np
));
1033 return (rfield(exprint(np
->n_left
)));
1041 /* initially formal var name and array key name are the same */
1042 fname
= aname
= tnp
->n_name
;
1043 if (tnp
->n_type
== PARM
) {
1046 if (!(tnp
->n_flags
& FLARRAY
)) {
1049 aname
= tnp
->n_name
;
1051 if (tnp
->n_type
!= ARRAY
) {
1052 if (!isstring(tnp
->n_flags
) || tnp
->n_string
!= _null
)
1053 awkerr(notarray
, fname
);
1055 /* promotion to array */
1057 if (tnp
->n_alink
!= NNULL
) {
1059 if (!(tnp
->n_flags
& FLARRAY
))
1061 aname
= tnp
->n_name
;
1064 if (tnp
->n_flags
& FLARRAY
)
1069 if (tnp
== varSYMTAB
) {
1070 if (np
== NNULL
|| np
->n_type
== COMMA
)
1072 "SYMTAB must have exactly one index"));
1073 np
= vlook(exprstring(np
));
1076 cp
= makeindex(np
, aname
, tag
);
1077 if (temp
== INDEX
) {
1079 if (!(np
->n_flags
& FINARRAY
)) {
1080 np
->n_alink
= tnp
->n_alink
;
1082 np
->n_flags
|= FINARRAY
;
1085 np
= vlookup(cp
, 1) == NNULL
? const0
: const1
;
1092 np
= exprconcat(np
, 0);
1097 return (intnode(exprtest(np
->n_left
) == 0 ? (INT
)1 : (INT
)0));
1100 return ((exprtest(np
->n_left
) != 0 &&
1101 exprtest(np
->n_right
) != 0) ? const1
: const0
);
1104 return ((exprtest(np
->n_left
) != 0 ||
1105 exprtest(np
->n_right
) != 0) ? const1
: const0
);
1112 * evaluate expressions in proper order before
1114 * Can't guarantee that compiler will do this
1115 * correctly for us if we put them inline.
1117 f1
= (double)exprreal(np
->n_left
);
1118 f2
= (double)exprreal(np
->n_right
);
1119 return (realnode((REAL
)pow(f1
, f2
)));
1123 if (np
->n_right
->n_type
!= COLON
)
1124 awkerr(interr
, "?:");
1125 if (exprtest(np
->n_left
))
1126 np
= np
->n_right
->n_left
; else
1127 np
= np
->n_right
->n_right
;
1128 return (exprreduce(np
));
1136 return (comparison(np
));
1143 return (arithmetic(np
));
1146 inc_oper
->n_type
= SUB
;
1149 inc_oper
->n_type
= ADD
;
1151 if ((np
= np
->n_left
)->n_type
== INDEX
)
1152 np
= exprreduce(np
);
1153 if (np
->n_flags
& FREAL
)
1154 tnp
= realnode(np
->n_real
);
1156 tnp
= intnode(exprint(np
));
1157 inc_oper
->n_left
= np
;
1158 (void) assign(np
, inc_oper
);
1162 inc_oper
->n_type
= SUB
;
1165 inc_oper
->n_type
= ADD
;
1167 if ((np
= np
->n_left
)->n_type
== INDEX
)
1168 np
= exprreduce(np
);
1169 inc_oper
->n_left
= np
;
1170 return (assign(np
, inc_oper
));
1173 asn_oper
->n_type
= ADD
;
1176 asn_oper
->n_type
= SUB
;
1179 asn_oper
->n_type
= MUL
;
1182 asn_oper
->n_type
= DIV
;
1185 asn_oper
->n_type
= REM
;
1188 asn_oper
->n_type
= EXP
;
1190 asn_oper
->n_right
= np
->n_right
;
1191 if ((np
= np
->n_left
)->n_type
== INDEX
)
1192 np
= exprreduce(np
);
1193 asn_oper
->n_left
= np
;
1194 return (assign(np
, asn_oper
));
1198 return (f_getline(np
));
1201 return ((*np
->n_left
->n_function
)(np
->n_right
));
1204 if (regmatch(np
->n_regexp
, linebuf
) == REG_OK
)
1209 cp
= exprstring(np
->n_left
);
1210 if (regmatch(getregexp(np
->n_right
), cp
) == REG_OK
)
1215 cp
= exprstring(np
->n_left
);
1216 if (regmatch(getregexp(np
->n_right
), cp
) != REG_OK
)
1221 return (assign(np
->n_left
, np
->n_right
));
1224 awkerr(badarray
, np
->n_name
);
1227 awkerr(varnotfunc
, np
->n_name
);
1230 awkerr(gettext("panic: exprreduce(%d)"), t
);
1237 * Do arithmetic operators.
1240 arithmetic(NODE
*np
)
1242 register NODE
*left
, *right
;
1244 register INT i1
, i2
;
1245 register INT iresult
;
1246 register REAL r1
, r2
;
1248 left
= exprreduce(np
->n_left
);
1249 if (isreal(left
->n_flags
) ||
1250 (isstring(left
->n_flags
) && (type_of(left
)&FVREAL
))) {
1252 r1
= exprreal(left
);
1253 r2
= exprreal(np
->n_right
);
1256 right
= exprreduce(np
->n_right
);
1257 if (isreal(right
->n_flags
) ||
1258 (isstring(right
->n_flags
) && (type_of(right
)&FVREAL
))) {
1262 r2
= exprreal(right
);
1265 i2
= exprint(right
);
1269 switch (np
->n_type
) {
1279 * Strategically placed between ADD and SUB
1280 * so "jo" branches will reach on 80*86
1321 double fmod(double x
, double y
);
1330 return (type
== FINT
? intnode(iresult
) : realnode(r1
));
1334 * Do comparison operators.
1337 comparison(NODE
*np
)
1339 register NODE
*left
, *right
;
1342 register REAL r1
, r2
;
1343 register INT i1
, i2
;
1346 if (isleaf(left
->n_flags
)) {
1347 if (left
->n_type
== PARM
)
1348 left
= left
->n_next
;
1350 left
= exprreduce(left
);
1352 right
= np
->n_right
;
1353 if (isleaf(right
->n_flags
)) {
1354 if (right
->n_type
== PARM
)
1355 right
= right
->n_next
;
1358 right
= exprreduce(right
);
1361 tr
= right
->n_flags
;
1363 * Posix mandates semantics for the comparison operators that
1364 * are incompatible with traditional AWK behaviour. If the following
1365 * define is true then awk will use the traditional behaviour.
1366 * if it's false, then AWK will use the POSIX-mandated behaviour.
1368 #define TRADITIONAL 0
1370 if (!isnumber(tl
) || !isnumber(tr
)) {
1371 cmp
= wcscoll((wchar_t *)exprstring(left
),
1372 (wchar_t *)exprstring(right
));
1373 } else if (isreal(tl
) || isreal(tr
)) {
1374 r1
= exprreal(left
);
1375 r2
= exprreal(right
);
1384 i2
= exprint(right
);
1393 if (!isnumber(tl
) && !isnumber(tr
)) {
1395 cmp
= wcscoll((wchar_t *)exprstring(left
),
1396 (wchar_t *)exprstring(right
));
1401 tr
= type_of(right
);
1402 if (!isnumber(tl
) || !isnumber(tr
))
1404 if (isreal(tl
) || isreal(tr
)) {
1405 r1
= exprreal(left
);
1406 r2
= exprreal(right
);
1415 i2
= exprint(right
);
1425 switch (np
->n_type
) {
1427 return (cmp
== 0 ? const1
: const0
);
1430 return (cmp
!= 0 ? const1
: const0
);
1433 return (cmp
>= 0 ? const1
: const0
);
1436 return (cmp
<= 0 ? const1
: const0
);
1439 return (cmp
> 0 ? const1
: const0
);
1442 return (cmp
< 0 ? const1
: const0
);
1445 awkerr(interr
, "comparison");
1452 * Return the type of a constant that is a string.
1453 * The node must be a FSTRING type and the return value
1454 * will possibly have FVINT or FVREAL or'ed in.
1464 int digitsaftere
= 0;
1466 cp
= (wchar_t *)np
->n_string
;
1468 return (FSTRING
|FVINT
);
1469 while (iswspace(*cp
))
1471 if (*cp
== '-' || *cp
== '+')
1473 while (*cp
!= '\0') {
1492 if (seene
|| !somedigits
)
1499 if (seensign
|| !seene
|| digitsaftere
)
1505 if (*cp
== radixpoint
) {
1506 if (seenradix
|| seene
|| (!somedigits
&&
1515 if (somedigits
== 0)
1517 if (somedigits
>= MAXDIGINT
|| seenradix
|| seene
) {
1518 if (seensign
&& !digitsaftere
)
1521 return (FSTRING
|FVREAL
);
1523 return (FSTRING
|FVINT
);
1527 * Return a field rvalue.
1532 register wchar_t *cp
;
1535 return (stringnode(linebuf
, FSTATIC
|FSENSE
, lbuflen
));
1538 if (fieldno
> nfield
|| fieldno
< 0)
1539 return (stringnode(_null
, FSTATIC
, 0));
1540 cp
= fields
[fieldno
-1];
1541 return (stringnode(cp
, FSTATIC
|FSENSE
, wcslen(cp
)));
1545 * Split linebuf into fields. Done only once
1546 * per input record (maximum).
1551 register wchar_t *ip
, *op
;
1555 if (fieldbuf
== NULL
)
1556 fieldbuf
= emalloc(NLINE
* sizeof (wchar_t));
1560 while ((ip
= (*awkfield
)(&ep
)) != NULL
) {
1561 fields
[fcount
++] = op
;
1562 if (fcount
> NFIELD
)
1563 awkerr(tmfld
, NFIELD
);
1565 (void) memcpy(op
, ip
, n
* sizeof (wchar_t));
1569 if (varNF
->n_flags
& FINT
)
1570 varNF
->n_int
= fcount
;
1572 constant
->n_int
= fcount
;
1573 (void) nassign(varNF
, constant
);
1580 * Assign to a field as an lvalue.
1581 * Return the unevaluated node as one doesn't always need it
1582 * evaluated in an assignment.
1585 lfield(INT fieldno
, NODE
*np
)
1587 register wchar_t *cp
;
1588 register wchar_t *op
;
1589 register wchar_t *sep
;
1591 register wchar_t *newval
;
1592 register int seplen
;
1593 register int newlen
;
1595 newlen
= wcslen(newval
= (wchar_t *)exprstring(np
));
1598 (void) memcpy(linebuf
, newval
, (newlen
+1) * sizeof (wchar_t));
1602 seplen
= wcslen(sep
= (wchar_t *)exprstring(varOFS
));
1605 if (--fieldno
< nfield
&&
1606 (newlen
<= wcslen(fields
[fieldno
]))) {
1607 (void) memcpy(fields
[fieldno
], newval
,
1608 (newlen
+1) * sizeof (wchar_t));
1610 register wchar_t *buf
;
1613 fieldbuf
= emalloc(NLINE
* sizeof (wchar_t));
1614 if (fieldno
>= nfield
) {
1615 if (fieldno
>= NFIELD
)
1616 awkerr(tmfld
, NFIELD
);
1617 while (nfield
< fieldno
)
1618 fields
[nfield
++] = _null
;
1621 fields
[fieldno
] = newval
;
1623 for (i
= 0; i
< nfield
; i
++) {
1624 newlen
= wcslen(cp
= fields
[i
])+1;
1626 if (op
+newlen
>= fieldbuf
+NLINE
)
1627 awkerr(toolong
, NLINE
);
1628 (void) memcpy(op
, cp
,
1629 newlen
* sizeof (wchar_t));
1639 while (i
< nfield
) {
1640 newlen
= wcslen(cp
= fields
[i
++]);
1641 (void) memcpy(op
, cp
, newlen
* sizeof (wchar_t));
1644 (void) memcpy(op
, sep
,
1645 seplen
* sizeof (wchar_t));
1648 if (op
>= &linebuf
[NLINE
])
1649 awkerr(toolong
, NLINE
);
1652 lbuflen
= op
-linebuf
;
1653 if (varNF
->n_flags
& FINT
)
1654 varNF
->n_int
= nfield
;
1656 constant
->n_int
= nfield
;
1657 (void) nassign(varNF
, constant
);
1664 * Do a user function.
1665 * Each formal parameter must:
1666 * have the actual parameter assigned to it (call by value),
1667 * have a pointer to an array put into it (call by reference),
1668 * and be made undefined (extra formal parameters)
1673 register NODE
*temp
;
1676 if ((fnp
= np
->n_left
) == NNULL
)
1677 awkerr(gettext("impossible function call"));
1678 if (fnp
->n_type
!= UFUNC
)
1679 awkerr(varnotfunc
, fnp
->n_name
);
1682 if (slevel
>= NRECUR
)
1683 awkerr(gettext("function \"%S\" nesting level > %u"),
1684 fnp
->n_name
, NRECUR
);
1687 awkerr(gettext("function \"%s\" nesting level too deep"),
1693 register NODE
*formal
;
1694 register NODE
*actual
;
1695 NODE
*formlist
, *actlist
, *templist
, *temptail
;
1697 templist
= temptail
= NNULL
;
1698 actlist
= np
->n_right
;
1699 formlist
= fnp
->n_left
;
1701 * pass through formal list, setting up a list
1702 * (on templist) containing temps for the values
1704 * If the actual list runs out before the formal
1705 * list, assign 'constundef' as the value
1707 while ((formal
= getlist(&formlist
)) != NNULL
) {
1708 register NODE
*array
;
1710 register size_t len
;
1711 register int scope_tag
;
1713 actual
= getlist(&actlist
);
1714 if (actual
== NNULL
) {
1715 actual
= constundef
;
1716 scope_tag
= slevel
+1;
1720 switch (actual
->n_type
) {
1727 array
= actual
= actual
->n_next
;
1729 scope_tag
= actual
->n_scope
;
1730 if (!(actual
->n_flags
& FLARRAY
))
1731 array
= actual
->n_alink
;
1738 temp
= emptynode(t
, len
= wcslen(formal
->n_name
));
1739 (void) memcpy(temp
->n_name
, formal
->n_name
,
1740 (len
+1) * sizeof (wchar_t));
1741 temp
->n_flags
= FSTRING
|FVINT
;
1742 temp
->n_string
= _null
;
1745 (void) assign(temp
, actual
);
1747 temp
->n_flags
|= FLARRAY
;
1748 temp
->n_scope
= scope_tag
;
1750 * link to actual parameter in case of promotion to
1753 if (actual
!= constundef
)
1754 temp
->n_alink
= actual
;
1756 * Build the templist
1758 if (templist
!= NNULL
) {
1759 temptail
->n_next
= temp
;
1762 templist
= temptail
= temp
;
1763 temp
->n_next
= NNULL
;
1764 if (actual
->n_type
== CONSTANT
)
1765 temp
->n_alink
= temp
;
1767 temp
->n_alink
= array
;
1770 * Bind results of the evaluation of actuals to formals.
1772 formlist
= fnp
->n_left
;
1773 while (templist
!= NNULL
) {
1775 templist
= temp
->n_next
;
1776 formal
= getlist(&formlist
);
1777 temp
->n_next
= formal
->n_next
;
1778 formal
->n_next
= temp
;
1790 register NODE
*savenode
= curnode
;
1793 if (action(fnp
->n_right
) == RETURN
)
1799 register NODE
*formal
;
1802 formlist
= fnp
->n_left
;
1803 while ((formal
= getlist(&formlist
)) != NNULL
) {
1804 temp
= formal
->n_next
;
1805 formal
->n_next
= temp
->n_next
;
1806 /* if node is a local array, free the elements */
1807 if (temp
->n_type
== ARRAY
&& (temp
->n_scope
== slevel
))
1817 * Get the regular expression from an expression tree.
1822 if (np
->n_type
== RE
)
1823 return (np
->n_regexp
);
1824 np
= renode((wchar_t *)exprstring(np
));
1825 return (np
->n_regexp
);
1829 * Get the next element from a list.
1836 if ((np
= *npp
) == NNULL
)
1838 if (np
->n_type
== COMMA
) {
1840 return (np
->n_left
);
1856 test
= exprtest(np
->n_left
);
1858 if (xp
->n_type
!= ELSE
)
1859 awkerr(interr
, "if/else");
1864 return (action(xp
));
1868 * while and do{}while statements.
1873 register int act
= 0;
1875 if (np
->n_type
== DO
)
1878 if (exprtest(np
->n_left
) == 0)
1881 if ((act
= action(np
->n_right
)) != 0) {
1903 register NODE
*testnp
, *incnp
, *initnp
;
1904 register int act
= 0;
1908 initnp
= getlist(&listp
);
1909 testnp
= getlist(&listp
);
1910 incnp
= getlist(&listp
);
1911 if (initnp
!= NNULL
)
1912 (void) exprreduce(initnp
);
1914 if (exprtest(testnp
) == 0)
1916 if ((act
= action(np
->n_right
)) != 0) {
1930 (void) exprreduce(incnp
);
1936 * for variable in array statement.
1941 register NODE
*left
;
1942 register int act
= 0;
1944 register NODE
**nnp
;
1945 register NODE
*statement
;
1946 register int issymtab
= 0;
1952 statement
= np
->n_right
;
1953 if (left
->n_type
!= IN
)
1954 awkerr(interr
, "for (var in array)");
1955 if ((var
= left
->n_left
)->n_type
== PARM
)
1958 if (np
->n_type
== PARM
) {
1960 if (!(np
->n_flags
& FLARRAY
))
1963 if (np
== varSYMTAB
) {
1969 * At this point if the node is not actually an array
1970 * check to see if it has already been established as
1971 * a scalar. If it is a scalar then flag an error. If
1972 * not then promote the object to an array type.
1974 if (np
->n_type
!= ARRAY
) {
1975 if (!isstring(np
->n_flags
) || np
->n_string
!= _null
)
1976 awkerr(notarray
, np
->n_name
);
1978 /* promotion to array */
1980 if (np
->n_alink
!= NNULL
)
1981 if (!(np
->n_flags
& FLARRAY
))
1986 * Set up a pointer to the first node in the array list.
1987 * Save this pointer on the delete stack. This information
1988 * is used by the delete function to advance any pointers
1989 * that might be pointing at a node which has been deleted.
1990 * See the delsymtab() function for more information. Note
1991 * that if the a_link field is nil, then just return 0 since
1992 * this array has no elements yet.
1994 if ((*(nnp
= next_forin
) = np
->n_alink
) == 0)
1996 if (++next_forin
> &forindex
[NFORINLOOP
])
1997 awkerr(toodeep
, NFORINLOOP
);
1999 * array elements have names of the form
2000 * <name>]<index> (global arrays)
2002 * <name>[<scope>]<index> (local arrays)
2003 * We need to know the offset of the index portion of the
2004 * name string in order to place it in the index variable so
2005 * we look for the ']'. This is calculated here and then
2008 for (alen
= 0; (*nnp
)->n_name
[alen
++] != ']'; )
2009 if ((*nnp
)->n_name
[alen
] == '\0')
2010 awkerr(interr
, "for: invalid array");
2014 if ((left
= symwalk(&nbuck
, &np
)) == NNULL
)
2016 index
= left
->n_name
;
2018 if ((np
= *nnp
) == NNULL
)
2020 index
= np
->n_name
+alen
;
2023 strassign(var
, index
, FSTATIC
, wcslen(index
));
2024 if ((act
= action(statement
)) != 0) {
2042 * Walk the symbol table using the same algorithm as arraynode.
2045 symwalk(int *buckp
, NODE
**npp
)
2051 while (np
== NNULL
) {
2052 if (*buckp
>= NBUCKET
)
2053 return (*npp
= NNULL
);
2054 np
= symtab
[(*buckp
)++];
2056 if (np
->n_type
== VAR
&&
2057 (!isstring(np
->n_flags
) || np
->n_string
!= _null
)) {
2067 * Test the result of an expression.
2076 if (freelist
!= NNULL
)
2078 np
= exprreduce(np
);
2079 if (isint(t
= np
->n_flags
)) {
2081 return (exprint(np
) != 0);
2082 return (np
->n_int
!= 0);
2087 rval
= isstring(t
) ? exprreal(np
) : np
->n_real
;
2088 return (rval
!= 0.0);
2090 return (*(wchar_t *)exprstring(np
) != '\0');
2094 * Return malloc'ed space that holds the given name "[" scope "]" index ...
2095 * concatenated string.
2096 * The node (np) is the list of indices and 'array' is the array name.
2099 makeindex(NODE
*np
, wchar_t *array
, int tag
)
2101 static wchar_t tags
[sizeof (int)];
2102 static wchar_t tag_chars
[] = M_MB_L("0123456789ABCDEF");
2103 register wchar_t *cp
;
2104 register NODE
*index
;
2107 register wchar_t *indstr
;
2108 register wchar_t *sep
;
2109 register int seplen
;
2110 register int taglen
;
2114 * calculate and create the tag string
2116 for (taglen
= 0; tag
; tag
>>= 4)
2117 tags
[taglen
++] = tag_chars
[tag
& 0xf];
2119 * Special (normal) case: only one index.
2121 if (np
->n_type
!= COMMA
) {
2125 if (isleaf(np
->n_flags
) && np
->n_type
== PARM
)
2127 if (isstring(np
->n_flags
)) {
2128 indstr
= np
->n_string
;
2131 indstr
= exprstring(np
);
2132 len
= wcslen(indstr
);
2134 i
= (n
= wcslen(array
)) + len
+ 3 + taglen
;
2138 ocp
= emalloc(i
* sizeof (wchar_t));
2139 (void) memcpy(ocp
, array
, n
* sizeof (wchar_t));
2144 *cp
++ = tags
[--taglen
];
2147 (void) memcpy(cp
, indstr
, (len
+1) * sizeof (wchar_t));
2152 seplen
= wcslen(sep
= (wchar_t *)exprstring(varSUBSEP
));
2153 while ((index
= getlist(&np
)) != NNULL
) {
2154 indstr
= exprstring(index
);
2155 len
= wcslen(indstr
);
2157 cp
= emalloc(sizeof (wchar_t) * ((n
= wcslen(array
)) +
2159 (void) memcpy(cp
, array
, n
* sizeof (wchar_t));
2163 cp
[n
++] = tags
[--taglen
];
2167 cp
= erealloc(cp
, (n
+len
+seplen
+1) * sizeof (wchar_t));
2168 (void) memcpy(cp
+n
, sep
, seplen
* sizeof (wchar_t));
2171 (void) memcpy(cp
+n
, indstr
, (len
+1) * sizeof (wchar_t));
2179 * Promote a node to an array. In the simplest case, just set the
2180 * node type field to ARRAY. The more complicated case involves walking
2181 * a list of variables that haven't been determined yet as scalar or array.
2182 * This routine plays with the pointers to avoid recursion.
2187 register NODE
*prev
= NNULL
;
2188 register NODE
*next
;
2191 * walk down the variable chain, reversing the pointers and
2192 * setting each node to type array.
2194 while ((n
->n_flags
& FLARRAY
) && (n
->n_alink
!= n
)) {
2203 * If the final entity on the chain is a local variable, then
2204 * reset it's alink field to NNULL - normally it points back
2205 * to itself - this is used in other parts of the code to
2206 * reduce the number of conditionals when handling locals.
2209 if (n
->n_flags
& FLARRAY
)
2213 * Now walk back up the list setting the alink to point to
2214 * the last entry in the chain and clear the 'local array'
2217 while (prev
!= NNULL
) {
2218 prev
->n_flags
&= ~FLARRAY
;
2219 next
= prev
->n_alink
;