2013-11-12, Denys Vlasenko <[email protected]>:

>On Tue, Nov 5, 2013 at 12:55 PM, Sven-Göran Bergh
><[email protected]> wrote:
>>   Example: awk -f mylib.awk '{print myfunction($1);}' ...>
>+    g_progname = "cmd. line";
>+#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
>+    while (list_e) { /* -e */
>+        parse_program(llist_pop(&list_e));
>+    }
>+    if (AWK_PROG_DEFINED) /* -e or -f */
>+        argc++;
>+    if (*argv && access(*argv, F_OK)) /* not a file -> parse it */
>+        parse_program(*argv++);
>+    else if (!AWK_PROG_DEFINED) /* no program defined */
>+               bb_show_usage();
>+#else
>+    if (AWK_PROG_DEFINED) {
>         argc++;
>     } else { // no -f: take program from 1st parameter
>         if (!argc)
>             bb_show_usage();
>-        g_progname = "cmd. line";
>         parse_program(*argv++);
>     }
>-    if (opt & 0x8) // -W
>+#endif
>
>
>The above looks too complex. Can it be just:
>
>        g_progname = "cmd. line";
>#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
>        while (list_e) { /* -e */
>                parse_program(llist_pop(&list_e));
>        }
>#endif
>        if (!(opt & (OPT_f | OPT_e))) {
>                if (!*argv)
>                        bb_show_usage();
>                parse_program(*argv++);
>                argc++;
>        }

I agree, it is complex. I guess it does not need to be that user friendly, so a
simplified version is fine with me. However, the above code will not work. It
needs to be:

        g_progname = "cmd. line";
#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
        while (list_e) { /* -e */
                parse_program(llist_pop(&list_e));
        }
#endif
        if ((opt & (OPT_f | OPT_e))) {

                argc++;
        } else {
                if (!*argv)
                        bb_show_usage();
                parse_program(*argv++);
        }


>>+//config:        * simultaneous use of -f and an Awk program on the command 
>>line.
>>+//config:          This enables the use of awk library files.
>>+//config:           Ex: awk -f mylib.awk '{print myfunction($1);}' ...
>
>This does not seem to work with GNU Awk 4.0.1:
>
>$ awk -f EMPTYFILE 'BEGIN {print "hello";}'
>$ awk -f EMPTYFILE -e 'BEGIN {print "hello";}'
>hello
>$
>
>In the first case, it seems that 'BEGIN {print "hello";}'
>is taken as a _filename_, not _awk program_.

Indeed, you are right. I do not know why I thought the first form was accepted 
by
gawk. My mistake. This makes the simplified code above even more relevant.

A new patch with theses changes is attached.

Brgds
/S-G
commit 8d17ea7c5468d6a4f456e0fde5e69bd2978e91fe
Author: Sven-Göran Bergh <[email protected]>
Date:   Thu Nov 14 16:33:27 2013 +0100

    awk: GNU extension -e
    
    Adds the extension -e to awk.
    This enables the use of awk library files that are pulled in
    with -f, while the "main" program is defined on the command line.
    Ex: awk -f mylib.awk -e '{print myfunction($1);}' ...

    function                                             old     new   delta
    awk_main                                            1054    1104     +50
    .rodata                                           149787  149799     +12
    packed_usage                                       29128   29135      +7
    ------------------------------------------------------------------------------
    (add/remove: 0/0 grow/shrink: 3/0 up/down: 69/0)               Total: 69 bytes

    
    Signed-off-by: Sven-Göran Bergh <[email protected]>

diff --git a/editors/Config.src b/editors/Config.src
index af1e1de..d3bd46e 100644
--- a/editors/Config.src
+++ b/editors/Config.src
@@ -7,21 +7,6 @@ menu "Editors"
 
 INSERT
 
-config AWK
-	bool "awk"
-	default y
-	help
-	  Awk is used as a pattern scanning and processing language. This is
-	  the BusyBox implementation of that programming language.
-
-config FEATURE_AWK_LIBM
-	bool "Enable math functions (requires libm)"
-	default y
-	depends on AWK
-	help
-	  Enable math functions of the Awk programming language.
-	  NOTE: This will require libm to be present for linking.
-
 config CMP
 	bool "cmp"
 	default y
diff --git a/editors/Kbuild.src b/editors/Kbuild.src
index 8888cba..15d7a4c 100644
--- a/editors/Kbuild.src
+++ b/editors/Kbuild.src
@@ -7,7 +7,6 @@
 lib-y:=
 
 INSERT
-lib-$(CONFIG_AWK)       += awk.o
 lib-$(CONFIG_CMP)       += cmp.o
 lib-$(CONFIG_DIFF)      += diff.o
 lib-$(CONFIG_ED)        += ed.o
diff --git a/editors/awk.c b/editors/awk.c
index 8848d94..4b350de 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -7,12 +7,45 @@
  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
 
+//applet:IF_AWK(APPLET_NOEXEC(awk, awk, BB_DIR_USR_BIN, BB_SUID_DROP, awk))
+
+//config:config AWK
+//config:	bool "awk"
+//config:	default y
+//config:	help
+//config:	  Awk is used as a pattern scanning and processing language. This is
+//config:	  the BusyBox implementation of that programming language.
+//config:
+//config:config FEATURE_AWK_LIBM
+//config:	bool "Enable math functions (requires libm)"
+//config:	default y
+//config:	depends on AWK
+//config:	help
+//config:	  Enable math functions of the Awk programming language.
+//config:	  NOTE: This will require libm to be present for linking.
+//config:
+//config:config FEATURE_AWK_GNU_EXTENSIONS
+//config:	bool "Enable a few GNU extensions"
+//config:	default y
+//config:	depends on AWK
+//config:	help
+//config:	  Adds the extension -e to awk.
+//config:	  This enables the use of awk library files that are pulled in
+//config:	  with -f, while the "main" program is defined on the command line.
+//config:	    Ex: awk -f mylib.awk -e '{print myfunction($1);}' ...
+//config:
+
+//kbuild:lib-$(CONFIG_AWK) += awk.o
+
 //usage:#define awk_trivial_usage
 //usage:       "[OPTIONS] [AWK_PROGRAM] [FILE]..."
 //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:	IF_FEATURE_AWK_GNU_EXTENSIONS(
