varnish-cache/lib/libvcc/vcc_parse.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
 * 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
 *    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
 * 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
 * SUCH DAMAGE.
29
 */
30
31
#include "config.h"
32
33
#include <string.h>
34
35
#include "vcc_compile.h"
36
37
/*--------------------------------------------------------------------*/
38
39
static void vcc_Compound(struct vcc *tl);
40
41
/*--------------------------------------------------------------------*/
42
43
#define L(tl, foo)      do {    \
44
        tl->indent += INDENT;   \
45
        foo;                    \
46
        tl->indent -= INDENT;   \
47
} while (0)
48
49
#define C(tl, sep)      do {                                            \
50
        Fb(tl, 1, "VPI_count(ctx, VGC_NREFS, %u)%s\n", ++tl->cnt, sep); \
51
        Fb(tl, 1, "if (UNLIKELY(ctx->vpi->trace)) VPI_trace(ctx, %u)%s\n", \
52
           tl->cnt, sep);                                               \
53
        tl->t->cnt = tl->cnt;                                           \
54
} while (0)
55
56
/*--------------------------------------------------------------------
57
 * SYNTAX:
58
 *    Conditional:
59
 *      '(' Cond_0 ')'
60
 */
61
62
static void
63 2005960
vcc_Conditional(struct vcc *tl)
64
{
65
66 2005960
        SkipToken(tl, '(');
67 2005960
        Fb(tl, 0, "(\n");
68 2005960
        L(tl, vcc_Expr(tl, BOOL));
69 2005960
        ERRCHK(tl);
70 2004680
        Fb(tl, 1, ")\n");
71 2004680
        SkipToken(tl, ')');
72 2005960
}
73
74
/*--------------------------------------------------------------------
75
 * SYNTAX:
76
 *    IfStmt:
77
 *      'if' Conditional  Compound Branch1* Branch2
78
 *    Branch1:
79
 *      'elseif' Conditional Compound
80
 *    Branch2:
81
 *      'else' Compound
82
 *      null
83
 */
84
85
void v_matchproto_(sym_act_f)
86 2000520
vcc_Act_If(struct vcc *tl, struct token *t, struct symbol *sym)
87
{
88
89 2000520
        (void)t;
90 2000520
        (void)sym;
91 2000520
        Fb(tl, 1, "if ");
92 2000520
        vcc_Conditional(tl);
93 2000520
        ERRCHK(tl);
94 1999200
        L(tl, vcc_Compound(tl));
95 1999200
        ERRCHK(tl);
96 2004640
        while (tl->t->tok == ID) {
97 484840
                if (vcc_IdIs(tl->t, "else")) {
98 122040
                        vcc_NextToken(tl);
99 122040
                        if (tl->t->tok == '{') {
100 118840
                                Fb(tl, 1, "else\n");
101 118840
                                L(tl, vcc_Compound(tl));
102 118840
                                ERRCHK(tl);
103 118840
                                return;
104
                        }
105 3200
                        if (tl->t->tok != ID || !vcc_IdIs(tl->t, "if")) {
106 0
                                VSB_printf(tl->sb,
107
                                    "'else' must be followed by 'if' or '{'\n");
108 0
                                vcc_ErrWhere(tl, tl->t);
109 0
                                return;
110
                        }
111 3200
                        Fb(tl, 1, "else if ");
112 3200
                        vcc_NextToken(tl);
113 3200
                        vcc_Conditional(tl);
114 3200
                        ERRCHK(tl);
115 3200
                        L(tl, vcc_Compound(tl));
116 3200
                        ERRCHK(tl);
117 726680
                } else if (vcc_IdIs(tl->t, "elseif") ||
118 362720
                     vcc_IdIs(tl->t, "elsif") ||
119 360680
                     vcc_IdIs(tl->t, "elif")) {
120 2240
                        Fb(tl, 1, "else if ");
121 2240
                        vcc_NextToken(tl);
122 2240
                        vcc_Conditional(tl);
123 2240
                        ERRCHK(tl);
124 2240
                        L(tl, vcc_Compound(tl));
125 2240
                        ERRCHK(tl);
126 2240
                } else {
127 360560
                        break;
128
                }
129
        }
130 1880360
        C(tl, ";");
131 2000520
}
132
133
/*--------------------------------------------------------------------
134
 * SYNTAX:
135
 *    Compound:
136
 *      '{' Stmt* '}'
137
 *
138
 *    Stmt:
139
 *      Compound
140
 *      IfStmt
141
 *      CSRC
142
 *      Id(Action) (XXX)
143
 */
