vinyl-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 103488
 *
8 103488
 * Redistribution and use in source and binary forms, with or without
9 103488
 * modification, are permitted provided that the following conditions
10 103488
 * are met:
11 103488
 * 1. Redistributions of source code must retain the above copyright
12 103488
 *    notice, this list of conditions and the following disclaimer.
13 103488
 * 2. Redistributions in binary form must reproduce the above copyright
14 103488
 *    notice, this list of conditions and the following disclaimer in the
15 103488
 *    documentation and/or other materials provided with the distribution.
16 103488
 *
17 103488
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 103488
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 103488
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 103488
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 103488
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 103488
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 103488
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 103488
 * 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 31458
vcc_VmodObject(struct vcc *tl, struct symbol *sym)
55
{
56
        struct vmod_obj *obj;
57
        struct vsb *buf;
58
59 31458
        buf = VSB_new_auto();
60 31458
        AN(buf);
61
62 31458
        VSB_printf(buf, "%s.%s", sym->vmod_name, sym->name);
63 31458
        AZ(VSB_finish(buf));
64
65 31458
        ALLOC_OBJ(obj, VMOD_OBJ_MAGIC);
66 31458
        AN(obj);
67 31458
        REPLACE(obj->name, VSB_data(buf));
68
69 31458
        INIT_OBJ(obj->type, TYPE_MAGIC);
70 31458
        obj->type->name = obj->name;
71 31458
        sym->type = obj->type;
72 31458
        VTAILQ_INSERT_TAIL(&tl->vmod_objects, obj, list);
73 31458
        VSB_destroy(&buf);
74 31458
}
75
76
static void
77 2730
alias_sym(struct vcc *tl, const struct symbol *psym, const struct vjsn_val *v)
78
{
79 2730
        char *alias = NULL, *func = NULL;
80
        struct symbol *sym;
81
        struct vsb *buf;
82
83 2730
        buf = VSB_new_auto();
84 2730
        AN(buf);
85
86 2730
        VCC_SymName(buf, psym);
87 2730
        VSB_printf(buf, ".%s", v->value);
88 2730
        AZ(VSB_finish(buf));
89 2730
        REPLACE(alias, VSB_data(buf));
90
91 2730
        v = VTAILQ_NEXT(v, list);
92 2730
        assert(vjsn_is_string(v));
93
94 2730
        VSB_clear(buf);
95 2730
        VCC_SymName(buf, psym);
96 2730
        VSB_printf(buf, ".%s", v->value);
97 2730
        AZ(VSB_finish(buf));
98 2730
        REPLACE(func, VSB_data(buf));
99
100 2730
        sym = VCC_MkSymAlias(tl, alias, func);
101 2730
        AN(sym);
102 2730
        assert(sym->kind == SYM_FUNC || sym->kind == SYM_METHOD);
103 2730
        VSB_destroy(&buf);
104 2730
        free(alias);
105 2730
        free(func);
106 2730
}
107
108
static void
109 486612
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 486612
        AN(v);
114 486612
        AN(sym);
115
116 486612
        if (kind != SYM_FUNC && kind != SYM_METHOD)
117 0
                return;
118
119 486612
        v = VTAILQ_NEXT(v, list);
120 486612
        if (!v || !vjsn_is_array(v))
121 29862
                return;
122 456750
        vv = VTAILQ_FIRST(&v->children);
123 456750
        AN(vv);
124 456750
        assert(vjsn_is_string(vv));
125 456750
        if (vstrcmp(vv->value, "$RESTRICT"))
126 407085
                return;
127 49665
        vv = VTAILQ_NEXT(vv, list);
128 49665
        AN(vv);
129 49665
        assert(vjsn_is_array(vv));
130 49665
        sym->r_methods = 0;
131 49665
        vv = VTAILQ_FIRST(&vv->children);
132
        unsigned s;
