Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/editors/awk.c


Ignore:
Timestamp:
Nov 6, 2007, 11:01:53 AM (16 years ago)
Author:
Bruno Cornec
Message:
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File:
1 edited

Legend:

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

    r821 r1770  
    88 */
    99
    10 #include <stdio.h>
    11 #include <stdlib.h>
    12 #include <unistd.h>
    13 #include <errno.h>
    14 #include <string.h>
    15 #include <strings.h>
    16 #include <time.h>
     10#include "libbb.h"
     11#include "xregex.h"
    1712#include <math.h>
    18 #include <ctype.h>
    19 #include <getopt.h>
    20 
    21 #include "xregex.h"
    22 #include "busybox.h"
    23 
    24 
    25 #define MAXVARFMT   240
    26 #define MINNVBLOCK  64
     13extern char **environ;
     14
     15/* This is a NOEXEC applet. Be very careful! */
     16
     17
     18#define MAXVARFMT       240
     19#define MINNVBLOCK      64
    2720
    2821/* variable flags */
    29 #define VF_NUMBER   0x0001  /* 1 = primary type is number */
    30 #define VF_ARRAY    0x0002  /* 1 = it's an array */
    31 
    32 #define VF_CACHED   0x0100  /* 1 = num/str value has cached str/num eq */
    33 #define VF_USER     0x0200  /* 1 = user input (may be numeric string) */
    34 #define VF_SPECIAL  0x0400  /* 1 = requires extra handling when changed */
    35 #define VF_WALK     0x0800  /* 1 = variable has alloc'd x.walker list */
    36 #define VF_FSTR     0x1000  /* 1 = string points to fstring buffer */
    37 #define VF_CHILD    0x2000  /* 1 = function arg; x.parent points to source */
    38 #define VF_DIRTY    0x4000  /* 1 = variable was set explicitly */
     22#define VF_NUMBER       0x0001  /* 1 = primary type is number */
     23#define VF_ARRAY        0x0002  /* 1 = it's an array */
     24
     25#define VF_CACHED       0x0100  /* 1 = num/str value has cached str/num eq */
     26#define VF_USER         0x0200  /* 1 = user input (may be numeric string) */
     27#define VF_SPECIAL      0x0400  /* 1 = requires extra handling when changed */
     28#define VF_WALK         0x0800  /* 1 = variable has alloc'd x.walker list */
     29#define VF_FSTR         0x1000  /* 1 = var::string points to fstring buffer */
     30#define VF_CHILD        0x2000  /* 1 = function arg; x.parent points to source */
     31#define VF_DIRTY        0x4000  /* 1 = variable was set explicitly */
    3932
    4033/* these flags are static, don't change them when value is changed */
    41 #define VF_DONTTOUCH (VF_ARRAY | VF_SPECIAL | VF_WALK | VF_CHILD | VF_DIRTY)
     34#define VF_DONTTOUCH    (VF_ARRAY | VF_SPECIAL | VF_WALK | VF_CHILD | VF_DIRTY)
    4235
    4336/* Variable */
    4437typedef struct var_s {
    45     unsigned short type;        /* flags */
     38    unsigned type;            /* flags */
    4639    double number;
    4740    char *string;
    4841    union {
    49         int aidx;               /* func arg idx (for compilation stage) */
    50         struct xhash_s *array;  /* array ptr */
    51         struct var_s *parent;   /* for func args, ptr to actual parameter */
    52         char **walker;          /* list of array elements (for..in) */
     42        int aidx;               /* func arg idx (for compilation stage) */
     43        struct xhash_s *array;  /* array ptr */
     44        struct var_s *parent;   /* for func args, ptr to actual parameter */
     45        char **walker;          /* list of array elements (for..in) */
    5346    } x;
    5447} var;
     
    5851    struct node_s *first;
    5952    struct node_s *last;
    60     char *programname;
     53    const char *programname;
    6154} chain;
    6255
    6356/* Function */
    6457typedef struct func_s {
    65     unsigned short nargs;
     58    unsigned nargs;
    6659    struct chain_s body;
    6760} func;
     
    7467    int size;
    7568    int pos;
    76     unsigned short is_pipe;
     69    smallint is_pipe;
    7770} rstream;
    7871
    7972typedef struct hash_item_s {
    8073    union {
    81         struct var_s v;         /* variable/array hash */
    82         struct rstream_s rs;    /* redirect streams hash */
    83         struct func_s f;        /* functions hash */
     74        struct var_s v;         /* variable/array hash */
     75        struct rstream_s rs;    /* redirect streams hash */
     76        struct func_s f;        /* functions hash */
    8477    } data;
    85     struct hash_item_s *next;   /* next in chain */
    86     char name[1];               /* really it's longer */
     78    struct hash_item_s *next;       /* next in chain */
     79    char name[1];                   /* really it's longer */
    8780} hash_item;
    8881
    8982typedef struct xhash_s {
    90     unsigned int nel;                   /* num of elements */
    91     unsigned int csize;                 /* current hash size */
    92     unsigned int nprime;                /* next hash size in PRIMES[] */
    93     unsigned int glen;                  /* summary length of item names */
     83    unsigned nel;           /* num of elements */
     84    unsigned csize;         /* current hash size */
     85    unsigned nprime;        /* next hash size in PRIMES[] */
     86    unsigned glen;          /* summary length of item names */
    9487    struct hash_item_s **items;
    9588} xhash;
     
    9891typedef struct node_s {
    9992    uint32_t info;
    100     unsigned short lineno;
     93    unsigned lineno;
    10194    union {
    10295        struct node_s *n;
     
    164157#define TC_NUMBER   (1 << 29)
    165158
    166 #define TC_UOPPRE   (TC_UOPPRE1 | TC_UOPPRE2)
     159#define TC_UOPPRE  (TC_UOPPRE1 | TC_UOPPRE2)
    167160
    168161/* combined token classes */
    169 #define TC_BINOP    (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN)
    170 #define TC_UNARYOP  (TC_UOPPRE | TC_UOPPOST)
    171 #define TC_OPERAND  (TC_VARIABLE | TC_ARRAY | TC_FUNCTION | \
    172     TC_BUILTIN | TC_GETLINE | TC_SEQSTART | TC_STRING | TC_NUMBER)
    173 
    174 #define TC_STATEMNT (TC_STATX | TC_WHILE)
    175 #define TC_OPTERM   (TC_SEMICOL | TC_NEWLINE)
     162#define TC_BINOP   (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN)
     163#define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST)
     164#define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \
     165                   | TC_BUILTIN | TC_GETLINE | TC_SEQSTART | TC_STRING | TC_NUMBER)
     166
     167#define TC_STATEMNT (TC_STATX | TC_WHILE)
     168#define TC_OPTERM  (TC_SEMICOL | TC_NEWLINE)
    176169
    177170/* word tokens, cannot mean something else if not expected */
    178 #define TC_WORD     (TC_IN | TC_STATEMNT | TC_ELSE | TC_BUILTIN | \
    179     TC_GETLINE | TC_FUNCDECL | TC_BEGIN | TC_END)
     171#define TC_WORD    (TC_IN | TC_STATEMNT | TC_ELSE | TC_BUILTIN \
     172                   | TC_GETLINE | TC_FUNCDECL | TC_BEGIN | TC_END)
    180173
    181174/* discard newlines after these */
    182 #define TC_NOTERM   (TC_COMMA | TC_GRPSTART | TC_GRPTERM | \
    183     TC_BINOP | TC_OPTERM)
     175#define TC_NOTERM  (TC_COMMA | TC_GRPSTART | TC_GRPTERM \
     176                   | TC_BINOP | TC_OPTERM)
    184177
    185178/* what can expression begin with */
    186 #define TC_OPSEQ    (TC_OPERAND | TC_UOPPRE | TC_REGEXP)
     179#define TC_OPSEQ   (TC_OPERAND | TC_UOPPRE | TC_REGEXP)
    187180/* what can group begin with */
    188 #define TC_GRPSEQ   (TC_OPSEQ | TC_OPTERM | TC_STATEMNT | TC_GRPSTART)
     181#define TC_GRPSEQ  (TC_OPSEQ | TC_OPTERM | TC_STATEMNT | TC_GRPSTART)
    189182
    190183/* if previous token class is CONCAT1 and next is CONCAT2, concatenation */
    191184/* operator is inserted between them */
    192 #define TC_CONCAT1  (TC_VARIABLE | TC_ARRTERM | TC_SEQTERM | \
    193     TC_STRING | TC_NUMBER | TC_UOPPOST)
    194 #define TC_CONCAT2  (TC_OPERAND | TC_UOPPRE)
    195 
    196 #define OF_RES1     0x010000
    197 #define OF_RES2     0x020000
    198 #define OF_STR1     0x040000
    199 #define OF_STR2     0x080000
    200 #define OF_NUM1     0x100000
    201 #define OF_CHECKED  0x200000
     185#define TC_CONCAT1 (TC_VARIABLE | TC_ARRTERM | TC_SEQTERM \
     186                   | TC_STRING | TC_NUMBER | TC_UOPPOST)
     187#define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE)
     188
     189#define OF_RES1    0x010000
     190#define OF_RES2    0x020000
     191#define OF_STR1    0x040000
     192#define OF_STR2    0x080000
     193#define OF_NUM1    0x100000
     194#define OF_CHECKED 0x200000
    202195
    203196/* combined operator flags */
     
    213206#define SS  (OF_RES1 | OF_STR1 | OF_RES2 | OF_STR2)
    214207
    215 #define OPCLSMASK   0xFF00
    216 #define OPNMASK     0x007F
     208#define OPCLSMASK 0xFF00
     209#define OPNMASK   0x007F
    217210
    218211/* operator priority is a highest byte (even: r->l, odd: l->r grouping)
     
    220213 * n - min. number of args, vN - resolve Nth arg to var, sN - resolve to string
    221214 */
    222 #define P(x)    (x << 24)
    223 #define PRIMASK     0x7F000000
    224 #define PRIMASK2    0x7E000000
     215#define P(x)      (x << 24)
     216#define PRIMASK   0x7F000000
     217#define PRIMASK2  0x7E000000
    225218
    226219/* Operation classes */
     
    230223
    231224enum {
    232     OC_DELETE=0x0100,   OC_EXEC=0x0200,     OC_NEWSOURCE=0x0300,
    233     OC_PRINT=0x0400,    OC_PRINTF=0x0500,   OC_WALKINIT=0x0600,
    234 
    235     OC_BR=0x0700,       OC_BREAK=0x0800,    OC_CONTINUE=0x0900,
    236     OC_EXIT=0x0a00,     OC_NEXT=0x0b00,     OC_NEXTFILE=0x0c00,
    237     OC_TEST=0x0d00,     OC_WALKNEXT=0x0e00,
    238 
    239     OC_BINARY=0x1000,   OC_BUILTIN=0x1100,  OC_COLON=0x1200,
    240     OC_COMMA=0x1300,    OC_COMPARE=0x1400,  OC_CONCAT=0x1500,
    241     OC_FBLTIN=0x1600,   OC_FIELD=0x1700,    OC_FNARG=0x1800,
    242     OC_FUNC=0x1900,     OC_GETLINE=0x1a00,  OC_IN=0x1b00,
    243     OC_LAND=0x1c00,     OC_LOR=0x1d00,      OC_MATCH=0x1e00,
    244     OC_MOVE=0x1f00,     OC_PGETLINE=0x2000, OC_REGEXP=0x2100,
    245     OC_REPLACE=0x2200,  OC_RETURN=0x2300,   OC_SPRINTF=0x2400,
    246     OC_TERNARY=0x2500,  OC_UNARY=0x2600,    OC_VAR=0x2700,
    247     OC_DONE=0x2800,
    248 
    249     ST_IF=0x3000,       ST_DO=0x3100,       ST_FOR=0x3200,
    250     ST_WHILE=0x3300
     225    OC_DELETE = 0x0100,     OC_EXEC = 0x0200,       OC_NEWSOURCE = 0x0300,
     226    OC_PRINT = 0x0400,      OC_PRINTF = 0x0500,     OC_WALKINIT = 0x0600,
     227
     228    OC_BR = 0x0700,         OC_BREAK = 0x0800,      OC_CONTINUE = 0x0900,
     229    OC_EXIT = 0x0a00,       OC_NEXT = 0x0b00,       OC_NEXTFILE = 0x0c00,
     230    OC_TEST = 0x0d00,       OC_WALKNEXT = 0x0e00,
     231
     232    OC_BINARY = 0x1000,     OC_BUILTIN = 0x1100,    OC_COLON = 0x1200,
     233    OC_COMMA = 0x1300,      OC_COMPARE = 0x1400,    OC_CONCAT = 0x1500,
     234    OC_FBLTIN = 0x1600,     OC_FIELD = 0x1700,      OC_FNARG = 0x1800,
     235    OC_FUNC = 0x1900,       OC_GETLINE = 0x1a00,    OC_IN = 0x1b00,
     236    OC_LAND = 0x1c00,       OC_LOR = 0x1d00,        OC_MATCH = 0x1e00,
     237    OC_MOVE = 0x1f00,       OC_PGETLINE = 0x2000,   OC_REGEXP = 0x2100,
     238    OC_REPLACE = 0x2200,    OC_RETURN = 0x2300,     OC_SPRINTF = 0x2400,
     239    OC_TERNARY = 0x2500,    OC_UNARY = 0x2600,      OC_VAR = 0x2700,
     240    OC_DONE = 0x2800,
     241
     242    ST_IF = 0x3000,         ST_DO = 0x3100,         ST_FOR = 0x3200,
     243    ST_WHILE = 0x3300
    251244};
    252245
    253246/* simple builtins */
    254247enum {
    255     F_in=0, F_rn,   F_co,   F_ex,   F_lg,   F_si,   F_sq,   F_sr,
     248    F_in,   F_rn,   F_co,   F_ex,   F_lg,   F_si,   F_sq,   F_sr,
    256249    F_ti,   F_le,   F_sy,   F_ff,   F_cl
    257250};
     
    259252/* builtins */
    260253enum {
    261     B_a2=0, B_ix,   B_ma,   B_sp,   B_ss,   B_ti,   B_lo,   B_up,
    262     B_ge,   B_gs,   B_su
     254    B_a2,   B_ix,   B_ma,   B_sp,   B_ss,   B_ti,   B_lo,   B_up,
     255    B_ge,   B_gs,   B_su,
     256    B_an,   B_co,   B_ls,   B_or,   B_rs,   B_xo,
    263257};
    264258
    265259/* tokens and their corresponding info values */
    266260
    267 #define NTC     "\377"      /* switch to next token class (tc<<1) */
    268 #define NTCC    '\377'
     261#define NTC     "\377"  /* switch to next token class (tc<<1) */
     262#define NTCC    '\377'
    269263
    270264#define OC_B    OC_BUILTIN
    271265
    272 static char * const tokenlist =
    273     "\1("       NTC
    274     "\1)"       NTC
    275     "\1/"       NTC                                 /* REGEXP */
    276     "\2>>"      "\1>"       "\1|"       NTC         /* OUTRDR */
    277     "\2++"      "\2--"      NTC                     /* UOPPOST */
    278     "\2++"      "\2--"      "\1$"       NTC         /* UOPPRE1 */
    279     "\2=="      "\1="       "\2+="      "\2-="      /* BINOPX */
    280     "\2*="      "\2/="      "\2%="      "\2^="
    281     "\1+"       "\1-"       "\3**="     "\2**"
    282     "\1/"       "\1%"       "\1^"       "\1*"
    283     "\2!="      "\2>="      "\2<="      "\1>"
    284     "\1<"       "\2!~"      "\1~"       "\2&&"
    285     "\2||"      "\1?"       "\1:"       NTC
    286     "\2in"      NTC
    287     "\1,"       NTC
    288     "\1|"       NTC
    289     "\1+"       "\1-"       "\1!"       NTC         /* UOPPRE2 */
    290     "\1]"       NTC
    291     "\1{"       NTC
    292     "\1}"       NTC
    293     "\1;"       NTC
    294     "\1\n"      NTC
    295     "\2if"      "\2do"      "\3for"     "\5break"   /* STATX */
    296     "\10continue"           "\6delete"  "\5print"
    297     "\6printf"  "\4next"    "\10nextfile"
    298     "\6return"  "\4exit"    NTC
    299     "\5while"   NTC
    300     "\4else"    NTC
    301 
    302     "\5close"   "\6system"  "\6fflush"  "\5atan2"   /* BUILTIN */
    303     "\3cos"     "\3exp"     "\3int"     "\3log"
    304     "\4rand"    "\3sin"     "\4sqrt"    "\5srand"
    305     "\6gensub"  "\4gsub"    "\5index"   "\6length"
    306     "\5match"   "\5split"   "\7sprintf" "\3sub"
    307     "\6substr"  "\7systime" "\10strftime"
    308     "\7tolower" "\7toupper" NTC
    309     "\7getline" NTC
    310     "\4func"    "\10function"   NTC
    311     "\5BEGIN"   NTC
    312     "\3END"     "\0"
     266static 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"
    313309    ;
    314310
    315311static const uint32_t tokeninfo[] = {
    316 
    317312    0,
    318313    0,
    319314    OC_REGEXP,
    320     xS|'a',     xS|'w',     xS|'|',
    321     OC_UNARY|xV|P(9)|'p',       OC_UNARY|xV|P(9)|'m',
    322     OC_UNARY|xV|P(9)|'P',       OC_UNARY|xV|P(9)|'M',
    323         OC_FIELD|xV|P(5),
    324     OC_COMPARE|VV|P(39)|5,      OC_MOVE|VV|P(74),
    325         OC_REPLACE|NV|P(74)|'+',    OC_REPLACE|NV|P(74)|'-',
    326     OC_REPLACE|NV|P(74)|'*',    OC_REPLACE|NV|P(74)|'/',
    327         OC_REPLACE|NV|P(74)|'%',    OC_REPLACE|NV|P(74)|'&',
    328     OC_BINARY|NV|P(29)|'+',     OC_BINARY|NV|P(29)|'-',
    329         OC_REPLACE|NV|P(74)|'&',    OC_BINARY|NV|P(15)|'&',
    330     OC_BINARY|NV|P(25)|'/',     OC_BINARY|NV|P(25)|'%',
    331         OC_BINARY|NV|P(15)|'&',     OC_BINARY|NV|P(25)|'*',
    332     OC_COMPARE|VV|P(39)|4,      OC_COMPARE|VV|P(39)|3,
    333         OC_COMPARE|VV|P(39)|0,      OC_COMPARE|VV|P(39)|1,
    334     OC_COMPARE|VV|P(39)|2,      OC_MATCH|Sx|P(45)|'!',
    335         OC_MATCH|Sx|P(45)|'~',      OC_LAND|Vx|P(55),
    336     OC_LOR|Vx|P(59),            OC_TERNARY|Vx|P(64)|'?',
    337         OC_COLON|xx|P(67)|':',
     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)|':',
    338333    OC_IN|SV|P(49),
    339334    OC_COMMA|SS|P(80),
    340335    OC_PGETLINE|SV|P(37),
    341     OC_UNARY|xV|P(19)|'+',      OC_UNARY|xV|P(19)|'-',
    342         OC_UNARY|xV|P(19)|'!',
     336    OC_UNARY|xV|P(19)|'+',      OC_UNARY|xV|P(19)|'-',
     337        OC_UNARY|xV|P(19)|'!',
    343338    0,
    344339    0,
     
    346341    0,
    347342    0,
    348     ST_IF,          ST_DO,          ST_FOR,         OC_BREAK,
    349     OC_CONTINUE,                    OC_DELETE|Vx,   OC_PRINT,
    350     OC_PRINTF,      OC_NEXT,        OC_NEXTFILE,
    351     OC_RETURN|Vx,   OC_EXIT|Nx,
     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,
    352347    ST_WHILE,
    353348    0,
    354349
     350    OC_B|B_an|P(0x83), OC_B|B_co|P(0x41), OC_B|B_ls|P(0x83), OC_B|B_or|P(0x83),
     351    OC_B|B_rs|P(0x83), OC_B|B_xo|P(0x83),
    355352    OC_FBLTIN|Sx|F_cl, OC_FBLTIN|Sx|F_sy, OC_FBLTIN|Sx|F_ff, OC_B|B_a2|P(0x83),
    356353    OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg,
     
    369366/* asterisk marks SPECIAL vars; $ is just no-named Field0 */
    370367enum {
    371     CONVFMT=0,  OFMT,       FS,         OFS,
    372     ORS,        RS,         RT,         FILENAME,
    373     SUBSEP,     ARGIND,     ARGC,       ARGV,
    374     ERRNO,      FNR,
    375     NR,         NF,         IGNORECASE,
    376     ENVIRON,    F0,         _intvarcount_
     368    CONVFMT,    OFMT,       FS,         OFS,
     369    ORS,        RS,         RT,         FILENAME,
     370    SUBSEP,     ARGIND,     ARGC,       ARGV,
     371    ERRNO,      FNR,
     372    NR,         NF,         IGNORECASE,
     373    ENVIRON,    F0,         NUM_INTERNAL_VARS
    377374};
    378375
    379 static char * vNames =
    380     "CONVFMT\0" "OFMT\0"    "FS\0*"     "OFS\0"
    381     "ORS\0"     "RS\0*"     "RT\0"      "FILENAME\0"
    382     "SUBSEP\0"  "ARGIND\0"  "ARGC\0"    "ARGV\0"
    383     "ERRNO\0"   "FNR\0"
    384     "NR\0"      "NF\0*"     "IGNORECASE\0*"
    385     "ENVIRON\0" "$\0*"      "\0";
    386 
    387 static char * vValues =
    388     "%.6g\0"    "%.6g\0"    " \0"       " \0"
    389     "\n\0"      "\n\0"      "\0"        "\0"
     376static const char vNames[] ALIGN1 =
     377    "CONVFMT\0" "OFMT\0"    "FS\0*"     "OFS\0"
     378    "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";
     383
     384static const char vValues[] ALIGN1 =
     385    "%.6g\0"    "%.6g\0"    " \0"       " \0"
     386    "\n\0"      "\n\0"      "\0"        "\0"
    390387    "\034\0"
    391388    "\377";
    392389
    393390/* hash size may grow to these values */
    394 #define FIRST_PRIME 61;
    395 static const unsigned int PRIMES[] = { 251, 1021, 4093, 16381, 65521 };
    396 enum { NPRIMES = sizeof(PRIMES) / sizeof(unsigned int) };
    397 
    398 /* globals */
    399 
    400 extern char **environ;
    401 
    402 static var * V[_intvarcount_];
    403 static chain beginseq, mainseq, endseq, *seq;
    404 static int nextrec, nextfile;
    405 static node *break_ptr, *continue_ptr;
    406 static rstream *iF;
    407 static xhash *vhash, *ahash, *fdhash, *fnhash;
    408 static char *programname;
    409 static short lineno;
    410 static int is_f0_split;
    411 static int nfields;
    412 static var *Fields;
    413 static tsplitter fsplitter, rsplitter;
    414 static nvblock *cb;
    415 static char *pos;
    416 static char *buf;
    417 static int icase;
    418 static int exiting;
    419 
    420 static struct {
    421     uint32_t tclass;
    422     uint32_t info;
    423     char *string;
    424     double number;
    425     short lineno;
    426     int rollback;
    427 } t;
     391#define FIRST_PRIME 61
     392static const uint16_t PRIMES[] ALIGN2 = { 251, 1021, 4093, 16381, 65521 };
     393
     394
     395/* Globals. Split in two parts so that first one is addressed
     396 * with (mostly short) negative offsets */
     397struct globals {
     398    chain beginseq, mainseq, endseq, *seq;
     399    node *break_ptr, *continue_ptr;
     400    rstream *iF;
     401    xhash *vhash, *ahash, *fdhash, *fnhash;
     402    const char *g_progname;
     403    int g_lineno;
     404    int nfields;
     405    int maxfields; /* used in fsrealloc() only */
     406    var *Fields;
     407    nvblock *g_cb;
     408    char *g_pos;
     409    char *g_buf;
     410    smallint icase;
     411    smallint exiting;
     412    smallint nextrec;
     413    smallint nextfile;
     414    smallint is_f0_split;
     415};
     416struct globals2 {
     417    uint32_t t_info; /* often used */
     418    uint32_t t_tclass;
     419    char *t_string;
     420    int t_lineno;
     421    int t_rollback;
     422
     423    var *intvar[NUM_INTERNAL_VARS]; /* often used */
     424
     425    /* former statics from various functions */
     426    char *split_f0__fstrings;
     427
     428    uint32_t next_token__save_tclass;
     429    uint32_t next_token__save_info;
     430    uint32_t next_token__ltclass;
     431    smallint next_token__concat_inserted;
     432
     433    smallint next_input_file__files_happen;
     434    rstream next_input_file__rsm;
     435
     436    var *evaluate__fnargs;
     437    unsigned evaluate__seed;
     438    regex_t evaluate__sreg;
     439
     440    var ptest__v;
     441
     442    tsplitter exec_builtin__tspl;
     443
     444    /* biggest and least used members go last */
     445    double t_double;
     446    tsplitter fsplitter, rsplitter;
     447};
     448#define G1 (ptr_to_globals[-1])
     449#define G (*(struct globals2 *const)ptr_to_globals)
     450/* For debug. nm --size-sort awk.o | grep -vi ' [tr] ' */
     451/* char G1size[sizeof(G1)]; - 0x6c */
     452/* char Gsize[sizeof(G)]; - 0x1cc */
     453/* Trying to keep most of members accessible with short offsets: */
     454/* char Gofs_seed[offsetof(struct globals2, evaluate__seed)]; - 0x90 */
     455#define beginseq     (G1.beginseq    )
     456#define mainseq      (G1.mainseq     )
     457#define endseq       (G1.endseq      )
     458#define seq          (G1.seq         )
     459#define break_ptr    (G1.break_ptr   )
     460#define continue_ptr (G1.continue_ptr)
     461#define iF           (G1.iF          )
     462#define vhash        (G1.vhash       )
     463#define ahash        (G1.ahash       )
     464#define fdhash       (G1.fdhash      )
     465#define fnhash       (G1.fnhash      )
     466#define g_progname   (G1.g_progname  )
     467#define g_lineno     (G1.g_lineno    )
     468#define nfields      (G1.nfields     )
     469#define maxfields    (G1.maxfields   )
     470#define Fields       (G1.Fields      )
     471#define g_cb         (G1.g_cb        )
     472#define g_pos        (G1.g_pos       )
     473#define g_buf        (G1.g_buf       )
     474#define icase        (G1.icase       )
     475#define exiting      (G1.exiting     )
     476#define nextrec      (G1.nextrec     )
     477#define nextfile     (G1.nextfile    )
     478#define is_f0_split  (G1.is_f0_split )
     479#define t_info       (G.t_info      )
     480#define t_tclass     (G.t_tclass    )
     481#define t_string     (G.t_string    )
     482#define t_double     (G.t_double    )
     483#define t_lineno     (G.t_lineno    )
     484#define t_rollback   (G.t_rollback  )
     485#define intvar       (G.intvar      )
     486#define fsplitter    (G.fsplitter   )
     487#define rsplitter    (G.rsplitter   )
     488#define INIT_G() do { \
     489    PTR_TO_GLOBALS = xzalloc(sizeof(G1) + sizeof(G)) + sizeof(G1); \
     490    G.next_token__ltclass = TC_OPTERM; \
     491    G.evaluate__seed = 1; \
     492} while (0)
     493
    428494
    429495/* function prototypes */
     
    438504/* ---- error handling ---- */
    439505
    440 static const char EMSG_INTERNAL_ERROR[] = "Internal error";
    441 static const char EMSG_UNEXP_EOS[] = "Unexpected end of string";
    442 static const char EMSG_UNEXP_TOKEN[] = "Unexpected token";
    443 static const char EMSG_DIV_BY_ZERO[] = "Division by zero";
    444 static const char EMSG_INV_FMT[] = "Invalid format specifier";
    445 static const char EMSG_TOO_FEW_ARGS[] = "Too few arguments for builtin";
    446 static const char EMSG_NOT_ARRAY[] = "Not an array";
    447 static const char EMSG_POSSIBLE_ERROR[] = "Possible syntax error";
    448 static const char EMSG_UNDEF_FUNC[] = "Call to undefined function";
    449 #ifndef CONFIG_FEATURE_AWK_MATH
    450 static const char EMSG_NO_MATH[] = "Math support is not compiled in";
     506static const char EMSG_INTERNAL_ERROR[] ALIGN1 = "Internal error";
     507static const char EMSG_UNEXP_EOS[] ALIGN1 = "Unexpected end of string";
     508static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token";
     509static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero";
     510static const char EMSG_INV_FMT[] ALIGN1 = "Invalid format specifier";
     511static const char EMSG_TOO_FEW_ARGS[] ALIGN1 = "Too few arguments for builtin";
     512static const char EMSG_NOT_ARRAY[] ALIGN1 = "Not an array";
     513static const char EMSG_POSSIBLE_ERROR[] ALIGN1 = "Possible syntax error";
     514static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function";
     515#if !ENABLE_FEATURE_AWK_MATH
     516static const char EMSG_NO_MATH[] ALIGN1 = "Math support is not compiled in";
    451517#endif
    452518
    453 static void syntax_error(const char * const message) ATTRIBUTE_NORETURN;
    454 static void syntax_error(const char * const message)
    455 {
    456     bb_error_msg_and_die("%s:%i: %s", programname, lineno, message);
    457 }
    458 
    459 #define runtime_error(x) syntax_error(x)
    460 
     519static void zero_out_var(var * vp)
     520{
     521    memset(vp, 0, sizeof(*vp));
     522}
     523
     524static void syntax_error(const char *const message) ATTRIBUTE_NORETURN;
     525static void syntax_error(const char *const message)
     526{
     527    bb_error_msg_and_die("%s:%i: %s", g_progname, g_lineno, message);
     528}
    461529
    462530/* ---- hash stuff ---- */
    463531
    464 static unsigned int hashidx(const char *name)
    465 {
    466     register unsigned int idx=0;
    467 
    468     while (*name)  idx = *name++ + (idx << 6) - idx;
     532static unsigned hashidx(const char *name)
     533{
     534    unsigned idx = 0;
     535
     536    while (*name) idx = *name++ + (idx << 6) - idx;
    469537    return idx;
    470538}
     
    475543    xhash *newhash;
    476544
    477     newhash = (xhash *)xzalloc(sizeof(xhash));
     545    newhash = xzalloc(sizeof(xhash));
    478546    newhash->csize = FIRST_PRIME;
    479     newhash->items = (hash_item **)xzalloc(newhash->csize * sizeof(hash_item *));
     547    newhash->items = xzalloc(newhash->csize * sizeof(hash_item *));
    480548
    481549    return newhash;
     
    499567static void hash_rebuild(xhash *hash)
    500568{
    501     unsigned int newsize, i, idx;
     569    unsigned newsize, i, idx;
    502570    hash_item **newitems, *hi, *thi;
    503571
    504     if (hash->nprime == NPRIMES)
     572    if (hash->nprime == ARRAY_SIZE(PRIMES))
    505573        return;
    506574
    507575    newsize = PRIMES[hash->nprime++];
    508     newitems = (hash_item **)xzalloc(newsize * sizeof(hash_item *));
    509 
    510     for (i=0; i<hash->csize; i++) {
     576    newitems = xzalloc(newsize * sizeof(hash_item *));
     577
     578    for (i = 0; i < hash->csize; i++) {
    511579        hi = hash->items[i];
    512580        while (hi) {
     
    528596{
    529597    hash_item *hi;
    530     unsigned int idx;
     598    unsigned idx;
    531599    int l;
    532600
    533601    hi = hash_search(hash, name);
    534     if (! hi) {
     602    if (!hi) {
    535603        if (++hash->nel / hash->csize > 10)
    536604            hash_rebuild(hash);
     
    548616}
    549617
    550 #define findvar(hash, name) (var *) hash_find ( (hash) , (name) )
    551 #define newvar(name) (var *) hash_find ( vhash , (name) )
    552 #define newfile(name) (rstream *) hash_find ( fdhash , (name) )
    553 #define newfunc(name) (func *) hash_find ( fnhash , (name) )
     618#define findvar(hash, name) ((var*)    hash_find((hash), (name)))
     619#define newvar(name)        ((var*)    hash_find(vhash, (name)))
     620#define newfile(name)       ((rstream*)hash_find(fdhash, (name)))
     621#define newfunc(name)       ((func*)   hash_find(fnhash, (name)))
    554622
    555623static void hash_remove(xhash *hash, const char *name)
     
    557625    hash_item *hi, **phi;
    558626
    559     phi = &(hash->items[ hashidx(name) % hash->csize ]);
     627    phi = &(hash->items[hashidx(name) % hash->csize]);
    560628    while (*phi) {
    561629        hi = *phi;
     
    575643static void skip_spaces(char **s)
    576644{
    577     register char *p = *s;
    578 
    579     while(*p == ' ' || *p == '\t' ||
    580             (*p == '\\' && *(p+1) == '\n' && (++p, ++t.lineno))) {
     645    char *p = *s;
     646
     647    while (1) {
     648        if (*p == '\\' && p[1] == '\n') {
     649            p++;
     650            t_lineno++;
     651        } else if (*p != ' ' && *p != '\t') {
     652            break;
     653        }
    581654        p++;
    582655    }
     
    586659static char *nextword(char **s)
    587660{
    588     register char *p = *s;
    589 
    590     while (*(*s)++) ;
     661    char *p = *s;
     662
     663    while (*(*s)++) /* */;
    591664
    592665    return p;
     
    595668static char nextchar(char **s)
    596669{
    597     register char c, *pps;
     670    char c, *pps;
    598671
    599672    c = *((*s)++);
     
    604677}
    605678
    606 static inline int isalnum_(int c)
     679static int ALWAYS_INLINE isalnum_(int c)
    607680{
    608681    return (isalnum(c) || c == '_');
     
    611684static FILE *afopen(const char *path, const char *mode)
    612685{
    613     return (*path == '-' && *(path+1) == '\0') ? stdin : bb_xfopen(path, mode);
     686    return (*path == '-' && *(path+1) == '\0') ? stdin : xfopen(path, mode);
    614687}
    615688
     
    623696        a = a->x.parent;
    624697
    625     if (! (a->type & VF_ARRAY)) {
     698    if (!(a->type & VF_ARRAY)) {
    626699        a->type |= VF_ARRAY;
    627700        a->x.array = hash_init();
     
    632705static void clear_array(xhash *array)
    633706{
    634     unsigned int i;
     707    unsigned i;
    635708    hash_item *hi, *thi;
    636709
    637     for (i=0; i<array->csize; i++) {
     710    for (i = 0; i < array->csize; i++) {
    638711        hi = array->items[i];
    639712        while (hi) {
     
    666739    v->string = value;
    667740    handle_special(v);
    668 
    669741    return v;
    670742}
     
    673745static var *setvar_s(var *v, const char *value)
    674746{
    675     return setvar_p(v, (value && *value) ? bb_xstrdup(value) : NULL);
     747    return setvar_p(v, (value && *value) ? xstrdup(value) : NULL);
    676748}
    677749
     
    687759static void setari_u(var *a, int idx, const char *s)
    688760{
    689     register var *v;
    690     static char sidx[12];
     761    char sidx[sizeof(int)*3 + 1];
     762    var *v;
    691763
    692764    sprintf(sidx, "%d", idx);
     
    705777}
    706778
    707 static char *getvar_s(var *v)
     779static const char *getvar_s(var *v)
    708780{
    709781    /* if v is numeric and has no cached string, convert it to string */
    710782    if ((v->type & (VF_NUMBER | VF_CACHED)) == VF_NUMBER) {
    711         fmt_num(buf, MAXVARFMT, getvar_s(V[CONVFMT]), v->number, TRUE);
    712         v->string = bb_xstrdup(buf);
     783        fmt_num(g_buf, MAXVARFMT, getvar_s(intvar[CONVFMT]), v->number, TRUE);
     784        v->string = xstrdup(g_buf);
    713785        v->type |= VF_CACHED;
    714786    }
     
    742814    if (dest != src) {
    743815        clrvar(dest);
    744         dest->type |= (src->type & ~VF_DONTTOUCH);
     816        dest->type |= (src->type & ~(VF_DONTTOUCH | VF_FSTR));
    745817        dest->number = src->number;
    746818        if (src->string)
    747             dest->string = bb_xstrdup(src->string);
     819            dest->string = xstrdup(src->string);
    748820    }
    749821    handle_special(dest);
     
    753825static var *incvar(var *v)
    754826{
    755     return setvar_i(v, getvar_i(v)+1.);
     827    return setvar_i(v, getvar_i(v) + 1.);
    756828}
    757829
     
    768840    if (is_numeric(v))
    769841        return (v->number == 0) ? 0 : 1;
    770     else
    771         return (v->string && *(v->string)) ? 1 : 0;
     842    return (v->string && *(v->string)) ? 1 : 0;
    772843}
    773844
     
    779850    int size;
    780851
    781     while (cb) {
    782         pb = cb;
    783         if ((cb->pos - cb->nv) + n <= cb->size) break;
    784         cb = cb->next;
    785     }
    786 
    787     if (! cb) {
     852    while (g_cb) {
     853        pb = g_cb;
     854        if ((g_cb->pos - g_cb->nv) + n <= g_cb->size) break;
     855        g_cb = g_cb->next;
     856    }
     857
     858    if (!g_cb) {
    788859        size = (n <= MINNVBLOCK) ? MINNVBLOCK : n;
    789         cb = (nvblock *)xmalloc(sizeof(nvblock) + size * sizeof(var));
    790         cb->size = size;
    791         cb->pos = cb->nv;
    792         cb->prev = pb;
    793         cb->next = NULL;
    794         if (pb) pb->next = cb;
    795     }
    796 
    797     v = r = cb->pos;
    798     cb->pos += n;
    799 
    800     while (v < cb->pos) {
     860        g_cb = xmalloc(sizeof(nvblock) + size * sizeof(var));
     861        g_cb->size = size;
     862        g_cb->pos = g_cb->nv;
     863        g_cb->prev = pb;
     864        g_cb->next = NULL;
     865        if (pb) pb->next = g_cb;
     866    }
     867
     868    v = r = g_cb->pos;
     869    g_cb->pos += n;
     870
     871    while (v < g_cb->pos) {
    801872        v->type = 0;
    802873        v->string = NULL;
     
    811882    var *p;
    812883
    813     if (v < cb->nv || v >= cb->pos)
    814         runtime_error(EMSG_INTERNAL_ERROR);
    815 
    816     for (p=v; p<cb->pos; p++) {
    817         if ((p->type & (VF_ARRAY|VF_CHILD)) == VF_ARRAY) {
     884    if (v < g_cb->nv || v >= g_cb->pos)
     885        syntax_error(EMSG_INTERNAL_ERROR);
     886
     887    for (p = v; p < g_cb->pos; p++) {
     888        if ((p->type & (VF_ARRAY | VF_CHILD)) == VF_ARRAY) {
    818889            clear_array(iamarray(p));
    819890            free(p->x.array->items);
     
    826897    }
    827898
    828     cb->pos = v;
    829     while (cb->prev && cb->pos == cb->nv) {
    830         cb = cb->prev;
     899    g_cb->pos = v;
     900    while (g_cb->prev && g_cb->pos == g_cb->nv) {
     901        g_cb = g_cb->prev;
    831902    }
    832903}
     
    834905/* ------- awk program text parsing ------- */
    835906
    836 /* Parse next token pointed by global pos, place results into global t.
     907/* Parse next token pointed by global pos, place results into global ttt.
    837908 * If token isn't expected, give away. Return token class
    838909 */
    839910static uint32_t next_token(uint32_t expected)
    840911{
     912#define concat_inserted (G.next_token__concat_inserted)
     913#define save_tclass     (G.next_token__save_tclass)
     914#define save_info       (G.next_token__save_info)
     915/* Initialized to TC_OPTERM: */
     916#define ltclass         (G.next_token__ltclass)
     917
    841918    char *p, *pp, *s;
    842     char *tl;
     919    const char *tl;
    843920    uint32_t tc;
    844921    const uint32_t *ti;
    845922    int l;
    846     static int concat_inserted;
    847     static uint32_t save_tclass, save_info;
    848     static uint32_t ltclass = TC_OPTERM;
    849 
    850     if (t.rollback) {
    851 
    852         t.rollback = FALSE;
     923
     924    if (t_rollback) {
     925        t_rollback = FALSE;
    853926
    854927    } else if (concat_inserted) {
    855 
    856928        concat_inserted = FALSE;
    857         t.tclass = save_tclass;
    858         t.info = save_info;
     929        t_tclass = save_tclass;
     930        t_info = save_info;
    859931
    860932    } else {
    861 
    862         p = pos;
    863 
    864     readnext:
     933        p = g_pos;
     934 readnext:
    865935        skip_spaces(&p);
    866         lineno = t.lineno;
     936        g_lineno = t_lineno;
    867937        if (*p == '#')
    868             while (*p != '\n' && *p != '\0') p++;
     938            while (*p != '\n' && *p != '\0')
     939                p++;
    869940
    870941        if (*p == '\n')
    871             t.lineno++;
     942            t_lineno++;
    872943
    873944        if (*p == '\0') {
     
    876947        } else if (*p == '\"') {
    877948            /* it's a string */
    878             t.string = s = ++p;
     949            t_string = s = ++p;
    879950            while (*p != '\"') {
    880951                if (*p == '\0' || *p == '\n')
     
    888959        } else if ((expected & TC_REGEXP) && *p == '/') {
    889960            /* it's regexp */
    890             t.string = s = ++p;
     961            t_string = s = ++p;
    891962            while (*p != '/') {
    892963                if (*p == '\0' || *p == '\n')
    893964                    syntax_error(EMSG_UNEXP_EOS);
    894                 if ((*s++ = *p++) == '\\') {
     965                *s = *p++;
     966                if (*s++ == '\\') {
    895967                    pp = p;
    896968                    *(s-1) = bb_process_escape_sequence((const char **)&p);
    897                     if (*pp == '\\') *s++ = '\\';
    898                     if (p == pp) *s++ = *p++;
     969                    if (*pp == '\\')
     970                        *s++ = '\\';
     971                    if (p == pp)
     972                        *s++ = *p++;
    899973                }
    900974            }
     
    905979        } else if (*p == '.' || isdigit(*p)) {
    906980            /* it's a number */
    907             t.number = strtod(p, &p);
     981            t_double = strtod(p, &p);
    908982            if (*p == '.')
    909983                syntax_error(EMSG_UNEXP_TOKEN);
     
    925999                 * then this is what we are looking for
    9261000                 */
    927                 if ((tc & (expected | TC_WORD | TC_NEWLINE)) &&
    928                 *tl == *p && strncmp(p, tl, l) == 0 &&
    929                 !((tc & TC_WORD) && isalnum_(*(p + l)))) {
    930                     t.info = *ti;
     1001                if ((tc & (expected | TC_WORD | TC_NEWLINE))
     1002                 && *tl == *p && strncmp(p, tl, l) == 0
     1003                 && !((tc & TC_WORD) && isalnum_(p[l]))
     1004                ) {
     1005                    t_info = *ti;
    9311006                    p += l;
    9321007                    break;
     
    9361011            }
    9371012
    938             if (! *tl) {
     1013            if (!*tl) {
    9391014                /* it's a name (var/array/function),
    9401015                 * otherwise it's something wrong
    9411016                 */
    942                 if (! isalnum_(*p))
     1017                if (!isalnum_(*p))
    9431018                    syntax_error(EMSG_UNEXP_TOKEN);
    9441019
    945                 t.string = --p;
    946                 while(isalnum_(*(++p))) {
     1020                t_string = --p;
     1021                while (isalnum_(*(++p))) {
    9471022                    *(p-1) = *p;
    9481023                }
     
    9501025                tc = TC_VARIABLE;
    9511026                /* also consume whitespace between functionname and bracket */
    952                 if (! (expected & TC_VARIABLE)) skip_spaces(&p);
     1027                if (!(expected & TC_VARIABLE))
     1028                    skip_spaces(&p);
    9531029                if (*p == '(') {
    9541030                    tc = TC_FUNCTION;
     
    9611037            }
    9621038        }
    963         pos = p;
     1039        g_pos = p;
    9641040
    9651041        /* skipping newlines in some cases */
     
    9681044
    9691045        /* insert concatenation operator when needed */
    970         if ((ltclass&TC_CONCAT1) && (tc&TC_CONCAT2) && (expected&TC_BINOP)) {
     1046        if ((ltclass & TC_CONCAT1) && (tc & TC_CONCAT2) && (expected & TC_BINOP)) {
    9711047            concat_inserted = TRUE;
    9721048            save_tclass = tc;
    973             save_info = t.info;
     1049            save_info = t_info;
    9741050            tc = TC_BINOP;
    975             t.info = OC_CONCAT | SS | P(35);
    976         }
    977 
    978         t.tclass = tc;
    979     }
    980     ltclass = t.tclass;
     1051            t_info = OC_CONCAT | SS | P(35);
     1052        }
     1053
     1054        t_tclass = tc;
     1055    }
     1056    ltclass = t_tclass;
    9811057
    9821058    /* Are we ready for this? */
    983     if (! (ltclass & expected))
     1059    if (!(ltclass & expected))
    9841060        syntax_error((ltclass & (TC_NEWLINE | TC_EOF)) ?
    985                                 EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN);
     1061                EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN);
    9861062
    9871063    return ltclass;
    988 }
    989 
    990 static void rollback_token(void) { t.rollback = TRUE; }
     1064#undef concat_inserted
     1065#undef save_tclass
     1066#undef save_info
     1067#undef ltclass
     1068}
     1069
     1070static void rollback_token(void)
     1071{
     1072    t_rollback = TRUE;
     1073}
    9911074
    9921075static node *new_node(uint32_t info)
    9931076{
    994     register node *n;
    995 
    996     n = (node *)xzalloc(sizeof(node));
     1077    node *n;
     1078
     1079    n = xzalloc(sizeof(node));
    9971080    n->info = info;
    998     n->lineno = lineno;
     1081    n->lineno = g_lineno;
    9991082    return n;
    10001083}
    10011084
    1002 static node *mk_re_node(char *s, node *n, regex_t *re)
     1085static node *mk_re_node(const char *s, node *n, regex_t *re)
    10031086{
    10041087    n->info = OC_REGEXP;
     
    10061089    n->r.ire = re + 1;
    10071090    xregcomp(re, s, REG_EXTENDED);
    1008     xregcomp(re+1, s, REG_EXTENDED | REG_ICASE);
     1091    xregcomp(re + 1, s, REG_EXTENDED | REG_ICASE);
    10091092
    10101093    return n;
     
    10311114    xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp;
    10321115
    1033     while (! ((tc = next_token(xtc)) & iexp)) {
    1034         if (glptr && (t.info == (OC_COMPARE|VV|P(39)|2))) {
     1116    while (!((tc = next_token(xtc)) & iexp)) {
     1117        if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) {
    10351118            /* input redirection (<) attached to glptr node */
    1036             cn = glptr->l.n = new_node(OC_CONCAT|SS|P(37));
     1119            cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37));
    10371120            cn->a.n = glptr;
    10381121            xtc = TC_OPERAND | TC_UOPPRE;
     
    10431126             * previous operators with higher priority */
    10441127            vn = cn;
    1045             while ( ((t.info & PRIMASK) > (vn->a.n->info & PRIMASK2)) ||
    1046               ((t.info == vn->info) && ((t.info & OPCLSMASK) == OC_COLON)) )
     1128            while ( ((t_info & PRIMASK) > (vn->a.n->info & PRIMASK2))
     1129             || ((t_info == vn->info) && ((t_info & OPCLSMASK) == OC_COLON)) )
    10471130                vn = vn->a.n;
    1048             if ((t.info & OPCLSMASK) == OC_TERNARY)
    1049                 t.info += P(6);
    1050             cn = vn->a.n->r.n = new_node(t.info);
     1131            if ((t_info & OPCLSMASK) == OC_TERNARY)
     1132                t_info += P(6);
     1133            cn = vn->a.n->r.n = new_node(t_info);
    10511134            cn->a.n = vn->a.n;
    10521135            if (tc & TC_BINOP) {
    10531136                cn->l.n = vn;
    10541137                xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP;
    1055                 if ((t.info & OPCLSMASK) == OC_PGETLINE) {
     1138                if ((t_info & OPCLSMASK) == OC_PGETLINE) {
    10561139                    /* it's a pipe */
    10571140                    next_token(TC_GETLINE);
     
    10701153             * to last node */
    10711154            vn = cn;
    1072             cn = vn->r.n = new_node(t.info);
     1155            cn = vn->r.n = new_node(t_info);
    10731156            cn->a.n = vn;
    10741157            xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP;
     
    10781161                 * only simple tclasses should be used! */
    10791162                switch (tc) {
    1080                   case TC_VARIABLE:
    1081                   case TC_ARRAY:
     1163                case TC_VARIABLE:
     1164                case TC_ARRAY:
    10821165                    cn->info = OC_VAR;
    1083                     if ((v = hash_search(ahash, t.string)) != NULL) {
     1166                    v = hash_search(ahash, t_string);
     1167                    if (v != NULL) {
    10841168                        cn->info = OC_FNARG;
    10851169                        cn->l.i = v->x.aidx;
    10861170                    } else {
    1087                         cn->l.v = newvar(t.string);
     1171                        cn->l.v = newvar(t_string);
    10881172                    }
    10891173                    if (tc & TC_ARRAY) {
     
    10931177                    break;
    10941178
    1095                   case TC_NUMBER:
    1096                   case TC_STRING:
     1179                case TC_NUMBER:
     1180                case TC_STRING:
    10971181                    cn->info = OC_VAR;
    10981182                    v = cn->l.v = xzalloc(sizeof(var));
    10991183                    if (tc & TC_NUMBER)
    1100                         setvar_i(v, t.number);
     1184                        setvar_i(v, t_double);
    11011185                    else
    1102                         setvar_s(v, t.string);
     1186                        setvar_s(v, t_string);
    11031187                    break;
    11041188
    1105                   case TC_REGEXP:
    1106                     mk_re_node(t.string, cn,
    1107                                     (regex_t *)xzalloc(sizeof(regex_t)*2));
     1189                case TC_REGEXP:
     1190                    mk_re_node(t_string, cn, xzalloc(sizeof(regex_t)*2));
    11081191                    break;
    11091192
    1110                   case TC_FUNCTION:
     1193                case TC_FUNCTION:
    11111194                    cn->info = OC_FUNC;
    1112                     cn->r.f = newfunc(t.string);
     1195                    cn->r.f = newfunc(t_string);
    11131196                    cn->l.n = condition();
    11141197                    break;
    11151198
    1116                   case TC_SEQSTART:
     1199                case TC_SEQSTART:
    11171200                    cn = vn->r.n = parse_expr(TC_SEQTERM);
    11181201                    cn->a.n = vn;
    11191202                    break;
    11201203
    1121                   case TC_GETLINE:
     1204                case TC_GETLINE:
    11221205                    glptr = cn;
    11231206                    xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
    11241207                    break;
    11251208
    1126                   case TC_BUILTIN:
     1209                case TC_BUILTIN:
    11271210                    cn->l.n = condition();
    11281211                    break;
     
    11371220static node *chain_node(uint32_t info)
    11381221{
    1139     register node *n;
    1140 
    1141     if (! seq->first)
     1222    node *n;
     1223
     1224    if (!seq->first)
    11421225        seq->first = seq->last = new_node(0);
    11431226
    1144     if (seq->programname != programname) {
    1145         seq->programname = programname;
     1227    if (seq->programname != g_progname) {
     1228        seq->programname = g_progname;
    11461229        n = chain_node(OC_NEWSOURCE);
    1147         n->l.s = bb_xstrdup(programname);
     1230        n->l.s = xstrdup(g_progname);
    11481231    }
    11491232
     
    11611244    n = chain_node(info);
    11621245    n->l.n = parse_expr(TC_OPTERM | TC_GRPTERM);
    1163     if (t.tclass & TC_GRPTERM)
     1246    if (t_tclass & TC_GRPTERM)
    11641247        rollback_token();
    11651248}
     
    11991282
    12001283    if (c & TC_GRPSTART) {
    1201         while(next_token(TC_GRPSEQ | TC_GRPTERM) != TC_GRPTERM) {
    1202             if (t.tclass & TC_NEWLINE) continue;
     1284        while (next_token(TC_GRPSEQ | TC_GRPTERM) != TC_GRPTERM) {
     1285            if (t_tclass & TC_NEWLINE) continue;
    12031286            rollback_token();
    12041287            chain_group();
     
    12081291        chain_expr(OC_EXEC | Vx);
    12091292    } else {                        /* TC_STATEMNT */
    1210         switch (t.info & OPCLSMASK) {
    1211             case ST_IF:
    1212                 n = chain_node(OC_BR | Vx);
    1213                 n->l.n = condition();
     1293        switch (t_info & OPCLSMASK) {
     1294        case ST_IF:
     1295            n = chain_node(OC_BR | Vx);
     1296            n->l.n = condition();
     1297            chain_group();
     1298            n2 = chain_node(OC_EXEC);
     1299            n->r.n = seq->last;
     1300            if (next_token(TC_GRPSEQ | TC_GRPTERM | TC_ELSE) == TC_ELSE) {
    12141301                chain_group();
    1215                 n2 = chain_node(OC_EXEC);
    1216                 n->r.n = seq->last;
    1217                 if (next_token(TC_GRPSEQ | TC_GRPTERM | TC_ELSE)==TC_ELSE) {
    1218                     chain_group();
    1219                     n2->a.n = seq->last;
    1220                 } else {
    1221                     rollback_token();
    1222                 }
    1223                 break;
    1224 
    1225             case ST_WHILE:
    1226                 n2 = condition();
     1302                n2->a.n = seq->last;
     1303            } else {
     1304                rollback_token();
     1305            }
     1306            break;
     1307
     1308        case ST_WHILE:
     1309            n2 = condition();
     1310            n = chain_loop(NULL);
     1311            n->l.n = n2;
     1312            break;
     1313
     1314        case ST_DO:
     1315            n2 = chain_node(OC_EXEC);
     1316            n = chain_loop(NULL);
     1317            n2->a.n = n->a.n;
     1318            next_token(TC_WHILE);
     1319            n->l.n = condition();
     1320            break;
     1321
     1322        case ST_FOR:
     1323            next_token(TC_SEQSTART);
     1324            n2 = parse_expr(TC_SEMICOL | TC_SEQTERM);
     1325            if (t_tclass & TC_SEQTERM) {    /* for-in */
     1326                if ((n2->info & OPCLSMASK) != OC_IN)
     1327                    syntax_error(EMSG_UNEXP_TOKEN);
     1328                n = chain_node(OC_WALKINIT | VV);
     1329                n->l.n = n2->l.n;
     1330                n->r.n = n2->r.n;
    12271331                n = chain_loop(NULL);
     1332                n->info = OC_WALKNEXT | Vx;
     1333                n->l.n = n2->l.n;
     1334            } else {            /* for (;;) */
     1335                n = chain_node(OC_EXEC | Vx);
    12281336                n->l.n = n2;
    1229                 break;
    1230 
    1231             case ST_DO:
    1232                 n2 = chain_node(OC_EXEC);
    1233                 n = chain_loop(NULL);
    1234                 n2->a.n = n->a.n;
    1235                 next_token(TC_WHILE);
    1236                 n->l.n = condition();
    1237                 break;
    1238 
    1239             case ST_FOR:
    1240                 next_token(TC_SEQSTART);
    1241                 n2 = parse_expr(TC_SEMICOL | TC_SEQTERM);
    1242                 if (t.tclass & TC_SEQTERM) {                /* for-in */
    1243                     if ((n2->info & OPCLSMASK) != OC_IN)
    1244                         syntax_error(EMSG_UNEXP_TOKEN);
    1245                     n = chain_node(OC_WALKINIT | VV);
    1246                     n->l.n = n2->l.n;
    1247                     n->r.n = n2->r.n;
    1248                     n = chain_loop(NULL);
    1249                     n->info = OC_WALKNEXT | Vx;
    1250                     n->l.n = n2->l.n;
    1251                 } else {                                    /* for(;;) */
    1252                     n = chain_node(OC_EXEC | Vx);
    1253                     n->l.n = n2;
    1254                     n2 = parse_expr(TC_SEMICOL);
    1255                     n3 = parse_expr(TC_SEQTERM);
    1256                     n = chain_loop(n3);
    1257                     n->l.n = n2;
    1258                     if (! n2)
    1259                         n->info = OC_EXEC;
    1260                 }
    1261                 break;
    1262 
    1263             case OC_PRINT:
    1264             case OC_PRINTF:
    1265                 n = chain_node(t.info);
    1266                 n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM);
    1267                 if (t.tclass & TC_OUTRDR) {
    1268                     n->info |= t.info;
    1269                     n->r.n = parse_expr(TC_OPTERM | TC_GRPTERM);
    1270                 }
    1271                 if (t.tclass & TC_GRPTERM)
    1272                     rollback_token();
    1273                 break;
    1274 
    1275             case OC_BREAK:
    1276                 n = chain_node(OC_EXEC);
    1277                 n->a.n = break_ptr;
    1278                 break;
    1279 
    1280             case OC_CONTINUE:
    1281                 n = chain_node(OC_EXEC);
    1282                 n->a.n = continue_ptr;
    1283                 break;
    1284 
    1285             /* delete, next, nextfile, return, exit */
    1286             default:
    1287                 chain_expr(t.info);
    1288 
     1337                n2 = parse_expr(TC_SEMICOL);
     1338                n3 = parse_expr(TC_SEQTERM);
     1339                n = chain_loop(n3);
     1340                n->l.n = n2;
     1341                if (!n2)
     1342                    n->info = OC_EXEC;
     1343            }
     1344            break;
     1345
     1346        case OC_PRINT:
     1347        case OC_PRINTF:
     1348            n = chain_node(t_info);
     1349            n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM);
     1350            if (t_tclass & TC_OUTRDR) {
     1351                n->info |= t_info;
     1352                n->r.n = parse_expr(TC_OPTERM | TC_GRPTERM);
     1353            }
     1354            if (t_tclass & TC_GRPTERM)
     1355                rollback_token();
     1356            break;
     1357
     1358        case OC_BREAK:
     1359            n = chain_node(OC_EXEC);
     1360            n->a.n = break_ptr;
     1361            break;
     1362
     1363        case OC_CONTINUE:
     1364            n = chain_node(OC_EXEC);
     1365            n->a.n = continue_ptr;
     1366            break;
     1367
     1368        /* delete, next, nextfile, return, exit */
     1369        default:
     1370            chain_expr(t_info);
    12891371        }
    12901372    }
     
    12981380    var *v;
    12991381
    1300     pos = p;
    1301     t.lineno = 1;
    1302     while((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART |
    1303                 TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) {
     1382    g_pos = p;
     1383    t_lineno = 1;
     1384    while ((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART |
     1385            TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) {
    13041386
    13051387        if (tclass & TC_OPTERM)
     
    13171399        } else if (tclass & TC_FUNCDECL) {
    13181400            next_token(TC_FUNCTION);
    1319             pos++;
    1320             f = newfunc(t.string);
     1401            g_pos++;
     1402            f = newfunc(t_string);
    13211403            f->body.first = NULL;
    13221404            f->nargs = 0;
    1323             while(next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
    1324                 v = findvar(ahash, t.string);
     1405            while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
     1406                v = findvar(ahash, t_string);
    13251407                v->x.aidx = (f->nargs)++;
    13261408
     
    13361418            cn = chain_node(OC_TEST);
    13371419            cn->l.n = parse_expr(TC_OPTERM | TC_EOF | TC_GRPSTART);
    1338             if (t.tclass & TC_GRPSTART) {
     1420            if (t_tclass & TC_GRPSTART) {
    13391421                rollback_token();
    13401422                chain_group();
     
    13541436/* -------- program execution part -------- */
    13551437
    1356 static node *mk_splitter(char *s, tsplitter *spl)
    1357 {
    1358     register regex_t *re, *ire;
     1438static node *mk_splitter(const char *s, tsplitter *spl)
     1439{
     1440    regex_t *re, *ire;
    13591441    node *n;
    13601442
     
    13621444    ire = &spl->re[1];
    13631445    n = &spl->n;
    1364     if ((n->info && OPCLSMASK) == OC_REGEXP) {
     1446    if ((n->info & OPCLSMASK) == OC_REGEXP) {
    13651447        regfree(re);
    1366         regfree(ire);
     1448        regfree(ire); // TODO: nuke ire, use re+1?
    13671449    }
    13681450    if (strlen(s) > 1) {
     
    13821464{
    13831465    var *v;
    1384     char *s;
     1466    const char *s;
    13851467
    13861468    if ((op->info & OPCLSMASK) == OC_REGEXP) {
    13871469        return icase ? op->r.ire : op->l.re;
    1388     } else {
    1389         v = nvalloc(1);
    1390         s = getvar_s(evaluate(op, v));
    1391         xregcomp(preg, s, icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED);
    1392         nvfree(v);
    1393         return preg;
    1394     }
     1470    }
     1471    v = nvalloc(1);
     1472    s = getvar_s(evaluate(op, v));
     1473    xregcomp(preg, s, icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED);
     1474    nvfree(v);
     1475    return preg;
    13951476}
    13961477
     
    13981479static void qrealloc(char **b, int n, int *size)
    13991480{
    1400     if (! *b || n >= *size)
     1481    if (!*b || n >= *size)
    14011482        *b = xrealloc(*b, *size = n + (n>>1) + 80);
    14021483}
     
    14051486static void fsrealloc(int size)
    14061487{
    1407     static int maxfields = 0;
    14081488    int i;
    14091489
     
    14111491        i = maxfields;
    14121492        maxfields = size + 16;
    1413         Fields = (var *)xrealloc(Fields, maxfields * sizeof(var));
    1414         for (; i<maxfields; i++) {
     1493        Fields = xrealloc(Fields, maxfields * sizeof(var));
     1494        for (; i < maxfields; i++) {
    14151495            Fields[i].type = VF_SPECIAL;
    14161496            Fields[i].string = NULL;
     
    14191499
    14201500    if (size < nfields) {
    1421         for (i=size; i<nfields; i++) {
    1422             clrvar(Fields+i);
     1501        for (i = size; i < nfields; i++) {
     1502            clrvar(Fields + i);
    14231503        }
    14241504    }
     
    14261506}
    14271507
    1428 static int awk_split(char *s, node *spl, char **slist)
    1429 {
    1430     int l, n=0;
     1508static int awk_split(const char *s, node *spl, char **slist)
     1509{
     1510    int l, n = 0;
    14311511    char c[4];
    14321512    char *s1;
    1433     regmatch_t pmatch[2];
     1513    regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough...
    14341514
    14351515    /* in worst case, each char would be a separate field */
    1436     *slist = s1 = bb_xstrndup(s, strlen(s) * 2 + 3);
     1516    *slist = s1 = xzalloc(strlen(s) * 2 + 3);
     1517    strcpy(s1, s);
    14371518
    14381519    c[0] = c[1] = (char)spl->info;
    14391520    c[2] = c[3] = '\0';
    1440     if (*getvar_s(V[RS]) == '\0') c[2] = '\n';
    1441 
    1442     if ((spl->info & OPCLSMASK) == OC_REGEXP) {     /* regex split */
    1443         while (*s) {
    1444             l = strcspn(s, c+2);
    1445             if (regexec(icase ? spl->r.ire : spl->l.re, s, 1, pmatch, 0) == 0 &&
    1446             pmatch[0].rm_so <= l) {
     1521    if (*getvar_s(intvar[RS]) == '\0')
     1522        c[2] = '\n';
     1523
     1524    if ((spl->info & OPCLSMASK) == OC_REGEXP) {  /* regex split */
     1525        if (!*s)
     1526            return n; /* "": zero fields */
     1527        n++; /* at least one field will be there */
     1528        do {
     1529            l = strcspn(s, c+2); /* len till next NUL or \n */
     1530            if (regexec(icase ? spl->r.ire : spl->l.re, s, 1, pmatch, 0) == 0
     1531             && pmatch[0].rm_so <= l
     1532            ) {
    14471533                l = pmatch[0].rm_so;
    1448                 if (pmatch[0].rm_eo == 0) { l++; pmatch[0].rm_eo++; }
     1534                if (pmatch[0].rm_eo == 0) {
     1535                    l++;
     1536                    pmatch[0].rm_eo++;
     1537                }
     1538                n++; /* we saw yet another delimiter */
    14491539            } else {
    14501540                pmatch[0].rm_eo = l;
    1451                 if (*(s+l)) pmatch[0].rm_eo++;
    1452             }
    1453 
     1541                if (s[l]) pmatch[0].rm_eo++;
     1542            }
    14541543            memcpy(s1, s, l);
    1455             *(s1+l) = '\0';
     1544            s1[l] = '\0';
    14561545            nextword(&s1);
    14571546            s += pmatch[0].rm_eo;
     1547        } while (*s);
     1548        return n;
     1549    }
     1550    if (c[0] == '\0') {  /* null split */
     1551        while (*s) {
     1552            *s1++ = *s++;
     1553            *s1++ = '\0';
    14581554            n++;
    14591555        }
    1460     } else if (c[0] == '\0') {      /* null split */
    1461         while(*s) {
    1462             *(s1++) = *(s++);
    1463             *(s1++) = '\0';
    1464             n++;
    1465         }
    1466     } else if (c[0] != ' ') {       /* single-character split */
     1556        return n;
     1557    }
     1558    if (c[0] != ' ') {  /* single-character split */
    14671559        if (icase) {
    14681560            c[0] = toupper(c[0]);
     
    14711563        if (*s1) n++;
    14721564        while ((s1 = strpbrk(s1, c))) {
    1473             *(s1++) = '\0';
     1565            *s1++ = '\0';
    14741566            n++;
    14751567        }
    1476     } else {                /* space split */
    1477         while (*s) {
    1478             while (isspace(*s)) s++;
    1479             if (! *s) break;
    1480             n++;
    1481             while (*s && !isspace(*s))
    1482                 *(s1++) = *(s++);
    1483             *(s1++) = '\0';
    1484         }
     1568        return n;
     1569    }
     1570    /* space split */
     1571    while (*s) {
     1572        s = skip_whitespace(s);
     1573        if (!*s) break;
     1574        n++;
     1575        while (*s && !isspace(*s))
     1576            *s1++ = *s++;
     1577        *s1++ = '\0';
    14851578    }
    14861579    return n;
     
    14891582static void split_f0(void)
    14901583{
    1491     static char *fstrings = NULL;
     1584/* static char *fstrings; */
     1585#define fstrings (G.split_f0__fstrings)
     1586
    14921587    int i, n;
    14931588    char *s;
     
    14991594    free(fstrings);
    15001595    fsrealloc(0);
    1501     n = awk_split(getvar_s(V[F0]), &fsplitter.n, &fstrings);
     1596    n = awk_split(getvar_s(intvar[F0]), &fsplitter.n, &fstrings);
    15021597    fsrealloc(n);
    15031598    s = fstrings;
    1504     for (i=0; i<n; i++) {
     1599    for (i = 0; i < n; i++) {
    15051600        Fields[i].string = nextword(&s);
    15061601        Fields[i].type |= (VF_FSTR | VF_USER | VF_DIRTY);
     
    15081603
    15091604    /* set NF manually to avoid side effects */
    1510     clrvar(V[NF]);
    1511     V[NF]->type = VF_NUMBER | VF_SPECIAL;
    1512     V[NF]->number = nfields;
     1605    clrvar(intvar[NF]);
     1606    intvar[NF]->type = VF_NUMBER | VF_SPECIAL;
     1607    intvar[NF]->number = nfields;
     1608#undef fstrings
    15131609}
    15141610
     
    15171613{
    15181614    int n;
    1519     char *b, *sep, *s;
     1615    char *b;
     1616    const char *sep, *s;
    15201617    int sl, l, len, i, bsize;
    15211618
    1522     if (! (v->type & VF_SPECIAL))
     1619    if (!(v->type & VF_SPECIAL))
    15231620        return;
    15241621
    1525     if (v == V[NF]) {
     1622    if (v == intvar[NF]) {
    15261623        n = (int)getvar_i(v);
    15271624        fsrealloc(n);
    15281625
    15291626        /* recalculate $0 */
    1530         sep = getvar_s(V[OFS]);
     1627        sep = getvar_s(intvar[OFS]);
    15311628        sl = strlen(sep);
    15321629        b = NULL;
    15331630        len = 0;
    1534         for (i=0; i<n; i++) {
     1631        for (i = 0; i < n; i++) {
    15351632            s = getvar_s(&Fields[i]);
    15361633            l = strlen(s);
     
    15431640            len += l;
    15441641        }
    1545         if (b) b[len] = '\0';
    1546         setvar_p(V[F0], b);
     1642        if (b)
     1643            b[len] = '\0';
     1644        setvar_p(intvar[F0], b);
    15471645        is_f0_split = TRUE;
    15481646
    1549     } else if (v == V[F0]) {
     1647    } else if (v == intvar[F0]) {
    15501648        is_f0_split = FALSE;
    15511649
    1552     } else if (v == V[FS]) {
     1650    } else if (v == intvar[FS]) {
    15531651        mk_splitter(getvar_s(v), &fsplitter);
    15541652
    1555     } else if (v == V[RS]) {
     1653    } else if (v == intvar[RS]) {
    15561654        mk_splitter(getvar_s(v), &rsplitter);
    15571655
    1558     } else if (v == V[IGNORECASE]) {
     1656    } else if (v == intvar[IGNORECASE]) {
    15591657        icase = istrue(v);
    15601658
    1561     } else {                        /* $n */
    1562         n = getvar_i(V[NF]);
    1563         setvar_i(V[NF], n > v-Fields ? n : v-Fields+1);
     1659    } else {                /* $n */
     1660        n = getvar_i(intvar[NF]);
     1661        setvar_i(intvar[NF], n > v-Fields ? n : v-Fields+1);
    15641662        /* right here v is invalid. Just to note... */
    15651663    }
     
    15911689
    15921690    v->type |= VF_WALK;
    1593     w = v->x.walker = (char **)xzalloc(2 + 2*sizeof(char *) + array->glen);
    1594     *w = *(w+1) = (char *)(w + 2);
    1595     for (i=0; i<array->csize; i++) {
     1691    w = v->x.walker = xzalloc(2 + 2*sizeof(char *) + array->glen);
     1692    w[0] = w[1] = (char *)(w + 2);
     1693    for (i = 0; i < array->csize; i++) {
    15961694        hi = array->items[i];
    1597         while(hi) {
     1695        while (hi) {
    15981696            strcpy(*w, hi->name);
    15991697            nextword(w);
     
    16081706
    16091707    w = v->x.walker;
    1610     if (*(w+1) == *w)
     1708    if (w[1] == w[0])
    16111709        return FALSE;
    16121710
     
    16181716static int ptest(node *pattern)
    16191717{
    1620     static var v;
    1621     return istrue(evaluate(pattern, &v));
     1718    /* ptest__v is "static": to save stack space? */
     1719    return istrue(evaluate(pattern, &G.ptest__v));
    16221720}
    16231721
     
    16421740    rp = 0;
    16431741
    1644     if (! m) qrealloc(&m, 256, &size);
     1742    if (!m) qrealloc(&m, 256, &size);
    16451743    do {
    16461744        b = m + a;
     
    16501748            if ((rsplitter.n.info & OPCLSMASK) == OC_REGEXP) {
    16511749                if (regexec(icase ? rsplitter.n.r.ire : rsplitter.n.l.re,
    1652                                                 b, 1, pmatch, 0) == 0) {
     1750                            b, 1, pmatch, 0) == 0) {
    16531751                    so = pmatch[0].rm_so;
    16541752                    eo = pmatch[0].rm_eo;
     
    16581756            } else if (c != '\0') {
    16591757                s = strchr(b+pp, c);
    1660                 if (! s) s = memchr(b+pp, '\0', p - pp);
     1758                if (!s) s = memchr(b+pp, '\0', p - pp);
    16611759                if (s) {
    16621760                    so = eo = s-b;
     
    16901788            p = 0;
    16911789            r = 0;
    1692             setvar_i(V[ERRNO], errno);
     1790            setvar_i(intvar[ERRNO], errno);
    16931791        }
    16941792        b[p] = '\0';
     
    17041802        b[so] = c;
    17051803        c = b[eo]; b[eo] = '\0';
    1706         setvar_s(V[RT], b+so);
     1804        setvar_s(intvar[RT], b+so);
    17071805        b[eo] = c;
    17081806    }
     
    17181816static int fmt_num(char *b, int size, const char *format, double n, int int_as_int)
    17191817{
    1720     int r=0;
     1818    int r = 0;
    17211819    char c;
    1722     const char *s=format;
     1820    const char *s = format;
    17231821
    17241822    if (int_as_int && n == (int)n) {
    17251823        r = snprintf(b, size, "%d", (int)n);
    17261824    } else {
    1727         do { c = *s; } while (*s && *++s);
     1825        do { c = *s; } while (c && *++s);
    17281826        if (strchr("diouxX", c)) {
    17291827            r = snprintf(b, size, format, (int)n);
     
    17311829            r = snprintf(b, size, format, n);
    17321830        } else {
    1733             runtime_error(EMSG_INV_FMT);
     1831            syntax_error(EMSG_INV_FMT);
    17341832        }
    17351833    }
     
    17421840{
    17431841    char *b = NULL;
    1744     char *fmt, *s, *s1, *f;
     1842    char *fmt, *s, *f;
     1843    const char *s1;
    17451844    int i, j, incr, bsize;
    17461845    char c, c1;
     
    17481847
    17491848    v = nvalloc(1);
    1750     fmt = f = bb_xstrdup(getvar_s(evaluate(nextarg(&n), v)));
     1849    fmt = f = xstrdup(getvar_s(evaluate(nextarg(&n), v)));
    17511850
    17521851    i = 0;
     
    17551854        while (*f && (*f != '%' || *(++f) == '%'))
    17561855            f++;
    1757         while (*f && !isalpha(*f))
     1856        while (*f && !isalpha(*f)) {
     1857            if (*f == '*')
     1858                syntax_error("%*x formats are not supported");
    17581859            f++;
     1860        }
    17591861
    17601862        incr = (f - s) + MAXVARFMT;
    1761         qrealloc(&b, incr+i, &bsize);
    1762         c = *f; if (c != '\0') f++;
    1763         c1 = *f ; *f = '\0';
     1863        qrealloc(&b, incr + i, &bsize);
     1864        c = *f;
     1865        if (c != '\0') f++;
     1866        c1 = *f;
     1867        *f = '\0';
    17641868        arg = evaluate(nextarg(&n), v);
    17651869
    17661870        j = i;
    17671871        if (c == 'c' || !c) {
    1768             i += sprintf(b+i, s,
    1769                     is_numeric(arg) ? (char)getvar_i(arg) : *getvar_s(arg));
    1770 
     1872            i += sprintf(b+i, s, is_numeric(arg) ?
     1873                    (char)getvar_i(arg) : *getvar_s(arg));
    17711874        } else if (c == 's') {
    1772             s1 = getvar_s(arg);
     1875            s1 = getvar_s(arg);
    17731876            qrealloc(&b, incr+i+strlen(s1), &bsize);
    17741877            i += sprintf(b+i, s, s1);
    1775 
    17761878        } else {
    17771879            i += fmt_num(b+i, incr, s, getvar_i(arg), FALSE);
     
    17811883        /* if there was an error while sprintf, return value is negative */
    17821884        if (i < j) i = j;
    1783 
    1784     }
    1785 
    1786     b = xrealloc(b, i+1);
     1885    }
     1886
     1887    b = xrealloc(b, i + 1);
    17871888    free(fmt);
    17881889    nvfree(v);
     
    17971898 * subexpression matching (\1-\9)
    17981899 */
    1799 static int awk_sub(node *rn, char *repl, int nm, var *src, var *dest, int ex)
     1900static int awk_sub(node *rn, const char *repl, int nm, var *src, var *dest, int ex)
    18001901{
    18011902    char *ds = NULL;
    1802     char *sp, *s;
     1903    const char *s;
     1904    const char *sp;
    18031905    int c, i, j, di, rl, so, eo, nbs, n, dssize;
    18041906    regmatch_t pmatch[10];
     
    18061908
    18071909    re = as_regex(rn, &sreg);
    1808     if (! src) src = V[F0];
    1809     if (! dest) dest = V[F0];
     1910    if (!src) src = intvar[F0];
     1911    if (!dest) dest = intvar[F0];
    18101912
    18111913    i = di = 0;
    18121914    sp = getvar_s(src);
    18131915    rl = strlen(repl);
    1814     while (regexec(re, sp, 10, pmatch, sp==getvar_s(src) ? 0:REG_NOTBOL) == 0) {
     1916    while (regexec(re, sp, 10, pmatch, sp==getvar_s(src) ? 0 : REG_NOTBOL) == 0) {
    18151917        so = pmatch[0].rm_so;
    18161918        eo = pmatch[0].rm_eo;
     
    18521954        if (i == nm) break;
    18531955        if (eo == so) {
    1854             if (! (ds[di++] = *sp++)) break;
     1956            ds[di] = *sp++;
     1957            if (!ds[di++]) break;
    18551958        }
    18561959    }
     
    18651968static var *exec_builtin(node *op, var *res)
    18661969{
     1970#define tspl (G.exec_builtin__tspl)
     1971
    18671972    int (*to_xxx)(int);
    18681973    var *tv;
    18691974    node *an[4];
    1870     var  *av[4];
    1871     char *as[4];
     1975    var *av[4];
     1976    const char *as[4];
    18721977    regmatch_t pmatch[2];
    18731978    regex_t sreg, *re;
    1874     static tsplitter tspl;
    18751979    node *spl;
    18761980    uint32_t isr, info;
     
    18851989
    18861990    av[2] = av[3] = NULL;
    1887     for (i=0 ; i<4 && op ; i++) {
     1991    for (i = 0; i < 4 && op; i++) {
    18881992        an[i] = nextarg(&op);
    18891993        if (isr & 0x09000000) av[i] = evaluate(an[i], &tv[i]);
     
    18941998    nargs = i;
    18951999    if (nargs < (info >> 30))
    1896         runtime_error(EMSG_TOO_FEW_ARGS);
     2000        syntax_error(EMSG_TOO_FEW_ARGS);
    18972001
    18982002    switch (info & OPNMASK) {
    18992003
    1900       case B_a2:
    1901 #ifdef CONFIG_FEATURE_AWK_MATH
     2004    case B_a2:
     2005#if ENABLE_FEATURE_AWK_MATH
    19022006        setvar_i(res, atan2(getvar_i(av[i]), getvar_i(av[1])));
    19032007#else
    1904         runtime_error(EMSG_NO_MATH);
     2008        syntax_error(EMSG_NO_MATH);
    19052009#endif
    19062010        break;
    19072011
    1908       case B_sp:
     2012    case B_sp:
    19092013        if (nargs > 2) {
    19102014            spl = (an[2]->info & OPCLSMASK) == OC_REGEXP ?
     
    19232027        break;
    19242028
    1925       case B_ss:
     2029    case B_ss:
    19262030        l = strlen(as[0]);
    19272031        i = getvar_i(av[1]) - 1;
    1928         if (i>l) i=l; if (i<0) i=0;
     2032        if (i > l) i = l;
     2033        if (i < 0) i = 0;
    19292034        n = (nargs > 2) ? getvar_i(av[2]) : l-i;
    1930         if (n<0) n=0;
     2035        if (n < 0) n = 0;
    19312036        s = xmalloc(n+1);
    19322037        strncpy(s, as[0]+i, n);
     
    19352040        break;
    19362041
    1937       case B_lo:
     2042    case B_an:
     2043        setvar_i(res, (long)getvar_i(av[0]) & (long)getvar_i(av[1]));
     2044        break;
     2045
     2046    case B_co:
     2047        setvar_i(res, ~(long)getvar_i(av[0]));
     2048        break;
     2049
     2050    case B_ls:
     2051        setvar_i(res, (long)getvar_i(av[0]) << (long)getvar_i(av[1]));
     2052        break;
     2053
     2054    case B_or:
     2055        setvar_i(res, (long)getvar_i(av[0]) | (long)getvar_i(av[1]));
     2056        break;
     2057
     2058    case B_rs:
     2059        setvar_i(res, (long)((unsigned long)getvar_i(av[0]) >> (unsigned long)getvar_i(av[1])));
     2060        break;
     2061
     2062    case B_xo:
     2063        setvar_i(res, (long)getvar_i(av[0]) ^ (long)getvar_i(av[1]));
     2064        break;
     2065
     2066    case B_lo:
    19382067        to_xxx = tolower;
    19392068        goto lo_cont;
    19402069
    1941       case B_up:
     2070    case B_up:
    19422071        to_xxx = toupper;
    1943 lo_cont:
    1944         s1 = s = bb_xstrdup(as[0]);
     2072 lo_cont:
     2073        s1 = s = xstrdup(as[0]);
    19452074        while (*s1) {
    19462075            *s1 = (*to_xxx)(*s1);
     
    19502079        break;
    19512080
    1952       case B_ix:
     2081    case B_ix:
    19532082        n = 0;
    19542083        ll = strlen(as[1]);
    19552084        l = strlen(as[0]) - ll;
    19562085        if (ll > 0 && l >= 0) {
    1957             if (! icase) {
     2086            if (!icase) {
    19582087                s = strstr(as[0], as[1]);
    19592088                if (s) n = (s - as[0]) + 1;
     
    19732102        break;
    19742103
    1975       case B_ti:
     2104    case B_ti:
    19762105        if (nargs > 1)
    19772106            tt = getvar_i(av[1]);
    19782107        else
    19792108            time(&tt);
    1980         s = (nargs > 0) ? as[0] : "%a %b %d %H:%M:%S %Z %Y";
    1981         i = strftime(buf, MAXVARFMT, s, localtime(&tt));
    1982         buf[i] = '\0';
    1983         setvar_s(res, buf);
     2109        //s = (nargs > 0) ? as[0] : "%a %b %d %H:%M:%S %Z %Y";
     2110        i = strftime(g_buf, MAXVARFMT,
     2111            ((nargs > 0) ? as[0] : "%a %b %d %H:%M:%S %Z %Y"),
     2112            localtime(&tt));
     2113        g_buf[i] = '\0';
     2114        setvar_s(res, g_buf);
    19842115        break;
    19852116
    1986       case B_ma:
     2117    case B_ma:
    19872118        re = as_regex(an[1], &sreg);
    19882119        n = regexec(re, as[0], 1, pmatch, 0);
     
    20002131        break;
    20012132
    2002       case B_ge:
     2133    case B_ge:
    20032134        awk_sub(an[0], as[1], getvar_i(av[2]), av[3], res, TRUE);
    20042135        break;
    20052136
    2006       case B_gs:
     2137    case B_gs:
    20072138        setvar_i(res, awk_sub(an[0], as[1], 0, av[2], av[2], FALSE));
    20082139        break;
    20092140
    2010       case B_su:
     2141    case B_su:
    20112142        setvar_i(res, awk_sub(an[0], as[1], 1, av[2], av[2], FALSE));
    20122143        break;
     
    20152146    nvfree(tv);
    20162147    return res;
     2148#undef tspl
    20172149}
    20182150
     
    20252157static var *evaluate(node *op, var *res)
    20262158{
    2027     /* This procedure is recursive so we should count every byte */
    2028     static var *fnargs = NULL;
    2029     static unsigned int seed = 1;
    2030     static regex_t sreg;
     2159/* This procedure is recursive so we should count every byte */
     2160#define fnargs (G.evaluate__fnargs)
     2161/* seed is initialized to 1 */
     2162#define seed   (G.evaluate__seed)
     2163#define sreg   (G.evaluate__sreg)
     2164
    20312165    node *op1;
    20322166    var *v1;
    20332167    union {
    20342168        var *v;
    2035         char *s;
     2169        const char *s;
    20362170        double d;
    20372171        int i;
    20382172    } L, R;
    20392173    uint32_t opinfo;
    2040     short opn;
     2174    int opn;
    20412175    union {
    20422176        char *s;
     
    20482182    } X;
    20492183
    2050     if (! op)
     2184    if (!op)
    20512185        return setvar_s(res, NULL);
    20522186
     
    20542188
    20552189    while (op) {
    2056 
    20572190        opinfo = op->info;
    2058         opn = (short)(opinfo & OPNMASK);
    2059         lineno = op->lineno;
     2191        opn = (opinfo & OPNMASK);
     2192        g_lineno = op->lineno;
    20602193
    20612194        /* execute inevitable things */
     
    20692202        switch (XC(opinfo & OPCLSMASK)) {
    20702203
    2071           /* -- iterative node type -- */
    2072 
    2073           /* test pattern */
    2074           case XC( OC_TEST ):
     2204        /* -- iterative node type -- */
     2205
     2206        /* test pattern */
     2207        case XC( OC_TEST ):
    20752208            if ((op1->info & OPCLSMASK) == OC_COMMA) {
    20762209                /* it's range pattern */
     
    20892222            break;
    20902223
    2091           /* just evaluate an expression, also used as unconditional jump */
    2092           case XC( OC_EXEC ):
    2093             break;
    2094 
    2095           /* branch, used in if-else and various loops */
    2096           case XC( OC_BR ):
     2224        /* just evaluate an expression, also used as unconditional jump */
     2225        case XC( OC_EXEC ):
     2226            break;
     2227
     2228        /* branch, used in if-else and various loops */
     2229        case XC( OC_BR ):
    20972230            op = istrue(L.v) ? op->a.n : op->r.n;
    20982231            break;
    20992232
    2100           /* initialize for-in loop */
    2101           case XC( OC_WALKINIT ):
     2233        /* initialize for-in loop */
     2234        case XC( OC_WALKINIT ):
    21022235            hashwalk_init(L.v, iamarray(R.v));
    21032236            break;
    21042237
    2105           /* get next array item */
    2106           case XC( OC_WALKNEXT ):
     2238        /* get next array item */
     2239        case XC( OC_WALKNEXT ):
    21072240            op = hashwalk_next(L.v) ? op->a.n : op->r.n;
    21082241            break;
    21092242
    2110           case XC( OC_PRINT ):
    2111           case XC( OC_PRINTF ):
     2243        case XC( OC_PRINT ):
     2244        case XC( OC_PRINTF ):
    21122245            X.F = stdout;
    21132246            if (op->r.n) {
    21142247                X.rsm = newfile(R.s);
    2115                 if (! X.rsm->F) {
     2248                if (!X.rsm->F) {
    21162249                    if (opn == '|') {
    2117                         if((X.rsm->F = popen(R.s, "w")) == NULL)
     2250                        X.rsm->F = popen(R.s, "w");
     2251                        if (X.rsm->F == NULL)
    21182252                            bb_perror_msg_and_die("popen");
    21192253                        X.rsm->is_pipe = 1;
    21202254                    } else {
    2121                         X.rsm->F = bb_xfopen(R.s, opn=='w' ? "w" : "a");
     2255                        X.rsm->F = xfopen(R.s, opn=='w' ? "w" : "a");
    21222256                    }
    21232257                }
     
    21262260
    21272261            if ((opinfo & OPCLSMASK) == OC_PRINT) {
    2128                 if (! op1) {
    2129                     fputs(getvar_s(V[F0]), X.F);
     2262                if (!op1) {
     2263                    fputs(getvar_s(intvar[F0]), X.F);
    21302264                } else {
    21312265                    while (op1) {
    21322266                        L.v = evaluate(nextarg(&op1), v1);
    21332267                        if (L.v->type & VF_NUMBER) {
    2134                             fmt_num(buf, MAXVARFMT, getvar_s(V[OFMT]),
    2135                                                         getvar_i(L.v), TRUE);
    2136                             fputs(buf, X.F);
     2268                            fmt_num(g_buf, MAXVARFMT, getvar_s(intvar[OFMT]),
     2269                                    getvar_i(L.v), TRUE);
     2270                            fputs(g_buf, X.F);
    21372271                        } else {
    21382272                            fputs(getvar_s(L.v), X.F);
    21392273                        }
    21402274
    2141                         if (op1) fputs(getvar_s(V[OFS]), X.F);
     2275                        if (op1) fputs(getvar_s(intvar[OFS]), X.F);
    21422276                    }
    21432277                }
    2144                 fputs(getvar_s(V[ORS]), X.F);
     2278                fputs(getvar_s(intvar[ORS]), X.F);
    21452279
    21462280            } else {    /* OC_PRINTF */
    21472281                L.s = awk_printf(op1);
    21482282                fputs(L.s, X.F);
    2149                 free(L.s);
     2283                free((char*)L.s);
    21502284            }
    21512285            fflush(X.F);
    21522286            break;
    21532287
    2154           case XC( OC_DELETE ):
     2288        case XC( OC_DELETE ):
    21552289            X.info = op1->info & OPCLSMASK;
    21562290            if (X.info == OC_VAR) {
     
    21592293                R.v = &fnargs[op1->l.i];
    21602294            } else {
    2161                 runtime_error(EMSG_NOT_ARRAY);
     2295                syntax_error(EMSG_NOT_ARRAY);
    21622296            }
    21632297
     
    21712305            break;
    21722306
    2173           case XC( OC_NEWSOURCE ):
    2174             programname = op->l.s;
    2175             break;
    2176 
    2177           case XC( OC_RETURN ):
     2307        case XC( OC_NEWSOURCE ):
     2308            g_progname = op->l.s;
     2309            break;
     2310
     2311        case XC( OC_RETURN ):
    21782312            copyvar(res, L.v);
    21792313            break;
    21802314
    2181           case XC( OC_NEXTFILE ):
     2315        case XC( OC_NEXTFILE ):
    21822316            nextfile = TRUE;
    2183           case XC( OC_NEXT ):
     2317        case XC( OC_NEXT ):
    21842318            nextrec = TRUE;
    2185           case XC( OC_DONE ):
     2319        case XC( OC_DONE ):
    21862320            clrvar(res);
    21872321            break;
    21882322
    2189           case XC( OC_EXIT ):
     2323        case XC( OC_EXIT ):
    21902324            awk_exit(L.d);
    21912325
    2192           /* -- recursive node type -- */
    2193 
    2194           case XC( OC_VAR ):
     2326        /* -- recursive node type -- */
     2327
     2328        case XC( OC_VAR ):
    21952329            L.v = op->l.v;
    2196             if (L.v == V[NF])
     2330            if (L.v == intvar[NF])
    21972331                split_f0();
    21982332            goto v_cont;
    21992333
    2200           case XC( OC_FNARG ):
     2334        case XC( OC_FNARG ):
    22012335            L.v = &fnargs[op->l.i];
    2202 
    2203 v_cont:
    2204             res = (op->r.n) ? findvar(iamarray(L.v), R.s) : L.v;
    2205             break;
    2206 
    2207           case XC( OC_IN ):
     2336 v_cont:
     2337            res = op->r.n ? findvar(iamarray(L.v), R.s) : L.v;
     2338            break;
     2339
     2340        case XC( OC_IN ):
    22082341            setvar_i(res, hash_search(iamarray(R.v), L.s) ? 1 : 0);
    22092342            break;
    22102343
    2211           case XC( OC_REGEXP ):
     2344        case XC( OC_REGEXP ):
    22122345            op1 = op;
    2213             L.s = getvar_s(V[F0]);
     2346            L.s = getvar_s(intvar[F0]);
    22142347            goto re_cont;
    22152348
    2216           case XC( OC_MATCH ):
     2349        case XC( OC_MATCH ):
    22172350            op1 = op->r.n;
    2218 re_cont:
     2351 re_cont:
    22192352            X.re = as_regex(op1, &sreg);
    22202353            R.i = regexec(X.re, L.s, 0, NULL, 0);
     
    22232356            break;
    22242357
    2225           case XC( OC_MOVE ):
     2358        case XC( OC_MOVE ):
    22262359            /* if source is a temporary string, jusk relink it to dest */
    22272360            if (R.v == v1+1 && R.v->string) {
     
    22332366            break;
    22342367
    2235           case XC( OC_TERNARY ):
     2368        case XC( OC_TERNARY ):
    22362369            if ((op->r.n->info & OPCLSMASK) != OC_COLON)
    2237                 runtime_error(EMSG_POSSIBLE_ERROR);
     2370                syntax_error(EMSG_POSSIBLE_ERROR);
    22382371            res = evaluate(istrue(L.v) ? op->r.n->l.n : op->r.n->r.n, res);
    22392372            break;
    22402373
    2241           case XC( OC_FUNC ):
    2242             if (! op->r.f->body.first)
    2243                 runtime_error(EMSG_UNDEF_FUNC);
     2374        case XC( OC_FUNC ):
     2375            if (!op->r.f->body.first)
     2376                syntax_error(EMSG_UNDEF_FUNC);
    22442377
    22452378            X.v = R.v = nvalloc(op->r.f->nargs+1);
     
    22562389            fnargs = X.v;
    22572390
    2258             L.s = programname;
     2391            L.s = g_progname;
    22592392            res = evaluate(op->r.f->body.first, res);
    2260             programname = L.s;
     2393            g_progname = L.s;
    22612394
    22622395            nvfree(fnargs);
     
    22642397            break;
    22652398
    2266           case XC( OC_GETLINE ):
    2267           case XC( OC_PGETLINE ):
     2399        case XC( OC_GETLINE ):
     2400        case XC( OC_PGETLINE ):
    22682401            if (op1) {
    22692402                X.rsm = newfile(L.s);
    2270                 if (! X.rsm->F) {
     2403                if (!X.rsm->F) {
    22712404                    if ((opinfo & OPCLSMASK) == OC_PGETLINE) {
    22722405                        X.rsm->F = popen(L.s, "r");
    22732406                        X.rsm->is_pipe = TRUE;
    22742407                    } else {
    2275                         X.rsm->F = fopen(L.s, "r");     /* not bb_xfopen! */
     2408                        X.rsm->F = fopen(L.s, "r");     /* not xfopen! */
    22762409                    }
    22772410                }
    22782411            } else {
    2279                 if (! iF) iF = next_input_file();
     2412                if (!iF) iF = next_input_file();
    22802413                X.rsm = iF;
    22812414            }
    22822415
    2283             if (! X.rsm->F) {
    2284                 setvar_i(V[ERRNO], errno);
     2416            if (!X.rsm->F) {
     2417                setvar_i(intvar[ERRNO], errno);
    22852418                setvar_i(res, -1);
    22862419                break;
    22872420            }
    22882421
    2289             if (! op->r.n)
    2290                 R.v = V[F0];
     2422            if (!op->r.n)
     2423                R.v = intvar[F0];
    22912424
    22922425            L.i = awk_getline(X.rsm, R.v);
    22932426            if (L.i > 0) {
    2294                 if (! op1) {
    2295                     incvar(V[FNR]);
    2296                     incvar(V[NR]);
     2427                if (!op1) {
     2428                    incvar(intvar[FNR]);
     2429                    incvar(intvar[NR]);
    22972430                }
    22982431            }
     
    23002433            break;
    23012434
    2302           /* simple builtins */
    2303           case XC( OC_FBLTIN ):
     2435        /* simple builtins */
     2436        case XC( OC_FBLTIN ):
    23042437            switch (opn) {
    23052438
    2306               case F_in:
     2439            case F_in:
    23072440                R.d = (int)L.d;
    23082441                break;
    23092442
    2310               case F_rn:
    2311                 R.d =  (double)rand() / (double)RAND_MAX;
     2443            case F_rn:
     2444                R.d = (double)rand() / (double)RAND_MAX;
    23122445                break;
    2313 
    2314 #ifdef CONFIG_FEATURE_AWK_MATH
    2315               case F_co:
     2446#if ENABLE_FEATURE_AWK_MATH
     2447            case F_co:
    23162448                R.d = cos(L.d);
    23172449                break;
    23182450
    2319               case F_ex:
     2451            case F_ex:
    23202452                R.d = exp(L.d);
    23212453                break;
    23222454
    2323               case F_lg:
     2455            case F_lg:
    23242456                R.d = log(L.d);
    23252457                break;
    23262458
    2327               case F_si:
     2459            case F_si:
    23282460                R.d = sin(L.d);
    23292461                break;
    23302462
    2331               case F_sq:
     2463            case F_sq:
    23322464                R.d = sqrt(L.d);
    23332465                break;
    23342466#else
    2335               case F_co:
    2336               case F_ex:
    2337               case F_lg:
    2338               case F_si:
    2339               case F_sq:
    2340                 runtime_error(EMSG_NO_MATH);
     2467            case F_co:
     2468            case F_ex:
     2469            case F_lg:
     2470            case F_si:
     2471            case F_sq:
     2472                syntax_error(EMSG_NO_MATH);
    23412473                break;
    23422474#endif
    2343 
    2344               case F_sr:
     2475            case F_sr:
    23452476                R.d = (double)seed;
    2346                 seed = op1 ? (unsigned int)L.d : (unsigned int)time(NULL);
     2477                seed = op1 ? (unsigned)L.d : (unsigned)time(NULL);
    23472478                srand(seed);
    23482479                break;
    23492480
    2350               case F_ti:
     2481            case F_ti:
    23512482                R.d = time(NULL);
    23522483                break;
    23532484
    2354               case F_le:
    2355                 if (! op1)
    2356                     L.s = getvar_s(V[F0]);
     2485            case F_le:
     2486                if (!op1)
     2487                    L.s = getvar_s(intvar[F0]);
    23572488                R.d = strlen(L.s);
    23582489                break;
    23592490
    2360               case F_sy:
     2491            case F_sy:
    23612492                fflush(NULL);
    2362                 R.d = (L.s && *L.s) ? (system(L.s) >> 8) : 0;
     2493                R.d = (ENABLE_FEATURE_ALLOW_EXEC && L.s && *L.s)
     2494                        ? (system(L.s) >> 8) : 0;
    23632495                break;
    23642496
    2365               case F_ff:
    2366                 if (! op1)
     2497            case F_ff:
     2498                if (!op1)
    23672499                    fflush(stdout);
    23682500                else {
     
    23762508                break;
    23772509
    2378               case F_cl:
     2510            case F_cl:
    23792511                X.rsm = (rstream *)hash_search(fdhash, L.s);
    23802512                if (X.rsm) {
     
    23842516                }
    23852517                if (R.i != 0)
    2386                     setvar_i(V[ERRNO], errno);
     2518                    setvar_i(intvar[ERRNO], errno);
    23872519                R.d = (double)R.i;
    23882520                break;
     
    23912523            break;
    23922524
    2393           case XC( OC_BUILTIN ):
     2525        case XC( OC_BUILTIN ):
    23942526            res = exec_builtin(op, res);
    23952527            break;
    23962528
    2397           case XC( OC_SPRINTF ):
     2529        case XC( OC_SPRINTF ):
    23982530            setvar_p(res, awk_printf(op1));
    23992531            break;
    24002532
    2401           case XC( OC_UNARY ):
     2533        case XC( OC_UNARY ):
    24022534            X.v = R.v;
    24032535            L.d = R.d = getvar_i(R.v);
    24042536            switch (opn) {
    2405               case 'P':
     2537            case 'P':
    24062538                L.d = ++R.d;
    24072539                goto r_op_change;
    2408               case 'p':
     2540            case 'p':
    24092541                R.d++;
    24102542                goto r_op_change;
    2411               case 'M':
     2543            case 'M':
    24122544                L.d = --R.d;
    24132545                goto r_op_change;
    2414               case 'm':
     2546            case 'm':
    24152547                R.d--;
    24162548                goto r_op_change;
    2417               case '!':
    2418                 L.d = istrue(X.v) ? 0 : 1;
     2549            case '!':
     2550                L.d = istrue(X.v) ? 0 : 1;
    24192551                break;
    2420               case '-':
     2552            case '-':
    24212553                L.d = -R.d;
    24222554                break;
    2423             r_op_change:
     2555 r_op_change:
    24242556                setvar_i(X.v, R.d);
    24252557            }
     
    24272559            break;
    24282560
    2429           case XC( OC_FIELD ):
     2561        case XC( OC_FIELD ):
    24302562            R.i = (int)getvar_i(R.v);
    24312563            if (R.i == 0) {
    2432                 res = V[F0];
     2564                res = intvar[F0];
    24332565            } else {
    24342566                split_f0();
    24352567                if (R.i > nfields)
    24362568                    fsrealloc(R.i);
    2437 
    2438                 res = &Fields[R.i-1];
    2439             }
    2440             break;
    2441 
    2442           /* concatenation (" ") and index joining (",") */
    2443           case XC( OC_CONCAT ):
    2444           case XC( OC_COMMA ):
     2569                res = &Fields[R.i - 1];
     2570            }
     2571            break;
     2572
     2573        /* concatenation (" ") and index joining (",") */
     2574        case XC( OC_CONCAT ):
     2575        case XC( OC_COMMA ):
    24452576            opn = strlen(L.s) + strlen(R.s) + 2;
    2446             X.s = (char *)xmalloc(opn);
     2577            X.s = xmalloc(opn);
    24472578            strcpy(X.s, L.s);
    24482579            if ((opinfo & OPCLSMASK) == OC_COMMA) {
    2449                 L.s = getvar_s(V[SUBSEP]);
    2450                 X.s = (char *)xrealloc(X.s, opn + strlen(L.s));
     2580                L.s = getvar_s(intvar[SUBSEP]);
     2581                X.s = xrealloc(X.s, opn + strlen(L.s));
    24512582                strcat(X.s, L.s);
    24522583            }
     
    24552586            break;
    24562587
    2457           case XC( OC_LAND ):
     2588        case XC( OC_LAND ):
    24582589            setvar_i(res, istrue(L.v) ? ptest(op->r.n) : 0);
    24592590            break;
    24602591
    2461           case XC( OC_LOR ):
     2592        case XC( OC_LOR ):
    24622593            setvar_i(res, istrue(L.v) ? 1 : ptest(op->r.n));
    24632594            break;
    24642595
    2465           case XC( OC_BINARY ):
    2466           case XC( OC_REPLACE ):
     2596        case XC( OC_BINARY ):
     2597        case XC( OC_REPLACE ):
    24672598            R.d = getvar_i(R.v);
    24682599            switch (opn) {
    2469               case '+':
     2600            case '+':
    24702601                L.d += R.d;
    24712602                break;
    2472               case '-':
     2603            case '-':
    24732604                L.d -= R.d;
    24742605                break;
    2475               case '*':
     2606            case '*':
    24762607                L.d *= R.d;
    24772608                break;
    2478               case '/':
    2479                 if (R.d == 0) runtime_error(EMSG_DIV_BY_ZERO);
     2609            case '/':
     2610                if (R.d == 0) syntax_error(EMSG_DIV_BY_ZERO);
    24802611                L.d /= R.d;
    24812612                break;
    2482               case '&':
    2483 #ifdef CONFIG_FEATURE_AWK_MATH
     2613            case '&':
     2614#if ENABLE_FEATURE_AWK_MATH
    24842615                L.d = pow(L.d, R.d);
    24852616#else
    2486                 runtime_error(EMSG_NO_MATH);
     2617                syntax_error(EMSG_NO_MATH);
    24872618#endif
    24882619                break;
    2489               case '%':
    2490                 if (R.d == 0) runtime_error(EMSG_DIV_BY_ZERO);
     2620            case '%':
     2621                if (R.d == 0) syntax_error(EMSG_DIV_BY_ZERO);
    24912622                L.d -= (int)(L.d / R.d) * R.d;
    24922623                break;
    24932624            }
    2494             res = setvar_i(((opinfo&OPCLSMASK) == OC_BINARY) ? res : X.v, L.d);
    2495             break;
    2496 
    2497           case XC( OC_COMPARE ):
     2625            res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : X.v, L.d);
     2626            break;
     2627
     2628        case XC( OC_COMPARE ):
    24982629            if (is_numeric(L.v) && is_numeric(R.v)) {
    24992630                L.d = getvar_i(L.v) - getvar_i(R.v);
     
    25042635            }
    25052636            switch (opn & 0xfe) {
    2506               case 0:
     2637            case 0:
    25072638                R.i = (L.d > 0);
    25082639                break;
    2509               case 2:
     2640            case 2:
    25102641                R.i = (L.d >= 0);
    25112642                break;
    2512               case 4:
     2643            case 4:
    25132644                R.i = (L.d == 0);
    25142645                break;
     
    25172648            break;
    25182649
    2519           default:
    2520             runtime_error(EMSG_POSSIBLE_ERROR);
     2650        default:
     2651            syntax_error(EMSG_POSSIBLE_ERROR);
    25212652        }
    25222653        if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS)
     
    25292660    nvfree(v1);
    25302661    return res;
     2662#undef fnargs
     2663#undef seed
     2664#undef sreg
    25312665}
    25322666
     
    25362670static int awk_exit(int r)
    25372671{
    2538     unsigned int i;
     2672    var tv;
     2673    unsigned i;
    25392674    hash_item *hi;
    2540     static var tv;
    2541 
    2542     if (! exiting) {
     2675
     2676    zero_out_var(&tv);
     2677
     2678    if (!exiting) {
    25432679        exiting = TRUE;
    25442680        nextrec = FALSE;
     
    25472683
    25482684    /* waiting for children */
    2549     for (i=0; i<fdhash->csize; i++) {
     2685    for (i = 0; i < fdhash->csize; i++) {
    25502686        hi = fdhash->items[i];
    2551         while(hi) {
     2687        while (hi) {
    25522688            if (hi->data.rs.F && hi->data.rs.is_pipe)
    25532689                pclose(hi->data.rs.F);
     
    25652701    char *exprc, *s, *s0, *s1;
    25662702
    2567     exprc = bb_xstrdup(expr);
     2703    exprc = xstrdup(expr);
    25682704    if (!isalnum_(*exprc) || (s = strchr(exprc, '=')) == NULL) {
    25692705        free(exprc);
     
    25852721static rstream *next_input_file(void)
    25862722{
    2587     static rstream rsm;
     2723#define rsm          (G.next_input_file__rsm)
     2724#define files_happen (G.next_input_file__files_happen)
     2725
    25882726    FILE *F = NULL;
    2589     char *fname, *ind;
    2590     static int files_happen = FALSE;
     2727    const char *fname, *ind;
    25912728
    25922729    if (rsm.F) fclose(rsm.F);
     
    25952732
    25962733    do {
    2597         if (getvar_i(V[ARGIND])+1 >= getvar_i(V[ARGC])) {
     2734        if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) {
    25982735            if (files_happen)
    25992736                return NULL;
     
    26012738            F = stdin;
    26022739        } else {
    2603             ind = getvar_s(incvar(V[ARGIND]));
    2604             fname = getvar_s(findvar(iamarray(V[ARGV]), ind));
     2740            ind = getvar_s(incvar(intvar[ARGIND]));
     2741            fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind));
    26052742            if (fname && *fname && !is_assignment(fname))
    26062743                F = afopen(fname, "r");
     
    26092746
    26102747    files_happen = TRUE;
    2611     setvar_s(V[FILENAME], fname);
     2748    setvar_s(intvar[FILENAME], fname);
    26122749    rsm.F = F;
    26132750    return &rsm;
    2614 }
    2615 
     2751#undef rsm
     2752#undef files_happen
     2753}
     2754
     2755int awk_main(int argc, char **argv);
    26162756int awk_main(int argc, char **argv)
    26172757{
    2618     char *s, *s1;
    2619     int i, j, c, flen;
     2758    unsigned opt;
     2759    char *opt_F, *opt_W;
     2760    llist_t *opt_v = NULL;
     2761    int i, j, flen;
    26202762    var *v;
    2621     static var tv;
     2763    var tv;
    26222764    char **envp;
    2623     static int from_file = FALSE;
    2624     rstream *rsm;
    2625     FILE *F, *stdfiles[3];
    2626     static char * stdnames = "/dev/stdin\0/dev/stdout\0/dev/stderr";
     2765    char *vnames = (char *)vNames; /* cheat */
     2766    char *vvalues = (char *)vValues;
     2767
     2768    INIT_G();
     2769
     2770    /* Undo busybox.c, or else strtod may eat ','! This breaks parsing:
     2771     * $1,$2 == '$1,' '$2', NOT '$1' ',' '$2' */
     2772    if (ENABLE_LOCALE_SUPPORT)
     2773        setlocale(LC_NUMERIC, "C");
     2774
     2775    zero_out_var(&tv);
    26272776
    26282777    /* allocate global buffer */
    2629     buf = xmalloc(MAXVARFMT+1);
     2778    g_buf = xmalloc(MAXVARFMT + 1);
    26302779
    26312780    vhash = hash_init();
     
    26352784
    26362785    /* initialize variables */
    2637     for (i=0;  *vNames; i++) {
    2638         V[i] = v = newvar(nextword(&vNames));
    2639         if (*vValues != '\377')
    2640             setvar_s(v, nextword(&vValues));
     2786    for (i = 0; *vnames; i++) {
     2787        intvar[i] = v = newvar(nextword(&vnames));
     2788        if (*vvalues != '\377')
     2789            setvar_s(v, nextword(&vvalues));
    26412790        else
    26422791            setvar_i(v, 0);
    26432792
    2644         if (*vNames == '*') {
     2793        if (*vnames == '*') {
    26452794            v->type |= VF_SPECIAL;
    2646             vNames++;
    2647         }
    2648     }
    2649 
    2650     handle_special(V[FS]);
    2651     handle_special(V[RS]);
    2652 
    2653     stdfiles[0] = stdin;
    2654     stdfiles[1] = stdout;
    2655     stdfiles[2] = stderr;
    2656     for (i=0; i<3; i++) {
    2657         rsm = newfile(nextword(&stdnames));
    2658         rsm->F = stdfiles[i];
    2659     }
    2660 
    2661     for (envp=environ; *envp; envp++) {
    2662         s = bb_xstrdup(*envp);
    2663         s1 = strchr(s, '=');
    2664         if (!s1) {
    2665             goto keep_going;
    2666         }
    2667         *(s1++) = '\0';
    2668         setvar_u(findvar(iamarray(V[ENVIRON]), s), s1);
    2669 keep_going:
     2795            vnames++;
     2796        }
     2797    }
     2798
     2799    handle_special(intvar[FS]);
     2800    handle_special(intvar[RS]);
     2801
     2802    newfile("/dev/stdin")->F = stdin;
     2803    newfile("/dev/stdout")->F = stdout;
     2804    newfile("/dev/stderr")->F = stderr;
     2805
     2806    /* Huh, people report that sometimes environ is NULL. Oh well. */
     2807    if (environ) for (envp = environ; *envp; envp++) {
     2808        /* environ is writable, thus we don't strdup it needlessly */
     2809        char *s = *envp;
     2810        char *s1 = strchr(s, '=');
     2811        if (s1) {
     2812            *s1 = '\0';
     2813            /* Both findvar and setvar_u take const char*
     2814             * as 2nd arg -> environment is not trashed */
     2815            setvar_u(findvar(iamarray(intvar[ENVIRON]), s), s1 + 1);
     2816            *s1 = '=';
     2817        }
     2818    }
     2819    opt_complementary = "v::";
     2820    opt = getopt32(argv, "F:v:f:W:", &opt_F, &opt_v, &g_progname, &opt_W);
     2821    argv += optind;
     2822    argc -= optind;
     2823    if (opt & 0x1)
     2824        setvar_s(intvar[FS], opt_F); // -F
     2825    while (opt_v) { /* -v */
     2826        if (!is_assignment(llist_pop(&opt_v)))
     2827            bb_show_usage();
     2828    }
     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 {
     2839            for (i = j = 1; j > 0; i += j) {
     2840                s = xrealloc(s, i + 4096);
     2841                j = fread(s + i, 1, 4094, from_file);
     2842            }
     2843        }
     2844        s[i] = '\0';
     2845        fclose(from_file);
     2846        parse_program(s + 1);
    26702847        free(s);
    2671     }
    2672 
    2673     while((c = getopt(argc, argv, "F:v:f:W:")) != EOF) {
    2674         switch (c) {
    2675             case 'F':
    2676                 setvar_s(V[FS], optarg);
    2677                 break;
    2678             case 'v':
    2679                 if (! is_assignment(optarg))
    2680                     bb_show_usage();
    2681                 break;
    2682             case 'f':
    2683                 from_file = TRUE;
    2684                 F = afopen(programname = optarg, "r");
    2685                 s = NULL;
    2686                 /* one byte is reserved for some trick in next_token */
    2687                 if (fseek(F, 0, SEEK_END) == 0) {
    2688                     flen = ftell(F);
    2689                     s = (char *)xmalloc(flen+4);
    2690                     fseek(F, 0, SEEK_SET);
    2691                     i = 1 + fread(s+1, 1, flen, F);
    2692                 } else {
    2693                     for (i=j=1; j>0; i+=j) {
    2694                         s = (char *)xrealloc(s, i+4096);
    2695                         j = fread(s+i, 1, 4094, F);
    2696                     }
    2697                 }
    2698                 s[i] = '\0';
    2699                 fclose(F);
    2700                 parse_program(s+1);
    2701                 free(s);
    2702                 break;
    2703             case 'W':
    2704                 bb_error_msg("Warning: unrecognized option '-W %s' ignored\n", optarg);
    2705                 break;
    2706 
    2707             default:
    2708                 bb_show_usage();
    2709         }
    2710     }
    2711 
    2712     if (!from_file) {
    2713         if (argc == optind)
     2848    } else { // no -f: take program from 1st parameter
     2849        if (!argc)
    27142850            bb_show_usage();
    2715         programname="cmd. line";
    2716         parse_program(argv[optind++]);
    2717 
    2718     }
     2851        g_progname = "cmd. line";
     2852        parse_program(*argv++);
     2853        argc--;
     2854    }
     2855    if (opt & 0x8) // -W
     2856        bb_error_msg("warning: unrecognized option '-W %s' ignored", opt_W);
    27192857
    27202858    /* fill in ARGV array */
    2721     setvar_i(V[ARGC], argc - optind + 1);
    2722     setari_u(V[ARGV], 0, "awk");
    2723     for(i=optind; i < argc; i++)
    2724         setari_u(V[ARGV], i+1-optind, argv[i]);
     2859    setvar_i(intvar[ARGC], argc + 1);
     2860    setari_u(intvar[ARGV], 0, "awk");
     2861    i = 0;
     2862    while (*argv)
     2863        setari_u(intvar[ARGV], ++i, *argv++);
    27252864
    27262865    evaluate(beginseq.first, &tv);
    2727     if (! mainseq.first && ! endseq.first)
     2866    if (!mainseq.first && !endseq.first)
    27282867        awk_exit(EXIT_SUCCESS);
    27292868
    27302869    /* input file could already be opened in BEGIN block */
    2731     if (! iF) iF = next_input_file();
     2870    if (!iF) iF = next_input_file();
    27322871
    27332872    /* passing through input files */
    27342873    while (iF) {
    2735 
    27362874        nextfile = FALSE;
    2737         setvar_i(V[FNR], 0);
    2738 
    2739         while ((c = awk_getline(iF, V[F0])) > 0) {
    2740 
     2875        setvar_i(intvar[FNR], 0);
     2876
     2877        while ((i = awk_getline(iF, intvar[F0])) > 0) {
    27412878            nextrec = FALSE;
    2742             incvar(V[NR]);
    2743             incvar(V[FNR]);
     2879            incvar(intvar[NR]);
     2880            incvar(intvar[FNR]);
    27442881            evaluate(mainseq.first, &tv);
    27452882
     
    27482885        }
    27492886
    2750         if (c < 0)
    2751             runtime_error(strerror(errno));
     2887        if (i < 0)
     2888            syntax_error(strerror(errno));
    27522889
    27532890        iF = next_input_file();
    2754 
    27552891    }
    27562892
    27572893    awk_exit(EXIT_SUCCESS);
    2758 
    2759     return 0;
    2760 }
    2761 
     2894    /*return 0;*/
     2895}
Note: See TracChangeset for help on using the changeset viewer.