vinyl-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://vinyl/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://vinyl/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 1217307
vcc_vcl_met2c(struct vsb *vsb, unsigned method)
81
{
82 1217307
        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 1217307
        AN(d);
96
}
97
98
99
/*--------------------------------------------------------------------*/
100
101
void * v_matchproto_(TlAlloc)
102 101736783
TlAlloc(struct vcc *tl, unsigned len)
103
{
104
        void *p;
105
106 101736783
        (void)tl;
107 101736783
        p = calloc(1, len);
108 101736783
        assert(p != NULL);
109 101736783
        return (p);
110
}
111
112
char *
113 4981437
TlDup(struct vcc *tl, const char *s)
114
{
115
        char *p;
116
117 4981437
        p = TlAlloc(tl, vstrlen(s) + 1);
118 4981437
        AN(p);
119 4981437
        strcpy(p, s);
120 4981437
        return (p);
121
}
122
123
static int
124 55272
TLWriteVSB(struct vcc *tl, const char *fn, const struct vsb *vsb,
125
    const char *what)
126
{
127 1217307
        int fo;
128
        int i;
129
130 55272
        fo = open(fn, O_WRONLY|O_TRUNC|O_CREAT, 0600);
131 55272
        if (fo < 0) {
132 0
                VSB_printf(tl->sb,
133
                    "Could not open %s file %s: %s\n",
134 1217307
                    what, fn, strerror(errno));
135 0
                return (-1);
136
        }
137 55272
        i = VSB_tofile(vsb, fo);
138 55272
        if (i) {
139 0
                VSB_printf(tl->sb,
140
                    "Could not write %s to %s: %s\n",
141 1217307
                    what, fn, strerror(errno));
142 0
        }
143 55272
        closefd(&fo);
144 55272
        return (i);
145 55272
}
146
147
/*--------------------------------------------------------------------*/
148
149
static void
150 294
vcc_refUnusedProbes(struct vcc *tl, const struct symbol *sym)
151 1217307
{
152 294
        if (sym->ndef != 0 && sym->nref == 0)
153 21
                Fc(tl, 0, "\t(void)%s;\n", sym->rname);
154 294
}
155
156
struct proc *
157 2856760
vcc_NewProc(struct vcc *tl, struct symbol *sym)
158
{
159
        struct proc *p;
160 1217307
161 2856760
        ALLOC_OBJ(p, PROC_MAGIC);
162 2856760
        AN(p);
163 2856760
        VTAILQ_INIT(&p->calls);
164 2856760
        VTAILQ_INIT(&p->uses);
165 2856760
        VTAILQ_INSERT_TAIL(&tl->procs, p, list);
166 2856760
        p->prologue = VSB_new_auto();
167 4074067
        AN(p->prologue);
168 2856760
        p->body = VSB_new_auto();
169 2856760
        AN(p->body);
170 2856760
        p->cname = VSB_new_auto();
171 4074067
        AN(p->cname);
172 2856760
        p->okmask = VCL_MET_TASK_ALL;
173 2856760
        sym->proc = p;
174 2856760
        p->sym = sym;
175 2856760
        return (p);
176 1217307
}
177
178
static void
179 1217307
vcc_EmitProc(struct vcc *tl, struct proc *p)
180
{
181
        struct vsb *vsbm;
182
        unsigned mask, nsub;
183
        const char *maskcmp;
184 1217307
        const char *cc_adv;
185 1217307
        int dyn = (p->sym->nref > p->called);
186
187 1217307
        AN(p->okmask);
188 1217307
        AZ(VSB_finish(p->cname));
189 2434614
        AZ(VSB_finish(p->prologue));
190 1217307
        AZ(VSB_finish(p->body));
191 1217307
        AN(p->sym);
192
193 1217307
        if (p->method) {
194 414540
                mask = p->method->bitval;
195 414540
                maskcmp = "==";
196 414540
        } else {
197 2020074
                mask = p->okmask;
198 802767
                maskcmp = "&";
199
        }
200
201 1217307
        if (dyn == 0 && (p->calledfrom & VCL_MET_TASK_H) == p->calledfrom)
202 55545
                cc_adv = "v_dont_optimize ";
203
        else
204 2379069
                cc_adv = "";
205
206 1217307
        nsub = tl->nsub++;
207
208 1217307
        Fh(tl, 1, "vcl_func_f %s;\n", VSB_data(p->cname));
209 2434614
        Fh(tl, 1, "extern const struct vcl_sub sub_%s[1];\n",
210 2434614
            VSB_data(p->cname));
211 1217307
        Fh(tl, 1, "const struct vcl_sub sub_%s[1] = {{\n", VSB_data(p->cname));
212 1217307
        Fh(tl, 1, "\t.magic\t\t= VCL_SUB_MAGIC,\n");
213 1217307
        Fh(tl, 1, "\t.methods\t= 0x%x,\n", p->okmask);
214 1217307
        Fh(tl, 1, "\t.name\t\t= \"%.*s\",\n", PF(p->name));
215 1217307
        Fh(tl, 1, "\t.vcl_conf\t= &VCL_conf,\n");
216 2434614
        Fh(tl, 1, "\t.func\t\t= %s,\n", VSB_data(p->cname));
217 1217307
        Fh(tl, 1, "\t.n\t\t= %d,\n", nsub);
218 1217307
        Fh(tl, 1, "\t.nref\t\t= %d,\n", p->sym->nref);
219 1217307
        Fh(tl, 1, "\t.called\t\t= %d\n", p->called);
220 1217307
        Fh(tl, 1, "\t// calledfrom\t  0x%x\n", p->calledfrom);
221 1217307
        Fh(tl, 1, "}};\n");
222
223 1217307
        if (dyn) {
224 714
                Fc(tl, 1, "\nstatic inline void %s\n", cc_adv);
225 714
                Fc(tl, 1, "%s_checked(VRT_CTX)\n{\n", VSB_data(p->cname));
226 714
        } else {
227 2433900
                Fc(tl, 1, "\nvoid %sv_matchproto_(vcl_func_f)\n", cc_adv);
228 2433186
                Fc(tl, 1, "%s(VRT_CTX, enum vcl_func_call_e call,\n",
229 1216593
                    VSB_data(p->cname));
230 1216593
                Fc(tl, 1, "    enum vcl_func_fail_e *failp)\n{\n");
231 1216593
                Fc(tl, 1, "  assert(call == VSUB_STATIC);\n");
232 1216593
                Fc(tl, 1, "  assert(failp == NULL);\n");
233
        }
234
235 1217307
        vsbm = VSB_new_auto();
236 1217307
        AN(vsbm);
237 1217307
        vcc_vcl_met2c(vsbm, mask);
238 1217307
        AZ(VSB_finish(vsbm));
239 1217307
        Fc(tl, 1, "  assert(ctx->method %s (%s));\n", maskcmp, VSB_data(vsbm));
240 1217307
        VSB_destroy(&vsbm);
241 1217307
        Fc(tl, 1, "%s\n%s}\n", VSB_data(p->prologue), VSB_data(p->body));
242 1217307
        VSB_destroy(&p->body);
243 1217307
        VSB_destroy(&p->prologue);
244
245 1217307
        if (! dyn) {
246 1216593
                VSB_destroy(&p->cname);
247 1216593
                return;
248
        }
249
250
        /* wrapper to call the actual (_checked) function */
251 714
        Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_f)\n");
