source: lib/libvcl/vcc_action.c @ c5c9e33

Revision c5c9e33, 8.4 KB checked in by Poul-Henning Kamp <phk@…>, 3 years ago (diff)

Eliminate a redundant include file

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2011 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
36#include "vcc_compile.h"
37
38/*--------------------------------------------------------------------*/
39
40static void
41parse_call(struct vcc *tl)
42{
43
44        vcc_NextToken(tl);
45        ExpectErr(tl, ID);
46        vcc_AddCall(tl, tl->t);
47        vcc_AddRef(tl, tl->t, SYM_SUB);
48        Fb(tl, 1, "if (VGC_function_%.*s(sp))\n", PF(tl->t));
49        Fb(tl, 1, "\treturn (1);\n");
50        vcc_NextToken(tl);
51        return;
52}
53
54/*--------------------------------------------------------------------*/
55
56static void
57parse_error(struct vcc *tl)
58{
59
60        vcc_NextToken(tl);
61        Fb(tl, 1, "VRT_error(sp,\n");
62        if (tl->t->tok == '(') {
63                vcc_NextToken(tl);
64                vcc_Expr(tl, INT);
65                if (tl->t->tok == ',') {
66                        Fb(tl, 1, ",\n");
67                        vcc_NextToken(tl);
68                        vcc_Expr(tl, STRING);
69                } else
70                        Fb(tl, 1, ", 0\n");
71                SkipToken(tl, ')');
72        } else {
73                vcc_Expr(tl, INT);
74                if (tl->t->tok != ';') {
75                        Fb(tl, 1, ",\n");
76                        vcc_Expr(tl, STRING);
77                } else
78                        Fb(tl, 1, ", 0\n");
79        }
80        Fb(tl, 1, ");\n");
81        Fb(tl, 1, "VRT_done(sp, VCL_RET_ERROR);\n");
82}
83
84/*--------------------------------------------------------------------*/
85
86static const struct arith {
87        enum var_type           type;
88        unsigned                oper;
89        enum var_type           want;
90} arith[] = {
91        { INT,          T_INCR,         INT },
92        { INT,          T_DECR,         INT },
93        { INT,          T_MUL,          INT },
94        { INT,          T_DIV,          INT },
95        { INT,          '=',            INT },
96        { INT,          0,              INT },
97        { TIME,         T_INCR,         DURATION },
98        { TIME,         T_DECR,         DURATION },
99        { TIME,         T_MUL,          REAL },
100        { TIME,         T_DIV,          REAL },
101        { TIME,         '=',            TIME },
102        { TIME,         0,              TIME },
103        { DURATION,     T_INCR,         DURATION },
104        { DURATION,     T_DECR,         DURATION },
105        { DURATION,     T_MUL,          REAL },
106        { DURATION,     T_DIV,          REAL },
107        { DURATION,     '=',            DURATION },
108        { DURATION,     0,              DURATION },
109        { VOID,         '=',            VOID }
110};
111
112static void
113parse_set(struct vcc *tl)
114{
115        const struct var *vp;
116        const struct arith *ap;
117        enum var_type fmt;
118
119        vcc_NextToken(tl);
120        ExpectErr(tl, ID);
121        vp = vcc_FindVar(tl, tl->t, 1, "cannot be set");
122        ERRCHK(tl);
123        assert(vp != NULL);
124        Fb(tl, 1, "%s", vp->lname);
125        vcc_NextToken(tl);
126        fmt = vp->fmt;
127        for (ap = arith; ap->type != VOID; ap++) {
128                if (ap->type != fmt)
129                        continue;
130                if (ap->oper != tl->t->tok)
131                        continue;
132                if (ap->oper != '=')
133                        Fb(tl, 0, "%s %c ", vp->rname, *tl->t->b);
134                vcc_NextToken(tl);
135                fmt = ap->want;
136                break;
137        }
138        if (ap->type == VOID)
139                SkipToken(tl, ap->oper);
140        if (fmt == STRING) {
141                vcc_Expr(tl, STRING_LIST);
142        } else {
143                vcc_Expr(tl, fmt);
144        }
145        Fb(tl, 1, ");\n");
146}
147
148/*--------------------------------------------------------------------*/
149
150static void
151parse_unset(struct vcc *tl)
152{
153        const struct var *vp;
154
155        vcc_NextToken(tl);
156        ExpectErr(tl, ID);
157        vp = vcc_FindVar(tl, tl->t, 1, "cannot be unset");
158        ERRCHK(tl);
159        assert(vp != NULL);
160        if (vp->fmt != STRING || vp->http == NULL) {
161                VSB_printf(tl->sb,
162                    "Only http header variables can be unset.\n");
163                vcc_ErrWhere(tl, tl->t);
164                return;
165        }
166        ERRCHK(tl);
167        Fb(tl, 1, "%s0);\n", vp->lname);
168        vcc_NextToken(tl);
169}
170
171/*--------------------------------------------------------------------*/
172
173static void
174parse_ban(struct vcc *tl)
175{
176
177        vcc_NextToken(tl);
178
179        ExpectErr(tl, '(');
180        vcc_NextToken(tl);
181
182        Fb(tl, 1, "VRT_ban_string(sp, ");
183        vcc_Expr(tl, STRING);
184        ERRCHK(tl);
185        Fb(tl, 0, ");\n");
186
187        ExpectErr(tl, ')');
188        vcc_NextToken(tl);
189}
190
191/*--------------------------------------------------------------------*/
192
193static void
194parse_ban_url(struct vcc *tl)
195{
196
197        vcc_NextToken(tl);
198        ExpectErr(tl, '(');
199        vcc_NextToken(tl);
200
201        Fb(tl, 1, "VRT_ban(sp, \"req.url\", \"~\", ");
202        vcc_Expr(tl, STRING);
203        ERRCHK(tl);
204        ExpectErr(tl, ')');
205        vcc_NextToken(tl);
206        Fb(tl, 0, ", 0);\n");
207}
208
209/*--------------------------------------------------------------------*/
210
211static void
212parse_new_syntax(struct vcc *tl)
213{
214
215        VSB_printf(tl->sb, "Please change \"%.*s\" to \"return(%.*s)\".\n",
216            PF(tl->t), PF(tl->t));
217        vcc_ErrWhere(tl, tl->t);
218}
219
220/*--------------------------------------------------------------------*/
221
222static void
223parse_hash_data(struct vcc *tl)
224{
225        vcc_NextToken(tl);
226        SkipToken(tl, '(');
227
228        Fb(tl, 1, "VRT_hashdata(sp, ");
229        vcc_Expr(tl, STRING_LIST);
230        ERRCHK(tl);
231        Fb(tl, 0, ");\n");
232        SkipToken(tl, ')');
233}
234
235/*--------------------------------------------------------------------*/
236
237static void
238parse_panic(struct vcc *tl)
239{
240        vcc_NextToken(tl);
241
242        Fb(tl, 1, "VRT_panic(sp, ");
243        vcc_Expr(tl, STRING);
244        ERRCHK(tl);
245        Fb(tl, 0, ", vrt_magic_string_end);\n");
246}
247
248/*--------------------------------------------------------------------*/
249
250static void
251parse_return(struct vcc *tl)
252{
253        int retval = 0;
254
255        vcc_NextToken(tl);
256        ExpectErr(tl, '(');
257        vcc_NextToken(tl);
258        ExpectErr(tl, ID);
259
260#define VCL_RET_MAC(l, U, B)                                            \
261        do {                                                            \
262                if (vcc_IdIs(tl->t, #l)) {                              \
263                        Fb(tl, 1, "VRT_done(sp, VCL_RET_" #U ");\n");   \
264                        vcc_ProcAction(tl->curproc, VCL_RET_##U, tl->t);\
265                        retval = 1;                                     \
266                }                                                       \
267        } while (0);
268#include "tbl/vcl_returns.h"
269#undef VCL_RET_MAC
270        if (!retval) {
271                VSB_printf(tl->sb, "Expected return action name.\n");
272                vcc_ErrWhere(tl, tl->t);
273                ERRCHK(tl);
274        }
275        vcc_NextToken(tl);
276        ExpectErr(tl, ')');
277        vcc_NextToken(tl);
278}
279
280/*--------------------------------------------------------------------*/
281
282static void
283parse_rollback(struct vcc *tl)
284{
285
286        vcc_NextToken(tl);
287        Fb(tl, 1, "VRT_Rollback(sp);\n");
288}
289
290/*--------------------------------------------------------------------*/
291
292static void
293parse_purge(struct vcc *tl)
294{
295
296        vcc_NextToken(tl);
297        Fb(tl, 1, "VRT_purge(sp, 0, 0);\n");
298}
299
300/*--------------------------------------------------------------------*/
301
302static void
303parse_synthetic(struct vcc *tl)
304{
305        vcc_NextToken(tl);
306
307        Fb(tl, 1, "VRT_synth_page(sp, 0, ");
308        vcc_Expr(tl, STRING_LIST);
309        ERRCHK(tl);
310        Fb(tl, 0, ");\n");
311}
312
313/*--------------------------------------------------------------------*/
314
315typedef void action_f(struct vcc *tl);
316
317static struct action_table {
318        const char              *name;
319        action_f                *func;
320        unsigned                bitmask;
321} action_table[] = {
322        { "error",              parse_error,
323            VCL_MET_RECV | VCL_MET_PIPE | VCL_MET_PASS | VCL_MET_HASH |
324            VCL_MET_MISS | VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DELIVER
325        },
326
327#define VCL_RET_MAC(l, U, B)                                            \
328        { #l,                   parse_new_syntax },
329#include "tbl/vcl_returns.h"
330#undef VCL_RET_MAC
331
332        /* Keep list sorted from here */
333        { "call",               parse_call },
334        { "hash_data",          parse_hash_data, VCL_MET_HASH },
335        { "panic",              parse_panic },
336        { "ban",                parse_ban },
337        { "ban_url",            parse_ban_url },
338        { "remove",             parse_unset }, /* backward compatibility */
339        { "return",             parse_return },
340        { "rollback",           parse_rollback },
341        { "set",                parse_set },
342        { "synthetic",          parse_synthetic, VCL_MET_ERROR },
343        { "unset",              parse_unset },
344        { "purge",              parse_purge, VCL_MET_MISS | VCL_MET_HIT },
345        { NULL,                 NULL }
346};
347
348int
349vcc_ParseAction(struct vcc *tl)
350{
351        struct token *at;
352        struct action_table *atp;
353        const struct symbol *sym;
354
355        at = tl->t;
356        assert (at->tok == ID);
357        for(atp = action_table; atp->name != NULL; atp++) {
358                if (vcc_IdIs(at, atp->name)) {
359                        if (atp->bitmask != 0)
360                                vcc_AddUses(tl, at, atp->bitmask,
361                                    "not a valid action");
362                        atp->func(tl);
363                        return (1);
364                }
365        }
366        sym = VCC_FindSymbol(tl, tl->t, SYM_NONE);
367        if (sym != NULL && sym->kind == SYM_PROC) {
368                vcc_Expr_Call(tl, sym);
369                return (1);
370        }
371        return (0);
372}
Note: See TracBrowser for help on using the repository browser.