varnish-cache/lib/libvcc/vcc_parse.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
30
#include "config.h"
31
32
#include <string.h>
33
34
#include "vcc_compile.h"
35
36
/*--------------------------------------------------------------------*/
37
38
static void vcc_Compound(struct vcc *tl);
39
40
/*--------------------------------------------------------------------*/
41
42
#define L(tl, foo)      do {    \
43
        tl->indent += INDENT;   \
44
        foo;                    \
45
        tl->indent -= INDENT;   \
46
} while (0)
47
48
#define C(tl, sep)      do {                                    \
49
        Fb(tl, 1, "VRT_count(ctx, %u)%s\n", ++tl->cnt, sep);    \
50
        tl->t->cnt = tl->cnt;                                   \
51
} while (0)
52
53
/*--------------------------------------------------------------------
54
 * SYNTAX:
55
 *    Conditional:
56
 *      '(' Cond_0 ')'
57
 */
58
59
static void
60 21094
vcc_Conditional(struct vcc *tl)
61
{
62
63 21094
        SkipToken(tl, '(');
64 21094
        Fb(tl, 0, "(\n");
65 21094
        L(tl, vcc_Expr(tl, BOOL));
66 21094
        ERRCHK(tl);
67 21042
        Fb(tl, 1, ")\n");
68 21042
        SkipToken(tl, ')');
69
}
70
71
/*--------------------------------------------------------------------
72
 * SYNTAX:
73
 *    IfStmt:
74
 *      'if' Conditional  Compound Branch1* Branch2
75
 *    Branch1:
76
 *      'elseif' Conditional Compound
77
 *    Branch2:
78
 *      'else' Compound
79
 *      null
80
 */
81
82
void v_matchproto_(sym_act_f)
83 19096
vcc_Act_If(struct vcc *tl, struct token *t, struct symbol *sym)
84
{
85
86
        (void)t;
87
        (void)sym;
88 19096
        Fb(tl, 1, "if ");
89 19096
        vcc_Conditional(tl);
90 19096
        ERRCHK(tl);
91 19044
        L(tl, vcc_Compound(tl));
92 19044
        ERRCHK(tl);
93 40086
        while (tl->t->tok == ID) {
94 20562
                if (vcc_IdIs(tl->t, "else")) {
95 3776
                        vcc_NextToken(tl);
96 3776
                        if (tl->t->tok == '{') {
97 1898
                                Fb(tl, 1, "else\n");
98 1898
                                L(tl, vcc_Compound(tl));
99 1898
                                ERRCHK(tl);
100 1898
                                return;
101
                        }
102 1878
                        if (tl->t->tok != ID || !vcc_IdIs(tl->t, "if")) {
103 0
                                VSB_printf(tl->sb,
104
                                    "'else' must be followed by 'if' or '{'\n");
105 0
                                vcc_ErrWhere(tl, tl->t);
106 0
                                return;
107
                        }
108 1878
                        Fb(tl, 1, "else if ");
109 1878
                        vcc_NextToken(tl);
110 1878
                        vcc_Conditional(tl);
111 1878
                        ERRCHK(tl);
112 1878
                        L(tl, vcc_Compound(tl));
113 1878
                        ERRCHK(tl);
114 33568
                } else if (vcc_IdIs(tl->t, "elseif") ||
115 33452
                     vcc_IdIs(tl->t, "elsif") ||
116 16670
                     vcc_IdIs(tl->t, "elif")) {
117 120
                        Fb(tl, 1, "else if ");
118 120
                        vcc_NextToken(tl);
119 120
                        vcc_Conditional(tl);
120 120
                        ERRCHK(tl);
121 120
                        L(tl, vcc_Compound(tl));
122 120
                        ERRCHK(tl);
123
                } else {
124
                        break;
125
                }
126
        }
127 17146
        C(tl, ";");
128
}
129
130
/*--------------------------------------------------------------------
131
 * SYNTAX:
132
 *    Compound:
133
 *      '{' Stmt* '}'
134
 *
135
 *    Stmt:
136
 *      Compound
137
 *      IfStmt
138
 *      CSRC
139
 *      Id(Action) (XXX)
140
 */