252 1428
        Fc(tl, 1, "%s(VRT_CTX, enum vcl_func_call_e call,\n",
253 714
            VSB_data(p->cname));
254 714
        Fc(tl, 1, "    enum vcl_func_fail_e *failp)\n{\n");
255 714
        Fc(tl, 1, "  enum vcl_func_fail_e fail;\n\n");
256 1428
        Fc(tl, 1, "  fail = VPI_Call_Check(ctx, &VCL_conf, 0x%x, %d);\n",
257 714
            mask, nsub);
258 714
        Fc(tl, 1, "  if (failp)\n");
259 714
        Fc(tl, 1, "    *failp = fail;\n");
260 714
        Fc(tl, 1, "  else if (fail == VSUB_E_METHOD)\n");
261 1428
        Fc(tl, 1, "    VRT_fail(ctx, \"call to \\\"sub %.*s{}\\\""
262 714
            " not allowed from here\");\n", PF(p->name));
263 714
        Fc(tl, 1, "  else if (fail == VSUB_E_RECURSE)\n");
264 1428
        Fc(tl, 1, "    VRT_fail(ctx, \"Recursive call to "
265 714
            "\\\"sub %.*s{}\\\"\");\n", PF(p->name));
266 714
        Fc(tl, 1, "  else\n");
267 714
        Fc(tl, 1, "    assert (fail == VSUB_E_OK);\n");
268 714
        Fc(tl, 1, "  if (fail != VSUB_E_OK || call == VSUB_CHECK)\n");
269 714
        Fc(tl, 1, "    return;\n");
270 714
        Fc(tl, 1, "  VPI_Call_Begin(ctx, %d);\n", nsub);
271 714
        Fc(tl, 1, "  %s_checked(ctx);\n", VSB_data(p->cname));
272 714
        Fc(tl, 1, "  VPI_Call_End(ctx, %d);\n", nsub);
273 714
        Fc(tl, 1, "}\n");
274 714
        VSB_destroy(&p->cname);
275 1217307
}
276
277
/*--------------------------------------------------------------------*/
278
279
struct inifin *
280 473416
New_IniFin(struct vcc *tl)
281
{
282
        struct inifin *p;
283
284 473416
        ALLOC_OBJ(p, INIFIN_MAGIC);
285 473416
        AN(p);
286 473416
        p->ini = VSB_new_auto();
287 473416
        AN(p->ini);
288 473416
        p->fin = VSB_new_auto();
289 473416
        AN(p->fin);
290 473416
        p->final = VSB_new_auto();
291 473416
        AN(p->final);
292 473416
        p->event = VSB_new_auto();
293 473416
        AN(p->event);
294 473416
        p->n = ++tl->ninifin;
295 473416
        VTAILQ_INSERT_TAIL(&tl->inifin, p, list);
296 473416
        return (p);
297
}
298
299
/*--------------------------------------------------------------------
300
 * Printf output to the vsbs, possibly indented
301
 */
