add back the include() function to awk (extracted from the old awx patch)
authorFelix Fietkau <nbd@openwrt.org>
Wed, 29 Oct 2008 20:02:52 +0000 (20:02 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Wed, 29 Oct 2008 20:02:52 +0000 (20:02 +0000)
SVN-Revision: 13081

package/busybox/patches/510-awk_include.patch [new file with mode: 0644]

diff --git a/package/busybox/patches/510-awk_include.patch b/package/busybox/patches/510-awk_include.patch
new file mode 100644 (file)
index 0000000..c2d3040
--- /dev/null
@@ -0,0 +1,212 @@
+--- a/editors/awk.c
++++ b/editors/awk.c
+@@ -53,9 +53,14 @@ typedef struct chain_s {
+ } chain;
+ /* Function */
++typedef var *(*awk_cfunc)(var *res, var *args, int nargs);
+ typedef struct func_s {
+       unsigned nargs;
++      enum { AWKFUNC, CFUNC } type;
++      union {
++              awk_cfunc cfunc;
+       struct chain_s body;
++      } x;
+ } func;
+ /* I/O stream */
+@@ -1395,7 +1400,8 @@ static void parse_program(char *p)
+                       next_token(TC_FUNCTION);
+                       g_pos++;
+                       f = newfunc(t_string);
+-                      f->body.first = NULL;
++                      f->type = AWKFUNC;
++                      f->x.body.first = NULL;
+                       f->nargs = 0;
+                       while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
+                               v = findvar(ahash, t_string);
+@@ -1404,7 +1410,7 @@ static void parse_program(char *p)
+                               if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
+                                       break;
+                       }
+-                      seq = &(f->body);
++                      seq = &(f->x.body);
+                       chain_group();
+                       clear_array(ahash);
+@@ -2367,7 +2373,8 @@ static var *evaluate(node *op, var *res)
+                       break;
+               case XC( OC_FUNC ):
+-                      if (!op->r.f->body.first)
++                      if ((op->r.f->type == AWKFUNC) &&
++                              !op->r.f->x.body.first)
+                               syntax_error(EMSG_UNDEF_FUNC);
+                       X.v = R.v = nvalloc(op->r.f->nargs+1);
+@@ -2384,7 +2391,10 @@ static var *evaluate(node *op, var *res)
+                       fnargs = X.v;
+                       L.s = g_progname;
+-                      res = evaluate(op->r.f->body.first, res);
++                      if (op->r.f->type == AWKFUNC)
++                              res = evaluate(op->r.f->x.body.first, res);
++                      else if (op->r.f->type == CFUNC)
++                              res = op->r.f->x.cfunc(res, fnargs, op->r.f->nargs);
+                       g_progname = L.s;
+                       nvfree(fnargs);
+@@ -2747,6 +2757,143 @@ static rstream *next_input_file(void)
+ #undef files_happen
+ }
++/* read the contents of an entire file */
++static char *get_file(const char *fname)
++{
++      FILE *F;
++      char *s = NULL;
++      int i, j, flen;
++
++      F = fopen(fname, "r");
++      if (!F) {
++              return NULL;
++      }
++
++      if (fseek(F, 0, SEEK_END) == 0) {
++              flen = ftell(F);
++              s = (char *)xmalloc(flen+4);
++              fseek(F, 0, SEEK_SET);
++              i = 1 + fread(s+1, 1, flen, F);
++      } else {
++              for (i=j=1; j>0; i+=j) {
++                      s = (char *)xrealloc(s, i+4096);
++                      j = fread(s+i, 1, 4094, F);
++              }
++      }
++
++      s[i] = '\0';
++      fclose(F);
++      return s;
++}
++
++
++/* parse_include():
++ *
++ * taken from parse_program from awk.c
++ * END{} is not parsed here, and BEGIN{} is executed immediately
++ */
++static void parse_include(char *p)
++{
++      uint32_t tclass;
++      chain *initseq = NULL;
++      chain tmp;
++      func *f;
++      var *v, *tv;
++
++      tv = nvalloc(1);
++      memset(&tmp, 0, sizeof(tmp));
++      g_pos = p;
++      t_lineno = 1;
++      while ((tclass = next_token(TC_EOF | TC_OPSEQ |
++                              TC_OPTERM | TC_BEGIN | TC_FUNCDECL)) != TC_EOF) {
++              if (tclass & TC_OPTERM)
++                      continue;
++
++              seq = &tmp;
++              if (tclass & TC_BEGIN) {
++                      initseq = xzalloc(sizeof(chain));
++                      seq = initseq;
++                      chain_group();
++              } else if (tclass & TC_FUNCDECL) {
++                      next_token(TC_FUNCTION);
++                      g_pos++;
++                      f = newfunc(t_string);
++                      f->type = AWKFUNC;
++                      f->x.body.first = NULL;
++                      f->nargs = 0;
++                      while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
++                              v = findvar(ahash, t_string);
++                              v->x.aidx = (f->nargs)++;
++
++                              if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
++                                      break;
++                      }
++                      seq = &(f->x.body);
++                      chain_group();
++                      clear_array(ahash);
++              }
++      }
++      if (initseq && initseq->first)
++              tv = evaluate(initseq->first, tv);
++      nvfree(tv);
++}
++
++
++/* include an awk file and run its BEGIN{} section */
++static xhash *includes = NULL;
++static void include_file(const char *filename)
++{
++      char *s;
++      var *v;
++      int oldlnr = g_lineno;
++      const char *oldprg = g_progname;
++
++      if (!includes)
++              includes = hash_init();
++
++      /* find out if the file has been included already */
++      v = findvar(includes, filename);
++      if (istrue(v))
++              return;
++      setvar_s(v, "1");
++
++      /* read include file */
++      s = get_file(filename);
++      if (!s) {
++              fprintf(stderr, "Could not open file.\n");
++              return;
++      }
++      g_lineno = 1;
++      g_progname = xstrdup(filename);
++      parse_include(s+1);
++      free(s);
++      g_lineno = oldlnr;
++      g_progname = oldprg;
++}
++
++static var *include(var *res, var *args, int nargs)
++{
++      const char *s;
++
++      nargs = nargs; /* shut up, gcc */
++      s = getvar_s(args);
++      if (s && (strlen(s) > 0))
++              include_file(s);
++
++      return res;
++}
++
++/* registers a global c function for the awk interpreter */
++static void register_cfunc(const char *name, awk_cfunc cfunc, int nargs)
++{
++      func *f;
++
++      f = newfunc(name);
++      f->type = CFUNC;
++      f->x.cfunc = cfunc;
++      f->nargs = nargs;
++}
++
+ int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+ int awk_main(int argc, char **argv)
+ {
+@@ -2812,6 +2959,9 @@ int awk_main(int argc, char **argv)
+                       *s1 = '=';
+               }
+       }
++
++      register_cfunc("include", include, 1);
++
+       opt_complementary = "v::f::"; /* -v and -f can occur multiple times */
+       opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, &opt_W);
+       argv += optind;