133 153132
        while (vv) {
134 103488
                s = 0;
135
#define VCL_CTX(l,H)                                                    \
136
                if (vstrcmp(vv->value, #l) == 0) s = VCL_MET_##H;
137
#include "tbl/vcl_context.h"
138 103488
                if (!s) {
139 21
                        VSB_printf(tl->sb, "Error in vmod \"%s\", invalid scope for $Restrict: %s\n",sym->vmod_name, vv->value);
140 21
                        tl->err = 1;
141 21
                        break;
142
                }
143
                sym->r_methods |= s;
144
                vv = VTAILQ_NEXT(vv,list);
145
        }
146 486612
}
147
148
static void
149 520800
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 520800
        if (kind == SYM_ALIAS) {
156 2730
                alias_sym(tl, psym, v);
157 2730
                return;
158
        }
159
160 518070
        buf = VSB_new_auto();
161 518070
        AN(buf);
162
163 518070
        VCC_SymName(buf, psym);
164 518070
        VSB_printf(buf, ".%s", v->value);
165 518070
        AZ(VSB_finish(buf));
166 518070
        sym = VCC_MkSym(tl, VSB_data(buf), SYM_MAIN, kind, VCL_LOW, VCL_HIGH);
167 518070
        AN(sym);
168 518070
        VSB_destroy(&buf);
169
170 518070
        if (kind == SYM_OBJECT) {
171 31458
                sym->eval_priv = v;
172 31458
                sym->vmod_name = psym->vmod_name;
173 31458
                sym->r_methods = VCL_MET_INIT;
174 31458
                vcc_VmodObject(tl, sym);
175 31458
                vcc_VmodSymbols(tl, sym);
176 31458
                return;
177
        }
178
179 486612
        if (kind == SYM_METHOD)
180 98973
                sym->extra = psym->rname;
181
182 486612
        v = VTAILQ_NEXT(v, list);
183
184 486612
        assert(vjsn_is_array(v));
185 486612
        sym->action = vcc_Act_Call;
186 486612
        sym->vmod_name = psym->vmod_name;
187 486612
        sym->eval = vcc_Eval_SymFunc;
188 486612
        sym->eval_priv = v;
189 486612
        v = VTAILQ_FIRST(&v->children);
190 486612
        assert(vjsn_is_array(v));
191 486612
        v = VTAILQ_FIRST(&v->children);
192 486612
        assert(vjsn_is_string(v));
193 486612
        sym->type = VCC_Type(v->value);
194 486612
        AN(sym->type);
195 486612
        sym->r_methods = VCL_MET_TASK_ALL;
196 486612
        func_restrict(tl, sym, kind, vv);
197 520800
}
198
199
void
200 44268
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 44268
        if (sym->kind == SYM_VMOD) {
207 12810
                CAST_OBJ_NOTNULL(vj, sym->eval_priv, VJSN_MAGIC);
208 12810
                vv = VTAILQ_FIRST(&vj->value->children);
209 44268
        } else if (sym->kind == SYM_OBJECT) {
210 31458
                CAST_OBJ_NOTNULL(vv, sym->eval_priv, VJSN_VAL_MAGIC);
211 31458
        } else {
212 0
                WRONG("symbol kind");
213
        }
214
215 802389
        for (; vv != NULL; vv = VTAILQ_NEXT(vv, list)) {
216 758142
                if (!vjsn_is_array(vv))
217 94374
                        continue;
218 663768
                vv1 = VTAILQ_FIRST(&vv->children);
219 663768
                AN(vv1);
220 663768
                assert(vjsn_is_string(vv1));
221 663768
                vv2 = VTAILQ_NEXT(vv1, list);
222 663768
                AN(vv2);
223 663768
                if (!vjsn_is_string(vv2))
224 112560
                        continue;
225
226 551208
                kind = SYM_NONE;
227
#define STANZA(UU, ll, ss) if (!strcmp(vv1->value, "$" #UU)) kind = ss;
228 551208
        STANZA_TBL
229
#undef STANZA
230 551208
                if (kind != SYM_NONE) {
231 520800
                        func_sym(tl, kind, sym, vv2, vv);
232 520800
                        ERRCHK(tl);
233 520779
                }
234 551187
        }
