varnish-cache/lib/libvcc/vcc_action.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9 2500200
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15 2500200
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 2500200
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 2500200
 * SUCH DAMAGE.
29
 *
30
 * This file parses the real action of the VCL code, the procedure
31
 * statements which do the actual work.
32
 */
33
34
#include "config.h"
35
36
#include <string.h>
37
38
#include "vcc_compile.h"
39
#include "libvcc.h"
40
41
/*--------------------------------------------------------------------*/
42
43
static void v_matchproto_(sym_act_f)
44 5318720
vcc_act_call(struct vcc *tl, struct token *t, struct symbol *sym)
45
{
46
        struct token *t0;
47
        unsigned u;
48
49 2818520
        (void)t;
50 5318720
        ExpectErr(tl, ID);
51 2818520
        t0 = tl->t;
52 2818520
        sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_NONE, SYMTAB_PARTIAL_NOERR,
53
            XREF_REF);
54 5318720
        if (sym == NULL) {
55 2475520
                sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_SUB, SYMTAB_CREATE,
56
                    XREF_REF);
57 2475520
                if (sym == NULL)
58 2500200
                        return;
59 2475520
                VCC_GlobalSymbol(sym, SUB);
60 2475520
        }
61
62 2818520
        if (sym->kind == SYM_SUB) {
63 5318600
                vcc_AddCall(tl, t0, sym);
64
65 2818400
                Fb(tl, 1, "%s(ctx, VSUB_STATIC, NULL);\n", sym->lname);
66 2818400
                SkipToken(tl, ';');
67 2818400
                return;
68
        }
69
70 2500320
        tl->t = t0;
71 120
        u = tl->unique++;
72
73 120
        Fb(tl, 1, "{\n");
74 120
        tl->indent += INDENT;
75 2500320
        Fb(tl, 2, "VCL_SUB call_%u =\n", u);
76 120
        tl->indent += INDENT;
77 120
        vcc_Expr(tl, SUB);
78 120
        Fb(tl, 2, ";\n\n");
79 2500320
        SkipToken(tl, ';');
80 80
        tl->indent -= INDENT;
81 80
        Fb(tl, 2, "if (call_%u == NULL) {\n", u);
82 80
        Fb(tl, 2, "  VRT_fail(ctx, \"Tried to call NULL SUB near"
83
           " source %%u line %%u\",\n");
84 80
        Fb(tl, 2, "    VGC_ref[%u].source,\n", tl->cnt);
85 80
        Fb(tl, 2, "    VGC_ref[%u].line);\n", tl->cnt);
86 80
        Fb(tl, 2, "  END_;\n");
87 80
        Fb(tl, 2, "}\n");
88 80
        Fb(tl, 2, "call_%u->func(ctx, VSUB_STATIC, NULL);\n", u);
89 2500280
        tl->indent -= INDENT;
90 80
        Fb(tl, 1, "}\n");
91 2818520
}
92
93
/*--------------------------------------------------------------------*/
94 2500200
95
static const struct assign {
96
        vcc_type_t              type;
97
        unsigned                oper;
98
        vcc_type_t              want;
99
        const char              *expr;
100
} assign[] = {
101
        { INT,          T_INCR,         INT, "\v + " },
102
        { INT,          T_DECR,         INT, "\v - " },
103
        { INT,          T_MUL,          INT, "\v * " },
104 2500200
        { INT,          T_DIV,          INT, "\v / " },
105
        { INT,          '=',            INT },
106
        { INT,          0,              INT },
107
        { TIME,         T_INCR,         DURATION, "\v + " },
108
        { TIME,         T_DECR,         DURATION, "\v - " },
109
        { TIME,         T_MUL,          REAL, "\v * " },
110
        { TIME,         T_DIV,          REAL, "\v / " },
111
        { TIME,         '=',            TIME },
112
        { TIME,         0,              TIME },
113
        { DURATION,     T_INCR,         DURATION, "\v + " },
114
        { DURATION,     T_DECR,         DURATION, "\v - " },
115
        { DURATION,     T_MUL,          REAL, "\v * " },
116
        { DURATION,     T_DIV,          REAL, "\v / " },
117
        { DURATION,     '=',            DURATION },
118
        { DURATION,     0,              DURATION },
119
        { STRING,       T_INCR,         STRANDS, "\v,\n" },
120
        { STRING,       '=',            STRANDS, "0,\n" },
121
        { HEADER,       T_INCR,         STRANDS, "VRT_GetHdr(ctx, \v),\n" },
122
        { HEADER,       '=',            STRANDS, "0,\n" },
123
        { BODY,         '=',            BODY, "LBODY_SET_" },
124
        { BODY,         T_INCR,         BODY, "LBODY_ADD_" },
125
        { VOID,         '=',            VOID }
126
};
127
128
static void
129 1123640
vcc_assign_expr(struct vcc *tl, struct symbol *sym, const struct assign *ap)
130
{
131
        const char *e;
132 1123640
        unsigned indent = 1;
133
134 1123640
        e = ap->expr;
135 1123640
        if (e == NULL)
136 252440
                return;
137
138 5068960
        while (*e != '\0') {
139 4197760
                if (*e == '\v')
140 680
                        Fb(tl, indent, "%s", sym->rname);
141
                else
142 4197080
                        Fb(tl, indent, "%c", *e);
143 4197760
                indent = 0;
144 4197760
                e++;
145
        }
146 1123640
}
147
148
/*--------------------------------------------------------------------*/
149
150
static void v_matchproto_(sym_act_f)
151 1124120
vcc_act_set(struct vcc *tl, struct token *t, struct symbol *sym)
152
{
153
        const struct assign *ap;
154
        vcc_type_t type;
155
156 1124120
        (void)t;
157 1124120
        ExpectErr(tl, ID);
158 1124120
        t = tl->t;
159 1124120
        sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_VAR, SYMTAB_EXISTING, XREF_NONE);
