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 125148
vcc_Conditional(struct vcc *tl)
61
{
62
63 125148
        SkipToken(tl, '(');
64 125148
        Fb(tl, 0, "(\n");
65 125148
        L(tl, vcc_Expr(tl, BOOL));
66 125148
        ERRCHK(tl);
67 124836
        Fb(tl, 1, ")\n");
68 124836
        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 113304
vcc_Act_If(struct vcc *tl, struct token *t, struct symbol *sym)
84
{
85
86
        (void)t;
87
        (void)sym;
88 113304
        Fb(tl, 1, "if ");
89 113304
        vcc_Conditional(tl);
90 113304
        ERRCHK(tl);
91 112992
        L(tl, vcc_Compound(tl));
92 112992
        ERRCHK(tl);
93 237828
        while (tl->t->tok == ID) {
94 122004
                if (vcc_IdIs(tl->t, "else")) {
95 22392
                        vcc_NextToken(tl);
96 22392
                        if (tl->t->tok == '{') {
97 11256
                                Fb(tl, 1, "else\n");
98 11256
                                L(tl, vcc_Compound(tl));
99 11256
                                ERRCHK(tl);
100 11256
                                return;
101
                        }
102 11136
                        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 11136
                        Fb(tl, 1, "else if ");
109 11136
                        vcc_NextToken(tl);
110 11136
                        vcc_Conditional(tl);
111 11136
                        ERRCHK(tl);
112 11136
                        L(tl, vcc_Compound(tl));
113 11136
                        ERRCHK(tl);
114 199200
                } else if (vcc_IdIs(tl->t, "elseif") ||
115 198516
                     vcc_IdIs(tl->t, "elsif") ||
116 98928
                     vcc_IdIs(tl->t, "elif")) {
117 708
                        Fb(tl, 1, "else if ");
118 708
                        vcc_NextToken(tl);
119 708
                        vcc_Conditional(tl);
120 708
                        ERRCHK(tl);
121 708
                        L(tl, vcc_Compound(tl));
122 708
                        ERRCHK(tl);
123
                } else {
124
                        break;
125
                }
126
        }
127 101736
        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 299976
vcc_Compound(struct vcc *tl)
144
{
145
        struct symbol *sym;
146
        struct token *t;
147
148 299976
        SkipToken(tl, '{');
149 299976
        Fb(tl, 1, "{\n");
150 299976
        tl->indent += INDENT;
151 299976
        C(tl, ";");
152
        while (1) {
153 1327872
                ERRCHK(tl);
154 812784
                t = tl->t;
155 812784
                switch (tl->t->tok) {
156
                case '{':
157 24
                        vcc_Compound(tl);
158 24
                        break;
159
                case '}':
160 298776
                        vcc_NextToken(tl);
161 298776
                        tl->indent -= INDENT;
162 298776
                        Fb(tl, 1, "}\n");
163 298776
                        return;
164
                case CSRC:
165 84
                        if (tl->allow_inline_c) {
166 144
                                Fb(tl, 1, "%.*s\n",
167 72
                                    (int) (tl->t->e - (tl->t->b + 2)),
168 72
                                    tl->t->b + 1);
169 72
                                vcc_NextToken(tl);
170
                        } else {
171 12
                                VSB_printf(tl->sb,
172
                                    "Inline-C not allowed\n");
173 12
                                vcc_ErrWhere(tl, tl->t);
174
                        }
175 84
                        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 513900
                        sym = VCC_SymbolGet(tl, SYM_NONE, SYMTAB_NOERR,
183
                            XREF_NONE);
184 513900
                        if (sym != NULL && sym->action != NULL) {
185 513840
                                if (sym->action_mask != 0)
186 34284
                                        vcc_AddUses(tl, t, NULL,
187
                                            sym->action_mask,
188
                                            "Not a valid action");
189 513840
                                sym->action(tl, t, sym);
190 513840
                                break;
191
                        }
192
                        /* FALLTHROUGH */
193
                default:
194
                        /* We deliberately do not mention inline C */
195 60
                        VSB_printf(tl->sb,
196
                            "Expected an action, 'if', '{' or '}'\n");
197 60
                        vcc_ErrWhere(tl, tl->t);
198 60
                        return;
199
                }
200 513948
                Fb(tl, 1, "if (*ctx->handling) return;\n");
201
        }
202
}
203
204
/*--------------------------------------------------------------------
205
 * SYNTAX:
206
 *    Function:
207
 *      'sub' ID(name) Compound
208
 */
209
210
static void
211 163908
vcc_ParseFunction(struct vcc *tl)
212
{
213
        struct symbol *sym;
214
        struct token *t;
215
        struct proc *p;
216
217 163908
        vcc_NextToken(tl);
218 163908
        vcc_ExpectVid(tl, "function");
219 163908
        ERRCHK(tl);
220
221 163896
        t = tl->t;
222 163896
        sym = VCC_SymbolGet(tl, SYM_SUB, SYMTAB_CREATE, XREF_DEF);
223 163896
        ERRCHK(tl);
224 163884
        AN(sym);
225 163884
        p = sym->proc;
226 163884
        if (p == NULL) {
227 240
                if ((t->b[0] == 'v'|| t->b[0] == 'V') &&
228 24
                    (t->b[1] == 'c'|| t->b[1] == 'C') &&
229 12
                    (t->b[2] == 'l'|| t->b[2] == 'L')) {
230 12
                        VSB_printf(tl->sb,
231
                            "The names 'vcl*' are reserved for subroutines.\n");
232 12
                        vcc_ErrWhere(tl, t);
233 12
                        VSB_printf(tl->sb, "Valid vcl_* subroutines are:\n");
234 180
                        VTAILQ_FOREACH(p, &tl->procs, list) {
235 168
                                if (p->method != NULL)
236 168
                                        VSB_printf(tl->sb, "\t%s\n",
237 168
                                            p->method->name);
238
                        }
239 12
                        return;
240
                }
241 216
                VCC_GlobalSymbol(sym, SUB, "VGC_function");
242 216
                p = vcc_NewProc(tl, sym);
243 216
                p->name = t;
244 216
                VSB_printf(p->cname, "%s", sym->rname);
245 163656
        } else if (p->method == NULL) {
246 12
                VSB_printf(tl->sb, "Function '%s' redefined\n", sym->name);
247 12
                vcc_ErrWhere(tl, t);
248 12
                VSB_printf(tl->sb, "Previously defined here:\n");
249 12
                vcc_ErrWhere(tl, p->name);
250 12
                return;
251
        } else {
252
                /* Add to VCL sub */
253 163644
                AN(p->method);
254 163644
                if (p->name == NULL)
255 151560
                        p->name = t;
256
        }
257 163860
        CHECK_OBJ_NOTNULL(p, PROC_MAGIC);
258 163860
        tl->fb = p->body;
259 163860
        Fb(tl, 1, "  /* ... from ");
260 163860
        vcc_Coord(tl, p->body, NULL);
261 163860
        Fb(tl, 0, " */\n");
262 163860
        tl->curproc = p;
263 163860
        tl->indent += INDENT;
264 163860
        Fb(tl, 1, "{\n");
265 163860
        L(tl, vcc_Compound(tl));
266 163860
        Fb(tl, 1, "}\n");
267 163860
        tl->indent -= INDENT;
268 163860
        tl->fb = NULL;
269 163860
        tl->curproc = NULL;
270
}
271
272
/*--------------------------------------------------------------------
273
 */
274
275
static void
276 23388
vcc_ParseVcl(struct vcc *tl)
277
{
278
        struct token *tok0, *tok1, *tok2;
279
        int syntax;
280
281 23388
        assert(vcc_IdIs(tl->t, "vcl"));
282 23388
        tok0 = tl->t;
283 23388
        vcc_NextToken(tl);
284
285 23388
        tok1 = tl->t;
286 23388
        Expect(tl, CNUM);
287 23388
        syntax = (*tl->t->b - '0') * 10;
288 23388
        vcc_NextToken(tl);
289 23388
        Expect(tl, '.');
290 23388
        vcc_NextToken(tl);
291
292 23388
        Expect(tl, CNUM);
293 23388
        tok2 = tl->t;
294 23388
        syntax += (*tl->t->b - '0');
295 23388
        vcc_NextToken(tl);
296
297 23388
        if (tok1->e - tok1->b != 1 || tok2->e - tok2->b != 1) {
298 36
                VSB_printf(tl->sb,
299
                    "Don't play silly buggers with VCL version numbers\n");
300 36
                vcc_ErrWhere2(tl, tok0, tl->t);
301 36
                ERRCHK(tl);
302
        }
303
304 23352
        if (syntax < VCL_LOW || syntax > VCL_HIGH) {
305 24
                VSB_printf(tl->sb, "VCL version %.1f not supported.\n",
306
                    .1 * syntax);
307 24
                vcc_ErrWhere2(tl, tok0, tl->t);
308 24
                ERRCHK(tl);
309
        }
310
311 23328
        if (tl->t->tok != ';') {
312
                /* Special handling, because next token might be 'vcl'
313
                 * in the built-in VCL, and that would give a very
314
                 * confusing error message
315
                 */
316 12
                VSB_printf(tl->sb,
317
                    "Expected 'vcl N.N;' found no semi-colon\n");
318 12
                vcc_ErrWhere2(tl, tok0, tl->t);
319 12
                ERRCHK(tl);
320
        }
321 23316
        vcc_NextToken(tl);
322 23316
        if (tl->syntax == 0)
323 12552
                tl->syntax = syntax;
324 23316
        if (syntax > tl->syntax) {
325 0
                VSB_printf(tl->sb,
326
                    "VCL version %.1f higher than"
327
                    " the top level version %.1f\n",
328 0
                    .1 * syntax, .1 * tl->syntax);
329 0
                vcc_ErrWhere2(tl, tok0, tl->t);
330 0
                ERRCHK(tl);
331
        }
332
}
333
334
/*--------------------------------------------------------------------
335
 * Top level of parser, recognize:
336
 *      Inline C-code
337
 *      ACL definitions
338
 *      Function definitions
339
 *      Backend definitions
340
 *      VMOD import directives
341
 *      VCL version declarations
342
 *      End of input
343
 */
344
345
typedef void parse_f(struct vcc *tl);
346
347
static struct toplev {
348
        const char      *name;
349
        parse_f         *func;
350
        unsigned        vcllo;
351
        unsigned        vclhi;
352
} toplev[] = {
353
        { "acl",                vcc_ParseAcl,           VCL_41, VCL_HIGH },
354
        { "sub",                vcc_ParseFunction,      VCL_41, VCL_HIGH },
355
        { "backend",            vcc_ParseBackend,       VCL_41, VCL_HIGH },
356
        { "probe",              vcc_ParseProbe,         VCL_41, VCL_HIGH },
357
        { "import",             vcc_ParseImport,        VCL_41, VCL_HIGH },
358
        { "vcl",                vcc_ParseVcl,           VCL_41, VCL_HIGH },
359
        { "default",            NULL,                   VCL_41, VCL_HIGH },
360
        { NULL, NULL }
361
};
362
363
void
364 12624
vcc_Parse(struct vcc *tl)
365
{
366
        struct toplev *tp;
367
368 12624
        AZ(tl->indent);
369 12624
        if (tl->t->tok != ID || !vcc_IdIs(tl->t, "vcl")) {
370 24
                VSB_printf(tl->sb,
371
                    "VCL version declaration missing\n"
372
                    "Update your VCL to Version 4 syntax, and add\n"
373
                    "\tvcl 4.1;\n"
374
                    "on the first line of the VCL files.\n"
375
                );
376 24
                vcc_ErrWhere(tl, tl->t);
377 24
                ERRCHK(tl);
378
        }
379 12600
        vcc_ParseVcl(tl);
380 12600
        ERRCHK(tl);
381 12552
        AN(tl->syntax);
382 218664
        while (tl->t->tok != EOI) {
383 195372
                ERRCHK(tl);
384 193584
                switch (tl->t->tok) {
385
                case CSRC:
386 96
                        if (tl->allow_inline_c) {
387 168
                                Fc(tl, 0, "%.*s\n",
388 84
                                    (int) (tl->t->e - (tl->t->b + 4)),
389 84
                                    tl->t->b + 2);
390 84
                                vcc_NextToken(tl);
391
                        } else {
392 12
                                VSB_printf(tl->sb,
393
                                    "Inline-C not allowed\n");
394 12
                                vcc_ErrWhere(tl, tl->t);
395
                        }
396 96
                        break;
397
                case EOI:
398 0
                        break;
399
                case ID:
400 456816
                        for (tp = toplev; tp->name != NULL; tp++) {
401 456804
                                if (tp->func == NULL)
402 12
                                        continue;
403 456792
                                if (!vcc_IdIs(tl->t, tp->name))
404 263328
                                        continue;
405 193464
                                tp->func(tl);
406 193464
                                break;
407
                        }
408 193476
                        if (tp->name != NULL)
409 193464
                                break;
410
                        /* FALLTHROUGH */
411
                default:
412
                        /* We deliberately do not mention inline-C */
413 24
                        VSB_printf(tl->sb, "Expected one of\n\t");
414 192
                        for (tp = toplev; tp->name != NULL; tp++) {
415 168
                                if (tp[1].name == NULL)
416 24
                                        VSB_printf(tl->sb, " or ");
417 168
                                VSB_printf(tl->sb, "'%s'", tp->name);
418 168
                                if (tp[1].name != NULL)
419 144
                                        VSB_printf(tl->sb, ", ");
420
                        }
421 24
                        VSB_printf(tl->sb, "\nFound: ");
422 24
                        vcc_ErrToken(tl, tl->t);
423 24
                        VSB_printf(tl->sb, " at\n");
424 24
                        vcc_ErrWhere(tl, tl->t);
425 24
                        return;
426
                }
427
        }
428 10740
        AZ(tl->indent);
429
}
430
431
void
432 12756
vcc_Parse_Init(struct vcc *tl)
433
{
434
        struct toplev *tp;
435
436 102048
        for (tp = toplev; tp->name != NULL; tp++)
437 89292
                AN(VCC_MkSym(tl, tp->name, SYM_NONE, tp->vcllo, tp->vclhi));
438 12756
}