| | varnish-cache/lib/libvcc/vcc_vmod_sym.c |
0 |
|
/*- |
1 |
|
* Copyright (c) 2010-2015 Varnish Software AS |
2 |
|
* All rights reserved. |
3 |
|
* |
4 |
|
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk> |
5 |
|
* |
6 |
|
* SPDX-License-Identifier: BSD-2-Clause |
7 |
|
* |
8 |
167400 |
* Redistribution and use in source and binary forms, with or without |
9 |
167400 |
* modification, are permitted provided that the following conditions |
10 |
167400 |
* are met: |
11 |
167400 |
* 1. Redistributions of source code must retain the above copyright |
12 |
167400 |
* notice, this list of conditions and the following disclaimer. |
13 |
167400 |
* 2. Redistributions in binary form must reproduce the above copyright |
14 |
167400 |
* notice, this list of conditions and the following disclaimer in the |
15 |
167400 |
* documentation and/or other materials provided with the distribution. |
16 |
167400 |
* |
17 |
167400 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
18 |
167400 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
19 |
167400 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
20 |
167400 |
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE |
21 |
167400 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
22 |
167400 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
23 |
167400 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 |
167400 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
25 |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
26 |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 |
|
* SUCH DAMAGE. |
28 |
|
* |
29 |
|
* Turn vmod JSON spec into symbols |
30 |
|
* |
31 |
|
*/ |
32 |
|
|
33 |
|
#include "config.h" |
34 |
|
|
35 |
|
#include <stdlib.h> |
36 |
|
#include <string.h> |
37 |
|
|
38 |
|
#include "vcc_compile.h" |
39 |
|
|
40 |
|
#include "libvcc.h" |
41 |
|
#include "vjsn.h" |
42 |
|
|
43 |
|
#include "vcc_vmod.h" |
44 |
|
|
45 |
|
struct vmod_obj { |
46 |
|
unsigned magic; |
47 |
|
#define VMOD_OBJ_MAGIC 0x349885f8 |
48 |
|
char *name; |
49 |
|
struct type type[1]; |
50 |
|
VTAILQ_ENTRY(vmod_obj) list; |
51 |
|
}; |
52 |
|
|
53 |
|
static void |
54 |
57600 |
vcc_VmodObject(struct vcc *tl, struct symbol *sym) |
55 |
|
{ |
56 |
|
struct vmod_obj *obj; |
57 |
|
struct vsb *buf; |
58 |
|
|
59 |
57600 |
buf = VSB_new_auto(); |
60 |
57600 |
AN(buf); |
61 |
|
|
62 |
57600 |
VSB_printf(buf, "%s.%s", sym->vmod_name, sym->name); |
63 |
57600 |
AZ(VSB_finish(buf)); |
64 |
|
|
65 |
57600 |
ALLOC_OBJ(obj, VMOD_OBJ_MAGIC); |
66 |
57600 |
AN(obj); |
67 |
57600 |
REPLACE(obj->name, VSB_data(buf)); |
68 |
|
|
69 |
57600 |
INIT_OBJ(obj->type, TYPE_MAGIC); |
70 |
57600 |
obj->type->name = obj->name; |
71 |
57600 |
sym->type = obj->type; |
72 |
57600 |
VTAILQ_INSERT_TAIL(&tl->vmod_objects, obj, list); |
73 |
57600 |
VSB_destroy(&buf); |
74 |
57600 |
} |
75 |
|
|
76 |
|
static void |
77 |
5600 |
alias_sym(struct vcc *tl, const struct symbol *psym, const struct vjsn_val *v) |
78 |
|
{ |
79 |
5600 |
char *alias = NULL, *func = NULL; |
80 |
|
struct symbol *sym; |
81 |
|
struct vsb *buf; |
82 |
|
|
83 |
5600 |
buf = VSB_new_auto(); |
84 |
5600 |
AN(buf); |
85 |
|
|
86 |
5600 |
VCC_SymName(buf, psym); |
87 |
5600 |
VSB_printf(buf, ".%s", v->value); |
88 |
5600 |
AZ(VSB_finish(buf)); |
89 |
5600 |
REPLACE(alias, VSB_data(buf)); |
90 |
|
|
91 |
5600 |
v = VTAILQ_NEXT(v, list); |
92 |
5600 |
assert(vjsn_is_string(v)); |
93 |
|
|
94 |
5600 |
VSB_clear(buf); |
95 |
5600 |
VCC_SymName(buf, psym); |
96 |
5600 |
VSB_printf(buf, ".%s", v->value); |
97 |
5600 |
AZ(VSB_finish(buf)); |
98 |
5600 |
REPLACE(func, VSB_data(buf)); |
99 |
|
|
100 |
5600 |
sym = VCC_MkSymAlias(tl, alias, func); |
101 |
5600 |
AN(sym); |
102 |
5600 |
assert(sym->kind == SYM_FUNC || sym->kind == SYM_METHOD); |
103 |
5600 |
VSB_destroy(&buf); |
104 |
5600 |
free(alias); |
105 |
5600 |
free(func); |
106 |
5600 |
} |
107 |
|
|
108 |
|
static void |
109 |
822120 |
func_restrict(struct vcc *tl, struct symbol *sym, vcc_kind_t kind, const struct vjsn_val *v) |
110 |
|
{ |
111 |
|
struct vjsn_val *vv; |
112 |
|
|
113 |
822120 |
AN(v); |
114 |
822120 |
AN(sym); |
115 |
|
|
116 |
822120 |
if (kind != SYM_FUNC && kind != SYM_METHOD) |
117 |
0 |
return; |
118 |
|
|
119 |
822120 |
v = VTAILQ_NEXT(v, list); |
120 |
822120 |
if (!v || !vjsn_is_array(v)) |
121 |
60640 |
return; |
122 |
761480 |
vv = VTAILQ_FIRST(&v->children); |
123 |
761480 |
AN(vv); |
124 |
761480 |
assert(vjsn_is_string(vv)); |
125 |
761480 |
if (strcmp(vv->value, "$RESTRICT")) |
126 |
684160 |
return; |
127 |
77320 |
vv = VTAILQ_NEXT(vv, list); |
128 |
77320 |
AN(vv); |
129 |
77320 |
assert(vjsn_is_array(vv)); |
130 |
77320 |
sym->r_methods = 0; |
131 |
77320 |
vv = VTAILQ_FIRST(&vv->children); |
132 |
|
unsigned s; |
133 |
244680 |
while (vv) { |
134 |
167400 |
s = 0; |
135 |
|
#define VCL_CTX(l,H) \ |
136 |
|
if (strcmp(vv->value, #l) == 0) s = VCL_MET_##H; |
137 |
|
#include "tbl/vcl_context.h" |
138 |
167400 |
if (!s) { |
139 |
40 |
VSB_printf(tl->sb, "Error in vmod \"%s\", invalid scope for $Restrict: %s\n",sym->vmod_name, vv->value); |
140 |
40 |
tl->err = 1; |
141 |
40 |
break; |
142 |
|
} |
143 |
|
sym->r_methods |= s; |
144 |
|
vv = VTAILQ_NEXT(vv,list); |
145 |
|
} |
146 |
822120 |
} |
147 |
|
|
148 |
|
static void |
149 |
885320 |
func_sym(struct vcc *tl, vcc_kind_t kind, const struct symbol *psym, |
150 |
|
const struct vjsn_val *v, const struct vjsn_val *vv) |
151 |
|
{ |
152 |
|
struct symbol *sym; |
153 |
|
struct vsb *buf; |
154 |
|
|
155 |
885320 |
if (kind == SYM_ALIAS) { |
156 |
5600 |
alias_sym(tl, psym, v); |
157 |
5600 |
return; |
158 |
|
} |
159 |
|
|
160 |
879720 |
buf = VSB_new_auto(); |
161 |
879720 |
AN(buf); |
162 |
|
|
163 |
879720 |
VCC_SymName(buf, psym); |
164 |
879720 |
VSB_printf(buf, ".%s", v->value); |
165 |
879720 |
AZ(VSB_finish(buf)); |
166 |
879720 |
sym = VCC_MkSym(tl, VSB_data(buf), SYM_MAIN, kind, VCL_LOW, VCL_HIGH); |
167 |
879720 |
AN(sym); |
168 |
879720 |
VSB_destroy(&buf); |
169 |
|
|
170 |
879720 |
if (kind == SYM_OBJECT) { |
171 |
57600 |
sym->eval_priv = v; |
172 |
57600 |
sym->vmod_name = psym->vmod_name; |
173 |
57600 |
sym->r_methods = VCL_MET_INIT; |
174 |
57600 |
vcc_VmodObject(tl, sym); |
175 |
57600 |
vcc_VmodSymbols(tl, sym); |
176 |
57600 |
return; |
177 |
|
} |
178 |
|
|
179 |
822120 |
if (kind == SYM_METHOD) |
180 |
182760 |
sym->extra = psym->rname; |
181 |
|
|
182 |
822120 |
v = VTAILQ_NEXT(v, list); |
183 |
|
|
184 |
822120 |
assert(vjsn_is_array(v)); |
185 |
822120 |
sym->action = vcc_Act_Call; |
186 |
822120 |
sym->vmod_name = psym->vmod_name; |
187 |
822120 |
sym->eval = vcc_Eval_SymFunc; |
188 |
822120 |
sym->eval_priv = v; |
189 |
822120 |
v = VTAILQ_FIRST(&v->children); |
190 |
822120 |
assert(vjsn_is_array(v)); |
191 |
822120 |
v = VTAILQ_FIRST(&v->children); |
192 |
822120 |
assert(vjsn_is_string(v)); |
193 |
822120 |
sym->type = VCC_Type(v->value); |
194 |
822120 |
AN(sym->type); |
195 |
822120 |
sym->r_methods = VCL_MET_TASK_ALL; |
196 |
822120 |
func_restrict(tl, sym, kind, vv); |
197 |
885320 |
} |
198 |
|
|
199 |
|
void |
200 |
80320 |
vcc_VmodSymbols(struct vcc *tl, const struct symbol *sym) |
201 |
|
{ |
202 |
|
const struct vjsn *vj; |
203 |
|
const struct vjsn_val *vv, *vv1, *vv2; |
204 |
|
vcc_kind_t kind; |
205 |
|
|
206 |
80320 |
if (sym->kind == SYM_VMOD) { |
207 |
22720 |
CAST_OBJ_NOTNULL(vj, sym->eval_priv, VJSN_MAGIC); |
208 |
22720 |
vv = VTAILQ_FIRST(&vj->value->children); |
209 |
80320 |
} else if (sym->kind == SYM_OBJECT) { |
210 |
57600 |
CAST_OBJ_NOTNULL(vv, sym->eval_priv, VJSN_VAL_MAGIC); |
211 |
57600 |
} else { |
212 |
0 |
WRONG("symbol kind"); |
213 |
|
} |
214 |
|
|
215 |
1381240 |
for (; vv != NULL; vv = VTAILQ_NEXT(vv, list)) { |
216 |
1300960 |
if (!vjsn_is_array(vv)) |
217 |
172800 |
continue; |
218 |
1128160 |
vv1 = VTAILQ_FIRST(&vv->children); |
219 |
1128160 |
AN(vv1); |
220 |
1128160 |
assert(vjsn_is_string(vv1)); |
221 |
1128160 |
vv2 = VTAILQ_NEXT(vv1, list); |
222 |
1128160 |
AN(vv2); |
223 |
1128160 |
if (!vjsn_is_string(vv2)) |
224 |
192480 |
continue; |
225 |
|
|
226 |
935680 |
kind = SYM_NONE; |
227 |
|
#define STANZA(UU, ll, ss) if (!strcmp(vv1->value, "$" #UU)) kind = ss; |
228 |
935680 |
STANZA_TBL |
229 |
|
#undef STANZA |
230 |
935680 |
if (kind != SYM_NONE) { |
231 |
885320 |
func_sym(tl, kind, sym, vv2, vv); |
232 |
885320 |
ERRCHK(tl); |
233 |
885280 |
} |
234 |
935640 |
} |
235 |
80320 |
} |
236 |
|
|
237 |
|
void v_matchproto_(sym_act_f) |
238 |
8280 |
vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym) |
239 |
|
{ |
240 |
|
struct symbol *isym, *osym; |
241 |
|
struct inifin *ifp; |
242 |
|
struct vsb *buf; |
243 |
|
const struct vjsn_val *vv, *vf; |
244 |
8280 |
int null_ok = 0; |
245 |
|
|
246 |
8280 |
(void)sym; |
247 |
8280 |
(void)t; |
248 |
|
|
249 |
8280 |
ExpectErr(tl, ID); |
250 |
8280 |
vcc_ExpectVid(tl, "VCL object"); |
251 |
8280 |
ERRCHK(tl); |
252 |
8240 |
isym = VCC_HandleSymbol(tl, INSTANCE); |
253 |
8240 |
ERRCHK(tl); |
254 |
8160 |
AN(isym); |
255 |
8160 |
isym->noref = 1; |
256 |
8160 |
isym->action = vcc_Act_Obj; |
257 |
|
|
258 |
8160 |
SkipToken(tl, '='); |
259 |
8160 |
ExpectErr(tl, ID); |
260 |
8160 |
osym = VCC_SymbolGet(tl, SYM_MAIN, SYM_OBJECT, SYMTAB_EXISTING, |
261 |
|
XREF_NONE); |
262 |
8160 |
ERRCHK(tl); |
263 |
8040 |
AN(osym); |
264 |
|
|
265 |
|
/* Scratch the generic INSTANCE type */ |
266 |
8040 |
isym->type = osym->type; |
267 |
|
|
268 |
8040 |
CAST_OBJ_NOTNULL(vv, osym->eval_priv, VJSN_VAL_MAGIC); |
269 |
|
// vv = object name |
270 |
|
|
271 |
8040 |
isym->vmod_name = osym->vmod_name; |
272 |
8040 |
isym->eval_priv = vv; |
273 |
|
|
274 |
8040 |
vv = VTAILQ_NEXT(vv, list); |
275 |
|
// vv = flags |
276 |
8040 |
assert(vjsn_is_object(vv)); |
277 |
16080 |
VTAILQ_FOREACH(vf, &vv->children, list) |
278 |
8200 |
if (!strcmp(vf->name, "NULL_OK") && vjsn_is_true(vf)) |
279 |
160 |
null_ok = 1; |
280 |
8040 |
if (!null_ok) |
281 |
7880 |
VTAILQ_INSERT_TAIL(&tl->sym_objects, isym, sideways); |
282 |
|
|
283 |
8040 |
vv = VTAILQ_NEXT(vv, list); |
284 |
|
// vv = struct name |
285 |
|
|
286 |
8040 |
Fh(tl, 0, "static %s *%s;\n\n", vv->value, isym->rname); |
287 |
8040 |
vv = VTAILQ_NEXT(vv, list); |
288 |
|
|
289 |
8040 |
vf = VTAILQ_FIRST(&vv->children); |
290 |
8040 |
vv = VTAILQ_NEXT(vv, list); |
291 |
8040 |
assert(vjsn_is_string(vf)); |
292 |
8040 |
assert(!strcmp(vf->value, "$INIT")); |
293 |
|
|
294 |
8040 |
vf = VTAILQ_NEXT(vf, list); |
295 |
|
|
296 |
8040 |
buf = VSB_new_auto(); |
297 |
8040 |
AN(buf); |
298 |
8040 |
VSB_printf(buf, "&%s, \"%s\"", isym->rname, isym->name); |
299 |
8040 |
AZ(VSB_finish(buf)); |
300 |
8040 |
vcc_Eval_Func(tl, vf, VSB_data(buf), osym); |
301 |
8040 |
VSB_destroy(&buf); |
302 |
8040 |
ERRCHK(tl); |
303 |
8040 |
SkipToken(tl, ';'); |
304 |
8040 |
isym->def_e = tl->t; |
305 |
|
|
306 |
8040 |
vf = VTAILQ_FIRST(&vv->children); |
307 |
8040 |
assert(vjsn_is_string(vf)); |
308 |
8040 |
assert(!strcmp(vf->value, "$FINI")); |
309 |
|
|
310 |
8040 |
vf = VTAILQ_NEXT(vf, list); |
311 |
8040 |
vf = VTAILQ_FIRST(&vf->children); |
312 |
8040 |
vf = VTAILQ_NEXT(vf, list); |
313 |
8040 |
ifp = New_IniFin(tl); |
314 |
8040 |
VSB_printf(ifp->fin, "\t\tif (%s)\n", isym->rname); |
315 |
8040 |
VSB_printf(ifp->fin, "\t\t\t\t%s(&%s);", vf->value, isym->rname); |
316 |
8280 |
} |