varnish-cache/lib/libvcc/vcc_compile.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
31
/*
32
 * XXX:
33
 *      Better error messages, throughout.
34
 *      >It also occurred to me that we could link the errors to the error
35
 *      >documentation.
36
 *      >
37
 *      >Unreferenced  function 'request_policy', first mention is
38
 *      >         Line 8 Pos 4
39
 *      >         sub request_policy {
40
 *      >         ----##############--
41
 *      >Read more about this type of error:
42
 *      >http://varnish/doc/error.html#Unreferenced%20function
43
 *      >
44
 *      >
45
 *      >         Unknown variable 'obj.bandwidth'
46
 *      >         At: Line 88 Pos 12
47
 *      >                 if (obj.bandwidth < 1 kb/h) {
48
 *      >         ------------#############------------
49
 *      >Read more about this type of error:
50
 *      >http://varnish/doc/error.html#Unknown%20variable
51
 *
52
 */
53
54
#include "config.h"
55
56
#include <fcntl.h>
57
#include <stdarg.h>
58
#include <stdlib.h>
59
#include <string.h>
60
#include <unistd.h>
61
62
#include "vcc_compile.h"
63
64
#include "libvcc.h"
65
#include "vfil.h"
66
#include "vct.h"
67
68
static const struct method method_tab[] = {
69
        { "none", 0U, 0},
70
#define VCL_MET_MAC(l,U,t,b)    { "vcl_"#l, b, VCL_MET_##U },
71
#include "tbl/vcl_returns.h"
72
        { NULL, 0U, 0}
73
};
74
75
struct vcc *vcc_builtin;
76
77
/*--------------------------------------------------------------------*/
78
79
static void
80 1026075
vcc_vcl_met2c(struct vsb *vsb, unsigned method)
81
{
82 1026075
        int d = 0;
83
84
        //lint -e{774} Boolean within 'if' always evaluates to False
85
#define VCL_MET_MAC(l,U,t,b)                            \
86
        do {                                            \
87
                if (method & VCL_MET_##U) {             \
88
                        if (d)                          \
89
                                VSB_putc(vsb, '|');     \
90
                        VSB_cat(vsb, "VCL_MET_" #U);    \
91
                        d = 1;                          \
92
                }                                       \
93
        } while (0);
94
#include "tbl/vcl_returns.h"
95 1026075
        AN(d);
96 1026075
}
97
98
99
/*--------------------------------------------------------------------*/
100
101
void * v_matchproto_(TlAlloc)
102 83674350
TlAlloc(struct vcc *tl, unsigned len)
103
{
104
        void *p;
105
106 83674350
        (void)tl;
107 83674350
        p = calloc(1, len);
108 83674350
        assert(p != NULL);
109 83674350
        return (p);
110
}
111
112 1055350
char *
113 4269100
TlDup(struct vcc *tl, const char *s)
114
{
115
        char *p;
116
117 4269100
        p = TlAlloc(tl, strlen(s) + 1);
118 4269100
        AN(p);
119 5324450
        strcpy(p, s);
120 4269100
        return (p);
121
}
122
123
static int
124 58550
TLWriteVSB(struct vcc *tl, const char *fn, const struct vsb *vsb,
125
    const char *what)
126 1055350
{
127
        int fo;
128
        int i;
129
130 58550
        fo = open(fn, O_WRONLY|O_TRUNC|O_CREAT, 0600);
131 58550
        if (fo < 0) {
132 0
                VSB_printf(tl->sb,
133
                    "Could not open %s file %s: %s\n",
134 0
                    what, fn, strerror(errno));
135 1055350
                return (-1);
136
        }
137 58550
        i = VSB_tofile(vsb, fo);
138 58550
        if (i) {
139 0
                VSB_printf(tl->sb,
140
                    "Could not write %s to %s: %s\n",
141 0
                    what, fn, strerror(errno));
142 1055350
        }
143 58550
        closefd(&fo);
144 58550
        return (i);
145 58550
}
146 1055350
147
/*--------------------------------------------------------------------*/
148
149
struct proc *
150 2434575
vcc_NewProc(struct vcc *tl, struct symbol *sym)
151 1055350
{
152
        struct proc *p;
153
154 2434575
        ALLOC_OBJ(p, PROC_MAGIC);
155 2434575
        AN(p);
156 2434575
        VTAILQ_INIT(&p->calls);
157 2434575
        VTAILQ_INIT(&p->uses);
158 2434575
        VTAILQ_INIT(&p->priv_tasks);
159 3489925
        VTAILQ_INIT(&p->priv_tops);
160 2434575
        VTAILQ_INSERT_TAIL(&tl->procs, p, list);
161 2434575
        p->prologue = VSB_new_auto();
162 2434575
        AN(p->prologue);
163 2434575
        p->body = VSB_new_auto();
164 3489925
        AN(p->body);
165 2434575
        p->cname = VSB_new_auto();
166 2434575
        AN(p->cname);
167 2434575
        p->okmask = VCL_MET_TASK_ALL;
168 2434575
        sym->proc = p;
169 2434575
        p->sym = sym;
170 2434575
        return (p);
171
}
172 1055350
173
static void
174 1026075
vcc_EmitProc(struct vcc *tl, struct proc *p)
175
{
176
        struct vsb *vsbm;
177
        unsigned mask, nsub;
178
        const char *maskcmp;
179 1055350
        const char *cc_adv;
180 1026075
        int dyn = (p->sym->nref > p->called);
181
182 1026075
        AN(p->okmask);
183 1026075
        AZ(VSB_finish(p->cname));
184 1026075
        AZ(VSB_finish(p->prologue));
185 2081425
        AZ(VSB_finish(p->body));
186 1026075
        AN(p->sym);
187
188 1026075
        if (p->method) {
189 409850
                mask = p->method->bitval;
190 409850
                maskcmp = "==";
191 1465200
        } else {
192 616225
                mask = p->okmask;
193 616225
                maskcmp = "&";
194
        }
195
196 1026075
        if (dyn == 0 && (p->calledfrom & VCL_MET_TASK_H) == p->calledfrom)
197 58850
                cc_adv = "v_dont_optimize ";
198
        else
199 967225
                cc_adv = "";
200
201 1026075
        nsub = tl->nsub++;
202 1055350
203 1026075
        Fh(tl, 1, "vcl_func_f %s;\n", VSB_data(p->cname));
204 2052150
        Fh(tl, 1, "extern const struct vcl_sub sub_%s[1];\n",
205 1026075
            VSB_data(p->cname));
206 1026075
        Fh(tl, 1, "const struct vcl_sub sub_%s[1] = {{\n", VSB_data(p->cname));
207 1026075
        Fh(tl, 1, "\t.magic\t\t= VCL_SUB_MAGIC,\n");
208 1026075
        Fh(tl, 1, "\t.methods\t= 0x%x,\n", p->okmask);
209 1026075
        Fh(tl, 1, "\t.name\t\t= \"%.*s\",\n", PF(p->name));
210 1026075
        Fh(tl, 1, "\t.vcl_conf\t= &VCL_conf,\n");
211 1026075
        Fh(tl, 1, "\t.func\t\t= %s,\n", VSB_data(p->cname));
212 1026075
        Fh(tl, 1, "\t.n\t\t= %d,\n", nsub);
213 1026075
        Fh(tl, 1, "\t.nref\t\t= %d,\n", p->sym->nref);
214 1026075
        Fh(tl, 1, "\t.called\t\t= %d\n", p->called);
215 1026075
        Fh(tl, 1, "\t// calledfrom\t  0x%x\n", p->calledfrom);
216 1026075
        Fh(tl, 1, "}};\n");
217
218 1026075
        if (dyn) {
219 700
                Fc(tl, 1, "\nstatic inline void %s\n", cc_adv);
220 700
                Fc(tl, 1, "%s_checked(VRT_CTX)\n{\n", VSB_data(p->cname));
221 700
        } else {
222 1025375
                Fc(tl, 1, "\nvoid %sv_matchproto_(vcl_func_f)\n", cc_adv);
223 2050750
                Fc(tl, 1, "%s(VRT_CTX, enum vcl_func_call_e call,\n",
224 1025375
                    VSB_data(p->cname));
225 1025375
                Fc(tl, 1, "    enum vcl_func_fail_e *failp)\n{\n");
226 1025375
                Fc(tl, 1, "  assert(call == VSUB_STATIC);\n");
227 1025375
                Fc(tl, 1, "  assert(failp == NULL);\n");
228
        }
229
230 1026075
        vsbm = VSB_new_auto();
231 1026075
        AN(vsbm);
232 1026075
        vcc_vcl_met2c(vsbm, mask);
233 1026075
        AZ(VSB_finish(vsbm));
234 1026075
        Fc(tl, 1, "  assert(ctx->method %s (%s));\n", maskcmp, VSB_data(vsbm));
235 1026075
        VSB_destroy(&vsbm);
236 1026075
        Fc(tl, 1, "%s\n%s}\n", VSB_data(p->prologue), VSB_data(p->body));
237 1026075
        VSB_destroy(&p->body);
238 1026075
        VSB_destroy(&p->prologue);
239
240 1026075
        if (! dyn) {
241 1025375
                VSB_destroy(&p->cname);
242 1025375
                return;
243
        }
244
245
        /* wrapper to call the actual (_checked) function */
246 700
        Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_f)\n");
247 1400
        Fc(tl, 1, "%s(VRT_CTX, enum vcl_func_call_e call,\n",
248 700
            VSB_data(p->cname));
249 700
        Fc(tl, 1, "    enum vcl_func_fail_e *failp)\n{\n");
250 700
        Fc(tl, 1, "  enum vcl_func_fail_e fail;\n\n");
251 1400
        Fc(tl, 1, "  fail = VPI_Call_Check(ctx, &VCL_conf, 0x%x, %d);\n",
252 700
            mask, nsub);
253 700
        Fc(tl, 1, "  if (failp)\n");
254 700
        Fc(tl, 1, "    *failp = fail;\n");
255 700
        Fc(tl, 1, "  else if (fail == VSUB_E_METHOD)\n");
256 1400
        Fc(tl, 1, "    VRT_fail(ctx, \"call to \\\"sub %.*s{}\\\""
257 700
            " not allowed from here\");\n", PF(p->name));
258 700
        Fc(tl, 1, "  else if (fail == VSUB_E_RECURSE)\n");
259 1400
        Fc(tl, 1, "    VRT_fail(ctx, \"Recursive call to "
260 700
            "\\\"sub %.*s{}\\\"\");\n", PF(p->name));
261 700
        Fc(tl, 1, "  else\n");
262 700
        Fc(tl, 1, "    assert (fail == VSUB_E_OK);\n");
263 700
        Fc(tl, 1, "  if (fail != VSUB_E_OK || call == VSUB_CHECK)\n");
264 700
        Fc(tl, 1, "    return;\n");
265 700
        Fc(tl, 1, "  VPI_Call_Begin(ctx, %d);\n", nsub);
266 700
        Fc(tl, 1, "  %s_checked(ctx);\n", VSB_data(p->cname));
267 700
        Fc(tl, 1, "  VPI_Call_End(ctx, %d);\n", nsub);
268 700
        Fc(tl, 1, "}\n");
269 700
        VSB_destroy(&p->cname);
270 1026075
}
271
272
/*--------------------------------------------------------------------*/
273
274
struct inifin *
275 368625
New_IniFin(struct vcc *tl)
276
{
277
        struct inifin *p;
278
279 368625
        ALLOC_OBJ(p, INIFIN_MAGIC);
280 368625
        AN(p);
281 368625
        p->ini = VSB_new_auto();
282 368625
        AN(p->ini);
283 368625
        p->fin = VSB_new_auto();
284 368625
        AN(p->fin);
285 368625
        p->final = VSB_new_auto();
286 368625
        AN(p->final);
287 368625
        p->event = VSB_new_auto();
288 368625
        AN(p->event);
289 368625
        p->n = ++tl->ninifin;
290 368625
        VTAILQ_INSERT_TAIL(&tl->inifin, p, list);
291 368625
        return (p);
292
}
293
294
/*--------------------------------------------------------------------
295
 * Printf output to the vsbs, possibly indented
296
 */
