aboutsummaryrefslogtreecommitdiff
path: root/editors/awk.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2023-10-02 15:24:06 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2023-10-02 15:24:06 +0200
commit92ab29fcf04bc3ff3d3ad897f1c2463d8b8d1410 (patch)
treee55cbae26eec69ff6bc05ac73ed892f14c71a8f0 /editors/awk.c
parent6d22c9abc29d43e919e819ff004fcd84a90de60b (diff)
downloadbusybox-w32-92ab29fcf04bc3ff3d3ad897f1c2463d8b8d1410.tar.gz
busybox-w32-92ab29fcf04bc3ff3d3ad897f1c2463d8b8d1410.tar.bz2
busybox-w32-92ab29fcf04bc3ff3d3ad897f1c2463d8b8d1410.zip
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>
Diffstat (limited to '')
-rw-r--r--editors/awk.c113
1 files changed, 65 insertions, 48 deletions
diff --git a/editors/awk.c b/editors/awk.c
index efdff2778..bc95c4155 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -40,7 +40,7 @@
40//usage:#define awk_full_usage "\n\n" 40//usage:#define awk_full_usage "\n\n"
41//usage: " -v VAR=VAL Set variable" 41//usage: " -v VAR=VAL Set variable"
42//usage: "\n -F SEP Use SEP as field separator" 42//usage: "\n -F SEP Use SEP as field separator"
43//usage: "\n -f FILE Read program from FILE" 43//usage: "\n -f/-E FILE Read program from FILE"
44//usage: IF_FEATURE_AWK_GNU_EXTENSIONS( 44//usage: IF_FEATURE_AWK_GNU_EXTENSIONS(
45//usage: "\n -e AWK_PROGRAM" 45//usage: "\n -e AWK_PROGRAM"
46//usage: ) 46//usage: )
@@ -76,8 +76,8 @@
76 * 1: -argz 76 * 1: -argz
77 */ 77 */
78#define OPTSTR_AWK "+" \ 78#define OPTSTR_AWK "+" \
79 "F:v:*f:*" \ 79 "F:v:f:" \
80 IF_FEATURE_AWK_GNU_EXTENSIONS("e:*") \ 80 IF_FEATURE_AWK_GNU_EXTENSIONS("e:E:") \
81 "W:" 81 "W:"
82enum { 82enum {
83 OPTBIT_F, /* define field separator */ 83 OPTBIT_F, /* define field separator */
@@ -560,6 +560,7 @@ struct globals {
560 var *Fields; 560 var *Fields;
561 char *g_pos; 561 char *g_pos;
562 char g_saved_ch; 562 char g_saved_ch;
563 smallint got_program;
563 smallint icase; 564 smallint icase;
564 smallint exiting; 565 smallint exiting;
565 smallint nextrec; 566 smallint nextrec;
@@ -635,6 +636,7 @@ struct globals2 {
635#define Fields (G1.Fields ) 636#define Fields (G1.Fields )
636#define g_pos (G1.g_pos ) 637#define g_pos (G1.g_pos )
637#define g_saved_ch (G1.g_saved_ch ) 638#define g_saved_ch (G1.g_saved_ch )
639#define got_program (G1.got_program )
638#define icase (G1.icase ) 640#define icase (G1.icase )
639#define exiting (G1.exiting ) 641#define exiting (G1.exiting )
640#define nextrec (G1.nextrec ) 642#define nextrec (G1.nextrec )
@@ -2899,11 +2901,13 @@ static int next_input_file(void)
2899 } 2901 }
2900 fname = getvar_s(findvar(iamarray(intvar[ARGV]), utoa(argind))); 2902 fname = getvar_s(findvar(iamarray(intvar[ARGV]), utoa(argind)));
2901 if (fname && *fname) { 2903 if (fname && *fname) {
2902 /* "If a filename on the command line has the form 2904 if (got_program != 2) { /* there was no -E option */
2903 * var=val it is treated as a variable assignment" 2905 /* "If a filename on the command line has the form
2904 */ 2906 * var=val it is treated as a variable assignment"
2905 if (try_to_assign(fname)) 2907 */
2906 continue; 2908 if (try_to_assign(fname))
2909 continue;
2910 }
2907 iF.F = xfopen_stdin(fname); 2911 iF.F = xfopen_stdin(fname);
2908 setvar_i(intvar[ARGIND], argind); 2912 setvar_i(intvar[ARGIND], argind);
2909 break; 2913 break;
@@ -3659,13 +3663,7 @@ static int awk_exit(void)
3659int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 3663int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
3660int awk_main(int argc UNUSED_PARAM, char **argv) 3664int awk_main(int argc UNUSED_PARAM, char **argv)
3661{ 3665{
3662 unsigned opt; 3666 int ch;
3663 char *opt_F;
3664 llist_t *list_v = NULL;
3665 llist_t *list_f = NULL;
3666#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
3667 llist_t *list_e = NULL;
3668#endif
3669 int i; 3667 int i;
3670 3668
3671 INIT_G(); 3669 INIT_G();
@@ -3714,49 +3712,68 @@ int awk_main(int argc UNUSED_PARAM, char **argv)
3714 } 3712 }
3715 } 3713 }
3716 } 3714 }
3717 opt = getopt32(argv, OPTSTR_AWK, &opt_F, &list_v, &list_f, IF_FEATURE_AWK_GNU_EXTENSIONS(&list_e,) NULL);
3718 argv += optind;
3719 //argc -= optind;
3720 if (opt & OPT_W)
3721 bb_simple_error_msg("warning: option -W is ignored");
3722 if (opt & OPT_F) {
3723 unescape_string_in_place(opt_F);
3724 setvar_s(intvar[FS], opt_F);
3725 }
3726 while (list_v) {
3727 if (!try_to_assign(llist_pop(&list_v)))
3728 bb_show_usage();
3729 }
3730 3715
3731 /* Parse all supplied programs */
3732 fnhash = hash_init(); 3716 fnhash = hash_init();
3733 ahash = hash_init(); 3717 ahash = hash_init();
3734 while (list_f) {
3735 int fd;
3736 char *s;
3737 3718
3738 g_progname = llist_pop(&list_f); 3719 /* Cannot use getopt32: need to preserve order of -e / -f / -E / -i */
3739 fd = xopen_stdin(g_progname); 3720 while ((ch = getopt(argc, argv, OPTSTR_AWK)) >= 0) {
3740 s = xmalloc_read(fd, NULL); /* it's NUL-terminated */ 3721 switch (ch) {
3741 if (!s) 3722 case 'F':
3742 bb_perror_msg_and_die("read error from '%s'", g_progname); 3723 unescape_string_in_place(optarg);
3743 close(fd); 3724 setvar_s(intvar[FS], optarg);
3744 parse_program(s); 3725 break;
3745 free(s); 3726 case 'v':
3746 } 3727 if (!try_to_assign(optarg))
3747 g_progname = "cmd. line"; 3728 bb_show_usage();
3729 break;
3730//TODO: implement -i LIBRARY, it is easy-ish
3731 case 'E':
3732 case 'f': {
3733 int fd;
3734 char *s;
3735 g_progname = optarg;
3736 fd = xopen_stdin(g_progname);
3737 s = xmalloc_read(fd, NULL); /* it's NUL-terminated */
3738 if (!s)
3739 bb_perror_msg_and_die("read error from '%s'", g_progname);
3740 close(fd);
3741 parse_program(s);
3742 free(s);
3743 got_program = 1;
3744 if (ch == 'E') {
3745 got_program = 2;
3746 goto stop_option_parsing;
3747 }
3748 break;
3749 }
3748#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS 3750#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
3749 while (list_e) { 3751 case 'e':
3750 parse_program(llist_pop(&list_e)); 3752 g_progname = "cmd. line";
3751 } 3753 parse_program(optarg);
3754 got_program = 1;
3755 break;
3752#endif 3756#endif
3753//FIXME: preserve order of -e and -f 3757 case 'W':
3754//TODO: implement -i LIBRARY and -E FILE too, they are easy-ish 3758 bb_simple_error_msg("warning: option -W is ignored");
3755 if (!(opt & (OPT_f | OPT_e))) { 3759 break;
3760 default:
3761//bb_error_msg("ch:%d", ch);
3762 bb_show_usage();
3763 }
3764 }
3765 stop_option_parsing:
3766
3767 argv += optind;
3768 //argc -= optind;
3769
3770 if (!got_program) {
3756 if (!*argv) 3771 if (!*argv)
3757 bb_show_usage(); 3772 bb_show_usage();
3773 g_progname = "cmd. line";
3758 parse_program(*argv++); 3774 parse_program(*argv++);
3759 } 3775 }
3776
3760 /* Free unused parse structures */ 3777 /* Free unused parse structures */
3761 //hash_free(fnhash); // ~250 bytes when empty, used only for function names 3778 //hash_free(fnhash); // ~250 bytes when empty, used only for function names
3762 //^^^^^^^^^^^^^^^^^ does not work, hash_clear() inside SEGVs 3779 //^^^^^^^^^^^^^^^^^ does not work, hash_clear() inside SEGVs