160 1124120
        ERRCHK(tl);
161 1123800
        AN(sym);
162 1123800
        vcc_AddUses(tl, t, tl->t, sym, XREF_WRITE);
163 1123800
        ERRCHK(tl);
164 1123800
        type = sym->type;
165 24692680
        for (ap = assign; ap->type != VOID; ap++) {
166 24562160
                if (ap->type != type)
167 22435600
                        continue;
168 2126560
                if (ap->oper != tl->t->tok)
169 1133280
                        continue;
170 993280
                vcc_NextToken(tl);
171 993280
                type = ap->want;
172 993280
                break;
173
        }
174
175 1123800
        if (ap->type == VOID)
176 130520
                SkipToken(tl, ap->oper);
177
178 1123640
        Fb(tl, 1, "%s\n", sym->lname);
179 1123640
        tl->indent += INDENT;
180 1123640
        vcc_assign_expr(tl, sym, ap);
181 1123640
        vcc_Expr(tl, type);
182 1123640
        ERRCHK(tl);
183 1121960
        tl->indent -= INDENT;
184 1121960
        Fb(tl, 1, ");\n");
185 1121960
        SkipToken(tl, ';');
186 1124120
}
187
188
/*--------------------------------------------------------------------*/
189
190
static void v_matchproto_(sym_act_f)
191 227480
vcc_act_unset(struct vcc *tl, struct token *t, struct symbol *sym)
192
{
193
194
        /* XXX: Wrong, should use VCC_Expr(HEADER) */
195 227480
        ExpectErr(tl, ID);
196 227480
        t = tl->t;
197 227480
        sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_VAR, SYMTAB_EXISTING, XREF_NONE);
198 227480
        ERRCHK(tl);
199 227480
        AN(sym);
200 227480
        if (sym->u_methods == 0) {
201 80
                vcc_ErrWhere2(tl, t, tl->t);
202 80
                VSB_cat(tl->sb, "Variable cannot be unset.\n");
203 80
                return;
204
        }
205 227400
        vcc_AddUses(tl, t, tl->t, sym, XREF_UNSET);
206 227400
        Fb(tl, 1, "%s;\n", sym->uname);
207 227400
        SkipToken(tl, ';');