302
303
void
304 21717873
Fh(const struct vcc *tl, int indent, const char *fmt, ...)
305
{
306
        va_list ap;
307
308 21717873
        if (indent)
309 15852711
                VSB_printf(tl->fh, "%*.*s", tl->hindent, tl->hindent, "");
310 21717873
        va_start(ap, fmt);
311 21717873
        VSB_vprintf(tl->fh, fmt, ap);
312 21717873
        va_end(ap);
313 21717873
}
314
315
void
316 57171583
Fb(const struct vcc *tl, int indent, const char *fmt, ...)
317
{
318
        va_list ap;
319
320 57171583
        assert(tl->fb != NULL);
321 57171583
        if (indent)
322 50654435
                VSB_printf(tl->fb, "%*.*s", tl->indent, tl->indent, "");
323 57171583
        va_start(ap, fmt);
324 57171583
        VSB_vprintf(tl->fb, fmt, ap);
325 57171583
        va_end(ap);
326 57171583
}
327
328
void
329 44142563
Fc(const struct vcc *tl, int indent, const char *fmt, ...)
330
{
331
        va_list ap;
332
333 44142563
        if (indent)
334 8532573
                VSB_printf(tl->fc, "%*.*s", tl->indent, tl->indent, "");
335 44142563
        va_start(ap, fmt);
336 44142563
        VSB_vprintf(tl->fc, fmt, ap);
337 44142563
        va_end(ap);
338 44142563
}
339
340
/*--------------------------------------------------------------------*/
341
342
void
343 2663137
EncToken(struct vsb *sb, const struct token *t)
344
{
345
346 2663137
        assert(t->tok == CSTR);
347 2663137
        VSB_quote(sb, t->dec, -1, VSB_QUOTE_CSTR);
348 2663137
}
349
350
/*--------------------------------------------------------------------
351
 * Output the location/profiling table.  For each counted token, we
352
 * record source+line+charpos for the first character in the token.
353
 */
354
355
static void
356 27636
EmitCoordinates(const struct vcc *tl, struct vsb *vsb)
357
{
358
        struct token *t;
359
        unsigned lin, pos;
360
        const struct source *sp;
361
        const char *p;
362
363 27636
        VSB_cat(vsb, "/* ---===### Source Code ###===---*/\n");
364
365 27636
        VSB_printf(vsb, "\n#define VGC_NSRCS %u\n", tl->nsources);
366
367 27636
        VSB_cat(vsb, "\nstatic const char *srcname[VGC_NSRCS] = {\n");
368 83580
        VTAILQ_FOREACH(sp, &tl->sources, list) {
369 55944
                VSB_cat(vsb, "\t");
370 55944
                VSB_quote(vsb, sp->name, -1, VSB_QUOTE_CSTR);
371 55944
                VSB_cat(vsb, ",\n");
372 55944
        }
373 27636
        VSB_cat(vsb, "};\n");
374
375 27636
        VSB_printf(vsb, "\nstatic const char *srcbody[%u] = {\n", tl->nsources);
376 83580
        VTAILQ_FOREACH(sp, &tl->sources, list) {
377 55944
                VSB_cat(vsb, "    /* ");
378 55944
                VSB_quote(vsb, sp->name, -1, VSB_QUOTE_CSTR);
379 55944
                VSB_cat(vsb, " */\n");
380 55944
                VSB_quote_pfx(vsb, "\t", sp->b, sp->e - sp->b, VSB_QUOTE_CSTR);
381 55944
                VSB_cat(vsb, ",\n");
382 55944
        }
383 27636
        VSB_cat(vsb, "};\n\n");
384
385 27636
        VSB_cat(vsb, "/* ---===### Location Counters ###===---*/\n");
386
387 27636
        VSB_printf(vsb, "\n#define VGC_NREFS %u\n\n", tl->cnt + 1);
388
389 27636
        VSB_cat(vsb, "static const struct vpi_ref VGC_ref[VGC_NREFS] = {\n");
390 27636
        lin = 1;
391 27636
        pos = 0;
392 27636
        sp = 0;
393 27636
        p = NULL;
394 29253294
        VTAILQ_FOREACH(t, &tl->tokens, list) {
395 29225658
                if (t->cnt == 0)
396 26779158
                        continue;
397 2446500
                assert(t->src != NULL);
398 2446500
                if (t->src != sp) {
399 47040
                        lin = 1;
400 47040
                        pos = 0;
401 47040
                        sp = t->src;
402 47040
                        p = sp->b;
403 47040
                }
404 2446500
                assert(sp != NULL);
405 2446500
                assert(p != NULL);
406 252706106
                for (;p < t->b; p++) {
407 250259606
                        if (*p == '\n') {
408 10629108
                                lin++;
409 10629108
                                pos = 0;
410 250259606
                        } else if (*p == '\t') {
411 5472747
                                pos &= ~7;
412 5472747
                                pos += 8;
413 5472747
                        } else
414 234157751
                                pos++;
415
416 250259606
                }
417 4893000
                VSB_printf(vsb, "  [%3u] = { VPI_REF_MAGIC, %u, %8tu, %4u, %3u, ",
418 2446500
                    t->cnt, sp->idx, t->b - sp->b, lin, pos + 1);
419 2446500
                if (t->tok == CSRC)
420 147
                        VSB_cat(vsb, " \"C{\"},\n");
421
                else
422 2446353
                        VSB_printf(vsb, " \"%.*s\" },\n", PF(t));
423 2446500
        }
424 27636
        VSB_cat(vsb, "};\n\n");
425 27636
}
426
427
/*--------------------------------------------------------------------
428
 * Init/Fini/Event
429
 *
430
 * We call DISCARD and COLD events in the opposite order of LOAD and
431
 * WARM.
432
 */
