|
|
@@ -1,217 +0,0 @@
|
|
|
---- 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;
|