297
298
void
299 18444025
Fh(const struct vcc *tl, int indent, const char *fmt, ...)
300
{
301
        va_list ap;
302
303 18444025
        if (indent)
304 13368350
                VSB_printf(tl->fh, "%*.*s", tl->hindent, tl->hindent, "");
305 18444025
        va_start(ap, fmt);
306 18444025
        VSB_vprintf(tl->fh, fmt, ap);
307 18444025
        va_end(ap);
308 18444025
}
309
310
void
311 46382975
Fb(const struct vcc *tl, int indent, const char *fmt, ...)
312
{
313
        va_list ap;
314
315 46382975
        assert(tl->fb != NULL);
316 46382975
        if (indent)
317 40771275
                VSB_printf(tl->fb, "%*.*s", tl->indent, tl->indent, "");
318 46382975
        va_start(ap, fmt);
319 46382975
        VSB_vprintf(tl->fb, fmt, ap);
320 46382975
        va_end(ap);
321 46382975
}
322
323
void
324 36791000
Fc(const struct vcc *tl, int indent, const char *fmt, ...)
325
{
326
        va_list ap;
327
328 36791000
        if (indent)
329 7193725
                VSB_printf(tl->fc, "%*.*s", tl->indent, tl->indent, "");
330 36791000
        va_start(ap, fmt);
331 36791000
        VSB_vprintf(tl->fc, fmt, ap);
332 36791000
        va_end(ap);
333 36791000
}
334
335
/*--------------------------------------------------------------------*/
336
337
void
338 2302200
EncToken(struct vsb *sb, const struct token *t)
339
{
340
341 2302200
        assert(t->tok == CSTR);
342 2302200
        VSB_quote(sb, t->dec, -1, VSB_QUOTE_CSTR);
343 2302200
}
344
345
/*--------------------------------------------------------------------
346
 * Output the location/profiling table.  For each counted token, we
347
 * record source+line+charpos for the first character in the token.
348
 */
