mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 05:24:26 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			218 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| --- a/editors/awk.c
 | |
| +++ b/editors/awk.c
 | |
| @@ -1,3 +1,4 @@
 | |
| +
 | |
|  /* vi: set sw=4 ts=4: */
 | |
|  /*
 | |
|   * awk implementation for busybox
 | |
| @@ -81,9 +82,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 */
 | |
| @@ -1473,7 +1479,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);
 | |
| @@ -1482,7 +1489,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);
 | |
|  
 | |
| @@ -2580,7 +2587,8 @@ static var *evaluate(node *op, var *res)
 | |
|  			var *vbeg, *v;
 | |
|  			const char *sv_progname;
 | |
|  
 | |
| -			if (!op->r.f->body.first)
 | |
| +			if ((op->r.f->type == AWKFUNC) &&
 | |
| +				!op->r.f->x.body.first)
 | |
|  				syntax_error(EMSG_UNDEF_FUNC);
 | |
|  
 | |
|  			vbeg = v = nvalloc(op->r.f->nargs + 1);
 | |
| @@ -2597,7 +2605,10 @@ static var *evaluate(node *op, var *res)
 | |
|  			fnargs = vbeg;
 | |
|  			sv_progname = 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 = sv_progname;
 | |
|  			nvfree(fnargs);
 | |
| @@ -2991,6 +3002,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)
 | |
|  {
 | |
| @@ -3056,6 +3204,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;
 |