summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko2023-10-02 15:24:06 +0200
committerDenys Vlasenko2023-10-02 15:24:06 +0200
commit92ab29fcf04bc3ff3d3ad897f1c2463d8b8d1410 (patch)
treee55cbae26eec69ff6bc05ac73ed892f14c71a8f0
parent6d22c9abc29d43e919e819ff004fcd84a90de60b (diff)
downloadbusybox-92ab29fcf04bc3ff3d3ad897f1c2463d8b8d1410.zip
busybox-92ab29fcf04bc3ff3d3ad897f1c2463d8b8d1410.tar.gz
awk: implement -E; do not reorder -f and -e
function old new delta awk_main 843 891 +48 next_input_file 243 261 +18 packed_usage 34631 34638 +7 .rodata 105391 105390 -1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/1 up/down: 73/-1) Total: 72 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--editors/awk.c113
1 files changed, 65 insertions, 48 deletions
diff --git a/editors/awk.c b/editors/awk.c
index efdff27..bc95c41 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -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