+//usage:     "\n	-e AWK_PROGRAM"
+//usage:	)
 
 #include "libbb.h"
 #include "xregex.h"
@@ -38,6 +71,25 @@
 #endif
 
 
+#define OPTSTR_AWK \
+	"F:v:f:" \
+	IF_FEATURE_AWK_GNU_EXTENSIONS("e:") \
+	"W:"
+#define OPTCOMPLSTR_AWK \
+	"v::f::" \
+	IF_FEATURE_AWK_GNU_EXTENSIONS("e::")
+enum {
+	OPTBIT_F,	/* define field separator */
+	OPTBIT_v,	/* define variable */
+	OPTBIT_f,	/* pull in awk program from file */
+	IF_FEATURE_AWK_GNU_EXTENSIONS(OPTBIT_e,) /* -e AWK_PROGRAM */
+	OPTBIT_W,	/* -W ignored */
+	OPT_F = 1 << OPTBIT_F,
+	OPT_v = 1 << OPTBIT_v,
+	OPT_f = 1 << OPTBIT_f,
+	OPT_e = IF_FEATURE_AWK_GNU_EXTENSIONS((1 << OPTBIT_e)) + 0,
+	OPT_W = 1 << OPTBIT_W
+};
 
 #define	MAXVARFMT       240
 #define	MINNVBLOCK      64
@@ -3087,6 +3139,9 @@ int awk_main(int argc, char **argv)
 	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 i, j;
 	var *v;
 	var tv;
@@ -3145,11 +3200,11 @@ int awk_main(int argc, char **argv)
 			*s1 = '=';
 		}
 	}
-	opt_complementary = "v::f::"; /* -v and -f can occur multiple times */
-	opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, NULL);
+	opt_complementary = OPTCOMPLSTR_AWK;
+	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 & 0x1) { /* -F */
+	if (opt & OPT_F) { /* -F */
 		unescape_string_in_place(opt_F);
 		setvar_s(intvar[FS], opt_F);
 	}
@@ -3157,31 +3212,36 @@ int awk_main(int argc, char **argv)
 		if (!is_assignment(llist_pop(&list_v)))
 			bb_show_usage();
 	}
-	if (list_f) { /* -f */
-		do {
-			char *s = NULL;
-			FILE *from_file;
-
-			g_progname = llist_pop(&list_f);
-			from_file = xfopen_stdin(g_progname);
-			/* one byte is reserved for some trick in next_token */
-			for (i = j = 1; j > 0; i += j) {
-				s = xrealloc(s, i + 4096);
-				j = fread(s + i, 1, 4094, from_file);
-			}
-			s[i] = '\0';
-			fclose(from_file);
-			parse_program(s + 1);
-			free(s);
-		} while (list_f);
+	while (list_f) { /* -f */
+		char *s = NULL;
+		FILE *from_file;
+
+		g_progname = llist_pop(&list_f);
+		from_file = xfopen_stdin(g_progname);
+		/* one byte is reserved for some trick in next_token */
+		for (i = j = 1; j > 0; i += j) {
+			s = xrealloc(s, i + 4096);
+			j = fread(s + i, 1, 4094, from_file);
+		}
+		s[i] = '\0';
+		fclose(from_file);
+		parse_program(s + 1);
+		free(s);
+	}
+	g_progname = "cmd. line";
+#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
+	while (list_e) { /* -e */
+		parse_program(llist_pop(&list_e));
+	}
+#endif
+	if (opt & (OPT_f | OPT_e)) {
 		argc++;
-	} else { // no -f: take program from 1st parameter
-		if (!argc)
+	} else { // no -f nor -e: take program from 1st parameter
+		if (!*argv)
 			bb_show_usage();
-		g_progname = "cmd. line";
 		parse_program(*argv++);
 	}
-	if (opt & 0x8) // -W
+	if (opt & OPT_W) // -W
 		bb_error_msg("warning: option -W is ignored");
 
 	/* fill in ARGV array */
diff --git a/include/applets.src.h b/include/applets.src.h
index 3a47e15..ac8f180 100644
--- a/include/applets.src.h
+++ b/include/applets.src.h
@@ -82,7 +82,6 @@ IF_ADJTIMEX(APPLET(adjtimex, BB_DIR_SBIN, BB_SUID_DROP))
 IF_AR(APPLET(ar, BB_DIR_USR_BIN, BB_SUID_DROP))
 IF_ARP(APPLET(arp, BB_DIR_SBIN, BB_SUID_DROP))
 IF_ARPING(APPLET(arping, BB_DIR_USR_SBIN, BB_SUID_DROP))
-IF_AWK(APPLET_NOEXEC(awk, awk, BB_DIR_USR_BIN, BB_SUID_DROP, awk))
 IF_BASENAME(APPLET_NOFORK(basename, basename, BB_DIR_USR_BIN, BB_SUID_DROP, basename))
 IF_BBCONFIG(APPLET(bbconfig, BB_DIR_BIN, BB_SUID_DROP))
 IF_BEEP(APPLET(beep, BB_DIR_USR_BIN, BB_SUID_DROP))
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to