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