Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/editors/awk.c


Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/editors/awk.c

    r1765 r2725  
    55 * Copyright (C) 2002 by Dmitry Zakharov <dmit@crp.bank.gov.ua>
    66 *
    7  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1111#include "xregex.h"
    1212#include <math.h>
    13 extern char **environ;
    1413
    1514/* This is a NOEXEC applet. Be very careful! */
     15
     16
     17/* If you comment out one of these below, it will be #defined later
     18 * to perform debug printfs to stderr: */
     19#define debug_printf_walker(...)  do {} while (0)
     20#define debug_printf_eval(...)  do {} while (0)
     21
     22#ifndef debug_printf_walker
     23# define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__))
     24#endif
     25#ifndef debug_printf_eval
     26# define debug_printf_eval(...) (fprintf(stderr, __VA_ARGS__))
     27#endif
     28
    1629
    1730
     
    3346/* these flags are static, don't change them when value is changed */
    3447#define VF_DONTTOUCH    (VF_ARRAY | VF_SPECIAL | VF_WALK | VF_CHILD | VF_DIRTY)
     48
     49typedef struct walker_list {
     50    char *end;
     51    char *cur;
     52    struct walker_list *prev;
     53    char wbuf[1];
     54} walker_list;
    3555
    3656/* Variable */
     
    4363        struct xhash_s *array;  /* array ptr */
    4464        struct var_s *parent;   /* for func args, ptr to actual parameter */
    45         char **walker;          /* list of array elements (for..in) */
     65        walker_list *walker;    /* list of array elements (for..in) */
    4666    } x;
    4767} var;
     
    95115        struct node_s *n;
    96116        var *v;
    97         int i;
    98         char *s;
     117        int aidx;
     118        char *new_progname;
    99119        regex_t *re;
    100120    } l;
     
    103123        regex_t *ire;
    104124        func *f;
    105         int argno;
    106125    } r;
    107126    union {
     
    116135    struct nvblock_s *prev;
    117136    struct nvblock_s *next;
    118     var nv[0];
     137    var nv[];
    119138} nvblock;
    120139
     
    252271/* builtins */
    253272enum {
    254     B_a2,   B_ix,   B_ma,   B_sp,   B_ss,   B_ti,   B_lo,   B_up,
     273    B_a2,   B_ix,   B_ma,   B_sp,   B_ss,   B_ti,   B_mt,   B_lo,   B_up,
    255274    B_ge,   B_gs,   B_su,
    256275    B_an,   B_co,   B_ls,   B_or,   B_rs,   B_xo,
     
    259278/* tokens and their corresponding info values */
    260279
    261 #define NTC     "\377"  /* switch to next token class (tc<<1) */
    262 #define NTCC    '\377'
    263 
    264 #define OC_B    OC_BUILTIN
     280#define NTC     "\377"  /* switch to next token class (tc<<1) */
     281#define NTCC    '\377'
     282
     283#define OC_B  OC_BUILTIN
    265284
    266285static const char tokenlist[] ALIGN1 =
    267     "\1("       NTC
    268     "\1)"       NTC
    269     "\1/"       NTC                                 /* REGEXP */
    270     "\2>>"      "\1>"       "\1|"       NTC         /* OUTRDR */
    271     "\2++"      "\2--"      NTC                     /* UOPPOST */
    272     "\2++"      "\2--"      "\1$"       NTC         /* UOPPRE1 */
    273     "\2=="      "\1="       "\2+="      "\2-="      /* BINOPX */
    274     "\2*="      "\2/="      "\2%="      "\2^="
    275     "\1+"       "\1-"       "\3**="     "\2**"
    276     "\1/"       "\1%"       "\1^"       "\1*"
    277     "\2!="      "\2>="      "\2<="      "\1>"
    278     "\1<"       "\2!~"      "\1~"       "\2&&"
    279     "\2||"      "\1?"       "\1:"       NTC
    280     "\2in"      NTC
    281     "\1,"       NTC
    282     "\1|"       NTC
    283     "\1+"       "\1-"       "\1!"       NTC         /* UOPPRE2 */
    284     "\1]"       NTC
    285     "\1{"       NTC
    286     "\1}"       NTC
    287     "\1;"       NTC
    288     "\1\n"      NTC
    289     "\2if"      "\2do"      "\3for"     "\5break"   /* STATX */
    290     "\10continue"           "\6delete"  "\5print"
    291     "\6printf"  "\4next"    "\10nextfile"
    292     "\6return"  "\4exit"    NTC
    293     "\5while"   NTC
    294     "\4else"    NTC
    295 
    296     "\3and"     "\5compl"   "\6lshift"  "\2or"
    297     "\6rshift"  "\3xor"
    298     "\5close"   "\6system"  "\6fflush"  "\5atan2"   /* BUILTIN */
    299     "\3cos"     "\3exp"     "\3int"     "\3log"
    300     "\4rand"    "\3sin"     "\4sqrt"    "\5srand"
    301     "\6gensub"  "\4gsub"    "\5index"   "\6length"
    302     "\5match"   "\5split"   "\7sprintf" "\3sub"
    303     "\6substr"  "\7systime" "\10strftime"
    304     "\7tolower" "\7toupper" NTC
    305     "\7getline" NTC
    306     "\4func"    "\10function"   NTC
    307     "\5BEGIN"   NTC
    308     "\3END"     "\0"
     286    "\1("         NTC
     287    "\1)"         NTC
     288    "\1/"         NTC                                   /* REGEXP */
     289    "\2>>"        "\1>"         "\1|"       NTC         /* OUTRDR */
     290    "\2++"        "\2--"        NTC                     /* UOPPOST */
     291    "\2++"        "\2--"        "\1$"       NTC         /* UOPPRE1 */
     292    "\2=="        "\1="         "\2+="      "\2-="      /* BINOPX */
     293    "\2*="        "\2/="        "\2%="      "\2^="
     294    "\1+"         "\1-"         "\3**="     "\2**"
     295    "\1/"         "\1%"         "\1^"       "\1*"
     296    "\2!="        "\2>="        "\2<="      "\1>"
     297    "\1<"         "\2!~"        "\1~"       "\2&&"
     298    "\2||"        "\1?"         "\1:"       NTC
     299    "\2in"        NTC
     300    "\1,"         NTC
     301    "\1|"         NTC
     302    "\1+"         "\1-"         "\1!"       NTC         /* UOPPRE2 */
     303    "\1]"         NTC
     304    "\1{"         NTC
     305    "\1}"         NTC
     306    "\1;"         NTC
     307    "\1\n"        NTC
     308    "\2if"        "\2do"        "\3for"     "\5break"   /* STATX */
     309    "\10continue" "\6delete"    "\5print"
     310    "\6printf"    "\4next"      "\10nextfile"
     311    "\6return"    "\4exit"      NTC
     312    "\5while"     NTC
     313    "\4else"      NTC
     314
     315    "\3and"       "\5compl"     "\6lshift"  "\2or"
     316    "\6rshift"    "\3xor"
     317    "\5close"     "\6system"    "\6fflush"  "\5atan2"   /* BUILTIN */
     318    "\3cos"       "\3exp"       "\3int"     "\3log"
     319    "\4rand"      "\3sin"       "\4sqrt"    "\5srand"
     320    "\6gensub"    "\4gsub"      "\5index"   "\6length"
     321    "\5match"     "\5split"     "\7sprintf" "\3sub"
     322    "\6substr"    "\7systime"   "\10strftime" "\6mktime"
     323    "\7tolower"   "\7toupper"   NTC
     324    "\7getline"   NTC
     325    "\4func"      "\10function" NTC
     326    "\5BEGIN"     NTC
     327    "\3END"
     328    /* compiler adds trailing "\0" */
    309329    ;
    310330
     
    313333    0,
    314334    OC_REGEXP,
    315     xS|'a',     xS|'w',     xS|'|',
    316     OC_UNARY|xV|P(9)|'p',       OC_UNARY|xV|P(9)|'m',
    317     OC_UNARY|xV|P(9)|'P',       OC_UNARY|xV|P(9)|'M',
    318         OC_FIELD|xV|P(5),
    319     OC_COMPARE|VV|P(39)|5,      OC_MOVE|VV|P(74),
    320         OC_REPLACE|NV|P(74)|'+',    OC_REPLACE|NV|P(74)|'-',
    321     OC_REPLACE|NV|P(74)|'*',    OC_REPLACE|NV|P(74)|'/',
    322         OC_REPLACE|NV|P(74)|'%',    OC_REPLACE|NV|P(74)|'&',
    323     OC_BINARY|NV|P(29)|'+',     OC_BINARY|NV|P(29)|'-',
    324         OC_REPLACE|NV|P(74)|'&',    OC_BINARY|NV|P(15)|'&',
    325     OC_BINARY|NV|P(25)|'/',     OC_BINARY|NV|P(25)|'%',
    326         OC_BINARY|NV|P(15)|'&',     OC_BINARY|NV|P(25)|'*',
    327     OC_COMPARE|VV|P(39)|4,      OC_COMPARE|VV|P(39)|3,
    328         OC_COMPARE|VV|P(39)|0,      OC_COMPARE|VV|P(39)|1,
    329     OC_COMPARE|VV|P(39)|2,      OC_MATCH|Sx|P(45)|'!',
    330         OC_MATCH|Sx|P(45)|'~',      OC_LAND|Vx|P(55),
    331     OC_LOR|Vx|P(59),            OC_TERNARY|Vx|P(64)|'?',
    332         OC_COLON|xx|P(67)|':',
    333     OC_IN|SV|P(49),
     335    xS|'a',                  xS|'w',                  xS|'|',
     336    OC_UNARY|xV|P(9)|'p',    OC_UNARY|xV|P(9)|'m',
     337    OC_UNARY|xV|P(9)|'P',    OC_UNARY|xV|P(9)|'M',    OC_FIELD|xV|P(5),
     338    OC_COMPARE|VV|P(39)|5,   OC_MOVE|VV|P(74),        OC_REPLACE|NV|P(74)|'+', OC_REPLACE|NV|P(74)|'-',
     339    OC_REPLACE|NV|P(74)|'*', OC_REPLACE|NV|P(74)|'/', OC_REPLACE|NV|P(74)|'%', OC_REPLACE|NV|P(74)|'&',
     340    OC_BINARY|NV|P(29)|'+',  OC_BINARY|NV|P(29)|'-',  OC_REPLACE|NV|P(74)|'&', OC_BINARY|NV|P(15)|'&',
     341    OC_BINARY|NV|P(25)|'/',  OC_BINARY|NV|P(25)|'%',  OC_BINARY|NV|P(15)|'&',  OC_BINARY|NV|P(25)|'*',
     342    OC_COMPARE|VV|P(39)|4,   OC_COMPARE|VV|P(39)|3,   OC_COMPARE|VV|P(39)|0,   OC_COMPARE|VV|P(39)|1,
     343    OC_COMPARE|VV|P(39)|2,   OC_MATCH|Sx|P(45)|'!',   OC_MATCH|Sx|P(45)|'~',   OC_LAND|Vx|P(55),
     344    OC_LOR|Vx|P(59),         OC_TERNARY|Vx|P(64)|'?', OC_COLON|xx|P(67)|':',
     345    OC_IN|SV|P(49), /* in */
    334346    OC_COMMA|SS|P(80),
    335347    OC_PGETLINE|SV|P(37),
    336     OC_UNARY|xV|P(19)|'+',      OC_UNARY|xV|P(19)|'-',
    337         OC_UNARY|xV|P(19)|'!',
     348    OC_UNARY|xV|P(19)|'+',   OC_UNARY|xV|P(19)|'-',   OC_UNARY|xV|P(19)|'!',
     349    0, /* ] */
    338350    0,
    339351    0,
    340352    0,
    341     0,
    342     0,
    343     ST_IF,          ST_DO,          ST_FOR,         OC_BREAK,
    344     OC_CONTINUE,                    OC_DELETE|Vx,   OC_PRINT,
    345     OC_PRINTF,      OC_NEXT,        OC_NEXTFILE,
    346     OC_RETURN|Vx,   OC_EXIT|Nx,
     353    0, /* \n */
     354    ST_IF,        ST_DO,        ST_FOR,      OC_BREAK,
     355    OC_CONTINUE,  OC_DELETE|Vx, OC_PRINT,
     356    OC_PRINTF,    OC_NEXT,      OC_NEXTFILE,
     357    OC_RETURN|Vx, OC_EXIT|Nx,
    347358    ST_WHILE,
    348     0,
     359    0, /* else */
    349360
    350361    OC_B|B_an|P(0x83), OC_B|B_co|P(0x41), OC_B|B_ls|P(0x83), OC_B|B_or|P(0x83),
     
    355366    OC_B|B_ge|P(0xd6), OC_B|B_gs|P(0xb6), OC_B|B_ix|P(0x9b), OC_FBLTIN|Sx|F_le,
    356367    OC_B|B_ma|P(0x89), OC_B|B_sp|P(0x8b), OC_SPRINTF,        OC_B|B_su|P(0xb6),
    357     OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti,    OC_B|B_ti|P(0x0b),
     368    OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti,    OC_B|B_ti|P(0x0b), OC_B|B_mt|P(0x0b),
    358369    OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49),
    359370    OC_GETLINE|SV|P(0),
    360     0,  0,
     371    0,                 0,
    361372    0,
    362     0
     373    0 /* END */
    363374};
    364375
     
    368379    CONVFMT,    OFMT,       FS,         OFS,
    369380    ORS,        RS,         RT,         FILENAME,
    370     SUBSEP,     ARGIND,     ARGC,       ARGV,
    371     ERRNO,      FNR,
    372     NR,         NF,         IGNORECASE,
    373     ENVIRON,    F0,         NUM_INTERNAL_VARS
     381    SUBSEP,     F0,         ARGIND,     ARGC,
     382    ARGV,       ERRNO,      FNR,        NR,
     383    NF,         IGNORECASE, ENVIRON,    NUM_INTERNAL_VARS
    374384};
    375385
     
    377387    "CONVFMT\0" "OFMT\0"    "FS\0*"     "OFS\0"
    378388    "ORS\0"     "RS\0*"     "RT\0"      "FILENAME\0"
    379     "SUBSEP\0"  "ARGIND\0"  "ARGC\0"    "ARGV\0"
    380     "ERRNO\0"   "FNR\0"
    381     "NR\0"      "NF\0*"     "IGNORECASE\0*"
    382     "ENVIRON\0" "$\0*"      "\0";
     389    "SUBSEP\0"  "$\0*"      "ARGIND\0"  "ARGC\0"
     390    "ARGV\0"    "ERRNO\0"   "FNR\0"     "NR\0"
     391    "NF\0*"     "IGNORECASE\0*" "ENVIRON\0" "\0";
    383392
    384393static const char vValues[] ALIGN1 =
    385394    "%.6g\0"    "%.6g\0"    " \0"       " \0"
    386395    "\n\0"      "\n\0"      "\0"        "\0"
    387     "\034\0"
    388     "\377";
     396    "\034\0"    "\0"        "\377";
    389397
    390398/* hash size may grow to these values */
     
    394402
    395403/* Globals. Split in two parts so that first one is addressed
    396  * with (mostly short) negative offsets */
     404 * with (mostly short) negative offsets.
     405 * NB: it's unsafe to put members of type "double"
     406 * into globals2 (gcc may fail to align them).
     407 */
    397408struct globals {
    398     chain beginseq, mainseq, endseq, *seq;
     409    double t_double;
     410    chain beginseq, mainseq, endseq;
     411    chain *seq;
    399412    node *break_ptr, *continue_ptr;
    400413    rstream *iF;
     
    443456
    444457    /* biggest and least used members go last */
    445     double t_double;
    446458    tsplitter fsplitter, rsplitter;
    447459};
    448460#define G1 (ptr_to_globals[-1])
    449 #define G (*(struct globals2 *const)ptr_to_globals)
     461#define G (*(struct globals2 *)ptr_to_globals)
    450462/* For debug. nm --size-sort awk.o | grep -vi ' [tr] ' */
    451 /* char G1size[sizeof(G1)]; - 0x6c */
    452 /* char Gsize[sizeof(G)]; - 0x1cc */
     463/*char G1size[sizeof(G1)]; - 0x74 */
     464/*char Gsize[sizeof(G)]; - 0x1c4 */
    453465/* Trying to keep most of members accessible with short offsets: */
    454 /* char Gofs_seed[offsetof(struct globals2, evaluate__seed)]; - 0x90 */
     466/*char Gofs_seed[offsetof(struct globals2, evaluate__seed)]; - 0x90 */
     467#define t_double     (G1.t_double    )
    455468#define beginseq     (G1.beginseq    )
    456469#define mainseq      (G1.mainseq     )
     
    480493#define t_tclass     (G.t_tclass    )
    481494#define t_string     (G.t_string    )
    482 #define t_double     (G.t_double    )
    483495#define t_lineno     (G.t_lineno    )
    484496#define t_rollback   (G.t_rollback  )
     
    487499#define rsplitter    (G.rsplitter   )
    488500#define INIT_G() do { \
    489     PTR_TO_GLOBALS = xzalloc(sizeof(G1) + sizeof(G)) + sizeof(G1); \
     501    SET_PTR_TO_GLOBALS((char*)xzalloc(sizeof(G1)+sizeof(G)) + sizeof(G1)); \
    490502    G.next_token__ltclass = TC_OPTERM; \
    491503    G.evaluate__seed = 1; \
     
    500512static rstream *next_input_file(void);
    501513static int fmt_num(char *, int, const char *, double, int);
    502 static int awk_exit(int) ATTRIBUTE_NORETURN;
     514static int awk_exit(int) NORETURN;
    503515
    504516/* ---- error handling ---- */
     
    513525static const char EMSG_POSSIBLE_ERROR[] ALIGN1 = "Possible syntax error";
    514526static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function";
    515 #if !ENABLE_FEATURE_AWK_MATH
    516527static const char EMSG_NO_MATH[] ALIGN1 = "Math support is not compiled in";
    517 #endif
    518 
    519 static void zero_out_var(var * vp)
     528
     529static void zero_out_var(var *vp)
    520530{
    521531    memset(vp, 0, sizeof(*vp));
    522532}
    523533
    524 static void syntax_error(const char *const message) ATTRIBUTE_NORETURN;
    525 static void syntax_error(const char *const message)
     534static void syntax_error(const char *message) NORETURN;
     535static void syntax_error(const char *message)
    526536{
    527537    bb_error_msg_and_die("%s:%i: %s", g_progname, g_lineno, message);
     
    534544    unsigned idx = 0;
    535545
    536     while (*name) idx = *name++ + (idx << 6) - idx;
     546    while (*name)
     547        idx = *name++ + (idx << 6) - idx;
    537548    return idx;
    538549}
     
    543554    xhash *newhash;
    544555
    545     newhash = xzalloc(sizeof(xhash));
     556    newhash = xzalloc(sizeof(*newhash));
    546557    newhash->csize = FIRST_PRIME;
    547     newhash->items = xzalloc(newhash->csize * sizeof(hash_item *));
     558    newhash->items = xzalloc(FIRST_PRIME * sizeof(newhash->items[0]));
    548559
    549560    return newhash;
     
    555566    hash_item *hi;
    556567
    557     hi = hash->items [ hashidx(name) % hash->csize ];
     568    hi = hash->items[hashidx(name) % hash->csize];
    558569    while (hi) {
    559570        if (strcmp(hi->name, name) == 0)
    560             return &(hi->data);
     571            return &hi->data;
    561572        hi = hi->next;
    562573    }
     
    574585
    575586    newsize = PRIMES[hash->nprime++];
    576     newitems = xzalloc(newsize * sizeof(hash_item *));
     587    newitems = xzalloc(newsize * sizeof(newitems[0]));
    577588
    578589    for (i = 0; i < hash->csize; i++) {
     
    605616
    606617        l = strlen(name) + 1;
    607         hi = xzalloc(sizeof(hash_item) + l);
    608         memcpy(hi->name, name, l);
     618        hi = xzalloc(sizeof(*hi) + l);
     619        strcpy(hi->name, name);
    609620
    610621        idx = hashidx(name) % hash->csize;
     
    613624        hash->glen += l;
    614625    }
    615     return &(hi->data);
     626    return &hi->data;
    616627}
    617628
     
    625636    hash_item *hi, **phi;
    626637
    627     phi = &(hash->items[hashidx(name) % hash->csize]);
     638    phi = &hash->items[hashidx(name) % hash->csize];
    628639    while (*phi) {
    629640        hi = *phi;
     
    635646            break;
    636647        }
    637         phi = &(hi->next);
     648        phi = &hi->next;
    638649    }
    639650}
     
    641652/* ------ some useful functions ------ */
    642653
    643 static void skip_spaces(char **s)
    644 {
    645     char *p = *s;
    646 
     654static char *skip_spaces(char *p)
     655{
    647656    while (1) {
    648657        if (*p == '\\' && p[1] == '\n') {
     
    654663        p++;
    655664    }
    656     *s = p;
    657 }
    658 
     665    return p;
     666}
     667
     668/* returns old *s, advances *s past word and terminating NUL */
    659669static char *nextword(char **s)
    660670{
    661671    char *p = *s;
    662 
    663     while (*(*s)++) /* */;
    664 
     672    while (*(*s)++ != '\0')
     673        continue;
    665674    return p;
    666675}
     
    670679    char c, *pps;
    671680
    672     c = *((*s)++);
     681    c = *(*s)++;
    673682    pps = *s;
    674     if (c == '\\') c = bb_process_escape_sequence((const char**)s);
    675     if (c == '\\' && *s == pps) c = *((*s)++);
     683    if (c == '\\')
     684        c = bb_process_escape_sequence((const char**)s);
     685    if (c == '\\' && *s == pps) { /* unrecognized \z? */
     686        c = *(*s); /* yes, fetch z */
     687        if (c)
     688            (*s)++; /* advance unless z = NUL */
     689    }
    676690    return c;
    677691}
    678692
    679 static int ALWAYS_INLINE isalnum_(int c)
     693static ALWAYS_INLINE int isalnum_(int c)
    680694{
    681695    return (isalnum(c) || c == '_');
    682696}
    683697
    684 static FILE *afopen(const char *path, const char *mode)
    685 {
    686     return (*path == '-' && *(path+1) == '\0') ? stdin : xfopen(path, mode);
     698static double my_strtod(char **pp)
     699{
     700    char *cp = *pp;
     701    if (ENABLE_DESKTOP && cp[0] == '0') {
     702        /* Might be hex or octal integer: 0x123abc or 07777 */
     703        char c = (cp[1] | 0x20);
     704        if (c == 'x' || isdigit(cp[1])) {
     705            unsigned long long ull = strtoull(cp, pp, 0);
     706            if (c == 'x')
     707                return ull;
     708            c = **pp;
     709            if (!isdigit(c) && c != '.')
     710                return ull;
     711            /* else: it may be a floating number. Examples:
     712             * 009.123 (*pp points to '9')
     713             * 000.123 (*pp points to '.')
     714             * fall through to strtod.
     715             */
     716        }
     717    }
     718    return strtod(cp, pp);
    687719}
    688720
     
    748780}
    749781
    750 /* same as setvar_s but set USER flag */
     782/* same as setvar_s but sets USER flag */
    751783static var *setvar_u(var *v, const char *value)
    752784{
    753     setvar_s(v, value);
     785    v = setvar_s(v, value);
    754786    v->type |= VF_USER;
    755787    return v;
     
    759791static void setari_u(var *a, int idx, const char *s)
    760792{
    761     char sidx[sizeof(int)*3 + 1];
    762793    var *v;
    763794
    764     sprintf(sidx, "%d", idx);
    765     v = findvar(iamarray(a), sidx);
     795    v = findvar(iamarray(a), itoa(idx));
    766796    setvar_u(v, s);
    767797}
     
    796826        s = v->string;
    797827        if (s && *s) {
    798             v->number = strtod(s, &s);
     828            debug_printf_eval("getvar_i: '%s'->", s);
     829            v->number = my_strtod(&s);
     830            debug_printf_eval("%f (s:'%s')\n", v->number, s);
    799831            if (v->type & VF_USER) {
    800                 skip_spaces(&s);
     832                s = skip_spaces(s);
    801833                if (*s != '\0')
    802834                    v->type &= ~VF_USER;
    803835            }
    804836        } else {
     837            debug_printf_eval("getvar_i: '%s'->zero\n", s);
    805838            v->type &= ~VF_USER;
    806839        }
    807840        v->type |= VF_CACHED;
    808841    }
     842    debug_printf_eval("getvar_i: %f\n", v->number);
    809843    return v->number;
     844}
     845
     846/* Used for operands of bitwise ops */
     847static unsigned long getvar_i_int(var *v)
     848{
     849    double d = getvar_i(v);
     850
     851    /* Casting doubles to longs is undefined for values outside
     852     * of target type range. Try to widen it as much as possible */
     853    if (d >= 0)
     854        return (unsigned long)d;
     855    /* Why? Think about d == -4294967295.0 (assuming 32bit longs) */
     856    return - (long) (unsigned long) (-d);
    810857}
    811858
     
    815862        clrvar(dest);
    816863        dest->type |= (src->type & ~(VF_DONTTOUCH | VF_FSTR));
     864        debug_printf_eval("copyvar: number:%f string:'%s'\n", src->number, src->string);
    817865        dest->number = src->number;
    818866        if (src->string)
     
    825873static var *incvar(var *v)
    826874{
    827     return setvar_i(v, getvar_i(v) + 1.);
     875    return setvar_i(v, getvar_i(v) + 1.0);
    828876}
    829877
     
    839887{
    840888    if (is_numeric(v))
    841         return (v->number == 0) ? 0 : 1;
    842     return (v->string && *(v->string)) ? 1 : 0;
     889        return (v->number != 0);
     890    return (v->string && v->string[0]);
    843891}
    844892
     
    852900    while (g_cb) {
    853901        pb = g_cb;
    854         if ((g_cb->pos - g_cb->nv) + n <= g_cb->size) break;
     902        if ((g_cb->pos - g_cb->nv) + n <= g_cb->size)
     903            break;
    855904        g_cb = g_cb->next;
    856905    }
     
    858907    if (!g_cb) {
    859908        size = (n <= MINNVBLOCK) ? MINNVBLOCK : n;
    860         g_cb = xmalloc(sizeof(nvblock) + size * sizeof(var));
     909        g_cb = xzalloc(sizeof(nvblock) + size * sizeof(var));
    861910        g_cb->size = size;
    862911        g_cb->pos = g_cb->nv;
    863912        g_cb->prev = pb;
    864         g_cb->next = NULL;
    865         if (pb) pb->next = g_cb;
     913        /*g_cb->next = NULL; - xzalloc did it */
     914        if (pb)
     915            pb->next = g_cb;
    866916    }
    867917
     
    891941            free(p->x.array);
    892942        }
    893         if (p->type & VF_WALK)
    894             free(p->x.walker);
    895 
     943        if (p->type & VF_WALK) {
     944            walker_list *n;
     945            walker_list *w = p->x.walker;
     946            debug_printf_walker("nvfree: freeing walker @%p\n", &p->x.walker);
     947            p->x.walker = NULL;
     948            while (w) {
     949                n = w->prev;
     950                debug_printf_walker(" free(%p)\n", w);
     951                free(w);
     952                w = n;
     953            }
     954        }
    896955        clrvar(p);
    897956    }
     
    916975#define ltclass         (G.next_token__ltclass)
    917976
    918     char *p, *pp, *s;
     977    char *p, *s;
    919978    const char *tl;
    920979    uint32_t tc;
    921980    const uint32_t *ti;
    922     int l;
    923981
    924982    if (t_rollback) {
     
    933991        p = g_pos;
    934992 readnext:
    935         skip_spaces(&p);
     993        p = skip_spaces(p);
    936994        g_lineno = t_lineno;
    937995        if (*p == '#')
     
    9491007            t_string = s = ++p;
    9501008            while (*p != '\"') {
     1009                char *pp;
    9511010                if (*p == '\0' || *p == '\n')
    9521011                    syntax_error(EMSG_UNEXP_EOS);
    953                 *(s++) = nextchar(&p);
     1012                pp = p;
     1013                *s++ = nextchar(&pp);
     1014                p = pp;
    9541015            }
    9551016            p++;
     
    9651026                *s = *p++;
    9661027                if (*s++ == '\\') {
    967                     pp = p;
    968                     *(s-1) = bb_process_escape_sequence((const char **)&p);
    969                     if (*pp == '\\')
     1028                    char *pp = p;
     1029                    s[-1] = bb_process_escape_sequence((const char **)&pp);
     1030                    if (*p == '\\')
    9701031                        *s++ = '\\';
    971                     if (p == pp)
     1032                    if (pp == p)
    9721033                        *s++ = *p++;
     1034                    else
     1035                        p = pp;
    9731036                }
    9741037            }
     
    9791042        } else if (*p == '.' || isdigit(*p)) {
    9801043            /* it's a number */
    981             t_double = strtod(p, &p);
     1044            char *pp = p;
     1045            t_double = my_strtod(&pp);
     1046            p = pp;
    9821047            if (*p == '.')
    9831048                syntax_error(EMSG_UNEXP_TOKEN);
     
    9901055            ti = tokeninfo;
    9911056            while (*tl) {
    992                 l = *(tl++);
    993                 if (l == NTCC) {
     1057                int l = (unsigned char) *tl++;
     1058                if (l == (unsigned char) NTCC) {
    9941059                    tc <<= 1;
    9951060                    continue;
    9961061                }
    997                 /* if token class is expected, token
    998                  * matches and it's not a longer word,
    999                  * then this is what we are looking for
     1062                /* if token class is expected,
     1063                 * token matches,
     1064                 * and it's not a longer word,
    10001065                 */
    10011066                if ((tc & (expected | TC_WORD | TC_NEWLINE))
    1002                  && *tl == *p && strncmp(p, tl, l) == 0
     1067                 && strncmp(p, tl, l) == 0
    10031068                 && !((tc & TC_WORD) && isalnum_(p[l]))
    10041069                ) {
     1070                    /* then this is what we are looking for */
    10051071                    t_info = *ti;
    10061072                    p += l;
    1007                     break;
     1073                    goto token_found;
    10081074                }
    10091075                ti++;
    10101076                tl += l;
    10111077            }
    1012 
    1013             if (!*tl) {
    1014                 /* it's a name (var/array/function),
    1015                  * otherwise it's something wrong
    1016                  */
    1017                 if (!isalnum_(*p))
    1018                     syntax_error(EMSG_UNEXP_TOKEN);
    1019 
    1020                 t_string = --p;
    1021                 while (isalnum_(*(++p))) {
    1022                     *(p-1) = *p;
     1078            /* not a known token */
     1079
     1080            /* is it a name? (var/array/function) */
     1081            if (!isalnum_(*p))
     1082                syntax_error(EMSG_UNEXP_TOKEN); /* no */
     1083            /* yes */
     1084            t_string = --p;
     1085            while (isalnum_(*++p)) {
     1086                p[-1] = *p;
     1087            }
     1088            p[-1] = '\0';
     1089            tc = TC_VARIABLE;
     1090            /* also consume whitespace between functionname and bracket */
     1091            if (!(expected & TC_VARIABLE) || (expected & TC_ARRAY))
     1092                p = skip_spaces(p);
     1093            if (*p == '(') {
     1094                tc = TC_FUNCTION;
     1095            } else {
     1096                if (*p == '[') {
     1097                    p++;
     1098                    tc = TC_ARRAY;
    10231099                }
    1024                 *(p-1) = '\0';
    1025                 tc = TC_VARIABLE;
    1026                 /* also consume whitespace between functionname and bracket */
    1027                 if (!(expected & TC_VARIABLE))
    1028                     skip_spaces(&p);
    1029                 if (*p == '(') {
    1030                     tc = TC_FUNCTION;
    1031                 } else {
    1032                     if (*p == '[') {
    1033                         p++;
    1034                         tc = TC_ARRAY;
    1035                     }
    1036                 }
    1037             }
     1100            }
     1101 token_found: ;
    10381102        }
    10391103        g_pos = p;
     
    10831147}
    10841148
    1085 static node *mk_re_node(const char *s, node *n, regex_t *re)
     1149static void mk_re_node(const char *s, node *n, regex_t *re)
    10861150{
    10871151    n->info = OC_REGEXP;
     
    10901154    xregcomp(re, s, REG_EXTENDED);
    10911155    xregcomp(re + 1, s, REG_EXTENDED | REG_ICASE);
    1092 
    1093     return n;
    10941156}
    10951157
     
    11151177
    11161178    while (!((tc = next_token(xtc)) & iexp)) {
     1179
    11171180        if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) {
    11181181            /* input redirection (<) attached to glptr node */
     
    11261189             * previous operators with higher priority */
    11271190            vn = cn;
    1128             while ( ((t_info & PRIMASK) > (vn->a.n->info & PRIMASK2))
    1129              || ((t_info == vn->info) && ((t_info & OPCLSMASK) == OC_COLON)) )
     1191            while (((t_info & PRIMASK) > (vn->a.n->info & PRIMASK2))
     1192                || ((t_info == vn->info) && ((t_info & OPCLSMASK) == OC_COLON))
     1193            ) {
    11301194                vn = vn->a.n;
     1195            }
    11311196            if ((t_info & OPCLSMASK) == OC_TERNARY)
    11321197                t_info += P(6);
     
    11671232                    if (v != NULL) {
    11681233                        cn->info = OC_FNARG;
    1169                         cn->l.i = v->x.aidx;
     1234                        cn->l.aidx = v->x.aidx;
    11701235                    } else {
    11711236                        cn->l.v = newvar(t_string);
     
    12281293        seq->programname = g_progname;
    12291294        n = chain_node(OC_NEWSOURCE);
    1230         n->l.s = xstrdup(g_progname);
     1295        n->l.new_progname = xstrdup(g_progname);
    12311296    }
    12321297
     
    12831348    if (c & TC_GRPSTART) {
    12841349        while (next_token(TC_GRPSEQ | TC_GRPTERM) != TC_GRPTERM) {
    1285             if (t_tclass & TC_NEWLINE) continue;
     1350            if (t_tclass & TC_NEWLINE)
     1351                continue;
    12861352            rollback_token();
    12871353            chain_group();
     
    14051471            while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
    14061472                v = findvar(ahash, t_string);
    1407                 v->x.aidx = (f->nargs)++;
     1473                v->x.aidx = f->nargs++;
    14081474
    14091475                if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
    14101476                    break;
    14111477            }
    1412             seq = &(f->body);
     1478            seq = &f->body;
    14131479            chain_group();
    14141480            clear_array(ahash);
     
    14481514        regfree(ire); // TODO: nuke ire, use re+1?
    14491515    }
    1450     if (strlen(s) > 1) {
     1516    if (s[0] && s[1]) { /* strlen(s) > 1 */
    14511517        mk_re_node(s, n, re);
    14521518    } else {
    1453         n->info = (uint32_t) *s;
     1519        n->info = (uint32_t) s[0];
    14541520    }
    14551521
     
    14631529static regex_t *as_regex(node *op, regex_t *preg)
    14641530{
     1531    int cflags;
    14651532    var *v;
    14661533    const char *s;
     
    14711538    v = nvalloc(1);
    14721539    s = getvar_s(evaluate(op, v));
    1473     xregcomp(preg, s, icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED);
     1540
     1541    cflags = icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED;
     1542    /* Testcase where REG_EXTENDED fails (unpaired '{'):
     1543     * echo Hi | awk 'gsub("@(samp|code|file)\{","");'
     1544     * gawk 3.1.5 eats this. We revert to ~REG_EXTENDED
     1545     * (maybe gsub is not supposed to use REG_EXTENDED?).
     1546     */
     1547    if (regcomp(preg, s, cflags)) {
     1548        cflags &= ~REG_EXTENDED;
     1549        xregcomp(preg, s, cflags);
     1550    }
    14741551    nvfree(v);
    14751552    return preg;
    14761553}
    14771554
    1478 /* gradually increasing buffer */
    1479 static void qrealloc(char **b, int n, int *size)
    1480 {
    1481     if (!*b || n >= *size)
    1482         *b = xrealloc(*b, *size = n + (n>>1) + 80);
     1555/* gradually increasing buffer.
     1556 * note that we reallocate even if n == old_size,
     1557 * and thus there is at least one extra allocated byte.
     1558 */
     1559static char* qrealloc(char *b, int n, int *size)
     1560{
     1561    if (!b || n >= *size) {
     1562        *size = n + (n>>1) + 80;
     1563        b = xrealloc(b, *size);
     1564    }
     1565    return b;
    14831566}
    14841567
     
    14911574        i = maxfields;
    14921575        maxfields = size + 16;
    1493         Fields = xrealloc(Fields, maxfields * sizeof(var));
     1576        Fields = xrealloc(Fields, maxfields * sizeof(Fields[0]));
    14941577        for (; i < maxfields; i++) {
    14951578            Fields[i].type = VF_SPECIAL;
     
    14971580        }
    14981581    }
    1499 
    1500     if (size < nfields) {
    1501         for (i = size; i < nfields; i++) {
    1502             clrvar(Fields + i);
    1503         }
     1582    /* if size < nfields, clear extra field variables */
     1583    for (i = size; i < nfields; i++) {
     1584        clrvar(Fields + i);
    15041585    }
    15051586    nfields = size;
     
    15081589static int awk_split(const char *s, node *spl, char **slist)
    15091590{
    1510     int l, n = 0;
     1591    int l, n;
    15111592    char c[4];
    15121593    char *s1;
     
    15221603        c[2] = '\n';
    15231604
     1605    n = 0;
    15241606    if ((spl->info & OPCLSMASK) == OC_REGEXP) {  /* regex split */
    15251607        if (!*s)
     
    15391621            } else {
    15401622                pmatch[0].rm_eo = l;
    1541                 if (s[l]) pmatch[0].rm_eo++;
     1623                if (s[l])
     1624                    pmatch[0].rm_eo++;
    15421625            }
    15431626            memcpy(s1, s, l);
    1544             s1[l] = '\0';
     1627            /* make sure we remove *all* of the separator chars */
     1628            do {
     1629                s1[l] = '\0';
     1630            } while (++l < pmatch[0].rm_eo);
    15451631            nextword(&s1);
    15461632            s += pmatch[0].rm_eo;
     
    15611647            c[1] = tolower(c[1]);
    15621648        }
    1563         if (*s1) n++;
    1564         while ((s1 = strpbrk(s1, c))) {
     1649        if (*s1)
     1650            n++;
     1651        while ((s1 = strpbrk(s1, c)) != NULL) {
    15651652            *s1++ = '\0';
    15661653            n++;
     
    15711658    while (*s) {
    15721659        s = skip_whitespace(s);
    1573         if (!*s) break;
     1660        if (!*s)
     1661            break;
    15741662        n++;
    15751663        while (*s && !isspace(*s))
     
    16361724                len += sl;
    16371725            }
    1638             qrealloc(&b, len+l+sl, &bsize);
     1726            b = qrealloc(b, len+l+sl, &bsize);
    16391727            memcpy(b+len, s, l);
    16401728            len += l;
     
    16811769static void hashwalk_init(var *v, xhash *array)
    16821770{
    1683     char **w;
    16841771    hash_item *hi;
    1685     int i;
    1686 
    1687     if (v->type & VF_WALK)
    1688         free(v->x.walker);
    1689 
    1690     v->type |= VF_WALK;
    1691     w = v->x.walker = xzalloc(2 + 2*sizeof(char *) + array->glen);
    1692     w[0] = w[1] = (char *)(w + 2);
     1772    unsigned i;
     1773    walker_list *w;
     1774    walker_list *prev_walker;
     1775
     1776    if (v->type & VF_WALK) {
     1777        prev_walker = v->x.walker;
     1778    } else {
     1779        v->type |= VF_WALK;
     1780        prev_walker = NULL;
     1781    }
     1782    debug_printf_walker("hashwalk_init: prev_walker:%p\n", prev_walker);
     1783
     1784    w = v->x.walker = xzalloc(sizeof(*w) + array->glen + 1); /* why + 1? */
     1785    debug_printf_walker(" walker@%p=%p\n", &v->x.walker, w);
     1786    w->cur = w->end = w->wbuf;
     1787    w->prev = prev_walker;
    16931788    for (i = 0; i < array->csize; i++) {
    16941789        hi = array->items[i];
    16951790        while (hi) {
    1696             strcpy(*w, hi->name);
    1697             nextword(w);
     1791            strcpy(w->end, hi->name);
     1792            nextword(&w->end);
    16981793            hi = hi->next;
    16991794        }
     
    17031798static int hashwalk_next(var *v)
    17041799{
    1705     char **w;
    1706 
    1707     w = v->x.walker;
    1708     if (w[1] == w[0])
     1800    walker_list *w = v->x.walker;
     1801
     1802    if (w->cur >= w->end) {
     1803        walker_list *prev_walker = w->prev;
     1804
     1805        debug_printf_walker("end of iteration, free(walker@%p:%p), prev_walker:%p\n", &v->x.walker, w, prev_walker);
     1806        free(w);
     1807        v->x.walker = prev_walker;
    17091808        return FALSE;
    1710 
    1711     setvar_s(v, nextword(w+1));
     1809    }
     1810
     1811    setvar_s(v, nextword(&w->cur));
    17121812    return TRUE;
    17131813}
     
    17251825    char *b;
    17261826    regmatch_t pmatch[2];
    1727     int a, p, pp=0, size;
     1827    int size, a, p, pp = 0;
    17281828    int fd, so, eo, r, rp;
    17291829    char c, *m, *s;
     1830
     1831    debug_printf_eval("entered %s()\n", __func__);
    17301832
    17311833    /* we're using our own buffer since we need access to accumulating
     
    17401842    rp = 0;
    17411843
    1742     if (!m) qrealloc(&m, 256, &size);
     1844    if (!m)
     1845        m = qrealloc(m, 256, &size);
     1846
    17431847    do {
    17441848        b = m + a;
     
    17561860            } else if (c != '\0') {
    17571861                s = strchr(b+pp, c);
    1758                 if (!s) s = memchr(b+pp, '\0', p - pp);
     1862                if (!s)
     1863                    s = memchr(b+pp, '\0', p - pp);
    17591864                if (s) {
    17601865                    so = eo = s-b;
     
    17681873                if (s) {
    17691874                    so = eo = s-b;
    1770                     while (b[eo] == '\n') eo++;
     1875                    while (b[eo] == '\n')
     1876                        eo++;
    17711877                    if (b[eo] != '\0')
    17721878                        break;
     
    17761882
    17771883        if (a > 0) {
    1778             memmove(m, (const void *)(m+a), p+1);
     1884            memmove(m, m+a, p+1);
    17791885            b = m;
    17801886            a = 0;
    17811887        }
    17821888
    1783         qrealloc(&m, a+p+128, &size);
     1889        m = qrealloc(m, a+p+128, &size);
    17841890        b = m + a;
    17851891        pp = p;
     
    18111917    rsm->size = size;
    18121918
     1919    debug_printf_eval("returning from %s(): %d\n", __func__, r);
     1920
    18131921    return r;
    18141922}
     
    18351943}
    18361944
    1837 
    18381945/* formatted output into an allocated buffer, return ptr to buffer */
    18391946static char *awk_printf(node *n)
     
    18521959    while (*f) {
    18531960        s = f;
    1854         while (*f && (*f != '%' || *(++f) == '%'))
     1961        while (*f && (*f != '%' || *++f == '%'))
    18551962            f++;
    18561963        while (*f && !isalpha(*f)) {
     
    18611968
    18621969        incr = (f - s) + MAXVARFMT;
    1863         qrealloc(&b, incr + i, &bsize);
     1970        b = qrealloc(b, incr + i, &bsize);
    18641971        c = *f;
    1865         if (c != '\0') f++;
     1972        if (c != '\0')
     1973            f++;
    18661974        c1 = *f;
    18671975        *f = '\0';
     
    18741982        } else if (c == 's') {
    18751983            s1 = getvar_s(arg);
    1876             qrealloc(&b, incr+i+strlen(s1), &bsize);
     1984            b = qrealloc(b, incr+i+strlen(s1), &bsize);
    18771985            i += sprintf(b+i, s, s1);
    18781986        } else {
     
    18821990
    18831991        /* if there was an error while sprintf, return value is negative */
    1884         if (i < j) i = j;
    1885     }
    1886 
    1887     b = xrealloc(b, i + 1);
     1992        if (i < j)
     1993            i = j;
     1994    }
     1995
    18881996    free(fmt);
    18891997    nvfree(v);
     1998    b = xrealloc(b, i + 1);
    18901999    b[i] = '\0';
    18912000    return b;
    18922001}
    18932002
    1894 /* common substitution routine
    1895  * replace (nm) substring of (src) that match (n) with (repl), store
    1896  * result into (dest), return number of substitutions. If nm=0, replace
    1897  * all matches. If src or dst is NULL, use $0. If ex=TRUE, enable
    1898  * subexpression matching (\1-\9)
     2003/* Common substitution routine.
     2004 * Replace (nm)'th substring of (src) that matches (rn) with (repl),
     2005 * store result into (dest), return number of substitutions.
     2006 * If nm = 0, replace all matches.
     2007 * If src or dst is NULL, use $0.
     2008 * If subexp != 0, enable subexpression matching (\1-\9).
    18992009 */
    1900 static int awk_sub(node *rn, const char *repl, int nm, var *src, var *dest, int ex)
    1901 {
    1902     char *ds = NULL;
    1903     const char *s;
     2010static int awk_sub(node *rn, const char *repl, int nm, var *src, var *dest, int subexp)
     2011{
     2012    char *resbuf;
    19042013    const char *sp;
    1905     int c, i, j, di, rl, so, eo, nbs, n, dssize;
     2014    int match_no, residx, replen, resbufsize;
     2015    int regexec_flags;
    19062016    regmatch_t pmatch[10];
    1907     regex_t sreg, *re;
    1908 
    1909     re = as_regex(rn, &sreg);
    1910     if (!src) src = intvar[F0];
    1911     if (!dest) dest = intvar[F0];
    1912 
    1913     i = di = 0;
    1914     sp = getvar_s(src);
    1915     rl = strlen(repl);
    1916     while (regexec(re, sp, 10, pmatch, sp==getvar_s(src) ? 0 : REG_NOTBOL) == 0) {
    1917         so = pmatch[0].rm_so;
    1918         eo = pmatch[0].rm_eo;
    1919 
    1920         qrealloc(&ds, di + eo + rl, &dssize);
    1921         memcpy(ds + di, sp, eo);
    1922         di += eo;
    1923         if (++i >= nm) {
     2017    regex_t sreg, *regex;
     2018
     2019    resbuf = NULL;
     2020    residx = 0;
     2021    match_no = 0;
     2022    regexec_flags = 0;
     2023    regex = as_regex(rn, &sreg);
     2024    sp = getvar_s(src ? src : intvar[F0]);
     2025    replen = strlen(repl);
     2026    while (regexec(regex, sp, 10, pmatch, regexec_flags) == 0) {
     2027        int so = pmatch[0].rm_so;
     2028        int eo = pmatch[0].rm_eo;
     2029
     2030        //bb_error_msg("match %u: [%u,%u] '%s'%p", match_no+1, so, eo, sp,sp);
     2031        resbuf = qrealloc(resbuf, residx + eo + replen, &resbufsize);
     2032        memcpy(resbuf + residx, sp, eo);
     2033        residx += eo;
     2034        if (++match_no >= nm) {
     2035            const char *s;
     2036            int nbs;
     2037
    19242038            /* replace */
    1925             di -= (eo - so);
     2039            residx -= (eo - so);
    19262040            nbs = 0;
    19272041            for (s = repl; *s; s++) {
    1928                 ds[di++] = c = *s;
     2042                char c = resbuf[residx++] = *s;
    19292043                if (c == '\\') {
    19302044                    nbs++;
    19312045                    continue;
    19322046                }
    1933                 if (c == '&' || (ex && c >= '0' && c <= '9')) {
    1934                     di -= ((nbs + 3) >> 1);
     2047                if (c == '&' || (subexp && c >= '0' && c <= '9')) {
     2048                    int j;
     2049                    residx -= ((nbs + 3) >> 1);
    19352050                    j = 0;
    19362051                    if (c != '&') {
     
    19392054                    }
    19402055                    if (nbs % 2) {
    1941                         ds[di++] = c;
     2056                        resbuf[residx++] = c;
    19422057                    } else {
    1943                         n = pmatch[j].rm_eo - pmatch[j].rm_so;
    1944                         qrealloc(&ds, di + rl + n, &dssize);
    1945                         memcpy(ds + di, sp + pmatch[j].rm_so, n);
    1946                         di += n;
     2058                        int n = pmatch[j].rm_eo - pmatch[j].rm_so;
     2059                        resbuf = qrealloc(resbuf, residx + replen + n, &resbufsize);
     2060                        memcpy(resbuf + residx, sp + pmatch[j].rm_so, n);
     2061                        residx += n;
    19472062                    }
    19482063                }
     
    19512066        }
    19522067
     2068        regexec_flags = REG_NOTBOL;
    19532069        sp += eo;
    1954         if (i == nm) break;
     2070        if (match_no == nm)
     2071            break;
    19552072        if (eo == so) {
    1956             ds[di] = *sp++;
    1957             if (!ds[di++]) break;
    1958         }
    1959     }
    1960 
    1961     qrealloc(&ds, di + strlen(sp), &dssize);
    1962     strcpy(ds + di, sp);
    1963     setvar_p(dest, ds);
    1964     if (re == &sreg) regfree(re);
    1965     return i;
    1966 }
    1967 
    1968 static var *exec_builtin(node *op, var *res)
     2073            /* Empty match (e.g. "b*" will match anywhere).
     2074             * Advance by one char. */
     2075//BUG (bug 1333):
     2076//gsub(/\<b*/,"") on "abc" will reach this point, advance to "bc"
     2077//... and will erroneously match "b" even though it is NOT at the word start.
     2078//we need REG_NOTBOW but it does not exist...
     2079//TODO: if EXTRA_COMPAT=y, use GNU matching and re_search,
     2080//it should be able to do it correctly.
     2081            /* Subtle: this is safe only because
     2082             * qrealloc allocated at least one extra byte */
     2083            resbuf[residx] = *sp;
     2084            if (*sp == '\0')
     2085                goto ret;
     2086            sp++;
     2087            residx++;
     2088        }
     2089    }
     2090
     2091    resbuf = qrealloc(resbuf, residx + strlen(sp), &resbufsize);
     2092    strcpy(resbuf + residx, sp);
     2093 ret:
     2094    //bb_error_msg("end sp:'%s'%p", sp,sp);
     2095    setvar_p(dest ? dest : intvar[F0], resbuf);
     2096    if (regex == &sreg)
     2097        regfree(regex);
     2098    return match_no;
     2099}
     2100
     2101static NOINLINE int do_mktime(const char *ds)
     2102{
     2103    struct tm then;
     2104    int count;
     2105
     2106    /*memset(&then, 0, sizeof(then)); - not needed */
     2107    then.tm_isdst = -1; /* default is unknown */
     2108
     2109    /* manpage of mktime says these fields are ints,
     2110     * so we can sscanf stuff directly into them */
     2111    count = sscanf(ds, "%u %u %u %u %u %u %d",
     2112        &then.tm_year, &then.tm_mon, &then.tm_mday,
     2113        &then.tm_hour, &then.tm_min, &then.tm_sec,
     2114        &then.tm_isdst);
     2115
     2116    if (count < 6
     2117     || (unsigned)then.tm_mon < 1
     2118     || (unsigned)then.tm_year < 1900
     2119    ) {
     2120        return -1;
     2121    }
     2122
     2123    then.tm_mon -= 1;
     2124    then.tm_year -= 1900;
     2125
     2126    return mktime(&then);
     2127}
     2128
     2129static NOINLINE var *exec_builtin(node *op, var *res)
    19692130{
    19702131#define tspl (G.exec_builtin__tspl)
    19712132
    1972     int (*to_xxx)(int);
    19732133    var *tv;
    19742134    node *an[4];
     
    19812141    int nargs;
    19822142    time_t tt;
    1983     char *s, *s1;
    19842143    int i, l, ll, n;
    19852144
     
    19912150    for (i = 0; i < 4 && op; i++) {
    19922151        an[i] = nextarg(&op);
    1993         if (isr & 0x09000000) av[i] = evaluate(an[i], &tv[i]);
    1994         if (isr & 0x08000000) as[i] = getvar_s(av[i]);
     2152        if (isr & 0x09000000)
     2153            av[i] = evaluate(an[i], &tv[i]);
     2154        if (isr & 0x08000000)
     2155            as[i] = getvar_s(av[i]);
    19952156        isr >>= 1;
    19962157    }
    19972158
    19982159    nargs = i;
    1999     if (nargs < (info >> 30))
     2160    if ((uint32_t)nargs < (info >> 30))
    20002161        syntax_error(EMSG_TOO_FEW_ARGS);
    20012162
    2002     switch (info & OPNMASK) {
     2163    info &= OPNMASK;
     2164    switch (info) {
    20032165
    20042166    case B_a2:
    2005 #if ENABLE_FEATURE_AWK_MATH
    2006         setvar_i(res, atan2(getvar_i(av[i]), getvar_i(av[1])));
    2007 #else
    2008         syntax_error(EMSG_NO_MATH);
    2009 #endif
     2167        if (ENABLE_FEATURE_AWK_LIBM)
     2168            setvar_i(res, atan2(getvar_i(av[0]), getvar_i(av[1])));
     2169        else
     2170            syntax_error(EMSG_NO_MATH);
    20102171        break;
    20112172
    2012     case B_sp:
     2173    case B_sp: {
     2174        char *s, *s1;
     2175
    20132176        if (nargs > 2) {
    20142177            spl = (an[2]->info & OPCLSMASK) == OC_REGEXP ?
     
    20212184        s1 = s;
    20222185        clear_array(iamarray(av[1]));
    2023         for (i=1; i<=n; i++)
    2024             setari_u(av[1], i, nextword(&s1));
    2025         free(s);
     2186        for (i = 1; i <= n; i++)
     2187            setari_u(av[1], i, nextword(&s));
     2188        free(s1);
    20262189        setvar_i(res, n);
    20272190        break;
    2028 
    2029     case B_ss:
     2191    }
     2192
     2193    case B_ss: {
     2194        char *s;
     2195
    20302196        l = strlen(as[0]);
    20312197        i = getvar_i(av[1]) - 1;
    2032         if (i > l) i = l;
    2033         if (i < 0) i = 0;
     2198        if (i > l)
     2199            i = l;
     2200        if (i < 0)
     2201            i = 0;
    20342202        n = (nargs > 2) ? getvar_i(av[2]) : l-i;
    2035         if (n < 0) n = 0;
    2036         s = xmalloc(n+1);
    2037         strncpy(s, as[0]+i, n);
    2038         s[n] = '\0';
     2203        if (n < 0)
     2204            n = 0;
     2205        s = xstrndup(as[0]+i, n);
    20392206        setvar_p(res, s);
    20402207        break;
    2041 
     2208    }
     2209
     2210    /* Bitwise ops must assume that operands are unsigned. GNU Awk 3.1.5:
     2211     * awk '{ print or(-1,1) }' gives "4.29497e+09", not "-2.xxxe+09" */
    20422212    case B_an:
    2043         setvar_i(res, (long)getvar_i(av[0]) & (long)getvar_i(av[1]));
     2213        setvar_i(res, getvar_i_int(av[0]) & getvar_i_int(av[1]));
    20442214        break;
    20452215
    20462216    case B_co:
    2047         setvar_i(res, ~(long)getvar_i(av[0]));
     2217        setvar_i(res, ~getvar_i_int(av[0]));
    20482218        break;
    20492219
    20502220    case B_ls:
    2051         setvar_i(res, (long)getvar_i(av[0]) << (long)getvar_i(av[1]));
     2221        setvar_i(res, getvar_i_int(av[0]) << getvar_i_int(av[1]));
    20522222        break;
    20532223
    20542224    case B_or:
    2055         setvar_i(res, (long)getvar_i(av[0]) | (long)getvar_i(av[1]));
     2225        setvar_i(res, getvar_i_int(av[0]) | getvar_i_int(av[1]));
    20562226        break;
    20572227
    20582228    case B_rs:
    2059         setvar_i(res, (long)((unsigned long)getvar_i(av[0]) >> (unsigned long)getvar_i(av[1])));
     2229        setvar_i(res, getvar_i_int(av[0]) >> getvar_i_int(av[1]));
    20602230        break;
    20612231
    20622232    case B_xo:
    2063         setvar_i(res, (long)getvar_i(av[0]) ^ (long)getvar_i(av[1]));
     2233        setvar_i(res, getvar_i_int(av[0]) ^ getvar_i_int(av[1]));
    20642234        break;
    20652235
    20662236    case B_lo:
    2067         to_xxx = tolower;
    2068         goto lo_cont;
    2069 
    2070     case B_up:
    2071         to_xxx = toupper;
    2072  lo_cont:
     2237    case B_up: {
     2238        char *s, *s1;
    20732239        s1 = s = xstrdup(as[0]);
    20742240        while (*s1) {
    2075             *s1 = (*to_xxx)(*s1);
     2241            //*s1 = (info == B_up) ? toupper(*s1) : tolower(*s1);
     2242            if ((unsigned char)((*s1 | 0x20) - 'a') <= ('z' - 'a'))
     2243                *s1 = (info == B_up) ? (*s1 & 0xdf) : (*s1 | 0x20);
    20762244            s1++;
    20772245        }
    20782246        setvar_p(res, s);
    20792247        break;
     2248    }
    20802249
    20812250    case B_ix:
     
    20852254        if (ll > 0 && l >= 0) {
    20862255            if (!icase) {
    2087                 s = strstr(as[0], as[1]);
    2088                 if (s) n = (s - as[0]) + 1;
     2256                char *s = strstr(as[0], as[1]);
     2257                if (s)
     2258                    n = (s - as[0]) + 1;
    20892259            } else {
    20902260                /* this piece of code is terribly slow and
    20912261                 * really should be rewritten
    20922262                 */
    2093                 for (i=0; i<=l; i++) {
     2263                for (i = 0; i <= l; i++) {
    20942264                    if (strncasecmp(as[0]+i, as[1], ll) == 0) {
    20952265                        n = i+1;
     
    21152285        break;
    21162286
     2287    case B_mt:
     2288        setvar_i(res, do_mktime(as[0]));
     2289        break;
     2290
    21172291    case B_ma:
    21182292        re = as_regex(an[1], &sreg);
     
    21282302        setvar_i(newvar("RLENGTH"), pmatch[0].rm_eo - pmatch[0].rm_so);
    21292303        setvar_i(res, pmatch[0].rm_so);
    2130         if (re == &sreg) regfree(re);
     2304        if (re == &sreg)
     2305            regfree(re);
    21312306        break;
    21322307
     
    21612336/* seed is initialized to 1 */
    21622337#define seed   (G.evaluate__seed)
    2163 #define sreg   (G.evaluate__sreg)
    2164 
    2165     node *op1;
     2338#define sreg   (G.evaluate__sreg)
     2339
    21662340    var *v1;
    2167     union {
    2168         var *v;
    2169         const char *s;
    2170         double d;
    2171         int i;
    2172     } L, R;
    2173     uint32_t opinfo;
    2174     int opn;
    2175     union {
    2176         char *s;
    2177         rstream *rsm;
    2178         FILE *F;
    2179         var *v;
    2180         regex_t *re;
    2181         uint32_t info;
    2182     } X;
    21832341
    21842342    if (!op)
    21852343        return setvar_s(res, NULL);
    21862344
     2345    debug_printf_eval("entered %s()\n", __func__);
     2346
    21872347    v1 = nvalloc(2);
    21882348
    21892349    while (op) {
     2350        struct {
     2351            var *v;
     2352            const char *s;
     2353        } L = L; /* for compiler */
     2354        struct {
     2355            var *v;
     2356            const char *s;
     2357        } R = R;
     2358        double L_d = L_d;
     2359        uint32_t opinfo;
     2360        int opn;
     2361        node *op1;
     2362
    21902363        opinfo = op->info;
    21912364        opn = (opinfo & OPNMASK);
    21922365        g_lineno = op->lineno;
     2366        op1 = op->l.n;
     2367        debug_printf_eval("opinfo:%08x opn:%08x\n", opinfo, opn);
    21932368
    21942369        /* execute inevitable things */
    2195         op1 = op->l.n;
    2196         if (opinfo & OF_RES1) X.v = L.v = evaluate(op1, v1);
    2197         if (opinfo & OF_RES2) R.v = evaluate(op->r.n, v1+1);
    2198         if (opinfo & OF_STR1) L.s = getvar_s(L.v);
    2199         if (opinfo & OF_STR2) R.s = getvar_s(R.v);
    2200         if (opinfo & OF_NUM1) L.d = getvar_i(L.v);
    2201 
     2370        if (opinfo & OF_RES1)
     2371            L.v = evaluate(op1, v1);
     2372        if (opinfo & OF_RES2)
     2373            R.v = evaluate(op->r.n, v1+1);
     2374        if (opinfo & OF_STR1) {
     2375            L.s = getvar_s(L.v);
     2376            debug_printf_eval("L.s:'%s'\n", L.s);
     2377        }
     2378        if (opinfo & OF_STR2) {
     2379            R.s = getvar_s(R.v);
     2380            debug_printf_eval("R.s:'%s'\n", R.s);
     2381        }
     2382        if (opinfo & OF_NUM1) {
     2383            L_d = getvar_i(L.v);
     2384            debug_printf_eval("L_d:%f\n", L_d);
     2385        }
     2386
     2387        debug_printf_eval("switch(0x%x)\n", XC(opinfo & OPCLSMASK));
    22022388        switch (XC(opinfo & OPCLSMASK)) {
    22032389
     
    22122398                    if (ptest(op1->r.n))
    22132399                        op->info &= ~OF_CHECKED;
    2214 
    22152400                    op = op->a.n;
    22162401                } else {
     
    22182403                }
    22192404            } else {
    2220                 op = (ptest(op1)) ? op->a.n : op->r.n;
     2405                op = ptest(op1) ? op->a.n : op->r.n;
    22212406            }
    22222407            break;
     
    22422427
    22432428        case XC( OC_PRINT ):
    2244         case XC( OC_PRINTF ):
    2245             X.F = stdout;
     2429        case XC( OC_PRINTF ): {
     2430            FILE *F = stdout;
     2431
    22462432            if (op->r.n) {
    2247                 X.rsm = newfile(R.s);
    2248                 if (!X.rsm->F) {
     2433                rstream *rsm = newfile(R.s);
     2434                if (!rsm->F) {
    22492435                    if (opn == '|') {
    2250                         X.rsm->F = popen(R.s, "w");
    2251                         if (X.rsm->F == NULL)
     2436                        rsm->F = popen(R.s, "w");
     2437                        if (rsm->F == NULL)
    22522438                            bb_perror_msg_and_die("popen");
    2253                         X.rsm->is_pipe = 1;
     2439                        rsm->is_pipe = 1;
    22542440                    } else {
    2255                         X.rsm->F = xfopen(R.s, opn=='w' ? "w" : "a");
     2441                        rsm->F = xfopen(R.s, opn=='w' ? "w" : "a");
    22562442                    }
    22572443                }
    2258                 X.F = X.rsm->F;
     2444                F = rsm->F;
    22592445            }
    22602446
    22612447            if ((opinfo & OPCLSMASK) == OC_PRINT) {
    22622448                if (!op1) {
    2263                     fputs(getvar_s(intvar[F0]), X.F);
     2449                    fputs(getvar_s(intvar[F0]), F);
    22642450                } else {
    22652451                    while (op1) {
    2266                         L.v = evaluate(nextarg(&op1), v1);
    2267                         if (L.v->type & VF_NUMBER) {
     2452                        var *v = evaluate(nextarg(&op1), v1);
     2453                        if (v->type & VF_NUMBER) {
    22682454                            fmt_num(g_buf, MAXVARFMT, getvar_s(intvar[OFMT]),
    2269                                     getvar_i(L.v), TRUE);
    2270                             fputs(g_buf, X.F);
     2455                                    getvar_i(v), TRUE);
     2456                            fputs(g_buf, F);
    22712457                        } else {
    2272                             fputs(getvar_s(L.v), X.F);
     2458                            fputs(getvar_s(v), F);
    22732459                        }
    22742460
    2275                         if (op1) fputs(getvar_s(intvar[OFS]), X.F);
     2461                        if (op1)
     2462                            fputs(getvar_s(intvar[OFS]), F);
    22762463                    }
    22772464                }
    2278                 fputs(getvar_s(intvar[ORS]), X.F);
     2465                fputs(getvar_s(intvar[ORS]), F);
    22792466
    22802467            } else {    /* OC_PRINTF */
    2281                 L.s = awk_printf(op1);
    2282                 fputs(L.s, X.F);
    2283                 free((char*)L.s);
    2284             }
    2285             fflush(X.F);
    2286             break;
    2287 
    2288         case XC( OC_DELETE ):
    2289             X.info = op1->info & OPCLSMASK;
    2290             if (X.info == OC_VAR) {
    2291                 R.v = op1->l.v;
    2292             } else if (X.info == OC_FNARG) {
    2293                 R.v = &fnargs[op1->l.i];
     2468                char *s = awk_printf(op1);
     2469                fputs(s, F);
     2470                free(s);
     2471            }
     2472            fflush(F);
     2473            break;
     2474        }
     2475
     2476        case XC( OC_DELETE ): {
     2477            uint32_t info = op1->info & OPCLSMASK;
     2478            var *v;
     2479
     2480            if (info == OC_VAR) {
     2481                v = op1->l.v;
     2482            } else if (info == OC_FNARG) {
     2483                v = &fnargs[op1->l.aidx];
    22942484            } else {
    22952485                syntax_error(EMSG_NOT_ARRAY);
     
    22972487
    22982488            if (op1->r.n) {
     2489                const char *s;
    22992490                clrvar(L.v);
    2300                 L.s = getvar_s(evaluate(op1->r.n, v1));
    2301                 hash_remove(iamarray(R.v), L.s);
     2491                s = getvar_s(evaluate(op1->r.n, v1));
     2492                hash_remove(iamarray(v), s);
    23022493            } else {
    2303                 clear_array(iamarray(R.v));
    2304             }
    2305             break;
     2494                clear_array(iamarray(v));
     2495            }
     2496            break;
     2497        }
    23062498
    23072499        case XC( OC_NEWSOURCE ):
    2308             g_progname = op->l.s;
     2500            g_progname = op->l.new_progname;
    23092501            break;
    23102502
     
    23222514
    23232515        case XC( OC_EXIT ):
    2324             awk_exit(L.d);
     2516            awk_exit(L_d);
    23252517
    23262518        /* -- recursive node type -- */
     
    23332525
    23342526        case XC( OC_FNARG ):
    2335             L.v = &fnargs[op->l.i];
     2527            L.v = &fnargs[op->l.aidx];
    23362528 v_cont:
    23372529            res = op->r.n ? findvar(iamarray(L.v), R.s) : L.v;
     
    23502542            op1 = op->r.n;
    23512543 re_cont:
    2352             X.re = as_regex(op1, &sreg);
    2353             R.i = regexec(X.re, L.s, 0, NULL, 0);
    2354             if (X.re == &sreg) regfree(X.re);
    2355             setvar_i(res, (R.i == 0 ? 1 : 0) ^ (opn == '!' ? 1 : 0));
     2544            {
     2545                regex_t *re = as_regex(op1, &sreg);
     2546                int i = regexec(re, L.s, 0, NULL, 0);
     2547                if (re == &sreg)
     2548                    regfree(re);
     2549                setvar_i(res, (i == 0) ^ (opn == '!'));
     2550            }
    23562551            break;
    23572552
    23582553        case XC( OC_MOVE ):
     2554            debug_printf_eval("MOVE\n");
    23592555            /* if source is a temporary string, jusk relink it to dest */
    2360             if (R.v == v1+1 && R.v->string) {
    2361                 res = setvar_p(L.v, R.v->string);
    2362                 R.v->string = NULL;
    2363             } else {
     2556//Disabled: if R.v is numeric but happens to have cached R.v->string,
     2557//then L.v ends up being a string, which is wrong
     2558//          if (R.v == v1+1 && R.v->string) {
     2559//              res = setvar_p(L.v, R.v->string);
     2560//              R.v->string = NULL;
     2561//          } else {
    23642562                res = copyvar(L.v, R.v);
    2365             }
     2563//          }
    23662564            break;
    23672565
     
    23722570            break;
    23732571
    2374         case XC( OC_FUNC ):
     2572        case XC( OC_FUNC ): {
     2573            var *vbeg, *v;
     2574            const char *sv_progname;
     2575
    23752576            if (!op->r.f->body.first)
    23762577                syntax_error(EMSG_UNDEF_FUNC);
    23772578
    2378             X.v = R.v = nvalloc(op->r.f->nargs+1);
     2579            vbeg = v = nvalloc(op->r.f->nargs + 1);
    23792580            while (op1) {
    2380                 L.v = evaluate(nextarg(&op1), v1);
    2381                 copyvar(R.v, L.v);
    2382                 R.v->type |= VF_CHILD;
    2383                 R.v->x.parent = L.v;
    2384                 if (++R.v - X.v >= op->r.f->nargs)
     2581                var *arg = evaluate(nextarg(&op1), v1);
     2582                copyvar(v, arg);
     2583                v->type |= VF_CHILD;
     2584                v->x.parent = arg;
     2585                if (++v - vbeg >= op->r.f->nargs)
    23852586                    break;
    23862587            }
    23872588
    2388             R.v = fnargs;
    2389             fnargs = X.v;
    2390 
    2391             L.s = g_progname;
     2589            v = fnargs;
     2590            fnargs = vbeg;
     2591            sv_progname = g_progname;
     2592
    23922593            res = evaluate(op->r.f->body.first, res);
    2393             g_progname = L.s;
    2394 
     2594
     2595            g_progname = sv_progname;
    23952596            nvfree(fnargs);
    2396             fnargs = R.v;
    2397             break;
     2597            fnargs = v;
     2598
     2599            break;
     2600        }
    23982601
    23992602        case XC( OC_GETLINE ):
    2400         case XC( OC_PGETLINE ):
     2603        case XC( OC_PGETLINE ): {
     2604            rstream *rsm;
     2605            int i;
     2606
    24012607            if (op1) {
    2402                 X.rsm = newfile(L.s);
    2403                 if (!X.rsm->F) {
     2608                rsm = newfile(L.s);
     2609                if (!rsm->F) {
    24042610                    if ((opinfo & OPCLSMASK) == OC_PGETLINE) {
    2405                         X.rsm->F = popen(L.s, "r");
    2406                         X.rsm->is_pipe = TRUE;
     2611                        rsm->F = popen(L.s, "r");
     2612                        rsm->is_pipe = TRUE;
    24072613                    } else {
    2408                         X.rsm->F = fopen(L.s, "r");     /* not xfopen! */
     2614                        rsm->F = fopen_for_read(L.s);  /* not xfopen! */
    24092615                    }
    24102616                }
    24112617            } else {
    2412                 if (!iF) iF = next_input_file();
    2413                 X.rsm = iF;
    2414             }
    2415 
    2416             if (!X.rsm->F) {
     2618                if (!iF)
     2619                    iF = next_input_file();
     2620                rsm = iF;
     2621            }
     2622
     2623            if (!rsm->F) {
    24172624                setvar_i(intvar[ERRNO], errno);
    24182625                setvar_i(res, -1);
     
    24232630                R.v = intvar[F0];
    24242631
    2425             L.i = awk_getline(X.rsm, R.v);
    2426             if (L.i > 0) {
    2427                 if (!op1) {
    2428                     incvar(intvar[FNR]);
    2429                     incvar(intvar[NR]);
     2632            i = awk_getline(rsm, R.v);
     2633            if (i > 0 && !op1) {
     2634                incvar(intvar[FNR]);
     2635                incvar(intvar[NR]);
     2636            }
     2637            setvar_i(res, i);
     2638            break;
     2639        }
     2640
     2641        /* simple builtins */
     2642        case XC( OC_FBLTIN ): {
     2643            double R_d = R_d; /* for compiler */
     2644
     2645            switch (opn) {
     2646            case F_in:
     2647                R_d = (int)L_d;
     2648                break;
     2649
     2650            case F_rn:
     2651                R_d = (double)rand() / (double)RAND_MAX;
     2652                break;
     2653
     2654            case F_co:
     2655                if (ENABLE_FEATURE_AWK_LIBM) {
     2656                    R_d = cos(L_d);
     2657                    break;
    24302658                }
    2431             }
    2432             setvar_i(res, L.i);
    2433             break;
    2434 
    2435         /* simple builtins */
    2436         case XC( OC_FBLTIN ):
    2437             switch (opn) {
    2438 
    2439             case F_in:
    2440                 R.d = (int)L.d;
    2441                 break;
    2442 
    2443             case F_rn:
    2444                 R.d = (double)rand() / (double)RAND_MAX;
    2445                 break;
    2446 #if ENABLE_FEATURE_AWK_MATH
    2447             case F_co:
    2448                 R.d = cos(L.d);
    2449                 break;
    24502659
    24512660            case F_ex:
    2452                 R.d = exp(L.d);
    2453                 break;
     2661                if (ENABLE_FEATURE_AWK_LIBM) {
     2662                    R_d = exp(L_d);
     2663                    break;
     2664                }
    24542665
    24552666            case F_lg:
    2456                 R.d = log(L.d);
    2457                 break;
     2667                if (ENABLE_FEATURE_AWK_LIBM) {
     2668                    R_d = log(L_d);
     2669                    break;
     2670                }
    24582671
    24592672            case F_si:
    2460                 R.d = sin(L.d);
    2461                 break;
     2673                if (ENABLE_FEATURE_AWK_LIBM) {
     2674                    R_d = sin(L_d);
     2675                    break;
     2676                }
    24622677
    24632678            case F_sq:
    2464                 R.d = sqrt(L.d);
    2465                 break;
    2466 #else
    2467             case F_co:
    2468             case F_ex:
    2469             case F_lg:
    2470             case F_si:
    2471             case F_sq:
     2679                if (ENABLE_FEATURE_AWK_LIBM) {
     2680                    R_d = sqrt(L_d);
     2681                    break;
     2682                }
     2683
    24722684                syntax_error(EMSG_NO_MATH);
    24732685                break;
    2474 #endif
     2686
    24752687            case F_sr:
    2476                 R.d = (double)seed;
    2477                 seed = op1 ? (unsigned)L.d : (unsigned)time(NULL);
     2688                R_d = (double)seed;
     2689                seed = op1 ? (unsigned)L_d : (unsigned)time(NULL);
    24782690                srand(seed);
    24792691                break;
    24802692
    24812693            case F_ti:
    2482                 R.d = time(NULL);
     2694                R_d = time(NULL);
    24832695                break;
    24842696
     
    24862698                if (!op1)
    24872699                    L.s = getvar_s(intvar[F0]);
    2488                 R.d = strlen(L.s);
     2700                R_d = strlen(L.s);
    24892701                break;
    24902702
    24912703            case F_sy:
    2492                 fflush(NULL);
    2493                 R.d = (ENABLE_FEATURE_ALLOW_EXEC && L.s && *L.s)
     2704                fflush_all();
     2705                R_d = (ENABLE_FEATURE_ALLOW_EXEC && L.s && *L.s)
    24942706                        ? (system(L.s) >> 8) : 0;
    24952707                break;
    24962708
    24972709            case F_ff:
    2498                 if (!op1)
     2710                if (!op1) {
    24992711                    fflush(stdout);
    2500                 else {
    2501                     if (L.s && *L.s) {
    2502                         X.rsm = newfile(L.s);
    2503                         fflush(X.rsm->F);
    2504                     } else {
    2505                         fflush(NULL);
    2506                     }
     2712                } else if (L.s && *L.s) {
     2713                    rstream *rsm = newfile(L.s);
     2714                    fflush(rsm->F);
     2715                } else {
     2716                    fflush_all();
    25072717                }
    25082718                break;
    25092719
    2510             case F_cl:
    2511                 X.rsm = (rstream *)hash_search(fdhash, L.s);
    2512                 if (X.rsm) {
    2513                     R.i = X.rsm->is_pipe ? pclose(X.rsm->F) : fclose(X.rsm->F);
    2514                     free(X.rsm->buffer);
     2720            case F_cl: {
     2721                rstream *rsm;
     2722                int err = 0;
     2723                rsm = (rstream *)hash_search(fdhash, L.s);
     2724                debug_printf_eval("OC_FBLTIN F_cl rsm:%p\n", rsm);
     2725                if (rsm) {
     2726                    debug_printf_eval("OC_FBLTIN F_cl "
     2727                        "rsm->is_pipe:%d, ->F:%p\n",
     2728                        rsm->is_pipe, rsm->F);
     2729                    /* Can be NULL if open failed. Example:
     2730                     * getline line <"doesnt_exist";
     2731                     * close("doesnt_exist"); <--- here rsm->F is NULL
     2732                     */
     2733                    if (rsm->F)
     2734                        err = rsm->is_pipe ? pclose(rsm->F) : fclose(rsm->F);
     2735                    free(rsm->buffer);
    25152736                    hash_remove(fdhash, L.s);
    25162737                }
    2517                 if (R.i != 0)
     2738                if (err)
    25182739                    setvar_i(intvar[ERRNO], errno);
    2519                 R.d = (double)R.i;
     2740                R_d = (double)err;
    25202741                break;
    25212742            }
    2522             setvar_i(res, R.d);
    2523             break;
     2743            } /* switch */
     2744            setvar_i(res, R_d);
     2745            break;
     2746        }
    25242747
    25252748        case XC( OC_BUILTIN ):
     
    25312754            break;
    25322755
    2533         case XC( OC_UNARY ):
    2534             X.v = R.v;
    2535             L.d = R.d = getvar_i(R.v);
     2756        case XC( OC_UNARY ): {
     2757            double Ld, R_d;
     2758
     2759            Ld = R_d = getvar_i(R.v);
    25362760            switch (opn) {
    25372761            case 'P':
    2538                 L.d = ++R.d;
     2762                Ld = ++R_d;
    25392763                goto r_op_change;
    25402764            case 'p':
    2541                 R.d++;
     2765                R_d++;
    25422766                goto r_op_change;
    25432767            case 'M':
    2544                 L.d = --R.d;
     2768                Ld = --R_d;
    25452769                goto r_op_change;
    25462770            case 'm':
    2547                 R.d--;
    2548                 goto r_op_change;
     2771                R_d--;
     2772 r_op_change:
     2773                setvar_i(R.v, R_d);
     2774                break;
    25492775            case '!':
    2550                 L.d = istrue(X.v) ? 0 : 1;
     2776                Ld = !istrue(R.v);
    25512777                break;
    25522778            case '-':
    2553                 L.d = -R.d;
     2779                Ld = -R_d;
    25542780                break;
    2555  r_op_change:
    2556                 setvar_i(X.v, R.d);
    2557             }
    2558             setvar_i(res, L.d);
    2559             break;
    2560 
    2561         case XC( OC_FIELD ):
    2562             R.i = (int)getvar_i(R.v);
    2563             if (R.i == 0) {
     2781            }
     2782            setvar_i(res, Ld);
     2783            break;
     2784        }
     2785
     2786        case XC( OC_FIELD ): {
     2787            int i = (int)getvar_i(R.v);
     2788            if (i == 0) {
    25642789                res = intvar[F0];
    25652790            } else {
    25662791                split_f0();
    2567                 if (R.i > nfields)
    2568                     fsrealloc(R.i);
    2569                 res = &Fields[R.i - 1];
    2570             }
    2571             break;
     2792                if (i > nfields)
     2793                    fsrealloc(i);
     2794                res = &Fields[i - 1];
     2795            }
     2796            break;
     2797        }
    25722798
    25732799        /* concatenation (" ") and index joining (",") */
    25742800        case XC( OC_CONCAT ):
    2575         case XC( OC_COMMA ):
    2576             opn = strlen(L.s) + strlen(R.s) + 2;
    2577             X.s = xmalloc(opn);
    2578             strcpy(X.s, L.s);
    2579             if ((opinfo & OPCLSMASK) == OC_COMMA) {
    2580                 L.s = getvar_s(intvar[SUBSEP]);
    2581                 X.s = xrealloc(X.s, opn + strlen(L.s));
    2582                 strcat(X.s, L.s);
    2583             }
    2584             strcat(X.s, R.s);
    2585             setvar_p(res, X.s);
    2586             break;
     2801        case XC( OC_COMMA ): {
     2802            const char *sep = "";
     2803            if ((opinfo & OPCLSMASK) == OC_COMMA)
     2804                sep = getvar_s(intvar[SUBSEP]);
     2805            setvar_p(res, xasprintf("%s%s%s", L.s, sep, R.s));
     2806            break;
     2807        }
    25872808
    25882809        case XC( OC_LAND ):
     
    25952816
    25962817        case XC( OC_BINARY ):
    2597         case XC( OC_REPLACE ):
    2598             R.d = getvar_i(R.v);
     2818        case XC( OC_REPLACE ): {
     2819            double R_d = getvar_i(R.v);
     2820            debug_printf_eval("BINARY/REPLACE: R_d:%f opn:%c\n", R_d, opn);
    25992821            switch (opn) {
    26002822            case '+':
    2601                 L.d += R.d;
     2823                L_d += R_d;
    26022824                break;
    26032825            case '-':
    2604                 L.d -= R.d;
     2826                L_d -= R_d;
    26052827                break;
    26062828            case '*':
    2607                 L.d *= R.d;
     2829                L_d *= R_d;
    26082830                break;
    26092831            case '/':
    2610                 if (R.d == 0) syntax_error(EMSG_DIV_BY_ZERO);
    2611                 L.d /= R.d;
     2832                if (R_d == 0)
     2833                    syntax_error(EMSG_DIV_BY_ZERO);
     2834                L_d /= R_d;
    26122835                break;
    26132836            case '&':
    2614 #if ENABLE_FEATURE_AWK_MATH
    2615                 L.d = pow(L.d, R.d);
    2616 #else
    2617                 syntax_error(EMSG_NO_MATH);
    2618 #endif
     2837                if (ENABLE_FEATURE_AWK_LIBM)
     2838                    L_d = pow(L_d, R_d);
     2839                else
     2840                    syntax_error(EMSG_NO_MATH);
    26192841                break;
    26202842            case '%':
    2621                 if (R.d == 0) syntax_error(EMSG_DIV_BY_ZERO);
    2622                 L.d -= (int)(L.d / R.d) * R.d;
     2843                if (R_d == 0)
     2844                    syntax_error(EMSG_DIV_BY_ZERO);
     2845                L_d -= (int)(L_d / R_d) * R_d;
    26232846                break;
    26242847            }
    2625             res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : X.v, L.d);
    2626             break;
    2627 
    2628         case XC( OC_COMPARE ):
     2848            debug_printf_eval("BINARY/REPLACE result:%f\n", L_d);
     2849            res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : L.v, L_d);
     2850            break;
     2851        }
     2852
     2853        case XC( OC_COMPARE ): {
     2854            int i = i; /* for compiler */
     2855            double Ld;
     2856
    26292857            if (is_numeric(L.v) && is_numeric(R.v)) {
    2630                 L.d = getvar_i(L.v) - getvar_i(R.v);
     2858                Ld = getvar_i(L.v) - getvar_i(R.v);
    26312859            } else {
    2632                 L.s = getvar_s(L.v);
    2633                 R.s = getvar_s(R.v);
    2634                 L.d = icase ? strcasecmp(L.s, R.s) : strcmp(L.s, R.s);
     2860                const char *l = getvar_s(L.v);
     2861                const char *r = getvar_s(R.v);
     2862                Ld = icase ? strcasecmp(l, r) : strcmp(l, r);
    26352863            }
    26362864            switch (opn & 0xfe) {
    26372865            case 0:
    2638                 R.i = (L.d > 0);
     2866                i = (Ld > 0);
    26392867                break;
    26402868            case 2:
    2641                 R.i = (L.d >= 0);
     2869                i = (Ld >= 0);
    26422870                break;
    26432871            case 4:
    2644                 R.i = (L.d == 0);
     2872                i = (Ld == 0);
    26452873                break;
    26462874            }
    2647             setvar_i(res, (opn & 0x1 ? R.i : !R.i) ? 1 : 0);
    2648             break;
     2875            setvar_i(res, (i == 0) ^ (opn & 1));
     2876            break;
     2877        }
    26492878
    26502879        default:
     
    26572886        if (nextrec)
    26582887            break;
    2659     }
     2888    } /* while (op) */
     2889
    26602890    nvfree(v1);
     2891    debug_printf_eval("returning from %s(): %p\n", __func__, res);
    26612892    return res;
    26622893#undef fnargs
     
    26992930static int is_assignment(const char *expr)
    27002931{
    2701     char *exprc, *s, *s0, *s1;
     2932    char *exprc, *val, *s, *s1;
     2933
     2934    if (!isalnum_(*expr) || (val = strchr(expr, '=')) == NULL) {
     2935        return FALSE;
     2936    }
    27022937
    27032938    exprc = xstrdup(expr);
    2704     if (!isalnum_(*exprc) || (s = strchr(exprc, '=')) == NULL) {
    2705         free(exprc);
    2706         return FALSE;
    2707     }
    2708 
    2709     *(s++) = '\0';
    2710     s0 = s1 = s;
    2711     while (*s)
    2712         *(s1++) = nextchar(&s);
    2713 
    2714     *s1 = '\0';
    2715     setvar_u(newvar(exprc), s0);
     2939    val = exprc + (val - expr);
     2940    *val++ = '\0';
     2941
     2942    s = s1 = val;
     2943    while ((*s1 = nextchar(&s)) != '\0')
     2944        s1++;
     2945
     2946    setvar_u(newvar(exprc), val);
    27162947    free(exprc);
    27172948    return TRUE;
     
    27272958    const char *fname, *ind;
    27282959
    2729     if (rsm.F) fclose(rsm.F);
     2960    if (rsm.F)
     2961        fclose(rsm.F);
    27302962    rsm.F = NULL;
    27312963    rsm.pos = rsm.adv = 0;
     
    27412973            fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind));
    27422974            if (fname && *fname && !is_assignment(fname))
    2743                 F = afopen(fname, "r");
     2975                F = xfopen_stdin(fname);
    27442976        }
    27452977    } while (!F);
     
    27532985}
    27542986
    2755 int awk_main(int argc, char **argv);
     2987int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    27562988int awk_main(int argc, char **argv)
    27572989{
    27582990    unsigned opt;
    27592991    char *opt_F, *opt_W;
    2760     llist_t *opt_v = NULL;
    2761     int i, j, flen;
     2992    llist_t *list_v = NULL;
     2993    llist_t *list_f = NULL;
     2994    int i, j;
    27622995    var *v;
    27632996    var tv;
     
    28173050        }
    28183051    }
    2819     opt_complementary = "v::";
    2820     opt = getopt32(argv, "F:v:f:W:", &opt_F, &opt_v, &g_progname, &opt_W);
     3052    opt_complementary = "v::f::"; /* -v and -f can occur multiple times */
     3053    opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, &opt_W);
    28213054    argv += optind;
    28223055    argc -= optind;
    28233056    if (opt & 0x1)
    28243057        setvar_s(intvar[FS], opt_F); // -F
    2825     while (opt_v) { /* -v */
    2826         if (!is_assignment(llist_pop(&opt_v)))
     3058    while (list_v) { /* -v */
     3059        if (!is_assignment(llist_pop(&list_v)))
    28273060            bb_show_usage();
    28283061    }
    2829     if (opt & 0x4) { // -f
    2830         char *s = s; /* die, gcc, die */
    2831         FILE *from_file = afopen(g_progname, "r");
    2832         /* one byte is reserved for some trick in next_token */
    2833         if (fseek(from_file, 0, SEEK_END) == 0) {
    2834             flen = ftell(from_file);
    2835             s = xmalloc(flen + 4);
    2836             fseek(from_file, 0, SEEK_SET);
    2837             i = 1 + fread(s + 1, 1, flen, from_file);
    2838         } else {
     3062    if (list_f) { /* -f */
     3063        do {
     3064            char *s = NULL;
     3065            FILE *from_file;
     3066
     3067            g_progname = llist_pop(&list_f);
     3068            from_file = xfopen_stdin(g_progname);
     3069            /* one byte is reserved for some trick in next_token */
    28393070            for (i = j = 1; j > 0; i += j) {
    28403071                s = xrealloc(s, i + 4096);
    28413072                j = fread(s + i, 1, 4094, from_file);
    28423073            }
    2843         }
    2844         s[i] = '\0';
    2845         fclose(from_file);
    2846         parse_program(s + 1);
    2847         free(s);
     3074            s[i] = '\0';
     3075            fclose(from_file);
     3076            parse_program(s + 1);
     3077            free(s);
     3078        } while (list_f);
     3079        argc++;
    28483080    } else { // no -f: take program from 1st parameter
    28493081        if (!argc)
     
    28513083        g_progname = "cmd. line";
    28523084        parse_program(*argv++);
    2853         argc--;
    28543085    }
    28553086    if (opt & 0x8) // -W
     
    28573088
    28583089    /* fill in ARGV array */
    2859     setvar_i(intvar[ARGC], argc + 1);
     3090    setvar_i(intvar[ARGC], argc);
    28603091    setari_u(intvar[ARGV], 0, "awk");
    28613092    i = 0;
     
    28683099
    28693100    /* input file could already be opened in BEGIN block */
    2870     if (!iF) iF = next_input_file();
     3101    if (!iF)
     3102        iF = next_input_file();
    28713103
    28723104    /* passing through input files */
Note: See TracChangeset for help on using the changeset viewer.