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

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

Archive Download this file



interactive