diff options
Diffstat (limited to 'awk.h')
-rw-r--r-- | awk.h | 922 |
1 files changed, 616 insertions, 306 deletions
@@ -117,14 +117,22 @@ extern int errno; #if HAVE_STDINT_H # include <stdint.h> #endif +#else /* ZOS_USS */ +#include <limits.h> +#include <sys/time.h> +#define INT32_MAX INT_MAX +#define INT32_MIN INT_MIN +#ifndef __uint32_t +#define __uint32_t 1 +typedef unsigned long uint32_t; +#endif +typedef long int32_t; #endif /* !ZOS_USS */ /* ----------------- System dependencies (with more includes) -----------*/ /* This section is the messiest one in the file, not a lot that can be done */ -#define MALLOC_ARG_T size_t - #ifndef VMS #ifdef HAVE_FCNTL_H #include <fcntl.h> @@ -146,10 +154,6 @@ typedef int off_t; # endif #endif /* VMS */ -#if ! defined(S_ISREG) && defined(S_IFREG) -#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#endif - #include "protos.h" #ifdef HAVE_STRING_H @@ -184,10 +188,6 @@ typedef int off_t; #define setlocale(locale, val) /* nothing */ #endif /* HAVE_SETLOCALE */ -#ifndef HAVE_SETSID -#define setsid() /* nothing */ -#endif /* HAVE_SETSID */ - #if HAVE_MEMCPY_ULONG extern char *memcpy_ulong(char *dest, const char *src, unsigned long l); #define memcpy memcpy_ulong @@ -210,6 +210,18 @@ typedef void *stackoverflow_context_t; this is a hack but it gives us the right semantics */ #define lintwarn (*(set_loc(__FILE__, __LINE__),lintfunc)) +#ifdef HAVE_MPFR +#include <gmp.h> +#include <mpfr.h> +#ifndef MPFR_RNDN +/* for compatibility with MPFR 2.X */ +#define MPFR_RNDN GMP_RNDN +#define MPFR_RNDZ GMP_RNDZ +#define MPFR_RNDU GMP_RNDU +#define MPFR_RNDD GMP_RNDD +#endif +#endif + #include "regex.h" #include "dfa.h" typedef struct Regexp { @@ -219,6 +231,8 @@ typedef struct Regexp { short dfa; short has_anchor; /* speed up of avoid_dfa kludge, temporary */ short non_empty; /* for use in fpat_parse_field */ + short has_meta; /* re has meta chars so (probably) isn't simple string */ + short maybe_long; /* re has meta chars that can match long text */ } Regexp; #define RESTART(rp,s) (rp)->regs.start[0] #define REEND(rp,s) (rp)->regs.end[0] @@ -230,6 +244,8 @@ typedef struct Regexp { #define RE_NEED_START 1 /* need to know start/end of match */ #define RE_NO_BOL 2 /* not allowed to match ^ in regexp */ +#include "gawkapi.h" + /* Stuff for losing systems. */ #if !defined(HAVE_STRTOD) extern double gawk_strtod(); @@ -254,27 +270,11 @@ extern double gawk_strtod(); #define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3) #endif /* ATTRIBUTE_PRINTF */ -/* We use __extension__ in some places to suppress -pedantic warnings - about GCC extensions. This feature didn't work properly before - gcc 2.8. */ -#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) -#define __extension__ -#endif - /* ------------------ Constants, Structures, Typedefs ------------------ */ #define AWKNUM double -#ifndef TRUE -/* a bit hackneyed, but what the heck */ -#define TRUE 1 -#define FALSE 0 -#endif - -#define LINT_INVALID 1 /* only warn about invalid */ -#define LINT_ALL 2 /* warn about all things */ - -enum defrule {BEGIN = 1, Rule, END, BEGINFILE, ENDFILE, +enum defrule { BEGIN = 1, Rule, END, BEGINFILE, ENDFILE, MAXRULE /* sentinel, not legal */ }; extern const char *const ruletab[]; @@ -293,10 +293,12 @@ typedef enum nodevals { Node_var_new, /* newly created variable, may become an array */ Node_param_list, /* lnode is a variable, rnode is more list */ Node_func, /* lnode is param. list, rnode is body */ + Node_ext_func, /* extension function, code_ptr is builtin code */ - Node_hashnode, /* an identifier in the symbol table */ - Node_ahash, /* an array element */ Node_array_ref, /* array passed by ref as parameter */ + Node_array_tree, /* Hashed array tree (HAT) */ + Node_array_leaf, /* Linear 1-D array */ + Node_dump_array, /* array info */ /* program execution -- stack item types */ Node_arrayfor, @@ -306,9 +308,44 @@ typedef enum nodevals { Node_final /* sentry value, not legal */ } NODETYPE; +struct exp_node; + +typedef union bucket_item { + struct { + union bucket_item *next; + char *str; + size_t len; + size_t code; + struct exp_node *name; + struct exp_node *val; + } hs; + struct { + union bucket_item *next; + long li[2]; + struct exp_node *val[2]; + size_t cnt; + } hi; +} BUCKET; + +/* string hash table */ +#define ahnext hs.next +#define ahname hs.name /* a string index node */ +#define ahname_str hs.str /* shallow copy; = ahname->stptr */ +#define ahname_len hs.len /* = ahname->stlen */ +#define ahvalue hs.val +#define ahcode hs.code + +/* integer hash table */ +#define ainext hi.next +#define ainum hi.li /* integer indices */ +#define aivalue hi.val +#define aicount hi.cnt struct exp_instruction; +typedef int (*Func_print)(FILE *, const char *, ...); +typedef struct exp_node **(*array_ptr)(struct exp_node *, struct exp_node *); + /* * NOTE - this struct is a rather kludgey -- it is packed to minimize * space usage, at the expense of cleanliness. Alter at own risk. @@ -320,13 +357,15 @@ typedef struct exp_node { struct exp_node *lptr; struct exp_instruction *li; long ll; + array_ptr *lp; } l; union { struct exp_node *rptr; Regexp *preg; struct exp_node **av; + BUCKET **bv; void (*uptr)(void); - struct exp_instruction *ri; + struct exp_instruction *iptr; } r; union { struct exp_node *extra; @@ -335,16 +374,27 @@ typedef struct exp_node { char **param_list; } x; char *name; + size_t reserved; struct exp_node *rn; + unsigned long cnt; unsigned long reflags; # define CASE 1 # define CONSTANT 2 # define FS_DFLT 4 } nodep; + struct { +#ifdef HAVE_MPFR + union { + AWKNUM fltnum; + mpfr_t mpnum; + mpz_t mpi; + } nm; +#else AWKNUM fltnum; /* this is here for optimal packing of - * the structure on many machines - */ + * the structure on many machines + */ +#endif char *sp; size_t slen; long sref; @@ -354,97 +404,126 @@ typedef struct exp_node { size_t wslen; #endif } val; - struct { - AWKNUM num; - struct exp_node *next; - char *name; - size_t length; - struct exp_node *value; - long ref; - size_t code; - } hash; -#define hnext sub.hash.next -#define hname sub.hash.name -#define hlength sub.hash.length -#define hvalue sub.hash.value - -#define ahnext sub.hash.next -#define ahname_str sub.hash.name -#define ahname_len sub.hash.length -#define ahname_num sub.hash.num -#define ahvalue sub.hash.value -#define ahname_ref sub.hash.ref -#define ahcode sub.hash.code } sub; NODETYPE type; - unsigned short flags; -# define MALLOC 1 /* can be free'd */ -# define PERM 2 /* can't be free'd */ -# define STRING 4 /* assigned as string */ -# define STRCUR 8 /* string value is current */ -# define NUMCUR 16 /* numeric value is current */ -# define NUMBER 32 /* assigned as number */ -# define MAYBE_NUM 64 /* user input: if NUMERIC then - * a NUMBER */ -# define ARRAYMAXED 128 /* array is at max size */ -# define FUNC 256 /* this parameter is really a - * function name; see awkgram.y */ -# define FIELD 512 /* this is a field */ -# define INTLSTR 1024 /* use localized version */ -# define NUMIND 2048 /* numeric val of index is current */ -# define WSTRCUR 4096 /* wide str value is current */ + unsigned int flags; + +/* any type */ +# define MALLOC 0x0001 /* can be free'd */ + +/* type = Node_val */ +# define STRING 0x0002 /* assigned as string */ +# define STRCUR 0x0004 /* string value is current */ +# define NUMCUR 0x0008 /* numeric value is current */ +# define NUMBER 0x0010 /* assigned as number */ +# define MAYBE_NUM 0x0020 /* user input: if NUMERIC then + * a NUMBER */ +# define FIELD 0x0040 /* this is a field */ +# define INTLSTR 0x0080 /* use localized version */ +# define NUMINT 0x0100 /* numeric value is an integer */ +# define INTIND 0x0200 /* integral value is array index; + * lazy conversion to string. + */ +# define WSTRCUR 0x0400 /* wide str value is current */ +# define MPFN 0x0800 /* arbitrary-precision floating-point number */ +# define MPZN 0x1000 /* arbitrary-precision integer */ +# define NO_EXT_SET 0x2000 /* extension cannot set a value for this variable */ + +/* type = Node_var_array */ +# define ARRAYMAXED 0x4000 /* array is at max size */ +# define HALFHAT 0x8000 /* half-capacity Hashed Array Tree; + * See cint_array.c */ +# define XARRAY 0x10000 } NODE; - #define vname sub.nodep.name #define lnode sub.nodep.l.lptr #define nextp sub.nodep.l.lptr #define rnode sub.nodep.r.rptr -#define param_cnt sub.nodep.l.ll -#define param vname +/* Node_param_list */ +#define param vname +#define dup_ent sub.nodep.r.rptr -#define parmlist sub.nodep.x.param_list -#define code_ptr sub.nodep.r.ri +/* Node_param_list, Node_func */ +#define param_cnt sub.nodep.l.ll +/* Node_func */ +#define fparms sub.nodep.rn +#define code_ptr sub.nodep.r.iptr + +/* Node_regex, Node_dynregex */ #define re_reg sub.nodep.r.preg #define re_flags sub.nodep.reflags #define re_text lnode #define re_exp sub.nodep.x.extra -#define re_cnt flags +#define re_cnt flags +/* Node_val */ #define stptr sub.val.sp #define stlen sub.val.slen #define valref sub.val.sref -#define stfmt sub.val.idx - +#define stfmt sub.val.idx #define wstptr sub.val.wsp #define wstlen sub.val.wslen +#ifdef HAVE_MPFR +#define mpg_numbr sub.val.nm.mpnum +#define mpg_i sub.val.nm.mpi +#define numbr sub.val.nm.fltnum +#else +#define numbr sub.val.fltnum +#endif -#define numbr sub.val.fltnum +/* Node_arrayfor */ +#define for_list sub.nodep.r.av +#define for_list_size sub.nodep.reflags +#define cur_idx sub.nodep.l.ll +#define for_array sub.nodep.rn /* Node_frame: */ #define stack sub.nodep.r.av #define func_node sub.nodep.x.extra #define prev_frame_size sub.nodep.reflags #define reti sub.nodep.l.li +#define num_tail_calls sub.nodep.cnt /* Node_var: */ -#define var_value lnode +#define var_value lnode #define var_update sub.nodep.r.uptr #define var_assign sub.nodep.x.aptr /* Node_var_array: */ -#define var_array sub.nodep.r.av -#define array_size sub.nodep.l.ll -#define table_size sub.nodep.x.xl -#define parent_array sub.nodep.rn +#define buckets sub.nodep.r.bv +#define nodes sub.nodep.r.av +#define array_funcs sub.nodep.l.lp +#define array_base sub.nodep.l.ll +#define table_size sub.nodep.reflags +#define array_size sub.nodep.cnt +#define array_capacity sub.nodep.reserved +#define xarray sub.nodep.rn +#define parent_array sub.nodep.x.extra + +/* array_funcs[0] is the array initialization function and + * array_funcs[1] is the index type checking function + */ +#define alookup array_funcs[2] +#define aexists array_funcs[3] +#define aclear array_funcs[4] +#define aremove array_funcs[5] +#define alist array_funcs[6] +#define acopy array_funcs[7] +#define adump array_funcs[8] +#define NUM_AFUNCS 9 /* # of entries in array_funcs */ /* Node_array_ref: */ #define orig_array lnode #define prev_array rnode +/* Node_array_print */ +#define adepth sub.nodep.l.ll +#define alevel sub.nodep.x.xl + /* --------------------------------lint warning types----------------------------*/ typedef enum lintvals { LINT_illegal, @@ -542,6 +621,7 @@ typedef enum opcodeval { Op_builtin, Op_sub_builtin, /* sub, gsub and gensub */ + Op_ext_builtin, Op_in_array, /* boolean test of membership in array */ /* function call instruction */ @@ -549,7 +629,7 @@ typedef enum opcodeval { Op_indirect_func_call, Op_push, /* scalar variable */ - Op_push_arg, /* variable type (scalar or array) argument to built-in */ + Op_push_arg, /* variable type (scalar or array) argument to built-in */ Op_push_i, /* number, string */ Op_push_re, /* regex */ Op_push_array, @@ -574,7 +654,6 @@ typedef enum opcodeval { Op_after_beginfile, Op_after_endfile, - Op_ext_func, Op_func, Op_exec_count, @@ -603,7 +682,8 @@ typedef enum opcodeval { enum redirval { /* I/O redirections */ - redirect_output = 1, + redirect_none = 0, + redirect_output, redirect_append, redirect_pipe, redirect_pipein, @@ -619,6 +699,7 @@ typedef struct exp_instruction { NODE *dn; struct exp_instruction *di; NODE *(*fptr)(int); + awk_value_t *(*efptr)(int, awk_value_t *); long dl; char *name; } d; @@ -639,6 +720,7 @@ typedef struct exp_instruction { #define memory d.dn #define builtin d.fptr +#define extfunc d.efptr #define builtin_idx d.dl #define expr_count x.xl @@ -675,6 +757,7 @@ typedef struct exp_instruction { /* Op_token */ #define lextok d.name +#define param_count x.xl /* Op_rule */ #define in_rule x.xl @@ -683,11 +766,11 @@ typedef struct exp_instruction { /* Op_K_case, Op_K_default */ #define case_stmt x.xi #define case_exp d.di -#define stmt_start case_exp -#define stmt_end case_stmt -#define match_exp x.xl +#define stmt_start case_exp +#define stmt_end case_stmt +#define match_exp x.xl -#define target_stmt x.xi +#define target_stmt x.xi /* Op_K_switch */ #define switch_end x.xi @@ -712,7 +795,7 @@ typedef struct exp_instruction { #define func_body x.xn /* Op_func_call */ -#define inrule d.dl +#define tail_call d.dl /* Op_subscript */ #define sub_count d.dl @@ -747,9 +830,9 @@ typedef struct exp_instruction { #define assign_ctxt d.dl /* Op_concat */ -#define concat_flag d.dl -#define CSUBSEP 1 -#define CSVAR 2 +#define concat_flag d.dl +#define CSUBSEP 1 +#define CSVAR 2 /* Op_breakpoint */ #define break_pt x.bpt @@ -779,10 +862,11 @@ typedef struct exp_instruction { #define condpair_left d.di #define condpair_right x.xi +/* Op_store_var */ +#define initval x.xn + typedef struct iobuf { - const char *name; /* filename */ - int fd; /* file descriptor */ - struct stat sbuf; /* stat buf */ + awk_input_buf_t public; /* exposed to extensions */ char *buf; /* start data buffer */ char *off; /* start of current record in buffer */ char *dataend; /* first byte in buffer to hold new data, @@ -793,19 +877,20 @@ typedef struct iobuf { ssize_t count; /* amount read last time */ size_t scanoff; /* where we were in the buffer when we had to regrow/refill */ + /* + * No argument prototype on read_func. See get_src_buf() + * in awkgram.y. + */ + ssize_t (*read_func)(); - void *opaque; /* private data for open hooks */ - int (*get_record)(char **out, struct iobuf *, int *errcode); - void (*close_func)(struct iobuf *); /* open and close hooks */ - + bool valid; int errcode; int flag; # define IOP_IS_TTY 1 -# define IOP_NOFREE_OBJ 2 -# define IOP_AT_EOF 4 -# define IOP_CLOSED 8 -# define IOP_AT_START 16 +# define IOP_AT_EOF 2 +# define IOP_CLOSED 4 +# define IOP_AT_START 8 } IOBUF; typedef void (*Func_ptr)(void); @@ -826,7 +911,6 @@ struct redirect { # define RED_SOCKET 1024 # define RED_TCP 2048 char *value; - FILE *fp; FILE *ifp; /* input fp, needed for PIPES_SIMULATED */ IOBUF *iop; int pid; @@ -834,6 +918,7 @@ struct redirect { struct redirect *prev; struct redirect *next; const char *mode; + awk_output_buf_t output; }; /* values for BINMODE, used as bit flags */ @@ -853,8 +938,14 @@ typedef struct srcfile { struct srcfile *next; struct srcfile *prev; - enum srctype { SRC_CMDLINE = 1, SRC_STDIN, SRC_FILE, SRC_INC } stype; - char *src; /* name on command line or inclde statement */ + enum srctype { + SRC_CMDLINE = 1, + SRC_STDIN, + SRC_FILE, + SRC_INC, + SRC_EXTLIB + } stype; + char *src; /* name on command line or include statement */ char *fullpath; /* full path after AWKPATH search */ time_t mtime; struct stat sbuf; @@ -880,7 +971,7 @@ typedef struct context { SRCFILE srcfiles; int sourceline; char *source; - void (*install_func)(char *); + void (*install_func)(NODE *); struct context *prev; } AWK_CONTEXT; @@ -890,6 +981,20 @@ struct flagtab { const char *name; }; + +typedef struct block_item { + size_t size; + struct block_item *freep; +} BLOCK; + +enum block_id { + BLOCK_INVALID = 0, /* not legal */ + BLOCK_NODE, + BLOCK_BUCKET, + BLOCK_MAX /* count */ +}; + + #ifndef LONG_MAX #define LONG_MAX ((long)(~(1L << (sizeof (long) * 8 - 1)))) #endif @@ -908,7 +1013,7 @@ extern long NR; extern long FNR; extern int BINMODE; extern int IGNORECASE; -extern int RS_is_null; +extern bool RS_is_null; extern char *OFS; extern int OFSlen; extern char *ORS; @@ -923,29 +1028,58 @@ extern NODE *FNR_node, *FS_node, *IGNORECASE_node, *NF_node; extern NODE *NR_node, *OFMT_node, *OFS_node, *ORS_node, *RLENGTH_node; extern NODE *RSTART_node, *RS_node, *RT_node, *SUBSEP_node, *PROCINFO_node; extern NODE *LINT_node, *ERRNO_node, *TEXTDOMAIN_node, *FPAT_node; +extern NODE *PREC_node, *ROUNDMODE_node; extern NODE *Nnull_string; extern NODE *Null_field; extern NODE **fields_arr; extern int sourceline; extern char *source; +extern int (*interpret)(INSTRUCTION *); /* interpreter routine */ +extern NODE *(*make_number)(double); /* double instead of AWKNUM on purpose */ +extern NODE *(*str2number)(NODE *); +extern NODE *(*format_val)(const char *, int, NODE *); +extern int (*cmp_numbers)(const NODE *, const NODE *); + +typedef int (*Func_pre_exec)(INSTRUCTION **); +typedef void (*Func_post_exec)(INSTRUCTION *); + +extern BLOCK nextfree[]; +extern bool field0_valid; + +extern int do_flags; + +enum do_flag_values { + DO_LINT_INVALID = 0x0001, /* only warn about invalid */ + DO_LINT_ALL = 0x0002, /* warn about all things */ + DO_LINT_OLD = 0x0004, /* warn about stuff not in V7 awk */ + DO_TRADITIONAL = 0x0008, /* no gnu extensions, add traditional weirdnesses */ + DO_POSIX = 0x0010, /* turn off gnu and unix extensions */ + DO_INTL = 0x0020, /* dump locale-izable strings to stdout */ + DO_NON_DEC_DATA = 0x0040, /* allow octal/hex C style DATA. Use with caution! */ + DO_INTERVALS = 0x0080, /* allow {...,...} in regexps, see resetup() */ + DO_PRETTY_PRINT = 0x0100, /* pretty print the program */ + DO_DUMP_VARS = 0x0200, /* dump all global variables at end */ + DO_TIDY_MEM = 0x0400, /* release vars when done */ + DO_SANDBOX = 0x0800, /* sandbox mode - disable 'system' function & redirections */ + DO_PROFILE = 0x1000, /* profile the program */ + DO_DEBUG = 0x2000, /* debug the program */ + DO_MPFR = 0x4000 /* arbitrary-precision floating-point math */ +}; -#if __GNUC__ < 2 -extern NODE *_t; /* used as temporary in tree_eval */ -#endif -extern NODE *_r; /* used as temporary in stack macros */ - -extern NODE *nextfree; -extern int field0_valid; -extern int do_traditional; -extern int do_posix; -extern int do_intervals; -extern int do_intl; -extern int do_non_decimal_data; -extern int do_profiling; -extern int do_dump_vars; -extern int do_tidy_mem; -extern int do_sandbox; -extern int do_optimize; +#define do_traditional (do_flags & DO_TRADITIONAL) +#define do_posix (do_flags & DO_POSIX) +#define do_intl (do_flags & DO_INTL) +#define do_non_decimal_data (do_flags & DO_NON_DEC_DATA) +#define do_intervals (do_flags & DO_INTERVALS) +#define do_pretty_print (do_flags & DO_PRETTY_PRINT) +#define do_profile (do_flags & DO_PROFILE) +#define do_dump_vars (do_flags & DO_DUMP_VARS) +#define do_tidy_mem (do_flags & DO_TIDY_MEM) +#define do_sandbox (do_flags & DO_SANDBOX) +#define do_debug (do_flags & DO_DEBUG) +#define do_mpfr (do_flags & DO_MPFR) + +extern bool do_optimize; extern int use_lc_numeric; extern int exit_val; @@ -953,8 +1087,8 @@ extern int exit_val; #define do_lint 0 #define do_lint_old 0 #else -extern int do_lint; -extern int do_lint_old; +#define do_lint (do_flags & (DO_LINT_INVALID|DO_LINT_ALL)) +#define do_lint_old (do_flags & DO_LINT_OLD) #endif #if MBS_SUPPORT extern int gawk_mb_cur_max; @@ -971,27 +1105,31 @@ extern int ngroups; extern struct lconv loc; #endif /* HAVE_LOCALE_H */ +#ifdef HAVE_MPFR +extern mpfr_prec_t PRECISION; +extern mpfr_rnd_t ROUND_MODE; +extern mpz_t MNR; +extern mpz_t MFNR; +extern mpz_t mpzval; +extern bool do_ieee_fmt; /* emulate IEEE 754 floating-point format */ +#endif + + extern const char *myname; extern const char def_strftime_format[]; extern char quote; extern char *defpath; +extern char *deflibpath; extern char envsep; extern char casetable[]; /* for case-independent regexp matching */ -/* - * Provide a way for code to know which program is executing: - * gawk vs dgawk vs pgawk. - */ -enum exe_mode { exe_normal = 1, exe_debugging, exe_profiling }; -extern enum exe_mode which_gawk; /* (defined in eval.c) */ - /* ------------------------- Runtime stack -------------------------------- */ typedef union stack_item { - NODE *rptr; /* variable etc. */ - NODE **lptr; /* address of a variable etc. */ + NODE *rptr; /* variable etc. */ + NODE **lptr; /* address of a variable etc. */ } STACK_ITEM; extern STACK_ITEM *stack_ptr; @@ -999,83 +1137,82 @@ extern NODE *frame_ptr; extern STACK_ITEM *stack_bottom; extern STACK_ITEM *stack_top; -#define decr_sp() (stack_ptr--) +#define decr_sp() (stack_ptr--) #define incr_sp() ((stack_ptr < stack_top) ? ++stack_ptr : grow_stack()) -#define stack_adj(n) (stack_ptr += (n)) -#define stack_empty() (stack_ptr < stack_bottom) - -#define POP() decr_sp()->rptr -#define POP_ADDRESS() decr_sp()->lptr -#define PEEK(n) (stack_ptr - (n))->rptr -#define TOP() stack_ptr->rptr /* same as PEEK(0) */ -#define TOP_ADDRESS() stack_ptr->lptr -#define PUSH(r) (void) (incr_sp()->rptr = (r)) -#define PUSH_ADDRESS(l) (void) (incr_sp()->lptr = (l)) -#define REPLACE(r) (void) (stack_ptr->rptr = (r)) -#define REPLACE_ADDRESS(l) (void) (stack_ptr->lptr = (l)) - +#define stack_adj(n) (stack_ptr += (n)) +#define stack_empty() (stack_ptr < stack_bottom) + +#define POP() (decr_sp()->rptr) +#define POP_ADDRESS() (decr_sp()->lptr) +#define PEEK(n) ((stack_ptr - (n))->rptr) +#define TOP() (stack_ptr->rptr) /* same as PEEK(0) */ +#define TOP_ADDRESS() (stack_ptr->lptr) +#define PUSH(r) (void) (incr_sp()->rptr = (r)) +#define PUSH_ADDRESS(l) (void) (incr_sp()->lptr = (l)) +#define REPLACE(r) (void) (stack_ptr->rptr = (r)) +#define REPLACE_ADDRESS(l) (void) (stack_ptr->lptr = (l)) /* function param */ -#define GET_PARAM(n) frame_ptr->stack[n] +#define GET_PARAM(n) frame_ptr->stack[n] /* - * UPREF and DEREF --- simplified versions of dupnode and unref - * UPREF does not handle FIELD node. Most appropriate use is - * for elements on the runtime stack. When in doubt, use dupnode. - */ - -#define DEREF(r) ( _r = (r), (!(_r->flags & PERM) && (--_r->valref == 0)) ? unref(_r) : (void)0 ) - -#if __GNUC__ >= 2 -#define UPREF(r) ({ NODE *_t = (r); !(_t->flags & PERM) && _t->valref++;}) - -#define POP_ARRAY() ({ NODE *_t = POP(); \ - _t->type == Node_var_array ? \ - _t : get_array(_t, TRUE); }) - -#define POP_PARAM() ({ NODE *_t = POP(); \ - _t->type == Node_var_array ? \ - _t : get_array(_t, FALSE); }) - -#define POP_NUMBER(x) ({ NODE *_t = POP_SCALAR(); \ - x = force_number(_t); DEREF(_t); }) -#define TOP_NUMBER(x) ({ NODE *_t = TOP_SCALAR(); \ - x = force_number(_t); DEREF(_t); }) - -#define POP_SCALAR() ({ NODE *_t = POP(); _t->type != Node_var_array ? _t \ - : (fatal(_("attempt to use array `%s' in a scalar context"), array_vname(_t)), _t);}) -#define TOP_SCALAR() ({ NODE *_t = TOP(); _t->type != Node_var_array ? _t \ - : (fatal(_("attempt to use array `%s' in a scalar context"), array_vname(_t)), _t);}) - -#else /* not __GNUC__ */ - -#define UPREF(r) (_t = (r), !(_t->flags & PERM) && _t->valref++) - -#define POP_ARRAY() (_t = POP(), \ - _t->type == Node_var_array ? \ - _t : get_array(_t, TRUE)) - -#define POP_PARAM() (_t = POP(), \ - _t->type == Node_var_array ? \ - _t : get_array(_t, FALSE)) - -#define POP_NUMBER(x) (_t = POP_SCALAR(), \ - x = force_number(_t), DEREF(_t)) -#define TOP_NUMBER(x) (_t = TOP_SCALAR(), \ - x = force_number(_t), DEREF(_t)) + * UPREF --- simplified versions of dupnode, does not handle FIELD node. + * Most appropriate use is for elements on the runtime stack. + * When in doubt, use dupnode. + */ -#define POP_SCALAR() (_t = POP(), _t->type != Node_var_array ? _t \ - : (fatal(_("attempt to use array `%s' in a scalar context"), array_vname(_t)), _t)) -#define TOP_SCALAR() (_t = TOP(), _t->type != Node_var_array ? _t \ - : (fatal(_("attempt to use array `%s' in a scalar context"), array_vname(_t)), _t)) +#define UPREF(r) (void) ((r)->valref++) -#endif /* __GNUC__ */ +extern void r_unref(NODE *tmp); +static inline void +DEREF(NODE *r) +{ + if (--r->valref == 0) + r_unref(r); +} -#define POP_STRING() force_string(POP_SCALAR()) -#define TOP_STRING() force_string(TOP_SCALAR()) +#define POP_NUMBER() force_number(POP_SCALAR()) +#define TOP_NUMBER() force_number(TOP_SCALAR()) /* ------------------------- Pseudo-functions ------------------------- */ +#ifdef HAVE_MPFR +/* conversion to C types */ +#define get_number_ui(n) (((n)->flags & MPFN) ? mpfr_get_ui((n)->mpg_numbr, ROUND_MODE) \ + : ((n)->flags & MPZN) ? mpz_get_ui((n)->mpg_i) \ + : (unsigned long) (n)->numbr) +#define get_number_si(n) (((n)->flags & MPFN) ? mpfr_get_si((n)->mpg_numbr, ROUND_MODE) \ + : ((n)->flags & MPZN) ? mpz_get_si((n)->mpg_i) \ + : (long) (n)->numbr) +#define get_number_d(n) (((n)->flags & MPFN) ? mpfr_get_d((n)->mpg_numbr, ROUND_MODE) \ + : ((n)->flags & MPZN) ? mpz_get_d((n)->mpg_i) \ + : (double) (n)->numbr) +#define get_number_uj(n) (((n)->flags & MPFN) ? mpfr_get_uj((n)->mpg_numbr, ROUND_MODE) \ + : ((n)->flags & MPZN) ? (uintmax_t) mpz_get_d((n)->mpg_i) \ + : (uintmax_t) (n)->numbr) + +#define iszero(n) (((n)->flags & MPFN) ? mpfr_zero_p((n)->mpg_numbr) \ + : ((n)->flags & MPZN) ? (mpz_sgn((n)->mpg_i) == 0) \ + : ((n)->numbr == 0.0)) + +#define IEEE_FMT(r, t) (void) (do_ieee_fmt && format_ieee(r, t)) + +#define mpg_float() mpg_node(MPFN) +#define mpg_integer() mpg_node(MPZN) +#define is_mpg_float(n) (((n)->flags & MPFN) != 0) +#define is_mpg_integer(n) (((n)->flags & MPZN) != 0) +#define is_mpg_number(n) (((n)->flags & (MPZN|MPFN)) != 0) +#else +#define get_number_ui(n) (unsigned long) (n)->numbr +#define get_number_si(n) (long) (n)->numbr +#define get_number_d(n) (double) (n)->numbr +#define get_number_uj(n) (uintmax_t) (n)->numbr + +#define is_mpg_number(n) 0 +#define is_mpg_float(n) 0 +#define is_mpg_integer(n) 0 +#define iszero(n) ((n)->numbr == 0.0) +#endif #define is_identchar(c) (isalnum(c) || (c) == '_') @@ -1084,21 +1221,19 @@ extern STACK_ITEM *stack_top; #define get_lhs(n, r) (n)->type == Node_var && ! var_uninitialized(n) ? \ &((n)->var_value) : r_get_lhs((n), (r)) -#ifdef MPROF -#define getnode(n) emalloc((n), NODE *, sizeof(NODE), "getnode"), \ - (n)->flags = 0 -#define freenode(n) efree(n) -#else /* not MPROF */ -#define getnode(n) (void) (nextfree ? \ - (n = nextfree, nextfree = nextfree->nextp) \ - : (n = more_nodes())) -#define freenode(n) ((n)->flags = 0, (n)->nextp = nextfree, nextfree = (n)) -#endif /* not MPROF */ +#define getblock(p, id, ty) (void) ((p = (ty) nextfree[id].freep) ? \ + (ty) (nextfree[id].freep = ((BLOCK *) p)->freep) \ + : (p = (ty) more_blocks(id))) +#define freeblock(p, id) (void) (((BLOCK *) p)->freep = nextfree[id].freep, \ + nextfree[id].freep = (BLOCK *) p) + +#define getnode(n) getblock(n, BLOCK_NODE, NODE *) +#define freenode(n) freeblock(n, BLOCK_NODE) -#define make_number(x) mk_number((x), (unsigned int)(MALLOC|NUMCUR|NUMBER)) +#define getbucket(b) getblock(b, BLOCK_BUCKET, BUCKET *) +#define freebucket(b) freeblock(b, BLOCK_BUCKET) -#define make_string(s, l) r_make_str_node((s), (size_t) (l), 0) -#define make_str_node(s, l, f) r_make_str_node((s), (size_t) (l), (f)) +#define make_string(s, l) make_str_node((s), (l), 0) #define SCAN 1 #define ALREADY_MALLOCED 2 @@ -1106,97 +1241,117 @@ extern STACK_ITEM *stack_top; #define cant_happen() r_fatal("internal error line %d, file: %s", \ __LINE__, __FILE__) -#define emalloc(var,ty,x,str) (void)((var=(ty)malloc((MALLOC_ARG_T)(x))) ||\ +#define emalloc(var,ty,x,str) (void)((var=(ty)malloc((size_t)(x))) ||\ (fatal(_("%s: %s: can't allocate %ld bytes of memory (%s)"),\ (str), #var, (long) (x), strerror(errno)),0)) -#define erealloc(var,ty,x,str) (void)((var = (ty)realloc((char *)var, (MALLOC_ARG_T)(x))) \ +#define erealloc(var,ty,x,str) (void)((var = (ty)realloc((char *)var, (size_t)(x))) \ ||\ (fatal(_("%s: %s: can't allocate %ld bytes of memory (%s)"),\ (str), #var, (long) (x), strerror(errno)),0)) #define efree(p) free(p) +static inline NODE * +force_string(NODE *s) +{ + if ((s->flags & STRCUR) != 0 + && (s->stfmt == -1 || s->stfmt == CONVFMTidx) + ) + return s; + return format_val(CONVFMT, CONVFMTidx, s); +} + #ifdef GAWKDEBUG -#define force_number r_force_number -#define force_string r_force_string +#define unref r_unref +#define force_number str2number #else /* not GAWKDEBUG */ -#if __GNUC__ >= 2 -#define force_number(n) __extension__ ({NODE *_tn = (n);\ - (_tn->flags & NUMCUR) ? _tn->numbr : r_force_number(_tn);}) - -#define force_string(s) __extension__ ({NODE *_ts = (s);\ - ((_ts->flags & STRCUR) && \ - (_ts->stfmt == -1 || _ts->stfmt == CONVFMTidx)) ?\ - _ts : format_val(CONVFMT, CONVFMTidx, _ts);}) -#else /* not __GNUC__ */ -#define force_number r_force_number -#define force_string r_force_string -#endif /* __GNUC__ */ + +static inline void +unref(NODE *r) +{ + if (r != NULL && --r->valref <= 0) + r_unref(r); +} + +static inline NODE * +force_number(NODE *n) +{ + return (n->flags & NUMCUR) ? n : str2number(n); +} + #endif /* GAWKDEBUG */ #define fatal set_loc(__FILE__, __LINE__), r_fatal extern jmp_buf fatal_tag; -extern int fatal_tag_valid; +extern bool fatal_tag_valid; #define PUSH_BINDING(stack, tag, val) \ if (val++) \ memcpy((char *) (stack), (const char *) tag, sizeof(jmp_buf)) #define POP_BINDING(stack, tag, val) \ -if (--val) \ +if (--val) \ memcpy((char *) tag, (const char *) (stack), sizeof(jmp_buf)) -/* ------------- Function prototypes or defs (as appropriate) ------------- */ -typedef int (*Func_print)(FILE *, const char *, ...); +#define array_empty(a) ((a)->table_size == 0) +#define assoc_lookup(a, s) ((a)->alookup(a, s)) + +/* assoc_clear --- flush all the values in symbol[] */ +#define assoc_clear(a) (void) ((a)->aclear(a, NULL)) + +/* assoc_remove --- remove an index from symbol[] */ +#define assoc_remove(a, s) ((a)->aremove(a, s) != NULL) +/* ------------- Function prototypes or defs (as appropriate) ------------- */ /* array.c */ typedef enum sort_context { SORTED_IN = 1, ASORT, ASORTI } SORT_CTXT; -extern NODE **assoc_list(NODE *array, const char *sort_str, SORT_CTXT sort_ctxt); -extern NODE *get_array(NODE *symbol, int canfatal); -extern char *array_vname(const NODE *symbol); +enum assoc_list_flags { + AINDEX = 0x001, /* list of indices */ + AVALUE = 0x002, /* list of values */ + AINUM = 0x004, /* numeric index */ + AISTR = 0x008, /* string index */ + AVNUM = 0x010, /* numeric scalar value */ + AVSTR = 0x020, /* string scalar value */ + AASC = 0x040, /* ascending order */ + ADESC = 0x080, /* descending order */ + ADELETE = 0x100 /* need a single index; for use in do_delete_loop */ +}; + +extern NODE *make_array(void); +extern void init_array(NODE *symbol); +extern NODE *get_array(NODE *symbol, bool canfatal); +extern const char *make_aname(const NODE *symbol); +extern const char *array_vname(const NODE *symbol); extern void array_init(void); +extern int register_array_func(array_ptr *afunc); extern void set_SUBSEP(void); -extern NODE *concat_exp(int nargs, int do_subsep); -extern void ahash_unref(NODE *tmp); -extern void assoc_clear(NODE *symbol); -extern NODE *in_array(NODE *symbol, NODE *subs); -extern NODE **assoc_lookup(NODE *symbol, NODE *subs, int reference); +extern NODE *concat_exp(int nargs, bool do_subsep); +extern NODE *assoc_copy(NODE *symbol, NODE *newsymb); +extern void assoc_dump(NODE *symbol, NODE *p); +extern NODE **assoc_list(NODE *symbol, const char *sort_str, SORT_CTXT sort_ctxt); +extern void assoc_info(NODE *subs, NODE *val, NODE *p, const char *aname); extern void do_delete(NODE *symbol, int nsubs); extern void do_delete_loop(NODE *symbol, NODE **lhs); -extern NODE *assoc_dump(NODE *symbol, int indent_level); extern NODE *do_adump(int nargs); +extern NODE *do_aoption(int nargs); extern NODE *do_asort(int nargs); extern NODE *do_asorti(int nargs); extern unsigned long (*hash)(const char *s, size_t len, unsigned long hsize, size_t *code); /* awkgram.c */ -extern NODE *mk_symbol(NODETYPE type, NODE *value); -extern NODE *install_symbol(char *name, NODE *value); -extern NODE *remove_symbol(char *name); -extern NODE *lookup(const char *name); -extern NODE *variable(char *name, NODETYPE type); +extern NODE *variable(int location, char *name, NODETYPE type); extern int parse_program(INSTRUCTION **pcode); +extern void track_ext_func(const char *name); extern void dump_funcs(void); extern void dump_vars(const char *fname); -extern void release_all_vars(void); extern const char *getfname(NODE *(*)(int)); extern NODE *stopme(int nargs); extern void shadow_funcs(void); extern int check_special(const char *name); -extern int foreach_func(int (*)(INSTRUCTION *, void *), int, void *); -extern INSTRUCTION *bcalloc(OPCODE op, int size, int srcline); -extern void bcfree(INSTRUCTION *); -extern SRCFILE *add_srcfile(int stype, char *src, SRCFILE *curr, int *already_included, int *errcode); +extern SRCFILE *add_srcfile(int stype, char *src, SRCFILE *curr, bool *already_included, int *errcode); extern void register_deferred_variable(const char *name, NODE *(*load_func)(void)); extern int files_are_same(char *path, SRCFILE *src); extern void valinfo(NODE *n, Func_print print_func, FILE *fp); -extern void print_vars(Func_print print_func, FILE *fp); -extern AWK_CONTEXT *new_context(void); -extern void push_context(AWK_CONTEXT *ctxt); -extern void pop_context(); -extern int in_main_context(); -extern void free_context(AWK_CONTEXT *ctxt, int ); -extern void append_symbol(char *name); - +extern void negate_num(NODE *n); /* builtin.c */ extern double double_to_int(double d); extern NODE *do_exp(int nargs); @@ -1245,8 +1400,9 @@ extern int strncasecmpmbs(const unsigned char *, /* eval.c */ extern void PUSH_CODE(INSTRUCTION *cp); extern INSTRUCTION *POP_CODE(void); -extern int interpret(INSTRUCTION *); -extern int cmp_nodes(NODE *, NODE *); +extern void init_interpret(void); +extern int cmp_nodes(NODE *t1, NODE *t2); +extern int cmp_awknums(const NODE *t1, const NODE *t2); extern void set_IGNORECASE(void); extern void set_OFS(void); extern void set_ORS(void); @@ -1255,8 +1411,9 @@ extern void set_CONVFMT(void); extern void set_BINMODE(void); extern void set_LINT(void); extern void set_TEXTDOMAIN(void); -extern void update_ERRNO(void); -extern void update_ERRNO_saved(int); +extern void update_ERRNO_int(int); +extern void update_ERRNO_string(const char *string); +extern void unset_ERRNO(void); extern void update_NR(void); extern void update_NF(void); extern void update_FNR(void); @@ -1265,24 +1422,21 @@ extern const char *flags2str(int); extern const char *genflags2str(int flagval, const struct flagtab *tab); extern const char *nodetype2str(NODETYPE type); extern void load_casetable(void); - extern AWKNUM calc_exp(AWKNUM x1, AWKNUM x2); extern const char *opcode2str(OPCODE type); extern const char *op2str(OPCODE type); -extern NODE **r_get_lhs(NODE *n, int reference); +extern NODE **r_get_lhs(NODE *n, bool reference); extern STACK_ITEM *grow_stack(void); -#ifdef PROFILING extern void dump_fcall_stack(FILE *fp); -#endif +extern int register_exec_hook(Func_pre_exec preh, Func_post_exec posth); /* ext.c */ -NODE *do_ext(int nargs); +void load_ext(const char *lib_name); #ifdef DYNAMIC -void make_builtin(const char *, NODE *(*)(int), int); -size_t get_curfunc_arg_count(void); -NODE *get_argument(int); -NODE *get_actual_argument(int, int, int); -#define get_scalar_argument(i, opt) get_actual_argument((i), (opt), FALSE) -#define get_array_argument(i, opt) get_actual_argument((i), (opt), TRUE) +extern awk_bool_t make_builtin(const awk_ext_func_t *); +extern NODE *get_argument(int); +extern NODE *get_actual_argument(int, bool, bool); +#define get_scalar_argument(i, opt) get_actual_argument((i), (opt), false) +#define get_array_argument(i, opt) get_actual_argument((i), (opt), true) #endif /* field.c */ extern void init_fields(void); @@ -1306,6 +1460,14 @@ typedef enum { } field_sep_type; extern field_sep_type current_field_sep(void); +/* gawkapi.c: */ +extern gawk_api_t api_impl; +extern void init_ext_api(void); +extern void update_ext_api(void); +extern NODE *awk_value_to_node(const awk_value_t *); +extern void run_ext_exit_handlers(int exitval); +extern void print_ext_versions(void); + /* gawkmisc.c */ extern char *gawk_name(const char *filespec); extern void os_arg_fixup(int *argcp, char ***argvp); @@ -1313,6 +1475,7 @@ extern int os_devopen(const char *name, int flag); extern void os_close_on_exec(int fd, const char *name, const char *what, const char *dir); extern int os_isatty(int fd); extern int os_isdir(int fd); +extern int os_isreadable(const awk_input_buf_t *iobuf, bool *isdir); extern int os_is_setuid(void); extern int os_setbinmode(int fd, int mode); extern void os_restore_mode(int fd); @@ -1321,60 +1484,93 @@ extern int ispath(const char *file); extern int isdirpunct(int c); /* io.c */ -extern void register_open_hook(void *(*open_func)(IOBUF *)); +extern void init_io(void); +extern void register_input_parser(awk_input_parser_t *input_parser); +extern void register_output_wrapper(awk_output_wrapper_t *wrapper); +extern void register_two_way_processor(awk_two_way_processor_t *processor); extern void set_FNR(void); extern void set_NR(void); extern struct redirect *redirect(NODE *redir_exp, int redirtype, int *errflg); extern NODE *do_close(int nargs); extern int flush_io(void); -extern int close_io(int *stdio_problem); +extern int close_io(bool *stdio_problem); extern int devopen(const char *name, const char *mode); extern int srcopen(SRCFILE *s); -extern char *find_source(const char *src, struct stat *stb, int *errcode); -extern NODE *do_getline_redir(int intovar, int redirtype); +extern char *find_source(const char *src, struct stat *stb, int *errcode, int is_extlib); +extern NODE *do_getline_redir(int intovar, enum redirval redirtype); extern NODE *do_getline(int intovar, IOBUF *iop); extern struct redirect *getredirect(const char *str, int len); extern int inrec(IOBUF *iop, int *errcode); -extern int nextfile(IOBUF **curfile, int skipping); +extern int nextfile(IOBUF **curfile, bool skipping); /* main.c */ -extern int arg_assign(char *arg, int initing); +extern int arg_assign(char *arg, bool initing); extern int is_std_var(const char *var); +extern int is_off_limits_var(const char *var); extern char *estrdup(const char *str, size_t len); extern void update_global_values(); +extern long getenv_long(const char *name); + +/* mpfr.c */ +extern void set_PREC(void); +extern void set_ROUNDMODE(void); +extern void mpfr_unset(NODE *n); +#ifdef HAVE_MPFR +extern int mpg_cmp(const NODE *, const NODE *); +extern int format_ieee(mpfr_ptr, int); +extern NODE *mpg_update_var(NODE *); +extern long mpg_set_var(NODE *); +extern NODE *do_mpfr_and(int); +extern NODE *do_mpfr_atan2(int); +extern NODE *do_mpfr_compl(int); +extern NODE *do_mpfr_cos(int); +extern NODE *do_mpfr_exp(int); +extern NODE *do_mpfr_int(int); +extern NODE *do_mpfr_log(int); +extern NODE *do_mpfr_lshift(int); +extern NODE *do_mpfr_or(int); +extern NODE *do_mpfr_rand(int); +extern NODE *do_mpfr_rhift(int); +extern NODE *do_mpfr_sin(int); +extern NODE *do_mpfr_sqrt(int); +extern NODE *do_mpfr_srand(int); +extern NODE *do_mpfr_strtonum(int); +extern NODE *do_mpfr_xor(int); +extern void init_mpfr(mpfr_prec_t, const char *); +extern NODE *mpg_node(unsigned int); +extern const char *mpg_fmt(const char *, ...); +extern int mpg_strtoui(mpz_ptr, char *, size_t, char **, int); +#endif /* msg.c */ extern void gawk_exit(int status); -extern void err(const char *s, const char *emsg, va_list argp) ATTRIBUTE_PRINTF(2, 0); +extern void final_exit(int status) ATTRIBUTE_NORETURN; +extern void err(bool isfatal, const char *s, const char *emsg, va_list argp) ATTRIBUTE_PRINTF(3, 0); extern void msg (const char *mesg, ...) ATTRIBUTE_PRINTF_1; extern void error (const char *mesg, ...) ATTRIBUTE_PRINTF_1; extern void warning (const char *mesg, ...) ATTRIBUTE_PRINTF_1; extern void set_loc (const char *file, int line); extern void r_fatal (const char *mesg, ...) ATTRIBUTE_PRINTF_1; #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2) -extern void (*lintfunc) (const char *mesg, ...) ATTRIBUTE_PRINTF_1; +extern void (*lintfunc)(const char *mesg, ...) ATTRIBUTE_PRINTF_1; #else -extern void (*lintfunc) (const char *mesg, ...); +extern void (*lintfunc)(const char *mesg, ...); #endif /* profile.c */ -extern void init_profiling(int *flag, const char *def_file); extern void init_profiling_signals(void); extern void set_prof_file(const char *filename); extern void dump_prog(INSTRUCTION *code); -extern char *pp_number(AWKNUM d); +extern char *pp_number(NODE *n); extern char *pp_string(const char *in_str, size_t len, int delim); extern char *pp_node(NODE *n); extern int pp_func(INSTRUCTION *pc, void *); extern void pp_string_fp(Func_print print_func, FILE *fp, const char *str, - size_t namelen, int delim, int breaklines); + size_t namelen, int delim, bool breaklines); /* node.c */ -extern AWKNUM r_force_number(NODE *n); -extern NODE *format_val(const char *format, int index, NODE *s); -extern NODE *r_force_string(NODE *s); -extern NODE *dupnode(NODE *n); -extern NODE *mk_number(AWKNUM x, unsigned int flags); -extern NODE *r_make_str_node(const char *s, unsigned long len, int scan); -extern NODE *more_nodes(void); -extern void unref(NODE *tmp); +extern NODE *r_force_number(NODE *n); +extern NODE *r_format_val(const char *format, int index, NODE *s); +extern NODE *r_dupnode(NODE *n); +extern NODE *make_str_node(const char *s, size_t len, int flags); +extern void *more_blocks(int id); extern int parse_escape(const char **string_ptr); #if MBS_SUPPORT extern NODE *str2wstr(NODE *n, size_t **ptr); @@ -1384,7 +1580,8 @@ extern const wchar_t *wstrstr(const wchar_t *haystack, size_t hs_len, const wchar_t *needle, size_t needle_len); extern const wchar_t *wcasestrstr(const wchar_t *haystack, size_t hs_len, const wchar_t *needle, size_t needle_len); -extern void free_wstr(NODE *n); +extern void r_free_wstr(NODE *n); +#define free_wstr(n) do { if ((n)->flags & WSTRCUR) r_free_wstr(n); } while(0) extern wint_t btowc_cache[]; #define btowc_cache(x) btowc_cache[(x)&0xFF] extern void init_btowc_cache(); @@ -1393,7 +1590,7 @@ extern void init_btowc_cache(); #define free_wstr(NODE) /* empty */ #endif /* re.c */ -extern Regexp *make_regexp(const char *s, size_t len, int ignorecase, int dfa, int canfatal); +extern Regexp *make_regexp(const char *s, size_t len, bool ignorecase, bool dfa, bool canfatal); extern int research(Regexp *rp, char *str, int start, size_t len, int flags); extern void refree(Regexp *rp); extern void reg_error(const char *s); @@ -1402,8 +1599,34 @@ extern void resyntax(int syntax); extern void resetup(void); extern int avoid_dfa(NODE *re, char *str, size_t len); extern int reisstring(const char *text, size_t len, Regexp *re, const char *buf); -extern int remaybelong(const char *text, size_t len); -extern int isnondecimal(const char *str, int use_locale); +extern int get_numbase(const char *str, bool use_locale); + +/* symbol.c */ +extern void load_symbols(); +extern void init_symbol_table(); +extern NODE *symbol_table; +extern NODE *func_table; +extern NODE *install_symbol(char *name, NODETYPE type); +extern NODE *remove_symbol(NODE *r); +extern void destroy_symbol(NODE *r); +extern void release_symbols(NODE *symlist, int keep_globals); +extern void append_symbol(NODE *r); +extern NODE *lookup(const char *name); +extern NODE *make_params(char **pnames, int pcount); +extern void install_params(NODE *func); +extern void remove_params(NODE *func); +extern void release_all_vars(void); +extern int foreach_func(NODE **table, int (*)(INSTRUCTION *, void *), void *); +extern INSTRUCTION *bcalloc(OPCODE op, int size, int srcline); +extern void bcfree(INSTRUCTION *); +extern AWK_CONTEXT *new_context(void); +extern void push_context(AWK_CONTEXT *ctxt); +extern void pop_context(); +extern int in_main_context(); +extern void free_context(AWK_CONTEXT *ctxt, bool keep_globals); +extern NODE **variable_list(); +extern NODE **function_list(int sort); +extern void print_vars(NODE **table, Func_print print_func, FILE *fp); /* floatcomp.c */ #ifdef VMS /* VMS linker weirdness? */ @@ -1419,8 +1642,6 @@ extern uintmax_t adjust_uint(uintmax_t n); #define adjust_uint(n) (n) #endif -#define INVALID_HANDLE (-1) - #ifdef HAVE_SYS_WAIT_H #include <sys/wait.h> #endif @@ -1446,7 +1667,6 @@ extern uintmax_t adjust_uint(uintmax_t n); /* For z/OS, from Dave Pitts. EXIT_FAILURE is normally 8, make it 1. */ #ifdef ZOS_USS -#undef DYNAMIC #ifdef EXIT_FAILURE #undef EXIT_FAILURE @@ -1454,3 +1674,93 @@ extern uintmax_t adjust_uint(uintmax_t n); #define EXIT_FAILURE 1 #endif + +/* ------------------ Inline Functions ------------------ */ + +/* + * These must come last to get all the function declarations and + * macro definitions before their bodies. + * + * This is wasteful if the compiler doesn't support inline. We won't + * worry about it until someone complains. + */ + +/* POP_ARRAY --- get the array at the top of the stack */ + +static inline NODE * +POP_ARRAY() +{ + NODE *t = POP(); + + return (t->type == Node_var_array) ? t : get_array(t, true); +} + +/* POP_PARAM --- get the top parameter, array or scalar */ + +static inline NODE * +POP_PARAM() +{ + NODE *t = POP(); + + return (t->type == Node_var_array) ? t : get_array(t, false); +} + +/* POP_SCALAR --- pop the scalar at the top of the stack */ + +static inline NODE * +POP_SCALAR() +{ + NODE *t = POP(); + + if (t->type == Node_var_array) + fatal(_("attempt to use array `%s' in a scalar context"), array_vname(t)); + + return t; +} + +/* TOP_SCALAR --- get the scalar at the top of the stack */ + +static inline NODE * +TOP_SCALAR() +{ + NODE *t = TOP(); + + if (t->type == Node_var_array) + fatal(_("attempt to use array `%s' in a scalar context"), array_vname(t)); + + return t; +} + +/* POP_STRING --- pop the string at the top of the stack */ +#define POP_STRING() force_string(POP_SCALAR()) + +/* TOP_STRING --- get the string at the top of the stack */ +#define TOP_STRING() force_string(TOP_SCALAR()) + +/* in_array --- return pointer to element in array if there */ + +static inline NODE * +in_array(NODE *a, NODE *s) +{ + NODE **ret; + + ret = a->aexists(a, s); + + return ret ? *ret : NULL; +} + +#ifdef GAWKDEBUG +#define dupnode r_dupnode +#else +/* dupnode --- up the reference on a node */ + +static inline NODE * +dupnode(NODE *n) +{ + if ((n->flags & MALLOC) != 0) { + n->valref++; + return n; + } + return r_dupnode(n); +} +#endif |