awk: implement -E; do not reorder -f and -e
No binary (build failed)
—
(log yok)
| @@ -40,7 +40,7 @@ | |
| //usage:#define awk_full_usage "\n\n" | |
| //usage: " -v VAR=VAL Set variable" | |
| //usage: "\n -F SEP Use SEP as field separator" | |
| - | //usage: "\n -f FILE Read program from FILE" |
| + | //usage: "\n -f/-E FILE Read program from FILE" |
| //usage: IF_FEATURE_AWK_GNU_EXTENSIONS( | |
| //usage: "\n -e AWK_PROGRAM" | |
| //usage: ) | |
| @@ -76,8 +76,8 @@ | |
| * 1: -argz | |
| */ | |
| #define OPTSTR_AWK "+" \ | |
| - | "F:v:*f:*" \ |
| - | IF_FEATURE_AWK_GNU_EXTENSIONS("e:*") \ |
| + | "F:v:f:" \ |
| + | IF_FEATURE_AWK_GNU_EXTENSIONS("e:E:") \ |
| "W:" | |
| enum { | |
| OPTBIT_F, /* define field separator */ | |
| @@ -560,6 +560,7 @@ struct globals { | |
| var *Fields; | |
| char *g_pos; | |
| char g_saved_ch; | |
| + | smallint got_program; |
| smallint icase; | |
| smallint exiting; | |
| smallint nextrec; | |
| @@ -635,6 +636,7 @@ struct globals2 { | |
| #define Fields (G1.Fields ) | |
| #define g_pos (G1.g_pos ) | |
| #define g_saved_ch (G1.g_saved_ch ) | |
| + | #define got_program (G1.got_program ) |
| #define icase (G1.icase ) | |
| #define exiting (G1.exiting ) | |
| #define nextrec (G1.nextrec ) | |
| @@ -2899,11 +2901,13 @@ static int next_input_file(void) | |
| } | |
| fname = getvar_s(findvar(iamarray(intvar[ARGV]), utoa(argind))); | |
| if (fname && *fname) { | |
| - | /* "If a filename on the command line has the form |
| - | * var=val it is treated as a variable assignment" |
| - | */ |
| - | if (try_to_assign(fname)) |
| - | continue; |
| + | if (got_program != 2) { /* there was no -E option */ |
| + | /* "If a filename on the command line has the form |
| + | * var=val it is treated as a variable assignment" |
| + | */ |
| + | if (try_to_assign(fname)) |
| + | continue; |
| + | } |
| iF.F = xfopen_stdin(fname); | |
| setvar_i(intvar[ARGIND], argind); | |
| break; | |
| @@ -3659,13 +3663,7 @@ static int awk_exit(void) | |
| int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| int awk_main(int argc UNUSED_PARAM, char **argv) | |
| { | |
| - | unsigned opt; |
| - | char *opt_F; |
| - | llist_t *list_v = NULL; |
| - | llist_t *list_f = NULL; |
| - | #if ENABLE_FEATURE_AWK_GNU_EXTENSIONS |
| - | llist_t *list_e = NULL; |
| - | #endif |
| + | int ch; |
| int i; | |
| INIT_G(); | |
| @@ -3714,49 +3712,68 @@ int awk_main(int argc UNUSED_PARAM, char **argv) | |
| } | |
| } | |
| } | |
| - | opt = getopt32(argv, OPTSTR_AWK, &opt_F, &list_v, &list_f, IF_FEATURE_AWK_GNU_EXTENSIONS(&list_e,) NULL); |
| - | argv += optind; |
| - | //argc -= optind; |
| - | if (opt & OPT_W) |
| - | bb_simple_error_msg("warning: option -W is ignored"); |
| - | if (opt & OPT_F) { |
| - | unescape_string_in_place(opt_F); |
| - | setvar_s(intvar[FS], opt_F); |
| - | } |
| - | while (list_v) { |
| - | if (!try_to_assign(llist_pop(&list_v))) |
| - | bb_show_usage(); |
| - | } |
| - | /* Parse all supplied programs */ |
| fnhash = hash_init(); | |
| ahash = hash_init(); | |
| - | while (list_f) { |
| - | int fd; |
| - | char *s; |
| - | g_progname = llist_pop(&list_f); |
| - | fd = xopen_stdin(g_progname); |
| - | s = xmalloc_read(fd, NULL); /* it's NUL-terminated */ |
| - | if (!s) |
| - | bb_perror_msg_and_die("read error from '%s'", g_progname); |
| - | close(fd); |
| - | parse_program(s); |
| - | free(s); |
| - | } |
| - | g_progname = "cmd. line"; |
| + | /* Cannot use getopt32: need to preserve order of -e / -f / -E / -i */ |
| + | while ((ch = getopt(argc, argv, OPTSTR_AWK)) >= 0) { |
| + | switch (ch) { |
| + | case 'F': |
| + | unescape_string_in_place(optarg); |
| + | setvar_s(intvar[FS], optarg); |
| + | break; |
| + | case 'v': |
| + | if (!try_to_assign(optarg)) |
| + | bb_show_usage(); |
| + | break; |
| + | //TODO: implement -i LIBRARY, it is easy-ish |
| + | case 'E': |
| + | case 'f': { |
| + | int fd; |
| + | char *s; |
| + | g_progname = optarg; |
| + | fd = xopen_stdin(g_progname); |
| + | s = xmalloc_read(fd, NULL); /* it's NUL-terminated */ |
| + | if (!s) |
| + | bb_perror_msg_and_die("read error from '%s'", g_progname); |
| + | close(fd); |
| + | parse_program(s); |
| + | free(s); |
| + | got_program = 1; |
| + | if (ch == 'E') { |
| + | got_program = 2; |
| + | goto stop_option_parsing; |
| + | } |
| + | break; |
| + | } |
| #if ENABLE_FEATURE_AWK_GNU_EXTENSIONS | |
| - | while (list_e) { |
| - | parse_program(llist_pop(&list_e)); |
| - | } |
| + | case 'e': |
| + | g_progname = "cmd. line"; |
| + | parse_program(optarg); |
| + | got_program = 1; |
| + | break; |
| #endif | |
| - | //FIXME: preserve order of -e and -f |
| - | //TODO: implement -i LIBRARY and -E FILE too, they are easy-ish |
| - | if (!(opt & (OPT_f | OPT_e))) { |
| + | case 'W': |
| + | bb_simple_error_msg("warning: option -W is ignored"); |
| + | break; |
| + | default: |
| + | //bb_error_msg("ch:%d", ch); |
| + | bb_show_usage(); |
| + | } |
| + | } |
| + | stop_option_parsing: |
| + | |
| + | argv += optind; |
| + | //argc -= optind; |
| + | |
| + | if (!got_program) { |
| if (!*argv) | |
| bb_show_usage(); | |
| + | g_progname = "cmd. line"; |
| parse_program(*argv++); | |
| } | |
| + | |
| /* Free unused parse structures */ | |
| //hash_free(fnhash); // ~250 bytes when empty, used only for function names | |
| //^^^^^^^^^^^^^^^^^ does not work, hash_clear() inside SEGVs | |