"Fossies" - the Fresh Open Source Software Archive

Member "gawk-5.1.0/awk.h" (13 Apr 2020, 60783 Bytes) of package /linux/misc/gawk-5.1.0.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "awk.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.0.1_vs_5.1.0.

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