349
350
static void
351 29275
EmitCoordinates(const struct vcc *tl, struct vsb *vsb)
352
{
353
        struct token *t;
354
        unsigned lin, pos;
355
        const struct source *sp;
356
        const char *p;
357
358 29275
        VSB_cat(vsb, "/* ---===### Source Code ###===---*/\n");
359
360 29275
        VSB_printf(vsb, "\n#define VGC_NSRCS %u\n", tl->nsources);
361
362 29275
        VSB_cat(vsb, "\nstatic const char *srcname[VGC_NSRCS] = {\n");
363 88600
        VTAILQ_FOREACH(sp, &tl->sources, list) {
364 59325
                VSB_cat(vsb, "\t");
365 59325
                VSB_quote(vsb, sp->name, -1, VSB_QUOTE_CSTR);
366 59325
                VSB_cat(vsb, ",\n");
367 59325
        }
368 29275
        VSB_cat(vsb, "};\n");
369
370 29275
        VSB_printf(vsb, "\nstatic const char *srcbody[%u] = {\n", tl->nsources);
371 88600
        VTAILQ_FOREACH(sp, &tl->sources, list) {
372 59325
                VSB_cat(vsb, "    /* ");
373 59325
                VSB_quote(vsb, sp->name, -1, VSB_QUOTE_CSTR);
374 59325
                VSB_cat(vsb, " */\n");
375 59325
                VSB_quote_pfx(vsb, "\t", sp->b, sp->e - sp->b, VSB_QUOTE_CSTR);
376 59325
                VSB_cat(vsb, ",\n");
377 59325
        }
378 29275
        VSB_cat(vsb, "};\n\n");
379
380 29275
        VSB_cat(vsb, "/* ---===### Location Counters ###===---*/\n");
381
382 29275
        VSB_printf(vsb, "\n#define VGC_NREFS %u\n\n", tl->cnt + 1);
383
384 29275
        VSB_cat(vsb, "static const struct vpi_ref VGC_ref[VGC_NREFS] = {\n");
385 29275
        lin = 1;
386 29275
        pos = 0;
387 29275
        sp = 0;
388 29275
        p = NULL;
389 24103200
        VTAILQ_FOREACH(t, &tl->tokens, list) {
390 24073925
                if (t->cnt == 0)
391 22157750
                        continue;
392 1916175
                assert(t->src != NULL);
393 1916175
                if (t->src != sp) {
394 49525
                        lin = 1;
395 49525
                        pos = 0;
396 49525
                        sp = t->src;
397 49525
                        p = sp->b;
398 49525
                }
399 1916175
                assert(sp != NULL);
400 1916175
                assert(p != NULL);
401 188894011
                for (;p < t->b; p++) {
402 186977836
                        if (*p == '\n') {
403 8646575
                                lin++;
404 8646575
                                pos = 0;
405 186977836
                        } else if (*p == '\t') {
406 4176300
                                pos &= ~7;
407 4176300
                                pos += 8;
408 4176300
                        } else
409 174154961
                                pos++;
410
411 186977836
                }
412 3832350
                VSB_printf(vsb, "  [%3u] = { VPI_REF_MAGIC, %u, %8tu, %4u, %3u, ",
413 1916175
                    t->cnt, sp->idx, t->b - sp->b, lin, pos + 1);
414 1916175
                if (t->tok == CSRC)
415 175
                        VSB_cat(vsb, " \"C{\"},\n");
416
                else
417 1916000
                        VSB_printf(vsb, " \"%.*s\" },\n", PF(t));
418 1916175
        }
419 29275
        VSB_cat(vsb, "};\n\n");
420 29275
}
421
422
/*--------------------------------------------------------------------
423
 * Init/Fini/Event
424
 *
425
 * We call DISCARD and COLD events in the opposite order of LOAD and
426
 * WARM.
427
 */
