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