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