varnish-cache/lib/libvcc/vcc_compile.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
/*
31
 * XXX:
32
 *      Better error messages, throughout.
33
 *      >It also occurred to me that we could link the errors to the error
34
 *      >documentation.
35
 *      >
36
 *      >Unreferenced  function 'request_policy', first mention is
37
 *      >         Line 8 Pos 4
38
 *      >         sub request_policy {
39
 *      >         ----##############--
40
 *      >Read more about this type of error:
41
 *      >http://varnish/doc/error.html#Unreferenced%20function
42
 *      >
43
 *      >
44
 *      >         Unknown variable 'obj.bandwidth'
45
 *      >         At: Line 88 Pos 12
46
 *      >                 if (obj.bandwidth < 1 kb/h) {
47
 *      >         ------------#############------------
48
 *      >Read more about this type of error:
49
 *      >http://varnish/doc/error.html#Unknown%20variable
50
 *
51
 */
52
53
#include "config.h"
54
55
#include <errno.h>
56
#include <stdarg.h>
57
#include <stdlib.h>
58
#include <string.h>
59
60
#include "vcc_compile.h"
61
62
#include "libvcc.h"
63
#include "vfil.h"
64
65
static const struct method method_tab[] = {
66
        { "none", 0U, 0},
67
#define VCL_MET_MAC(l,U,t,b)    { "vcl_"#l, b, VCL_MET_##U },
68
#include "tbl/vcl_returns.h"
69
        { NULL, 0U, 0}
70
};
71
72
/*--------------------------------------------------------------------*/
73
74
void * v_matchproto_(TlAlloc)
75 786347
TlAlloc(struct vcc *tl, unsigned len)
76
{
77
        void *p;
78
79
        (void)tl;
80 786347
        p = calloc(1, len);
81 786347
        assert(p != NULL);
82 786347
        return (p);
83
}
84
85
char *
86 29274
TlDup(struct vcc *tl, const char *s)
87
{
88
        char *p;
89
90 29274
        p = TlAlloc(tl, strlen(s) + 1);
91 29274
        AN(p);
92 29274
        strcpy(p, s);
93 29274
        return (p);
94
}
95
96
/*--------------------------------------------------------------------*/
97
98
struct proc *
99 12701
vcc_NewProc(struct vcc *tl, struct symbol *sym)
100
{
101
        struct proc *p;
102
103 12701
        ALLOC_OBJ(p, PROC_MAGIC);
104 12701
        AN(p);
105 12701
        VTAILQ_INIT(&p->calls);
106 12701
        VTAILQ_INIT(&p->uses);
107 12701
        VTAILQ_INSERT_TAIL(&tl->procs, p, list);
108 12701
        p->prologue = VSB_new_auto();
109 12701
        AN(p->prologue);
110 12701
        p->body = VSB_new_auto();
111 12701
        AN(p->body);
112 12701
        p->cname = VSB_new_auto();
113 12701
        AN(p->cname);
114 12701
        sym->proc = p;
115 12701
        return (p);
116
}
117
118
static void
119 10576
vcc_EmitProc(struct vcc *tl, struct proc *p)
120
{
121 10576
        AZ(VSB_finish(p->cname));
122 10576
        AZ(VSB_finish(p->prologue));
123 10576
        AZ(VSB_finish(p->body));
124 10576
        Fh(tl, 1, "vcl_func_f %s;\n", VSB_data(p->cname));
125 10576
        Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_f)\n");
126 10576
        Fc(tl, 1, "%s(VRT_CTX)\n", VSB_data(p->cname));
127 10576
        Fc(tl, 1, "{\n%s\n%s}\n", VSB_data(p->prologue), VSB_data(p->body));
128 10576
        VSB_destroy(&p->body);
129 10576
        VSB_destroy(&p->prologue);
130 10576
        VSB_destroy(&p->cname);
