diff options
Diffstat (limited to 'package/busybox/patches/510-awk_include.patch')
-rw-r--r-- | package/busybox/patches/510-awk_include.patch | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/package/busybox/patches/510-awk_include.patch b/package/busybox/patches/510-awk_include.patch new file mode 100644 index 0000000000..c2d3040fc1 --- /dev/null +++ b/package/busybox/patches/510-awk_include.patch @@ -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; |