1 /*
2  * awk.h -- Definitions for gawk.
3  */
4 
5 /*
6  * Copyright (C) 1986, 1988, 1989, 1991-2021 the Free Software Foundation, Inc.
7  *
8  * This file is part of GAWK, the GNU implementation of the
9  * AWK Programming Language.
10  *
11  * GAWK is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * GAWK is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
24  */
25 
26 /* ------------------------------ Includes ------------------------------ */
27 
28 /*
29  * config.h absolutely, positively, *M*U*S*T* be included before
30  * any system headers.  Otherwise, extreme death, destruction
31  * and loss of life results.
32  */
33 #if defined(_TANDEM_SOURCE)
34 /*
35  * config.h forces this even on non-tandem systems but it
36  * causes problems elsewhere if used in the check below.
37  * so workaround it. bleah.
38  */
39 #define tandem_for_real	1
40 #endif
41 
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45 
46 #if defined(tandem_for_real) && ! defined(_SCO_DS)
47 #define _XOPEN_SOURCE_EXTENDED 1
48 #endif
49 
50 #include <stdio.h>
51 #include <assert.h>
52 #include <limits.h>
53 #include <ctype.h>
54 #include <setjmp.h>
55 #include <math.h>
56 
57 #include "gettext.h"
58 #define _(msgid)  gettext(msgid)
59 #define N_(msgid) msgid
60 
61 #if ! (defined(HAVE_LIBINTL_H) && defined(ENABLE_NLS) && ENABLE_NLS > 0)
62 #ifndef LOCALEDIR
63 #define LOCALEDIR NULL
64 #endif /* LOCALEDIR */
65 #endif
66 
67 #if !defined(__SUNPRO_C)
68 #if !defined(__STDC__) || __STDC__ < 1
69 #error "gawk no longer supports non-C89 environments (no __STDC__ or __STDC__ < 1)"
70 #endif
71 #endif
72 
73 #include <stdarg.h>
74 #include <stdbool.h>
75 #include <signal.h>
76 #include <time.h>
77 #include <errno.h>
78 #if ! defined(errno)
79 extern int errno;
80 #endif
81 
82 #ifdef STDC_HEADERS
83 #include <stdlib.h>
84 #endif	/* not STDC_HEADERS */
85 
86 
87 /* We can handle multibyte strings.  */
88 #include <wchar.h>
89 #include <wctype.h>
90 
91 #ifdef STDC_HEADERS
92 #include <float.h>
93 #endif
94 
95 #undef CHARBITS
96 #undef INTBITS
97 
98 #if HAVE_INTTYPES_H
99 # include <inttypes.h>
100 #endif
101 #if HAVE_STDINT_H
102 # include <stdint.h>
103 #endif
104 
105 /* ----------------- System dependencies (with more includes) -----------*/
106 
107 /* This section is the messiest one in the file, not a lot that can be done */
108 
109 #ifndef VMS
110 #ifdef HAVE_FCNTL_H
111 #include <fcntl.h>
112 #endif
113 #include <sys/types.h>
114 #include <sys/stat.h>
115 #else	/* VMS */
116 #include <stddef.h>
117 #include <stat.h>
118 #include <file.h>	/* avoid <fcntl.h> in io.c */
119 /* debug.c needs this; when _DECC_V4_SOURCE is defined (as it is
120    in our config.h [vms/vms-conf.h]), off_t won't get declared */
121 # if !defined(__OFF_T) && !defined(_OFF_T)
122 #  if defined(____OFF_T) || defined(___OFF_T)
123 typedef __off_t off_t;	/* __off_t is either int or __int64 */
124 #  else
125 typedef int off_t;
126 #  endif
127 # endif
128 #endif	/* VMS */
129 
130 #include "protos.h"
131 
132 #ifdef HAVE_STRING_H
133 #include <string.h>
134 #ifdef NEED_MEMORY_H
135 #include <memory.h>
136 #endif	/* NEED_MEMORY_H */
137 #endif /* HAVE_STRING_H */
138 #ifdef HAVE_STRINGS_H
139 #include <strings.h>
140 #endif	/* HAVE_STRINGS_H */
141 
142 #if HAVE_UNISTD_H
143 #include <unistd.h>
144 #endif	/* HAVE_UNISTD_H */
145 
146 #ifdef VMS
147 #include <unixlib.h>
148 #include "vms/redirect.h"
149 #endif  /*VMS*/
150 
151 #ifndef O_BINARY
152 #define O_BINARY	0
153 #endif
154 
155 #ifndef HAVE_SETLOCALE
156 #define setlocale(locale, val)	/* nothing */
157 #endif /* HAVE_SETLOCALE */
158 
159 #if HAVE_MEMCPY_ULONG
160 extern char *memcpy_ulong(char *dest, const char *src, unsigned long l);
161 #define memcpy memcpy_ulong
162 #endif
163 #if HAVE_MEMSET_ULONG
164 extern void *memset_ulong(void *dest, int val, unsigned long l);
165 #define memset memset_ulong
166 #endif
167 
168 #ifdef HAVE_FWRITE_UNLOCKED
169 #define fwrite	fwrite_unlocked
170 #endif /* HAVE_FWRITE_UNLOCKED */
171 
172 #if defined(__DJGPP__) || defined(__EMX__) || defined(__MINGW32__)
173 #include "nonposix.h"
174 #endif /* defined(__DJGPP__) || defined(__EMX__) || defined(__MINGW32__) */
175 
176 /* use this as lintwarn("...")
177    this is a hack but it gives us the right semantics */
178 #define lintwarn (*(set_loc(__FILE__, __LINE__),lintfunc))
179 /* same thing for warning */
180 #define warning (*(set_loc(__FILE__, __LINE__),r_warning))
181 
182 #ifdef HAVE_MPFR
183 #include <gmp.h>
184 #include <mpfr.h>
185 #ifndef MPFR_RNDN
186 /* for compatibility with MPFR 2.X */
187 #define MPFR_RNDN GMP_RNDN
188 #define MPFR_RNDZ GMP_RNDZ
189 #define MPFR_RNDU GMP_RNDU
190 #define MPFR_RNDD GMP_RNDD
191 #endif
192 #endif
193 
194 #include "regex.h"
195 #include "dfa.h"
196 typedef struct Regexp {
197 	struct re_pattern_buffer pat;
198 	struct re_registers regs;
199 	struct dfa *dfareg;
200 	bool has_meta;		/* re has meta chars so (probably) isn't simple string */
201 	bool maybe_long;	/* re has meta chars that can match long text */
202 } Regexp;
203 #define	RESTART(rp,s)	(rp)->regs.start[0]
204 #define	REEND(rp,s)	(rp)->regs.end[0]
205 #define	SUBPATSTART(rp,s,n)	(rp)->regs.start[n]
206 #define	SUBPATEND(rp,s,n)	(rp)->regs.end[n]
207 #define	NUMSUBPATS(rp,s)	(rp)->regs.num_regs
208 
209 /* regexp matching flags: */
210 #define RE_NO_FLAGS	0	/* empty flags */
211 #define RE_NEED_START	1	/* need to know start/end of match */
212 #define RE_NO_BOL	2	/* not allowed to match ^ in regexp */
213 
214 #include "gawkapi.h"
215 
216 /* Stuff for losing systems. */
217 #if !defined(HAVE_STRTOD)
218 extern double gawk_strtod();
219 #define strtod gawk_strtod
220 #endif
221 
222 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
223 # define __attribute__(arg)
224 #endif
225 
226 #ifndef ATTRIBUTE_UNUSED
227 #define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
228 #endif /* ATTRIBUTE_UNUSED */
229 
230 #ifndef ATTRIBUTE_NORETURN
231 #define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
232 #endif /* ATTRIBUTE_NORETURN */
233 
234 #ifndef ATTRIBUTE_PRINTF
235 #define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
236 #define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
237 #define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3)
238 #endif /* ATTRIBUTE_PRINTF */
239 
240 /* ------------------ Constants, Structures, Typedefs  ------------------ */
241 
242 #define AWKNUM	double
243 
244 enum defrule { BEGIN = 1, Rule, END, BEGINFILE, ENDFILE,
245 	MAXRULE /* sentinel, not legal */ };
246 extern const char *const ruletab[];
247 
248 
249 typedef enum nodevals {
250 	/* illegal entry == 0 */
251 	Node_illegal,
252 
253 	Node_val,		/* node is a value - type in flags */
254 	Node_regex,		/* a regexp, text, compiled, flags, etc */
255 	Node_dynregex,		/* a dynamic regexp */
256 
257 	/* symbol table values */
258 	Node_var,		/* scalar variable, lnode is value */
259 	Node_var_array,		/* array is ptr to elements, table_size num of eles */
260 	Node_var_new,		/* newly created variable, may become an array */
261 	Node_param_list,	/* lnode is a variable, rnode is more list */
262 	Node_func,		/* lnode is param. list, rnode is body */
263 	Node_ext_func,		/* extension function, code_ptr is builtin code */
264 	Node_builtin_func,	/* built-in function, main use is for FUNCTAB */
265 
266 	Node_array_ref,		/* array passed by ref as parameter */
267 	Node_array_tree,	/* Hashed array tree (HAT) */
268 	Node_array_leaf,	/* Linear 1-D array */
269 	Node_dump_array,	/* array info */
270 
271 	/* program execution -- stack item types */
272 	Node_arrayfor,
273 	Node_frame,
274 	Node_instruction,
275 
276 	Node_final		/* sentry value, not legal */
277 } NODETYPE;
278 
279 struct exp_node;
280 
281 typedef union bucket_item {
282 	struct {
283 		union bucket_item *next;
284 		char *str;
285 		size_t len;
286 		size_t code;
287 		struct exp_node *name;
288 		struct exp_node *val;
289 	} hs;
290 	struct {
291 		union bucket_item *next;
292 		long li[2];
293 		struct exp_node *val[2];
294 		size_t cnt;
295 	} hi;
296 } BUCKET;
297 
298 enum commenttype {
299 	EOL_COMMENT = 1,
300 	BLOCK_COMMENT,
301 	FOR_COMMENT	// special case
302 };
303 
304 /* string hash table */
305 #define ahnext		hs.next
306 #define	ahname		hs.name	/* a string index node */
307 #define	ahname_str	hs.str	/* shallow copy; = ahname->stptr */
308 #define	ahname_len	hs.len	/* = ahname->stlen */
309 #define	ahvalue		hs.val
310 #define	ahcode		hs.code
311 
312 /* integer hash table */
313 #define	ainext		hi.next
314 #define ainum		hi.li	/* integer indices */
315 #define aivalue		hi.val
316 #define aicount		hi.cnt
317 
318 struct exp_instruction;
319 
320 typedef int (*Func_print)(FILE *, const char *, ...);
321 typedef struct exp_node **(*afunc_t)(struct exp_node *, struct exp_node *);
322 typedef struct {
323 	const char *name;
324 	afunc_t init;
325 	afunc_t type_of;	/* avoid reserved word typeof */
326 	afunc_t lookup;
327 	afunc_t exists;
328 	afunc_t clear;
329 	afunc_t remove;
330 	afunc_t list;
331 	afunc_t copy;
332 	afunc_t dump;
333 	afunc_t store;
334 } array_funcs_t;
335 
336 /*
337  * NOTE - this struct is a rather kludgey -- it is packed to minimize
338  * space usage, at the expense of cleanliness.  Alter at own risk.
339  */
340 typedef struct exp_node {
341 	union {
342 		struct {
343 			union {
344 				struct exp_node *lptr;
345 				struct exp_instruction *li;
346 				long ll;
347 				const array_funcs_t *lp;
348 			} l;
349 			union {
350 				struct exp_node *rptr;
351 				Regexp *preg[2];
352 				struct exp_node **av;
353 				BUCKET **bv;
354 				void (*uptr)(void);
355 				struct exp_instruction *iptr;
356 			} r;
357 			union {
358 				struct exp_node *extra;
359 				void (*aptr)(void);
360 				long xl;
361 				void *cmnt;	// used by pretty printer
362 			} x;
363 			char *name;
364 			size_t reserved;
365 			struct exp_node *rn;
366 			unsigned long cnt;
367 			enum reflagvals {
368 				CONSTANT = 1,
369 				FS_DFLT  = 2,
370 			} reflags;
371 		} nodep;
372 
373 		struct {
374 #ifdef HAVE_MPFR
375 			union {
376 				AWKNUM fltnum;
377 				mpfr_t mpnum;
378 				mpz_t mpi;
379 			} nm;
380 			int rndmode;
381 #else
382 			AWKNUM fltnum;
383 #endif
384 			char *sp;
385 			size_t slen;
386 			int idx;
387 			wchar_t *wsp;
388 			size_t wslen;
389 			struct exp_node *typre;
390 			enum commenttype comtype;
391 		} val;
392 	} sub;
393 	NODETYPE type;
394 	enum flagvals {
395 	/* type = Node_val */
396 		/*
397 		 * STRING and NUMBER are mutually exclusive, except for the special
398 		 * case of an uninitialized value, represented internally by
399 		 * Nnull_string. They represent the type of a value as assigned.
400 		 * Nnull_string has both STRING and NUMBER attributes, but all other
401 		 * scalar values should have precisely one of these bits set.
402 		 *
403 		 * STRCUR and NUMCUR are not mutually exclusive. They represent that
404 		 * the particular type of value is up to date.  For example,
405 		 *
406 		 * 	a = 5		# NUMBER | NUMCUR
407 		 * 	b = a ""	# Adds STRCUR to a, since a string value
408 		 * 			# is now available. But the type hasn't changed!
409 		 *
410 		 * 	a = "42"	# STRING | STRCUR
411 		 * 	b = a + 0	# Adds NUMCUR to a, since numeric value
412 		 * 			# is now available. But the type hasn't changed!
413 		 *
414 		 * USER_INPUT is the joker.  When STRING|USER_INPUT is set, it means
415 		 * "this is string data, but the user may have really wanted it to be a
416 		 * number. If we have to guess, like in a comparison, turn it into a
417 		 * number if the string is indeed numeric."
418 		 * For example,    gawk -v a=42 ....
419 		 * Here, `a' gets STRING|STRCUR|USER_INPUT and then when used where
420 		 * a number is needed, it gets turned into a NUMBER and STRING
421 		 * is cleared. In that case, we leave the USER_INPUT in place, so
422 		 * the combination NUMBER|USER_INPUT means it is a strnum a.k.a. a
423 		 * "numeric string".
424 		 *
425 		 * WSTRCUR is for efficiency. If in a multibyte locale, and we
426 		 * need to do something character based (substr, length, etc.)
427 		 * we create the corresponding wide character string and store it,
428 		 * and add WSTRCUR to the flags so that we don't have to do the
429 		 * conversion more than once.
430 		 *
431 		 * The NUMINT flag may be used with a value of any type -- NUMBER,
432 		 * STRING, or STRNUM. It indicates that the string representation
433 		 * equals the result of sprintf("%ld", <numeric value>). So, for
434 		 * example, NUMINT should NOT be set if it's a strnum or string value
435 		 * where the string is " 1" or "01" or "+1" or "1.0" or "0.1E1". This
436 		 * is a hint to indicate that an integer array optimization may be
437 		 * used when this value appears as a subscript.
438 		 *
439 		 * We hope that the rest of the flags are self-explanatory. :-)
440 		 */
441 		MALLOC	= 0x0001,       /* stptr can be free'd, i.e. not a field node pointing into a shared buffer */
442 		STRING	= 0x0002,       /* assigned as string */
443 		STRCUR	= 0x0004,       /* string value is current */
444 		NUMCUR	= 0x0008,       /* numeric value is current */
445 		NUMBER	= 0x0010,       /* assigned as number */
446 		USER_INPUT = 0x0020,    /* user input: if NUMERIC then
447 					 * a NUMBER */
448 		INTLSTR	= 0x0040,       /* use localized version */
449 		NUMINT	= 0x0080,       /* numeric value is an integer */
450 		INTIND	= 0x0100,	/* integral value is array index;
451 					 * lazy conversion to string.
452 					 */
453 		WSTRCUR	= 0x0200,       /* wide str value is current */
454 		MPFN	= 0x0400,       /* arbitrary-precision floating-point number */
455 		MPZN	= 0x0800,       /* arbitrary-precision integer */
456 		NO_EXT_SET = 0x1000,    /* extension cannot set a value for this variable */
457 		NULL_FIELD = 0x2000,    /* this is the null field */
458 
459 	/* type = Node_var_array */
460 		ARRAYMAXED	= 0x4000,       /* array is at max size */
461 		HALFHAT		= 0x8000,       /* half-capacity Hashed Array Tree;
462 						 * See cint_array.c */
463 		XARRAY		= 0x10000,
464 		NUMCONSTSTR	= 0x20000,	/* have string value for numeric constant */
465 		REGEX           = 0x40000,	/* this is a typed regex */
466 	} flags;
467 	long valref;
468 } NODE;
469 
470 #define vname sub.nodep.name
471 
472 #define lnode	sub.nodep.l.lptr
473 #define rnode	sub.nodep.r.rptr
474 
475 /* Node_param_list */
476 #define param      vname
477 #define dup_ent    sub.nodep.r.rptr
478 
479 /* Node_param_list, Node_func */
480 #define param_cnt  sub.nodep.l.ll
481 
482 /* Node_func */
483 #define fparms		sub.nodep.rn
484 #define code_ptr    sub.nodep.r.iptr
485 
486 /* Node_regex, Node_dynregex */
487 #define re_reg	sub.nodep.r.preg
488 #define re_flags sub.nodep.reflags
489 #define re_text lnode
490 #define re_exp	sub.nodep.x.extra
491 #define re_cnt	flags
492 
493 /* Node_val */
494 /*
495  * Note that the string in stptr may not be NUL-terminated, but it is
496  * guaranteed to have at least one extra byte that may be temporarily set
497  * to '\0'. This is helpful when calling functions such as strtod that require
498  * a NUL-terminated argument. In particular, field values $n for n > 0 and
499  * n < NF will not have a NUL terminator, since they point into the $0 buffer.
500  * All other strings are NUL-terminated.
501  */
502 #define stptr	sub.val.sp
503 #define stlen	sub.val.slen
504 #define stfmt	sub.val.idx
505 #define strndmode sub.val.rndmode
506 #define wstptr	sub.val.wsp
507 #define wstlen	sub.val.wslen
508 #ifdef HAVE_MPFR
509 #define mpg_numbr	sub.val.nm.mpnum
510 #define mpg_i		sub.val.nm.mpi
511 #define numbr		sub.val.nm.fltnum
512 #else
513 #define numbr		sub.val.fltnum
514 #endif
515 #define typed_re	sub.val.typre
516 
517 /*
518  * If stfmt is set to STFMT_UNUSED, it means that the string representation
519  * stored in stptr is not a function of the value of CONVFMT or OFMT. That
520  * indicates that either the string value was explicitly assigned, or it
521  * was converted from a NUMBER that has an integer value. When stfmt is not
522  * set to STFMT_UNUSED, it is an offset into the fmt_list array of distinct
523  * CONVFMT and OFMT node pointers.
524  */
525 #define STFMT_UNUSED	-1
526 
527 /* Node_arrayfor */
528 #define for_list	sub.nodep.r.av
529 #define for_list_size	sub.nodep.reflags
530 #define cur_idx		sub.nodep.l.ll
531 #define for_array 	sub.nodep.rn
532 
533 /* Node_frame: */
534 #define stack        sub.nodep.r.av
535 #define func_node    sub.nodep.x.extra
536 #define prev_frame_size	sub.nodep.reflags
537 #define reti         sub.nodep.l.li
538 
539 /* Node_var: */
540 #define var_value    lnode
541 #define var_update   sub.nodep.r.uptr
542 #define var_assign   sub.nodep.x.aptr
543 
544 /* Node_var_array: */
545 #define buckets		sub.nodep.r.bv
546 #define nodes		sub.nodep.r.av
547 #define array_funcs	sub.nodep.l.lp
548 #define array_base	sub.nodep.l.ll
549 #define table_size	sub.nodep.reflags
550 #define array_size	sub.nodep.cnt
551 #define array_capacity	sub.nodep.reserved
552 #define xarray		sub.nodep.rn
553 #define parent_array	sub.nodep.x.extra
554 
555 #define ainit		array_funcs->init
556 #define atypeof		array_funcs->type_of
557 #define alookup 	array_funcs->lookup
558 #define aexists 	array_funcs->exists
559 #define aclear		array_funcs->clear
560 #define aremove		array_funcs->remove
561 #define alist		array_funcs->list
562 #define acopy		array_funcs->copy
563 #define adump		array_funcs->dump
564 #define astore		array_funcs->store
565 
566 /* Node_array_ref: */
567 #define orig_array lnode
568 #define prev_array rnode
569 
570 /* Node_array_print */
571 #define adepth     sub.nodep.l.ll
572 #define alevel     sub.nodep.x.xl
573 
574 /* Op_comment	*/
575 #define comment_type	sub.val.comtype
576 
577 /* --------------------------------lint warning types----------------------------*/
578 typedef enum lintvals {
579 	LINT_illegal,
580 	LINT_assign_in_cond,
581 	LINT_no_effect
582 } LINTTYPE;
583 
584 /* --------------------------------Instruction ---------------------------------- */
585 
586 typedef enum opcodeval {
587 	Op_illegal = 0,		/* illegal entry */
588 
589 	/* binary operators */
590 	Op_times,
591 	Op_times_i,
592 	Op_quotient,
593 	Op_quotient_i,
594 	Op_mod,
595 	Op_mod_i,
596 	Op_plus,
597 	Op_plus_i,
598 	Op_minus,
599 	Op_minus_i,
600 	Op_exp,
601 	Op_exp_i,
602 	Op_concat,
603 
604 	/* line range instruction pair */
605 	Op_line_range,		/* flags for Op_cond_pair */
606 	Op_cond_pair,		/* conditional pair */
607 
608 	Op_subscript,
609 	Op_sub_array,
610 
611 	/* unary operators */
612 	Op_preincrement,
613 	Op_predecrement,
614 	Op_postincrement,
615 	Op_postdecrement,
616 	Op_unary_minus,
617 	Op_unary_plus,
618 	Op_field_spec,
619 
620 	/* unary relationals */
621 	Op_not,
622 
623 	/* assignments */
624 	Op_assign,
625 	Op_store_var,		/* simple variable assignment optimization */
626 	Op_store_sub,		/* array[subscript] assignment optimization */
627 	Op_store_field,  	/* $n assignment optimization */
628 	Op_assign_times,
629 	Op_assign_quotient,
630 	Op_assign_mod,
631 	Op_assign_plus,
632 	Op_assign_minus,
633 	Op_assign_exp,
634 	Op_assign_concat,
635 
636 	/* boolean binaries */
637 	Op_and,			/* a left subexpression in && */
638 	Op_and_final,		/* right subexpression of && */
639 	Op_or,
640 	Op_or_final,
641 
642 	/* binary relationals */
643 	Op_equal,
644 	Op_notequal,
645 	Op_less,
646 	Op_greater,
647 	Op_leq,
648 	Op_geq,
649 	Op_match,
650 	Op_match_rec,		/* match $0 */
651 	Op_nomatch,
652 
653 	Op_rule,
654 
655 	/* keywords */
656 	Op_K_case,
657 	Op_K_default,
658 	Op_K_break,
659 	Op_K_continue,
660 	Op_K_print,
661 	Op_K_print_rec,
662 	Op_K_printf,
663 	Op_K_next,
664 	Op_K_exit,
665 	Op_K_return,
666 	Op_K_return_from_eval,
667 	Op_K_delete,
668 	Op_K_delete_loop,
669 	Op_K_getline_redir,
670 	Op_K_getline,
671 	Op_K_nextfile,
672 	Op_K_namespace,
673 
674 	Op_builtin,
675 	Op_sub_builtin,		/* sub, gsub and gensub */
676 	Op_ext_builtin,
677 	Op_in_array,		/* boolean test of membership in array */
678 
679 	/* function call instruction */
680 	Op_func_call,
681 	Op_indirect_func_call,
682 
683 	Op_push,		/* scalar variable */
684 	Op_push_arg,		/* variable type (scalar or array) argument to built-in */
685 	Op_push_arg_untyped,	/* like Op_push_arg, but for typeof */
686 	Op_push_i,		/* number, string */
687 	Op_push_re,		/* regex */
688 	Op_push_array,
689 	Op_push_param,
690 	Op_push_lhs,
691 	Op_subscript_lhs,
692 	Op_field_spec_lhs,
693 	Op_no_op,		/* jump target */
694 	Op_pop,			/* pop an item from the runtime stack */
695 	Op_jmp,
696 	Op_jmp_true,
697 	Op_jmp_false,
698 	Op_get_record,
699 	Op_newfile,
700 	Op_arrayfor_init,
701 	Op_arrayfor_incr,
702 	Op_arrayfor_final,
703 
704 	Op_var_update,		/* update value of NR, NF or FNR */
705 	Op_var_assign,
706 	Op_field_assign,
707 	Op_subscript_assign,
708 	Op_after_beginfile,
709 	Op_after_endfile,
710 
711 	Op_func,
712 
713 	Op_comment,		/* for pretty printing */
714 	Op_exec_count,
715 	Op_breakpoint,
716 	Op_lint,
717 	Op_lint_plus,
718 	Op_atexit,
719 	Op_stop,
720 
721 	/* parsing (yylex and yyparse), should never appear in valid compiled code */
722 	Op_token,
723 	Op_symbol,
724 	Op_list,
725 
726 	/* program structures -- for use in the profiler/pretty printer */
727 	Op_K_do,
728 	Op_K_for,
729 	Op_K_arrayfor,
730 	Op_K_while,
731 	Op_K_switch,
732 	Op_K_if,
733 	Op_K_else,
734 	Op_K_function,
735 	Op_cond_exp,
736 	Op_parens,
737 	Op_final			/* sentry value, not legal */
738 } OPCODE;
739 
740 enum redirval {
741 	/* I/O redirections */
742 	redirect_none = 0,
743 	redirect_output,
744 	redirect_append,
745 	redirect_pipe,
746 	redirect_pipein,
747 	redirect_input,
748 	redirect_twoway
749 };
750 
751 struct break_point;
752 
753 #if __DECC && __VAX
754 typedef unsigned long exec_count_t;	// for exec_count
755 #define EXEC_COUNT_FMT	"%lu"
756 #define EXEC_COUNT_PROFILE_FMT	"%6lu"
757 #else
758 typedef unsigned long long exec_count_t;	// for exec_count
759 #define EXEC_COUNT_FMT	"%llu"
760 #define EXEC_COUNT_PROFILE_FMT	"%6llu"
761 #endif
762 
763 typedef struct exp_instruction {
764 	struct exp_instruction *nexti;
765 	union {
766 		NODE *dn;
767 		struct exp_instruction *di;
768 		NODE *(*fptr)(int);
769 		awk_value_t *(*efptr)(int num_actual_args,
770 					awk_value_t *result,
771 					struct awk_ext_func *finfo);
772 		long dl;
773 		exec_count_t ldl;	// for exec_count
774 		char *name;
775 	} d;
776 
777 	union {
778 		long  xl;
779 		NODE *xn;
780 		void (*aptr)(void);
781 		struct exp_instruction *xi;
782 		struct break_point *bpt;
783 		awk_ext_func_t *exf;
784 	} x;
785 
786 	struct exp_instruction *comment;
787 	short source_line;
788 	short pool_size;	// memory management in symbol.c
789 	OPCODE opcode;
790 } INSTRUCTION;
791 
792 #define func_name       d.name
793 
794 #define memory          d.dn
795 #define builtin         d.fptr
796 #define extfunc         d.efptr
797 #define builtin_idx     d.dl
798 
799 #define expr_count      x.xl
800 
801 #define c_function	x.exf
802 
803 #define target_continue d.di
804 #define target_jmp      d.di
805 #define target_break    x.xi
806 
807 /* Op_sub_builtin */
808 #define sub_flags       d.dl
809 #define GSUB            0x01	/* builtin is gsub */
810 #define GENSUB          0x02	/* builtin is gensub */
811 #define LITERAL         0x04	/* target is a literal string */
812 
813 
814 /* Op_K_exit */
815 #define target_end      d.di
816 #define target_atexit   x.xi
817 
818 /* Op_newfile, Op_K_getline, Op_nextfile */
819 #define target_endfile	x.xi
820 
821 /* Op_newfile */
822 #define target_get_record	x.xi
823 
824 /* Op_get_record, Op_K_nextfile */
825 #define target_newfile	d.di
826 
827 /* Op_K_getline */
828 #define target_beginfile	d.di
829 
830 /* Op_get_record */
831 #define has_endfile		x.xl
832 
833 /* Op_token */
834 #define lextok          d.name
835 #define param_count     x.xl
836 
837 /* Op_rule */
838 #define in_rule         x.xl
839 #define source_file     d.name
840 
841  /* Op_K_case, Op_K_default */
842 #define case_stmt       x.xi
843 #define case_exp        d.di
844 #define stmt_start      case_exp
845 #define stmt_end        case_stmt
846 #define match_exp       x.xl
847 
848 #define target_stmt     x.xi
849 
850 /* Op_K_switch */
851 #define switch_end      x.xi
852 #define switch_start    d.di
853 
854 /* Op_K_getline, Op_K_getline_redir */
855 #define into_var        x.xl
856 
857 /* Op_K_getline_redir, Op_K_print, Op_K_print_rec, Op_K_printf */
858 #define redir_type      d.dl
859 
860 /* Op_arrayfor_incr	*/
861 #define array_var       x.xn
862 
863 /* Op_line_range */
864 #define triggered       x.xl
865 
866 /* Op_cond_pair */
867 #define line_range      x.xi
868 
869 /* Op_func_call, Op_func */
870 #define func_body       x.xn
871 
872 /* Op_subscript */
873 #define sub_count       d.dl
874 
875 /* Op_push_lhs, Op_subscript_lhs, Op_field_spec_lhs */
876 #define do_reference    x.xl
877 
878 /* Op_list, Op_rule, Op_func */
879 #define lasti           d.di
880 #define firsti          x.xi
881 
882 /* Op_rule, Op_func */
883 #define last_line       x.xl
884 #define first_line      source_line
885 
886 /* Op_lint */
887 #define lint_type       d.dl
888 
889 /* Op_field_spec_lhs */
890 #define target_assign	d.di
891 
892 /* Op_var_assign */
893 #define assign_var	x.aptr
894 
895 /* Op_var_update */
896 #define update_var	x.aptr
897 
898 /* Op_field_assign */
899 #define field_assign    x.aptr
900 
901 /* Op_field_assign, Op_var_assign */
902 #define assign_ctxt	d.dl
903 
904 /* Op_concat */
905 #define concat_flag     d.dl
906 #define CSUBSEP		1
907 #define CSVAR		2
908 
909 /* Op_breakpoint */
910 #define break_pt        x.bpt
911 
912 /*------------------ pretty printing/profiling --------*/
913 /* Op_exec_count */
914 #define exec_count      d.ldl
915 
916 /* Op_K_while */
917 #define while_body      d.di
918 
919 /* Op_K_do */
920 #define doloop_cond     d.di
921 
922 /* Op_K_for */
923 #define forloop_cond    d.di
924 #define forloop_body    x.xi
925 
926 /* Op_K_if */
927 #define branch_if       d.di
928 #define branch_else     x.xi
929 
930 /* Op_K_else */
931 #define branch_end      x.xi
932 
933 /* Op_line_range */
934 #define condpair_left   d.di
935 #define condpair_right  x.xi
936 
937 /* Op_Rule, Op_Func */
938 #define ns_name		d.name
939 
940 /* Op_store_var */
941 #define initval         x.xn
942 
943 typedef struct iobuf {
944 	awk_input_buf_t public;	/* exposed to extensions */
945 	char *buf;              /* start data buffer */
946 	char *off;              /* start of current record in buffer */
947 	char *dataend;          /* first byte in buffer to hold new data,
948 				   NULL if not read yet */
949 	char *end;              /* end of buffer */
950 	size_t readsize;        /* set from fstat call */
951 	size_t size;            /* buffer size */
952 	ssize_t count;          /* amount read last time */
953 	size_t scanoff;         /* where we were in the buffer when we had
954 				   to regrow/refill */
955 	bool valid;
956 	int errcode;
957 
958 	enum iobuf_flags {
959 		IOP_IS_TTY	= 1,
960 		IOP_AT_EOF	= 2,
961 		IOP_CLOSED	= 4,
962 		IOP_AT_START	= 8,
963 	} flag;
964 } IOBUF;
965 
966 typedef void (*Func_ptr)(void);
967 
968 /* structure used to dynamically maintain a linked-list of open files/pipes */
969 struct redirect {
970 	enum redirect_flags {
971 		RED_NONE	= 0,
972 		RED_FILE	= 1,
973 		RED_PIPE	= 2,
974 		RED_READ	= 4,
975 		RED_WRITE	= 8,
976 		RED_APPEND	= 16,
977 		RED_NOBUF	= 32,
978 		RED_USED	= 64,	/* closed temporarily to reuse fd */
979 		RED_EOF		= 128,
980 		RED_TWOWAY	= 256,
981 		RED_PTY		= 512,
982 		RED_SOCKET	= 1024,
983 		RED_TCP		= 2048,
984 	} flag;
985 	char *value;
986 	FILE *ifp;	/* input fp, needed for PIPES_SIMULATED */
987 	IOBUF *iop;
988 	int pid;
989 	int status;
990 	struct redirect *prev;
991 	struct redirect *next;
992 	const char *mode;
993 	awk_output_buf_t output;
994 };
995 typedef enum redirect_flags redirect_flags_t;
996 
997 /* values for BINMODE, used as bit flags */
998 
999 enum binmode_values {
1000 	TEXT_TRANSLATE	= 0,	/* usual \r\n ---> \n translation */
1001 	BINMODE_INPUT	= 1,	/* no translation for input files */
1002 	BINMODE_OUTPUT	= 2,	/* no translation for output files */
1003 	BINMODE_BOTH	= 3	/* no translation for either */
1004 };
1005 
1006 /*
1007  * structure for our source, either a command line string or a source file.
1008  */
1009 
1010 typedef struct srcfile {
1011 	struct srcfile *next;
1012 	struct srcfile *prev;
1013 
1014 	enum srctype {
1015 		SRC_CMDLINE = 1,
1016 		SRC_STDIN,
1017 		SRC_FILE,
1018 		SRC_INC,
1019 		SRC_EXTLIB
1020 	} stype;
1021 	char *src;	/* name on command line or include statement */
1022 	char *fullpath;	/* full path after AWKPATH search */
1023 	time_t mtime;
1024 	struct stat sbuf;
1025 	int srclines;	/* no of lines in source */
1026 	size_t bufsize;
1027 	char *buf;
1028 	int *line_offset;	/* offset to the beginning of each line */
1029 	int fd;
1030 	int maxlen;	/* size of the longest line */
1031 
1032 	void (*fini_func)();	/* dynamic extension of type SRC_EXTLIB */
1033 
1034 	char *lexptr;
1035 	char *lexend;
1036 	char *lexeme;
1037 	char *lexptr_begin;
1038 	int lasttok;
1039 	INSTRUCTION *comment;	/* comment on @load line */
1040 	const char *namespace;
1041 } SRCFILE;
1042 
1043 // structure for INSTRUCTION pool, needed mainly for debugger
1044 typedef struct instruction_pool {
1045 #define MAX_INSTRUCTION_ALLOC	4	// we don't call bcalloc with more than this
1046 	struct instruction_mem_pool {
1047 		struct instruction_block *block_list;
1048 		INSTRUCTION *free_space;	// free location in active block
1049 		INSTRUCTION *free_list;
1050 	} pool[MAX_INSTRUCTION_ALLOC];
1051 } INSTRUCTION_POOL;
1052 
1053 /* structure for execution context */
1054 typedef struct context {
1055 	INSTRUCTION_POOL pools;
1056 	NODE symbols;
1057 	INSTRUCTION rule_list;
1058 	SRCFILE srcfiles;
1059 	int sourceline;
1060 	char *source;
1061 	void (*install_func)(NODE *);
1062 	struct context *prev;
1063 } AWK_CONTEXT;
1064 
1065 /* for debugging purposes */
1066 struct flagtab {
1067 	int val;
1068 	const char *name;
1069 };
1070 
1071 
1072 struct block_item {
1073 	struct block_item *freep;
1074 };
1075 
1076 struct block_header {
1077 	struct block_item *freep;
1078 	size_t size;
1079 	const char *name;
1080 	long highwater;
1081 #ifdef MEMDEBUG
1082 	long active;
1083 #endif
1084 };
1085 
1086 enum block_id {
1087 	BLOCK_NODE = 0,
1088 	BLOCK_BUCKET,
1089 	BLOCK_MAX	/* count */
1090 };
1091 
1092 typedef int (*Func_pre_exec)(INSTRUCTION **);
1093 typedef void (*Func_post_exec)(INSTRUCTION *);
1094 
1095 #ifndef LONG_MAX
1096 #define LONG_MAX ((long)(~(1L << (sizeof (long) * 8 - 1))))
1097 #endif
1098 #ifndef ULONG_MAX
1099 #define ULONG_MAX (~(unsigned long)0)
1100 #endif
1101 #ifndef LONG_MIN
1102 #define LONG_MIN ((long)(-LONG_MAX - 1L))
1103 #endif
1104 #define UNLIMITED    LONG_MAX
1105 
1106 /* -------------------------- External variables -------------------------- */
1107 /* gawk builtin variables */
1108 extern long NF;
1109 extern long NR;
1110 extern long FNR;
1111 extern int BINMODE;
1112 extern bool IGNORECASE;
1113 extern bool RS_is_null;
1114 extern char *OFS;
1115 extern int OFSlen;
1116 extern char *ORS;
1117 extern int ORSlen;
1118 extern char *OFMT;
1119 extern const char *CONVFMT;
1120 extern int CONVFMTidx;
1121 extern int OFMTidx;
1122 #ifdef HAVE_MPFR
1123 extern int MPFR_round_mode;
1124 #endif
1125 extern char *TEXTDOMAIN;
1126 extern NODE *BINMODE_node, *CONVFMT_node, *FIELDWIDTHS_node, *FILENAME_node;
1127 extern NODE *FNR_node, *FS_node, *IGNORECASE_node, *NF_node;
1128 extern NODE *NR_node, *OFMT_node, *OFS_node, *ORS_node, *RLENGTH_node;
1129 extern NODE *RSTART_node, *RS_node, *RT_node, *SUBSEP_node, *PROCINFO_node;
1130 extern NODE *LINT_node, *ERRNO_node, *TEXTDOMAIN_node, *FPAT_node;
1131 extern NODE *PREC_node, *ROUNDMODE_node;
1132 extern NODE *Nnull_string;
1133 extern NODE *Null_field;
1134 extern NODE **fields_arr;
1135 extern int sourceline;
1136 extern char *source;
1137 extern int errcount;
1138 extern int (*interpret)(INSTRUCTION *);	/* interpreter routine */
1139 extern NODE *(*make_number)(double);	/* double instead of AWKNUM on purpose */
1140 extern NODE *(*str2number)(NODE *);
1141 extern NODE *(*format_val)(const char *, int, NODE *);
1142 extern int (*cmp_numbers)(const NODE *, const NODE *);
1143 
1144 /* built-in array types */
1145 extern const array_funcs_t str_array_func;
1146 extern const array_funcs_t cint_array_func;
1147 extern const array_funcs_t int_array_func;
1148 
1149 /* special node used to indicate success in array routines (not NULL) */
1150 extern NODE *success_node;
1151 
1152 extern struct block_header nextfree[];
1153 extern bool field0_valid;
1154 
1155 extern bool do_itrace;	/* separate so can poke from a debugger */
1156 
1157 extern SRCFILE *srcfiles; /* source files */
1158 
1159 extern enum do_flag_values {
1160 	DO_FLAG_NONE       = 0x00000,
1161 	DO_LINT_INVALID	   = 0x00001,	/* only warn about invalid */
1162 	DO_LINT_EXTENSIONS = 0x00002,	/* warn about gawk extensions */
1163 	DO_LINT_ALL	   = 0x00004,	/* warn about all things */
1164 	DO_LINT_OLD	   = 0x00008,	/* warn about stuff not in V7 awk */
1165 	DO_TRADITIONAL	   = 0x00010,	/* no gnu extensions, add traditional weirdnesses */
1166 	DO_POSIX	   = 0x00020,	/* turn off gnu and unix extensions */
1167 	DO_INTL		   = 0x00040,	/* dump locale-izable strings to stdout */
1168 	DO_NON_DEC_DATA	   = 0x00080,	/* allow octal/hex C style DATA. Use with caution! */
1169 	DO_INTERVALS	   = 0x00100,	/* allow {...,...} in regexps, see resetup() */
1170 	DO_PRETTY_PRINT	   = 0x00200,	/* pretty print the program */
1171 	DO_DUMP_VARS	   = 0x00400,	/* dump all global variables at end */
1172 	DO_TIDY_MEM	   = 0x00800,	/* release vars when done */
1173 	DO_SANDBOX	   = 0x01000,	/* sandbox mode - disable 'system' function & redirections */
1174 	DO_PROFILE	   = 0x02000,	/* profile the program */
1175 	DO_DEBUG	   = 0x04000,	/* debug the program */
1176 	DO_MPFR		   = 0x08000,	/* arbitrary-precision floating-point math */
1177 } do_flags;
1178 
1179 #define do_traditional      (do_flags & DO_TRADITIONAL)
1180 #define do_posix            (do_flags & DO_POSIX)
1181 #define do_intl             (do_flags & DO_INTL)
1182 #define do_non_decimal_data (do_flags & DO_NON_DEC_DATA)
1183 #define do_intervals        (do_flags & DO_INTERVALS)
1184 #define do_pretty_print     (do_flags & DO_PRETTY_PRINT)
1185 #define do_profile          (do_flags & DO_PROFILE)
1186 #define do_dump_vars        (do_flags & DO_DUMP_VARS)
1187 #define do_tidy_mem         (do_flags & DO_TIDY_MEM)
1188 #define do_sandbox          (do_flags & DO_SANDBOX)
1189 #define do_debug            (do_flags & DO_DEBUG)
1190 #define do_mpfr             (do_flags & DO_MPFR)
1191 
1192 extern bool do_optimize;
1193 extern int use_lc_numeric;
1194 extern int exit_val;
1195 
1196 #ifdef NO_LINT
1197 #define do_lint 0
1198 #define do_lint_old 0
1199 #define do_lint_extensions 0
1200 #else
1201 #define do_lint             (do_flags & (DO_LINT_INVALID|DO_LINT_ALL))
1202 #define do_lint_old         (do_flags & DO_LINT_OLD)
1203 #define do_lint_extensions  (do_flags & DO_LINT_EXTENSIONS)
1204 #endif
1205 extern int gawk_mb_cur_max;
1206 
1207 #if defined (HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0
1208 extern GETGROUPS_T *groupset;
1209 extern int ngroups;
1210 #endif
1211 
1212 #ifdef HAVE_LOCALE_H
1213 extern struct lconv loc;
1214 #endif /* HAVE_LOCALE_H */
1215 
1216 #ifdef HAVE_MPFR
1217 extern mpfr_prec_t PRECISION;
1218 extern mpfr_rnd_t ROUND_MODE;
1219 extern mpz_t MNR;
1220 extern mpz_t MFNR;
1221 extern mpz_t mpzval;
1222 extern bool do_ieee_fmt;	/* emulate IEEE 754 floating-point format */
1223 #endif
1224 
1225 
1226 extern const char *myname;
1227 extern const char def_strftime_format[];
1228 
1229 extern const char quote;
1230 extern const char *defpath;
1231 extern const char *deflibpath;
1232 extern const char envsep;
1233 
1234 extern char casetable[];	/* for case-independent regexp matching */
1235 
1236 extern const char awk_namespace[];	/* "awk" */
1237 extern const char *current_namespace;
1238 extern bool namespace_changed;
1239 
1240 /* ------------------------- Runtime stack -------------------------------- */
1241 
1242 typedef union stack_item {
1243 	NODE *rptr;	/* variable etc. */
1244 	NODE **lptr;	/* address of a variable etc. */
1245 } STACK_ITEM;
1246 
1247 extern STACK_ITEM *stack_ptr;
1248 extern NODE *frame_ptr;
1249 extern STACK_ITEM *stack_bottom;
1250 extern STACK_ITEM *stack_top;
1251 
1252 #define decr_sp()		(stack_ptr--)
1253 #define incr_sp()		((stack_ptr < stack_top) ? ++stack_ptr : grow_stack())
1254 #define stack_adj(n)		(stack_ptr += (n))
1255 #define stack_empty()		(stack_ptr < stack_bottom)
1256 
1257 #define POP()			(decr_sp()->rptr)
1258 #define POP_ADDRESS()		(decr_sp()->lptr)
1259 #define PEEK(n)			((stack_ptr - (n))->rptr)
1260 #define TOP()			(stack_ptr->rptr)		/* same as PEEK(0) */
1261 #define TOP_ADDRESS()		(stack_ptr->lptr)
1262 #define PUSH(r)			(void) (incr_sp()->rptr = (r))
1263 #define PUSH_ADDRESS(l)		(void) (incr_sp()->lptr = (l))
1264 #define REPLACE(r)		(void) (stack_ptr->rptr = (r))
1265 #define REPLACE_ADDRESS(l)	(void) (stack_ptr->lptr = (l))
1266 
1267 /* function param */
1268 #define GET_PARAM(n)	frame_ptr->stack[n]
1269 
1270 /*
1271  * UPREF --- simplified versions of dupnode, does not handle FIELD node.
1272  * Most appropriate use is for elements on the runtime stack.
1273  * When in doubt, use dupnode.
1274  */
1275 
1276 #define UPREF(r)	(void) ((r)->valref++)
1277 
1278 extern void r_unref(NODE *tmp);
1279 
1280 static inline void
DEREF(NODE * r)1281 DEREF(NODE *r)
1282 {
1283 	assert(r->valref > 0);
1284 #ifndef GAWKDEBUG
1285 	if (--r->valref > 0)
1286 		return;
1287 #endif
1288 	r_unref(r);
1289 }
1290 
1291 #define POP_NUMBER() force_number(POP_SCALAR())
1292 #define TOP_NUMBER() force_number(TOP_SCALAR())
1293 
1294 /* ------------------------- Pseudo-functions ------------------------- */
1295 #ifdef HAVE_MPFR
1296 
1297 #if 0
1298 
1299 /*
1300  * In principle, there is no need to have both the MPFN and MPZN flags,
1301  * since we are using 2 bits to encode 1 bit of information. But
1302  * there may be some minor performance advantages from testing only the
1303  * node flag bits without needing also to access the global do_mpfr flag bit.
1304  */
1305 #define numtype_choose(n, mpfrval, mpzval, dblval)	\
1306  (!do_mpfr ? (dblval) : (((n)->flags & MPFN) ? (mpfrval) : (mpzval)))
1307 
1308 #endif
1309 
1310 /* N.B. This implementation seems to give the fastest results. */
1311 #define numtype_choose(n, mpfrval, mpzval, dblval)	\
1312  (!((n)->flags & (MPFN|MPZN)) ? (dblval) : (((n)->flags & MPFN) ? (mpfrval) : (mpzval)))
1313 
1314 /* conversion to C types */
1315 #define get_number_ui(n)	numtype_choose((n), mpfr_get_ui((n)->mpg_numbr, ROUND_MODE), mpz_get_ui((n)->mpg_i), (unsigned long) (n)->numbr)
1316 
1317 #define get_number_si(n)	numtype_choose((n), mpfr_get_si((n)->mpg_numbr, ROUND_MODE), mpz_get_si((n)->mpg_i), (long) (n)->numbr)
1318 
1319 #define get_number_d(n)		numtype_choose((n), mpfr_get_d((n)->mpg_numbr, ROUND_MODE), mpz_get_d((n)->mpg_i), (double) (n)->numbr)
1320 
1321 #define get_number_uj(n)	numtype_choose((n), mpfr_get_uj((n)->mpg_numbr, ROUND_MODE), (uintmax_t) mpz_get_d((n)->mpg_i), (uintmax_t) (n)->numbr)
1322 
1323 #define is_zero(n)		numtype_choose((n), mpfr_zero_p((n)->mpg_numbr), (mpz_sgn((n)->mpg_i) == 0), ((n)->numbr == 0.0))
1324 
1325 #define IEEE_FMT(r, t)		(void) (do_ieee_fmt && format_ieee(r, t))
1326 
1327 #define mpg_float()		mpg_node(MPFN)
1328 #define mpg_integer()		mpg_node(MPZN)
1329 #define is_mpg_float(n)		(((n)->flags & MPFN) != 0)
1330 #define is_mpg_integer(n)	(((n)->flags & MPZN) != 0)
1331 #define is_mpg_number(n)	(((n)->flags & (MPZN|MPFN)) != 0)
1332 #else
1333 #define get_number_ui(n)	(unsigned long) (n)->numbr
1334 #define get_number_si(n)	(long) (n)->numbr
1335 #define get_number_d(n)		(double) (n)->numbr
1336 #define get_number_uj(n)	(uintmax_t) (n)->numbr
1337 
1338 #define is_mpg_number(n)	0
1339 #define is_mpg_float(n)		0
1340 #define is_mpg_integer(n)	0
1341 #define is_zero(n)		((n)->numbr == 0.0)
1342 #endif
1343 
1344 #define var_uninitialized(n)	((n)->var_value == Nnull_string)
1345 
1346 #define get_lhs(n, r)	 (n)->type == Node_var && ! var_uninitialized(n) ? \
1347 				&((n)->var_value) : r_get_lhs((n), (r))
1348 
1349 #ifdef MEMDEBUG
1350 
1351 extern void *r_getblock(int id);
1352 extern void r_freeblock(void *, int id);
1353 #define getblock(p, id, ty)	(void) (p = (ty) r_getblock(id))
1354 #define freeblock(p, id)	(void) (r_freeblock(p, id))
1355 
1356 #else /* MEMDEBUG */
1357 
1358 #define getblock(p, id, ty)  (void) ((p = (ty) nextfree[id].freep) ? \
1359 			(ty) (nextfree[id].freep = ((struct block_item *) p)->freep) \
1360 			: (p = (ty) more_blocks(id)))
1361 #define freeblock(p, id)	 (void) (((struct block_item *) p)->freep = nextfree[id].freep, \
1362 					nextfree[id].freep = (struct block_item *) p)
1363 
1364 #endif /* MEMDEBUG */
1365 
1366 #define getnode(n)	getblock(n, BLOCK_NODE, NODE *)
1367 #define freenode(n)	freeblock(n, BLOCK_NODE)
1368 
1369 #define getbucket(b) 	getblock(b, BLOCK_BUCKET, BUCKET *)
1370 #define freebucket(b)	freeblock(b, BLOCK_BUCKET)
1371 
1372 #define	make_string(s, l)	make_str_node((s), (l), 0)
1373 
1374 // Flags for making string nodes
1375 #define		SCAN			1
1376 #define		ALREADY_MALLOCED	2
1377 #define		ELIDE_BACK_NL		4
1378 
1379 #define	cant_happen()	r_fatal("internal error line %d, file: %s", \
1380 				__LINE__, __FILE__)
1381 
1382 #define	emalloc(var,ty,x,str)	(void) (var = (ty) emalloc_real((size_t)(x), str, #var, __FILE__, __LINE__))
1383 #define	ezalloc(var,ty,x,str)	(void) (var = (ty) ezalloc_real((size_t)(x), str, #var, __FILE__, __LINE__))
1384 #define	erealloc(var,ty,x,str)	(void) (var = (ty) erealloc_real((void *) var, (size_t)(x), str, #var, __FILE__, __LINE__))
1385 
1386 #define efree(p)	free(p)
1387 
1388 #define fatal		(*(set_loc(__FILE__, __LINE__), r_fatal))
1389 
1390 extern jmp_buf fatal_tag;
1391 extern int fatal_tag_valid;
1392 
1393 #define assoc_length(a)	((a)->table_size)
1394 #define assoc_empty(a)	(assoc_length(a) == 0)
1395 #define assoc_lookup(a, s)	((a)->alookup(a, s))
1396 
1397 /* assoc_clear --- flush all the values in symbol[] */
1398 #define assoc_clear(a)	(void) ((a)->aclear(a, NULL))
1399 
1400 /* assoc_remove --- remove an index from symbol[] */
1401 #define assoc_remove(a, s) ((a)->aremove(a, s) != NULL)
1402 
1403 
1404 /* ------------- Function prototypes or defs (as appropriate) ------------- */
1405 /* array.c */
1406 typedef enum { SORTED_IN = 1, ASORT, ASORTI } sort_context_t;
1407 typedef enum {
1408 	ANONE   = 0x00,		/* "unused" value */
1409 	AINDEX	= 0x001,	/* list of indices */
1410 	AVALUE	= 0x002,	/* list of values */
1411 	AINUM	= 0x004,	/* numeric index */
1412 	AISTR	= 0x008,	/* string index */
1413 	AVNUM	= 0x010,	/* numeric scalar value */
1414 	AVSTR	= 0x020,	/* string scalar value */
1415 	AASC	= 0x040,	/* ascending order */
1416 	ADESC	= 0x080,	/* descending order */
1417 	ADELETE = 0x100		/* need a single index; for use in do_delete_loop */
1418 } assoc_kind_t;
1419 
1420 extern NODE *make_array(void);
1421 extern void null_array(NODE *symbol);
1422 extern NODE *force_array(NODE *symbol, bool canfatal);
1423 extern const char *make_aname(const NODE *symbol);
1424 extern const char *array_vname(const NODE *symbol);
1425 extern void array_init(void);
1426 extern NODE **null_afunc(NODE *symbol, NODE *subs);
1427 extern void set_SUBSEP(void);
1428 extern NODE *concat_exp(int nargs, bool do_subsep);
1429 extern NODE *assoc_copy(NODE *symbol, NODE *newsymb);
1430 extern void assoc_dump(NODE *symbol, NODE *p);
1431 extern NODE **assoc_list(NODE *symbol, const char *sort_str, sort_context_t sort_ctxt);
1432 extern void assoc_info(NODE *subs, NODE *val, NODE *p, const char *aname);
1433 extern void do_delete(NODE *symbol, int nsubs);
1434 extern void do_delete_loop(NODE *symbol, NODE **lhs);
1435 extern NODE *do_adump(int nargs);
1436 extern NODE *do_aoption(int nargs);
1437 extern NODE *do_asort(int nargs);
1438 extern NODE *do_asorti(int nargs);
1439 extern unsigned long (*hash)(const char *s, size_t len, unsigned long hsize, size_t *code);
1440 extern void init_env_array(NODE *env_node);
1441 extern void init_argv_array(NODE *argv_node, NODE *shadow_node);
1442 /* awkgram.c */
1443 extern NODE *variable(int location, char *name, NODETYPE type);
1444 extern int parse_program(INSTRUCTION **pcode, bool from_eval);
1445 extern void track_ext_func(const char *name);
1446 extern void dump_funcs(void);
1447 extern void dump_vars(const char *fname);
1448 extern const char *getfname(NODE *(*)(int), bool prepend_awk);
1449 extern NODE *stopme(int nargs);
1450 extern void shadow_funcs(void);
1451 extern int check_special(const char *name);
1452 extern SRCFILE *add_srcfile(enum srctype stype, char *src, SRCFILE *curr, bool *already_included, int *errcode);
1453 extern void free_srcfile(SRCFILE *thisfile);
1454 extern int files_are_same(char *path, SRCFILE *src);
1455 extern void valinfo(NODE *n, Func_print print_func, FILE *fp);
1456 extern void negate_num(NODE *n);
1457 typedef NODE *(*builtin_func_t)(int);	/* function that implements a built-in */
1458 extern builtin_func_t lookup_builtin(const char *name);
1459 extern void install_builtins(void);
1460 extern bool is_alpha(int c);
1461 extern bool is_alnum(int c);
1462 extern bool is_letter(int c);
1463 extern bool is_identchar(int c);
1464 extern NODE *make_regnode(NODETYPE type, NODE *exp);
1465 extern bool validate_qualified_name(char *token);
1466 /* builtin.c */
1467 extern double double_to_int(double d);
1468 extern NODE *do_exp(int nargs);
1469 extern NODE *do_fflush(int nargs);
1470 extern NODE *do_index(int nargs);
1471 extern NODE *do_int(int nargs);
1472 extern NODE *do_isarray(int nargs);
1473 extern NODE *do_length(int nargs);
1474 extern NODE *do_log(int nargs);
1475 extern NODE *do_mktime(int nargs);
1476 extern NODE *do_sprintf(int nargs);
1477 extern void do_printf(int nargs, int redirtype);
1478 extern void print_simple(NODE *tree, FILE *fp);
1479 extern NODE *do_sqrt(int nargs);
1480 extern NODE *do_substr(int nargs);
1481 extern NODE *do_strftime(int nargs);
1482 extern NODE *do_systime(int nargs);
1483 extern NODE *do_system(int nargs);
1484 extern void do_print(int nargs, int redirtype);
1485 extern void do_print_rec(int args, int redirtype);
1486 extern NODE *do_tolower(int nargs);
1487 extern NODE *do_toupper(int nargs);
1488 extern NODE *do_atan2(int nargs);
1489 extern NODE *do_sin(int nargs);
1490 extern NODE *do_cos(int nargs);
1491 extern NODE *do_rand(int nargs);
1492 extern NODE *do_srand(int nargs);
1493 extern NODE *do_match(int nargs);
1494 extern NODE *do_sub(int nargs, unsigned int flags);
1495 extern NODE *call_sub(const char *name, int nargs);
1496 extern NODE *call_match(int nargs);
1497 extern NODE *call_split_func(const char *name, int nargs);
1498 extern NODE *format_tree(const char *, size_t, NODE **, long);
1499 extern NODE *do_lshift(int nargs);
1500 extern NODE *do_rshift(int nargs);
1501 extern NODE *do_and(int nargs);
1502 extern NODE *do_or(int nargs);
1503 extern NODE *do_xor(int nargs);
1504 extern NODE *do_compl(int nargs);
1505 extern NODE *do_strtonum(int nargs);
1506 extern AWKNUM nondec2awknum(char *str, size_t len, char **endptr);
1507 extern NODE *do_dcgettext(int nargs);
1508 extern NODE *do_dcngettext(int nargs);
1509 extern NODE *do_bindtextdomain(int nargs);
1510 extern NODE *do_intdiv(int nargs);
1511 extern NODE *do_typeof(int nargs);
1512 extern int strncasecmpmbs(const unsigned char *,
1513 			  const unsigned char *, size_t);
1514 extern int sanitize_exit_status(int status);
1515 extern void check_symtab_functab(NODE *dest, const char *fname, const char *msg);
1516 /* debug.c */
1517 extern void init_debug(void);
1518 extern int debug_prog(INSTRUCTION *pc);
1519 /* eval.c */
1520 extern void PUSH_CODE(INSTRUCTION *cp);
1521 extern INSTRUCTION *POP_CODE(void);
1522 extern void init_interpret(void);
1523 extern int cmp_nodes(NODE *t1, NODE *t2, bool use_strcmp);
1524 extern int cmp_awknums(const NODE *t1, const NODE *t2);
1525 extern void set_IGNORECASE(void);
1526 extern void set_OFS(void);
1527 extern void set_ORS(void);
1528 extern void set_OFMT(void);
1529 extern void set_CONVFMT(void);
1530 extern void set_BINMODE(void);
1531 extern void set_LINT(void);
1532 extern void set_TEXTDOMAIN(void);
1533 extern void update_ERRNO_int(int);
1534 extern void update_ERRNO_string(const char *string);
1535 extern void unset_ERRNO(void);
1536 extern void update_NR(void);
1537 extern void update_NF(void);
1538 extern void update_FNR(void);
1539 extern const char *redflags2str(int);
1540 extern const char *flags2str(int);
1541 extern const char *genflags2str(int flagval, const struct flagtab *tab);
1542 extern const char *nodetype2str(NODETYPE type);
1543 extern void load_casetable(void);
1544 extern AWKNUM calc_exp(AWKNUM x1, AWKNUM x2);
1545 extern const char *opcode2str(OPCODE type);
1546 extern const char *op2str(OPCODE type);
1547 extern NODE **r_get_lhs(NODE *n, bool reference);
1548 extern STACK_ITEM *grow_stack(void);
1549 extern void dump_fcall_stack(FILE *fp);
1550 extern int register_exec_hook(Func_pre_exec preh, Func_post_exec posth);
1551 extern NODE **r_get_field(NODE *n, Func_ptr *assign, bool reference);
1552 /* ext.c */
1553 extern NODE *do_ext(int nargs);
1554 void load_ext(const char *lib_name);	/* temporary */
1555 extern void close_extensions(void);
1556 extern bool is_valid_identifier(const char *name);
1557 #ifdef DYNAMIC
1558 extern awk_bool_t make_builtin(const char *name_space, const awk_ext_func_t *);
1559 extern NODE *get_argument(int);
1560 extern NODE *get_actual_argument(NODE *, int, bool);
1561 #define get_scalar_argument(n, i)  get_actual_argument((n), (i), false)
1562 #define get_array_argument(n, i)   get_actual_argument((n), (i), true)
1563 #endif
1564 /* field.c */
1565 extern void init_fields(void);
1566 extern void set_record(const char *buf, int cnt, const awk_fieldwidth_info_t *);
1567 extern void reset_record(void);
1568 extern void rebuild_record(void);
1569 extern void set_NF(void);
1570 extern NODE **get_field(long num, Func_ptr *assign);
1571 extern NODE *do_split(int nargs);
1572 extern NODE *do_patsplit(int nargs);
1573 extern void set_FS(void);
1574 extern void set_RS(void);
1575 extern void set_FIELDWIDTHS(void);
1576 extern void set_FPAT(void);
1577 extern void update_PROCINFO_str(const char *subscript, const char *str);
1578 extern void update_PROCINFO_num(const char *subscript, AWKNUM val);
1579 
1580 typedef enum {
1581 	Using_FS,
1582 	Using_FIELDWIDTHS,
1583 	Using_FPAT,
1584 	Using_API
1585 } field_sep_type;
1586 extern field_sep_type current_field_sep(void);
1587 extern const char *current_field_sep_str(void);
1588 
1589 /* gawkapi.c: */
1590 extern gawk_api_t api_impl;
1591 extern void init_ext_api(void);
1592 extern void update_ext_api(void);
1593 extern NODE *awk_value_to_node(const awk_value_t *);
1594 extern void run_ext_exit_handlers(int exitval);
1595 extern void print_ext_versions(void);
1596 extern void free_api_string_copies(void);
1597 
1598 /* gawkmisc.c */
1599 extern const char *gawk_name(const char *filespec);
1600 extern void os_arg_fixup(int *argcp, char ***argvp);
1601 extern int os_devopen(const char *name, int flag);
1602 extern void os_close_on_exec(int fd, const char *name, const char *what, const char *dir);
1603 extern int os_isatty(int fd);
1604 extern int os_isdir(int fd);
1605 extern int os_isreadable(const awk_input_buf_t *iobuf, bool *isdir);
1606 extern int os_is_setuid(void);
1607 extern int os_setbinmode(int fd, int mode);
1608 extern void os_restore_mode(int fd);
1609 extern size_t optimal_bufsize(int fd, struct stat *sbuf);
1610 extern int ispath(const char *file);
1611 extern int isdirpunct(int c);
1612 
1613 /* io.c */
1614 extern void init_sockets(void);
1615 extern void init_io(void);
1616 extern void register_input_parser(awk_input_parser_t *input_parser);
1617 extern void register_output_wrapper(awk_output_wrapper_t *wrapper);
1618 extern void register_two_way_processor(awk_two_way_processor_t *processor);
1619 extern void set_FNR(void);
1620 extern void set_NR(void);
1621 
1622 extern struct redirect *redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal);
1623 extern struct redirect *redirect_string(const char *redir_exp_str,
1624 		size_t redir_exp_len, bool not_string_flag, int redirtype,
1625 		int *errflg, int extfd, bool failure_fatal);
1626 extern NODE *do_close(int nargs);
1627 extern int flush_io(void);
1628 extern int close_io(bool *stdio_problem, bool *got_EPIPE);
1629 typedef enum { CLOSE_ALL, CLOSE_TO, CLOSE_FROM } two_way_close_type;
1630 extern int close_rp(struct redirect *rp, two_way_close_type how);
1631 extern int devopen_simple(const char *name, const char *mode, bool try_real_open);
1632 extern int devopen(const char *name, const char *mode);
1633 extern int srcopen(SRCFILE *s);
1634 extern char *find_source(const char *src, struct stat *stb, int *errcode, int is_extlib);
1635 extern NODE *do_getline_redir(int intovar, enum redirval redirtype);
1636 extern NODE *do_getline(int intovar, IOBUF *iop);
1637 extern struct redirect *getredirect(const char *str, int len);
1638 extern bool inrec(IOBUF *iop, int *errcode);
1639 extern int nextfile(IOBUF **curfile, bool skipping);
1640 extern bool is_non_fatal_std(FILE *fp);
1641 extern bool is_non_fatal_redirect(const char *str, size_t len);
1642 extern void ignore_sigpipe(void);
1643 extern void set_sigpipe_to_default(void);
1644 extern bool non_fatal_flush_std_file(FILE *fp);
1645 
1646 /* main.c */
1647 extern int arg_assign(char *arg, bool initing);
1648 extern int is_std_var(const char *var);
1649 extern int is_off_limits_var(const char *var);
1650 extern char *estrdup(const char *str, size_t len);
1651 extern void update_global_values();
1652 extern long getenv_long(const char *name);
1653 extern void after_beginfile(IOBUF **curfile);
1654 extern void set_current_namespace(const char *new_namespace);
1655 
1656 /* mpfr.c */
1657 extern void set_PREC(void);
1658 extern void set_ROUNDMODE(void);
1659 extern void mpfr_unset(NODE *n);
1660 #ifdef HAVE_MPFR
1661 extern int mpg_cmp(const NODE *, const NODE *);
1662 extern int format_ieee(mpfr_ptr, int);
1663 extern NODE *mpg_update_var(NODE *);
1664 extern long mpg_set_var(NODE *);
1665 extern NODE *do_mpfr_and(int);
1666 extern NODE *do_mpfr_atan2(int);
1667 extern NODE *do_mpfr_compl(int);
1668 extern NODE *do_mpfr_cos(int);
1669 extern NODE *do_mpfr_exp(int);
1670 extern NODE *do_mpfr_int(int);
1671 extern NODE *do_mpfr_intdiv(int);
1672 extern NODE *do_mpfr_log(int);
1673 extern NODE *do_mpfr_lshift(int);
1674 extern NODE *do_mpfr_or(int);
1675 extern NODE *do_mpfr_rand(int);
1676 extern NODE *do_mpfr_rshift(int);
1677 extern NODE *do_mpfr_sin(int);
1678 extern NODE *do_mpfr_sqrt(int);
1679 extern NODE *do_mpfr_srand(int);
1680 extern NODE *do_mpfr_strtonum(int);
1681 extern NODE *do_mpfr_xor(int);
1682 extern void init_mpfr(mpfr_prec_t, const char *);
1683 extern void cleanup_mpfr(void);
1684 extern NODE *mpg_node(unsigned int);
1685 extern const char *mpg_fmt(const char *, ...);
1686 extern int mpg_strtoui(mpz_ptr, char *, size_t, char **, int);
1687 extern void mpg_zero(NODE *n);
1688 #endif
1689 /* msg.c */
1690 extern void gawk_exit(int status);
1691 extern void final_exit(int status) ATTRIBUTE_NORETURN;
1692 extern void err(bool isfatal, const char *s, const char *emsg, va_list argp) ATTRIBUTE_PRINTF(3, 0);
1693 extern void msg (const char *mesg, ...) ATTRIBUTE_PRINTF_1;
1694 extern void error (const char *mesg, ...) ATTRIBUTE_PRINTF_1;
1695 extern void r_warning (const char *mesg, ...) ATTRIBUTE_PRINTF_1;
1696 extern void set_loc (const char *file, int line);
1697 extern void r_fatal (const char *mesg, ...) ATTRIBUTE_PRINTF_1;
1698 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)
1699 extern void (*lintfunc)(const char *mesg, ...) ATTRIBUTE_PRINTF_1;
1700 #else
1701 extern void (*lintfunc)(const char *mesg, ...);
1702 #endif
1703 /* profile.c */
1704 extern void init_profiling_signals(void);
1705 extern void set_prof_file(const char *filename);
1706 extern void dump_prog(INSTRUCTION *code);
1707 extern char *pp_number(NODE *n);
1708 extern char *pp_string(const char *in_str, size_t len, int delim);
1709 extern char *pp_node(NODE *n);
1710 extern int pp_func(INSTRUCTION *pc, void *);
1711 extern void pp_string_fp(Func_print print_func, FILE *fp, const char *str,
1712 		size_t namelen, int delim, bool breaklines);
1713 /* node.c */
1714 extern NODE *r_force_number(NODE *n);
1715 extern NODE *r_format_val(const char *format, int index, NODE *s);
1716 extern NODE *r_dupnode(NODE *n);
1717 extern NODE *make_str_node(const char *s, size_t len, int flags);
1718 extern NODE *make_typed_regex(const char *re, size_t len);
1719 extern void *more_blocks(int id);
1720 extern int parse_escape(const char **string_ptr);
1721 extern NODE *str2wstr(NODE *n, size_t **ptr);
1722 extern NODE *wstr2str(NODE *n);
1723 #define force_wstring(n)	str2wstr(n, NULL)
1724 extern const wchar_t *wstrstr(const wchar_t *haystack, size_t hs_len,
1725 		const wchar_t *needle, size_t needle_len);
1726 extern const wchar_t *wcasestrstr(const wchar_t *haystack, size_t hs_len,
1727 		const wchar_t *needle, size_t needle_len);
1728 extern void r_free_wstr(NODE *n);
1729 #define free_wstr(n)	do { if ((n)->flags & WSTRCUR) r_free_wstr(n); } while(0)
1730 extern wint_t btowc_cache[];
1731 #define btowc_cache(x) btowc_cache[(x)&0xFF]
1732 extern void init_btowc_cache();
1733 #define is_valid_character(b)	(btowc_cache[(b)&0xFF] != WEOF)
1734 extern bool out_of_range(NODE *n);
1735 extern char *format_nan_inf(NODE *n, char format);
1736 extern bool is_ieee_magic_val(const char *val);
1737 /* re.c */
1738 extern Regexp *make_regexp(const char *s, size_t len, bool ignorecase, bool dfa, bool canfatal);
1739 extern int research(Regexp *rp, char *str, int start, size_t len, int flags);
1740 extern void refree(Regexp *rp);
1741 extern void reg_error(const char *s);
1742 extern Regexp *re_update(NODE *t);
1743 extern void resyntax(int syntax);
1744 extern void resetup(void);
1745 extern int reisstring(const char *text, size_t len, Regexp *re, const char *buf);
1746 extern int get_numbase(const char *str, size_t len, bool use_locale);
1747 extern bool using_utf8(void);
1748 
1749 /* symbol.c */
1750 extern void load_symbols();
1751 extern void init_symbol_table();
1752 extern NODE *symbol_table;
1753 extern NODE *func_table;
1754 extern NODE *install_symbol(const char *name, NODETYPE type);
1755 extern NODE *remove_symbol(NODE *r);
1756 extern void destroy_symbol(NODE *r);
1757 extern void release_symbols(NODE *symlist, int keep_globals);
1758 extern void append_symbol(NODE *r);
1759 extern NODE *lookup(const char *name);
1760 extern NODE *make_params(char **pnames, int pcount);
1761 extern void install_params(NODE *func);
1762 extern void remove_params(NODE *func);
1763 extern void release_all_vars(void);
1764 extern int foreach_func(NODE **table, int (*)(INSTRUCTION *, void *), void *);
1765 extern INSTRUCTION *bcalloc(OPCODE op, int size, int srcline);
1766 extern void bcfree(INSTRUCTION *);
1767 extern AWK_CONTEXT *new_context(void);
1768 extern void push_context(AWK_CONTEXT *ctxt);
1769 extern void pop_context();
1770 extern int in_main_context();
1771 extern void free_context(AWK_CONTEXT *ctxt, bool keep_globals);
1772 extern NODE **variable_list();
1773 extern NODE **function_list(bool sort);
1774 extern void print_vars(NODE **table, Func_print print_func, FILE *fp);
1775 extern bool check_param_names(void);
1776 extern bool is_all_upper(const char *name);
1777 
1778 /* floatcomp.c */
1779 #ifdef HAVE_UINTMAX_T
1780 extern uintmax_t adjust_uint(uintmax_t n);
1781 #else
1782 #define adjust_uint(n) (n)
1783 #endif
1784 
1785 #ifdef HAVE_SYS_WAIT_H
1786 #include <sys/wait.h>
1787 #endif
1788 #ifndef WEXITSTATUS
1789 #if defined(VMS)
1790 #define WEXITSTATUS(stat_val) (stat_val)
1791 #else /* ! defined(VMS) */
1792 #define WEXITSTATUS(stat_val) ((((unsigned) (stat_val)) >> 8) & 0xFF)
1793 #endif /* ! defined(VMS)) */
1794 #endif /* WEXITSTATUS */
1795 
1796 /* For z/OS, from Dave Pitts. EXIT_FAILURE is normally 8, make it 1. */
1797 #if defined(EXIT_FAILURE) && EXIT_FAILURE == 8
1798 # undef EXIT_FAILURE
1799 #endif
1800 
1801 /* EXIT_SUCCESS and EXIT_FAILURE normally come from <stdlib.h> */
1802 #ifndef EXIT_SUCCESS
1803 # define EXIT_SUCCESS 0
1804 #endif
1805 #ifndef EXIT_FAILURE
1806 # define EXIT_FAILURE 1
1807 #endif
1808 /* EXIT_FATAL is specific to gawk, not part of Standard C */
1809 #ifndef EXIT_FATAL
1810 # define EXIT_FATAL   2
1811 #endif
1812 
1813 /* ------------------ Inline Functions ------------------ */
1814 
1815 /*
1816  * These must come last to get all the function declarations and
1817  * macro definitions before their bodies.
1818  *
1819  * This is wasteful if the compiler doesn't support inline. We won't
1820  * worry about it until someone complains.
1821  */
1822 
1823 /* POP_ARRAY --- get the array at the top of the stack */
1824 
1825 static inline NODE *
POP_ARRAY(bool check_for_untyped)1826 POP_ARRAY(bool check_for_untyped)
1827 {
1828 	NODE *t = POP();
1829 	static bool warned = false;
1830 
1831 	if (do_lint && ! warned && check_for_untyped && t->type == Node_var_new) {
1832 		warned = true;
1833 		lintwarn(_("behavior of `for' loop on untyped variable is not defined by POSIX"));
1834 	}
1835 
1836 	return (t->type == Node_var_array) ? t : force_array(t, true);
1837 }
1838 
1839 /* POP_PARAM --- get the top parameter, array or scalar */
1840 
1841 static inline NODE *
POP_PARAM()1842 POP_PARAM()
1843 {
1844 	NODE *t = POP();
1845 
1846 	return (t->type == Node_var_array) ? t : force_array(t, false);
1847 }
1848 
1849 /* POP_SCALAR --- pop the scalar at the top of the stack */
1850 
1851 static inline NODE *
POP_SCALAR()1852 POP_SCALAR()
1853 {
1854 	NODE *t = POP();
1855 
1856 	if (t->type == Node_var_array)
1857 		fatal(_("attempt to use array `%s' in a scalar context"), array_vname(t));
1858 
1859 	return t;
1860 }
1861 
1862 /* TOP_SCALAR --- get the scalar at the top of the stack */
1863 
1864 static inline NODE *
TOP_SCALAR()1865 TOP_SCALAR()
1866 {
1867 	NODE *t = TOP();
1868 
1869 	if (t->type == Node_var_array)
1870 		fatal(_("attempt to use array `%s' in a scalar context"), array_vname(t));
1871 
1872 	return t;
1873 }
1874 
1875 /* POP_STRING --- pop the string at the top of the stack */
1876 #define POP_STRING()	force_string(POP_SCALAR())
1877 
1878 /* TOP_STRING --- get the string at the top of the stack */
1879 #define TOP_STRING()	force_string(TOP_SCALAR())
1880 
1881 /* in_array --- return pointer to element in array if there */
1882 
1883 static inline NODE *
in_array(NODE * a,NODE * s)1884 in_array(NODE *a, NODE *s)
1885 {
1886 	NODE **ret;
1887 
1888 	ret = a->aexists(a, s);
1889 
1890 	return ret ? *ret : NULL;
1891 }
1892 
1893 #ifdef GAWKDEBUG
1894 #define dupnode	r_dupnode
1895 #else
1896 /* dupnode --- up the reference on a node */
1897 
1898 static inline NODE *
dupnode(NODE * n)1899 dupnode(NODE *n)
1900 {
1901 	if ((n->flags & MALLOC) != 0) {
1902 		n->valref++;
1903 		return n;
1904 	}
1905 	return r_dupnode(n);
1906 }
1907 #endif
1908 
1909 /*
1910  * force_string_fmt --- force a node to have a string value in a given format.
1911  * The string representation of a number may change due to whether it was most
1912  * recently rendered with CONVFMT or OFMT, or due to changes in the CONVFMT
1913  * and OFMT values. But if the value entered gawk as a string or strnum, then
1914  * stfmt should be set to STFMT_UNUSED, and the string representation should
1915  * not change.
1916  *
1917  * Additional twist: If ROUNDMODE changed at some point we have to
1918  * recompute also.
1919  */
1920 
1921 static inline NODE *
force_string_fmt(NODE * s,const char * fmtstr,int fmtidx)1922 force_string_fmt(NODE *s, const char *fmtstr, int fmtidx)
1923 {
1924 	if ((s->flags & STRCUR) != 0
1925 		&& (s->stfmt == STFMT_UNUSED || (s->stfmt == fmtidx
1926 #ifdef HAVE_MPFR
1927 						&& s->strndmode == MPFR_round_mode
1928 #endif
1929 				)))
1930 		return s;
1931 	return format_val(fmtstr, fmtidx, s);
1932 }
1933 
1934 /* conceptually should be force_string_convfmt, but this is the typical case */
1935 #define force_string(s)		force_string_fmt((s), CONVFMT, CONVFMTidx)
1936 
1937 #define force_string_ofmt(s)	force_string_fmt((s), OFMT, OFMTidx)
1938 
1939 #ifdef GAWKDEBUG
1940 #define unref	r_unref
1941 #define	force_number	str2number
1942 #else /* not GAWKDEBUG */
1943 
1944 /* unref --- decrease the reference count and/or free a node */
1945 
1946 static inline void
unref(NODE * r)1947 unref(NODE *r)
1948 {
1949 	assert(r == NULL || r->valref > 0);
1950 	if (r != NULL && --r->valref <= 0)
1951 		r_unref(r);
1952 }
1953 
1954 /* force_number --- force a  node to have a numeric value */
1955 
1956 static inline NODE *
force_number(NODE * n)1957 force_number(NODE *n)
1958 {
1959 	return (n->flags & NUMCUR) != 0 ? n : str2number(n);
1960 }
1961 
1962 #endif /* GAWKDEBUG */
1963 
1964 
1965 /* fixtype --- make a node decide if it's a number or a string */
1966 
1967 /*
1968  * In certain contexts, the true type of a scalar value matters, and we
1969  * must ascertain whether it is a NUMBER or a STRING. In such situations,
1970  * please use this function to resolve the type.
1971  *
1972  * It is safe to assume that the return value will be the same NODE,
1973  * since force_number on a USER_INPUT should always return the same NODE,
1974  * and force_string on an INTIND should as well.
1975  */
1976 
1977 static inline NODE *
fixtype(NODE * n)1978 fixtype(NODE *n)
1979 {
1980 	assert(n->type == Node_val);
1981 	if ((n->flags & (NUMCUR|USER_INPUT)) == USER_INPUT)
1982 		return force_number(n);
1983 	if ((n->flags & INTIND) != 0)
1984 		return force_string(n);
1985 	return n;
1986 }
1987 
1988 /* boolval --- return true/false based on awk's criteria */
1989 
1990 /*
1991  * In awk, a value is considered to be true if it is nonzero _or_
1992  * non-null. Otherwise, the value is false.
1993  */
1994 
1995 static inline bool
boolval(NODE * t)1996 boolval(NODE *t)
1997 {
1998 	(void) fixtype(t);
1999 	if ((t->flags & NUMBER) != 0)
2000 		return ! is_zero(t);
2001 	return (t->stlen > 0);
2002 }
2003 
2004 /* emalloc_real --- malloc with error checking */
2005 
2006 static inline void *
emalloc_real(size_t count,const char * where,const char * var,const char * file,int line)2007 emalloc_real(size_t count, const char *where, const char *var, const char *file, int line)
2008 {
2009 	void *ret;
2010 
2011 	if (count == 0)
2012 		fatal("%s:%d: emalloc called with zero bytes", file, line);
2013 
2014 	ret = (void *) malloc(count);
2015 	if (ret == NULL)
2016 		fatal(_("%s:%d:%s: %s: cannot allocate %ld bytes of memory: %s"),
2017 			file, line, where, var, (long) count, strerror(errno));
2018 
2019 	return ret;
2020 }
2021 
2022 /* ezalloc_real --- malloc zero-filled bytes with error checking */
2023 
2024 static inline void *
ezalloc_real(size_t count,const char * where,const char * var,const char * file,int line)2025 ezalloc_real(size_t count, const char *where, const char *var, const char *file, int line)
2026 {
2027 	void *ret;
2028 
2029 	if (count == 0)
2030 		fatal("%s:%d: ezalloc called with zero bytes", file, line);
2031 
2032 	ret = (void *) calloc(1, count);
2033 	if (ret == NULL)
2034 		fatal(_("%s:%d:%s: %s: cannot allocate %ld bytes of memory: %s"),
2035 			file, line, where, var, (long) count, strerror(errno));
2036 
2037 	return ret;
2038 }
2039 
2040 /* erealloc_real --- realloc with error checking */
2041 
2042 static inline void *
erealloc_real(void * ptr,size_t count,const char * where,const char * var,const char * file,int line)2043 erealloc_real(void *ptr, size_t count, const char *where, const char *var, const char *file, int line)
2044 {
2045 	void *ret;
2046 
2047 	if (count == 0)
2048 		fatal("%s:%d: erealloc called with zero bytes", file, line);
2049 
2050 	ret = (void *) realloc(ptr, count);
2051 	if (ret == NULL)
2052 		fatal(_("%s:%d:%s: %s: cannot reallocate %ld bytes of memory: %s"),
2053 			file, line, where, var, (long) count, strerror(errno));
2054 
2055 	return ret;
2056 }
2057 
2058 /* make_number_node --- make node with the given flags */
2059 
2060 static inline NODE *
make_number_node(unsigned int flags)2061 make_number_node(unsigned int flags)
2062 {
2063 	NODE *r;
2064 	getnode(r);
2065 	memset(r, 0, sizeof(*r));
2066 	r->type = Node_val;
2067 	r->valref = 1;
2068 	r->flags = (flags|MALLOC|NUMBER|NUMCUR);
2069 	return r;
2070 }
2071 
2072 /* assoc_set -- set an element in an array. Does unref(sub)! */
2073 
2074 static inline void
assoc_set(NODE * array,NODE * sub,NODE * value)2075 assoc_set(NODE *array, NODE *sub, NODE *value)
2076 {
2077 
2078 	NODE **lhs = assoc_lookup(array, sub);
2079 	unref(*lhs);
2080 	*lhs = value;
2081 	if (array->astore != NULL)
2082 		(*array->astore)(array, sub);
2083 	unref(sub);
2084 }
2085 
2086 /*
2087  * str_terminate_f, str_terminate, str_restore: function and macros to
2088  * reduce chances of typos when terminating and restoring strings.
2089  * This also helps to enforce that the NODE must be in scope when we restore.
2090  */
2091 
2092 static inline void
str_terminate_f(NODE * n,char * savep)2093 str_terminate_f(NODE *n, char *savep)
2094 {
2095 	*savep = n->stptr[n->stlen];
2096 	n->stptr[n->stlen] = '\0';
2097 }
2098 
2099 #define str_terminate(n, save) str_terminate_f((n), &save)
2100 #define str_restore(n, save) (n)->stptr[(n)->stlen] = save
2101 
2102 #ifdef SIGPIPE
2103 #define ignore_sigpipe() signal(SIGPIPE, SIG_IGN)
2104 #define set_sigpipe_to_default() signal(SIGPIPE, SIG_DFL)
2105 #define die_via_sigpipe() (signal(SIGPIPE, SIG_DFL), kill(getpid(), SIGPIPE))
2106 #else
2107 #define ignore_sigpipe()
2108 #define set_sigpipe_to_default()
2109 #ifdef __MINGW32__
2110 /* 0xC0000008 is EXCEPTION_INVALID_HANDLE, somewhat appropriate for EPIPE */
2111 #define die_via_sigpipe() exit(0xC0000008)
2112 #else  /* !__MINGW32__ */
2113 #define die_via_sigpipe() exit(EXIT_FATAL)
2114 #endif	/* !__MINGW32__ */
2115 #endif
2116