428
429
static void
430 29275
EmitInitFini(const struct vcc *tl)
431
{
432 29275
        struct inifin *p, *q = NULL;
433 29275
        unsigned has_event = 0;
434
        struct symbol *sy;
435
436 29275
        Fh(tl, 0, "\n");
437 29275
        Fh(tl, 0, "static unsigned vgc_inistep;\n");
438 29275
        Fh(tl, 0, "static unsigned vgc_warmupstep;\n");
439
440
        /*
441
         * LOAD
442
         */
443 29275
        Fc(tl, 0, "\nstatic int\nVGC_Load(VRT_CTX)\n{\n\n");
444 29275
        Fc(tl, 0, "\tvgc_inistep = 0;\n");
445 29275
        Fc(tl, 0, "\tsize_t ndirector = %dUL;\n", tl->ndirector);
446 29275
        Fc(tl, 0, "\n");
447 234900
        VTAILQ_FOREACH(p, &tl->inifin, list) {
448 205625
                AZ(VSB_finish(p->ini));
449 205625
                assert(p->n > 0);
450 205625
                if (VSB_len(p->ini))
451 200225
                        Fc(tl, 0, "\t/* %u */\n%s\n", p->n, VSB_data(p->ini));
452 205625
                if (p->ignore_errors == 0) {
453 176350
                        Fc(tl, 0, "\tif (ctx->vpi->handling == VCL_RET_FAIL)\n");
454 176350
                        Fc(tl, 0, "\t\treturn(1);\n");
455 176350
                }
456 205625
                Fc(tl, 0, "\tvgc_inistep = %u;\n\n", p->n);
457 205625
                VSB_destroy(&p->ini);
458
459 205625
                AZ(VSB_finish(p->event));
460 205625
                if (VSB_len(p->event))
461 2400
                        has_event = 1;
462 205625
        }
463
464
        /* Handle failures from vcl_init */
465 29275
        Fc(tl, 0, "\n");
466 29275
        Fc(tl, 0, "\tif (ctx->vpi->handling != VCL_RET_OK)\n");
467 29275
        Fc(tl, 0, "\t\treturn(1);\n");
468 29275
        Fc(tl, 0, "\tctx->vpi->handling = 0;\n");
469
470 34025
        VTAILQ_FOREACH(sy, &tl->sym_objects, sideways) {
471 4750
                Fc(tl, 0, "\tif (!%s) {\n", sy->rname);
472 9500
                Fc(tl, 0, "\t\tVRT_fail(ctx, "
473 4750
                    "\"Object %s not initialized\");\n" , sy->name);
474 4750
                Fc(tl, 0, "\t\treturn(1);\n");
475 4750
                Fc(tl, 0, "\t}\n");
476 4750
        }
477
478 29275
        Fc(tl, 0, "\treturn(0);\n");
479 29275
        Fc(tl, 0, "}\n");
480
481
        /*
482
         * DISCARD
483
         */
484 29275
        Fc(tl, 0, "\nstatic int\nVGC_Discard(VRT_CTX)\n{\n\n");
485
486 29275
        Fc(tl, 0, "\tswitch (vgc_inistep) {\n");
487 234900
        VTAILQ_FOREACH_REVERSE(p, &tl->inifin, inifinhead, list) {
488 205625
                AZ(VSB_finish(p->fin));
489 205625
                if (q)
490 176350
                        assert(q->n > p->n);
491 205625
                q = p;
492 205625
                Fc(tl, 0, "\t\tcase %u:\n", p->n);
493 205625
                if (VSB_len(p->fin))
494 205575
                        Fc(tl, 0, "\t%s\n", VSB_data(p->fin));
495 205625
                Fc(tl, 0, "\t\t\t/* FALLTHROUGH */\n");
496 205625
                VSB_destroy(&p->fin);
497 205625
        }
498 29275
        Fc(tl, 0, "\t\tdefault:\n\t\t\tbreak;\n");
499 29275
        Fc(tl, 0, "\t}\n\n");
500 29275
        Fc(tl, 0, "\tswitch (vgc_inistep) {\n");
501 234900
        VTAILQ_FOREACH_REVERSE(p, &tl->inifin, inifinhead, list) {
502 205625
                AZ(VSB_finish(p->final));
503 205625
                Fc(tl, 0, "\t\tcase %u:\n", p->n);
504 205625
                if (VSB_len(p->final))
505 11975
                        Fc(tl, 0, "\t%s\n", VSB_data(p->final));
506 205625
                Fc(tl, 0, "\t\t\t/* FALLTHROUGH */\n");
507 205625
                VSB_destroy(&p->final);
508 205625
        }
509 29275
        Fc(tl, 0, "\t\tdefault:\n\t\t\tbreak;\n");
510 29275
        Fc(tl, 0, "\t}\n\n");
511
512 29275
        Fc(tl, 0, "\treturn (0);\n");
513 29275
        Fc(tl, 0, "}\n");
514
515 29275
        if (has_event) {
516
                /*
517
                 * WARM
518
                 */
519 2400
                Fc(tl, 0, "\nstatic int\n");
520 2400
                Fc(tl, 0, "VGC_Warmup(VRT_CTX, enum vcl_event_e ev)\n{\n\n");
521
522 2400
                Fc(tl, 0, "\tvgc_warmupstep = 0;\n\n");
523 24525
                VTAILQ_FOREACH(p, &tl->inifin, list) {
524 22125
                        assert(p->n > 0);
525 22125
                        if (VSB_len(p->event)) {
526 2400
                                Fc(tl, 0, "\t/* %u */\n", p->n);
527 2400
                                Fc(tl, 0, "\tif (%s)\n", VSB_data(p->event));
528 2400
                                Fc(tl, 0, "\t\treturn (1);\n");
529 2400
                                Fc(tl, 0, "\tvgc_warmupstep = %u;\n\n", p->n);
530 2400
                        }
531 22125
                }
532
533 2400
                Fc(tl, 0, "\treturn (0);\n");
534 2400
                Fc(tl, 0, "}\n");
535
536
                /*
537
                 * COLD
538
                 */
539 2400
                Fc(tl, 0, "\nstatic int\n");
540 2400
                Fc(tl, 0, "VGC_Cooldown(VRT_CTX, enum vcl_event_e ev)\n{\n");
541 2400
                Fc(tl, 0, "\tint retval = 0;\n\n");
542
543 24525
                VTAILQ_FOREACH_REVERSE(p, &tl->inifin, inifinhead, list) {
544 22125
                        if (VSB_len(p->event)) {
545 2400
                                Fc(tl, 0, "\t/* %u */\n", p->n);
546 4800
                                Fc(tl, 0,
547 2400
                                    "\tif (vgc_warmupstep >= %u &&\n", p->n);
548 4800
                                Fc(tl, 0,
549 2400
                                    "\t    %s != 0)\n", VSB_data(p->event));
550 2400
                                Fc(tl, 0, "\t\tretval = 1;\n\n");
551 2400
                        }
552 22125
                        VSB_destroy(&p->event);
553 22125
                }
554
555 2400
                Fc(tl, 0, "\treturn (retval);\n");
556 2400
                Fc(tl, 0, "}\n");
557 2400
        }
558
559
        /*
560
         * EVENTS
561
         */
562 29275
        Fc(tl, 0, "\nstatic int\n");
563 29275
        Fc(tl, 0, "VGC_Event(VRT_CTX, enum vcl_event_e ev)\n");
564 29275
        Fc(tl, 0, "{\n");
565 29275
        Fc(tl, 0, "\tif (ev == VCL_EVENT_LOAD)\n");
566 29275
        Fc(tl, 0, "\t\treturn (VGC_Load(ctx));\n");
567 29275
        if (has_event) {
568 2400
                Fc(tl, 0, "\tif (ev == VCL_EVENT_WARM)\n");
569 2400
                Fc(tl, 0, "\t\treturn (VGC_Warmup(ctx, ev));\n");
570 2400
                Fc(tl, 0, "\tif (ev == VCL_EVENT_COLD)\n");
571 2400
                Fc(tl, 0, "\t\treturn (VGC_Cooldown(ctx, ev));\n");
572 2400
        }
573 29275
        Fc(tl, 0, "\tif (ev == VCL_EVENT_DISCARD)\n");
574 29275
        Fc(tl, 0, "\t\treturn (VGC_Discard(ctx));\n");
575 29275
        Fc(tl, 0, "\n");
576 29275
        if (!has_event)
577 26875
                Fc(tl, 0, "\t(void)vgc_warmupstep;\n");
578 29275
        Fc(tl, 0, "\treturn (%d);\n", has_event ? 1 : 0);
579 29275
        Fc(tl, 0, "}\n");
580 29275
}
581
582
/*--------------------------------------------------------------------*/
583
584
static void
585 29275
EmitStruct(const struct vcc *tl)
586
{
587 29275
        Fc(tl, 0, "\nconst struct VCL_conf VCL_conf = {\n");
588 29275
        Fc(tl, 0, "\t.magic = VCL_CONF_MAGIC,\n");
589 29275
        Fc(tl, 0, "\t.syntax = %u,\n", tl->syntax);
590 29275
        Fc(tl, 0, "\t.event_vcl = VGC_Event,\n");
591 29275
        Fc(tl, 0, "\t.default_director = &%s,\n", tl->default_director);
592 29275
        if (tl->default_probe != NULL)
593 200
                Fc(tl, 0, "\t.default_probe = %s,\n", tl->default_probe);
594 29275
        Fc(tl, 0, "\t.ref = VGC_ref,\n");
595 29275
        Fc(tl, 0, "\t.nref = VGC_NREFS,\n");
596 29275
        Fc(tl, 0, "\t.nsrc = VGC_NSRCS,\n");
597 29275
        Fc(tl, 0, "\t.nsub = %d,\n", tl->subref > 0 ? tl->nsub : 0);
598 29275
        Fc(tl, 0, "\t.srcname = srcname,\n");
599 29275
        Fc(tl, 0, "\t.srcbody = srcbody,\n");
600 29275
        Fc(tl, 0, "\t.nvmod = %u,\n", tl->vmod_count);
601
#define VCL_MET_MAC(l,u,t,b) \
602
        Fc(tl, 0, "\t." #l "_func = VGC_function_vcl_" #l ",\n");
603
#include "tbl/vcl_returns.h"
604 29275
        Fc(tl, 0, "\t.instance_info = VGC_instance_info\n");
605 29275
        Fc(tl, 0, "};\n");
606 29275
}
607
608
/*--------------------------------------------------------------------
609
 * Compile the VCL code from the given source and return the C-source
610
 */
611
612
static struct vsb *
613 72975
vcc_CompileSource(struct vcc *tl, struct source *sp, const char *jfile)
614
{
615
        struct proc *p;
616
        struct vsb *vsb;
617
        struct inifin *ifp;
618
619 72975
        Fh(tl, 0, "/* ---===### VCC generated .h code ###===---*/\n");
620 72975
        Fc(tl, 0, "\n/* ---===### VCC generated .c code ###===---*/\n");
621
622 72975
        Fc(tl, 0, "\n#define END_ if (ctx->vpi->handling) return\n");
623
624 72975
        vcc_Parse_Init(tl);
625
626 72975
        vcc_Expr_Init(tl);
627
628 72975
        vcc_Action_Init(tl);
629
630 72975
        vcc_Backend_Init(tl);
631
632 72975
        vcc_Var_Init(tl);
633
634 72975
        vcc_Type_Init(tl);
635
636 72975
        Fh(tl, 0, "\nextern const struct VCL_conf VCL_conf;\n");
637
638
        /* Register and lex the main source */
639 72975
        if (sp != NULL) {
640 36475
                AN(vcc_builtin);
641 36475
                vcc_lex_source(tl, sp, 0);
642 36475
                if (tl->err)
643 800
                        return (NULL);
644 35675
        }
645
646
        /* Register and lex the builtin VCL */
647 72175
        sp = vcc_new_source(tl->builtin_vcl, "builtin", "<builtin>");
648 72175
        assert(sp != NULL);
649 72175
        vcc_lex_source(tl, sp, 1);
650 72175
        if (tl->err)
651 0
                return (NULL);
652
653
        /* Expand and lex any includes in the token string */
654 72175
        if (tl->err)
655 0
                return (NULL);
656
657
        /* Parse the token string */
658 72175
        tl->t = VTAILQ_FIRST(&tl->tokens);
659 72175
        vcc_Parse(tl);
660 72175
        if (tl->err)
661 5000
                return (NULL);
662
663
        /* Check for orphans */
664 67175
        if (vcc_CheckReferences(tl))
665 225
                return (NULL);
666
667
        /* Check that all action returns are legal */
668 66950
        if (vcc_CheckAction(tl) || tl->err)
669 75
                return (NULL);
670
671
        /* Check that all variable uses are legal */
672 66875
        if (vcc_CheckUses(tl) || tl->err)
673 1050
                return (NULL);
674
675 65825
        if (vcc_builtin == NULL)
676 36500
                return (NULL);
677
678
        /* Check if we have any backends at all */
679 29325
        if (tl->default_director == NULL) {
680 50
                VSB_cat(tl->sb,
681
                    "No backends or directors found in VCL program, "
682
                    "at least one is necessary.\n");
683 50
                tl->err = 1;
684 50
                return (NULL);
685
        }
686
687
        /* Tie vcl_init/fini in */
688 29275
        ifp = New_IniFin(tl);
689 29275
        VSB_cat(ifp->ini, "\tVGC_function_vcl_init(ctx, VSUB_STATIC, NULL);\n");
690
        /*
691
         * Because the failure could be half way into vcl_init{} so vcl_fini{}
692
         * must always be called, also on failure.
693
         */
694 29275
        ifp->ignore_errors = 1;
695 29275
        VSB_cat(ifp->fin, "\t\tVGC_function_vcl_fini(ctx, VSUB_STATIC, NULL);\n");
696 29275
        VSB_cat(ifp->fin, "\t\t\tVPI_vcl_fini(ctx);");
697
698
        /* Emit method functions */
699 29275
        Fh(tl, 1, "\n");
700 1055350
        VTAILQ_FOREACH(p, &tl->procs, list)
701 1642300
                if (p->method == NULL)
702 616225
                        vcc_EmitProc(tl, p);
703 1055350
        VTAILQ_FOREACH(p, &tl->procs, list)
704 1435925
                if (p->method != NULL)
705 409850
                        vcc_EmitProc(tl, p);
706
707 29275
        EmitInitFini(tl);
708
709 29275
        VCC_InstanceInfo(tl);
710
711 29275
        EmitStruct(tl);
712
713 29275
        VCC_XrefTable(tl);
714
715 29275
        VSB_cat(tl->symtab, "\n]\n");
716 29275
        AZ(VSB_finish(tl->symtab));
717 29275
        if (TLWriteVSB(tl, jfile, tl->symtab, "Symbol table"))
718 0
                return (NULL);
719
720
        /* Combine it all */
721
722 29275
        vsb = VSB_new_auto();
723 29275
        AN(vsb);
724
725 29275
        vcl_output_lang_h(vsb);
726
727 29275
        EmitCoordinates(tl, vsb);
728
729 29275
        AZ(VSB_finish(tl->fh));
730 29275
        VSB_cat(vsb, VSB_data(tl->fh));
731
732 29275
        AZ(VSB_finish(tl->fc));
733 29275
        VSB_cat(vsb, VSB_data(tl->fc));
734
735 29275
        AZ(VSB_finish(vsb));
736 29275
        return (vsb);
737 72975
}
738
739
static struct vcc *
740 36500
vcc_ParseBuiltin(struct vcc *tl)
741
{
742
        struct vcc *tl_builtin;
743
744 36500
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
745 36500
        tl_builtin = VCC_New();
746 36500
        AN(tl_builtin);
747 36500
        VCC_Builtin_VCL(tl_builtin, tl->builtin_vcl);
748 36500
        AZ(vcc_CompileSource(tl_builtin, NULL, NULL));
749 36500
        return (tl_builtin);
750
}
751
752
/*--------------------------------------------------------------------
753
 * Report the range of VCL language we support
754
 */
755
void
756 24800
VCC_VCL_Range(unsigned *lo, unsigned *hi)
757
{
758
759 24800
        AN(lo);
760 24800
        *lo = VCL_LOW;
761 24800
        AN(hi);
762 24800
        *hi = VCL_HIGH;
763 24800
}
764
765
/*--------------------------------------------------------------------
766
 * Compile the VCL code in the argument.  Error messages, if any are
767
 * formatted into the vsb.
768
 */
769
770
int
771 36500
VCC_Compile(struct vcc *tl, struct vsb **sb,
772
    const char *vclsrc, const char *vclsrcfile,
773
    const char *ofile, const char *jfile)
774
{
775
        struct source *sp;
776 36500
        struct vsb *r = NULL;
777 36500
        int retval = 0;
778
779 36500
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
780 36500
        AN(sb);
781 36500
        AN(vclsrcfile);
782 36500
        AN(ofile);
783 36500
        AN(jfile);
784
785 36500
        AZ(vcc_builtin);
786 36500
        vcc_builtin = vcc_ParseBuiltin(tl);
787 36500
        AN(vcc_builtin);
788 36500
        if (vcc_builtin->err) {
789 0
                AZ(VSB_finish(vcc_builtin->sb));
790 0
                *sb = vcc_builtin->sb;
791 0
                return (-1);
792
        }
793
794 36500
        if (vclsrc != NULL)
795 36200
                sp = vcc_new_source(vclsrc, "vcl.inline", vclsrcfile);
796
        else
797 300
                sp = vcc_file_source(tl, vclsrcfile);
798
799 36500
        if (sp != NULL)
800 36475
                r = vcc_CompileSource(tl, sp, jfile);
801
802 36500
        if (r != NULL) {
803 29275
                retval = TLWriteVSB(tl, ofile, r, "C-source");
804 29275
                VSB_destroy(&r);
805 29275
        } else {
806 7225
                retval = -1;
807
        }
808 36500
        AZ(VSB_finish(tl->sb));
809 36500
        *sb = tl->sb;
810 36500
        return (retval);
811 36500
}
812
813
/*--------------------------------------------------------------------
814
 * Allocate a compiler instance
815
 */
816
817
struct vcc *
818 73000
VCC_New(void)
819
{
820
        struct vcc *tl;
821
        struct symbol *sym;
822
        struct proc *p;
823
        struct vsb *vsb;
824
        int i;
825
826 73000
        ALLOC_OBJ(tl, VCC_MAGIC);
827 73000
        AN(tl);
828 73000
        VTAILQ_INIT(&tl->inifin);
829 73000
        VTAILQ_INIT(&tl->tokens);
830 73000
        VTAILQ_INIT(&tl->sources);
831 73000
        VTAILQ_INIT(&tl->procs);
832 73000
        VTAILQ_INIT(&tl->sym_objects);
833 73000
        VTAILQ_INIT(&tl->sym_vmods);
834 73000
        VTAILQ_INIT(&tl->vmod_objects);
835
836 73000
        tl->nsources = 0;
837
838 73000
        tl->symtab = VSB_new_auto();
839 73000
        assert(tl->symtab != NULL);
840 73000
        VSB_cat(tl->symtab, "[\n    {\"version\": 0}");
841
842 73000
        tl->fc = VSB_new_auto();
843 73000
        assert(tl->fc != NULL);
844
845 73000
        tl->fh = VSB_new_auto();
846 73000
        assert(tl->fh != NULL);
847
848 1095000
        for (i = 1; i < VCL_MET_MAX; i++) {
849 2044000
                sym = VCC_MkSym(tl, method_tab[i].name,
850 1022000
                    SYM_MAIN, SYM_SUB, VCL_LOW, VCL_HIGH);
851 1022000
                p = vcc_NewProc(tl, sym);
852 1022000
                p->method = &method_tab[i];
853
854
                // see also VCC_GlobalSymbol()
855 1022000
                vsb = VSB_new_auto();
856 1022000
                AN(vsb);
857 1022000
                VSB_printf(vsb, "%s_%s", SUB->global_pfx, p->method->name);
858 1022000
                AZ(VSB_finish(vsb));
859
860 1022000
                AZ(VSB_bcat(p->cname, VSB_data(vsb), VSB_len(vsb)));
861
862 1022000
                sym->lname = strdup(VSB_data(vsb));
863 1022000
                AN(sym->lname);
864
865 1022000
                VSB_clear(vsb);
866 1022000
                VSB_printf(vsb, "sub_%s", sym->lname);
867 1022000
                AZ(VSB_finish(vsb));
868
869 1022000
                sym->rname = strdup(VSB_data(vsb));
870 1022000
                AN(sym->rname);
871 1022000
                VSB_destroy(&vsb);
872
873 1022000
                sym->type = SUB;
874 1022000
                sym->kind = VCC_HandleKind(SUB);
875 1022000
                AZ(VCT_invalid_name(sym->rname, NULL));
876 1022000
                sym->eval = vcc_Eval_Sub;
877 1022000
        }
878 73000
        tl->sb = VSB_new_auto();
879 73000
        AN(tl->sb);
880 73000
        return (tl);
881
}
882
883
/*--------------------------------------------------------------------
884
 * Configure builtin VCL source code
885
 */
886
887
void
888 73000
VCC_Builtin_VCL(struct vcc *vcc, const char *str)
889
{
890
891 73000
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
892 73000
        REPLACE(vcc->builtin_vcl, str);
893 73000
}
894
895
/*--------------------------------------------------------------------
896
 * Configure default VCL source path
897
 */
898
899
void
900 36500
VCC_VCL_path(struct vcc *vcc, const char *str)
901
{
902
903 36500
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
904 36500
        VFIL_setpath(&vcc->vcl_path, str);
905 36500
}
906
907
/*--------------------------------------------------------------------
908
 * Configure default VMOD path
909
 */
910
911
void
912 36500
VCC_VMOD_path(struct vcc *vcc, const char *str)
913
{
914
915 36500
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
916 36500
        VFIL_setpath(&vcc->vmod_path, str);
917 36500
}
918
919
/*--------------------------------------------------------------------
920
 * Configure settings
921
 */
922
923
#define VCC_FEATURE_BIT(U, l, d)                                \
924
        void VCC_Opt_ ## l(struct vcc *vcc, unsigned val)       \
925
        {                                                       \
926
                CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);              \
927
                vcc->l = val;                                   \
928
        }
929
#include "tbl/vcc_feature_bits.h"
930
931
/*--------------------------------------------------------------------
932
 * Configure settings
933
 */
934
935
static void
936 1050
vcc_predef_vcl(struct vcc *vcc, const char *name)
937
{
938
        struct symbol *sym;
939
940 1050
        sym = VCC_MkSym(vcc, name, SYM_MAIN, SYM_VCL, VCL_LOW, VCL_HIGH);
941 1050
        AN(sym);
942 1050
        sym->type = VCL;
943 1050
        sym->r_methods = VCL_MET_RECV;
944 1050
}
945
946
void
947 74175
VCC_Predef(struct vcc *vcc, const char *type, const char *name)
948
{
949
950 74175
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
951 74175
        if (!strcmp(type, "VCL_STEVEDORE"))
952 73125
                vcc_stevedore(vcc, name);
953 1050
        else if (!strcmp(type, "VCL_VCL"))
954 1050
                vcc_predef_vcl(vcc, name);
955
        else
956 0
                WRONG("Unknown VCC predef type");
957 74175
}
958
959
void
960 25
VCC_VEXT(struct vcc *vcc, const char *filename)
961
{
962 25
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
963 25
        vcc_ImportVext(vcc, filename);
964 25
}