141
142
static void
143 50566
vcc_Compound(struct vcc *tl)
144
{
145
        struct symbol *sym;
146
        struct token *t;
147
148 50566
        SkipToken(tl, '{');
149 50566
        Fb(tl, 1, "{\n");
150 50566
        tl->indent += INDENT;
151 50566
        C(tl, ";");
152
        while (1) {
153 223926
                ERRCHK(tl);
154 137056
                t = tl->t;
155 137056
                switch (tl->t->tok) {
156
                case '{':
157 4
                        vcc_Compound(tl);
158 4
                        break;
159
                case '}':
160 50366
                        vcc_NextToken(tl);
161 50366
                        tl->indent -= INDENT;
162 50366
                        Fb(tl, 1, "}\n");
163 50366
                        return;
164
                case CSRC:
165 14
                        if (tl->allow_inline_c) {
166 24
                                Fb(tl, 1, "%.*s\n",
167 12
                                    (int) (tl->t->e - (tl->t->b + 2)),
168 12
                                    tl->t->b + 1);
169 12
                                vcc_NextToken(tl);
170
                        } else {
171 2
                                VSB_printf(tl->sb,
172
                                    "Inline-C not allowed\n");
173 2
                                vcc_ErrWhere(tl, tl->t);
174
                        }
175 14
                        break;
176
                case EOI:
177 0
                        VSB_printf(tl->sb,
178
                            "End of input while in compound statement\n");
179 0
                        tl->err = 1;
180 0
                        return;
181
                case ID:
182 86672
                        sym = VCC_SymbolGet(tl, SYM_NONE, SYMTAB_NOERR,
183
                            XREF_NONE);
184 86672
                        if (sym == NULL) {
185 10
                                VSB_printf(tl->sb, "Symbol not found.\n");
186 10
                                vcc_ErrWhere(tl, tl->t);
187 10
                                return;
188
                        }
189 86662
                        if (sym->action == NULL) {
190 0
                                VSB_printf(tl->sb,
191
                                    "Symbol cannot be used here.\n");
192 0
                                vcc_ErrWhere(tl, tl->t);
193 0
                                return;
194
                        }
195 86662
                        if (sym->action_mask != 0)
196 5778
                                vcc_AddUses(tl, t, NULL,
197
                                    sym->action_mask,
198
                                    "Not a valid action");
199 86662
                        sym->action(tl, t, sym);
200 86662
                        break;
201
                default:
202
                        /* We deliberately do not mention inline C */
203 0
                        VSB_printf(tl->sb,
204
                            "Expected an action, 'if', '{' or '}'\n");
205 0
                        vcc_ErrWhere(tl, tl->t);
206 0
                        return;
207
                }
208 86680
                Fb(tl, 1, "if (*ctx->handling) return;\n");
209
        }
210
}
211
212
/*--------------------------------------------------------------------
213
 * SYNTAX:
214
 *    Function:
215
 *      'sub' ID(name) Compound
216
 */