208 227480
}
209
210
/*--------------------------------------------------------------------*/
211
212
static void v_matchproto_(sym_act_f)
213 600
vcc_act_ban(struct vcc *tl, struct token *t, struct symbol *sym)
214
{
215
216 600
        (void)t;
217 600
        (void)sym;
218
219 600
        SkipToken(tl, '(');
220
221 600
        Fb(tl, 1, "(void) VRT_ban_string(ctx, \n");
222 600
        tl->indent += INDENT;
223 600
        vcc_Expr(tl, STRING);
224 600
        tl->indent -= INDENT;
225 600
        ERRCHK(tl);
226 560
        Fb(tl, 1, ");\n");
227
228 560
        SkipToken(tl, ')');
229 560
        SkipToken(tl, ';');
230 600
}
231
232
/*--------------------------------------------------------------------*/
233
234
static void v_matchproto_(sym_act_f)
235 338080
vcc_act_hash_data(struct vcc *tl, struct token *t, struct symbol *sym)
236
{
237
238 338080
        (void)t;
239 338080
        (void)sym;
240 338080
        SkipToken(tl, '(');
241
242 338080
        Fb(tl, 1, "VRT_hashdata(ctx,\n  ");
243 338080
        vcc_Expr(tl, STRANDS);
244 338080
        ERRCHK(tl);
245 338040
        Fb(tl, 1, ");\n");
246 338040
        SkipToken(tl, ')');
247 338040
        SkipToken(tl, ';');
248 338080
}
249
250
/*--------------------------------------------------------------------*/
251
252
static void
253 320
vcc_act_return_pass(struct vcc *tl)
254
{
255
256 320
        SkipToken(tl, '(');
257 320
        Fb(tl, 1, "VRT_hit_for_pass(ctx,\n");
258 320
        tl->indent += INDENT;
259 320
        vcc_Expr(tl, DURATION);
260 320
        ERRCHK(tl);
261 320
        SkipToken(tl, ')');
262 320
        Fb(tl, 1, ");\n");
263 320
        tl->indent -= INDENT;
264 320
}
265
/*--------------------------------------------------------------------*/
266
267
static void
268 2240
vcc_act_return_fail(struct vcc *tl)
269
{
270 2240
        SkipToken(tl, '(');
271 2240
        Fb(tl, 1, "VRT_fail(ctx, \"%%s\",\n");
272 2240
        tl->indent += INDENT;
273 2240
        vcc_Expr(tl, STRING);
274 2240
        tl->indent -= INDENT;
275 2240
        ERRCHK(tl);
276 2240
        SkipToken(tl, ')');
277 2240
        Fb(tl, 1, ");\n");
278 2240
}
279
280
/*--------------------------------------------------------------------*/
281
282
static void
283 345520
vcc_act_return_synth(struct vcc *tl)
284
{
285
286 345520
        SkipToken(tl, '(');
287 345520
        Fb(tl, 1, "VRT_synth(ctx,\n");
288 345520
        tl->indent += INDENT;
289 345520
        vcc_Expr(tl, INT);
290 345520
        ERRCHK(tl);
291 345520
        Fb(tl, 1, ",\n");
292 345520
        if (tl->t->tok == ',') {
293 114400
                vcc_NextToken(tl);
294 114400
                vcc_Expr(tl, STRING);
295 114400
                ERRCHK(tl);
296 114400
        } else {
297 231120
                Fb(tl, 1, "(const char*)0\n");
298
        }
299 345520
        tl->indent -= INDENT;
300 345520
        SkipToken(tl, ')');
301 345520
        Fb(tl, 1, ");\n");
302 345520
}
303
304
/*--------------------------------------------------------------------*/
305
306
static void
307 960
vcc_act_return_vcl(struct vcc *tl)
308
{
309
        struct symbol *sym;
310
        struct inifin *p;
311
        char buf[1024];
312
313 960
        SkipToken(tl, '(');
314 960
        ExpectErr(tl, ID);
315 960
        sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_VCL, SYMTAB_EXISTING, XREF_NONE);
316 960
        ERRCHK(tl);
317 880
        AN(sym);
318 880
        if (sym->eval_priv == NULL) {
319 840
                VSB_cat(tl->symtab, ",\n    {\n");
320 840
                VSB_cat(tl->symtab, "\t\"dir\": \"import\",\n");
321 840
                VSB_cat(tl->symtab, "\t\"type\": \"$VCL\",\n");
322 840
                VSB_printf(tl->symtab, "\t\"name\": \"%s\"\n", sym->name);
323 840
                VSB_cat(tl->symtab, "   }");
324
325 840
                bprintf(buf, "vgc_vcl_%u", tl->unique++);
326 840
                sym->eval_priv = strdup(buf);
327 840
                AN(sym->eval_priv);
328
329 840
                Fh(tl, 0, "static VCL_VCL %s;", buf);
330 840
                Fh(tl, 0, "\t/* VCL %s */\n", sym->name);
331
332 840
                p = New_IniFin(tl);
333 840
                AN(p);
334 1680
                VSB_printf(p->ini, "\t%s = VPI_vcl_get(ctx, \"%s\");",
335 840
                    buf, sym->name);
336 1680
                VSB_printf(p->fin, "\tVPI_vcl_rel(ctx, %s);",
337 840
                    buf);
338 840
        }
339 1760
        Fb(tl, 1, "VPI_vcl_select(ctx, %s);\t/* %s */\n",
340 880
            (const char*)sym->eval_priv, sym->name);
341 880
        SkipToken(tl, ')');