433
434
static void
435 27636
EmitInitFini(struct vcc *tl)
436
{
437 27636
        struct inifin *p, *q = NULL;
438 27636
        unsigned has_event = 0;
439
        struct symbol *sy;
440
441 27636
        Fh(tl, 0, "\n");
442 27636
        Fh(tl, 0, "static unsigned vgc_inistep;\n");
443 27636
        Fh(tl, 0, "static unsigned vgc_warmupstep;\n");
444
445
        /*
446
         * LOAD
447
         */
448 27636
        Fc(tl, 0, "\nstatic int\nVGC_Load(VRT_CTX)\n{\n\n");
449 27636
        Fc(tl, 0, "\tvgc_inistep = 0;\n");
450 27636
        Fc(tl, 0, "\tsize_t ndirector = %dUL;\n", tl->ndirector);
451 27636
        Fc(tl, 0, "\n");
452 278271
        VTAILQ_FOREACH(p, &tl->inifin, list) {
453 250635
                AZ(VSB_finish(p->ini));
454 250635
                assert(p->n > 0);
455 250635
                if (VSB_len(p->ini))
456 246078
                        Fc(tl, 0, "\t/* %u */\n%s\n", p->n, VSB_data(p->ini));
457 250635
                if (p->ignore_errors == 0) {
458 222894
                        Fc(tl, 0, "\tif (ctx->vpi->handling == VCL_RET_FAIL)\n");
459 222894
                        Fc(tl, 0, "\t\treturn(1);\n");
460 222894
                }
461 250635
                Fc(tl, 0, "\tvgc_inistep = %u;\n\n", p->n);
462 250635
                VSB_destroy(&p->ini);
463
464 250635
                AZ(VSB_finish(p->event));
465 250635
                if (VSB_len(p->event))
466 4389
                        has_event = 1;
467 250635
        }
468
469
        /* Handle failures from vcl_init */
470 27636
        Fc(tl, 0, "\n");
471 27636
        Fc(tl, 0, "\tif (ctx->vpi->handling != VCL_RET_OK)\n");
472 27636
        Fc(tl, 0, "\t\treturn(1);\n");
473 27636
        Fc(tl, 0, "\tctx->vpi->handling = 0;\n");
474
475 31626
        VTAILQ_FOREACH(sy, &tl->sym_objects, sideways) {
476 3990
                Fc(tl, 0, "\tif (!%s) {\n", sy->rname);
477 7980
                Fc(tl, 0, "\t\tVRT_fail(ctx, "
478 3990
                    "\"Object %s not initialized\");\n" , sy->name);
479 3990
                Fc(tl, 0, "\t\treturn(1);\n");
480 3990
                Fc(tl, 0, "\t}\n");
481 3990
        }
482
483 27636
        Fc(tl, 0, "\treturn(0);\n");
484 27636
        Fc(tl, 0, "}\n");
485
486
        /*
487
         * DISCARD
488
         */
489 27636
        Fc(tl, 0, "\nstatic int\nVGC_Discard(VRT_CTX)\n{\n\n");
490
491 27636
        Fc(tl, 0, "\tswitch (vgc_inistep) {\n");
492 278271
        VTAILQ_FOREACH_REVERSE(p, &tl->inifin, inifinhead, list) {
493 250635
                AZ(VSB_finish(p->fin));
494 250635
                if (q)
495 222999
                        assert(q->n > p->n);
496 250635
                q = p;
497 250635
                Fc(tl, 0, "\t\tcase %u:\n", p->n);
498 250635
                if (VSB_len(p->fin))
499 250488
                        Fc(tl, 0, "\t%s\n", VSB_data(p->fin));
500 250635
                Fc(tl, 0, "\t\t\t/* FALLTHROUGH */\n");
501 250635
                VSB_destroy(&p->fin);
502 250635
        }
503 27636
        Fc(tl, 0, "\t\tdefault:\n\t\t\tbreak;\n");
504 27636
        Fc(tl, 0, "\t}\n\n");
505 27636
        Fc(tl, 0, "\tswitch (vgc_inistep) {\n");
506 278271
        VTAILQ_FOREACH_REVERSE(p, &tl->inifin, inifinhead, list) {
507 250635
                AZ(VSB_finish(p->final));
508 250635
                Fc(tl, 0, "\t\tcase %u:\n", p->n);
509 250635
                if (VSB_len(p->final))
510 11382
                        Fc(tl, 0, "\t%s\n", VSB_data(p->final));
511 250635
                Fc(tl, 0, "\t\t\t/* FALLTHROUGH */\n");
512 250635
                VSB_destroy(&p->final);
513 250635
        }
514 27636
        Fc(tl, 0, "\t\tdefault:\n\t\t\tbreak;\n");
515 27636
        Fc(tl, 0, "\t}\n\n");
516
517 27636
        Fc(tl, 0, "\treturn (0);\n");
518 27636
        Fc(tl, 0, "}\n");
519
520 27636
        if (has_event) {
521
                /*
522
                 * WARM
523
                 */
524 4158
                Fc(tl, 0, "\nstatic int\n");
525 4158
                Fc(tl, 0, "VGC_Warmup(VRT_CTX, enum vcl_event_e ev)\n{\n\n");
526
527 4158
                Fc(tl, 0, "\tvgc_warmupstep = 0;\n\n");
528 49980
                VTAILQ_FOREACH(p, &tl->inifin, list) {
529 45822
                        assert(p->n > 0);
530 45822
                        if (VSB_len(p->event)) {
531 4389
                                Fc(tl, 0, "\t/* %u */\n", p->n);
532 4389
                                Fc(tl, 0, "\tif (%s)\n", VSB_data(p->event));
533 4389
                                Fc(tl, 0, "\t\treturn (1);\n");
534 4389
                                Fc(tl, 0, "\tvgc_warmupstep = %u;\n\n", p->n);
535 4389
                        }
536 45822
                }
537
538 4158
                Fc(tl, 0, "\treturn (0);\n");
539 4158
                Fc(tl, 0, "}\n");
540
541
                /*
542
                 * COLD
543
                 */
544 4158
                Fc(tl, 0, "\nstatic int\n");
545 4158
                Fc(tl, 0, "VGC_Cooldown(VRT_CTX, enum vcl_event_e ev)\n{\n");
546 4158
                Fc(tl, 0, "\tint retval = 0;\n\n");
547
548 49980
                VTAILQ_FOREACH_REVERSE(p, &tl->inifin, inifinhead, list) {
549 45822
                        if (VSB_len(p->event)) {
550 4389
                                Fc(tl, 0, "\t/* %u */\n", p->n);
551 8778
                                Fc(tl, 0,
552 4389
                                    "\tif (vgc_warmupstep >= %u &&\n", p->n);
553 8778
                                Fc(tl, 0,
554 4389
                                    "\t    %s != 0)\n", VSB_data(p->event));
555 4389
                                Fc(tl, 0, "\t\tretval = 1;\n\n");
556 4389
                        }
557 45822
                        VSB_destroy(&p->event);
558 45822
                }
559
560 4158
                Fc(tl, 0, "\treturn (retval);\n");
561 4158
                Fc(tl, 0, "}\n");
562 4158
        }
563
564
        /*
565
         * EVENTS
566
         */
567 27636
        Fc(tl, 0, "\nstatic int\n");
568 27636
        Fc(tl, 0, "VGC_Event(VRT_CTX, enum vcl_event_e ev)\n");
569 27636
        Fc(tl, 0, "{\n");
570 27636
        Fc(tl, 0, "\tif (ev == VCL_EVENT_LOAD)\n");
571 27636
        Fc(tl, 0, "\t\treturn (VGC_Load(ctx));\n");
572 27636
        if (has_event) {
573 4158
                Fc(tl, 0, "\tif (ev == VCL_EVENT_WARM)\n");
574 4158
                Fc(tl, 0, "\t\treturn (VGC_Warmup(ctx, ev));\n");
575 4158
                Fc(tl, 0, "\tif (ev == VCL_EVENT_COLD)\n");
576 4158
                Fc(tl, 0, "\t\treturn (VGC_Cooldown(ctx, ev));\n");
577 4158
        }
578 27636
        Fc(tl, 0, "\tif (ev == VCL_EVENT_DISCARD)\n");
579 27636
        Fc(tl, 0, "\t\treturn (VGC_Discard(ctx));\n");
580 27636
        Fc(tl, 0, "\tassert(ev != VDI_EVENT_SICK);\n");
581 27636
        Fc(tl, 0, "\n");
582 27636
        if (!has_event)
583 23478
                Fc(tl, 0, "\t(void)vgc_warmupstep;\n");
584 27636
        VCC_WalkSymbols(tl, vcc_refUnusedProbes, SYM_MAIN, SYM_PROBE);
585 27636
        Fc(tl, 0, "\treturn (%d);\n", has_event ? 1 : 0);
586 27636
        Fc(tl, 0, "}\n");
587 27636
}
588
589
/*--------------------------------------------------------------------*/
590
591
static void
592 27636
EmitStruct(const struct vcc *tl)
593
{
594 27636
        Fc(tl, 0, "\nconst struct VCL_conf VCL_conf = {\n");
595 27636
        Fc(tl, 0, "\t.magic = VCL_CONF_MAGIC,\n");
596 27636
        Fc(tl, 0, "\t.syntax = %u,\n", tl->syntax);
597 27636
        Fc(tl, 0, "\t.event_vcl = VGC_Event,\n");
598 27636
        Fc(tl, 0, "\t.default_director = &%s,\n", tl->default_director);
599 27636
        if (tl->default_probe != NULL)
600 210
                Fc(tl, 0, "\t.default_probe = %s,\n", tl->default_probe);
601 27636
        Fc(tl, 0, "\t.ref = VGC_ref,\n");
602 27636
        Fc(tl, 0, "\t.nref = VGC_NREFS,\n");
603 27636
        Fc(tl, 0, "\t.nsrc = VGC_NSRCS,\n");
604 27636
        Fc(tl, 0, "\t.nsub = %d,\n", tl->subref > 0 ? tl->nsub : 0);
605 27636
        Fc(tl, 0, "\t.srcname = srcname,\n");
606 27636
        Fc(tl, 0, "\t.srcbody = srcbody,\n");
607 27636
        Fc(tl, 0, "\t.nvmod = %u,\n", tl->vmod_count);
608
#define VCL_MET_MAC(l,u,t,b) \
609
        Fc(tl, 0, "\t." #l "_func = VGC_function_vcl_" #l ",\n");
610
#include "tbl/vcl_returns.h"
611
        Fc(tl, 0, "\t.instance_info = VGC_instance_info\n");
612
        Fc(tl, 0, "};\n");
613
}
614
615
/*--------------------------------------------------------------------
616
 * Compile the VCL code from the given source and return the C-source
617
 */
618
619
static struct vsb *
620 68395
vcc_CompileSource(struct vcc *tl, struct source *sp, const char *jfile)
621
{
622
        struct proc *p;
623
        struct vsb *vsb;
624
        struct inifin *ifp;
625
626 68395
        Fh(tl, 0, "/* ---===### VCC generated .h code ###===---*/\n");
627 68395
        Fc(tl, 0, "\n/* ---===### VCC generated .c code ###===---*/\n");
628
629 68395
        Fc(tl, 0, "\n#define END_ if (ctx->vpi->handling) return\n");
630
631 68395
        vcc_Parse_Init(tl);
632
633 68395
        vcc_Expr_Init(tl);
634
635 68395
        vcc_Action_Init(tl);
636
637 68395
        vcc_Backend_Init(tl);
638
639 68395
        vcc_Var_Init(tl);
640
641 68395
        vcc_Type_Init(tl);
642
643 68395
        Fh(tl, 0, "\nextern const struct VCL_conf VCL_conf;\n");
644
645
        /* Register and lex the main source */
646 68395
        if (sp != NULL) {
647 34187
                AN(vcc_builtin);
648 34187
                vcc_lex_source(tl, sp, 0);
649 34187
                if (tl->err)
650 798
                        return (NULL);
651 33389
        }
652
653
        /* Register and lex the builtin VCL */
654 67597
        sp = vcc_new_source(tl->builtin_vcl, "builtin", "<builtin>");
655 67597
        assert(sp != NULL);
656 67597
        vcc_lex_source(tl, sp, 1);
657 67597
        if (tl->err)
658 0
                return (NULL);
659
660
        /* Parse the token string */
661 67597
        tl->t = VTAILQ_FIRST(&tl->tokens);
662 67597
        vcc_Parse(tl);
663 67597
        if (tl->err)
664 4535
                return (NULL);
665
666
        /* Check for orphans */
667 63062
        if (vcc_CheckReferences(tl))
668 231
                return (NULL);
669
670
        /* Check that all action returns are legal */
671 62831
        if (vcc_CheckAction(tl) || tl->err)
672 63
                return (NULL);
673
674
        /* Check that all variable uses are legal */
675 62768
        if (vcc_CheckUses(tl) || tl->err)
676 882
                return (NULL);
677
678 61886
        if (vcc_builtin == NULL)
679 34208
                return (NULL);
680
681
        /* Check if we have any backends at all */
682 27678
        if (tl->default_director == NULL) {
683 42
                VSB_cat(tl->sb,
684
                    "No backends or directors found in VCL program, "
685
                    "at least one is necessary.\n");
686 42
                tl->err = 1;
687 42
                return (NULL);
688
        }
689
690
        /* Tie vcl_init/fini in */
691 27636
        ifp = New_IniFin(tl);
692 27636
        VSB_cat(ifp->ini, "\tVGC_function_vcl_init(ctx, VSUB_STATIC, NULL);\n");
693
        /*
694
         * Because the failure could be half way into vcl_init{} so vcl_fini{}
695
         * must always be called, also on failure.
696
         */
697 27636
        ifp->ignore_errors = 1;
698 27636
        VSB_cat(ifp->fin, "\t\tVGC_function_vcl_fini(ctx, VSUB_STATIC, NULL);\n");
699 27636
        VSB_cat(ifp->fin, "\t\t\tVPI_vcl_fini(ctx);");
700
701
        /* Emit method functions */
702 27636
        Fh(tl, 1, "\n");
703 1244943
        VTAILQ_FOREACH(p, &tl->procs, list)
704 2020074
                if (p->method == NULL)
705 802767
                        vcc_EmitProc(tl, p);
706 1244943
        VTAILQ_FOREACH(p, &tl->procs, list)
707 1631847
                if (p->method != NULL)
708 414540
                        vcc_EmitProc(tl, p);
709
710 27636
        EmitInitFini(tl);
711
712 27636
        VCC_InstanceInfo(tl);
713
714 27636
        EmitStruct(tl);
715
716 27636
        VCC_XrefTable(tl);
717
718 27636
        VSB_cat(tl->symtab, "\n]\n");
719 27636
        AZ(VSB_finish(tl->symtab));
720 27636
        if (TLWriteVSB(tl, jfile, tl->symtab, "Symbol table"))
721 0
                return (NULL);
722
723
        /* Combine it all */
724
725 27636
        vsb = VSB_new_auto();
726 27636
        AN(vsb);
727
728 27636
        vcl_output_lang_h(vsb);
729
730 27636
        EmitCoordinates(tl, vsb);
731
732 27636
        AZ(VSB_finish(tl->fh));
733 27636
        VSB_cat(vsb, VSB_data(tl->fh));
734
735 27636
        AZ(VSB_finish(tl->fc));
736 27636
        VSB_cat(vsb, VSB_data(tl->fc));
737
738 27636
        AZ(VSB_finish(vsb));
739 27636
        return (vsb);
740 68395
}
741
742
static struct vcc *
743 34208
vcc_ParseBuiltin(struct vcc *tl)
744
{
745
        struct vcc *tl_builtin;
746
747 34208
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
748 34208
        tl_builtin = VCC_New();
749 34208
        AN(tl_builtin);
750 34208
        VCC_Builtin_VCL(tl_builtin, tl->builtin_vcl);
751 34208
        AZ(vcc_CompileSource(tl_builtin, NULL, NULL));
752 34208
        return (tl_builtin);
753
}
754
755
/*--------------------------------------------------------------------
756
 * Report the range of VCL language we support
757
 */
758
void
759 23351
VCC_VCL_Range(unsigned *lo, unsigned *hi)
760
{
761
762 23351
        AN(lo);
763 23351
        *lo = VCL_LOW;
764 23351
        AN(hi);
765 23351
        *hi = VCL_HIGH;
766 23351
}
767
768
/*--------------------------------------------------------------------
769
 * Compile the VCL code in the argument.  Error messages, if any are
770
 * formatted into the vsb.
771
 */
772
773
int
774 34208
VCC_Compile(struct vcc *tl, struct vsb **sb,
775
    const char *vclsrc, const char *vclsrcfile,
776
    const char *ofile, const char *jfile)
777
{
778
        struct source *sp;
779 34208
        struct vsb *r = NULL;
780 34208
        int retval = 0;
781
782 34208
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
783 34208
        AN(sb);
784 34208
        AN(vclsrcfile);
785 34208
        AN(ofile);
786 34208
        AN(jfile);
787
788 34208
        AZ(vcc_builtin);
789 34208
        vcc_builtin = vcc_ParseBuiltin(tl);
790 34208
        AN(vcc_builtin);
791 34208
        if (vcc_builtin->err) {
792 0
                AZ(VSB_finish(vcc_builtin->sb));
793 0
                *sb = vcc_builtin->sb;
794 0
                return (-1);
795
        }
796
797 34208
        if (vclsrc != NULL)
798 33893
                sp = vcc_new_source(vclsrc, "vcl.inline", vclsrcfile);
799
        else
800 315
                sp = vcc_file_source(tl, vclsrcfile);
801
802 34208
        if (sp != NULL)
803 34187
                r = vcc_CompileSource(tl, sp, jfile);
804
805 34208
        if (r != NULL) {
806 27636
                retval = TLWriteVSB(tl, ofile, r, "C-source");
807 27636
                VSB_destroy(&r);
808 27636
        } else {
809 6572
                retval = -1;
810
        }
811 34208
        AZ(VSB_finish(tl->sb));
812 34208
        *sb = tl->sb;
813 34208
        return (retval);
814 34208
}
815
816
/*--------------------------------------------------------------------
817
 * Allocate a compiler instance
818
 */
819
820
struct vcc *
821 68416
VCC_New(void)
822
{
823
        struct vcc *tl;
824
        struct symbol *sym;
825
        struct proc *p;
826
        struct vsb *vsb;
827
        int i;
828
829 68416
        ALLOC_OBJ(tl, VCC_MAGIC);
830 68416
        AN(tl);
831 68416
        VTAILQ_INIT(&tl->inifin);
832 68416
        VTAILQ_INIT(&tl->tokens);
833 68416
        VTAILQ_INIT(&tl->sources);
834 68416
        VTAILQ_INIT(&tl->procs);
835 68416
        VTAILQ_INIT(&tl->sym_objects);
836 68416
        VTAILQ_INIT(&tl->sym_vmods);
837 68416
        VTAILQ_INIT(&tl->vmod_objects);
838
839 68416
        tl->nsources = 0;
840
841 68416
        tl->symtab = VSB_new_auto();
842 68416
        assert(tl->symtab != NULL);
843 68416
        VSB_cat(tl->symtab, "[\n    {\"version\": 0}");
844
845 68416
        tl->fc = VSB_new_auto();
846 68416
        assert(tl->fc != NULL);
847
848 68416
        tl->fh = VSB_new_auto();
849 68416
        assert(tl->fh != NULL);
850
851 1094656
        for (i = 1; i < VCL_MET_MAX; i++) {
852 2052480
                sym = VCC_MkSym(tl, method_tab[i].name,
853 1026240
                    SYM_MAIN, SYM_SUB, VCL_LOW, VCL_HIGH);
854 1026240
                p = vcc_NewProc(tl, sym);
855 1026240
                p->method = &method_tab[i];
856
857
                // see also VCC_GlobalSymbol()
858 1026240
                vsb = VSB_new_auto();
859 1026240
                AN(vsb);
860 1026240
                VSB_printf(vsb, "%s_%s", SUB->global_pfx, p->method->name);
861 1026240
                AZ(VSB_finish(vsb));
862
863 1026240
                AZ(VSB_bcat(p->cname, VSB_data(vsb), VSB_len(vsb)));
864
865 1026240
                sym->lname = strdup(VSB_data(vsb));
866 1026240
                AN(sym->lname);
867
868 1026240
                VSB_clear(vsb);
869 1026240
                VSB_printf(vsb, "sub_%s", sym->lname);
870 1026240
                AZ(VSB_finish(vsb));
871
872 1026240
                sym->rname = strdup(VSB_data(vsb));
873 1026240
                AN(sym->rname);
874 1026240
                VSB_destroy(&vsb);
875
876 1026240
                sym->type = SUB;
877 1026240
                sym->kind = VCC_HandleKind(SUB);
878 1026240
                AZ(VCT_invalid_name(sym->rname, NULL));
879 1026240
                sym->eval = vcc_Eval_Sub;
880 1026240
        }
881 68416
        tl->sb = VSB_new_auto();
882 68416
        AN(tl->sb);
883 68416
        return (tl);
884
}
885
886
/*--------------------------------------------------------------------
887
 * Configure builtin VCL source code
888
 */
889
890
void
891 68416
VCC_Builtin_VCL(struct vcc *vcc, const char *str)
892
{
893
894 68416
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
895 68416
        REPLACE(vcc->builtin_vcl, str);
896 68416
}
897
898
/*--------------------------------------------------------------------
899
 * Configure default VCL source path
900
 */
901
902
void
903 34208
VCC_VCL_path(struct vcc *vcc, const char *str)
904
{
905
906 34208
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
907 34208
        VFIL_setpath(&vcc->vcl_path, str);
908 34208
}
909
910
/*--------------------------------------------------------------------
911
 * Configure default VMOD path
912
 */
913
914
void
915 34208
VCC_VMOD_path(struct vcc *vcc, const char *str)
916
{
917
918 34208
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
919 34208
        VFIL_setpath(&vcc->vmod_path, str);
920 34208
}
921
922
/*--------------------------------------------------------------------
923
 * Configure settings
924
 */
925
926
#define VCC_FEATURE_BIT(U, l, d)                                \
927
        void VCC_Opt_ ## l(struct vcc *vcc, unsigned val)       \
928
        {                                                       \
929
                CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);              \
930
                vcc->l = val;                                   \
931
        }
932
#include "tbl/vcc_feature_bits.h"
933
934
/*--------------------------------------------------------------------
935
 * Configure settings
936
 */
937
938
static void
939 882
vcc_predef_vcl(struct vcc *vcc, const char *name)
940
{
941
        struct symbol *sym;
942
943 882
        sym = VCC_MkSym(vcc, name, SYM_MAIN, SYM_VCL, VCL_LOW, VCL_HIGH);
944 882
        AN(sym);
945 882
        sym->type = VCL;
946 882
        sym->r_methods = VCL_MET_RECV;
947 882
}
948
949
void
950 103611
VCC_Predef(struct vcc *vcc, const char *type, const char *name)
951
{
952
953 103611
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
954 103611
        if (!vstrcmp(type, "VCL_STEVEDORE"))
955 102729
                vcc_stevedore(vcc, name);
956 882
        else if (!vstrcmp(type, "VCL_VCL"))
957 882
                vcc_predef_vcl(vcc, name);
958
        else
959 0
                WRONG("Unknown VCC predef type");
960 103611
}
961
962
void
963 42
VCC_VEXT(struct vcc *vcc, const char *filename)
964
{
965 42
        CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
966 42
        vcc_ImportVext(vcc, filename);
967 42
}