217
218
static void
219 27630
vcc_ParseFunction(struct vcc *tl)
220
{
221
        struct symbol *sym;
222
        struct token *t;
223
        struct proc *p;
224
225 27630
        vcc_NextToken(tl);
226 27630
        vcc_ExpectVid(tl, "function");
227 27630
        ERRCHK(tl);
228
229 27628
        t = tl->t;
230 27628
        sym = VCC_SymbolGet(tl, SYM_SUB, SYMTAB_CREATE, XREF_DEF);
231 27628
        ERRCHK(tl);
232 27626
        AN(sym);
233 27626
        p = sym->proc;
234 27626
        if (p == NULL) {
235 42
                if ((t->b[0] == 'v'|| t->b[0] == 'V') &&
236 4
                    (t->b[1] == 'c'|| t->b[1] == 'C') &&
237 2
                    (t->b[2] == 'l'|| t->b[2] == 'L')) {
238 2
                        VSB_printf(tl->sb,
239
                            "The names 'vcl*' are reserved for subroutines.\n");
240 2
                        vcc_ErrWhere(tl, t);
241 2
                        VSB_printf(tl->sb, "Valid vcl_* subroutines are:\n");
242 30
                        VTAILQ_FOREACH(p, &tl->procs, list) {
243 28
                                if (p->method != NULL)
244 28
                                        VSB_printf(tl->sb, "\t%s\n",
245 28
                                            p->method->name);
246
                        }
247 2
                        return;
248
                }
249 38
                VCC_GlobalSymbol(sym, SUB, "VGC_function");
250 38
                p = vcc_NewProc(tl, sym);
251 38
                p->name = t;
252 38
                VSB_printf(p->cname, "%s", sym->rname);
253 27586
        } else if (p->method == NULL) {
254 2
                VSB_printf(tl->sb, "Function '%s' redefined\n", sym->name);
255 2
                vcc_ErrWhere(tl, t);
256 2
                VSB_printf(tl->sb, "Previously defined here:\n");
257 2
                vcc_ErrWhere(tl, p->name);
258 2
                return;
259
        } else {
260
                /* Add to VCL sub */
261 27584
                AN(p->method);
262 27584
                if (p->name == NULL)
263 25540
                        p->name = t;
264
        }
265 27622
        CHECK_OBJ_NOTNULL(p, PROC_MAGIC);
266 27622
        tl->fb = p->body;
267 27622
        Fb(tl, 1, "  /* ... from ");
268 27622
        vcc_Coord(tl, p->body, NULL);
269 27622
        Fb(tl, 0, " */\n");
270 27622
        tl->curproc = p;
271 27622
        tl->indent += INDENT;
272 27622
        Fb(tl, 1, "{\n");
273 27622
        L(tl, vcc_Compound(tl));
274 27622
        Fb(tl, 1, "}\n");
275 27622
        tl->indent -= INDENT;
276 27622
        tl->fb = NULL;
277 27622
        tl->curproc = NULL;
278
}
279
280
/*--------------------------------------------------------------------
281
 */
282
283
static void
284 3938
vcc_ParseVcl(struct vcc *tl)
285
{
286
        struct token *tok0;
287
        int syntax;
288
289 3938
        assert(vcc_IdIs(tl->t, "vcl"));
290 3938
        tok0 = tl->t;
291 3938
        vcc_NextToken(tl);
292
293 3938
        Expect(tl, FNUM);
294 3938
        if (tl->t->e - tl->t->b != 3 || tl->t->b[1] != '.') {
295 6
                VSB_printf(tl->sb,
296
                    "Don't play silly buggers with VCL version numbers\n");
297 6
                vcc_ErrWhere(tl, tl->t);
298 6
                ERRCHK(tl);
299
        }
300 3932
        syntax = (tl->t->b[0] - '0') * 10 + (tl->t->b[2] - '0');
301 3932
        vcc_NextToken(tl);
302
303 3932
        if (syntax < VCL_LOW || syntax > VCL_HIGH) {
304 4
                VSB_printf(tl->sb, "VCL version %.1f not supported.\n",
305
                    .1 * syntax);
306 4
                vcc_ErrWhere2(tl, tok0, tl->t);
307 4
                ERRCHK(tl);
308
        }
309
310 3928
        if (tl->t->tok != ';') {
311
                /* Special handling, because next token might be 'vcl'
312
                 * in the built-in VCL, and that would give a very
313
                 * confusing error message
314
                 */
315 2
                VSB_printf(tl->sb,
316
                    "Expected 'vcl N.N;' found no semi-colon\n");
317 2
                vcc_ErrWhere2(tl, tok0, tl->t);
318 2
                ERRCHK(tl);
319
        }
320 3926
        vcc_NextToken(tl);
321 3926
        if (tl->syntax == 0)
322 2112
                tl->syntax = syntax;
323 3926
        if (syntax > tl->syntax) {
324 0
                VSB_printf(tl->sb,
325
                    "VCL version %.1f higher than"
326
                    " the top level version %.1f\n",
327 0
                    .1 * syntax, .1 * tl->syntax);
328 0
                vcc_ErrWhere2(tl, tok0, tl->t);
329 0
                ERRCHK(tl);
330
        }
331
}
332
333
/*--------------------------------------------------------------------
334
 * Top level of parser, recognize:
335
 *      Inline C-code
336
 *      ACL definitions
337
 *      Function definitions
338
 *      Backend definitions
339
 *      VMOD import directives
340
 *      VCL version declarations
341
 *      End of input
342
 */
