This patch adds two GNU extensions to awk. In essence, it allows -f to
be mixed with programs defined on the command line, with or without -e.

I know this is breaks POSIX and is a GNU extension, but it is really
convenient, especially when you want to organize awk functions into
libraries. Thus, it is controlled by FEATURE_AWK_GNU_EXTENSIONS.


Brgds
/S-G

  FEATURE_AWK_GNU_EXTENSIONS
  Add the extension -e to awk.
  Add the ability to mix -f and command line program definitions.
  This enables the use of awk library files that are pulled in
  with -f, while the "main" program is defined on the command line.
  
  Example: awk -f mylib.awk '{print myfunction($1);}' ...
  
  With FEATURE_AWK_GNU_EXTENSIONS:
  function                                             old     new   delta
  awk_main                                            1054    1127     +73
  .rodata                                           149787  149799     +12
  packed_usage                                       29128   29135      +7
  ------------------------------------------------------------------------------
  (add/remove: 0/0 grow/shrink: 3/0 up/down: 92/0)               Total: 92 bytes
  
  Without FEATURE_AWK_GNU_EXTENSIONS:
  function                                             old     new   delta
  awk_main                                            1054    1057      +3
  ------------------------------------------------------------------------------
  (add/remove: 0/0 grow/shrink: 1/0 up/down: 3/0)                 Total: 3 bytes
  
  Signed-off-by: Sven-Göran Bergh <[email protected]>

---

Patch attached
commit 95bf1105243887b105ddefc1c61870ce6a2aebea
Author: Sven-Göran Bergh <[email protected]>
Date:   Tue Nov 5 12:27:00 2013 +0100

    awk: GNU extension -e
    
    FEATURE_AWK_GNU_EXTENSIONS
    Add the extension -e to awk.
    Add the ability to mix -f and command line program definitions.
    This enables the use of awk library files that are pulled in
    with -f, while the "main" program is defined on the command line.
    
    Example: awk -f mylib.awk '{print myfunction($1);}' ...
    
    With FEATURE_AWK_GNU_EXTENSIONS:
    function                                             old     new   delta
    awk_main                                            1054    1127     +73
    .rodata                                           149787  149799     +12
    packed_usage                                       29128   29135      +7
    ------------------------------------------------------------------------------
    (add/remove: 0/0 grow/shrink: 3/0 up/down: 92/0)               Total: 92 bytes
    
    Without FEATURE_AWK_GNU_EXTENSIONS:
    function                                             old     new   delta
    awk_main                                            1054    1057      +3
    ------------------------------------------------------------------------------
    (add/remove: 0/0 grow/shrink: 1/0 up/down: 3/0)                 Total: 3 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..f7f7615 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -7,12 +7,46 @@
  * 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:	  Enable a few features from gawk:
+//config:	  * command line option -e AWK_PROGRAM
+//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);}' ...
+//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 +72,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
@@ -3083,10 +3136,14 @@ static rstream *next_input_file(void)
 int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int awk_main(int argc, char **argv)
 {
+#define AWK_PROG_DEFINED (opt & (OPT_f | OPT_e)) /* -e or -f */
 	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 i, j;
 	var *v;
 	var tv;
@@ -3145,11 +3202,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 +3214,43 @@ 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));
+	}
+	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
+	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