xref: /titanic_51/usr/src/cmd/awk_xpg4/awk3.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * awk -- executor
24  *
25  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
26  * Use is subject to license terms.
27  *
28  * Copyright 1985, 1994 by Mortice Kern Systems Inc.  All rights reserved.
29  *
30  * Based on MKS awk(1) ported to be /usr/xpg4/bin/awk with POSIX/XCU4 changes
31  */
32 
33 #pragma ident	"%Z%%M%	%I%	%E% SMI"
34 
35 #include "awk.h"
36 #include "y.tab.h"
37 
38 static int	dohash(wchar_t *name);
39 static NODE	*arithmetic(NODE *np);
40 static NODE	*comparison(NODE *np);
41 static int	typeof(NODE *np);
42 static NODE	*lfield(INT fieldno, NODE *value);
43 static NODE	*rfield(INT fieldno);
44 static NODE	*userfunc(NODE *np);
45 static wchar_t	*lltoa(long long l);
46 static NODE	*exprconcat(NODE *np, int len);
47 static int	s_if(NODE *np);
48 static int	s_while(NODE *np);
49 static int	s_for(NODE *np);
50 static int	s_forin(NODE *np);
51 static void	setrefield(NODE *value);
52 static void	freetemps(void);
53 static int	action(NODE *np);
54 static wchar_t	*makeindex(NODE *np, wchar_t *array, int tag);
55 static int	exprtest(NODE *np);
56 
57 #define	regmatch(rp, s) REGWEXEC(rp, s, 0, (REGWMATCH_T*)NULL, 0)
58 
59 /*
60  * This code allows for integers to be stored in longs (type INT) and
61  * only promoted to double precision floating point numbers (type REAL)
62  * when overflow occurs during +, -, or * operations.  This is very
63  * non-portable if you desire such a speed optimisation.  You may wish
64  * to put something here for your system.  This "something" would likely
65  * include either an assembler "jump on overflow" instruction or a
66  * method to get traps on overflows from the hardware.
67  *
68  * This portable method works for ones and twos complement integer
69  * representations (which is, realistically) almost all machines.
70  */
71 #if	__TURBOC__
72 #define	addoverflow()	asm	jo	overflow
73 #define	suboverflow()	asm	jo	overflow
74 #else
75 /*
76  * These are portable to two's complement integer machines
77  */
78 #define	addoverflow()	if ((i1^i2)>=0 && (iresult^i1)<0) goto overflow
79 #define	suboverflow()	if ((i1^i2)<0 && (iresult^i2)>=0) goto overflow
80 #endif
81 #define	muloverflow()	if (((short)i1!=i1 || (short)i2!=i2)	\
82 			 && ((i2!=0 && iresult/i2!=i1)		\
83 			  || (i1==LONG_MIN && i2==-1)))	  goto overflow
84 
85 static char	notarray[] = "scalar \"%s\" cannot be used as array";
86 static char	badarray[] = "array \"%s\" cannot be used as a scalar";
87 static char	varnotfunc[] = "variable \"%s\" cannot be used as a function";
88 static char	tmfld[] = "Too many fields (LIMIT: %d)";
89 static char	toolong[] = "Record too long (LIMIT: %d bytes)";
90 static char	divzero[] =  "division (/ or %%) by zero";
91 static char	toodeep[] = "too deeply nested for in loop (LIMIT: %d)";
92 
93 static wchar_t	numbuf[NUMSIZE];	/* Used to convert INTs to strings */
94 static wchar_t	*fields[NFIELD];	/* Cache of pointers into fieldbuf */
95 static wchar_t	*fieldbuf;		/* '\0' separated copy of linebuf */
96 static NODE	nodes[NSNODE];		/* Cache of quick access nodes */
97 static NODE	*fnodep = &nodes[0];
98 #define	NINDEXBUF	50
99 static wchar_t	indexbuf[NINDEXBUF];	/* Used for simple array indices */
100 static int	concflag;		/* In CONCAT operation (no frees) */
101 static NODE	*retval;		/* Last return value of a function */
102 
103 /*
104  * The following stack is used to store the next pointers for all nested
105  * for-in loops. This needs to be global so that delete can check to see
106  * if it is deleting the next node to be used by a loop.
107  */
108 #define NFORINLOOP	10
109 static NODE*	forindex[NFORINLOOP];
110 static NODE**	next_forin = forindex;
111 
112 /*
113  * Assign a string directly to a NODE without creating an intermediate
114  * NODE.  This can handle either FALLOC, FSTATIC, FNOALLOC or FSENSE for
115  * "flags" argument.  Also the NODE "np" must be reduced to an lvalue
116  * (PARM nodes are not acceptable).
117  */
118 void
119 strassign(NODE *np, STRING string, int flags, size_t length)
120 {
121 	if (np->n_type == FUNC)
122 		awkerr(gettext("attempt to redefine builtin function"));
123 	else if (np->n_type == GETLINE || np->n_type == KEYWORD)
124 		awkerr(gettext("inadmissible use of reserved keyword"));
125 	if (np->n_flags & FSPECIAL) {
126 		(void)nassign(np, stringnode(string, flags, length));
127 		return;
128 	}
129 	if (isastring(np->n_flags))
130 		free((wchar_t *)np->n_string);
131 	np->n_strlen = length++;
132 	if (flags & FALLOC) {
133 		length *= sizeof(wchar_t);
134 		np->n_string = (STRING) emalloc(length);
135 		(void) memcpy((void *)np->n_string, string, length);
136 	} else {
137 		np->n_string = string;
138 		if (flags & FNOALLOC) {
139 			flags &= ~FNOALLOC;
140 			flags |= FALLOC;
141 		}
142 	}
143 	np->n_flags &= FSAVE;
144 	if (flags & FSENSE) {
145 		flags &= ~FSENSE;
146 		flags |= typeof(np);
147 	} else
148 		flags |= FSTRING;
149 	np->n_flags |= flags;
150 }
151 
152 /*
153  * Assign to a variable node.
154  * LHS must be a VAR type and RHS must be reduced by now.
155  * To speed certain operations up, check for
156  * certain things here and do special assignments.
157  */
158 NODE *
159 nassign(NODE *np, NODE *value)
160 {
161 	register wchar_t *cp;
162 	register int len;
163 
164 	/* short circuit assignment of a node to itself */
165 	if (np == value)
166 		return (np);
167 	if (np->n_flags & FSPECIAL) {
168 		if (np == varRS || np == varFS) {
169 			if (isastring(np->n_flags))
170 				free((void *)np->n_string);
171 			len = sizeof(wchar_t) * ((np->n_strlen =
172 				wcslen(cp = exprstring(value)))+1);
173 			np->n_string = emalloc(len);
174 			(void) memcpy((wchar_t *)np->n_string, cp, len);
175 			np->n_flags = FALLOC|FSTRING|FSPECIAL;
176 			if (np == varRS) {
177 				if (np->n_string[0] == '\n')
178 					awkrecord = defrecord;
179 				else if (np->n_string[0] == '\0')
180 					awkrecord = multirecord;
181 				else
182 					awkrecord = charrecord;
183 			} else if (np == varFS) {
184 				if (resep != (REGEXP)NULL) {
185 					regfree(resep);
186 					resep = (REGEXP)NULL;
187 				}
188 				if (wcslen((wchar_t *)np->n_string) > 1)
189 					setrefield(np);
190 				else if (np->n_string[0] == ' ')
191 					awkfield = whitefield;
192 				else
193 					awkfield = blackfield;
194 			}
195 			return (np);
196 		}
197 	}
198 	if (isastring(np->n_flags))
199 		free((wchar_t *)np->n_string);
200 	if (isstring(value->n_flags)) {
201 		np->n_strlen = value->n_strlen;
202 		if (value->n_flags&FALLOC || value->n_string!=_null) {
203 			len = (np->n_strlen+1) * sizeof(wchar_t);
204 			np->n_string = emalloc(len);
205 			(void) memcpy(np->n_string, value->n_string, len);
206 			np->n_flags &= FSAVE;
207 			np->n_flags |= value->n_flags & ~FSAVE;
208 			np->n_flags |= FALLOC;
209 			return (np);
210 		} else
211 			np->n_string = value->n_string;
212 	} else if (value->n_flags & FINT)
213 		np->n_int = value->n_int;
214 	else
215 		np->n_real = value->n_real;
216 	np->n_flags &= FSAVE;
217 	np->n_flags |= value->n_flags & ~FSAVE;
218 	return (np);
219 }
220 
221 /*
222  * Set regular expression FS value.
223  */
224 static void
225 setrefield(NODE *np)
226 {
227 	static regex_t re;
228 	int n;
229 
230 	if ((n = REGWCOMP(&re, np->n_string, REG_EXTENDED)) != REG_OK) {
231 		regerror(n, &re, (char *)linebuf, sizeof(linebuf));
232 		awkerr(gettext("syntax error \"%s\" in /%s/\n"),
233 			(char *)linebuf, np->n_string);
234 	}
235 	resep = &re;
236 	awkfield = refield;
237 }
238 
239 /*
240  * Assign to an l-value node.
241  */
242 NODE *
243 assign(NODE *left, NODE *right)
244 {
245 	if (isleaf(right->n_flags)) {
246 		if (right->n_type == PARM)
247 			right = right->n_next;
248 	} else
249 		right = exprreduce(right);
250 top:
251 	switch (left->n_type) {
252 	case INDEX:
253 		left = exprreduce(left);
254 	case VAR:
255 		return (nassign(left, right));
256 
257 	case PARM:
258 		/*
259 		 * If it's a parameter then link to the actual value node and
260 		 * do the checks again.
261 		 */
262 		left = left->n_next;
263 		goto top;
264 
265 	case FIELD:
266 		return (lfield(exprint(left->n_left), right));
267 
268 	case CALLUFUNC:
269 	case UFUNC:
270 		awkerr(gettext("cannot assign to function \"%s\""),
271 		    left->n_name);
272 
273 	default:
274 		awkerr(gettext("lvalue required in assignment"));
275 	}
276 	/* NOTREACHED */
277 }
278 
279 /*
280  * Compiled tree non-terminal node.
281  */
282 NODE *
283 node(int type, NODE *left, NODE *right)
284 {
285 	register NODE *np;
286 
287 	np = emptynode(type, 0);
288 	np->n_left = left;
289 	np->n_right = right;
290 	np->n_lineno = lineno;
291 	return (np);
292 }
293 
294 /*
295  * Create an integer node.
296  */
297 NODE *
298 intnode(INT i)
299 {
300 	register NODE *np;
301 
302 	np = emptynode(CONSTANT, 0);
303 	np->n_flags = FINT|FVINT;
304 	np->n_int = i;
305 	return (np);
306 }
307 
308 /*
309  * Create a real number node.
310  */
311 NODE *
312 realnode(REAL real)
313 {
314 	register NODE *np;
315 
316 	np = emptynode(CONSTANT, 0);
317 	np->n_flags = FREAL|FVREAL;
318 	np->n_real = real;
319 	return (np);
320 }
321 
322 /*
323  * Make a node for a string.
324  */
325 NODE *
326 stringnode(STRING s, int how, size_t length)
327 {
328 	register NODE *np;
329 
330 	np = emptynode(CONSTANT, 0);
331 	np->n_strlen = length;
332 	if (how & FALLOC) {
333 		np->n_string = emalloc(length = (length+1) * sizeof(wchar_t));
334 		(void) memcpy(np->n_string, s, length);
335 	} else {
336 		np->n_string = s;
337 		if (how & FNOALLOC) {
338 			how &= ~FNOALLOC;
339 			how |= FALLOC;
340 		}
341 	}
342 	if (how & FSENSE) {
343 		np->n_flags = typeof(np);
344 		how &= ~FSENSE;
345 	} else
346 		np->n_flags = FSTRING;
347 	np->n_flags |= how;
348 	return (np);
349 }
350 
351 /*
352  * Save a copy of a string.
353  */
354 STRING
355 strsave(wchar_t *old)
356 {
357 	STRING new;
358 	register size_t len;
359 
360 	new = (STRING)emalloc(len = (wcslen(old)+1) * sizeof(wchar_t));
361 	(void) memcpy(new, old, len);
362 	return (new);
363 }
364 
365 /*
366  * Allocate an empty node of given type.
367  * String space for the node is given by `length'.
368  */
369 NODE *
370 emptynode(int type, size_t length)
371 {
372 	register NODE *np;
373 
374 	if (length==0 && running && fnodep < &nodes[NSNODE]) {
375 		np = fnodep++;
376 	} else {
377 		np = (NODE *) emalloc(sizeof(NODE)+(length * sizeof(wchar_t)));
378 		if (running && type!=VAR && type!=ARRAY) {
379 			np->n_next = freelist;
380 			freelist = np;
381 		}
382 	}
383 	np->n_flags = FNONTOK;
384 	np->n_type = type;
385 	np->n_alink = NNULL;
386 
387 	return (np);
388 }
389 
390 /*
391  * Free a node.
392  */
393 void
394 freenode(NODE *np)
395 {
396 	if (isastring(np->n_flags))
397 		free((wchar_t *)np->n_string);
398 	else if (np->n_type == RE) {
399 		regfree(np->n_regexp);
400 		free((wchar_t *)np->n_regexp);
401 	}
402 	free((wchar_t *)np);
403 }
404 
405 /*
406  * Install a keyword of given `type'.
407  */
408 void
409 kinstall(LOCCHARP name, int type)
410 {
411 	register NODE *np;
412 	register size_t l;
413 
414 	l = wcslen(name);
415 	np = emptynode(KEYWORD, l);
416 	np->n_keywtype = type;
417 	(void) memcpy(np->n_name, name, (l+1) * sizeof(wchar_t));
418 	addsymtab(np);
419 }
420 
421 /*
422  * Install built-in function.
423  */
424 NODE *
425 finstall(LOCCHARP name, FUNCTION func, int type)
426 {
427 	register NODE *np;
428 	register size_t l;
429 
430 	l = wcslen(name);
431 	np = emptynode(type, l);
432 	np->n_function = func;
433 	(void) memcpy(np->n_name, name, (l+1) * sizeof(wchar_t));
434 	addsymtab(np);
435 	return np;
436 }
437 
438 /*
439  * Lookup an identifier.
440  * nocreate contains the following flag values:
441  *	1 if no creation of a new NODE,
442  *	0 if ok to create new NODE
443  */
444 NODE *
445 vlookup(wchar_t *name, int nocreate)
446 {
447 	register ushort hash;
448 	register NODE *np;
449 
450 	np = symtab[hashbuck(hash = dohash((wchar_t*)name))];
451 	while (np != NNULL) {
452 		if (np->n_hash==hash && wcscmp(name, np->n_name)==0)
453 			return (np);
454 		np = np->n_next;
455 	}
456 	if (nocreate) {
457 		np = NNULL;
458 	} else {
459 		np = emptynode(VAR, hash = wcslen(name));
460 		np->n_flags = FSTRING|FVINT;
461 		np->n_strlen = 0;
462 		np->n_string = _null;
463 		(void) memcpy(np->n_name, name,
464 			(hash+1) * sizeof(wchar_t));
465 		addsymtab(np);
466 	}
467 	return (np);
468 }
469 
470 /*
471  * Add a symbol to the table.
472  */
473 void
474 addsymtab(NODE *np)
475 {
476 	register NODE **spp;
477 
478 	np->n_hash = dohash((wchar_t *)np->n_name);
479 	spp = &symtab[hashbuck(np->n_hash)];
480 	np->n_next = *spp;
481 	*spp = np;
482 }
483 
484 /*
485  * Delete the given node from the symbol table.
486  * If fflag is non-zero, also free the node space.
487  * This routine must also check the stack of forin loop pointers. If
488  * we are deleting the next item to be used, then the pointer must be
489  * advanced.
490  */
491 void
492 delsymtab(NODE *np, int fflag)
493 {
494 	register NODE *rnp;
495 	register NODE *prevp;
496 	register NODE **sptr;
497 	register ushort h;
498 
499 
500 
501 
502 
503 	h = hashbuck(np->n_hash);
504 	prevp = NNULL;
505 	for (rnp = symtab[h]; rnp != NNULL; rnp = rnp->n_next) {
506 		if (rnp == np) {
507 			/*
508 			 * check all of the for-in loop pointers
509 			 * to see if any need to be advanced because
510 			 * this element is being deleted.
511 			 */
512 			if (next_forin != forindex) {
513 				sptr = next_forin;
514 				do {
515 					if (*--sptr == rnp) {
516 						*sptr = rnp->n_next;
517 						break;
518 					}
519 				} while (sptr != forindex);
520 			}
521 			if (prevp == NNULL)
522 				symtab[h] = rnp->n_next; else
523 				prevp->n_next = rnp->n_next;
524 			if (fflag)
525 				freenode(rnp);
526 			break;
527 		}
528 		prevp = rnp;
529 	}
530 }
531 
532 /*
533  * Hashing function.
534  */
535 static int
536 dohash(wchar_t *name)
537 {
538 	register int hash = 0;
539 
540 	while (*name != '\0')
541 		hash += *name++;
542 	return (hash);
543 }
544 
545 /*
546  * Top level executor for an awk programme.
547  * This will be passed: pattern, action or a list of these.
548  * The former function to evaluate a pattern has been
549  * subsumed into this function for speed.
550  * Patterns are:
551  *	BEGIN,
552  *	END,
553  *	other expressions (including regular expressions)
554  */
555 void
556 execute(NODE *wp)
557 {
558 	register NODE *np;
559 	register int type;
560 	register NODE *tnp;
561 
562 	curnode = wp;
563 	if (phase != 0) {
564 		linebuf[0] = '\0';
565 		lbuflen = 0;
566 	}
567 	while (wp != NNULL) {
568 		if (wp->n_type == COMMA) {
569 			np = wp->n_left;
570 			wp = wp->n_right;
571 		} else {
572 			np = wp;
573 			wp = NNULL;
574 		}
575 		if (np->n_type != PACT)
576 			awkerr(interr, "PACT");
577 		/*
578 		 * Save the parent node and evaluate the pattern.
579 		 * If it evaluates to false (0) just continue
580 		 * to the next pattern/action (PACT) pair.
581 		 */
582 		tnp = np;
583 		np = np->n_left;
584 		if (np == NNULL) {
585 			if (phase != 0)
586 				continue;
587 		} else if (phase != 0) {
588 			if (np->n_type != phase)
589 				continue;
590 		} else if ((type = np->n_type)==BEGIN || type==END) {
591 			continue;
592 		} else if (type == COMMA) {
593 			/*
594 			 * The grammar only allows expressions
595 			 * to be separated by the ',' operator
596 			 * for range patterns.
597 			 */
598 			if (np->n_flags & FMATCH) {
599 				if (exprint(np->n_right) != 0)
600 					np->n_flags &= ~FMATCH;
601 			} else if (exprint(np->n_left) != 0) {
602 				if (exprint(np->n_right) == 0)
603 					np->n_flags |= FMATCH;
604 			} else
605 				continue;
606 		} else if (exprint(np) == 0)
607 			continue;
608 		np = tnp;
609 		if (action(np->n_right)) {
610 			loopexit = 0;
611 			break;
612 		}
613 	}
614 	if (freelist != NNULL)
615 		freetemps();
616 }
617 
618 /*
619  * Free all temporary nodes.
620  */
621 static void
622 freetemps()
623 {
624 	register NODE *np, *nnp;
625 
626 	if (concflag)
627 		return;
628 	for (np = &nodes[0]; np < fnodep; np++) {
629 		if (isastring(np->n_flags)) {
630 			free((wchar_t *)np->n_string);
631 		} else if (np->n_type == RE) {
632 			regfree(np->n_regexp);
633 			free((wchar_t *)np->n_regexp);
634 		}
635 	}
636 	fnodep = &nodes[0];
637 	for (np = freelist; np != NNULL; np = nnp) {
638 		nnp = np->n_next;
639 		freenode(np);
640 	}
641 	freelist = NNULL;
642 }
643 
644 /*
645  * Do the given action.
646  * Actions are statements or expressions.
647  */
648 static int
649 action(NODE *wp)
650 {
651 	register NODE *np;
652 	register int act = 0;
653 	register NODE *l;
654 
655 	while (wp != NNULL) {
656 		if (wp->n_type == COMMA) {
657 			np = wp->n_left;
658 			wp = wp->n_right;
659 		} else {
660 			np = wp;
661 			wp = NNULL;
662 		}
663 		if (freelist != NNULL)
664 			freetemps();
665 		curnode = np;
666 		/*
667 		 * Don't change order of these cases without
668 		 * changing order in awk.y declarations.
669 		 * The order is optimised.
670 		 */
671 		switch (np->n_type) {
672 		case ASG:
673 			(void)assign(np->n_left, np->n_right);
674 			continue;
675 
676 		case PRINT:
677 			s_print(np);
678 			continue;
679 
680 		case PRINTF:
681 			s_prf(np);
682 			continue;
683 
684 		case EXIT:
685 			if (np->n_left != NNULL)
686 				act = (int)exprint(np->n_left); else
687 				act = 0;
688 			doend(act);
689 			/* NOTREACHED */
690 
691 		case RETURN:
692 			if (slevel == 0)
693 				awkerr(gettext("return outside of a function"));
694 			np = np->n_left!=NNULL
695 			    ? exprreduce(np->n_left)
696 			    : const0;
697 			retval = emptynode(CONSTANT, 0);
698 			retval->n_flags = FINT;
699 			(void)nassign(retval, np);
700 			return (RETURN);
701 
702 		case NEXT:
703 			loopexit = NEXT;
704 		case BREAK:
705 		case CONTINUE:
706 			return (np->n_type);
707 
708 		case DELETE:
709 			if ((l = np->n_left)->n_type == PARM) {
710 				l = l->n_next;
711 				if (!(l->n_flags & FLARRAY))
712 					l = l->n_alink;
713 			}
714 			switch (l->n_type) {
715 			case ARRAY:
716 				delarray(l);
717 				break;
718 
719 			case INDEX:
720 				if ((np = l->n_left)->n_type == PARM) {
721 	 				np = np->n_next;
722 					if (!(np->n_flags & FLARRAY))
723 						np = np->n_alink;
724 				}
725 				/*
726 				 * get pointer to the node for this array
727 				 * element using the hash key.
728 				 */
729 				l = exprreduce(l);
730 				/*
731 				 * now search linearly from the beginning of
732 				 * the list to find the element before the
733 				 * one being deleted. This must be done
734 				 * because arrays are singley-linked.
735 				 */
736 				while (np != NNULL) {
737 					if (np->n_alink == l) {
738 						np->n_alink = l->n_alink;
739 						break;
740 					}
741 					np = np->n_alink;
742 				}
743 				delsymtab(l, 1);
744 				break;
745 
746 			case VAR:
747 				if (isstring(l->n_flags) && l->n_string==_null)
748 					break;
749 			default:
750 				awkerr(gettext(
751 				    "may delete only array element or array"));
752 				break;
753 			}
754 			continue;
755 
756 		case WHILE:
757 		case DO:
758 			if ((act = s_while(np)) != 0)
759 				break;
760 			continue;
761 
762 		case FOR:
763 			if ((act = s_for(np)) != 0)
764 				break;
765 			continue;
766 
767 		case FORIN:
768 			if ((act = s_forin(np)) != 0)
769 				break;
770 			continue;
771 
772 		case IF:
773 			if ((act = s_if(np)) != 0)
774 				break;
775 			continue;
776 
777 		default:
778 			(void)exprreduce(np);
779 			if (loopexit != 0) {
780 				act = loopexit;
781 				break;
782 			}
783 			continue;
784 		}
785 		return (act);
786 	}
787 	return (0);
788 }
789 
790 /*
791  * Delete an entire array
792  */
793 void
794 delarray(NODE *np)
795 {
796 	register NODE *nnp;
797 
798 	nnp = np->n_alink;
799 	np->n_alink = NNULL;
800 	while (nnp != NNULL) {
801 		np = nnp->n_alink;
802 		delsymtab(nnp, 1);
803 		nnp = np;
804 	}
805 }
806 
807 /*
808  * Return the INT value of an expression.
809  */
810 INT
811 exprint(NODE *np)
812 {
813 	if (isleaf(np->n_flags)) {
814 		if (np->n_type == PARM)
815 			np = np->n_next;
816 		goto leaf;
817 	}
818 	np = exprreduce(np);
819 	switch (np->n_type) {
820 	case CONSTANT:
821 	case VAR:
822 	leaf:
823 		if (np->n_flags & FINT)
824 			return (np->n_int);
825 		if (np->n_flags & FREAL)
826 			return ((INT)np->n_real);
827 		return ((INT)watoll(np->n_string));
828 
829 	default:
830 		awkerr(interr, "exprint");
831 	}
832 	/* NOTREACHED */
833 }
834 
835 /*
836  * Return a real number from an expression tree.
837  */
838 REAL
839 exprreal(NODE *np)
840 {
841 	if (loopexit)
842 		return (loopexit);
843 	if (isleaf(np->n_flags)) {
844 		if (np->n_type == PARM)
845 			np = np->n_next;
846 		goto leaf;
847 	}
848 	np = exprreduce(np);
849 	switch (np->n_type) {
850 	case CONSTANT:
851 	case VAR:
852 	leaf:
853 		if (np->n_flags & FREAL)
854 			return (np->n_real);
855 		if (np->n_flags & FINT)
856 			return ((REAL)np->n_int);
857 		return ((REAL)wcstod((wchar_t *)np->n_string, (wchar_t **)0));
858 
859 	default:
860 		awkerr(interr, "exprreal");
861 	}
862 	/* NOTREACHED */
863 }
864 
865 /*
866  * Return a string from an expression tree.
867  */
868 STRING
869 exprstring(NODE *np)
870 {
871 	if (isleaf(np->n_flags)) {
872 		if (np->n_type == PARM)
873 			np = np->n_next;
874 		goto leaf;
875 	}
876 	np = exprreduce(np);
877 	switch (np->n_type) {
878 	case CONSTANT:
879 	case VAR:
880 	leaf:
881 		if (isstring(np->n_flags))
882 			return (np->n_string);
883 		if (np->n_flags & FINT)
884 			return (STRING)lltoa((long long)np->n_int);
885 		{
886 			char *tmp;
887 			(void) wsprintf(numbuf,
888 		(const char *) (tmp = wcstombsdup(exprstring(varCONVFMT))),
889 				(double) np->n_real);
890 			if (tmp != NULL)
891 				free (tmp);
892 		}
893 		return ((STRING)numbuf);
894 
895 	default:
896 		awkerr(interr, "exprstring");
897 	}
898 	/* NOTREACHED */
899 }
900 
901 /*
902  * Convert number to string.
903  */
904 static wchar_t *
905 lltoa(long long l)
906 {
907 	register wchar_t *p = &numbuf[NUMSIZE];
908 	register int s;
909 	register int neg;
910 	static wchar_t zero[] = M_MB_L("0");
911 
912 	if (l == 0)
913 		return (zero);
914 	*--p = '\0';
915 	if (l < 0)
916 		neg = 1, l = -l; else
917 		neg = 0;
918 	if ((s = (short)l) == l) {
919 		while (s != 0) {
920 			*--p = s%10 + '0';
921 			s /= 10;
922 		}
923 	} else {
924 		while (l != 0) {
925 			*--p = l%10 + '0';
926 			l /= 10;
927 		}
928 	}
929 	if (neg)
930 		*--p = '-';
931 	return (wcscpy(numbuf, p));
932 }
933 
934 /*
935  * Return pointer to node with concatenation of operands of CONCAT node.
936  * In the interest of speed, a left recursive tree of CONCAT nodes
937  * is handled with a single malloc.  The accumulated lengths of the
938  * right operands are passed down recursive invocations of this
939  * routine, which allocates a large enough string when the left
940  * operand is not a CONCAT node.
941  */
942 static NODE *
943 exprconcat(NODE *np, int len)
944 {
945 	/* we KNOW (np->n_type==CONCAT) */
946 	register NODE *lnp = np->n_left;
947 	register NODE *rnp = np->n_right;
948 	register STRING	rsp;
949 	int rlen;
950 	size_t llen;
951 	wchar_t *cp;
952 	wchar_t rnumbuf[NUMSIZE];
953 
954 	if (isleaf(rnp->n_flags) && rnp->n_type==PARM)
955 		rnp = rnp->n_next;
956 	if (isstring(rnp->n_flags)) {
957 		rsp = rnp->n_string;
958 		rlen = rnp->n_strlen;
959 	} else
960 		rlen = wcslen((wchar_t*)(rsp = exprstring(rnp)));
961 	if (rsp == numbuf) {	/* static, so save a copy */
962 		(void) memcpy(rnumbuf, (wchar_t*)rsp,
963 			(rlen+1) * sizeof(wchar_t));
964 		rsp=rnumbuf;
965 	}
966 	len += rlen;
967 	if (lnp->n_type == CONCAT) {
968 		lnp = exprconcat(lnp, len);
969 		cp = lnp->n_string;
970 		llen = lnp->n_strlen;
971 	} else {
972 		register STRING	lsp;
973 
974 		if (isleaf(lnp->n_flags) && lnp->n_type==PARM)
975 			lnp = lnp->n_next;
976 		if (isstring(lnp->n_flags)) {
977 			lsp = lnp->n_string;
978 			llen = lnp->n_strlen;
979 		} else
980 			llen = wcslen((wchar_t*)(lsp = exprstring(lnp)));
981 		cp = emalloc((llen+len+1) * sizeof(wchar_t));
982 		(void) memcpy(cp, (wchar_t*)lsp, llen * sizeof(wchar_t));
983 		lnp = stringnode(cp, FNOALLOC, llen);
984 	}
985 	(void) memcpy(cp+llen, (wchar_t*)rsp, (rlen+1) * sizeof(wchar_t));
986 	lnp->n_strlen += rlen;
987 	return (lnp);
988 }
989 
990 /*
991  * Reduce an expression to a terminal node.
992  */
993 NODE *
994 exprreduce(NODE *np)
995 {
996 	register wchar_t *cp;
997 	NODE *tnp;
998 	register int temp;
999 	register int t;
1000 	register int  tag;
1001 	register wchar_t *fname;
1002 	register wchar_t *aname;
1003 
1004 	/*
1005 	 * a var or constant is a leaf-node (no further reduction required)
1006 	 * so return immediately.
1007 	 */
1008 	if ((t = np->n_type)==VAR || t==CONSTANT)
1009 		return (np);
1010 	/*
1011 	 * If it's a parameter then it is probably a leaf node but it
1012 	 * might be an array so we check.. If it is an array, then signal
1013 	 * an error as an array by itself cannot be used in this context.
1014 	 */
1015 	if (t == PARM)
1016 		if ((np = np->n_next)->n_type == ARRAY)
1017 			awkerr(badarray, np->n_name);
1018 		else
1019 			return (np);
1020 	/*
1021 	 * All the rest are non-leaf nodes.
1022 	 */
1023 	curnode = np;
1024 	switch (t) {
1025 	case CALLUFUNC:
1026 		return (userfunc(np));
1027 
1028 	case FIELD:
1029 		return (rfield(exprint(np->n_left)));
1030 
1031 	case IN:
1032 	case INDEX:
1033 		tag = 0;
1034 		temp = np->n_type;
1035 		tnp = np->n_left;
1036 		np = np->n_right;
1037 		/* initially formal var name and array key name are the same */
1038 		fname = aname = tnp->n_name;
1039 		if (tnp->n_type == PARM) {
1040 			tnp = tnp->n_next;
1041 			tag = tnp->n_scope;
1042 			if (!(tnp->n_flags & FLARRAY)) {
1043 				tnp = tnp->n_alink;
1044 			}
1045 			aname = tnp->n_name;
1046 		}
1047 		if (tnp->n_type != ARRAY) {
1048 			if (!isstring(tnp->n_flags) || tnp->n_string!=_null)
1049 				awkerr(notarray, fname);
1050 			else {
1051 				/* promotion to array */
1052 				promote(tnp);
1053 				if (tnp->n_alink != NNULL) {
1054 					tag = tnp->n_scope;
1055 					if (!(tnp->n_flags & FLARRAY))
1056 						tnp = tnp->n_alink;
1057 					aname = tnp->n_name;
1058 				} else {
1059 					tag = 0;
1060 					if (tnp->n_flags & FLARRAY)
1061 						tag = tnp->n_scope;
1062 				}
1063 			}
1064 		}
1065 		if (tnp == varSYMTAB) {
1066 			if (np==NNULL || np->n_type==COMMA)
1067 				awkerr(gettext(
1068 				    "SYMTAB must have exactly one index"));
1069 			np = vlook(exprstring(np));
1070 			return (np);
1071 		}
1072 		cp = makeindex(np, aname, tag);
1073 		if (temp == INDEX) {
1074 			np = vlook(cp);
1075 			if (!(np->n_flags & FINARRAY)) {
1076 				np->n_alink = tnp->n_alink;
1077 				tnp->n_alink = np;
1078 				np->n_flags |= FINARRAY;
1079 			}
1080 		} else
1081 			np = vlookup(cp, 1)==NNULL ? const0 : const1;
1082 		if (cp != indexbuf)
1083 			free(cp);
1084 		return (np);
1085 
1086 	case CONCAT:
1087 		++concflag;
1088 		np = exprconcat(np, 0);
1089 		--concflag;
1090 		return (np);
1091 
1092 	case NOT:
1093 		return (intnode(exprtest(np->n_left)==0 ? (INT)1 : (INT)0));
1094 
1095 	case AND:
1096 		return ((exprtest(np->n_left) != 0
1097 		    && exprtest(np->n_right) != 0) ? const1 : const0);
1098 
1099 	case OR:
1100 		return ((exprtest(np->n_left) != 0
1101 		    || exprtest(np->n_right) != 0) ? const1 : const0);
1102 
1103 	case EXP:
1104 		{
1105                         double f1, f2;
1106 
1107 			/* evaluate expressions in proper order before
1108 			 * calling pow().
1109 			 * Can't guarantee that compiler will do this
1110 			 * correctly for us if we put them inline.
1111 			 */
1112                         f1 = (double)exprreal(np->n_left);
1113                         f2 = (double)exprreal(np->n_right);
1114                         return (realnode((REAL)pow(f1, f2)));
1115                 }
1116 
1117 	case QUEST:
1118 		if (np->n_right->n_type != COLON)
1119 			awkerr(interr, "?:");
1120 		if (exprtest(np->n_left))
1121 			np = np->n_right->n_left; else
1122 			np = np->n_right->n_right;
1123 		return (exprreduce(np));
1124 
1125 	case EQ:
1126 	case NE:
1127 	case GE:
1128 	case LE:
1129 	case GT:
1130 	case LT:
1131 		return (comparison(np));
1132 
1133 	case ADD:
1134 	case SUB:
1135 	case MUL:
1136 	case DIV:
1137 	case REM:
1138 		return (arithmetic(np));
1139 
1140 	case DEC:
1141 		inc_oper->n_type = SUB;
1142 		goto do_inc_op;
1143 	case INC:
1144 		inc_oper->n_type = ADD;
1145 do_inc_op:
1146 		if ((np = np->n_left)->n_type == INDEX)
1147 			np = exprreduce(np);
1148 		if (np->n_flags & FREAL)
1149 			tnp = realnode(np->n_real);
1150 		else
1151 			tnp = intnode(exprint(np));
1152 		inc_oper->n_left = np;
1153 		(void)assign(np, inc_oper);
1154 		return (tnp);
1155 
1156 	case PRE_DEC:
1157 		inc_oper->n_type = SUB;
1158 		goto do_pinc_op;
1159 	case PRE_INC:
1160 		inc_oper->n_type = ADD;
1161 do_pinc_op:
1162 		if ((np = np->n_left)->n_type == INDEX)
1163 			np = exprreduce(np);
1164 		inc_oper->n_left = np;
1165 		return (assign(np, inc_oper));
1166 
1167 	case AADD:
1168 		asn_oper->n_type = ADD;
1169 		goto do_asn_op;
1170 	case ASUB:
1171 		asn_oper->n_type = SUB;
1172 		goto do_asn_op;
1173 	case AMUL:
1174 		asn_oper->n_type = MUL;
1175 		goto do_asn_op;
1176 	case ADIV:
1177 		asn_oper->n_type = DIV;
1178 		goto do_asn_op;
1179 	case AREM:
1180 		asn_oper->n_type = REM;
1181 		goto do_asn_op;
1182 	case AEXP:
1183 		asn_oper->n_type = EXP;
1184 do_asn_op:
1185 		asn_oper->n_right = np->n_right;
1186 		if ((np = np->n_left)->n_type == INDEX)
1187 			np = exprreduce(np);
1188 		asn_oper->n_left = np;
1189 		return (assign(np, asn_oper));
1190 
1191 
1192 	case GETLINE:
1193 		return (f_getline(np));
1194 
1195 	case CALLFUNC:
1196 		return ((*np->n_left->n_function)(np->n_right));
1197 
1198 	case RE:
1199 		if (regmatch(np->n_regexp, linebuf) == REG_OK)
1200 			return (const1);
1201 		return (const0);
1202 
1203 	case TILDE:
1204 		cp = exprstring(np->n_left);
1205 		if (regmatch(getregexp(np->n_right), cp) == REG_OK)
1206 			return (const1);
1207 		return (const0);
1208 
1209 	case NRE:
1210 		cp = exprstring(np->n_left);
1211 		if (regmatch(getregexp(np->n_right), cp) != REG_OK)
1212 			return (const1);
1213 		return (const0);
1214 
1215 	case ASG:
1216 		return (assign(np->n_left, np->n_right));
1217 
1218 	case ARRAY:
1219 		awkerr(badarray, np->n_name);
1220 
1221 	case UFUNC:
1222 		awkerr(varnotfunc, np->n_name);
1223 
1224 	default:
1225 		awkerr(gettext("panic: exprreduce(%d)"), t);
1226 		/* NOTREACHED */
1227 	}
1228 }
1229 
1230 /*
1231  * Do arithmetic operators.
1232  */
1233 static NODE *
1234 arithmetic(NODE *np)
1235 {
1236 	register NODE *left, *right;
1237 	int type;
1238 	register INT i1, i2;
1239 	register INT iresult;
1240 	register REAL r1, r2;
1241 
1242 	left = exprreduce(np->n_left);
1243 	if (isreal(left->n_flags)
1244 	|| (isstring(left->n_flags) && (typeof(left)&FVREAL))) {
1245 		type = FREAL;
1246 		r1 = exprreal(left);
1247 		r2 = exprreal(np->n_right);
1248 	} else {
1249 		i1 = exprint(left);
1250 		right = exprreduce(np->n_right);
1251 		if (isreal(right->n_flags)
1252 		 || (isstring(right->n_flags) && (typeof(right)&FVREAL))) {
1253 
1254 			type = FREAL;
1255 			r1 = i1;
1256 			r2 = exprreal(right);
1257 		} else {
1258 			type = FINT;
1259 			i2 = exprint(right);
1260 		}
1261 	}
1262 reswitch:
1263 	switch (np->n_type) {
1264 	case ADD:
1265 		if (type == FINT) {
1266 			iresult = i1 + i2;
1267 			addoverflow();
1268 		} else
1269 			r1 += r2;
1270 		break;
1271 
1272 	/*
1273 	 * Strategically placed between ADD and SUB
1274 	 * so "jo" branches will reach on 80*86
1275 	 */
1276 	overflow:
1277 		r1 = i1;
1278 		r2 = i2;
1279 		type = FREAL;
1280 		goto reswitch;
1281 
1282 	case SUB:
1283 		if (type == FINT) {
1284 			iresult = i1 - i2;
1285 			suboverflow();
1286 		} else
1287 			r1 -= r2;
1288 		break;
1289 
1290 	case MUL:
1291 		if (type == FINT) {
1292 			iresult = i1 * i2;
1293 			muloverflow();
1294 		} else
1295 			r1 *= r2;
1296 		break;
1297 
1298 	case DIV:
1299 		if (type == FINT) {
1300 			r1 = i1;
1301 			r2 = i2;
1302 			type = FREAL;
1303 		}
1304 		if (r2 == 0.0)
1305 			awkerr(divzero);
1306 		r1 /= r2;
1307 		break;
1308 
1309 	case REM:
1310 		if (type == FINT) {
1311 			if (i2 == 0)
1312 				awkerr(divzero);
1313 			iresult = i1 % i2;
1314 		} else {
1315 			double fmod(double x, double y);
1316 
1317 			errno = 0;
1318 			r1 = fmod(r1, r2);
1319 			if (errno == EDOM)
1320 				awkerr(divzero);
1321 		}
1322 		break;
1323 	}
1324 	return (type==FINT ? intnode(iresult) : realnode(r1));
1325 }
1326 
1327 /*
1328  * Do comparison operators.
1329  */
1330 static NODE *
1331 comparison(NODE *np)
1332 {
1333 	register NODE *left, *right;
1334 	register int cmp;
1335 	int tl, tr;
1336 	register REAL r1, r2;
1337 	register INT i1, i2;
1338 
1339 	left = np->n_left;
1340 	if (isleaf(left->n_flags)) {
1341 		if (left->n_type == PARM)
1342 			left = left->n_next;
1343 	} else
1344 		left = exprreduce(left);
1345 	tl = left->n_flags;
1346 	right = np->n_right;
1347 	if (isleaf(right->n_flags)) {
1348 		if (right->n_type == PARM)
1349 			right = right->n_next;
1350 	} else {
1351 		++concflag;
1352 		right = exprreduce(right);
1353 		--concflag;
1354 	}
1355 	tr = right->n_flags;
1356 	/*
1357 	 * Posix mandates semantics for the comparison operators that
1358 	 * are incompatible with traditional AWK behaviour. If the following
1359 	 * define is true then awk will use the traditional behaviour.
1360 	 * if it's false, then AWK will use the POSIX-mandated behaviour.
1361 	 */
1362 #define	TRADITIONAL 0
1363 #if TRADITIONAL
1364 	if (!isnumber(tl) || !isnumber(tr)) {
1365 		cmp = wcscoll((wchar_t *)exprstring(left),
1366 		    (wchar_t *)exprstring(right));
1367 	} else if (isreal(tl) || isreal(tr)) {
1368 		r1 = exprreal(left);
1369 		r2 = exprreal(right);
1370 		if (r1 < r2)
1371 			cmp = -1;
1372 		else if (r1 > r2)
1373 			cmp = 1;
1374 		else
1375 			cmp = 0;
1376 	} else {
1377 		i1 = exprint(left);
1378 		i2 = exprint(right);
1379 		if (i1 < i2)
1380 			cmp = -1;
1381 		else if (i1 > i2)
1382 			cmp = 1;
1383 		else
1384 			cmp = 0;
1385 	}
1386 #else
1387 	if (!isnumber(tl) && !isnumber(tr)) {
1388 do_strcmp:
1389 		cmp = wcscoll((wchar_t *)exprstring(left),
1390 		    (wchar_t *)exprstring(right));
1391 	} else {
1392 		if (isstring(tl))
1393 			tl = typeof(left);
1394 		if (isstring(tr))
1395 			tr = typeof(right);
1396 		if (!isnumber(tl) || !isnumber(tr))
1397 			goto do_strcmp;
1398 		if (isreal(tl) || isreal(tr)) {
1399 			r1 = exprreal(left);
1400 			r2 = exprreal(right);
1401 			if (r1 < r2)
1402 				cmp = -1;
1403 			else if (r1 > r2)
1404 				cmp = 1;
1405 			else
1406 				cmp = 0;
1407 		} else {
1408 			i1 = exprint(left);
1409 			i2 = exprint(right);
1410 			if (i1 < i2)
1411 				cmp = -1;
1412 			else if (i1 > i2)
1413 				cmp = 1;
1414 			else
1415 				cmp = 0;
1416 		}
1417 	}
1418 #endif
1419 	switch (np->n_type) {
1420 	case EQ:
1421 		return (cmp==0 ? const1 : const0);
1422 
1423 	case  NE:
1424 		return (cmp!=0 ? const1 : const0);
1425 
1426 	case GE:
1427 		return (cmp>=0 ? const1 : const0);
1428 
1429 	case LE:
1430 		return (cmp<=0 ? const1 : const0);
1431 
1432 	case GT:
1433 		return (cmp>0 ? const1 : const0);
1434 
1435 	case LT:
1436 		return (cmp<0 ? const1 : const0);
1437 
1438 	default:
1439 		awkerr(interr, "comparison");
1440 	}
1441 	/* NOTREACHED */
1442 }
1443 
1444 /*
1445  * Return the type of a constant that is a string.
1446  * The node must be a FSTRING type and the return value
1447  * will possibly have FVINT or FVREAL or'ed in.
1448  */
1449 static int
1450 typeof(NODE *np)
1451 {
1452 	wchar_t *cp;
1453 	int somedigits = 0;
1454 	int seene = 0;
1455 	int seenradix = 0;
1456 	int seensign = 0;
1457 	int digitsaftere = 0;
1458 
1459 	cp = (wchar_t *)np->n_string;
1460 	if (*cp == '\0')
1461 		return (FSTRING|FVINT);
1462 	while (iswspace(*cp))
1463 		cp++;
1464 	if (*cp=='-' || *cp=='+')
1465 		cp++;
1466 	while (*cp != '\0') {
1467 		switch (*cp) {
1468 		case '0':
1469 		case '1':
1470 		case '2':
1471 		case '3':
1472 		case '4':
1473 		case '5':
1474 		case '6':
1475 		case '7':
1476 		case '8':
1477 		case '9':
1478 			if (seene)
1479 				digitsaftere = 1;
1480 			somedigits++;
1481 			break;
1482 
1483 		case 'E':
1484 		case 'e':
1485 			if (seene || !somedigits)
1486 				return (FSTRING);
1487 			seene = 1;
1488 			break;
1489 
1490 		case '+':
1491 		case '-':
1492 			if (seensign || !seene || digitsaftere)
1493 				return (FSTRING);
1494 			seensign = 1;
1495 			break;
1496 
1497 		default:
1498 			if (*cp == radixpoint) {
1499 				if (seenradix || seene || (!somedigits &&
1500 				    !iswdigit(*++cp)))
1501 					return (FSTRING);
1502 			} else
1503 				return (FSTRING);
1504 			seenradix = 1;
1505 		}
1506 		cp++;
1507 	}
1508 	if (somedigits == 0)
1509 		return (FSTRING);
1510 	if (somedigits >= MAXDIGINT || seenradix || seene) {
1511 		if (seensign && !digitsaftere)
1512 			return (FSTRING);
1513 		else
1514 			return (FSTRING|FVREAL);
1515 	} else
1516 		return (FSTRING|FVINT);
1517 }
1518 
1519 /*
1520  * Return a field rvalue.
1521  */
1522 static NODE *
1523 rfield(INT fieldno)
1524 {
1525 	register wchar_t *cp;
1526 
1527 	if (fieldno == 0)
1528 		return (stringnode(linebuf, FSTATIC|FSENSE, lbuflen));
1529 	if (!splitdone)
1530 		fieldsplit();
1531 	if (fieldno>nfield || fieldno<0)
1532 		return (stringnode(_null, FSTATIC, 0));
1533 	cp = fields[fieldno-1];
1534 	return (stringnode(cp, FSTATIC|FSENSE, wcslen(cp)));
1535 }
1536 
1537 /*
1538  * Split linebuf into fields.  Done only once
1539  * per input record (maximum).
1540  */
1541 void
1542 fieldsplit()
1543 {
1544 	register wchar_t *ip, *op;
1545 	register int n;
1546 	wchar_t *ep;
1547 
1548 	if (fieldbuf == NULL)
1549 		fieldbuf = emalloc(NLINE * sizeof(wchar_t));
1550 	fcount = 0;
1551 	ep = linebuf;
1552 	op = fieldbuf;
1553 	while ((ip = (*awkfield)(&ep)) != NULL) {
1554 		fields[fcount++] = op;
1555 		if (fcount > NFIELD)
1556 			awkerr(tmfld, NFIELD);
1557 		n = ep-ip;
1558 		(void) memcpy(op, ip, n * sizeof(wchar_t));
1559 		op += n;
1560 		*op++ = '\0';
1561 	}
1562 	if (varNF->n_flags & FINT)
1563 		varNF->n_int = fcount;
1564 	else {
1565 		constant->n_int = fcount;
1566 		(void)nassign(varNF, constant);
1567 	}
1568 	nfield = fcount;
1569 	splitdone++;
1570 }
1571 
1572 /*
1573  * Assign to a field as an lvalue.
1574  * Return the unevaluated node as one doesn't always need it
1575  * evaluated in an assignment.
1576  */
1577 static NODE *
1578 lfield(INT fieldno, NODE *np)
1579 {
1580 	register wchar_t *cp;
1581 	register wchar_t *op;
1582 	register wchar_t *sep;
1583 	register int i;
1584 	register wchar_t *newval;
1585 	register int seplen;
1586 	register int newlen;
1587 
1588 	newlen = wcslen(newval = (wchar_t *)exprstring(np));
1589 	if (fieldno == 0) {
1590 		splitdone = 0;
1591 		(void) memcpy(linebuf, newval, (newlen+1) * sizeof(wchar_t));
1592 		lbuflen = newlen;
1593 		fieldsplit();
1594 	} else {
1595 		seplen = wcslen(sep = (wchar_t *)exprstring(varOFS));
1596 		if (!splitdone)
1597 			fieldsplit();
1598 		if (--fieldno < nfield
1599 		 && (newlen <= wcslen(fields[fieldno]))) {
1600 			(void) memcpy(fields[fieldno], newval,
1601 				(newlen+1) * sizeof(wchar_t));
1602 		} else {
1603 			register wchar_t *buf;
1604 
1605 			buf = fieldbuf;
1606 			fieldbuf = emalloc(NLINE * sizeof(wchar_t));
1607 			if (fieldno >= nfield) {
1608 				if (fieldno >= NFIELD)
1609 					awkerr(tmfld, NFIELD);
1610 				while (nfield < fieldno)
1611 					fields[nfield++] = _null;
1612 				++nfield;
1613 			}
1614 			fields[fieldno] = newval;
1615 			op = fieldbuf;
1616 			for (i=0; i<nfield; i++) {
1617 				newlen = wcslen(cp = fields[i])+1;
1618 				fields[i] = op;
1619 				if (op+newlen >= fieldbuf+NLINE)
1620 					awkerr(toolong, NLINE);
1621 				(void) memcpy(op, cp, newlen * sizeof(wchar_t));
1622 				op += newlen;
1623 			}
1624 			free(buf);
1625 		}
1626 		/*
1627 		 * Reconstruct $0
1628 		 */
1629 		op = linebuf;
1630 		i = 0;
1631 		while (i < nfield) {
1632 			newlen = wcslen(cp = fields[i++]);
1633 			(void) memcpy(op, cp, newlen * sizeof(wchar_t));
1634 			op += newlen;
1635 			if (i < nfield) {
1636 				(void) memcpy(op, sep,
1637 					seplen * sizeof(wchar_t));
1638 				op += seplen;
1639 			}
1640 			if (op >= &linebuf[NLINE])
1641 				awkerr(toolong, NLINE);
1642 		}
1643 		*op = '\0';
1644 		lbuflen = op-linebuf;
1645 		if (varNF->n_flags & FINT)
1646 			varNF->n_int = nfield;
1647 		else {
1648 			constant->n_int = nfield;
1649 			(void)nassign(varNF, constant);
1650 		}
1651 	}
1652 	return (np);
1653 }
1654 
1655 /*
1656  * Do a user function.
1657  * Each formal parameter must:
1658  *	have the actual parameter assigned to it (call by value),
1659  *	have a pointer to an array put into it (call by reference),
1660  *	and be made undefined (extra formal parameters)
1661  */
1662 static NODE *
1663 userfunc(NODE *np)
1664 {
1665 	register NODE *temp;
1666 	NODE *fnp;
1667 
1668 	if ((fnp = np->n_left)==NNULL)
1669 		awkerr(gettext("impossible function call"));
1670 	if (fnp->n_type!=UFUNC)
1671 		awkerr(varnotfunc, fnp->n_name);
1672 
1673 #ifndef M_STKCHK
1674 	if (slevel >= NRECUR)
1675 		awkerr(gettext("function \"%S\" nesting level > %u"),
1676 		    fnp->n_name, NRECUR);
1677 #else
1678 	if (!M_STKCHK)
1679 		awkerr(gettext("function \"%s\" nesting level too deep"),
1680 		    fnp->n_name);
1681 #endif
1682 
1683 	fnp = fnp->n_ufunc;
1684 	{
1685 		register NODE *formal;
1686 		register NODE *actual;
1687 		NODE *formlist, *actlist, *templist, *temptail;
1688 
1689 		templist = temptail = NNULL;
1690 		actlist = np->n_right;
1691 		formlist = fnp->n_left;
1692 		/* pass through formal list, setting up a list
1693 		 * (on templist) containing temps for the values
1694 		 * of the actuals.
1695 		 * If the actual list runs out before the formal
1696 		 * list, assign 'constundef' as the value
1697 		 */
1698 		while ((formal = getlist(&formlist)) != NNULL) {
1699 			register NODE *array;
1700 			register int t;
1701 			register size_t len;
1702 			register int scope_tag;
1703 
1704 			actual = getlist(&actlist);
1705 			if (actual == NNULL) {
1706 				actual = constundef;
1707 				scope_tag = slevel+1;
1708 			} else
1709 				scope_tag = 0;
1710 			array = actual;
1711 			switch (actual->n_type) {
1712 			case ARRAY:
1713 				t = ARRAY;
1714 				scope_tag = 0;
1715 				break;
1716 
1717 			case PARM:
1718 				array = actual = actual->n_next;
1719 				t = actual->n_type;
1720 				scope_tag = actual->n_scope;
1721 				if (!(actual->n_flags & FLARRAY))
1722 					array = actual->n_alink;
1723 				break;
1724 
1725 			default:
1726 				t = VAR;
1727 				break;
1728 			}
1729 			temp = emptynode(t, len=wcslen(formal->n_name));
1730 			(void) memcpy(temp->n_name,formal->n_name,
1731 				(len+1) * sizeof(wchar_t));
1732 			temp->n_flags = FSTRING|FVINT;
1733 			temp->n_string = _null;
1734 			temp->n_strlen = 0;
1735 			if (t == VAR)
1736 				(void)assign(temp, actual);
1737 			if (t != ARRAY)
1738 				temp->n_flags |= FLARRAY;
1739 			temp->n_scope = scope_tag;
1740 			/*
1741 			 * link to actual parameter in case of promotion to
1742 			 * array
1743 			 */
1744 			if (actual != constundef)
1745 				temp->n_alink = actual;
1746 			/*
1747 			 * Build the templist
1748 			 */
1749 			if (templist != NNULL) {
1750 				temptail->n_next = temp;
1751 				temptail = temp;
1752 			} else
1753 				templist = temptail = temp;
1754 			temp->n_next = NNULL;
1755 			if (actual->n_type == CONSTANT)
1756 				temp->n_alink = temp;
1757 			else
1758 				temp->n_alink = array;
1759 		}
1760 		/*
1761 		 * Bind results of the evaluation of actuals to formals.
1762 		 */
1763 		formlist = fnp->n_left;
1764 		while (templist != NNULL) {
1765 			temp = templist;
1766 			templist = temp->n_next;
1767 			formal = getlist(&formlist);
1768 			temp->n_next = formal->n_next;
1769 			formal->n_next = temp;
1770 
1771 
1772 
1773 
1774 
1775 
1776 
1777 
1778 		}
1779 	}
1780 	{
1781 		register NODE *savenode = curnode;
1782 
1783 		++slevel;
1784 		if (action(fnp->n_right) == RETURN)
1785 			np = retval; else
1786 			np = const0;
1787 		curnode = savenode;
1788 	}
1789 	{
1790 		register NODE *formal;
1791 		NODE *formlist;
1792 
1793 		formlist = fnp->n_left;
1794 		while ((formal = getlist(&formlist)) != NNULL) {
1795 			temp = formal->n_next;
1796 			formal->n_next = temp->n_next;
1797 			/* if node is a local array, free the elements */
1798 			if (temp->n_type == ARRAY && (temp->n_scope == slevel))
1799 				delarray(temp);
1800 			freenode(temp);
1801 		}
1802 	}
1803 	--slevel;
1804 	return (np);
1805 }
1806 
1807 /*
1808  * Get the regular expression from an expression tree.
1809  */
1810 REGEXP
1811 getregexp(NODE *np)
1812 {
1813 	if (np->n_type == RE)
1814 		return (np->n_regexp);
1815 	np = renode((wchar_t *)exprstring(np));
1816 	return (np->n_regexp);
1817 }
1818 
1819 /*
1820  * Get the next element from a list.
1821  */
1822 NODE *
1823 getlist(NODE **npp)
1824 {
1825 	register NODE *np;
1826 
1827 	if ((np = *npp) == NNULL)
1828 		return (np);
1829 	if (np->n_type == COMMA) {
1830 		*npp = np->n_right;
1831 		return (np->n_left);
1832 	} else {
1833 		*npp = NNULL;
1834 		return (np);
1835 	}
1836 }
1837 
1838 /*
1839  * if statement.
1840  */
1841 static int
1842 s_if(NODE *np)
1843 {
1844 	register NODE *xp;
1845 	register int test;
1846 
1847 	test = exprtest(np->n_left);
1848 	xp = np->n_right;
1849 	if (xp->n_type != ELSE)
1850 		awkerr(interr, "if/else");
1851 	if (test)
1852 		xp = xp->n_left;
1853 	else
1854 		xp = xp->n_right;
1855 	return (action(xp));
1856 }
1857 
1858 /*
1859  * while and do{}while statements.
1860  */
1861 static int
1862 s_while(NODE *np)
1863 {
1864 	register int act = 0;
1865 
1866 	if (np->n_type == DO)
1867 		goto dowhile;
1868 	for (;;) {
1869 		if (exprtest(np->n_left) == 0)
1870 			break;
1871 	dowhile:
1872 		if ((act = action(np->n_right)) != 0) {
1873 			switch (act) {
1874 			case BREAK:
1875 				act = 0;
1876 				break;
1877 
1878 			case CONTINUE:
1879 				act = 0;
1880 				continue;
1881 			}
1882 			break;
1883 		}
1884 	}
1885 	return (act);
1886 }
1887 
1888 /*
1889  * for statement.
1890  */
1891 static int
1892 s_for(NODE *np)
1893 {
1894 	register NODE *testnp, *incnp, *initnp;
1895 	register int act = 0;
1896 	NODE *listp;
1897 
1898 	listp = np->n_left;
1899 	initnp = getlist(&listp);
1900 	testnp = getlist(&listp);
1901 	incnp = getlist(&listp);
1902 	if (initnp != NNULL)
1903 		(void)exprreduce(initnp);
1904 	for (;;) {
1905 		if (exprtest(testnp) == 0)
1906 			break;
1907 		if ((act = action(np->n_right)) != 0) {
1908 			switch (act) {
1909 			case BREAK:
1910 				act = 0;
1911 				break;
1912 
1913 			case CONTINUE:
1914 				act = 0;
1915 				goto clabel;
1916 			}
1917 			break;
1918 		}
1919 	clabel:
1920 		if (incnp != NNULL)
1921 			(void)exprreduce(incnp);
1922 	}
1923 	return (act);
1924 }
1925 
1926 /*
1927  * for variable in array statement.
1928  */
1929 static int
1930 s_forin(NODE *np)
1931 {
1932 	register NODE *left;
1933 	register int act = 0;
1934 	register NODE *var;
1935 	register NODE **nnp;
1936 	register NODE *statement;
1937 	register int issymtab = 0;
1938 	wchar_t *index;
1939 	register int alen;
1940 	int nbuck;
1941 
1942 	left = np->n_left;
1943 	statement = np->n_right;
1944 	if (left->n_type != IN)
1945 		awkerr(interr, "for (var in array)");
1946 	if ((var = left->n_left)->n_type == PARM)
1947 		var = var->n_next;
1948 	np = left->n_right;
1949 	if (np->n_type == PARM) {
1950 		np = np->n_next;
1951 		if (!(np->n_flags & FLARRAY))
1952 			np = np->n_alink;
1953 	}
1954 	if (np == varSYMTAB) {
1955 		issymtab++;
1956 		np = NNULL;
1957 		nbuck = 0;
1958 	} else {
1959 		/*l
1960 		 * At this point if the node is not actually an array
1961 		 * check to see if it has already been established as
1962 		 * a scalar. If it is a scalar then flag an error. If
1963 		 * not then promote the object to an array type.
1964 		 */
1965 		if (np->n_type != ARRAY) {
1966 			if (!isstring(np->n_flags) || np->n_string!=_null)
1967 				awkerr(notarray, np->n_name);
1968 			else {
1969 				/* promotion to array */
1970 				promote(np);
1971 				if (np->n_alink != NNULL)
1972 					if (!(np->n_flags & FLARRAY))
1973 						np = np->n_alink;
1974 			}
1975 		}
1976 		/*
1977 		 * Set up a pointer to the first node in the array list.
1978 		 * Save this pointer on the delete stack. This information
1979 		 * is used by the delete function to advance any pointers
1980 		 * that might be pointing at a node which has been deleted.
1981 		 * See the delsymtab() function for more information. Note
1982 		 * that if the a_link field is nil, then just return 0 since
1983 		 * this array has no elements yet.
1984 		 */
1985 		if ((*(nnp = next_forin) = np->n_alink) == 0)
1986 			return (0);
1987 		if (++next_forin > &forindex[NFORINLOOP])
1988 			awkerr(toodeep, NFORINLOOP);
1989 		/*
1990 		 * array elements have names of the form
1991 		 *	<name>]<index> (global arrays)
1992 		 * or
1993 		 *	<name>[<scope>]<index> (local arrays)
1994 		 * We need to know the offset of the index portion of the
1995 		 * name string in order to place it in the index variable so
1996 		 * we look for the ']'. This is calculated here and then
1997 		 * used below.
1998 		 */
1999 		for (alen = 0; (*nnp)->n_name[alen++] != ']'; )
2000 			if ((*nnp)->n_name[alen] == '\0')
2001 				awkerr(interr, "for: invalid array");
2002 	}
2003 	for (;;) {
2004 		if (issymtab) {
2005 			if ((left = symwalk(&nbuck, &np)) == NNULL)
2006 				break;
2007 			index = left->n_name;
2008 		} else {
2009 			if ((np = *nnp) == NNULL)
2010 				break;
2011 			index = np->n_name+alen;
2012 			*nnp = np->n_alink;
2013 		}
2014 		strassign(var, index, FSTATIC, wcslen(index));
2015 		if ((act = action(statement)) != 0) {
2016 			switch (act) {
2017 			case BREAK:
2018 				act = 0;
2019 				break;
2020 
2021 			case CONTINUE:
2022 				act = 0;
2023 				continue;
2024 			}
2025 			break;
2026 		}
2027 	}
2028 	next_forin--;
2029 	return (act);
2030 }
2031 
2032 /*
2033  * Walk the symbol table using the same algorithm as arraynode.
2034  */
2035 NODE *
2036 symwalk(int *buckp, NODE **npp)
2037 {
2038 	register NODE *np;
2039 
2040 	np = *npp;
2041 	for (;;) {
2042 		while (np == NNULL) {
2043 			if (*buckp >= NBUCKET)
2044 				return (*npp = NNULL);
2045 			np = symtab[(*buckp)++];
2046 		}
2047 		if (np->n_type == VAR
2048 		 && (!isstring(np->n_flags) || np->n_string!=_null)) {
2049 			*npp = np->n_next;
2050 			return (np);
2051 		}
2052 		np = np->n_next;
2053 	}
2054 	/* NOTREACHED */
2055 }
2056 
2057 /*
2058  * Test the result of an expression.
2059  */
2060 static int
2061 exprtest(NODE *np)
2062 {
2063 	register int t;
2064 
2065 	if (np == NNULL)
2066 		return (1);
2067 	if (freelist != NNULL)
2068 		freetemps();
2069 	np = exprreduce(np);
2070 	if (isint(t = np->n_flags)) {
2071 		if (isstring(t))
2072 			return (exprint(np) != 0);
2073 		return (np->n_int != 0);
2074 	}
2075 	if (isreal(t)) {
2076 		REAL rval;
2077 
2078 		rval = isstring(t) ? exprreal(np) : np->n_real;
2079 		return (rval != 0.0);
2080 	}
2081 	return (*(wchar_t *)exprstring(np) != '\0');
2082 }
2083 
2084 /*
2085  * Return malloc'ed space that holds the given name "[" scope "]" index ...
2086  * concatenated string.
2087  * The node (np) is the list of indices and 'array' is the array name.
2088  */
2089 static wchar_t *
2090 makeindex(NODE *np, wchar_t *array, int tag)
2091 {
2092 	static wchar_t tags[sizeof(int)];
2093 	static wchar_t tag_chars[] = M_MB_L("0123456789ABCDEF");
2094 	register wchar_t *cp;
2095 	register NODE *index;
2096 	register uint n;
2097 	register int len;
2098 	register wchar_t *indstr;
2099 	register wchar_t *sep;
2100 	register int seplen;
2101 	register int taglen;
2102 
2103 
2104 	/*
2105 	 * calculate and create the tag string
2106 	 */
2107 	for (taglen = 0; tag; tag >>= 4)
2108 		tags[taglen++] = tag_chars[tag & 0xf];
2109 	/*
2110 	 * Special (normal) case: only one index.
2111 	 */
2112 	if (np->n_type != COMMA) {
2113 		wchar_t *ocp;
2114 		size_t i;
2115 
2116 		if (isleaf(np->n_flags) && np->n_type==PARM)
2117 			np = np->n_next;
2118 		if (isstring(np->n_flags)) {
2119 			indstr = np->n_string;
2120 			len = np->n_strlen;
2121 		} else {
2122 			indstr = exprstring(np);
2123 			len = wcslen(indstr);
2124 		}
2125 		i = (n = wcslen(array)) + len + 3 + taglen;
2126 		if (i < NINDEXBUF)
2127 			ocp = indexbuf;
2128 		else
2129 			ocp = emalloc(i * sizeof(wchar_t));
2130 		(void) memcpy(ocp, array, n * sizeof(wchar_t));
2131 		cp = ocp+n;
2132 		if (taglen) {
2133 			*cp++ = '[';
2134 			while (taglen)
2135 				*cp++ = tags[--taglen];
2136 		}
2137 		*cp++ = ']';
2138 		(void) memcpy(cp, indstr, (len+1) * sizeof(wchar_t));
2139 
2140 		return (ocp);
2141 	}
2142 	n = 0;
2143 	seplen = wcslen(sep = (wchar_t *)exprstring(varSUBSEP));
2144 	while ((index = getlist(&np)) != NNULL) {
2145 		indstr = exprstring(index);
2146 		len = wcslen(indstr);
2147 		if (n == 0) {
2148 			cp = emalloc(sizeof(wchar_t) * ((n = wcslen(array)) +
2149 				len + 3 + taglen));
2150 			(void) memcpy(cp, array, n * sizeof(wchar_t));
2151 			if (taglen) {
2152 				cp[n++] = '[';
2153 				while (taglen)
2154 					cp[n++] = tags[--taglen];
2155 			}
2156 			cp[n++] = ']';
2157 		} else {
2158 			cp = erealloc(cp, (n+len+seplen+1) * sizeof(wchar_t));
2159 			(void) memcpy(cp+n, sep, seplen * sizeof(wchar_t));
2160 			n += seplen;
2161 		}
2162 		(void) memcpy(cp+n, indstr, (len+1) * sizeof(wchar_t));
2163 		n += len;
2164 	}
2165 	return (cp);
2166 }
2167 
2168 
2169 /*
2170  * Promote a node to an array. In the simplest case, just set the
2171  * node type field to ARRAY. The more complicated case involves walking
2172  * a list of variables that haven't been determined yet as scalar or array.
2173  * This routine plays with the pointers to avoid recursion.
2174  */
2175 void
2176 promote(NODE *n)
2177 {
2178 	register NODE *prev = NNULL;
2179 	register NODE *next;
2180 
2181 	/*
2182 	 * walk down the variable chain, reversing the pointers and
2183 	 * setting each node to type array.
2184 	 */
2185 	while ((n->n_flags & FLARRAY) && (n->n_alink != n)) {
2186 		n->n_type = ARRAY;
2187 		next = n->n_alink;
2188 		n->n_alink = prev;
2189 		prev = n;
2190 		n = next;
2191 	}
2192 
2193 	/*
2194 	 * If the final entity on the chain is a local variable, then
2195 	 * reset it's alink field to NNULL - normally it points back
2196 	 * to itself - this is used in other parts of the code to
2197 	 * reduce the number of conditionals when handling locals.
2198 	 */
2199 	n->n_type = ARRAY;
2200 	if (n->n_flags & FLARRAY)
2201 		n->n_alink = NNULL;
2202 
2203 	/*
2204 	 * Now walk back up the list setting the alink to point to
2205 	 * the last entry in the chain and clear the 'local array'
2206 	 * flag.
2207 	 */
2208 	while (prev != NNULL) {
2209 		prev->n_flags &= ~FLARRAY;
2210 		next=prev->n_alink;
2211 		prev->n_alink = n;
2212 		prev=next;
2213 	}
2214 }
2215