[package] busybox: Comcast uses option 150 for 6RD DHCP announcements, cover it
[openwrt/svn-archive/archive.git] / 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 @@ -70,9 +71,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 @@ -1453,7 +1459,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 @@ -1462,7 +1469,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 @@ -2547,7 +2554,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 @@ -2564,7 +2572,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 @@ -2942,6 +2953,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 @@ -3007,6 +3155,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;