235 44268
}
236
237
void v_matchproto_(sym_act_f)
238 4347
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 4347
        int null_ok = 0;
245
246 4347
        (void)sym;
247 4347
        (void)t;
248
249 4347
        ExpectErr(tl, ID);
250 4347
        vcc_ExpectVid(tl, "VCL object");
251 4347
        ERRCHK(tl);
252 4326
        isym = VCC_HandleSymbol(tl, INSTANCE);
253 4326
        ERRCHK(tl);
254 4284
        AN(isym);
255 4284
        isym->noref = 1;
256 4284
        isym->action = vcc_Act_Obj;
257
258 4284
        SkipToken(tl, '=');
259 4284
        ExpectErr(tl, ID);
260 4284
        osym = VCC_SymbolGet(tl, SYM_MAIN, SYM_OBJECT, SYMTAB_EXISTING,
261
            XREF_NONE);
262 4284
        ERRCHK(tl);
263 4221
        AN(osym);
264
265
        /* Scratch the generic INSTANCE type */
266 4221
        isym->type = osym->type;
267
268 4221
        CAST_OBJ_NOTNULL(vv, osym->eval_priv, VJSN_VAL_MAGIC);
269
        // vv = object name
270
271 4221
        isym->vmod_name = osym->vmod_name;
272 4221
        isym->eval_priv = vv;
273
274 4221
        vv = VTAILQ_NEXT(vv, list);
275
        // vv = flags
276 4221
        assert(vjsn_is_object(vv));
277 8442
        VTAILQ_FOREACH(vf, &vv->children, list)
278 4305
                if (!vstrcmp(vf->name, "NULL_OK") && vjsn_is_true(vf))
279 84
                        null_ok = 1;
280 4221
        if (!null_ok)
281 4137
                VTAILQ_INSERT_TAIL(&tl->sym_objects, isym, sideways);
282
283 4221
        vv = VTAILQ_NEXT(vv, list);
284
        // vv = struct name
285
286 4221
        Fh(tl, 0, "static %s *%s;\n\n", vv->value, isym->rname);
287 4221
        vv = VTAILQ_NEXT(vv, list);
288
289 4221
        vf = VTAILQ_FIRST(&vv->children);
290 4221
        vv = VTAILQ_NEXT(vv, list);
291 4221
        assert(vjsn_is_string(vf));
292 4221
        assert(!vstrcmp(vf->value, "$INIT"));
293
294 4221
        vf = VTAILQ_NEXT(vf, list);
295
296 4221
        buf = VSB_new_auto();
297 4221
        AN(buf);
298 4221
        VSB_printf(buf, "&%s, \"%s\"", isym->rname, isym->name);
299 4221
        AZ(VSB_finish(buf));
300 4221
        vcc_Eval_Func(tl, vf, VSB_data(buf), osym);
301 4221
        VSB_destroy(&buf);
302 4221
        ERRCHK(tl);
303 4221
        SkipToken(tl, ';');
304 4221
        isym->def_e = tl->t;
305
306 4221
        vf = VTAILQ_FIRST(&vv->children);
307 4221
        assert(vjsn_is_string(vf));
308 4221
        assert(!vstrcmp(vf->value, "$FINI"));
309
310 4221
        vf = VTAILQ_NEXT(vf, list);
311 4221
        vf = VTAILQ_FIRST(&vf->children);
312 4221
        vf = VTAILQ_NEXT(vf, list);
313 4221
        ifp = New_IniFin(tl);
314 4221
        VSB_printf(ifp->fin, "\t\tif (%s)\n", isym->rname);
315 4221
        VSB_printf(ifp->fin, "\t\t\t\t%s(&%s);", vf->value, isym->rname);
316 4347
}