144
145
static void
146 6943280
vcc_Compound(struct vcc *tl)
147
{
148
        struct symbol *sym;
149
        struct token *t;
150
151 6943280
        SkipToken(tl, '{');
152 6943280
        Fb(tl, 1, "{\n");
153 6943280
        tl->indent += INDENT;
154 6943280
        C(tl, ";");
155 6943280
        Fb(tl, 1, "END_;\n");
156 17130760
        while (1) {
157 17130760
                ERRCHK(tl);
158 17126200
                t = tl->t;
159 17126200
                switch (tl->t->tok) {
160
                case '{':
161 80
                        vcc_Compound(tl);
162 80
                        break;
163
                case '}':
164 6938520
                        vcc_NextToken(tl);
165 6938520
                        tl->indent -= INDENT;
166 6938520
                        Fb(tl, 1, "}\n");
167 6938520
                        return;
168
                case CSRC:
169 600
                        if (tl->allow_inline_c) {
170 1120
                                Fb(tl, 1, "%.*s\n",
171 560
                                    (int) (tl->t->e - (tl->t->b + 2)),
172 560
                                    tl->t->b + 1);
173 560
                                vcc_NextToken(tl);
174 560
                        } else {
175 40
                                VSB_printf(tl->sb,
176
                                    "Inline-C not allowed\n");
177 40
                                vcc_ErrWhere(tl, tl->t);
178
                        }
179 600
                        break;
180
                case EOI:
181 0
                        VSB_printf(tl->sb,
182
                            "End of input while in compound statement\n");
183 0
                        tl->err = 1;
184 0
                        return;
185
                case ID:
186 10187000
                        sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_NONE,
187
                            SYMTAB_PARTIAL, XREF_NONE);
188 10187000
                        if (sym == NULL) {
189 160
                                VSB_printf(tl->sb, "Symbol not found.\n");
190 160
                                vcc_ErrWhere(tl, t);
191 160
                                return;
192
                        }
193 10186840
                        if (sym->action == NULL) {
194 40
                                VSB_printf(tl->sb,
195
                                    "Symbol cannot be used here.\n");
196 40
                                vcc_ErrWhere(tl, t);
197 40
                                return;
198
                        }
199 10186800
                        if (sym->action_mask != 0)
200 356640
                                vcc_AddUses(tl, t, NULL, sym, XREF_ACTION);
201 10186800
                        sym->action(tl, t, sym);
202 10186800
                        break;
203
                default:
204
                        /* We deliberately do not mention inline C */
205 0
                        VSB_printf(tl->sb,
206
                            "Expected an action, 'if', '{' or '}'\n");
207 0
                        vcc_ErrWhere(tl, tl->t);
208 0
                        return;
209
                }
210 10187480
                Fb(tl, 1, "END_;\n");
211
        }
212 6943280
}
213
214
/*--------------------------------------------------------------------
215
 */
216
217
static void
218 320
vcc_ParseUnused(struct vcc *tl)
219
{
220
        struct symbol *sym;
221
        struct token *t;
222
        struct inifin *ifp;
223
224 320
        vcc_NextToken(tl);
225 320
        ExpectErr(tl, ID);
226 280
        t = tl->t;
227 280
        sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_NONE, SYMTAB_EXISTING, XREF_REF);
228 280
        ERRCHK(tl);
229 240
        AN(sym);
230 360
        if (sym->kind != SYM_BACKEND && sym->kind != SYM_PROBE &&
231 160
            sym->kind != SYM_ACL && sym->kind != SYM_SUB) {
232 80
                vcc_ErrWhere2(tl, t, tl->t);
233 160
                VSB_printf(tl->sb, "Symbol '%s' cannot follow 'unused'.\n",
234 80
                    sym->name);
235 80
                return;
236
        }
237 160
        AN(sym->rname);
238 160
        ifp = New_IniFin(tl);
239 160
        VSB_printf(ifp->ini, "\t(void)%s;\n", sym->rname);
240 160
        ifp->ignore_errors = 1;
241 160
        SkipToken(tl, ';');
242 320
}
243
244
/*--------------------------------------------------------------------
245
 * SYNTAX:
246
 *    Function:
247
 *      'sub' ID(name) Compound
248
 */
249
250
static void
251 4819880
vcc_ParseFunction(struct vcc *tl)
252
{
253
        struct symbol *sym, *bsym;
254
        struct token *t;
255
        struct proc *p;
256
257 4819880
        vcc_NextToken(tl);
258 4819880
        vcc_ExpectVid(tl, "subroutine");
259 4819880
        ERRCHK(tl);
260
261 4819840
        t = tl->t;
262 4819840
        sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_SUB, SYMTAB_CREATE, XREF_DEF);
263 4819840
        ERRCHK(tl);
264 4819800
        AN(sym);
