5 /* vi: set sw=4 ts=4: */
7 * awk implementation for busybox
8 @@ -70,9 +71,14 @@ typedef struct chain_s {
12 +typedef var *(*awk_cfunc)(var *res, var *args, int nargs);
13 typedef struct func_s {
15 + enum { AWKFUNC, CFUNC } type;
23 @@ -1453,7 +1459,8 @@ static void parse_program(char *p)
24 next_token(TC_FUNCTION);
26 f = newfunc(t_string);
27 - f->body.first = NULL;
29 + f->x.body.first = NULL;
31 while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
32 v = findvar(ahash, t_string);
33 @@ -1462,7 +1469,7 @@ static void parse_program(char *p)
34 if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
42 @@ -2547,7 +2554,8 @@ static var *evaluate(node *op, var *res)
44 const char *sv_progname;
46 - if (!op->r.f->body.first)
47 + if ((op->r.f->type == AWKFUNC) &&
48 + !op->r.f->x.body.first)
49 syntax_error(EMSG_UNDEF_FUNC);
51 vbeg = v = nvalloc(op->r.f->nargs + 1);
52 @@ -2564,7 +2572,10 @@ static var *evaluate(node *op, var *res)
54 sv_progname = g_progname;
56 - res = evaluate(op->r.f->body.first, res);
57 + if (op->r.f->type == AWKFUNC)
58 + res = evaluate(op->r.f->x.body.first, res);
59 + else if (op->r.f->type == CFUNC)
60 + res = op->r.f->x.cfunc(res, fnargs, op->r.f->nargs);
62 g_progname = sv_progname;
64 @@ -2942,6 +2953,143 @@ static rstream *next_input_file(void)
68 +/* read the contents of an entire file */
69 +static char *get_file(const char *fname)
75 + F = fopen(fname, "r");
80 + if (fseek(F, 0, SEEK_END) == 0) {
82 + s = (char *)xmalloc(flen+4);
83 + fseek(F, 0, SEEK_SET);
84 + i = 1 + fread(s+1, 1, flen, F);
86 + for (i=j=1; j>0; i+=j) {
87 + s = (char *)xrealloc(s, i+4096);
88 + j = fread(s+i, 1, 4094, F);
100 + * taken from parse_program from awk.c
101 + * END{} is not parsed here, and BEGIN{} is executed immediately
103 +static void parse_include(char *p)
106 + chain *initseq = NULL;
112 + memset(&tmp, 0, sizeof(tmp));
115 + while ((tclass = next_token(TC_EOF | TC_OPSEQ |
116 + TC_OPTERM | TC_BEGIN | TC_FUNCDECL)) != TC_EOF) {
117 + if (tclass & TC_OPTERM)
121 + if (tclass & TC_BEGIN) {
122 + initseq = xzalloc(sizeof(chain));
125 + } else if (tclass & TC_FUNCDECL) {
126 + next_token(TC_FUNCTION);
128 + f = newfunc(t_string);
130 + f->x.body.first = NULL;
132 + while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
133 + v = findvar(ahash, t_string);
134 + v->x.aidx = (f->nargs)++;
136 + if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
139 + seq = &(f->x.body);
141 + clear_array(ahash);
144 + if (initseq && initseq->first)
145 + tv = evaluate(initseq->first, tv);
150 +/* include an awk file and run its BEGIN{} section */
151 +static xhash *includes = NULL;
152 +static void include_file(const char *filename)
156 + int oldlnr = g_lineno;
157 + const char *oldprg = g_progname;
160 + includes = hash_init();
162 + /* find out if the file has been included already */
163 + v = findvar(includes, filename);
168 + /* read include file */
169 + s = get_file(filename);
171 + fprintf(stderr, "Could not open file.\n");
175 + g_progname = xstrdup(filename);
176 + parse_include(s+1);
179 + g_progname = oldprg;
182 +static var *include(var *res, var *args, int nargs)
186 + nargs = nargs; /* shut up, gcc */
187 + s = getvar_s(args);
188 + if (s && (strlen(s) > 0))
194 +/* registers a global c function for the awk interpreter */
195 +static void register_cfunc(const char *name, awk_cfunc cfunc, int nargs)
201 + f->x.cfunc = cfunc;
205 int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
206 int awk_main(int argc, char **argv)
208 @@ -3007,6 +3155,9 @@ int awk_main(int argc, char **argv)
213 + register_cfunc("include", include, 1);
215 opt_complementary = "v::f::"; /* -v and -f can occur multiple times */
216 opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, &opt_W);