131 10576
}
132
133
/*--------------------------------------------------------------------*/
134
135
struct inifin *
136 3701
New_IniFin(struct vcc *tl)
137
{
138
        struct inifin *p;
139
140 3701
        p = TlAlloc(tl, sizeof *p);
141 3701
        AN(p);
142 3701
        p->magic = INIFIN_MAGIC;
143 3701
        p->ini = VSB_new_auto();
144 3701
        p->fin = VSB_new_auto();
145 3701
        p->event = VSB_new_auto();
146 3701
        p->n = ++tl->ninifin;
147 3701
        VTAILQ_INSERT_TAIL(&tl->inifin, p, list);
148 3701
        return (p);
149
}
150
151
/*--------------------------------------------------------------------
152
 * Printf output to the vsbs, possibly indented
153
 */
154
155
void
156 48044
Fh(const struct vcc *tl, int indent, const char *fmt, ...)
157
{
158
        va_list ap;
159
160 48044
        if (indent)
161 11335
                VSB_printf(tl->fh, "%*.*s", tl->hindent, tl->hindent, "");
162 48044
        va_start(ap, fmt);
163 48044
        VSB_vprintf(tl->fh, fmt, ap);
164 48044
        va_end(ap);
165 48044
}
166
167
void
168 228515
Fb(const struct vcc *tl, int indent, const char *fmt, ...)
169
{
170
        va_list ap;
171
172 228515
        assert(tl->fb != NULL);
173 228515
        if (indent)
174 199369
                VSB_printf(tl->fb, "%*.*s", tl->indent, tl->indent, "");
175 228515
        va_start(ap, fmt);
176 228515
        VSB_vprintf(tl->fb, fmt, ap);
177 228515
        va_end(ap);
178 228515
}
179
180
void
181 676105
Fc(const struct vcc *tl, int indent, const char *fmt, ...)
182
{
183
        va_list ap;
184
185 676105
        if (indent)
186 31728
                VSB_printf(tl->fc, "%*.*s", tl->indent, tl->indent, "");
187 676105
        va_start(ap, fmt);
188 676105
        VSB_vprintf(tl->fc, fmt, ap);
189 676105
        va_end(ap);
190 676105
}
191
192
/*--------------------------------------------------------------------*/
193
194
void
195 28373
EncToken(struct vsb *sb, const struct token *t)
196
{
197
198 28373
        assert(t->tok == CSTR);
199 28373
        VSB_quote(sb, t->dec, -1, VSB_QUOTE_CSTR);
200 28373
}
201
202
/*--------------------------------------------------------------------
203
 * Output the location/profiling table.  For each counted token, we
204
 * record source+line+charpos for the first character in the token.
205
 */
