Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/editors/awk.c


Ignore:
Timestamp:
Jan 1, 2014, 12:47:38 AM (10 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.21.1
File:
1 edited

Legend:

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

    r2725 r3232  
    88 */
    99
     10//usage:#define awk_trivial_usage
     11//usage:       "[OPTIONS] [AWK_PROGRAM] [FILE]..."
     12//usage:#define awk_full_usage "\n\n"
     13//usage:       "    -v VAR=VAL  Set variable"
     14//usage:     "\n    -F SEP      Use SEP as field separator"
     15//usage:     "\n    -f FILE     Read program from FILE"
     16
    1017#include "libbb.h"
    1118#include "xregex.h"
     
    1926#define debug_printf_walker(...)  do {} while (0)
    2027#define debug_printf_eval(...)  do {} while (0)
     28#define debug_printf_parse(...)  do {} while (0)
    2129
    2230#ifndef debug_printf_walker
     
    2533#ifndef debug_printf_eval
    2634# define debug_printf_eval(...) (fprintf(stderr, __VA_ARGS__))
     35#endif
     36#ifndef debug_printf_parse
     37# define debug_printf_parse(...) (fprintf(stderr, __VA_ARGS__))
    2738#endif
    2839
     
    145156/* simple token classes */
    146157/* Order and hex values are very important!!!  See next_token() */
    147 #define TC_SEQSTART  1              /* ( */
     158#define TC_SEQSTART 1           /* ( */
    148159#define TC_SEQTERM  (1 << 1)        /* ) */
    149160#define TC_REGEXP   (1 << 2)        /* /.../ */
     
    232243 * n - min. number of args, vN - resolve Nth arg to var, sN - resolve to string
    233244 */
     245#undef P
     246#undef PRIMASK
     247#undef PRIMASK2
    234248#define P(x)      (x << 24)
    235249#define PRIMASK   0x7F000000
     
    426440    smallint nextfile;
    427441    smallint is_f0_split;
     442    smallint t_rollback;
    428443};
    429444struct globals2 {
     
    432447    char *t_string;
    433448    int t_lineno;
    434     int t_rollback;
    435449
    436450    var *intvar[NUM_INTERNAL_VARS]; /* often used */
     
    490504#define nextfile     (G1.nextfile    )
    491505#define is_f0_split  (G1.is_f0_split )
     506#define t_rollback   (G1.t_rollback  )
    492507#define t_info       (G.t_info      )
    493508#define t_tclass     (G.t_tclass    )
    494509#define t_string     (G.t_string    )
    495510#define t_lineno     (G.t_lineno    )
    496 #define t_rollback   (G.t_rollback  )
    497511#define intvar       (G.intvar      )
    498512#define fsplitter    (G.fsplitter   )
     
    683697    if (c == '\\')
    684698        c = bb_process_escape_sequence((const char**)s);
     699    /* Example awk statement:
     700     * s = "abc\"def"
     701     * we must treat \" as "
     702     */
    685703    if (c == '\\' && *s == pps) { /* unrecognized \z? */
    686704        c = *(*s); /* yes, fetch z */
     
    689707    }
    690708    return c;
     709}
     710
     711/* TODO: merge with strcpy_and_process_escape_sequences()?
     712 */
     713static void unescape_string_in_place(char *s1)
     714{
     715    char *s = s1;
     716    while ((*s1 = nextchar(&s)) != '\0')
     717        s1++;
    691718}
    692719
     
    10021029        if (*p == '\0') {
    10031030            tc = TC_EOF;
     1031            debug_printf_parse("%s: token found: TC_EOF\n", __func__);
    10041032
    10051033        } else if (*p == '\"') {
     
    10171045            *s = '\0';
    10181046            tc = TC_STRING;
     1047            debug_printf_parse("%s: token found:'%s' TC_STRING\n", __func__, t_string);
    10191048
    10201049        } else if ((expected & TC_REGEXP) && *p == '/') {
     
    10391068            *s = '\0';
    10401069            tc = TC_REGEXP;
     1070            debug_printf_parse("%s: token found:'%s' TC_REGEXP\n", __func__, t_string);
    10411071
    10421072        } else if (*p == '.' || isdigit(*p)) {
     
    10481078                syntax_error(EMSG_UNEXP_TOKEN);
    10491079            tc = TC_NUMBER;
     1080            debug_printf_parse("%s: token found:%f TC_NUMBER\n", __func__, t_double);
    10501081
    10511082        } else {
     
    10701101                    /* then this is what we are looking for */
    10711102                    t_info = *ti;
     1103                    debug_printf_parse("%s: token found:'%.*s' t_info:%x\n", __func__, l, p, t_info);
    10721104                    p += l;
    10731105                    goto token_found;
     
    10931125            if (*p == '(') {
    10941126                tc = TC_FUNCTION;
     1127                debug_printf_parse("%s: token found:'%s' TC_FUNCTION\n", __func__, t_string);
    10951128            } else {
    10961129                if (*p == '[') {
    10971130                    p++;
    10981131                    tc = TC_ARRAY;
    1099                 }
    1100             }
    1101  token_found: ;
    1102         }
     1132                    debug_printf_parse("%s: token found:'%s' TC_ARRAY\n", __func__, t_string);
     1133                } else
     1134                    debug_printf_parse("%s: token found:'%s' TC_VARIABLE\n", __func__, t_string);
     1135            }
     1136        }
     1137 token_found:
    11031138        g_pos = p;
    11041139
     
    11721207    var *v;
    11731208
     1209    debug_printf_parse("%s(%x)\n", __func__, iexp);
     1210
    11741211    sn.info = PRIMASK;
    11751212    sn.r.n = glptr = NULL;
     
    11801217        if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) {
    11811218            /* input redirection (<) attached to glptr node */
     1219            debug_printf_parse("%s: input redir\n", __func__);
    11821220            cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37));
    11831221            cn->a.n = glptr;
     
    11861224
    11871225        } else if (tc & (TC_BINOP | TC_UOPPOST)) {
     1226            debug_printf_parse("%s: TC_BINOP | TC_UOPPOST\n", __func__);
    11881227            /* for binary and postfix-unary operators, jump back over
    11891228             * previous operators with higher priority */
     
    12151254
    12161255        } else {
     1256            debug_printf_parse("%s: other\n", __func__);
    12171257            /* for operands and prefix-unary operators, attach them
    12181258             * to last node */
     
    12221262            xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP;
    12231263            if (tc & (TC_OPERAND | TC_REGEXP)) {
     1264                debug_printf_parse("%s: TC_OPERAND | TC_REGEXP\n", __func__);
    12241265                xtc = TC_UOPPRE | TC_UOPPOST | TC_BINOP | TC_OPERAND | iexp;
    12251266                /* one should be very careful with switch on tclass -
     
    12281269                case TC_VARIABLE:
    12291270                case TC_ARRAY:
     1271                    debug_printf_parse("%s: TC_VARIABLE | TC_ARRAY\n", __func__);
    12301272                    cn->info = OC_VAR;
    12311273                    v = hash_search(ahash, t_string);
     
    12441286                case TC_NUMBER:
    12451287                case TC_STRING:
     1288                    debug_printf_parse("%s: TC_NUMBER | TC_STRING\n", __func__);
    12461289                    cn->info = OC_VAR;
    12471290                    v = cn->l.v = xzalloc(sizeof(var));
     
    12531296
    12541297                case TC_REGEXP:
     1298                    debug_printf_parse("%s: TC_REGEXP\n", __func__);
    12551299                    mk_re_node(t_string, cn, xzalloc(sizeof(regex_t)*2));
    12561300                    break;
    12571301
    12581302                case TC_FUNCTION:
     1303                    debug_printf_parse("%s: TC_FUNCTION\n", __func__);
    12591304                    cn->info = OC_FUNC;
    12601305                    cn->r.f = newfunc(t_string);
     
    12631308
    12641309                case TC_SEQSTART:
     1310                    debug_printf_parse("%s: TC_SEQSTART\n", __func__);
    12651311                    cn = vn->r.n = parse_expr(TC_SEQTERM);
     1312                    if (!cn)
     1313                        syntax_error("Empty sequence");
    12661314                    cn->a.n = vn;
    12671315                    break;
    12681316
    12691317                case TC_GETLINE:
     1318                    debug_printf_parse("%s: TC_GETLINE\n", __func__);
    12701319                    glptr = cn;
    12711320                    xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
     
    12731322
    12741323                case TC_BUILTIN:
     1324                    debug_printf_parse("%s: TC_BUILTIN\n", __func__);
    12751325                    cn->l.n = condition();
    12761326                    break;
     
    12791329        }
    12801330    }
     1331
     1332    debug_printf_parse("%s() returns %p\n", __func__, sn.r.n);
    12811333    return sn.r.n;
    12821334}
     
    13471399
    13481400    if (c & TC_GRPSTART) {
     1401        debug_printf_parse("%s: TC_GRPSTART\n", __func__);
    13491402        while (next_token(TC_GRPSEQ | TC_GRPTERM) != TC_GRPTERM) {
     1403            debug_printf_parse("%s: !TC_GRPTERM\n", __func__);
    13501404            if (t_tclass & TC_NEWLINE)
    13511405                continue;
     
    13531407            chain_group();
    13541408        }
     1409        debug_printf_parse("%s: TC_GRPTERM\n", __func__);
    13551410    } else if (c & (TC_OPSEQ | TC_OPTERM)) {
     1411        debug_printf_parse("%s: TC_OPSEQ | TC_OPTERM\n", __func__);
    13561412        rollback_token();
    13571413        chain_expr(OC_EXEC | Vx);
    1358     } else {                        /* TC_STATEMNT */
     1414    } else {
     1415        /* TC_STATEMNT */
     1416        debug_printf_parse("%s: TC_STATEMNT(?)\n", __func__);
    13591417        switch (t_info & OPCLSMASK) {
    13601418        case ST_IF:
     1419            debug_printf_parse("%s: ST_IF\n", __func__);
    13611420            n = chain_node(OC_BR | Vx);
    13621421            n->l.n = condition();
     
    13731432
    13741433        case ST_WHILE:
     1434            debug_printf_parse("%s: ST_WHILE\n", __func__);
    13751435            n2 = condition();
    13761436            n = chain_loop(NULL);
     
    13791439
    13801440        case ST_DO:
     1441            debug_printf_parse("%s: ST_DO\n", __func__);
    13811442            n2 = chain_node(OC_EXEC);
    13821443            n = chain_loop(NULL);
     
    13871448
    13881449        case ST_FOR:
     1450            debug_printf_parse("%s: ST_FOR\n", __func__);
    13891451            next_token(TC_SEQSTART);
    13901452            n2 = parse_expr(TC_SEMICOL | TC_SEQTERM);
     
    14121474        case OC_PRINT:
    14131475        case OC_PRINTF:
     1476            debug_printf_parse("%s: OC_PRINT[F]\n", __func__);
    14141477            n = chain_node(t_info);
    14151478            n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM);
     
    14231486
    14241487        case OC_BREAK:
     1488            debug_printf_parse("%s: OC_BREAK\n", __func__);
    14251489            n = chain_node(OC_EXEC);
    14261490            n->a.n = break_ptr;
     
    14281492
    14291493        case OC_CONTINUE:
     1494            debug_printf_parse("%s: OC_CONTINUE\n", __func__);
    14301495            n = chain_node(OC_EXEC);
    14311496            n->a.n = continue_ptr;
     
    14341499        /* delete, next, nextfile, return, exit */
    14351500        default:
     1501            debug_printf_parse("%s: default\n", __func__);
    14361502            chain_expr(t_info);
    14371503        }
     
    14511517            TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) {
    14521518
    1453         if (tclass & TC_OPTERM)
     1519        if (tclass & TC_OPTERM) {
     1520            debug_printf_parse("%s: TC_OPTERM\n", __func__);
    14541521            continue;
     1522        }
    14551523
    14561524        seq = &mainseq;
    14571525        if (tclass & TC_BEGIN) {
     1526            debug_printf_parse("%s: TC_BEGIN\n", __func__);
    14581527            seq = &beginseq;
    14591528            chain_group();
    14601529
    14611530        } else if (tclass & TC_END) {
     1531            debug_printf_parse("%s: TC_END\n", __func__);
    14621532            seq = &endseq;
    14631533            chain_group();
    14641534
    14651535        } else if (tclass & TC_FUNCDECL) {
     1536            debug_printf_parse("%s: TC_FUNCDECL\n", __func__);
    14661537            next_token(TC_FUNCTION);
    14671538            g_pos++;
     
    14811552
    14821553        } else if (tclass & TC_OPSEQ) {
     1554            debug_printf_parse("%s: TC_OPSEQ\n", __func__);
    14831555            rollback_token();
    14841556            cn = chain_node(OC_TEST);
    14851557            cn->l.n = parse_expr(TC_OPTERM | TC_EOF | TC_GRPSTART);
    14861558            if (t_tclass & TC_GRPSTART) {
     1559                debug_printf_parse("%s: TC_GRPSTART\n", __func__);
    14871560                rollback_token();
    14881561                chain_group();
    14891562            } else {
     1563                debug_printf_parse("%s: !TC_GRPSTART\n", __func__);
    14901564                chain_node(OC_PRINT);
    14911565            }
     
    14931567
    14941568        } else /* if (tclass & TC_GRPSTART) */ {
     1569            debug_printf_parse("%s: TC_GRPSTART(?)\n", __func__);
    14951570            rollback_token();
    14961571            chain_group();
    14971572        }
    14981573    }
     1574    debug_printf_parse("%s: TC_EOF\n", __func__);
    14991575}
    15001576
     
    17371813
    17381814    } else if (v == intvar[FS]) {
     1815        /*
     1816         * The POSIX-2008 standard says that changing FS should have no effect on the
     1817         * current input line, but only on the next one. The language is:
     1818         *
     1819         * > Before the first reference to a field in the record is evaluated, the record
     1820         * > shall be split into fields, according to the rules in Regular Expressions,
     1821         * > using the value of FS that was current at the time the record was read.
     1822         *
     1823         * So, split up current line before assignment to FS:
     1824         */
     1825        split_f0();
     1826
    17391827        mk_splitter(getvar_s(v), &fsplitter);
    17401828
     
    26212709            }
    26222710
    2623             if (!rsm->F) {
     2711            if (!rsm || !rsm->F) {
    26242712                setvar_i(intvar[ERRNO], errno);
    26252713                setvar_i(res, -1);
     
    29303018static int is_assignment(const char *expr)
    29313019{
    2932     char *exprc, *val, *s, *s1;
     3020    char *exprc, *val;
    29333021
    29343022    if (!isalnum_(*expr) || (val = strchr(expr, '=')) == NULL) {
     
    29403028    *val++ = '\0';
    29413029
    2942     s = s1 = val;
    2943     while ((*s1 = nextchar(&s)) != '\0')
    2944         s1++;
    2945 
     3030    unescape_string_in_place(val);
    29463031    setvar_u(newvar(exprc), val);
    29473032    free(exprc);
     
    29553040#define files_happen (G.next_input_file__files_happen)
    29563041
    2957     FILE *F = NULL;
     3042    FILE *F;
    29583043    const char *fname, *ind;
    29593044
     
    29633048    rsm.pos = rsm.adv = 0;
    29643049
    2965     do {
     3050    for (;;) {
    29663051        if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) {
    29673052            if (files_happen)
     
    29693054            fname = "-";
    29703055            F = stdin;
    2971         } else {
    2972             ind = getvar_s(incvar(intvar[ARGIND]));
    2973             fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind));
    2974             if (fname && *fname && !is_assignment(fname))
    2975                 F = xfopen_stdin(fname);
    2976         }
    2977     } while (!F);
     3056            break;
     3057        }
     3058        ind = getvar_s(incvar(intvar[ARGIND]));
     3059        fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind));
     3060        if (fname && *fname && !is_assignment(fname)) {
     3061            F = xfopen_stdin(fname);
     3062            break;
     3063        }
     3064    }
    29783065
    29793066    files_happen = TRUE;
     
    29893076{
    29903077    unsigned opt;
    2991     char *opt_F, *opt_W;
     3078    char *opt_F;
    29923079    llist_t *list_v = NULL;
    29933080    llist_t *list_f = NULL;
     
    30513138    }
    30523139    opt_complementary = "v::f::"; /* -v and -f can occur multiple times */
    3053     opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, &opt_W);
     3140    opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, NULL);
    30543141    argv += optind;
    30553142    argc -= optind;
    3056     if (opt & 0x1)
    3057         setvar_s(intvar[FS], opt_F); // -F
     3143    if (opt & 0x1) { /* -F */
     3144        unescape_string_in_place(opt_F);
     3145        setvar_s(intvar[FS], opt_F);
     3146    }
    30583147    while (list_v) { /* -v */
    30593148        if (!is_assignment(llist_pop(&list_v)))
     
    30853174    }
    30863175    if (opt & 0x8) // -W
    3087         bb_error_msg("warning: unrecognized option '-W %s' ignored", opt_W);
     3176        bb_error_msg("warning: option -W is ignored");
    30883177
    30893178    /* fill in ARGV array */
Note: See TracChangeset for help on using the changeset viewer.