lantiq: Tune the XWAY subtarget cflags
[openwrt.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 @@ -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;