342 960
}
343
344
/*--------------------------------------------------------------------*/
345
346
static void v_matchproto_(sym_act_f)
347 2500440
vcc_act_return(struct vcc *tl, struct token *t, struct symbol *sym)
348
{
349
        unsigned hand, mask;
350
        const char *h;
351
352 2500440
        (void)t;
353 2500440
        (void)sym;
354 2500440
        AN(tl->curproc);
355 2500440
        if (tl->t->tok == ';' && tl->curproc->method == NULL) {
356 200
                SkipToken(tl, ';');
357 200
                Fb(tl, 1, "return;\n");
358 200
                return;
359
        }
360 2500240
        SkipToken(tl, '(');
361 2500200
        ExpectErr(tl, ID);
362
363 2500200
        hand = VCL_RET_MAX;
364 2500200
        h = NULL;
365 2500200
        mask = 0;
366
#define VCL_RET_MAC(l, U, B)                            \
367
                if (vcc_IdIs(tl->t, #l)) {              \
368
                        hand = VCL_RET_ ## U;           \
369
                        h = #U;                         \
370
                        mask = (B);                     \
371
                }
372
#include "tbl/vcl_returns.h"
373 2500200
        if (h == NULL) {
374 40
                VSB_cat(tl->sb, "Expected return action name.\n");
375 40
                vcc_ErrWhere(tl, tl->t);
376 40
                ERRCHK(tl);
377 0
        }
378 2500160
        assert(hand < VCL_RET_MAX);
379 2500160
        AN(mask);
380
381
        vcc_ProcAction(tl->curproc, hand, mask, tl->t);
382
        vcc_NextToken(tl);
383 2500160
        if (tl->t->tok == '(') {
384 349080
                if (hand == VCL_RET_SYNTH || hand == VCL_RET_ERROR)
385 345520
                        vcc_act_return_synth(tl);
386 3560
                else if (hand == VCL_RET_VCL)
387 960
                        vcc_act_return_vcl(tl);
388 2600
                else if (hand == VCL_RET_PASS)
389 320
                        vcc_act_return_pass(tl);
390 2280
                else if (hand == VCL_RET_FAIL)
391 2240
                        vcc_act_return_fail(tl);
392
                else {
393 40
                        VSB_cat(tl->sb, "Arguments not allowed.\n");
394 40
                        vcc_ErrWhere(tl, tl->t);
395
                }
396 349080
        } else {
397 2151080
                if (hand == VCL_RET_SYNTH || hand == VCL_RET_VCL) {
398 40
                        VSB_cat(tl->sb, "Missing argument.\n");
399 40
                        vcc_ErrWhere(tl, tl->t);
400 40
                }
401
        }
402 2500160
        ERRCHK(tl);
403
        Fb(tl, 1, "END_;\n");
404 2500000
        if (hand == VCL_RET_FAIL)
405 3120
                Fb(tl, 1, "VRT_fail(ctx, \"Failed from VCL\");\n");
406
        else
407 2496880
                Fb(tl, 1, "VRT_handling(ctx, VCL_RET_%s);\n", h);
408 2500000
        SkipToken(tl, ')');
409 2500000
        SkipToken(tl, ';');
410
}
411
412
/*--------------------------------------------------------------------*/
413
414
static void v_matchproto_(sym_act_f)
415 240
vcc_act_synthetic(struct vcc *tl, struct token *t, struct symbol *sym)
416
{
417
418 240
        (void)t;
419 240
        (void)sym;
420 240
        ExpectErr(tl, '(');
421 240
        ERRCHK(tl);
422 240
        vcc_NextToken(tl);
423
424 240
        Fb(tl, 1, "VRT_synth_strands(ctx, ");
425 240
        vcc_Expr(tl, STRANDS);
426 240
        ERRCHK(tl);
427 200
        Fb(tl, 1, ");\n");
428
429 200
        SkipToken(tl, ')');
430 200
        SkipToken(tl, ';');
431 240
}
432
433
/*--------------------------------------------------------------------*/
434
435
// The pp[] trick is to make the length of #name visible to flexelint.
436
#define ACT(name, func, mask)                                           \
437
        do {                                                            \
438
                const char pp[] = #name;                                \
439
                sym = VCC_MkSym(tl, pp, SYM_MAIN, SYM_ACTION, VCL_LOW,  \
440
                    VCL_HIGH);                                          \
441
                AN(sym);                                                \
442
                sym->action = func;                                     \
443
                sym->action_mask = (mask);                              \
444
        } while (0)
445
446
void
447 121960
vcc_Action_Init(struct vcc *tl)
448
{
449
        struct symbol *sym;
450
451 121960
        ACT(ban,        vcc_act_ban,    0);
452 121960
        ACT(call,       vcc_act_call,   0);
453 121960
        ACT(hash_data,  vcc_act_hash_data,
454
                VCL_MET_HASH);
455 121960
        ACT(if,         vcc_Act_If,     0);
456 121960
        ACT(new,        vcc_Act_New,
457
                VCL_MET_INIT);
458 121960
        ACT(return,     vcc_act_return, 0);
459 121960
        ACT(set,        vcc_act_set,    0);
460 121960
        ACT(synthetic,  vcc_act_synthetic,
461
                VCL_MET_SYNTH | VCL_MET_BACKEND_ERROR);
462 121960
        ACT(unset,      vcc_act_unset,  0);
463 121960
}