206
207
static void
208 755
EmitCoordinates(const struct vcc *tl, struct vsb *vsb)
209
{
210
        struct token *t;
211
        unsigned lin, pos;
212
        struct source *sp;
213
        const char *p;
214
215 755
        VSB_printf(vsb, "/* ---===### Source Code ###===---*/\n");
216
217 755
        VSB_printf(vsb, "\n#define VGC_NSRCS %u\n", tl->nsources);
218
219 755
        VSB_printf(vsb, "\nstatic const char *srcname[VGC_NSRCS] = {\n");
220 2284
        VTAILQ_FOREACH(sp, &tl->sources, list) {
221 1529
                VSB_printf(vsb, "\t");
222 1529
                VSB_quote(vsb, sp->name, -1, VSB_QUOTE_CSTR);
223 1529
                VSB_printf(vsb, ",\n");
224
        }
225 755
        VSB_printf(vsb, "};\n");
226
227 755
        VSB_printf(vsb, "\nstatic const char *srcbody[%u] = {\n", tl->nsources);
228 2284
        VTAILQ_FOREACH(sp, &tl->sources, list) {
229 1529
                VSB_printf(vsb, "    /* ");
230 1529
                VSB_quote(vsb, sp->name, -1, VSB_QUOTE_CSTR);
231 1529
                VSB_printf(vsb, "*/\n");
232 1529
                VSB_printf(vsb, "\t");
233 1529
                VSB_quote(vsb, sp->b, sp->e - sp->b, VSB_QUOTE_CSTR);
234 1529
                VSB_printf(vsb, ",\n");
235
        }
236 755
        VSB_printf(vsb, "};\n\n");
237
238 755
        VSB_printf(vsb, "/* ---===### Location Counters ###===---*/\n");
239
240 755
        VSB_printf(vsb, "\n#define VGC_NREFS %u\n\n", tl->cnt + 1);
241
242 755
        VSB_printf(vsb, "static const struct vrt_ref VGC_ref[VGC_NREFS] = {\n");
243 755
        lin = 1;
244 755
        pos = 0;
245 755
        sp = 0;
246 755
        p = NULL;
247 361458
        VTAILQ_FOREACH(t, &tl->tokens, list) {
248 360703
                if (t->cnt == 0)
249 334085
                        continue;
250 26618
                assert(t->src != NULL);
251 26618
                if (t->src != sp) {
252 1279
                        lin = 1;
253 1279
                        pos = 0;
254 1279
                        sp = t->src;
255 1279
                        p = sp->b;
256
                }
257 26618
                assert(sp != NULL);
258 26618
                assert(p != NULL);
259 4137594
                for (;p < t->b; p++) {
260 4110976
                        if (*p == '\n') {
261 151295
                                lin++;
262 151295
                                pos = 0;
263 3959681
                        } else if (*p == '\t') {
264 8949
                                pos &= ~7;
265 8949
                                pos += 8;
266
                        } else
267 3950732
                                pos++;
268
269
                }
270 79854
                VSB_printf(vsb, "  [%3u] = { %u, %8tu, %4u, %3u, ",
271 53236
                    t->cnt, sp->idx, t->b - sp->b, lin, pos + 1);
272 26618
                if (t->tok == CSRC)
273 5
                        VSB_printf(vsb, " \"C{\"},\n");
274
                else
275 26613
                        VSB_printf(vsb, " \"%.*s\" },\n", PF(t));
276
        }
277 755
        VSB_printf(vsb, "};\n\n");
278 755
}
279
280
/*--------------------------------------------------------------------
281
 * Init/Fini/Event
282
 *
283
 * We call DISCARD and COLD events in the opposite order of LOAD and
284
 * WARM.
285
 */
