diff options
Diffstat (limited to 'package')
| -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 000000000..c2d3040fc --- /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; | 