343
344
typedef void parse_f(struct vcc *tl);
345
346
static struct toplev {
347
        const char      *name;
348
        parse_f         *func;
349
        unsigned        vcllo;
350
        unsigned        vclhi;
351
} toplev[] = {
352
        { "acl",                vcc_ParseAcl,           VCL_41, VCL_HIGH },
353
        { "sub",                vcc_ParseFunction,      VCL_41, VCL_HIGH },
354
        { "backend",            vcc_ParseBackend,       VCL_41, VCL_HIGH },
355
        { "probe",              vcc_ParseProbe,         VCL_41, VCL_HIGH },
356
        { "import",             vcc_ParseImport,        VCL_41, VCL_HIGH },
357
        { "vcl",                vcc_ParseVcl,           VCL_41, VCL_HIGH },
358
        { "default",            NULL,                   VCL_41, VCL_HIGH },
359
        { NULL, NULL }
360
};
361
362
void
363 2122
vcc_Parse(struct vcc *tl)
364
{
365
        struct toplev *tp;
366
367 2122
        AZ(tl->indent);
368 2122
        if (tl->t->tok != ID || !vcc_IdIs(tl->t, "vcl")) {
369 2
                VSB_printf(tl->sb,
370
                    "VCL version declaration missing\n"
371
                    "Update your VCL to Version 4 syntax, and add\n"
372
                    "\tvcl 4.1;\n"
373
                    "on the first line of the VCL files.\n"
374
                );
375 2
                vcc_ErrWhere(tl, tl->t);
376 2
                ERRCHK(tl);
377
        }
378 2120
        vcc_ParseVcl(tl);
379 2120
        ERRCHK(tl);
380 2112
        AN(tl->syntax);
381 36854
        while (tl->t->tok != EOI) {
382 32932
                ERRCHK(tl);
383 32634
                switch (tl->t->tok) {
384
                case CSRC:
385 16
                        if (tl->allow_inline_c) {
386 28
                                Fc(tl, 0, "%.*s\n",
387 14
                                    (int) (tl->t->e - (tl->t->b + 4)),
388 14
                                    tl->t->b + 2);
389 14
                                vcc_NextToken(tl);
390
                        } else {
391 2
                                VSB_printf(tl->sb,
392
                                    "Inline-C not allowed\n");
393 2
                                vcc_ErrWhere(tl, tl->t);
394
                        }
395 16
                        break;
396
                case EOI:
397 0
                        break;
398
                case ID:
399 77032
                        for (tp = toplev; tp->name != NULL; tp++) {
400 77030
                                if (tp->func == NULL)
401 2
                                        continue;
402 77028
                                if (!vcc_IdIs(tl->t, tp->name))
403 44414
                                        continue;
404 32614
                                tp->func(tl);
405 32614
                                break;
406
                        }
407 32616
                        if (tp->name != NULL)
408 32614
                                break;
409
                        /* FALLTHROUGH */
410
                default:
411
                        /* We deliberately do not mention inline-C */
412 4
                        VSB_printf(tl->sb, "Expected one of\n\t");
413 32
                        for (tp = toplev; tp->name != NULL; tp++) {
414 28
                                if (tp[1].name == NULL)
415 4
                                        VSB_printf(tl->sb, " or ");
416 28
                                VSB_printf(tl->sb, "'%s'", tp->name);
417 28
                                if (tp[1].name != NULL)
418 24
                                        VSB_printf(tl->sb, ", ");
419
                        }
420 4
                        VSB_printf(tl->sb, "\nFound: ");
421 4
                        vcc_ErrToken(tl, tl->t);
422 4
                        VSB_printf(tl->sb, " at\n");
423 4
                        vcc_ErrWhere(tl, tl->t);
424 4
                        return;
425
                }
426
        }
427 1810
        AZ(tl->indent);
428
}
429
430
void
431 2144
vcc_Parse_Init(struct vcc *tl)
432
{
433
        struct toplev *tp;
434
435 17152
        for (tp = toplev; tp->name != NULL; tp++)
436 15008
                AN(VCC_MkSym(tl, tp->name, SYM_NONE, tp->vcllo, tp->vclhi));
437 2144
}