varnish-cache/lib/libvcc/vcc_action.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * 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
 * This file parses the real action of the VCL code, the procedure
30
 * statements which do the actual work.
31
 */
32
33
#include "config.h"
34
35
#include <string.h>
36
37
#include "vcc_compile.h"
38
#include "libvcc.h"
39
40
/*--------------------------------------------------------------------*/
41
42
static void v_matchproto_(sym_act_f)
43 28
vcc_act_call(struct vcc *tl, struct token *t, struct symbol *sym)
44
{
45
46
        (void)t;
47 28
        ExpectErr(tl, ID);
48 28
        sym = VCC_SymbolGet(tl, SYM_SUB, SYMTAB_CREATE, XREF_REF);
49 28
        AN(sym);
50 28
        vcc_AddCall(tl, sym);
51 28
        VCC_GlobalSymbol(sym, SUB, "VGC_function");
52 28
        Fb(tl, 1, "%s(ctx);\n", sym->rname);
53 28
        SkipToken(tl, ';');
54
}
55
56
/*--------------------------------------------------------------------*/
57
58
static const struct arith {
59
        vcc_type_t              type;
60
        unsigned                oper;
61
        vcc_type_t              want;
62
} arith[] = {
63
        { INT,          T_INCR,         INT },
64
        { INT,          T_DECR,         INT },
65
        { INT,          T_MUL,          INT },
66
        { INT,          T_DIV,          INT },
67
        { INT,          '=',            INT },
68
        { INT,          0,              INT },
69
        { TIME,         T_INCR,         DURATION },
70
        { TIME,         T_DECR,         DURATION },
71
        { TIME,         T_MUL,          REAL },
72
        { TIME,         T_DIV,          REAL },
73
        { TIME,         '=',            TIME },
74
        { TIME,         0,              TIME },
75
        { DURATION,     T_INCR,         DURATION },
76
        { DURATION,     T_DECR,         DURATION },
77
        { DURATION,     T_MUL,          REAL },
78
        { DURATION,     T_DIV,          REAL },
79
        { DURATION,     '=',            DURATION },
80
        { DURATION,     0,              DURATION },
81
        { VOID,         '=',            VOID }
82
};
83
84
85
/*--------------------------------------------------------------------*/
86
87
static void v_matchproto_(sym_act_f)
88 18388
vcc_act_set(struct vcc *tl, struct token *t, struct symbol *sym)
89
{
90
        const struct arith *ap;
91
        vcc_type_t type;
92
93
        (void)t;
94 18388
        ExpectErr(tl, ID);
95 18388
        t = tl->t;
96 18388
        sym = VCC_SymbolGet(tl, SYM_VAR, "Unknown variable", XREF_NONE);
97 18388
        ERRCHK(tl);
98 18376
        AN(sym);
99 18376
        if (sym->w_methods == 0) {
100 12
                vcc_ErrWhere2(tl, t, tl->t);
101 12
                if (sym->r_methods != 0)
102 10
                        VSB_printf(tl->sb, "Variable is read only.\n");
103
                else
104 2
                        VSB_printf(tl->sb, "Variable cannot be set.\n");
105 12
                return;
106
        }
107 18364
        vcc_AddUses(tl, t, tl->t, sym->w_methods, "Cannot be set");
108 18364
        Fb(tl, 1, "%s\n", sym->lname);
109 18364
        tl->indent += INDENT;
110 18364
        type = sym->type;
111 343670
        for (ap = arith; ap->type != VOID; ap++) {
112 327458
                if (ap->type != type)
113 316716
                        continue;
114 10742
                if (ap->oper != tl->t->tok)
115 8590
                        continue;
116 2152
                if (ap->oper != '=')
117 10
                        Fb(tl, 1, "%s %c ", sym->rname, *tl->t->b);
118 2152
                vcc_NextToken(tl);
119 2152
                type = ap->want;
120 2152
                break;
121
        }
122 18364
        if (ap->type == VOID)
123 16212
                SkipToken(tl, ap->oper);
124 18356
        if (type == HEADER) {
125 10022
                vcc_Expr(tl, STRING_LIST);
126 8334
        } else if (type == STRING) {
127 106
                vcc_Expr(tl, STRING_LIST);
128 8228
        } else if (type == BODY) {
129 3636
                vcc_Expr(tl, STRING_LIST);
130
        } else {
131 4592
                vcc_Expr(tl, type);
132
        }
133 18356
        ERRCHK(tl);
134 18290
        tl->indent -= INDENT;
135 18290
        Fb(tl, 1, ");\n");
136 18290
        SkipToken(tl, ';');
137
}
138
139
/*--------------------------------------------------------------------*/
140
141
static void v_matchproto_(sym_act_f)
142 1872
vcc_act_unset(struct vcc *tl, struct token *t, struct symbol *sym)
143
{
144
145
        /* XXX: Wrong, should use VCC_Expr(HEADER) */
146 1872
        ExpectErr(tl, ID);
147 1872
        t = tl->t;
148 1872
        sym = VCC_SymbolGet(tl, SYM_VAR, "Unknown variable", XREF_NONE);
149 1872
        ERRCHK(tl);
150 1872
        AN(sym);
151 1872
        if (sym->u_methods == 0) {
152 2
                vcc_ErrWhere2(tl, t, tl->t);
153 2
                VSB_printf(tl->sb, "Variable cannot be unset.\n");
154 2
                return;
155
        }
156 1870
        vcc_AddUses(tl, t, tl->t, sym->u_methods, "Cannot be unset");
157 1870
        Fb(tl, 1, "%s;\n", sym->uname);
158 1870
        SkipToken(tl, ';');
159
}
160
161
/*--------------------------------------------------------------------*/
162
163
static void v_matchproto_(sym_act_f)
164 30
vcc_act_ban(struct vcc *tl, struct token *t, struct symbol *sym)
165
{
166
167
        (void)t;
168
        (void)sym;
169
170 30
        ExpectErr(tl, '(');
171 30
        vcc_NextToken(tl);
172
173 30
        Fb(tl, 1, "VRT_ban_string(ctx, \n");
174 30
        tl->indent += INDENT;
175 30
        vcc_Expr(tl, STRING);
176 30
        tl->indent -= INDENT;
177 30
        ERRCHK(tl);
178 28
        Fb(tl, 1, ");\n");
179
180 28
        SkipToken(tl, ')');
181 28
        SkipToken(tl, ';');
182
}
183
184
/*--------------------------------------------------------------------*/
185
186
static void v_matchproto_(sym_act_f)
187 5448
vcc_act_hash_data(struct vcc *tl, struct token *t, struct symbol *sym)
188
{
189
190
        (void)t;
191
        (void)sym;
192 5448
        SkipToken(tl, '(');
193
194 5448
        Fb(tl, 1, "VRT_hashdata(ctx,\n  ");
195 5448
        vcc_Expr(tl, STRING_LIST);
196 5448
        ERRCHK(tl);
197 5446
        Fb(tl, 1, ");\n");
198 5446
        SkipToken(tl, ')');
199 5446
        SkipToken(tl, ';');
200
}
201
202
/*--------------------------------------------------------------------*/
203
204
static void
205 8
vcc_act_return_pass(struct vcc *tl)
206
{
207
208 8
        ExpectErr(tl, '(');
209 8
        vcc_NextToken(tl);
210 8
        Fb(tl, 1, "VRT_hit_for_pass(ctx,\n");
211 8
        tl->indent += INDENT;
212 8
        vcc_Expr(tl, DURATION);
213 8
        ERRCHK(tl);
214 8
        SkipToken(tl, ')');
215 8
        Fb(tl, 1, ");\n");
216 8
        tl->indent -= INDENT;
217
}
218
/*--------------------------------------------------------------------*/
219
220
static void
221 4
vcc_act_return_fail(struct vcc *tl)
222
{
223 4
        ExpectErr(tl, '(');
224 4
        vcc_NextToken(tl);
225 4
        Fb(tl, 1, "VRT_fail(ctx,\n");
226 4
        tl->indent += INDENT;
227 4
        vcc_Expr(tl, STRING);
228 4
        tl->indent -= INDENT;
229 4
        ERRCHK(tl);
230 4
        SkipToken(tl, ')');
231 4
        Fb(tl, 1, ");\n");
232
}
233
234
/*--------------------------------------------------------------------*/
235
236
static void
237 5658
vcc_act_return_synth(struct vcc *tl)
238
{
239
240 5658
        ExpectErr(tl, '(');
241 5658
        vcc_NextToken(tl);
242 5658
        Fb(tl, 1, "VRT_synth(ctx,\n");
243 5658
        tl->indent += INDENT;
244 5658
        vcc_Expr(tl, INT);
245 5658
        ERRCHK(tl);
246 5658
        Fb(tl, 1, ",\n");
247 5658
        if (tl->t->tok == ',') {
248 1864
                vcc_NextToken(tl);
249 1864
                vcc_Expr(tl, STRING);
250 1864
                ERRCHK(tl);
251
        } else {
252 3794
                Fb(tl, 1, "(const char*)0\n");
253
        }
254 5658
        tl->indent -= INDENT;
255 5658
        SkipToken(tl, ')');
256 5658
        Fb(tl, 1, ");\n");
257
}
258
259
/*--------------------------------------------------------------------*/
260
261
static void
262 36
vcc_act_return_vcl(struct vcc *tl)
263
{
264
        struct symbol *sym;
265
        struct inifin *p;
266
        char buf[1024];
267
268 40
        ExpectErr(tl, '(');
269 36
        vcc_NextToken(tl);
270 36
        ExpectErr(tl, ID);
271 36
        sym = VCC_SymbolGet(tl, SYM_VCL, "Not a VCL label", XREF_NONE);
272 36
        ERRCHK(tl);
273 32
        AN(sym);
274 32
        if (sym->eval_priv == NULL) {
275 32
                VSB_printf(tl->fi, "%s VCL %s */\n", VCC_INFO_PREFIX,
276
                    sym->name);
277
278 32
                bprintf(buf, "vgc_vcl_%u", tl->unique++);
279 32
                sym->eval_priv = strdup(buf);
280 32
                AN(sym->eval_priv);
281
282 32
                Fh(tl, 0, "static VCL_VCL %s;", buf);
283 32
                Fh(tl, 0, "\t/* VCL %s */\n", sym->name);
284
285 32
                p = New_IniFin(tl);
286 32
                AN(p);
287 32
                VSB_printf(p->ini, "\t%s = VRT_vcl_get(ctx, \"%s\");",
288
                    buf, sym->name);
289 32
                VSB_printf(p->fin, "\tVRT_vcl_rel(ctx, %s);",
290
                    buf);
291
        }
292 64
        Fb(tl, 1, "VRT_vcl_select(ctx, %s);\t/* %s */\n",
293 32
            (const char*)sym->eval_priv, sym->name);
294 32
        SkipToken(tl, ')');
295
}
296
297
/*--------------------------------------------------------------------*/
298
299
static void v_matchproto_(sym_act_f)
300 40534
vcc_act_return(struct vcc *tl, struct token *t, struct symbol *sym)
301
{
302
        unsigned hand;
303
        const char *h;
304
305
        (void)t;
306
        (void)sym;
307 40534
        AN(tl->curproc);
308 40534
        if (tl->t->tok == ';' && tl->curproc->method == NULL) {
309 2
                SkipToken(tl, ';');
310 2
                Fb(tl, 1, "return;\n");
311 2
                return;
312
        }
313 40532
        SkipToken(tl, '(');
314 40530
        ExpectErr(tl, ID);
315
316 40530
        hand = VCL_RET_MAX;
317 40530
        h = NULL;
318
#define VCL_RET_MAC(l, U, B)                            \
319
                if (vcc_IdIs(tl->t, #l)) {              \
320
                        hand = VCL_RET_ ## U;           \
321
                        h = #U;                         \
322
                }
323
#include "tbl/vcl_returns.h"
324 40530
        if (h == NULL) {
325 2
                VSB_printf(tl->sb, "Expected return action name.\n");
326 2
                vcc_ErrWhere(tl, tl->t);
327 2
                ERRCHK(tl);
328
        }
329 40528
        assert(hand < VCL_RET_MAX);
330
331 40528
        vcc_ProcAction(tl->curproc, hand, tl->t);
332 40528
        vcc_NextToken(tl);
333 40528
        if (tl->t->tok == '(') {
334 5708
                if (hand == VCL_RET_SYNTH)
335 5658
                        vcc_act_return_synth(tl);
336 50
                else if (hand == VCL_RET_VCL)
337 36
                        vcc_act_return_vcl(tl);
338 14
                else if (hand == VCL_RET_PASS)
339 8
                        vcc_act_return_pass(tl);
340 6
                else if (hand == VCL_RET_FAIL)
341 4
                        vcc_act_return_fail(tl);
342
                else {
343 2
                        VSB_printf(tl->sb, "Arguments not allowed.\n");
344 2
                        vcc_ErrWhere(tl, tl->t);
345
                }
346
        } else {
347 34820
                if (hand == VCL_RET_SYNTH || hand == VCL_RET_VCL) {
348 2
                        VSB_printf(tl->sb, "Missing argument.\n");
349 2
                        vcc_ErrWhere(tl, tl->t);
350
                }
351
        }
352 40528
        ERRCHK(tl);
353 40520
        Fb(tl, 1, "VRT_handling(ctx, VCL_RET_%s);\n", h);
354 40520
        SkipToken(tl, ')');
355 40520
        SkipToken(tl, ';');
356
}
357
358
/*--------------------------------------------------------------------*/
359
360
static void v_matchproto_(sym_act_f)
361 6
vcc_act_synthetic(struct vcc *tl, struct token *t, struct symbol *sym)
362
{
363
364
        (void)t;
365
        (void)sym;
366 6
        ExpectErr(tl, '(');
367 6
        ERRCHK(tl);
368 6
        vcc_NextToken(tl);
369
370 6
        Fb(tl, 1, "VRT_synth_page(ctx, ");
371 6
        vcc_Expr(tl, STRING_LIST);
372 6
        ERRCHK(tl);
373 4
        Fb(tl, 1, ");\n");
374
375 4
        SkipToken(tl, ')');
376 4
        SkipToken(tl, ';');
377
}
378
379
/*--------------------------------------------------------------------*/
380
381
// The pp[] trick is to make the length of #name visible to flexelint.
382
#define ACT(name, func, mask)                                           \
383
        do {                                                            \
384
                const char pp[] = #name;                                \
385
                sym = VCC_MkSym(tl, pp, SYM_ACTION, VCL_LOW, VCL_HIGH); \
386
                AN(sym);                                                \
387
                sym->action = func;                                     \
388
                sym->action_mask = (mask);                              \
389
        } while (0)
390
391
void
392 2144
vcc_Action_Init(struct vcc *tl)
393
{
394
        struct symbol *sym;
395
396 2144
        ACT(ban,        vcc_act_ban,    0);
397 2144
        ACT(call,       vcc_act_call,   0);
398 2144
        ACT(hash_data,  vcc_act_hash_data,
399
                VCL_MET_HASH);
400 2144
        ACT(if,         vcc_Act_If,     0);
401 2144
        ACT(new,        vcc_Act_New,
402
                VCL_MET_INIT);
403 2144
        ACT(return,     vcc_act_return, 0);
404 2144
        ACT(set,        vcc_act_set,    0);
405 2144
        ACT(synthetic,  vcc_act_synthetic,
406
                VCL_MET_SYNTH | VCL_MET_BACKEND_ERROR);
407 2144
        ACT(unset,      vcc_act_unset,  0);
408 2144
}