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
32 #pragma ident "%Z%%M% %I% %E% SMI"
37 static int dohash(wchar_t *name
);
38 static NODE
*arithmetic(NODE
*np
);
39 static NODE
*comparison(NODE
*np
);
40 static int type_of(NODE
*np
);
41 static NODE
*lfield(INT fieldno
, NODE
*value
);
42 static NODE
*rfield(INT fieldno
);
43 static NODE
*userfunc(NODE
*np
);
44 static wchar_t *lltoa(long long l
);
45 static NODE
*exprconcat(NODE
*np
, int len
);
46 static int s_if(NODE
*np
);
47 static int s_while(NODE
*np
);
48 static int s_for(NODE
*np
);
49 static int s_forin(NODE
*np
);
50 static void setrefield(NODE
*value
);
51 static void freetemps(void);
52 static int action(NODE
*np
);
53 static wchar_t *makeindex(NODE
*np
, wchar_t *array
, int tag
);
54 static int exprtest(NODE
*np
);
56 #define regmatch(rp, s) REGWEXEC(rp, s, 0, (REGWMATCH_T*)NULL, 0)
59 * This code allows for integers to be stored in longs (type INT) and
60 * only promoted to double precision floating point numbers (type REAL)
61 * when overflow occurs during +, -, or * operations. This is very
62 * non-portable if you desire such a speed optimisation. You may wish
63 * to put something here for your system. This "something" would likely
64 * include either an assembler "jump on overflow" instruction or a
65 * method to get traps on overflows from the hardware.
67 * This portable method works for ones and twos complement integer
68 * representations (which is, realistically) almost all machines.
71 #define addoverflow() asm jo overflow
72 #define suboverflow() asm jo overflow
75 * These are portable to two's complement integer machines
77 #define addoverflow() if ((i1^i2) >= 0 && (iresult^i1) < 0) goto overflow
78 #define suboverflow() if ((i1^i2) < 0 && (iresult^i2) >= 0) goto overflow
80 #define muloverflow() if (((short)i1 != i1 || (short)i2 != i2) && \
81 ((i2 != 0 && iresult/i2 != i1) || \
82 (i1 == LONG_MIN && i2 == -1))) goto overflow
84 static char notarray
[] = "scalar \"%s\" cannot be used as array";
85 static char badarray
[] = "array \"%s\" cannot be used as a scalar";
86 static char varnotfunc
[] = "variable \"%s\" cannot be used as a function";
87 static char tmfld
[] = "Too many fields (LIMIT: %d)";
88 static char toolong
[] = "Record too long (LIMIT: %d bytes)";
89 static char divzero
[] = "division (/ or %%) by zero";
90 static char toodeep
[] = "too deeply nested for in loop (LIMIT: %d)";
92 static wchar_t numbuf
[NUMSIZE
]; /* Used to convert INTs to strings */
93 static wchar_t *fields
[NFIELD
]; /* Cache of pointers into fieldbuf */
94 static wchar_t *fieldbuf
; /* '\0' separated copy of linebuf */
95 static NODE nodes
[NSNODE
]; /* Cache of quick access nodes */
96 static NODE
*fnodep
= &nodes
[0];
98 static wchar_t indexbuf
[NINDEXBUF
]; /* Used for simple array indices */
99 static int concflag
; /* In CONCAT operation (no frees) */
100 static NODE
*retval
; /* Last return value of a function */
103 * The following stack is used to store the next pointers for all nested
104 * for-in loops. This needs to be global so that delete can check to see
105 * if it is deleting the next node to be used by a loop.
107 #define NFORINLOOP 10
108 static NODE
* forindex
[NFORINLOOP
];
109 static NODE
** next_forin
= forindex
;
112 * Assign a string directly to a NODE without creating an intermediate
113 * NODE. This can handle either FALLOC, FSTATIC, FNOALLOC or FSENSE for
114 * "flags" argument. Also the NODE "np" must be reduced to an lvalue
115 * (PARM nodes are not acceptable).
118 strassign(NODE
*np
, STRING string
, int flags
, size_t length
)
120 if (np
->n_type
== FUNC
)
121 awkerr(gettext("attempt to redefine builtin function"));
122 else if (np
->n_type
== GETLINE
|| np
->n_type
== KEYWORD
)
123 awkerr(gettext("inadmissible use of reserved keyword"));
124 if (np
->n_flags
& FSPECIAL
) {
125 (void) nassign(np
, stringnode(string
, flags
, length
));
128 if (isastring(np
->n_flags
))
129 free((wchar_t *)np
->n_string
);
130 np
->n_strlen
= length
++;
131 if (flags
& FALLOC
) {
132 length
*= sizeof (wchar_t);
133 np
->n_string
= (STRING
) emalloc(length
);
134 (void) memcpy((void *)np
->n_string
, string
, length
);
136 np
->n_string
= string
;
137 if (flags
& FNOALLOC
) {
142 np
->n_flags
&= FSAVE
;
143 if (flags
& FSENSE
) {
145 flags
|= type_of(np
);
148 np
->n_flags
|= flags
;
152 * Assign to a variable node.
153 * LHS must be a VAR type and RHS must be reduced by now.
154 * To speed certain operations up, check for
155 * certain things here and do special assignments.
158 nassign(NODE
*np
, NODE
*value
)
160 register wchar_t *cp
;
163 /* short circuit assignment of a node to itself */
166 if (np
->n_flags
& FSPECIAL
) {
167 if (np
== varRS
|| np
== varFS
) {
168 if (isastring(np
->n_flags
))
169 free((void *)np
->n_string
);
170 len
= sizeof (wchar_t) * ((np
->n_strlen
=
171 wcslen(cp
= exprstring(value
)))+1);
172 np
->n_string
= emalloc(len
);
173 (void) memcpy((wchar_t *)np
->n_string
, cp
, len
);
174 np
->n_flags
= FALLOC
|FSTRING
|FSPECIAL
;
176 if (np
->n_string
[0] == '\n')
177 awkrecord
= defrecord
;
178 else if (np
->n_string
[0] == '\0')
179 awkrecord
= multirecord
;
181 awkrecord
= charrecord
;
182 } else if (np
== varFS
) {
183 if (resep
!= (REGEXP
)NULL
) {
185 resep
= (REGEXP
)NULL
;
187 if (wcslen((wchar_t *)np
->n_string
) > 1)
189 else if (np
->n_string
[0] == ' ')
190 awkfield
= whitefield
;
192 awkfield
= blackfield
;
197 if (isastring(np
->n_flags
))
198 free((wchar_t *)np
->n_string
);
199 if (isstring(value
->n_flags
)) {
200 np
->n_strlen
= value
->n_strlen
;
201 if (value
->n_flags
&FALLOC
|| value
->n_string
!= _null
) {
202 len
= (np
->n_strlen
+1) * sizeof (wchar_t);
203 np
->n_string
= emalloc(len
);
204 (void) memcpy(np
->n_string
, value
->n_string
, len
);
205 np
->n_flags
&= FSAVE
;
206 np
->n_flags
|= value
->n_flags
& ~FSAVE
;
207 np
->n_flags
|= FALLOC
;
210 np
->n_string
= value
->n_string
;
211 } else if (value
->n_flags
& FINT
)
212 np
->n_int
= value
->n_int
;
214 np
->n_real
= value
->n_real
;
215 np
->n_flags
&= FSAVE
;
216 np
->n_flags
|= value
->n_flags
& ~FSAVE
;
221 * Set regular expression FS value.
229 if ((n
= REGWCOMP(&re
, np
->n_string
)) != REG_OK
) {
230 REGWERROR(n
, &re
, (char *)linebuf
, sizeof (linebuf
));
231 awkerr(gettext("syntax error \"%s\" in /%s/\n"),
232 (char *)linebuf
, np
->n_string
);
239 * Assign to an l-value node.
242 assign(NODE
*left
, NODE
*right
)
244 if (isleaf(right
->n_flags
)) {
245 if (right
->n_type
== PARM
)
246 right
= right
->n_next
;
248 right
= exprreduce(right
);
250 switch (left
->n_type
) {
252 left
= exprreduce(left
);
255 return (nassign(left
, right
));
259 * If it's a parameter then link to the actual value node and
260 * do the checks again.
266 return (lfield(exprint(left
->n_left
), right
));
270 awkerr(gettext("cannot assign to function \"%s\""),
274 awkerr(gettext("lvalue required in assignment"));
281 * Compiled tree non-terminal node.
284 node(int type
, NODE
*left
, NODE
*right
)
288 np
= emptynode(type
, 0);
291 np
->n_lineno
= lineno
;
296 * Create an integer node.
303 np
= emptynode(CONSTANT
, 0);
304 np
->n_flags
= FINT
|FVINT
;
310 * Create a real number node.
317 np
= emptynode(CONSTANT
, 0);
318 np
->n_flags
= FREAL
|FVREAL
;
324 * Make a node for a string.
327 stringnode(STRING s
, int how
, size_t length
)
331 np
= emptynode(CONSTANT
, 0);
332 np
->n_strlen
= length
;
334 np
->n_string
= emalloc(length
= (length
+1) * sizeof (wchar_t));
335 (void) memcpy(np
->n_string
, s
, length
);
338 if (how
& FNOALLOC
) {
344 np
->n_flags
= type_of(np
);
347 np
->n_flags
= FSTRING
;
353 * Save a copy of a string.
356 strsave(wchar_t *old
)
361 new = (STRING
)emalloc(len
= (wcslen(old
)+1) * sizeof (wchar_t));
362 (void) memcpy(new, old
, len
);
367 * Allocate an empty node of given type.
368 * String space for the node is given by `length'.
371 emptynode(int type
, size_t length
)
375 if (length
== 0 && running
&& fnodep
< &nodes
[NSNODE
]) {
378 np
= (NODE
*)emalloc(sizeof (NODE
) +
379 (length
* sizeof (wchar_t)));
380 if (running
&& type
!= VAR
&& type
!= ARRAY
) {
381 np
->n_next
= freelist
;
385 np
->n_flags
= FNONTOK
;
398 if (isastring(np
->n_flags
))
399 free((wchar_t *)np
->n_string
);
400 else if (np
->n_type
== RE
) {
401 REGWFREE(np
->n_regexp
);
407 * Install a keyword of given `type'.
410 kinstall(LOCCHARP name
, int type
)
416 np
= emptynode(KEYWORD
, l
);
417 np
->n_keywtype
= type
;
418 (void) memcpy(np
->n_name
, name
, (l
+1) * sizeof (wchar_t));
423 * Install built-in function.
426 finstall(LOCCHARP name
, FUNCTION func
, int type
)
432 np
= emptynode(type
, l
);
433 np
->n_function
= func
;
434 (void) memcpy(np
->n_name
, name
, (l
+1) * sizeof (wchar_t));
440 * Lookup an identifier.
441 * nocreate contains the following flag values:
442 * 1 if no creation of a new NODE,
443 * 0 if ok to create new NODE
446 vlookup(wchar_t *name
, int nocreate
)
448 register ushort_t hash
;
451 np
= symtab
[hashbuck(hash
= dohash((wchar_t *)name
))];
452 while (np
!= NNULL
) {
453 if (np
->n_hash
== hash
&& wcscmp(name
, np
->n_name
) == 0)
460 np
= emptynode(VAR
, hash
= wcslen(name
));
461 np
->n_flags
= FSTRING
|FVINT
;
463 np
->n_string
= _null
;
464 (void) memcpy(np
->n_name
, name
,
465 (hash
+1) * sizeof (wchar_t));
472 * Add a symbol to the table.
479 np
->n_hash
= dohash((wchar_t *)np
->n_name
);
480 spp
= &symtab
[hashbuck(np
->n_hash
)];
486 * Delete the given node from the symbol table.
487 * If fflag is non-zero, also free the node space.
488 * This routine must also check the stack of forin loop pointers. If
489 * we are deleting the next item to be used, then the pointer must be
493 delsymtab(NODE
*np
, int fflag
)
496 register NODE
*prevp
;
497 register NODE
**sptr
;
504 h
= hashbuck(np
->n_hash
);
506 for (rnp
= symtab
[h
]; rnp
!= NNULL
; rnp
= rnp
->n_next
) {
509 * check all of the for-in loop pointers
510 * to see if any need to be advanced because
511 * this element is being deleted.
513 if (next_forin
!= forindex
) {
516 if (*--sptr
== rnp
) {
520 } while (sptr
!= forindex
);
523 symtab
[h
] = rnp
->n_next
; else
524 prevp
->n_next
= rnp
->n_next
;
537 dohash(wchar_t *name
)
539 register int hash
= 0;
541 while (*name
!= '\0')
547 * Top level executor for an awk programme.
548 * This will be passed: pattern, action or a list of these.
549 * The former function to evaluate a pattern has been
550 * subsumed into this function for speed.
554 * other expressions (including regular expressions)
568 while (wp
!= NNULL
) {
569 if (wp
->n_type
== COMMA
) {
576 if (np
->n_type
!= PACT
)
577 awkerr(interr
, "PACT");
579 * Save the parent node and evaluate the pattern.
580 * If it evaluates to false (0) just continue
581 * to the next pattern/action (PACT) pair.
588 } else if (phase
!= 0) {
589 if (np
->n_type
!= phase
)
591 } else if ((type
= np
->n_type
) == BEGIN
|| type
== END
) {
593 } else if (type
== COMMA
) {
595 * The grammar only allows expressions
596 * to be separated by the ',' operator
597 * for range patterns.
599 if (np
->n_flags
& FMATCH
) {
600 if (exprint(np
->n_right
) != 0)
601 np
->n_flags
&= ~FMATCH
;
602 } else if (exprint(np
->n_left
) != 0) {
603 if (exprint(np
->n_right
) == 0)
604 np
->n_flags
|= FMATCH
;
607 } else if (exprint(np
) == 0)
610 if (action(np
->n_right
)) {
615 if (freelist
!= NNULL
)
620 * Free all temporary nodes.
625 register NODE
*np
, *nnp
;
629 for (np
= &nodes
[0]; np
< fnodep
; np
++) {
630 if (isastring(np
->n_flags
)) {
631 free((wchar_t *)np
->n_string
);
632 } else if (np
->n_type
== RE
) {
633 REGWFREE(np
->n_regexp
);
637 for (np
= freelist
; np
!= NNULL
; np
= nnp
) {
645 * Do the given action.
646 * Actions are statements or expressions.
652 register int act
= 0;
655 while (wp
!= NNULL
) {
656 if (wp
->n_type
== COMMA
) {
663 if (freelist
!= NNULL
)
667 * Don't change order of these cases without
668 * changing order in awk.y declarations.
669 * The order is optimised.
671 switch (np
->n_type
) {
673 (void) assign(np
->n_left
, np
->n_right
);
685 if (np
->n_left
!= NNULL
)
686 act
= (int)exprint(np
->n_left
); else
693 awkerr(gettext("return outside of a function"));
694 np
= np
->n_left
!= NNULL
695 ? exprreduce(np
->n_left
)
697 retval
= emptynode(CONSTANT
, 0);
698 retval
->n_flags
= FINT
;
699 (void) nassign(retval
, np
);
710 if ((l
= np
->n_left
)->n_type
== PARM
) {
712 if (!(l
->n_flags
& FLARRAY
))
721 if ((np
= l
->n_left
)->n_type
== PARM
) {
723 if (!(np
->n_flags
& FLARRAY
))
727 * get pointer to the node for this array
728 * element using the hash key.
732 * now search linearly from the beginning of
733 * the list to find the element before the
734 * one being deleted. This must be done
735 * because arrays are singley-linked.
737 while (np
!= NNULL
) {
738 if (np
->n_alink
== l
) {
739 np
->n_alink
= l
->n_alink
;
748 if (isstring(l
->n_flags
) &&
749 l
->n_string
== _null
)
753 "may delete only array element or array"));
760 if ((act
= s_while(np
)) != 0)
765 if ((act
= s_for(np
)) != 0)
770 if ((act
= s_forin(np
)) != 0)
775 if ((act
= s_if(np
)) != 0)
780 (void) exprreduce(np
);
793 * Delete an entire array
802 while (nnp
!= NNULL
) {
810 * Return the INT value of an expression.
815 if (isleaf(np
->n_flags
)) {
816 if (np
->n_type
== PARM
)
821 switch (np
->n_type
) {
825 if (np
->n_flags
& FINT
)
827 if (np
->n_flags
& FREAL
)
828 return ((INT
)np
->n_real
);
829 return ((INT
)wcstoll(np
->n_string
, NULL
, 10));
832 awkerr(interr
, "exprint");
839 * Return a real number from an expression tree.
845 return ((REAL
)loopexit
);
846 if (isleaf(np
->n_flags
)) {
847 if (np
->n_type
== PARM
)
852 switch (np
->n_type
) {
856 if (np
->n_flags
& FREAL
)
858 if (np
->n_flags
& FINT
)
859 return ((REAL
)np
->n_int
);
860 return ((REAL
)wcstod((wchar_t *)np
->n_string
, (wchar_t **)0));
863 awkerr(interr
, "exprreal");
870 * Return a string from an expression tree.
875 if (isleaf(np
->n_flags
)) {
876 if (np
->n_type
== PARM
)
881 switch (np
->n_type
) {
885 if (isstring(np
->n_flags
))
886 return (np
->n_string
);
887 if (np
->n_flags
& FINT
)
888 return (STRING
)lltoa((long long)np
->n_int
);
891 (void) wsprintf(numbuf
,
892 (const char *) (tmp
= wcstombsdup(exprstring(varCONVFMT
))),
897 return ((STRING
)numbuf
);
900 awkerr(interr
, "exprstring");
907 * Convert number to string.
912 register wchar_t *p
= &numbuf
[NUMSIZE
];
915 static wchar_t zero
[] = M_MB_L("0");
921 neg
= 1, l
= -l
; else
923 if ((s
= (short)l
) == l
) {
936 return (wcscpy(numbuf
, p
));
940 * Return pointer to node with concatenation of operands of CONCAT node.
941 * In the interest of speed, a left recursive tree of CONCAT nodes
942 * is handled with a single malloc. The accumulated lengths of the
943 * right operands are passed down recursive invocations of this
944 * routine, which allocates a large enough string when the left
945 * operand is not a CONCAT node.
948 exprconcat(NODE
*np
, int len
)
950 /* we KNOW (np->n_type==CONCAT) */
951 register NODE
*lnp
= np
->n_left
;
952 register NODE
*rnp
= np
->n_right
;
957 wchar_t rnumbuf
[NUMSIZE
];
959 if (isleaf(rnp
->n_flags
) && rnp
->n_type
== PARM
)
961 if (isstring(rnp
->n_flags
)) {
963 rlen
= rnp
->n_strlen
;
965 rlen
= wcslen((wchar_t *)(rsp
= exprstring(rnp
)));
966 if (rsp
== numbuf
) { /* static, so save a copy */
967 (void) memcpy(rnumbuf
, (wchar_t *)rsp
,
968 (rlen
+1) * sizeof (wchar_t));
972 if (lnp
->n_type
== CONCAT
) {
973 lnp
= exprconcat(lnp
, len
);
975 llen
= lnp
->n_strlen
;
979 if (isleaf(lnp
->n_flags
) && lnp
->n_type
== PARM
)
981 if (isstring(lnp
->n_flags
)) {
983 llen
= lnp
->n_strlen
;
985 llen
= wcslen((wchar_t *)(lsp
= exprstring(lnp
)));
986 cp
= emalloc((llen
+len
+1) * sizeof (wchar_t));
987 (void) memcpy(cp
, (wchar_t *)lsp
, llen
* sizeof (wchar_t));
988 lnp
= stringnode(cp
, FNOALLOC
, llen
);
990 (void) memcpy(cp
+llen
, (wchar_t *)rsp
, (rlen
+1) * sizeof (wchar_t));
991 lnp
->n_strlen
+= rlen
;
996 * Reduce an expression to a terminal node.
1001 register wchar_t *cp
;
1006 register wchar_t *fname
;
1007 register wchar_t *aname
;
1010 * a var or constant is a leaf-node (no further reduction required)
1011 * so return immediately.
1013 if ((t
= np
->n_type
) == VAR
|| t
== CONSTANT
)
1016 * If it's a parameter then it is probably a leaf node but it
1017 * might be an array so we check.. If it is an array, then signal
1018 * an error as an array by itself cannot be used in this context.
1021 if ((np
= np
->n_next
)->n_type
== ARRAY
)
1022 awkerr(badarray
, np
->n_name
);
1026 * All the rest are non-leaf nodes.
1031 return (userfunc(np
));
1034 return (rfield(exprint(np
->n_left
)));
1042 /* initially formal var name and array key name are the same */
1043 fname
= aname
= tnp
->n_name
;
1044 if (tnp
->n_type
== PARM
) {
1047 if (!(tnp
->n_flags
& FLARRAY
)) {
1050 aname
= tnp
->n_name
;
1052 if (tnp
->n_type
!= ARRAY
) {
1053 if (!isstring(tnp
->n_flags
) || tnp
->n_string
!= _null
)
1054 awkerr(notarray
, fname
);
1056 /* promotion to array */
1058 if (tnp
->n_alink
!= NNULL
) {
1060 if (!(tnp
->n_flags
& FLARRAY
))
1062 aname
= tnp
->n_name
;
1065 if (tnp
->n_flags
& FLARRAY
)
1070 if (tnp
== varSYMTAB
) {
1071 if (np
== NNULL
|| np
->n_type
== COMMA
)
1073 "SYMTAB must have exactly one index"));
1074 np
= vlook(exprstring(np
));
1077 cp
= makeindex(np
, aname
, tag
);
1078 if (temp
== INDEX
) {
1080 if (!(np
->n_flags
& FINARRAY
)) {
1081 np
->n_alink
= tnp
->n_alink
;
1083 np
->n_flags
|= FINARRAY
;
1086 np
= vlookup(cp
, 1) == NNULL
? const0
: const1
;
1093 np
= exprconcat(np
, 0);
1098 return (intnode(exprtest(np
->n_left
) == 0 ? (INT
)1 : (INT
)0));
1101 return ((exprtest(np
->n_left
) != 0 &&
1102 exprtest(np
->n_right
) != 0) ? const1
: const0
);
1105 return ((exprtest(np
->n_left
) != 0 ||
1106 exprtest(np
->n_right
) != 0) ? const1
: const0
);
1113 * evaluate expressions in proper order before
1115 * Can't guarantee that compiler will do this
1116 * correctly for us if we put them inline.
1118 f1
= (double)exprreal(np
->n_left
);
1119 f2
= (double)exprreal(np
->n_right
);
1120 return (realnode((REAL
)pow(f1
, f2
)));
1124 if (np
->n_right
->n_type
!= COLON
)
1125 awkerr(interr
, "?:");
1126 if (exprtest(np
->n_left
))
1127 np
= np
->n_right
->n_left
; else
1128 np
= np
->n_right
->n_right
;
1129 return (exprreduce(np
));
1137 return (comparison(np
));
1144 return (arithmetic(np
));
1147 inc_oper
->n_type
= SUB
;
1150 inc_oper
->n_type
= ADD
;
1152 if ((np
= np
->n_left
)->n_type
== INDEX
)
1153 np
= exprreduce(np
);
1154 if (np
->n_flags
& FREAL
)
1155 tnp
= realnode(np
->n_real
);
1157 tnp
= intnode(exprint(np
));
1158 inc_oper
->n_left
= np
;
1159 (void) assign(np
, inc_oper
);
1163 inc_oper
->n_type
= SUB
;
1166 inc_oper
->n_type
= ADD
;
1168 if ((np
= np
->n_left
)->n_type
== INDEX
)
1169 np
= exprreduce(np
);
1170 inc_oper
->n_left
= np
;
1171 return (assign(np
, inc_oper
));
1174 asn_oper
->n_type
= ADD
;
1177 asn_oper
->n_type
= SUB
;
1180 asn_oper
->n_type
= MUL
;
1183 asn_oper
->n_type
= DIV
;
1186 asn_oper
->n_type
= REM
;
1189 asn_oper
->n_type
= EXP
;
1191 asn_oper
->n_right
= np
->n_right
;
1192 if ((np
= np
->n_left
)->n_type
== INDEX
)
1193 np
= exprreduce(np
);
1194 asn_oper
->n_left
= np
;
1195 return (assign(np
, asn_oper
));
1199 return (f_getline(np
));
1202 return ((*np
->n_left
->n_function
)(np
->n_right
));
1205 if (regmatch(np
->n_regexp
, linebuf
) == REG_OK
)
1210 cp
= exprstring(np
->n_left
);
1211 if (regmatch(getregexp(np
->n_right
), cp
) == REG_OK
)
1216 cp
= exprstring(np
->n_left
);
1217 if (regmatch(getregexp(np
->n_right
), cp
) != REG_OK
)
1222 return (assign(np
->n_left
, np
->n_right
));
1225 awkerr(badarray
, np
->n_name
);
1229 awkerr(varnotfunc
, np
->n_name
);
1233 awkerr(gettext("panic: exprreduce(%d)"), t
);
1240 * Do arithmetic operators.
1243 arithmetic(NODE
*np
)
1245 register NODE
*left
, *right
;
1247 register INT i1
, i2
;
1248 register INT iresult
;
1249 register REAL r1
, r2
;
1251 left
= exprreduce(np
->n_left
);
1252 if (isreal(left
->n_flags
) ||
1253 (isstring(left
->n_flags
) && (type_of(left
)&FVREAL
))) {
1255 r1
= exprreal(left
);
1256 r2
= exprreal(np
->n_right
);
1259 right
= exprreduce(np
->n_right
);
1260 if (isreal(right
->n_flags
) ||
1261 (isstring(right
->n_flags
) && (type_of(right
)&FVREAL
))) {
1265 r2
= exprreal(right
);
1268 i2
= exprint(right
);
1272 switch (np
->n_type
) {
1282 * Strategically placed between ADD and SUB
1283 * so "jo" branches will reach on 80*86
1324 double fmod(double x
, double y
);
1333 return (type
== FINT
? intnode(iresult
) : realnode(r1
));
1337 * Do comparison operators.
1340 comparison(NODE
*np
)
1342 register NODE
*left
, *right
;
1345 register REAL r1
, r2
;
1346 register INT i1
, i2
;
1349 if (isleaf(left
->n_flags
)) {
1350 if (left
->n_type
== PARM
)
1351 left
= left
->n_next
;
1353 left
= exprreduce(left
);
1355 right
= np
->n_right
;
1356 if (isleaf(right
->n_flags
)) {
1357 if (right
->n_type
== PARM
)
1358 right
= right
->n_next
;
1361 right
= exprreduce(right
);
1364 tr
= right
->n_flags
;
1366 * Posix mandates semantics for the comparison operators that
1367 * are incompatible with traditional AWK behaviour. If the following
1368 * define is true then awk will use the traditional behaviour.
1369 * if it's false, then AWK will use the POSIX-mandated behaviour.
1371 #define TRADITIONAL 0
1373 if (!isnumber(tl
) || !isnumber(tr
)) {
1374 cmp
= wcscoll((wchar_t *)exprstring(left
),
1375 (wchar_t *)exprstring(right
));
1376 } else if (isreal(tl
) || isreal(tr
)) {
1377 r1
= exprreal(left
);
1378 r2
= exprreal(right
);
1387 i2
= exprint(right
);
1396 if (!isnumber(tl
) && !isnumber(tr
)) {
1398 cmp
= wcscoll((wchar_t *)exprstring(left
),
1399 (wchar_t *)exprstring(right
));
1404 tr
= type_of(right
);
1405 if (!isnumber(tl
) || !isnumber(tr
))
1407 if (isreal(tl
) || isreal(tr
)) {
1408 r1
= exprreal(left
);
1409 r2
= exprreal(right
);
1418 i2
= exprint(right
);
1428 switch (np
->n_type
) {
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 return (cmp
< 0 ? const1
: const0
);
1448 awkerr(interr
, "comparison");
1455 * Return the type of a constant that is a string.
1456 * The node must be a FSTRING type and the return value
1457 * will possibly have FVINT or FVREAL or'ed in.
1467 int digitsaftere
= 0;
1469 cp
= (wchar_t *)np
->n_string
;
1471 return (FSTRING
|FVINT
);
1472 while (iswspace(*cp
))
1474 if (*cp
== '-' || *cp
== '+')
1476 while (*cp
!= '\0') {
1495 if (seene
|| !somedigits
)
1502 if (seensign
|| !seene
|| digitsaftere
)
1508 if (*cp
== radixpoint
) {
1509 if (seenradix
|| seene
|| (!somedigits
&&
1518 if (somedigits
== 0)
1520 if (somedigits
>= MAXDIGINT
|| seenradix
|| seene
) {
1521 if (seensign
&& !digitsaftere
)
1524 return (FSTRING
|FVREAL
);
1526 return (FSTRING
|FVINT
);
1530 * Return a field rvalue.
1535 register wchar_t *cp
;
1538 return (stringnode(linebuf
, FSTATIC
|FSENSE
, lbuflen
));
1541 if (fieldno
> nfield
|| fieldno
< 0)
1542 return (stringnode(_null
, FSTATIC
, 0));
1543 cp
= fields
[fieldno
-1];
1544 return (stringnode(cp
, FSTATIC
|FSENSE
, wcslen(cp
)));
1548 * Split linebuf into fields. Done only once
1549 * per input record (maximum).
1554 register wchar_t *ip
, *op
;
1558 if (fieldbuf
== NULL
)
1559 fieldbuf
= emalloc(NLINE
* sizeof (wchar_t));
1563 while ((ip
= (*awkfield
)(&ep
)) != NULL
) {
1564 fields
[fcount
++] = op
;
1565 if (fcount
> NFIELD
)
1566 awkerr(tmfld
, NFIELD
);
1568 (void) memcpy(op
, ip
, n
* sizeof (wchar_t));
1572 if (varNF
->n_flags
& FINT
)
1573 varNF
->n_int
= fcount
;
1575 constant
->n_int
= fcount
;
1576 (void) nassign(varNF
, constant
);
1583 * Assign to a field as an lvalue.
1584 * Return the unevaluated node as one doesn't always need it
1585 * evaluated in an assignment.
1588 lfield(INT fieldno
, NODE
*np
)
1590 register wchar_t *cp
;
1591 register wchar_t *op
;
1592 register wchar_t *sep
;
1594 register wchar_t *newval
;
1595 register int seplen
;
1596 register int newlen
;
1598 newlen
= wcslen(newval
= (wchar_t *)exprstring(np
));
1601 (void) memcpy(linebuf
, newval
, (newlen
+1) * sizeof (wchar_t));
1605 seplen
= wcslen(sep
= (wchar_t *)exprstring(varOFS
));
1608 if (--fieldno
< nfield
&&
1609 (newlen
<= wcslen(fields
[fieldno
]))) {
1610 (void) memcpy(fields
[fieldno
], newval
,
1611 (newlen
+1) * sizeof (wchar_t));
1613 register wchar_t *buf
;
1616 fieldbuf
= emalloc(NLINE
* sizeof (wchar_t));
1617 if (fieldno
>= nfield
) {
1618 if (fieldno
>= NFIELD
)
1619 awkerr(tmfld
, NFIELD
);
1620 while (nfield
< fieldno
)
1621 fields
[nfield
++] = _null
;
1624 fields
[fieldno
] = newval
;
1626 for (i
= 0; i
< nfield
; i
++) {
1627 newlen
= wcslen(cp
= fields
[i
])+1;
1629 if (op
+newlen
>= fieldbuf
+NLINE
)
1630 awkerr(toolong
, NLINE
);
1631 (void) memcpy(op
, cp
,
1632 newlen
* sizeof (wchar_t));
1642 while (i
< nfield
) {
1643 newlen
= wcslen(cp
= fields
[i
++]);
1644 (void) memcpy(op
, cp
, newlen
* sizeof (wchar_t));
1647 (void) memcpy(op
, sep
,
1648 seplen
* sizeof (wchar_t));
1651 if (op
>= &linebuf
[NLINE
])
1652 awkerr(toolong
, NLINE
);
1655 lbuflen
= op
-linebuf
;
1656 if (varNF
->n_flags
& FINT
)
1657 varNF
->n_int
= nfield
;
1659 constant
->n_int
= nfield
;
1660 (void) nassign(varNF
, constant
);
1667 * Do a user function.
1668 * Each formal parameter must:
1669 * have the actual parameter assigned to it (call by value),
1670 * have a pointer to an array put into it (call by reference),
1671 * and be made undefined (extra formal parameters)
1676 register NODE
*temp
;
1679 if ((fnp
= np
->n_left
) == NNULL
)
1680 awkerr(gettext("impossible function call"));
1681 if (fnp
->n_type
!= UFUNC
)
1682 awkerr(varnotfunc
, fnp
->n_name
);
1685 if (slevel
>= NRECUR
)
1686 awkerr(gettext("function \"%S\" nesting level > %u"),
1687 fnp
->n_name
, NRECUR
);
1690 awkerr(gettext("function \"%s\" nesting level too deep"),
1696 register NODE
*formal
;
1697 register NODE
*actual
;
1698 NODE
*formlist
, *actlist
, *templist
, *temptail
;
1700 templist
= temptail
= NNULL
;
1701 actlist
= np
->n_right
;
1702 formlist
= fnp
->n_left
;
1704 * pass through formal list, setting up a list
1705 * (on templist) containing temps for the values
1707 * If the actual list runs out before the formal
1708 * list, assign 'constundef' as the value
1710 while ((formal
= getlist(&formlist
)) != NNULL
) {
1711 register NODE
*array
;
1713 register size_t len
;
1714 register int scope_tag
;
1716 actual
= getlist(&actlist
);
1717 if (actual
== NNULL
) {
1718 actual
= constundef
;
1719 scope_tag
= slevel
+1;
1723 switch (actual
->n_type
) {
1730 array
= actual
= actual
->n_next
;
1732 scope_tag
= actual
->n_scope
;
1733 if (!(actual
->n_flags
& FLARRAY
))
1734 array
= actual
->n_alink
;
1741 temp
= emptynode(t
, len
= wcslen(formal
->n_name
));
1742 (void) memcpy(temp
->n_name
, formal
->n_name
,
1743 (len
+1) * sizeof (wchar_t));
1744 temp
->n_flags
= FSTRING
|FVINT
;
1745 temp
->n_string
= _null
;
1748 (void) assign(temp
, actual
);
1750 temp
->n_flags
|= FLARRAY
;
1751 temp
->n_scope
= scope_tag
;
1753 * link to actual parameter in case of promotion to
1756 if (actual
!= constundef
)
1757 temp
->n_alink
= actual
;
1759 * Build the templist
1761 if (templist
!= NNULL
) {
1762 temptail
->n_next
= temp
;
1765 templist
= temptail
= temp
;
1766 temp
->n_next
= NNULL
;
1767 if (actual
->n_type
== CONSTANT
)
1768 temp
->n_alink
= temp
;
1770 temp
->n_alink
= array
;
1773 * Bind results of the evaluation of actuals to formals.
1775 formlist
= fnp
->n_left
;
1776 while (templist
!= NNULL
) {
1778 templist
= temp
->n_next
;
1779 formal
= getlist(&formlist
);
1780 temp
->n_next
= formal
->n_next
;
1781 formal
->n_next
= temp
;
1793 register NODE
*savenode
= curnode
;
1796 if (action(fnp
->n_right
) == RETURN
)
1802 register NODE
*formal
;
1805 formlist
= fnp
->n_left
;
1806 while ((formal
= getlist(&formlist
)) != NNULL
) {
1807 temp
= formal
->n_next
;
1808 formal
->n_next
= temp
->n_next
;
1809 /* if node is a local array, free the elements */
1810 if (temp
->n_type
== ARRAY
&& (temp
->n_scope
== slevel
))
1820 * Get the regular expression from an expression tree.
1825 if (np
->n_type
== RE
)
1826 return (np
->n_regexp
);
1827 np
= renode((wchar_t *)exprstring(np
));
1828 return (np
->n_regexp
);
1832 * Get the next element from a list.
1839 if ((np
= *npp
) == NNULL
)
1841 if (np
->n_type
== COMMA
) {
1843 return (np
->n_left
);
1859 test
= exprtest(np
->n_left
);
1861 if (xp
->n_type
!= ELSE
)
1862 awkerr(interr
, "if/else");
1867 return (action(xp
));
1871 * while and do{}while statements.
1876 register int act
= 0;
1878 if (np
->n_type
== DO
)
1881 if (exprtest(np
->n_left
) == 0)
1884 if ((act
= action(np
->n_right
)) != 0) {
1906 register NODE
*testnp
, *incnp
, *initnp
;
1907 register int act
= 0;
1911 initnp
= getlist(&listp
);
1912 testnp
= getlist(&listp
);
1913 incnp
= getlist(&listp
);
1914 if (initnp
!= NNULL
)
1915 (void) exprreduce(initnp
);
1917 if (exprtest(testnp
) == 0)
1919 if ((act
= action(np
->n_right
)) != 0) {
1933 (void) exprreduce(incnp
);
1939 * for variable in array statement.
1944 register NODE
*left
;
1945 register int act
= 0;
1947 register NODE
**nnp
;
1948 register NODE
*statement
;
1949 register int issymtab
= 0;
1955 statement
= np
->n_right
;
1956 if (left
->n_type
!= IN
)
1957 awkerr(interr
, "for (var in array)");
1958 if ((var
= left
->n_left
)->n_type
== PARM
)
1961 if (np
->n_type
== PARM
) {
1963 if (!(np
->n_flags
& FLARRAY
))
1966 if (np
== varSYMTAB
) {
1972 * At this point if the node is not actually an array
1973 * check to see if it has already been established as
1974 * a scalar. If it is a scalar then flag an error. If
1975 * not then promote the object to an array type.
1977 if (np
->n_type
!= ARRAY
) {
1978 if (!isstring(np
->n_flags
) || np
->n_string
!= _null
)
1979 awkerr(notarray
, np
->n_name
);
1981 /* promotion to array */
1983 if (np
->n_alink
!= NNULL
)
1984 if (!(np
->n_flags
& FLARRAY
))
1989 * Set up a pointer to the first node in the array list.
1990 * Save this pointer on the delete stack. This information
1991 * is used by the delete function to advance any pointers
1992 * that might be pointing at a node which has been deleted.
1993 * See the delsymtab() function for more information. Note
1994 * that if the a_link field is nil, then just return 0 since
1995 * this array has no elements yet.
1997 if ((*(nnp
= next_forin
) = np
->n_alink
) == 0)
1999 if (++next_forin
> &forindex
[NFORINLOOP
])
2000 awkerr(toodeep
, NFORINLOOP
);
2002 * array elements have names of the form
2003 * <name>]<index> (global arrays)
2005 * <name>[<scope>]<index> (local arrays)
2006 * We need to know the offset of the index portion of the
2007 * name string in order to place it in the index variable so
2008 * we look for the ']'. This is calculated here and then
2011 for (alen
= 0; (*nnp
)->n_name
[alen
++] != ']'; )
2012 if ((*nnp
)->n_name
[alen
] == '\0')
2013 awkerr(interr
, "for: invalid array");
2017 if ((left
= symwalk(&nbuck
, &np
)) == NNULL
)
2019 index
= left
->n_name
;
2021 if ((np
= *nnp
) == NNULL
)
2023 index
= np
->n_name
+alen
;
2026 strassign(var
, index
, FSTATIC
, wcslen(index
));
2027 if ((act
= action(statement
)) != 0) {
2045 * Walk the symbol table using the same algorithm as arraynode.
2048 symwalk(int *buckp
, NODE
**npp
)
2054 while (np
== NNULL
) {
2055 if (*buckp
>= NBUCKET
)
2056 return (*npp
= NNULL
);
2057 np
= symtab
[(*buckp
)++];
2059 if (np
->n_type
== VAR
&&
2060 (!isstring(np
->n_flags
) || np
->n_string
!= _null
)) {
2070 * Test the result of an expression.
2079 if (freelist
!= NNULL
)
2081 np
= exprreduce(np
);
2082 if (isint(t
= np
->n_flags
)) {
2084 return (exprint(np
) != 0);
2085 return (np
->n_int
!= 0);
2090 rval
= isstring(t
) ? exprreal(np
) : np
->n_real
;
2091 return (rval
!= 0.0);
2093 return (*(wchar_t *)exprstring(np
) != '\0');
2097 * Return malloc'ed space that holds the given name "[" scope "]" index ...
2098 * concatenated string.
2099 * The node (np) is the list of indices and 'array' is the array name.
2102 makeindex(NODE
*np
, wchar_t *array
, int tag
)
2104 static wchar_t tags
[sizeof (int)];
2105 static wchar_t tag_chars
[] = M_MB_L("0123456789ABCDEF");
2106 register wchar_t *cp
;
2107 register NODE
*index
;
2110 register wchar_t *indstr
;
2111 register wchar_t *sep
;
2112 register int seplen
;
2113 register int taglen
;
2117 * calculate and create the tag string
2119 for (taglen
= 0; tag
; tag
>>= 4)
2120 tags
[taglen
++] = tag_chars
[tag
& 0xf];
2122 * Special (normal) case: only one index.
2124 if (np
->n_type
!= COMMA
) {
2128 if (isleaf(np
->n_flags
) && np
->n_type
== PARM
)
2130 if (isstring(np
->n_flags
)) {
2131 indstr
= np
->n_string
;
2134 indstr
= exprstring(np
);
2135 len
= wcslen(indstr
);
2137 i
= (n
= wcslen(array
)) + len
+ 3 + taglen
;
2141 ocp
= emalloc(i
* sizeof (wchar_t));
2142 (void) memcpy(ocp
, array
, n
* sizeof (wchar_t));
2147 *cp
++ = tags
[--taglen
];
2150 (void) memcpy(cp
, indstr
, (len
+1) * sizeof (wchar_t));
2155 seplen
= wcslen(sep
= (wchar_t *)exprstring(varSUBSEP
));
2156 while ((index
= getlist(&np
)) != NNULL
) {
2157 indstr
= exprstring(index
);
2158 len
= wcslen(indstr
);
2160 cp
= emalloc(sizeof (wchar_t) * ((n
= wcslen(array
)) +
2162 (void) memcpy(cp
, array
, n
* sizeof (wchar_t));
2166 cp
[n
++] = tags
[--taglen
];
2170 cp
= erealloc(cp
, (n
+len
+seplen
+1) * sizeof (wchar_t));
2171 (void) memcpy(cp
+n
, sep
, seplen
* sizeof (wchar_t));
2174 (void) memcpy(cp
+n
, indstr
, (len
+1) * sizeof (wchar_t));
2182 * Promote a node to an array. In the simplest case, just set the
2183 * node type field to ARRAY. The more complicated case involves walking
2184 * a list of variables that haven't been determined yet as scalar or array.
2185 * This routine plays with the pointers to avoid recursion.
2190 register NODE
*prev
= NNULL
;
2191 register NODE
*next
;
2194 * walk down the variable chain, reversing the pointers and
2195 * setting each node to type array.
2197 while ((n
->n_flags
& FLARRAY
) && (n
->n_alink
!= n
)) {
2206 * If the final entity on the chain is a local variable, then
2207 * reset it's alink field to NNULL - normally it points back
2208 * to itself - this is used in other parts of the code to
2209 * reduce the number of conditionals when handling locals.
2212 if (n
->n_flags
& FLARRAY
)
2216 * Now walk back up the list setting the alink to point to
2217 * the last entry in the chain and clear the 'local array'
2220 while (prev
!= NNULL
) {
2221 prev
->n_flags
&= ~FLARRAY
;
2222 next
= prev
->n_alink
;