265
266 4819800
        if (vcc_builtin != NULL) {
267 2245000
                vcc_builtin->t = t;
268 2245000
                bsym = VCC_SymbolGet(vcc_builtin, SYM_MAIN, SYM_SUB,
269
                    SYMTAB_NOERR, XREF_NONE);
270 2245000
                AZ(vcc_builtin->err);
271 2245000
        }
272
        else
273 2574800
                bsym = NULL;
274
275 4819800
        p = sym->proc;
276 4819800
        if (p == NULL) {
277 3015120
                if (vcc_builtin != NULL && bsym == NULL &&
278 3280
                    vcc_Has_vcl_prefix(t->b)) {
279 40
                        VSB_printf(tl->sb,"The names 'vcl_*'"
280
                            " are reserved for subroutines.\n");
281 40
                        vcc_ErrWhere(tl, t);
282 40
                        VSB_printf(tl->sb, "Valid vcl_* subroutines are:\n");
283 1680
                        VTAILQ_FOREACH(p, &vcc_builtin->procs, list) {
284 1640
                                t = p->name;
285 3280
                                VSB_printf(tl->sb, "\t%.*s\n",
286 1640
                                    (int)pdiff(t->b, t->e), t->b);
287 1640
                        }
288 40
                        return;
289
                }
290 3015080
                VCC_GlobalSymbol(sym, SUB);
291 3015080
                p = vcc_NewProc(tl, sym);
292 3015080
                p->name = t;
293 3015080
                VSB_printf(p->cname, "%s", sym->lname);
294 4819760
        } else if (p->method == NULL && bsym == NULL) {
295 40
                VSB_printf(tl->sb, "Subroutine '%s' redefined\n", sym->name);
296 40
                vcc_ErrWhere(tl, t);
297 40
                VSB_printf(tl->sb, "Previously defined here:\n");
298 40
                vcc_ErrWhere(tl, p->name);
299 40
                return;
300
        } else {
301
                /* Add to VCL sub */
302 1804640
                if (p->name == NULL)
303 1742480
                        p->name = t;
304
        }
305 4819720
        CHECK_OBJ_NOTNULL(p, PROC_MAGIC);
306 4819720
        tl->fb = p->body;
307 4819720
        Fb(tl, 1, "  /* ... from ");
308 4819720
        vcc_Coord(tl, p->body, NULL);
309 4819720
        Fb(tl, 0, " */\n");
310 4819720
        tl->curproc = p;
311 4819720
        tl->indent += INDENT;
312 4819720
        Fb(tl, 1, "{\n");
313 4819720
        L(tl, vcc_Compound(tl));
314 4819720
        Fb(tl, 1, "}\n");
315 4819720
        tl->indent -= INDENT;
316 4819720
        tl->fb = NULL;
317 4819720
        tl->curproc = NULL;
318 4819880
}
319
320
/*--------------------------------------------------------------------
321
 */
322
323
static void
324 177440
vcc_ParseVcl(struct vcc *tl)
325
{
326
        struct token *tok0;
327
        int syntax;
328
329 177440
        assert(vcc_IdIs(tl->t, "vcl"));
330 177440
        tok0 = tl->t;
331 177440
        vcc_NextToken(tl);
332
333 177440
        Expect(tl, FNUM);
334 177440
        if (tl->t->e - tl->t->b != 3 || tl->t->b[1] != '.') {
335 120
                VSB_cat(tl->sb,
336
                    "Don't play silly buggers with VCL version numbers\n");
337 120
                vcc_ErrWhere(tl, tl->t);
338 120
                ERRCHK(tl);
339 0
        }
340 177320
        syntax = (tl->t->b[0] - '0') * 10 + (tl->t->b[2] - '0');
341 177320
        vcc_NextToken(tl);
342
343 177320
        if (syntax < VCL_LOW || syntax > VCL_HIGH) {
344 160
                VSB_printf(tl->sb, "VCL version %.1f not supported.\n",
345 80
                    .1 * syntax);
346 80
                vcc_ErrWhere2(tl, tok0, tl->t);
347 80
                ERRCHK(tl);
348 0
        }
349
350 177240
        if (tl->t->tok != ';') {
351
                /* Special handling, because next token might be 'vcl'
352
                 * in the built-in VCL, and that would give a very
353
                 * confusing error message
354
                 */
355 40
                VSB_cat(tl->sb, "Expected 'vcl N.N;' found no semi-colon\n");
356 40
                vcc_ErrWhere2(tl, tok0, tl->t);
357 40
                ERRCHK(tl);
358 0
        }
359 177200
        vcc_NextToken(tl);
360 177200
        if (tl->syntax == 0)
361 124000
                tl->syntax = syntax;
362 177200
        if (syntax > tl->syntax) {
363 0
                VSB_printf(tl->sb,
364
                    "VCL version %.1f higher than"
365
                    " the top level version %.1f\n",
366 0
                    .1 * syntax, .1 * tl->syntax);
367 0
                vcc_ErrWhere2(tl, tok0, tl->t);
368 0
                ERRCHK(tl);
369 0
        }
370 177440
}
371
372
/*--------------------------------------------------------------------
373
 * Top level of parser, recognize:
374
 *      Inline C-code
375
 *      ACL definitions
376
 *      Function definitions
377
 *      Backend definitions
378
 *      VMOD import directives
379
 *      VCL version declarations
380
 *      Unused symbols declarations
381
 *      End of input
382
 */
