Root/package/busybox/patches/510-awk_include.patch

1--- a/editors/awk.c
2+++ b/editors/awk.c
3@@ -1,3 +1,4 @@
4+
5 /* vi: set sw=4 ts=4: */
6 /*
7  * awk implementation for busybox
8@@ -81,9 +82,14 @@ typedef struct chain_s {
9 } chain;
10 
11 /* Function */
12+typedef var *(*awk_cfunc)(var *res, var *args, int nargs);
13 typedef struct func_s {
14     unsigned nargs;
15+ enum { AWKFUNC, CFUNC } type;
16+ union {
17+ awk_cfunc cfunc;
18     struct chain_s body;
19+ } x;
20 } func;
21 
22 /* I/O stream */
23@@ -1473,7 +1479,8 @@ static void parse_program(char *p)
24             next_token(TC_FUNCTION);
25             g_pos++;
26             f = newfunc(t_string);
27- f->body.first = NULL;
28+ f->type = AWKFUNC;
29+ f->x.body.first = NULL;
30             f->nargs = 0;
31             while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
32                 v = findvar(ahash, t_string);
33@@ -1482,7 +1489,7 @@ static void parse_program(char *p)
34                 if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
35                     break;
36             }
37- seq = &f->body;
38+ seq = &f->x.body;
39             chain_group();
40             clear_array(ahash);
41 
42@@ -2580,7 +2587,8 @@ static var *evaluate(node *op, var *res)
43             var *vbeg, *v;
44             const char *sv_progname;
45 
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);
50 
51             vbeg = v = nvalloc(op->r.f->nargs + 1);
52@@ -2597,7 +2605,10 @@ static var *evaluate(node *op, var *res)
53             fnargs = vbeg;
54             sv_progname = g_progname;
55 
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);
61 
62             g_progname = sv_progname;
63             nvfree(fnargs);
64@@ -2991,6 +3002,143 @@ static rstream *next_input_file(void)
65 #undef files_happen
66 }
67 
68+/* read the contents of an entire file */
69+static char *get_file(const char *fname)
70+{
71+ FILE *F;
72+ char *s = NULL;
73+ int i, j, flen;
74+
75+ F = fopen(fname, "r");
76+ if (!F) {
77+ return NULL;
78+ }
79+
80+ if (fseek(F, 0, SEEK_END) == 0) {
81+ flen = ftell(F);
82+ s = (char *)xmalloc(flen+4);
83+ fseek(F, 0, SEEK_SET);
84+ i = 1 + fread(s+1, 1, flen, F);
85+ } else {
86+ for (i=j=1; j>0; i+=j) {
87+ s = (char *)xrealloc(s, i+4096);
88+ j = fread(s+i, 1, 4094, F);
89+ }
90+ }
91+
92+ s[i] = '\0';
93+ fclose(F);
94+ return s;
95+}
96+
97+
98+/* parse_include():
99+ *
100+ * taken from parse_program from awk.c
101+ * END{} is not parsed here, and BEGIN{} is executed immediately
102+ */
103+static void parse_include(char *p)
104+{
105+ uint32_t tclass;
106+ chain *initseq = NULL;
107+ chain tmp;
108+ func *f;
109+ var *v, *tv;
110+
111+ tv = nvalloc(1);
112+ memset(&tmp, 0, sizeof(tmp));
113+ g_pos = p;
114+ t_lineno = 1;
115+ while ((tclass = next_token(TC_EOF | TC_OPSEQ |
116+ TC_OPTERM | TC_BEGIN | TC_FUNCDECL)) != TC_EOF) {
117+ if (tclass & TC_OPTERM)
118+ continue;
119+
120+ seq = &tmp;
121+ if (tclass & TC_BEGIN) {
122+ initseq = xzalloc(sizeof(chain));
123+ seq = initseq;
124+ chain_group();
125+ } else if (tclass & TC_FUNCDECL) {
126+ next_token(TC_FUNCTION);
127+ g_pos++;
128+ f = newfunc(t_string);
129+ f->type = AWKFUNC;
130+ f->x.body.first = NULL;
131+ f->nargs = 0;
132+ while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
133+ v = findvar(ahash, t_string);
134+ v->x.aidx = (f->nargs)++;
135+
136+ if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
137+ break;
138+ }
139+ seq = &(f->x.body);
140+ chain_group();
141+ clear_array(ahash);
142+ }
143+ }
144+ if (initseq && initseq->first)
145+ tv = evaluate(initseq->first, tv);
146+ nvfree(tv);
147+}
148+
149+
150+/* include an awk file and run its BEGIN{} section */
151+static xhash *includes = NULL;
152+static void include_file(const char *filename)
153+{
154+ char *s;
155+ var *v;
156+ int oldlnr = g_lineno;
157+ const char *oldprg = g_progname;
158+
159+ if (!includes)
160+ includes = hash_init();
161+
162+ /* find out if the file has been included already */
163+ v = findvar(includes, filename);
164+ if (istrue(v))
165+ return;
166+ setvar_s(v, "1");
167+
168+ /* read include file */
169+ s = get_file(filename);
170+ if (!s) {
171+ fprintf(stderr, "Could not open file.\n");
172+ return;
173+ }
174+ g_lineno = 1;
175+ g_progname = xstrdup(filename);
176+ parse_include(s+1);
177+ free(s);
178+ g_lineno = oldlnr;
179+ g_progname = oldprg;
180+}
181+
182+static var *include(var *res, var *args, int nargs)
183+{
184+ const char *s;
185+
186+ nargs = nargs; /* shut up, gcc */
187+ s = getvar_s(args);
188+ if (s && (strlen(s) > 0))
189+ include_file(s);
190+
191+ return res;
192+}
193+
194+/* registers a global c function for the awk interpreter */
195+static void register_cfunc(const char *name, awk_cfunc cfunc, int nargs)
196+{
197+ func *f;
198+
199+ f = newfunc(name);
200+ f->type = CFUNC;
201+ f->x.cfunc = cfunc;
202+ f->nargs = nargs;
203+}
204+
205 int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
206 int awk_main(int argc, char **argv)
207 {
208@@ -3056,6 +3204,9 @@ int awk_main(int argc, char **argv)
209             *s1 = '=';
210         }
211     }
212+
213+ register_cfunc("include", include, 1);
214+
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);
217     argv += optind;
218

Archive Download this file



interactive