Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/editors/awk.c


Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (7 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

Location:
branches/3.3
Files:
1 edited
1 copied

Legend:

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

    r3232 r3621  
    88 */
    99
     10//config:config AWK
     11//config:   bool "awk"
     12//config:   default y
     13//config:   help
     14//config:     Awk is used as a pattern scanning and processing language. This is
     15//config:     the BusyBox implementation of that programming language.
     16//config:
     17//config:config FEATURE_AWK_LIBM
     18//config:   bool "Enable math functions (requires libm)"
     19//config:   default y
     20//config:   depends on AWK
     21//config:   help
     22//config:     Enable math functions of the Awk programming language.
     23//config:     NOTE: This will require libm to be present for linking.
     24//config:
     25//config:config FEATURE_AWK_GNU_EXTENSIONS
     26//config:   bool "Enable a few GNU extensions"
     27//config:   default y
     28//config:   depends on AWK
     29//config:   help
     30//config:     Enable a few features from gawk:
     31//config:     * command line option -e AWK_PROGRAM
     32//config:     * simultaneous use of -f and -e on the command line.
     33//config:       This enables the use of awk library files.
     34//config:       Ex: awk -f mylib.awk -e '{print myfunction($1);}' ...
     35
     36//applet:IF_AWK(APPLET_NOEXEC(awk, awk, BB_DIR_USR_BIN, BB_SUID_DROP, awk))
     37
     38//kbuild:lib-$(CONFIG_AWK) += awk.o
     39
    1040//usage:#define awk_trivial_usage
    1141//usage:       "[OPTIONS] [AWK_PROGRAM] [FILE]..."
     
    1444//usage:     "\n    -F SEP      Use SEP as field separator"
    1545//usage:     "\n    -f FILE     Read program from FILE"
     46//usage:    IF_FEATURE_AWK_GNU_EXTENSIONS(
     47//usage:     "\n    -e AWK_PROGRAM"
     48//usage:    )
    1649
    1750#include "libbb.h"
     
    3972
    4073
     74#define OPTSTR_AWK \
     75    "F:v:f:" \
     76    IF_FEATURE_AWK_GNU_EXTENSIONS("e:") \
     77    "W:"
     78#define OPTCOMPLSTR_AWK \
     79    "v::f::" \
     80    IF_FEATURE_AWK_GNU_EXTENSIONS("e::")
     81enum {
     82    OPTBIT_F,   /* define field separator */
     83    OPTBIT_v,   /* define variable */
     84    OPTBIT_f,   /* pull in awk program from file */
     85    IF_FEATURE_AWK_GNU_EXTENSIONS(OPTBIT_e,) /* -e AWK_PROGRAM */
     86    OPTBIT_W,   /* -W ignored */
     87    OPT_F = 1 << OPTBIT_F,
     88    OPT_v = 1 << OPTBIT_v,
     89    OPT_f = 1 << OPTBIT_f,
     90    OPT_e = IF_FEATURE_AWK_GNU_EXTENSIONS((1 << OPTBIT_e)) + 0,
     91    OPT_W = 1 << OPTBIT_W
     92};
    4193
    4294#define MAXVARFMT       240
     
    156208/* simple token classes */
    157209/* Order and hex values are very important!!!  See next_token() */
    158 #define TC_SEQSTART 1           /* ( */
     210#define TC_SEQSTART (1 << 0)        /* ( */
    159211#define TC_SEQTERM  (1 << 1)        /* ) */
    160212#define TC_REGEXP   (1 << 2)        /* /.../ */
     
    176228#define TC_ELSE     (1 << 18)
    177229#define TC_BUILTIN  (1 << 19)
    178 #define TC_GETLINE  (1 << 20)
    179 #define TC_FUNCDECL (1 << 21)       /* `function' `func' */
    180 #define TC_BEGIN    (1 << 22)
    181 #define TC_END      (1 << 23)
    182 #define TC_EOF      (1 << 24)
    183 #define TC_VARIABLE (1 << 25)
    184 #define TC_ARRAY    (1 << 26)
    185 #define TC_FUNCTION (1 << 27)
    186 #define TC_STRING   (1 << 28)
    187 #define TC_NUMBER   (1 << 29)
     230/* This costs ~50 bytes of code.
     231 * A separate class to support deprecated "length" form. If we don't need that
     232 * (i.e. if we demand that only "length()" with () is valid), then TC_LENGTH
     233 * can be merged with TC_BUILTIN:
     234 */
     235#define TC_LENGTH   (1 << 20)
     236#define TC_GETLINE  (1 << 21)
     237#define TC_FUNCDECL (1 << 22)       /* `function' `func' */
     238#define TC_BEGIN    (1 << 23)
     239#define TC_END      (1 << 24)
     240#define TC_EOF      (1 << 25)
     241#define TC_VARIABLE (1 << 26)
     242#define TC_ARRAY    (1 << 27)
     243#define TC_FUNCTION (1 << 28)
     244#define TC_STRING   (1 << 29)
     245#define TC_NUMBER   (1 << 30)
    188246
    189247#define TC_UOPPRE  (TC_UOPPRE1 | TC_UOPPRE2)
     
    191249/* combined token classes */
    192250#define TC_BINOP   (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN)
    193 #define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST)
     251//#define   TC_UNARYOP (TC_UOPPRE | TC_UOPPOST)
    194252#define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \
    195                    | TC_BUILTIN | TC_GETLINE | TC_SEQSTART | TC_STRING | TC_NUMBER)
     253                   | TC_BUILTIN | TC_LENGTH | TC_GETLINE \
     254                   | TC_SEQSTART | TC_STRING | TC_NUMBER)
    196255
    197256#define TC_STATEMNT (TC_STATX | TC_WHILE)
     
    199258
    200259/* word tokens, cannot mean something else if not expected */
    201 #define TC_WORD    (TC_IN | TC_STATEMNT | TC_ELSE | TC_BUILTIN \
    202                    | TC_GETLINE | TC_FUNCDECL | TC_BEGIN | TC_END)
     260#define TC_WORD    (TC_IN | TC_STATEMNT | TC_ELSE \
     261                   | TC_BUILTIN | TC_LENGTH | TC_GETLINE \
     262                   | TC_FUNCDECL | TC_BEGIN | TC_END)
    203263
    204264/* discard newlines after these */
     
    295355#define NTCC    '\377'
    296356
    297 #define OC_B  OC_BUILTIN
    298 
    299357static const char tokenlist[] ALIGN1 =
    300     "\1("         NTC
    301     "\1)"         NTC
    302     "\1/"         NTC                                   /* REGEXP */
    303     "\2>>"        "\1>"         "\1|"       NTC         /* OUTRDR */
    304     "\2++"        "\2--"        NTC                     /* UOPPOST */
    305     "\2++"        "\2--"        "\1$"       NTC         /* UOPPRE1 */
    306     "\2=="        "\1="         "\2+="      "\2-="      /* BINOPX */
     358    "\1("         NTC                                   /* TC_SEQSTART */
     359    "\1)"         NTC                                   /* TC_SEQTERM */
     360    "\1/"         NTC                                   /* TC_REGEXP */
     361    "\2>>"        "\1>"         "\1|"       NTC         /* TC_OUTRDR */
     362    "\2++"        "\2--"        NTC                     /* TC_UOPPOST */
     363    "\2++"        "\2--"        "\1$"       NTC         /* TC_UOPPRE1 */
     364    "\2=="        "\1="         "\2+="      "\2-="      /* TC_BINOPX */
    307365    "\2*="        "\2/="        "\2%="      "\2^="
    308366    "\1+"         "\1-"         "\3**="     "\2**"
     
    311369    "\1<"         "\2!~"        "\1~"       "\2&&"
    312370    "\2||"        "\1?"         "\1:"       NTC
    313     "\2in"        NTC
    314     "\1,"         NTC
    315     "\1|"         NTC
    316     "\1+"         "\1-"         "\1!"       NTC         /* UOPPRE2 */
    317     "\1]"         NTC
    318     "\1{"         NTC
    319     "\1}"         NTC
    320     "\1;"         NTC
    321     "\1\n"        NTC
    322     "\2if"        "\2do"        "\3for"     "\5break"   /* STATX */
     371    "\2in"        NTC                                   /* TC_IN */
     372    "\1,"         NTC                                   /* TC_COMMA */
     373    "\1|"         NTC                                   /* TC_PIPE */
     374    "\1+"         "\1-"         "\1!"       NTC         /* TC_UOPPRE2 */
     375    "\1]"         NTC                                   /* TC_ARRTERM */
     376    "\1{"         NTC                                   /* TC_GRPSTART */
     377    "\1}"         NTC                                   /* TC_GRPTERM */
     378    "\1;"         NTC                                   /* TC_SEMICOL */
     379    "\1\n"        NTC                                   /* TC_NEWLINE */
     380    "\2if"        "\2do"        "\3for"     "\5break"   /* TC_STATX */
    323381    "\10continue" "\6delete"    "\5print"
    324382    "\6printf"    "\4next"      "\10nextfile"
    325383    "\6return"    "\4exit"      NTC
    326     "\5while"     NTC
    327     "\4else"      NTC
    328 
    329     "\3and"       "\5compl"     "\6lshift"  "\2or"
     384    "\5while"     NTC                                   /* TC_WHILE */
     385    "\4else"      NTC                                   /* TC_ELSE */
     386    "\3and"       "\5compl"     "\6lshift"  "\2or"      /* TC_BUILTIN */
    330387    "\6rshift"    "\3xor"
    331     "\5close"     "\6system"    "\6fflush"  "\5atan2"   /* BUILTIN */
     388    "\5close"     "\6system"    "\6fflush"  "\5atan2"
    332389    "\3cos"       "\3exp"       "\3int"     "\3log"
    333390    "\4rand"      "\3sin"       "\4sqrt"    "\5srand"
    334     "\6gensub"    "\4gsub"      "\5index"   "\6length"
     391    "\6gensub"    "\4gsub"      "\5index"   /* "\6length" was here */
    335392    "\5match"     "\5split"     "\7sprintf" "\3sub"
    336393    "\6substr"    "\7systime"   "\10strftime" "\6mktime"
    337394    "\7tolower"   "\7toupper"   NTC
    338     "\7getline"   NTC
    339     "\4func"      "\10function" NTC
    340     "\5BEGIN"     NTC
    341     "\3END"
     395    "\6length"    NTC                                   /* TC_LENGTH */
     396    "\7getline"   NTC                                   /* TC_GETLINE */
     397    "\4func"      "\10function" NTC                     /* TC_FUNCDECL */
     398    "\5BEGIN"     NTC                                   /* TC_BEGIN */
     399    "\3END"                                             /* TC_END */
    342400    /* compiler adds trailing "\0" */
    343401    ;
     402
     403#define OC_B  OC_BUILTIN
    344404
    345405static const uint32_t tokeninfo[] = {
     
    357417    OC_COMPARE|VV|P(39)|2,   OC_MATCH|Sx|P(45)|'!',   OC_MATCH|Sx|P(45)|'~',   OC_LAND|Vx|P(55),
    358418    OC_LOR|Vx|P(59),         OC_TERNARY|Vx|P(64)|'?', OC_COLON|xx|P(67)|':',
    359     OC_IN|SV|P(49), /* in */
     419    OC_IN|SV|P(49), /* TC_IN */
    360420    OC_COMMA|SS|P(80),
    361421    OC_PGETLINE|SV|P(37),
     
    372432    ST_WHILE,
    373433    0, /* else */
    374 
    375434    OC_B|B_an|P(0x83), OC_B|B_co|P(0x41), OC_B|B_ls|P(0x83), OC_B|B_or|P(0x83),
    376435    OC_B|B_rs|P(0x83), OC_B|B_xo|P(0x83),
     
    378437    OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg,
    379438    OC_FBLTIN|F_rn,    OC_FBLTIN|Nx|F_si, OC_FBLTIN|Nx|F_sq, OC_FBLTIN|Nx|F_sr,
    380     OC_B|B_ge|P(0xd6), OC_B|B_gs|P(0xb6), OC_B|B_ix|P(0x9b), OC_FBLTIN|Sx|F_le,
     439    OC_B|B_ge|P(0xd6), OC_B|B_gs|P(0xb6), OC_B|B_ix|P(0x9b), /* OC_FBLTIN|Sx|F_le, was here */
    381440    OC_B|B_ma|P(0x89), OC_B|B_sp|P(0x8b), OC_SPRINTF,        OC_B|B_su|P(0xb6),
    382441    OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti,    OC_B|B_ti|P(0x0b), OC_B|B_mt|P(0x0b),
    383442    OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49),
     443    OC_FBLTIN|Sx|F_le, /* TC_LENGTH */
    384444    OC_GETLINE|SV|P(0),
    385445    0,                 0,
    386446    0,
    387     0 /* END */
     447    0 /* TC_END */
    388448};
    389449
     
    10091069    if (t_rollback) {
    10101070        t_rollback = FALSE;
    1011 
    10121071    } else if (concat_inserted) {
    10131072        concat_inserted = FALSE;
    10141073        t_tclass = save_tclass;
    10151074        t_info = save_info;
    1016 
    10171075    } else {
    10181076        p = g_pos;
     
    10301088            tc = TC_EOF;
    10311089            debug_printf_parse("%s: token found: TC_EOF\n", __func__);
    1032 
    10331090        } else if (*p == '\"') {
    10341091            /* it's a string */
     
    10461103            tc = TC_STRING;
    10471104            debug_printf_parse("%s: token found:'%s' TC_STRING\n", __func__, t_string);
    1048 
    10491105        } else if ((expected & TC_REGEXP) && *p == '/') {
    10501106            /* it's regexp */
     
    10791135            tc = TC_NUMBER;
    10801136            debug_printf_parse("%s: token found:%f TC_NUMBER\n", __func__, t_double);
    1081 
    10821137        } else {
    10831138            /* search for something known */
     
    11561211
    11571212    /* Are we ready for this? */
    1158     if (!(ltclass & expected))
     1213    if (!(ltclass & expected)) {
    11591214        syntax_error((ltclass & (TC_NEWLINE | TC_EOF)) ?
    11601215                EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN);
     1216    }
    11611217
    11621218    return ltclass;
     
    13251381                    cn->l.n = condition();
    13261382                    break;
     1383
     1384                case TC_LENGTH:
     1385                    debug_printf_parse("%s: TC_LENGTH\n", __func__);
     1386                    next_token(TC_SEQSTART | TC_OPTERM | TC_GRPTERM);
     1387                    rollback_token();
     1388                    if (t_tclass & TC_SEQSTART) {
     1389                        /* It was a "(" token. Handle just like TC_BUILTIN */
     1390                        cn->l.n = condition();
     1391                    }
     1392                    break;
    13271393                }
    13281394            }
     
    14891555            n = chain_node(OC_EXEC);
    14901556            n->a.n = break_ptr;
     1557            chain_expr(t_info);
    14911558            break;
    14921559
     
    14951562            n = chain_node(OC_EXEC);
    14961563            n->a.n = continue_ptr;
     1564            chain_expr(t_info);
    14971565            break;
    14981566
     
    15271595            seq = &beginseq;
    15281596            chain_group();
    1529 
    15301597        } else if (tclass & TC_END) {
    15311598            debug_printf_parse("%s: TC_END\n", __func__);
    15321599            seq = &endseq;
    15331600            chain_group();
    1534 
    15351601        } else if (tclass & TC_FUNCDECL) {
    15361602            debug_printf_parse("%s: TC_FUNCDECL\n", __func__);
     
    15501616            chain_group();
    15511617            clear_array(ahash);
    1552 
    15531618        } else if (tclass & TC_OPSEQ) {
    15541619            debug_printf_parse("%s: TC_OPSEQ\n", __func__);
     
    15651630            }
    15661631            cn->r.n = mainseq.last;
    1567 
    15681632        } else /* if (tclass & TC_GRPSTART) */ {
    15691633            debug_printf_parse("%s: TC_GRPSTART(?)\n", __func__);
     
    18261890
    18271891        mk_splitter(getvar_s(v), &fsplitter);
    1828 
    18291892    } else if (v == intvar[RS]) {
    18301893        mk_splitter(getvar_s(v), &rsplitter);
    1831 
    18321894    } else if (v == intvar[IGNORECASE]) {
    18331895        icase = istrue(v);
    1834 
    18351896    } else {                /* $n */
    18361897        n = getvar_i(intvar[NF]);
     
    20162077    const char *s = format;
    20172078
    2018     if (int_as_int && n == (int)n) {
    2019         r = snprintf(b, size, "%d", (int)n);
     2079    if (int_as_int && n == (long long)n) {
     2080        r = snprintf(b, size, "%lld", (long long)n);
    20202081    } else {
    20212082        do { c = *s; } while (c && *++s);
     
    26622723            const char *sv_progname;
    26632724
    2664             if (!op->r.f->body.first)
     2725            /* The body might be empty, still has to eval the args */
     2726            if (!op->r.n->info && !op->r.f->body.first)
    26652727                syntax_error(EMSG_UNDEF_FUNC);
    26662728
     
    27332795            switch (opn) {
    27342796            case F_in:
    2735                 R_d = (int)L_d;
     2797                R_d = (long long)L_d;
    27362798                break;
    27372799
     
    27842846
    27852847            case F_le:
    2786                 if (!op1)
     2848                debug_printf_eval("length: L.s:'%s'\n", L.s);
     2849                if (!op1) {
    27872850                    L.s = getvar_s(intvar[F0]);
     2851                    debug_printf_eval("length: L.s='%s'\n", L.s);
     2852                }
     2853                else if (L.v->type & VF_ARRAY) {
     2854                    R_d = L.v->x.array->nel;
     2855                    debug_printf_eval("length: array_len:%d\n", L.v->x.array->nel);
     2856                    break;
     2857                }
    27882858                R_d = strlen(L.s);
    27892859                break;
     
    29313001                if (R_d == 0)
    29323002                    syntax_error(EMSG_DIV_BY_ZERO);
    2933                 L_d -= (int)(L_d / R_d) * R_d;
     3003                L_d -= (long long)(L_d / R_d) * R_d;
    29343004                break;
    29353005            }
     
    30793149    llist_t *list_v = NULL;
    30803150    llist_t *list_f = NULL;
     3151#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
     3152    llist_t *list_e = NULL;
     3153#endif
    30813154    int i, j;
    30823155    var *v;
     
    31373210        }
    31383211    }
    3139     opt_complementary = "v::f::"; /* -v and -f can occur multiple times */
    3140     opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, NULL);
     3212    opt_complementary = OPTCOMPLSTR_AWK;
     3213    opt = getopt32(argv, OPTSTR_AWK, &opt_F, &list_v, &list_f, IF_FEATURE_AWK_GNU_EXTENSIONS(&list_e,) NULL);
    31413214    argv += optind;
    31423215    argc -= optind;
    3143     if (opt & 0x1) { /* -F */
     3216    if (opt & OPT_W)
     3217        bb_error_msg("warning: option -W is ignored");
     3218    if (opt & OPT_F) {
    31443219        unescape_string_in_place(opt_F);
    31453220        setvar_s(intvar[FS], opt_F);
    31463221    }
    3147     while (list_v) { /* -v */
     3222    while (list_v) {
    31483223        if (!is_assignment(llist_pop(&list_v)))
    31493224            bb_show_usage();
    31503225    }
    3151     if (list_f) { /* -f */
    3152         do {
    3153             char *s = NULL;
    3154             FILE *from_file;
    3155 
    3156             g_progname = llist_pop(&list_f);
    3157             from_file = xfopen_stdin(g_progname);
    3158             /* one byte is reserved for some trick in next_token */
    3159             for (i = j = 1; j > 0; i += j) {
    3160                 s = xrealloc(s, i + 4096);
    3161                 j = fread(s + i, 1, 4094, from_file);
    3162             }
    3163             s[i] = '\0';
    3164             fclose(from_file);
    3165             parse_program(s + 1);
    3166             free(s);
    3167         } while (list_f);
    3168         argc++;
    3169     } else { // no -f: take program from 1st parameter
    3170         if (!argc)
     3226    while (list_f) {
     3227        char *s = NULL;
     3228        FILE *from_file;
     3229
     3230        g_progname = llist_pop(&list_f);
     3231        from_file = xfopen_stdin(g_progname);
     3232        /* one byte is reserved for some trick in next_token */
     3233        for (i = j = 1; j > 0; i += j) {
     3234            s = xrealloc(s, i + 4096);
     3235            j = fread(s + i, 1, 4094, from_file);
     3236        }
     3237        s[i] = '\0';
     3238        fclose(from_file);
     3239        parse_program(s + 1);
     3240        free(s);
     3241    }
     3242    g_progname = "cmd. line";
     3243#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
     3244    while (list_e) {
     3245        parse_program(llist_pop(&list_e));
     3246    }
     3247#endif
     3248    if (!(opt & (OPT_f | OPT_e))) {
     3249        if (!*argv)
    31713250            bb_show_usage();
    3172         g_progname = "cmd. line";
    31733251        parse_program(*argv++);
    3174     }
    3175     if (opt & 0x8) // -W
    3176         bb_error_msg("warning: option -W is ignored");
     3252        argc--;
     3253    }
    31773254
    31783255    /* fill in ARGV array */
    3179     setvar_i(intvar[ARGC], argc);
     3256    setvar_i(intvar[ARGC], argc + 1);
    31803257    setari_u(intvar[ARGV], 0, "awk");
    31813258    i = 0;
Note: See TracChangeset for help on using the changeset viewer.