286
287
static void
288 755
EmitInitFini(const struct vcc *tl)
289
{
290 755
        struct inifin *p, *q = NULL;
291 755
        unsigned has_event = 0;
292
293 755
        Fh(tl, 0, "\n");
294 755
        Fh(tl, 0, "static unsigned vgc_inistep;\n");
295 755
        Fh(tl, 0, "static unsigned vgc_warmupstep;\n");
296
297
        /*
298
         * LOAD
299
         */
300 755
        Fc(tl, 0, "\nstatic int\nVGC_Load(VRT_CTX)\n{\n\n");
301 755
        Fc(tl, 0, "\tvgc_inistep = 0;\n\n");
302 4314
        VTAILQ_FOREACH(p, &tl->inifin, list) {
303 3559
                AZ(VSB_finish(p->ini));
304 3559
                assert(p->n > 0);
305 3559
                if (VSB_len(p->ini))
306 3437
                        Fc(tl, 0, "\t/* %u */\n%s\n", p->n, VSB_data(p->ini));
307 3559
                Fc(tl, 0, "\tvgc_inistep = %u;\n\n", p->n);
308 3559
                VSB_destroy(&p->ini);
309
310 3559
                AZ(VSB_finish(p->event));
311 3559
                if (VSB_len(p->event))
312 41
                        has_event = 1;
313
        }
314
315 755
        Fc(tl, 0, "\treturn(0);\n");
316 755
        Fc(tl, 0, "}\n");
317
318
        /*
319
         * DISCARD
320
         */
321 755
        Fc(tl, 0, "\nstatic int\nVGC_Discard(VRT_CTX)\n{\n\n");
322
323 755
        Fc(tl, 0, "\tswitch (vgc_inistep) {\n\n");
324 4314
        VTAILQ_FOREACH_REVERSE(p, &tl->inifin, inifinhead, list) {
325 3559
                AZ(VSB_finish(p->fin));
326 3559
                if (q)
327 2804
                        assert(q->n > p->n);
328 3559
                q = p;
329 3559
                if (VSB_len(p->fin)) {
330 2725
                        Fc(tl, 0, "\t\tcase %u :\n", p->n);
331 2725
                        Fc(tl, 0, "\t%s\n", VSB_data(p->fin));
332 2725
                        Fc(tl, 0, "\t\t\t/* FALLTHROUGH */\n");
333
                }
334 3559
                VSB_destroy(&p->fin);
335
        }
336 755
        Fc(tl, 0, "\t}\n");
337
338 755
        Fc(tl, 0, "\treturn (0);\n");
339 755
        Fc(tl, 0, "}\n");
340
341 755
        if (has_event) {
342
                /*
343
                 * WARM
344
                 */
345 41
                Fc(tl, 0, "\nstatic int\n");
346 41
                Fc(tl, 0, "VGC_Warmup(VRT_CTX, enum vcl_event_e ev)\n{\n\n");
347
348 41
                Fc(tl, 0, "\tvgc_warmupstep = 0;\n\n");
349 324
                VTAILQ_FOREACH(p, &tl->inifin, list) {
350 283
                        assert(p->n > 0);
351 283
                        if (VSB_len(p->event)) {
352 41
                                Fc(tl, 0, "\t/* %u */\n", p->n);
353 41
                                Fc(tl, 0, "\tif (%s)\n", VSB_data(p->event));
354 41
                                Fc(tl, 0, "\t\treturn (1);\n");
355 41
                                Fc(tl, 0, "\tvgc_warmupstep = %u;\n\n", p->n);
356
                        }
357
                }
358
359 41
                Fc(tl, 0, "\treturn (0);\n");
360 41
                Fc(tl, 0, "}\n");
361
362
                /*
363
                 * COLD
364
                 */
365 41
                Fc(tl, 0, "\nstatic int\n");
366 41
                Fc(tl, 0, "VGC_Cooldown(VRT_CTX, enum vcl_event_e ev)\n{\n");
367 41
                Fc(tl, 0, "\tint retval = 0;\n\n");
368
369 324
                VTAILQ_FOREACH_REVERSE(p, &tl->inifin, inifinhead, list) {
370 283
                        if (VSB_len(p->event)) {
371 41
                                Fc(tl, 0, "\t/* %u */\n", p->n);
372 41
                                Fc(tl, 0,
373
                                    "\tif (vgc_warmupstep >= %u &&\n", p->n);
374 41
                                Fc(tl, 0,
375 41
                                    "\t    %s != 0)\n", VSB_data(p->event));
376 41
                                Fc(tl, 0, "\t\tretval = 1;\n\n");
377
                        }
378 283
                        VSB_destroy(&p->event);
379
                }
380
381 41
                Fc(tl, 0, "\treturn (retval);\n");
382 41
                Fc(tl, 0, "}\n");
383
        }
384
385
        /*
386
         * EVENTS
387
         */
388 755
        Fc(tl, 0, "\nstatic int\n");
389 755
        Fc(tl, 0, "VGC_Event(VRT_CTX, enum vcl_event_e ev)\n");
390 755
        Fc(tl, 0, "{\n");
391 755
        Fc(tl, 0, "\tif (ev == VCL_EVENT_LOAD)\n");
392 755
        Fc(tl, 0, "\t\treturn (VGC_Load(ctx));\n");
393 755
        if (has_event) {
394 41
                Fc(tl, 0, "\tif (ev == VCL_EVENT_WARM)\n");
395 41
                Fc(tl, 0, "\t\treturn (VGC_Warmup(ctx, ev));\n");
396 41
                Fc(tl, 0, "\tif (ev == VCL_EVENT_COLD)\n");
397 41
                Fc(tl, 0, "\t\treturn (VGC_Cooldown(ctx, ev));\n");
398
        }
399 755
        Fc(tl, 0, "\tif (ev == VCL_EVENT_DISCARD)\n");
400 755
        Fc(tl, 0, "\t\treturn (VGC_Discard(ctx));\n");
401 755
        Fc(tl, 0, "\n");
402 755
        if (!has_event)
403 714
                Fc(tl, 0, "\t(void)vgc_warmupstep;\n");
404 755
        Fc(tl, 0, "\treturn (%d);\n", has_event ? 1 : 0);
405 755
        Fc(tl, 0, "}\n");
406 755
}
407
408
/*--------------------------------------------------------------------*/
409
410
static void
411 755
EmitStruct(const struct vcc *tl)
412
{
413 755
        Fc(tl, 0, "\nconst struct VCL_conf VCL_conf = {\n");
414 755
        Fc(tl, 0, "\t.magic = VCL_CONF_MAGIC,\n");
415 755
        Fc(tl, 0, "\t.event_vcl = VGC_Event,\n");
416 755
        Fc(tl, 0, "\t.default_director = &%s,\n", tl->default_director);
417 755
        if (tl->default_probe != NULL)
418 2
                Fc(tl, 0, "\t.default_probe = %s,\n", tl->default_probe);
419 755
        Fc(tl, 0, "\t.ref = VGC_ref,\n");
420 755
        Fc(tl, 0, "\t.nref = VGC_NREFS,\n");
421 755
        Fc(tl, 0, "\t.nsrc = VGC_NSRCS,\n");
422 755
        Fc(tl, 0, "\t.srcname = srcname,\n");
423 755
        Fc(tl, 0, "\t.srcbody = srcbody,\n");
424
#define VCL_MET_MAC(l,u,t,b) \
425
        Fc(tl, 0, "\t." #l "_func = VGC_function_vcl_" #l ",\n");
426
#include "tbl/vcl_returns.h"
427 755
        Fc(tl, 0, "};\n");
428 755
}
429
430
/*--------------------------------------------------------------------*/
431
432
static struct source *
433 1826
vcc_new_source(const char *b, const char *e, const char *name)
434
{
435
        struct source *sp;
436
437 1826
        if (e == NULL)
438 1826
                e = strchr(b, '\0');
439 1826
        sp = calloc(1, sizeof *sp);
440 1826
        assert(sp != NULL);
441 1826
        sp->name = strdup(name);
442 1826
        AN(sp->name);
443 1826
        sp->b = b;
444 1826
        sp->e = e;
445 1826
        return (sp);
446
}
447
448
/*--------------------------------------------------------------------*/
449
450
static struct source *
451 27
vcc_file_source(const struct vcc *tl, const char *fn)
452
{
453
        char *f, *fnp;
454
        struct source *sp;
455
456 27
        if (!tl->unsafe_path && strchr(fn, '/') != NULL) {
457 1
                VSB_printf(tl->sb, "VCL filename '%s' is unsafe.\n", fn);
458 1
                return (NULL);
459
        }
460 26
        f = NULL;
461 26
        if (VFIL_searchpath(tl->vcl_path, NULL, &f, fn, &fnp) || f == NULL) {
462 2
                VSB_printf(tl->sb, "Cannot read file '%s' (%s)\n",
463 2
                    fnp != NULL ? fnp : fn, strerror(errno));
464 1
                free(fnp);
465 1
                return (NULL);
466
        }
467 25
        sp = vcc_new_source(f, NULL, fnp);
468 25
        free(fnp);
469 25
        sp->freeit = f;
470 25
        return (sp);
471
}
472
473
/*--------------------------------------------------------------------*/
474
475
static void
476 921
vcc_resolve_includes(struct vcc *tl)
477
{
478
        struct token *t, *t1, *t2;
479
        struct source *sp;
480
        struct vsb *vsb;
481
        const char *p;
482
483 846822
        VTAILQ_FOREACH(t, &tl->tokens, list) {
484 422517
                if (t->tok != ID || !vcc_IdIs(t, "include"))
485 422490
                        continue;
486
487 27
                t1 = VTAILQ_NEXT(t, list);
488 27
                AN(t1);                 /* There's always an EOI */
489 27
                if (t1->tok != CSTR) {
490 2
                        VSB_printf(tl->sb,
491
                            "include not followed by string constant.\n");
492 2
                        vcc_ErrWhere(tl, t1);
493 2
                        return;
494
                }
495 25
                t2 = VTAILQ_NEXT(t1, list);
496 25
                AN(t2);                 /* There's always an EOI */
497
498 25
                if (t2->tok != ';') {
499 1
                        VSB_printf(tl->sb,
500
                            "include <string> not followed by semicolon.\n");
501 1
                        vcc_ErrWhere(tl, t1);
502 1
                        return;
503
                }
504
505 24
                if (t1->dec[0] == '.' && t1->dec[1] == '/') {
506
                        /*
507
                         * Nested include filenames, starting with "./" are
508
                         * resolved relative to the VCL file which contains
509
                         * the include directive.
510
                         */
511 8
                        if (t1->src->name[0] != '/') {
512 1
                                VSB_printf(tl->sb,
513
                                    "include \"./xxxxx\"; needs absolute "
514
                                    "filename of including file.\n");
515 1
                                vcc_ErrWhere(tl, t1);
516 1
                                return;
517
                        }
518 7
                        vsb = VSB_new_auto();
519 7
                        AN(vsb);
520 7
                        p = strrchr(t1->src->name, '/');
521 7
                        AN(p);
522 7
                        VSB_bcat(vsb, t1->src->name, p - t1->src->name);
523 7
                        VSB_cat(vsb, t1->dec + 1);
524 7
                        AZ(VSB_finish(vsb));
525 7
                        sp = vcc_file_source(tl, VSB_data(vsb));
526 7
                        VSB_destroy(&vsb);
527
                } else {
528 16
                        sp = vcc_file_source(tl, t1->dec);
529
                }
530 23
                if (sp == NULL) {
531 1
                        vcc_ErrWhere(tl, t1);
532 1
                        return;
533
                }
534 22
                VTAILQ_INSERT_TAIL(&tl->sources, sp, list);
535 22
                sp->idx = tl->nsources++;
536 22
                tl->t = t2;
537 22
                vcc_Lexer(tl, sp);
538
539 22
                VTAILQ_REMOVE(&tl->tokens, t, list);
540 22
                VTAILQ_REMOVE(&tl->tokens, t1, list);
541 22
                VTAILQ_REMOVE(&tl->tokens, t2, list);
542 22
                if (!tl->err)
543 22
                        vcc_resolve_includes(tl);
544 22
                return;
545
        }
546
}
547
548
/*--------------------------------------------------------------------
549
 * Compile the VCL code from the given source and return the C-source
550
 */
551
552
static struct vsb *
553 905
vcc_CompileSource(struct vcc *tl, struct source *sp)
554
{
555
        struct symbol *sym;
556
        struct proc *p;
557
        const struct var *v;
558
        struct vsb *vsb;
559
        struct inifin *ifp;
560
561 905
        vcc_Expr_Init(tl);
562
563 73305
        for (v = vcc_vars; v->name != NULL; v++) {
564 72400
                if (v->fmt == HEADER) {
565 5430
                        sym = VCC_Symbol(tl, NULL, v->name, NULL,
566
                            SYM_NONE, 1);
567 5430
                        sym->wildcard = vcc_Var_Wildcard;
568 5430
                        sym->wildcard_priv = v;
569
                } else {
570 66970
                        sym = VCC_Symbol(tl, NULL, v->name, NULL, SYM_VAR, 1);
571
                }
572 72400
                sym->fmt = v->fmt;
573 72400
                sym->eval = vcc_Eval_Var;
574 72400
                sym->r_methods = v->r_methods;
575 72400
                sym->w_methods = v->w_methods;
576 72400
                sym->lname = v->lname;
577 72400
                REPLACE(sym->rname, v->rname);
578
        }
579
580 905
        Fh(tl, 0, "/* ---===### VCC generated .h code ###===---*/\n");
581 905
        Fc(tl, 0, "\n/* ---===### VCC generated .c code ###===---*/\n");
582 905
        Fh(tl, 0, "\nextern const struct VCL_conf VCL_conf;\n");
583
584
        /* Register and lex the main source */
585 905
        VTAILQ_INSERT_TAIL(&tl->sources, sp, list);
586 905
        sp->idx = tl->nsources++;
587 905
        vcc_Lexer(tl, sp);
588 905
        if (tl->err)
589 6
                return (NULL);
590
591
        /* Register and lex the builtin VCL */
592 899
        sp = vcc_new_source(tl->builtin_vcl, NULL, "Builtin");
593 899
        assert(sp != NULL);
594 899
        VTAILQ_INSERT_TAIL(&tl->sources, sp, list);
595 899
        sp->idx = tl->nsources++;
596 899
        vcc_Lexer(tl, sp);
597 899
        if (tl->err)
598 0
                return (NULL);
599
600
        /* Add "END OF INPUT" token */
601 899
        vcc_AddToken(tl, EOI, sp->e, sp->e);
602 899
        if (tl->err)
603 0
                return (NULL);
604
605
        /* Expand and lex any includes in the token string */
606 899
        vcc_resolve_includes(tl);
607 899
        if (tl->err)
608 5
                return (NULL);
609
610
        /* Parse the token string */
611 894
        tl->t = VTAILQ_FIRST(&tl->tokens);
612 894
        vcc_Parse(tl);
613 894
        if (tl->err)
614 124
                return (NULL);
615
616
        /* Check if we have any backends at all */
617 770
        if (tl->default_director == NULL) {
618 0
                VSB_printf(tl->sb,
619
                    "No backends or directors found in VCL program, "
620
                    "at least one is necessary.\n");
621 0
                tl->err = 1;
622 0
                return (NULL);
623
        }
624
625
        /* Configure the default director */
626 770
        (void)vcc_AddRef(tl, tl->t_default_director, SYM_BACKEND);
627
628
        /* Check for orphans */
629 770
        if (vcc_CheckReferences(tl))
630 6
                return (NULL);
631
632
        /* Check that all action returns are legal */
633 764
        if (vcc_CheckAction(tl) || tl->err)
634 3
                return (NULL);
635
636
        /* Check that all variable uses are legal */
637 761
        if (vcc_CheckUses(tl) || tl->err)
638 6
                return (NULL);
639
640
        /* Tie vcl_init/fini in */
641 755
        ifp = New_IniFin(tl);
642 755
        VSB_printf(ifp->ini, "\tVGC_function_vcl_init(ctx);");
643 755
        VSB_printf(ifp->fin, "\t\tVGC_function_vcl_fini(ctx);");
644
645
        /* Emit method functions */
646 755
        Fh(tl, 1, "\n");
647 11331
        VTAILQ_FOREACH(p, &tl->procs, list)
648 10576
                if (p->method == NULL)
649 6
                        vcc_EmitProc(tl, p);
650 11331
        VTAILQ_FOREACH(p, &tl->procs, list)
651 10576
                if (p->method != NULL)
652 10570
                        vcc_EmitProc(tl, p);
653
654 755
        EmitInitFini(tl);
655
656 755
        EmitStruct(tl);
657
658 755
        VCC_XrefTable(tl);
659
660
        /* Combine it all */
661
662 755
        vsb = VSB_new_auto();
663 755
        AN(vsb);
664
665 755
        AZ(VSB_finish(tl->fi));
666 755
        VSB_cat(vsb, VSB_data(tl->fi));
667
668 755
        vcl_output_lang_h(vsb);
669
670 755
        EmitCoordinates(tl, vsb);
671
672 755
        AZ(VSB_finish(tl->fh));
673 755
        VSB_cat(vsb, VSB_data(tl->fh));
674
675 755
        AZ(VSB_finish(tl->fc));
676 755
        VSB_cat(vsb, VSB_data(tl->fc));
677
678 755
        AZ(VSB_finish(vsb));
679 755
        return (vsb);
680
}
681
682
/*--------------------------------------------------------------------
683
 * Compile the VCL code in the argument.  Error messages, if any are
684
 * formatted into the vsb.
685
 */
686
687
struct vsb *
688 906
VCC_Compile(struct vcc *tl, struct vsb **sb,
689
    const char *vclsrc, const char *vclsrcfile)
690
{
691
        struct source *sp;
692 906
        struct vsb *r = NULL;
693
694 906
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
695 906
        AN(sb);
696 906
        AN(vclsrcfile);
697
698 906
        if (vclsrc != NULL)
699 902
                sp = vcc_new_source(vclsrc, NULL, vclsrcfile);
700
        else
701 4
                sp = vcc_file_source(tl, vclsrcfile);
702 906
        if (sp != NULL)
703 905
                r = vcc_CompileSource(tl, sp);
704 906
        *sb = tl->sb;
705 906
        return (r);
706
}
707
708
/*--------------------------------------------------------------------
709
 * Allocate a compiler instance
710
 */
711
712
struct vcc *
713 906
VCC_New(void)
714
{
715
        struct vcc *tl;
716
        struct symbol *sym;
717
        struct proc *p;
718
        int i;
719
720 906
        ALLOC_OBJ(tl, VCC_MAGIC);
721 906
        AN(tl);
722 906
        VTAILQ_INIT(&tl->inifin);
723 906
        VTAILQ_INIT(&tl->tokens);
724 906
        VTAILQ_INIT(&tl->sources);
725 906
        VTAILQ_INIT(&tl->procs);
726
727 906
        tl->nsources = 0;
728
729 906
        tl->fi = VSB_new_auto();
730 906
        assert(tl->fi != NULL);
731
732 906
        tl->fc = VSB_new_auto();
733 906
        assert(tl->fc != NULL);
734
735 906
        tl->fh = VSB_new_auto();
736 906
        assert(tl->fh != NULL);
737
738 13590
        for (i = 1; i < VCL_MET_MAX; i++) {
739 12684
                sym = VCC_Symbol(tl, NULL,
740
                    method_tab[i].name, NULL, SYM_SUB, 1);
741 12684
                p = vcc_NewProc(tl, sym);
742 12684
                p->method = &method_tab[i];
743 12684
                VSB_printf(p->cname, "VGC_function_%s", p->method->name);
744
        }
745 906
        tl->sb = VSB_new_auto();
746 906
        AN(tl->sb);
747 906
        return (tl);
748
}
749
750
/*--------------------------------------------------------------------
751
 * Configure builtin VCL source code
752
 */
753
754
void
755 906
VCC_Builtin_VCL(struct vcc *vcc, const char *str)
756
{
757
758 906
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
759 906
        REPLACE(vcc->builtin_vcl, str);
760 906
}
761
762
/*--------------------------------------------------------------------
763
 * Configure default VCL source path
764
 */
765
766
void
767 906
VCC_VCL_path(struct vcc *vcc, const char *str)
768
{
769
770 906
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
771 906
        VFIL_setpath(&vcc->vcl_path, str);
772 906
}
773
774
/*--------------------------------------------------------------------
775
 * Configure default VMOD path
776
 */
777
778
void
779 906
VCC_VMOD_path(struct vcc *vcc, const char *str)
780
{
781
782 906
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
783 906
        VFIL_setpath(&vcc->vmod_path, str);
784 906
}
785
786
/*--------------------------------------------------------------------
787
 * Configure settings
788
 */
789
790
void
791 906
VCC_Err_Unref(struct vcc *vcc, unsigned u)
792
{
793
794 906
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
795 906
        vcc->err_unref = u;
796 906
}
797
798
void
799 906
VCC_Allow_InlineC(struct vcc *vcc, unsigned u)
800
{
801
802 906
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
803 906
        vcc->allow_inline_c = u;
804 906
}
805
806
void
807 906
VCC_Unsafe_Path(struct vcc *vcc, unsigned u)
808
{
809
810 906
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
811 906
        vcc->unsafe_path = u;
812 906
}
813
814
/*--------------------------------------------------------------------
815
 * Configure settings
816
 */
817
818
static void
819 36
vcc_predef_vcl(struct vcc *vcc, const char *name)
820
{
821
        struct symbol *sym;
822
823 36
        sym = VCC_Symbol(vcc, NULL, name, NULL, SYM_VCL, 1);
824 36
        AN(sym);
825 36
        sym->fmt = VCL;
826 36
        sym->r_methods = VCL_MET_RECV;
827 36
}
828
829
void
830 1856
VCC_Predef(struct vcc *vcc, const char *type, const char *name)
831
{
832
833 1856
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
834 1856
        if (!strcmp(type, "VCL_STEVEDORE"))
835 1820
                vcc_stevedore(vcc, name);
836 36
        else if (!strcmp(type, "VCL_VCL"))
837 36
                vcc_predef_vcl(vcc, name);
838
        else
839 0
                WRONG("Unknown VCC predef type");
840 1856
}