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