eda5beee9dc1a57b7bd8081245d6c141477158c1
[openwrt/svn-archive/archive.git] / 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 @@ -1424,7 +1429,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 @@ -1433,7 +1439,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 @@ -2446,7 +2452,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 @@ -2463,7 +2470,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 @@ -2829,6 +2839,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 @@ -2894,6 +3041,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;