383
384
typedef void parse_f(struct vcc *tl);
385
386
static struct toplev {
387
        const char      *name;
388
        parse_f         *func;
389
        unsigned        vcllo;
390
        unsigned        vclhi;
391
} toplev[] = {
392
        { "acl",                vcc_ParseAcl,           VCL_41, VCL_HIGH },
393
        { "sub",                vcc_ParseFunction,      VCL_41, VCL_HIGH },
394
        { "backend",            vcc_ParseBackend,       VCL_41, VCL_HIGH },
395
        { "probe",              vcc_ParseProbe,         VCL_41, VCL_HIGH },
396
        { "import",             vcc_ParseImport,        VCL_41, VCL_HIGH },
397
        { "vcl",                vcc_ParseVcl,           VCL_41, VCL_HIGH },
398
        { "unused",             vcc_ParseUnused,        VCL_41, VCL_HIGH},
399
        { NULL, NULL }
400
};
401
402
void
403 124200
vcc_Parse(struct vcc *tl)
404
{
405
        struct toplev *tp;
406
407 124200
        AZ(tl->indent);
408 124200
        if (tl->t->tok != ID || !vcc_IdIs(tl->t, "vcl")) {
409 40
                VSB_cat(tl->sb,
410
                    "VCL version declaration missing\n"
411
                    "Update your VCL to Version 4 syntax, and add\n"
412
                    "\tvcl 4.1;\n"
413
                    "on the first line of the VCL files.\n"
414
                );
415 40
                vcc_ErrWhere(tl, tl->t);
416 40
                ERRCHK(tl);
417 0
        }
418 124160
        vcc_ParseVcl(tl);
419 124160
        ERRCHK(tl);
420 124000
        AN(tl->syntax);
421 5093160
        while (tl->t->tok != EOI) {
422 4977320
                ERRCHK(tl);
423 4969240
                switch (tl->t->tok) {
424
                case CSRC:
425 360
                        if (tl->allow_inline_c) {
426 640
                                Fc(tl, 0, "%.*s\n",
427 320
                                    (int) (tl->t->e - (tl->t->b + 4)),
428 320
                                    tl->t->b + 2);
429 320
                                vcc_NextToken(tl);
430 320
                        } else {
431 40
                                VSB_cat(tl->sb, "Inline-C not allowed\n");
432 40
                                vcc_ErrWhere(tl, tl->t);
433
                        }
434 360
                        break;
435
                case EOI:
436 0
                        break;
437
                case ID:
438 10293840
                        for (tp = toplev; tp->name != NULL; tp++) {
439 10293800
                                if (tp->func == NULL)
440 0
                                        continue;
441 10293800
                                if (!vcc_IdIs(tl->t, tp->name))
442 5325000
                                        continue;
443 4968800
                                tp->func(tl);
444 4968800
                                break;
445
                        }
446 4968840
                        if (tp->name != NULL)
447 4968800
                                break;
448
                        /* FALLTHROUGH */
449
                default:
450
                        /* We deliberately do not mention inline-C */
451 80
                        VSB_cat(tl->sb, "Expected one of\n\t");
452 640
                        for (tp = toplev; tp->name != NULL; tp++) {
453 560
                                if (tp[1].name == NULL)
454 80
                                        VSB_cat(tl->sb, " or ");
455 560
                                VSB_printf(tl->sb, "'%s'", tp->name);
456 560
                                if (tp[1].name != NULL)
457 480
                                        VSB_cat(tl->sb, ", ");
458 560
                        }
459 80
                        VSB_cat(tl->sb, "\nFound: ");
460 80
                        vcc_ErrToken(tl, tl->t);
461 80
                        VSB_cat(tl->sb, " at\n");
462 80
                        vcc_ErrWhere(tl, tl->t);
463 80
                        return;
464
                }
465
        }
466 115840
        AZ(tl->indent);
467 124200
}
468
469
void
470 125560
vcc_Parse_Init(struct vcc *tl)
471
{
472
        struct toplev *tp;
473
474 1004480
        for (tp = toplev; tp->name != NULL; tp++)
475 878920
                AN(VCC_MkSym(tl, tp->name, SYM_MAIN, SYM_RESERVED,
476
                    tp->vcllo, tp->vclhi));
477 125560
}