| | 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 |
2060600 |
vcc_vcl_met2c(struct vsb *vsb, unsigned method) |
| 81 |
|
{ |
| 82 |
2060600 |
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 |
2060600 |
AN(d); |
| 96 |
|
} |
| 97 |
|
|
| 98 |
|
|
| 99 |
|
/*--------------------------------------------------------------------*/ |
| 100 |
|
|
| 101 |
|
void * v_matchproto_(TlAlloc) |
| 102 |
166818200 |
TlAlloc(struct vcc *tl, unsigned len) |
| 103 |
|
{ |
| 104 |
|
void *p; |
| 105 |
|
|
| 106 |
166818200 |
(void)tl; |
| 107 |
166818200 |
p = calloc(1, len); |
| 108 |
166818200 |
assert(p != NULL); |
| 109 |
166818200 |
return (p); |
| 110 |
|
} |
| 111 |
|
|
| 112 |
|
char * |
| 113 |
8628000 |
TlDup(struct vcc *tl, const char *s) |
| 114 |
|
{ |
| 115 |
|
char *p; |
| 116 |
|
|
| 117 |
8628000 |
p = TlAlloc(tl, strlen(s) + 1); |
| 118 |
8628000 |
AN(p); |
| 119 |
8628000 |
strcpy(p, s); |
| 120 |
8628000 |
return (p); |
| 121 |
|
} |
| 122 |
|
|
| 123 |
|
static int |
| 124 |
100400 |
TLWriteVSB(struct vcc *tl, const char *fn, const struct vsb *vsb, |
| 125 |
|
const char *what) |
| 126 |
|
{ |
| 127 |
|
int fo; |
| 128 |
2060600 |
int i; |
| 129 |
|
|
| 130 |
100400 |
fo = open(fn, O_WRONLY|O_TRUNC|O_CREAT, 0600); |
| 131 |
100400 |
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 |
2060600 |
return (-1); |
| 136 |
|
} |
| 137 |
100400 |
i = VSB_tofile(vsb, fo); |
| 138 |
100400 |
if (i) { |
| 139 |
0 |
VSB_printf(tl->sb, |
| 140 |
|
"Could not write %s to %s: %s\n", |
| 141 |
0 |
what, fn, strerror(errno)); |
| 142 |
2060600 |
} |
| 143 |
100400 |
closefd(&fo); |
| 144 |
100400 |
return (i); |
| 145 |
100400 |
} |
| 146 |
|
|
| 147 |
|
/*--------------------------------------------------------------------*/ |
| 148 |
|
|
| 149 |
|
struct proc * |
| 150 |
4834080 |
vcc_NewProc(struct vcc *tl, struct symbol *sym) |
| 151 |
|
{ |
| 152 |
2060600 |
struct proc *p; |
| 153 |
|
|
| 154 |
4834080 |
ALLOC_OBJ(p, PROC_MAGIC); |
| 155 |
4834080 |
AN(p); |
| 156 |
4834080 |
VTAILQ_INIT(&p->calls); |
| 157 |
4834080 |
VTAILQ_INIT(&p->uses); |
| 158 |
4834080 |
VTAILQ_INSERT_TAIL(&tl->procs, p, list); |
| 159 |
4834080 |
p->prologue = VSB_new_auto(); |
| 160 |
4834080 |
AN(p->prologue); |
| 161 |
6894680 |
p->body = VSB_new_auto(); |
| 162 |
4834080 |
AN(p->body); |
| 163 |
4834080 |
p->cname = VSB_new_auto(); |
| 164 |
4834080 |
AN(p->cname); |
| 165 |
4834080 |
p->okmask = VCL_MET_TASK_ALL; |
| 166 |
4834080 |
sym->proc = p; |
| 167 |
4834080 |
p->sym = sym; |
| 168 |
6894680 |
return (p); |
| 169 |
|
} |
| 170 |
|
|
| 171 |
|
static void |
| 172 |
4121200 |
vcc_EmitProc(struct vcc *tl, struct proc *p) |
| 173 |
|
{ |
| 174 |
|
struct vsb *vsbm; |
| 175 |
|
unsigned mask, nsub; |
| 176 |
|
const char *maskcmp; |
| 177 |
2060600 |
const char *cc_adv; |
| 178 |
2060600 |
int dyn = (p->sym->nref > p->called); |
| 179 |
|
|
| 180 |
2060600 |
AN(p->okmask); |
| 181 |
2060600 |
AZ(VSB_finish(p->cname)); |
| 182 |
2060600 |
AZ(VSB_finish(p->prologue)); |
| 183 |
2060600 |
AZ(VSB_finish(p->body)); |
| 184 |
2060600 |
AN(p->sym); |
| 185 |
2060600 |
|
| 186 |
2060600 |
if (p->method) { |
| 187 |
753000 |
mask = p->method->bitval; |
| 188 |
753000 |
maskcmp = "=="; |
| 189 |
753000 |
} else { |
| 190 |
3368200 |
mask = p->okmask; |
| 191 |
1307600 |
maskcmp = "&"; |
| 192 |
|
} |
| 193 |
|
|
| 194 |
2060600 |
if (dyn == 0 && (p->calledfrom & VCL_MET_TASK_H) == p->calledfrom) |
| 195 |
100880 |
cc_adv = "v_dont_optimize "; |
| 196 |
|
else |
| 197 |
1959720 |
cc_adv = ""; |
| 198 |
2060600 |
|
| 199 |
2060600 |
nsub = tl->nsub++; |
| 200 |
|
|
| 201 |
2060600 |
Fh(tl, 1, "vcl_func_f %s;\n", VSB_data(p->cname)); |
| 202 |
4121200 |
Fh(tl, 1, "extern const struct vcl_sub sub_%s[1];\n", |
| 203 |
2060600 |
VSB_data(p->cname)); |
| 204 |
2060600 |
Fh(tl, 1, "const struct vcl_sub sub_%s[1] = {{\n", VSB_data(p->cname)); |
| 205 |
4121200 |
Fh(tl, 1, "\t.magic\t\t= VCL_SUB_MAGIC,\n"); |
| 206 |
2060600 |
Fh(tl, 1, "\t.methods\t= 0x%x,\n", p->okmask); |
| 207 |
2060600 |
Fh(tl, 1, "\t.name\t\t= \"%.*s\",\n", PF(p->name)); |
| 208 |
2060600 |
Fh(tl, 1, "\t.vcl_conf\t= &VCL_conf,\n"); |
| 209 |
2060600 |
Fh(tl, 1, "\t.func\t\t= %s,\n", VSB_data(p->cname)); |
| 210 |
2060600 |
Fh(tl, 1, "\t.n\t\t= %d,\n", nsub); |
| 211 |
4121200 |
Fh(tl, 1, "\t.nref\t\t= %d,\n", p->sym->nref); |
| 212 |
2060600 |
Fh(tl, 1, "\t.called\t\t= %d\n", p->called); |
| 213 |
2060600 |
Fh(tl, 1, "\t// calledfrom\t 0x%x\n", p->calledfrom); |
| 214 |
2060600 |
Fh(tl, 1, "}};\n"); |
| 215 |
|
|
| 216 |
2060600 |
if (dyn) { |
| 217 |
2061840 |
Fc(tl, 1, "\nstatic inline void %s\n", cc_adv); |
| 218 |
1240 |
Fc(tl, 1, "%s_checked(VRT_CTX)\n{\n", VSB_data(p->cname)); |
| 219 |
1240 |
} else { |
| 220 |
2059360 |
Fc(tl, 1, "\nvoid %sv_matchproto_(vcl_func_f)\n", cc_adv); |
| 221 |
4118720 |
Fc(tl, 1, "%s(VRT_CTX, enum vcl_func_call_e call,\n", |
| 222 |
2059360 |
VSB_data(p->cname)); |
| 223 |
2059360 |
Fc(tl, 1, " enum vcl_func_fail_e *failp)\n{\n"); |
| 224 |
2059360 |
Fc(tl, 1, " assert(call == VSUB_STATIC);\n"); |
| 225 |
2059360 |
Fc(tl, 1, " assert(failp == NULL);\n"); |
| 226 |
|
} |
| 227 |
|
|
| 228 |
4121200 |
vsbm = VSB_new_auto(); |
| 229 |
2060600 |
AN(vsbm); |
| 230 |
2060600 |
vcc_vcl_met2c(vsbm, mask); |
| 231 |
2060600 |
AZ(VSB_finish(vsbm)); |
| 232 |
2060600 |
Fc(tl, 1, " assert(ctx->method %s (%s));\n", maskcmp, VSB_data(vsbm)); |
| 233 |
2060600 |
VSB_destroy(&vsbm); |
| 234 |
2060600 |
Fc(tl, 1, "%s\n%s}\n", VSB_data(p->prologue), VSB_data(p->body)); |
| 235 |
2060600 |
VSB_destroy(&p->body); |
| 236 |
2060600 |
VSB_destroy(&p->prologue); |
| 237 |
|
|
| 238 |
2060600 |
if (! dyn) { |
| 239 |
2059360 |
VSB_destroy(&p->cname); |
| 240 |
2059360 |
return; |
| 241 |
|
} |
| 242 |
|
|
| 243 |
|
/* wrapper to call the actual (_checked) function */ |
| 244 |
1240 |
Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_f)\n"); |
| 245 |
2480 |
Fc(tl, 1, "%s(VRT_CTX, enum vcl_func_call_e call,\n", |
| 246 |
1240 |
VSB_data(p->cname)); |
| 247 |
1240 |
Fc(tl, 1, " enum vcl_func_fail_e *failp)\n{\n"); |
| 248 |
1240 |
Fc(tl, 1, " enum vcl_func_fail_e fail;\n\n"); |
| 249 |
2480 |
Fc(tl, 1, " fail = VPI_Call_Check(ctx, &VCL_conf, 0x%x, %d);\n", |
| 250 |
1240 |
mask, nsub); |
| 251 |
1240 |
Fc(tl, 1, " if (failp)\n"); |
| 252 |
1240 |
Fc(tl, 1, " *failp = fail;\n"); |
| 253 |
1240 |
Fc(tl, 1, " else if (fail == VSUB_E_METHOD)\n"); |
| 254 |
2480 |
Fc(tl, 1, " VRT_fail(ctx, \"call to \\\"sub %.*s{}\\\"" |
| 255 |
1240 |
" not allowed from here\");\n", PF(p->name)); |
| 256 |
1240 |
Fc(tl, 1, " else if (fail == VSUB_E_RECURSE)\n"); |
| 257 |
2480 |
Fc(tl, 1, " VRT_fail(ctx, \"Recursive call to " |
| 258 |
1240 |
"\\\"sub %.*s{}\\\"\");\n", PF(p->name)); |
| 259 |
1240 |
Fc(tl, 1, " else\n"); |
| 260 |
1240 |
Fc(tl, 1, " assert (fail == VSUB_E_OK);\n"); |
| 261 |
1240 |
Fc(tl, 1, " if (fail != VSUB_E_OK || call == VSUB_CHECK)\n"); |
| 262 |
1240 |
Fc(tl, 1, " return;\n"); |
| 263 |
1240 |
Fc(tl, 1, " VPI_Call_Begin(ctx, %d);\n", nsub); |
| 264 |
1240 |
Fc(tl, 1, " %s_checked(ctx);\n", VSB_data(p->cname)); |
| 265 |
1240 |
Fc(tl, 1, " VPI_Call_End(ctx, %d);\n", nsub); |
| 266 |
1240 |
Fc(tl, 1, "}\n"); |
| 267 |
1240 |
VSB_destroy(&p->cname); |
| 268 |
2060600 |
} |
| 269 |
|
|
| 270 |
|
/*--------------------------------------------------------------------*/ |
| 271 |
|
|
| 272 |
|
struct inifin * |
| 273 |
626760 |
New_IniFin(struct vcc *tl) |
| 274 |
|
{ |
| 275 |
|
struct inifin *p; |
| 276 |
|
|
| 277 |
626760 |
ALLOC_OBJ(p, INIFIN_MAGIC); |
| 278 |
626760 |
AN(p); |
| 279 |
626760 |
p->ini = VSB_new_auto(); |
| 280 |
626760 |
AN(p->ini); |
| 281 |
626760 |
p->fin = VSB_new_auto(); |
| 282 |
626760 |
AN(p->fin); |
| 283 |
626760 |
p->final = VSB_new_auto(); |
| 284 |
626760 |
AN(p->final); |
| 285 |
626760 |
p->event = VSB_new_auto(); |
| 286 |
626760 |
AN(p->event); |
| 287 |
626760 |
p->n = ++tl->ninifin; |
| 288 |
626760 |
VTAILQ_INSERT_TAIL(&tl->inifin, p, list); |
| 289 |
626760 |
return (p); |
| 290 |
|
} |
| 291 |
|
|
| 292 |
|
/*-------------------------------------------------------------------- |
| 293 |
|
* Printf output to the vsbs, possibly indented |
| 294 |
|
*/ |
| 295 |
|
|
| 296 |
|
void |
| 297 |
36692800 |
Fh(const struct vcc *tl, int indent, const char *fmt, ...) |
| 298 |
|
{ |
| 299 |
|
va_list ap; |
| 300 |
|
|
| 301 |
36692800 |
if (indent) |
| 302 |
26838160 |
VSB_printf(tl->fh, "%*.*s", tl->hindent, tl->hindent, ""); |
| 303 |
36692800 |
va_start(ap, fmt); |
| 304 |
36692800 |
VSB_vprintf(tl->fh, fmt, ap); |
| 305 |
36692800 |
va_end(ap); |
| 306 |
36692800 |
} |
| 307 |
|
|
| 308 |
|
void |
| 309 |
93275240 |
Fb(const struct vcc *tl, int indent, const char *fmt, ...) |
| 310 |
|
{ |
| 311 |
|
va_list ap; |
| 312 |
|
|
| 313 |
93275240 |
assert(tl->fb != NULL); |
| 314 |
93275240 |
if (indent) |
| 315 |
82240560 |
VSB_printf(tl->fb, "%*.*s", tl->indent, tl->indent, ""); |
| 316 |
93275240 |
va_start(ap, fmt); |
| 317 |
93275240 |
VSB_vprintf(tl->fb, fmt, ap); |
| 318 |
93275240 |
va_end(ap); |
| 319 |
93275240 |
} |
| 320 |
|
|
| 321 |
|
void |
| 322 |
74811360 |
Fc(const struct vcc *tl, int indent, const char *fmt, ...) |
| 323 |
|
{ |
| 324 |
|
va_list ap; |
| 325 |
|
|
| 326 |
74811360 |
if (indent) |
| 327 |
14444040 |
VSB_printf(tl->fc, "%*.*s", tl->indent, tl->indent, ""); |
| 328 |
74811360 |
va_start(ap, fmt); |
| 329 |
74811360 |
VSB_vprintf(tl->fc, fmt, ap); |
| 330 |
74811360 |
va_end(ap); |
| 331 |
74811360 |
} |
| 332 |
|
|
| 333 |
|
/*--------------------------------------------------------------------*/ |
| 334 |
|
|
| 335 |
|
void |
| 336 |
4260600 |
EncToken(struct vsb *sb, const struct token *t) |
| 337 |
|
{ |
| 338 |
|
|
| 339 |
4260600 |
assert(t->tok == CSTR); |
| 340 |
4260600 |
VSB_quote(sb, t->dec, -1, VSB_QUOTE_CSTR); |
| 341 |
4260600 |
} |
| 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 |
50200 |
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 |
50200 |
VSB_cat(vsb, "/* ---===### Source Code ###===---*/\n"); |
| 357 |
|
|
| 358 |
50200 |
VSB_printf(vsb, "\n#define VGC_NSRCS %u\n", tl->nsources); |
| 359 |
|
|
| 360 |
50200 |
VSB_cat(vsb, "\nstatic const char *srcname[VGC_NSRCS] = {\n"); |
| 361 |
151840 |
VTAILQ_FOREACH(sp, &tl->sources, list) { |
| 362 |
101640 |
VSB_cat(vsb, "\t"); |
| 363 |
101640 |
VSB_quote(vsb, sp->name, -1, VSB_QUOTE_CSTR); |
| 364 |
101640 |
VSB_cat(vsb, ",\n"); |
| 365 |
101640 |
} |
| 366 |
50200 |
VSB_cat(vsb, "};\n"); |
| 367 |
|
|
| 368 |
50200 |
VSB_printf(vsb, "\nstatic const char *srcbody[%u] = {\n", tl->nsources); |
| 369 |
151840 |
VTAILQ_FOREACH(sp, &tl->sources, list) { |
| 370 |
101640 |
VSB_cat(vsb, " /* "); |
| 371 |
101640 |
VSB_quote(vsb, sp->name, -1, VSB_QUOTE_CSTR); |
| 372 |
101640 |
VSB_cat(vsb, " */\n"); |
| 373 |
101640 |
VSB_quote_pfx(vsb, "\t", sp->b, sp->e - sp->b, VSB_QUOTE_CSTR); |
| 374 |
101640 |
VSB_cat(vsb, ",\n"); |
| 375 |
101640 |
} |
| 376 |
50200 |
VSB_cat(vsb, "};\n\n"); |
| 377 |
|
|
| 378 |
50200 |
VSB_cat(vsb, "/* ---===### Location Counters ###===---*/\n"); |
| 379 |
|
|
| 380 |
50200 |
VSB_printf(vsb, "\n#define VGC_NREFS %u\n\n", tl->cnt + 1); |
| 381 |
|
|
| 382 |
50200 |
VSB_cat(vsb, "static const struct vpi_ref VGC_ref[VGC_NREFS] = {\n"); |
| 383 |
50200 |
lin = 1; |
| 384 |
50200 |
pos = 0; |
| 385 |
50200 |
sp = 0; |
| 386 |
50200 |
p = NULL; |
| 387 |
47775320 |
VTAILQ_FOREACH(t, &tl->tokens, list) { |
| 388 |
47725120 |
if (t->cnt == 0) |
| 389 |
43835000 |
continue; |
| 390 |
3890120 |
assert(t->src != NULL); |
| 391 |
3890120 |
if (t->src != sp) { |
| 392 |
85240 |
lin = 1; |
| 393 |
85240 |
pos = 0; |
| 394 |
85240 |
sp = t->src; |
| 395 |
85240 |
p = sp->b; |
| 396 |
85240 |
} |
| 397 |
3890120 |
assert(sp != NULL); |
| 398 |
3890120 |
assert(p != NULL); |
| 399 |
381382269 |
for (;p < t->b; p++) { |
| 400 |
377492149 |
if (*p == '\n') { |
| 401 |
16942720 |
lin++; |
| 402 |
16942720 |
pos = 0; |
| 403 |
377492149 |
} else if (*p == '\t') { |
| 404 |
8626320 |
pos &= ~7; |
| 405 |
8626320 |
pos += 8; |
| 406 |
8626320 |
} else |
| 407 |
351923109 |
pos++; |
| 408 |
|
|
| 409 |
377492149 |
} |
| 410 |
7780240 |
VSB_printf(vsb, " [%3u] = { VPI_REF_MAGIC, %u, %8tu, %4u, %3u, ", |
| 411 |
3890120 |
t->cnt, sp->idx, t->b - sp->b, lin, pos + 1); |
| 412 |
3890120 |
if (t->tok == CSRC) |
| 413 |
280 |
VSB_cat(vsb, " \"C{\"},\n"); |
| 414 |
|
else |
| 415 |
3889840 |
VSB_printf(vsb, " \"%.*s\" },\n", PF(t)); |
| 416 |
3890120 |
} |
| 417 |
50200 |
VSB_cat(vsb, "};\n\n"); |
| 418 |
50200 |
} |
| 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 |
50200 |
EmitInitFini(const struct vcc *tl) |
| 429 |
|
{ |
| 430 |
50200 |
struct inifin *p, *q = NULL; |
| 431 |
50200 |
unsigned has_event = 0; |
| 432 |
|
struct symbol *sy; |
| 433 |
|
|
| 434 |
50200 |
Fh(tl, 0, "\n"); |
| 435 |
50200 |
Fh(tl, 0, "static unsigned vgc_inistep;\n"); |
| 436 |
50200 |
Fh(tl, 0, "static unsigned vgc_warmupstep;\n"); |
| 437 |
|
|
| 438 |
|
/* |
| 439 |
|
* LOAD |
| 440 |
|
*/ |
| 441 |
50200 |
Fc(tl, 0, "\nstatic int\nVGC_Load(VRT_CTX)\n{\n\n"); |
| 442 |
50200 |
Fc(tl, 0, "\tvgc_inistep = 0;\n"); |
| 443 |
50200 |
Fc(tl, 0, "\tsize_t ndirector = %dUL;\n", tl->ndirector); |
| 444 |
50200 |
Fc(tl, 0, "\n"); |
| 445 |
401760 |
VTAILQ_FOREACH(p, &tl->inifin, list) { |
| 446 |
351560 |
AZ(VSB_finish(p->ini)); |
| 447 |
351560 |
assert(p->n > 0); |
| 448 |
351560 |
if (VSB_len(p->ini)) |
| 449 |
342920 |
Fc(tl, 0, "\t/* %u */\n%s\n", p->n, VSB_data(p->ini)); |
| 450 |
351560 |
if (p->ignore_errors == 0) { |
| 451 |
301360 |
Fc(tl, 0, "\tif (ctx->vpi->handling == VCL_RET_FAIL)\n"); |
| 452 |
301360 |
Fc(tl, 0, "\t\treturn(1);\n"); |
| 453 |
301360 |
} |
| 454 |
351560 |
Fc(tl, 0, "\tvgc_inistep = %u;\n\n", p->n); |
| 455 |
351560 |
VSB_destroy(&p->ini); |
| 456 |
|
|
| 457 |
351560 |
AZ(VSB_finish(p->event)); |
| 458 |
351560 |
if (VSB_len(p->event)) |
| 459 |
4360 |
has_event = 1; |
| 460 |
351560 |
} |
| 461 |
|
|
| 462 |
|
/* Handle failures from vcl_init */ |
| 463 |
50200 |
Fc(tl, 0, "\n"); |
| 464 |
50200 |
Fc(tl, 0, "\tif (ctx->vpi->handling != VCL_RET_OK)\n"); |
| 465 |
50200 |
Fc(tl, 0, "\t\treturn(1);\n"); |
| 466 |
50200 |
Fc(tl, 0, "\tctx->vpi->handling = 0;\n"); |
| 467 |
|
|
| 468 |
57800 |
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 |
50200 |
Fc(tl, 0, "\treturn(0);\n"); |
| 477 |
50200 |
Fc(tl, 0, "}\n"); |
| 478 |
|
|
| 479 |
|
/* |
| 480 |
|
* DISCARD |
| 481 |
|
*/ |
| 482 |
50200 |
Fc(tl, 0, "\nstatic int\nVGC_Discard(VRT_CTX)\n{\n\n"); |
| 483 |
|
|
| 484 |
50200 |
Fc(tl, 0, "\tswitch (vgc_inistep) {\n"); |
| 485 |
401760 |
VTAILQ_FOREACH_REVERSE(p, &tl->inifin, inifinhead, list) { |
| 486 |
351560 |
AZ(VSB_finish(p->fin)); |
| 487 |
351560 |
if (q) |
| 488 |
301360 |
assert(q->n > p->n); |
| 489 |
351560 |
q = p; |
| 490 |
351560 |
Fc(tl, 0, "\t\tcase %u:\n", p->n); |
| 491 |
351560 |
if (VSB_len(p->fin)) |
| 492 |
351480 |
Fc(tl, 0, "\t%s\n", VSB_data(p->fin)); |
| 493 |
351560 |
Fc(tl, 0, "\t\t\t/* FALLTHROUGH */\n"); |
| 494 |
351560 |
VSB_destroy(&p->fin); |
| 495 |
351560 |
} |
| 496 |
50200 |
Fc(tl, 0, "\t\tdefault:\n\t\t\tbreak;\n"); |
| 497 |
50200 |
Fc(tl, 0, "\t}\n\n"); |
| 498 |
50200 |
Fc(tl, 0, "\tswitch (vgc_inistep) {\n"); |
| 499 |
401760 |
VTAILQ_FOREACH_REVERSE(p, &tl->inifin, inifinhead, list) { |
| 500 |
351560 |
AZ(VSB_finish(p->final)); |
| 501 |
351560 |
Fc(tl, 0, "\t\tcase %u:\n", p->n); |
| 502 |
351560 |
if (VSB_len(p->final)) |
| 503 |
20560 |
Fc(tl, 0, "\t%s\n", VSB_data(p->final)); |
| 504 |
351560 |
Fc(tl, 0, "\t\t\t/* FALLTHROUGH */\n"); |
| 505 |
351560 |
VSB_destroy(&p->final); |
| 506 |
351560 |
} |
| 507 |
50200 |
Fc(tl, 0, "\t\tdefault:\n\t\t\tbreak;\n"); |
| 508 |
50200 |
Fc(tl, 0, "\t}\n\n"); |
| 509 |
|
|
| 510 |
50200 |
Fc(tl, 0, "\treturn (0);\n"); |
| 511 |
50200 |
Fc(tl, 0, "}\n"); |
| 512 |
|
|
| 513 |
50200 |
if (has_event) { |
| 514 |
|
/* |
| 515 |
|
* WARM |
| 516 |
|
*/ |
| 517 |
4360 |
Fc(tl, 0, "\nstatic int\n"); |
| 518 |
4360 |
Fc(tl, 0, "VGC_Warmup(VRT_CTX, enum vcl_event_e ev)\n{\n\n"); |
| 519 |
|
|
| 520 |
4360 |
Fc(tl, 0, "\tvgc_warmupstep = 0;\n\n"); |
| 521 |
44120 |
VTAILQ_FOREACH(p, &tl->inifin, list) { |
| 522 |
39760 |
assert(p->n > 0); |
| 523 |
39760 |
if (VSB_len(p->event)) { |
| 524 |
4360 |
Fc(tl, 0, "\t/* %u */\n", p->n); |
| 525 |
4360 |
Fc(tl, 0, "\tif (%s)\n", VSB_data(p->event)); |
| 526 |
4360 |
Fc(tl, 0, "\t\treturn (1);\n"); |
| 527 |
4360 |
Fc(tl, 0, "\tvgc_warmupstep = %u;\n\n", p->n); |
| 528 |
4360 |
} |
| 529 |
39760 |
} |
| 530 |
|
|
| 531 |
4360 |
Fc(tl, 0, "\treturn (0);\n"); |
| 532 |
4360 |
Fc(tl, 0, "}\n"); |
| 533 |
|
|
| 534 |
|
/* |
| 535 |
|
* COLD |
| 536 |
|
*/ |
| 537 |
4360 |
Fc(tl, 0, "\nstatic int\n"); |
| 538 |
4360 |
Fc(tl, 0, "VGC_Cooldown(VRT_CTX, enum vcl_event_e ev)\n{\n"); |
| 539 |
4360 |
Fc(tl, 0, "\tint retval = 0;\n\n"); |
| 540 |
|
|
| 541 |
44120 |
VTAILQ_FOREACH_REVERSE(p, &tl->inifin, inifinhead, list) { |
| 542 |
39760 |
if (VSB_len(p->event)) { |
| 543 |
4360 |
Fc(tl, 0, "\t/* %u */\n", p->n); |
| 544 |
8720 |
Fc(tl, 0, |
| 545 |
4360 |
"\tif (vgc_warmupstep >= %u &&\n", p->n); |
| 546 |
8720 |
Fc(tl, 0, |
| 547 |
4360 |
"\t %s != 0)\n", VSB_data(p->event)); |
| 548 |
4360 |
Fc(tl, 0, "\t\tretval = 1;\n\n"); |
| 549 |
4360 |
} |
| 550 |
39760 |
VSB_destroy(&p->event); |
| 551 |
39760 |
} |
| 552 |
|
|
| 553 |
4360 |
Fc(tl, 0, "\treturn (retval);\n"); |
| 554 |
4360 |
Fc(tl, 0, "}\n"); |
| 555 |
4360 |
} |
| 556 |
|
|
| 557 |
|
/* |
| 558 |
|
* EVENTS |
| 559 |
|
*/ |
| 560 |
50200 |
Fc(tl, 0, "\nstatic int\n"); |
| 561 |
50200 |
Fc(tl, 0, "VGC_Event(VRT_CTX, enum vcl_event_e ev)\n"); |
| 562 |
50200 |
Fc(tl, 0, "{\n"); |
| 563 |
50200 |
Fc(tl, 0, "\tif (ev == VCL_EVENT_LOAD)\n"); |
| 564 |
50200 |
Fc(tl, 0, "\t\treturn (VGC_Load(ctx));\n"); |
| 565 |
50200 |
if (has_event) { |
| 566 |
4360 |
Fc(tl, 0, "\tif (ev == VCL_EVENT_WARM)\n"); |
| 567 |
4360 |
Fc(tl, 0, "\t\treturn (VGC_Warmup(ctx, ev));\n"); |
| 568 |
4360 |
Fc(tl, 0, "\tif (ev == VCL_EVENT_COLD)\n"); |
| 569 |
4360 |
Fc(tl, 0, "\t\treturn (VGC_Cooldown(ctx, ev));\n"); |
| 570 |
4360 |
} |
| 571 |
50200 |
Fc(tl, 0, "\tif (ev == VCL_EVENT_DISCARD)\n"); |
| 572 |
50200 |
Fc(tl, 0, "\t\treturn (VGC_Discard(ctx));\n"); |
| 573 |
50200 |
Fc(tl, 0, "\n"); |
| 574 |
50200 |
if (!has_event) |
| 575 |
45840 |
Fc(tl, 0, "\t(void)vgc_warmupstep;\n"); |
| 576 |
50200 |
Fc(tl, 0, "\treturn (%d);\n", has_event ? 1 : 0); |
| 577 |
50200 |
Fc(tl, 0, "}\n"); |
| 578 |
50200 |
} |
| 579 |
|
|
| 580 |
|
/*--------------------------------------------------------------------*/ |
| 581 |
|
|
| 582 |
|
static void |
| 583 |
50200 |
EmitStruct(const struct vcc *tl) |
| 584 |
|
{ |
| 585 |
50200 |
Fc(tl, 0, "\nconst struct VCL_conf VCL_conf = {\n"); |
| 586 |
50200 |
Fc(tl, 0, "\t.magic = VCL_CONF_MAGIC,\n"); |
| 587 |
50200 |
Fc(tl, 0, "\t.syntax = %u,\n", tl->syntax); |
| 588 |
50200 |
Fc(tl, 0, "\t.event_vcl = VGC_Event,\n"); |
| 589 |
50200 |
Fc(tl, 0, "\t.default_director = &%s,\n", tl->default_director); |
| 590 |
50200 |
if (tl->default_probe != NULL) |
| 591 |
400 |
Fc(tl, 0, "\t.default_probe = %s,\n", tl->default_probe); |
| 592 |
50200 |
Fc(tl, 0, "\t.ref = VGC_ref,\n"); |
| 593 |
50200 |
Fc(tl, 0, "\t.nref = VGC_NREFS,\n"); |
| 594 |
50200 |
Fc(tl, 0, "\t.nsrc = VGC_NSRCS,\n"); |
| 595 |
50200 |
Fc(tl, 0, "\t.nsub = %d,\n", tl->subref > 0 ? tl->nsub : 0); |
| 596 |
50200 |
Fc(tl, 0, "\t.srcname = srcname,\n"); |
| 597 |
50200 |
Fc(tl, 0, "\t.srcbody = srcbody,\n"); |
| 598 |
50200 |
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 |
123800 |
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 |
123800 |
Fh(tl, 0, "/* ---===### VCC generated .h code ###===---*/\n"); |
| 618 |
123800 |
Fc(tl, 0, "\n/* ---===### VCC generated .c code ###===---*/\n"); |
| 619 |
|
|
| 620 |
123800 |
Fc(tl, 0, "\n#define END_ if (ctx->vpi->handling) return\n"); |
| 621 |
|
|
| 622 |
123800 |
vcc_Parse_Init(tl); |
| 623 |
|
|
| 624 |
123800 |
vcc_Expr_Init(tl); |
| 625 |
|
|
| 626 |
123800 |
vcc_Action_Init(tl); |
| 627 |
|
|
| 628 |
123800 |
vcc_Backend_Init(tl); |
| 629 |
|
|
| 630 |
123800 |
vcc_Var_Init(tl); |
| 631 |
|
|
| 632 |
123800 |
vcc_Type_Init(tl); |
| 633 |
|
|
| 634 |
123800 |
Fh(tl, 0, "\nextern const struct VCL_conf VCL_conf;\n"); |
| 635 |
|
|
| 636 |
|
/* Register and lex the main source */ |
| 637 |
123800 |
if (sp != NULL) { |
| 638 |
61880 |
AN(vcc_builtin); |
| 639 |
61880 |
vcc_lex_source(tl, sp, 0); |
| 640 |
61880 |
if (tl->err) |
| 641 |
1320 |
return (NULL); |
| 642 |
60560 |
} |
| 643 |
|
|
| 644 |
|
/* Register and lex the builtin VCL */ |
| 645 |
122480 |
sp = vcc_new_source(tl->builtin_vcl, "builtin", "<builtin>"); |
| 646 |
122480 |
assert(sp != NULL); |
| 647 |
122480 |
vcc_lex_source(tl, sp, 1); |
| 648 |
122480 |
if (tl->err) |
| 649 |
0 |
return (NULL); |
| 650 |
|
|
| 651 |
|
/* Expand and lex any includes in the token string */ |
| 652 |
122480 |
if (tl->err) |
| 653 |
0 |
return (NULL); |
| 654 |
|
|
| 655 |
|
/* Parse the token string */ |
| 656 |
122480 |
tl->t = VTAILQ_FIRST(&tl->tokens); |
| 657 |
122480 |
vcc_Parse(tl); |
| 658 |
122480 |
if (tl->err) |
| 659 |
8120 |
return (NULL); |
| 660 |
|
|
| 661 |
|
/* Check for orphans */ |
| 662 |
114360 |
if (vcc_CheckReferences(tl)) |
| 663 |
360 |
return (NULL); |
| 664 |
|
|
| 665 |
|
/* Check that all action returns are legal */ |
| 666 |
114000 |
if (vcc_CheckAction(tl) || tl->err) |
| 667 |
120 |
return (NULL); |
| 668 |
|
|
| 669 |
|
/* Check that all variable uses are legal */ |
| 670 |
113880 |
if (vcc_CheckUses(tl) || tl->err) |
| 671 |
1680 |
return (NULL); |
| 672 |
|
|
| 673 |
112200 |
if (vcc_builtin == NULL) |
| 674 |
61920 |
return (NULL); |
| 675 |
|
|
| 676 |
|
/* Check if we have any backends at all */ |
| 677 |
50280 |
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 |
50200 |
ifp = New_IniFin(tl); |
| 687 |
50200 |
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 |
50200 |
ifp->ignore_errors = 1; |
| 693 |
50200 |
VSB_cat(ifp->fin, "\t\tVGC_function_vcl_fini(ctx, VSUB_STATIC, NULL);\n"); |
| 694 |
50200 |
VSB_cat(ifp->fin, "\t\t\tVPI_vcl_fini(ctx);"); |
| 695 |
|
|
| 696 |
|
/* Emit method functions */ |
| 697 |
50200 |
Fh(tl, 1, "\n"); |
| 698 |
2110800 |
VTAILQ_FOREACH(p, &tl->procs, list) |
| 699 |
3368200 |
if (p->method == NULL) |
| 700 |
1307600 |
vcc_EmitProc(tl, p); |
| 701 |
2110800 |
VTAILQ_FOREACH(p, &tl->procs, list) |
| 702 |
2813600 |
if (p->method != NULL) |
| 703 |
753000 |
vcc_EmitProc(tl, p); |
| 704 |
|
|
| 705 |
50200 |
EmitInitFini(tl); |
| 706 |
|
|
| 707 |
50200 |
VCC_InstanceInfo(tl); |
| 708 |
|
|
| 709 |
50200 |
EmitStruct(tl); |
| 710 |
|
|
| 711 |
50200 |
VCC_XrefTable(tl); |
| 712 |
|
|
| 713 |
50200 |
VSB_cat(tl->symtab, "\n]\n"); |
| 714 |
50200 |
AZ(VSB_finish(tl->symtab)); |
| 715 |
50200 |
if (TLWriteVSB(tl, jfile, tl->symtab, "Symbol table")) |
| 716 |
0 |
return (NULL); |
| 717 |
|
|
| 718 |
|
/* Combine it all */ |
| 719 |
|
|
| 720 |
50200 |
vsb = VSB_new_auto(); |
| 721 |
50200 |
AN(vsb); |
| 722 |
|
|
| 723 |
50200 |
vcl_output_lang_h(vsb); |
| 724 |
|
|
| 725 |
50200 |
EmitCoordinates(tl, vsb); |
| 726 |
|
|
| 727 |
50200 |
AZ(VSB_finish(tl->fh)); |
| 728 |
50200 |
VSB_cat(vsb, VSB_data(tl->fh)); |
| 729 |
|
|
| 730 |
50200 |
AZ(VSB_finish(tl->fc)); |
| 731 |
50200 |
VSB_cat(vsb, VSB_data(tl->fc)); |
| 732 |
|
|
| 733 |
50200 |
AZ(VSB_finish(vsb)); |
| 734 |
50200 |
return (vsb); |
| 735 |
123800 |
} |
| 736 |
|
|
| 737 |
|
static struct vcc * |
| 738 |
61920 |
vcc_ParseBuiltin(struct vcc *tl) |
| 739 |
|
{ |
| 740 |
|
struct vcc *tl_builtin; |
| 741 |
|
|
| 742 |
61920 |
CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); |
| 743 |
61920 |
tl_builtin = VCC_New(); |
| 744 |
61920 |
AN(tl_builtin); |
| 745 |
61920 |
VCC_Builtin_VCL(tl_builtin, tl->builtin_vcl); |
| 746 |
61920 |
AZ(vcc_CompileSource(tl_builtin, NULL, NULL)); |
| 747 |
61920 |
return (tl_builtin); |
| 748 |
|
} |
| 749 |
|
|
| 750 |
|
/*-------------------------------------------------------------------- |
| 751 |
|
* Report the range of VCL language we support |
| 752 |
|
*/ |
| 753 |
|
void |
| 754 |
42200 |
VCC_VCL_Range(unsigned *lo, unsigned *hi) |
| 755 |
|
{ |
| 756 |
|
|
| 757 |
42200 |
AN(lo); |
| 758 |
42200 |
*lo = VCL_LOW; |
| 759 |
42200 |
AN(hi); |
| 760 |
42200 |
*hi = VCL_HIGH; |
| 761 |
42200 |
} |
| 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 |
61920 |
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 |
61920 |
struct vsb *r = NULL; |
| 775 |
61920 |
int retval = 0; |
| 776 |
|
|
| 777 |
61920 |
CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); |
| 778 |
61920 |
AN(sb); |
| 779 |
61920 |
AN(vclsrcfile); |
| 780 |
61920 |
AN(ofile); |
| 781 |
61920 |
AN(jfile); |
| 782 |
|
|
| 783 |
61920 |
AZ(vcc_builtin); |
| 784 |
61920 |
vcc_builtin = vcc_ParseBuiltin(tl); |
| 785 |
61920 |
AN(vcc_builtin); |
| 786 |
61920 |
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 |
61920 |
if (vclsrc != NULL) |
| 793 |
61400 |
sp = vcc_new_source(vclsrc, "vcl.inline", vclsrcfile); |
| 794 |
|
else |
| 795 |
520 |
sp = vcc_file_source(tl, vclsrcfile); |
| 796 |
|
|
| 797 |
61920 |
if (sp != NULL) |
| 798 |
61880 |
r = vcc_CompileSource(tl, sp, jfile); |
| 799 |
|
|
| 800 |
61920 |
if (r != NULL) { |
| 801 |
50200 |
retval = TLWriteVSB(tl, ofile, r, "C-source"); |
| 802 |
50200 |
VSB_destroy(&r); |
| 803 |
50200 |
} else { |
| 804 |
11720 |
retval = -1; |
| 805 |
|
} |
| 806 |
61920 |
AZ(VSB_finish(tl->sb)); |
| 807 |
61920 |
*sb = tl->sb; |
| 808 |
61920 |
return (retval); |
| 809 |
61920 |
} |
| 810 |
|
|
| 811 |
|
/*-------------------------------------------------------------------- |
| 812 |
|
* Allocate a compiler instance |
| 813 |
|
*/ |
| 814 |
|
|
| 815 |
|
struct vcc * |
| 816 |
123840 |
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 |
123840 |
ALLOC_OBJ(tl, VCC_MAGIC); |
| 825 |
123840 |
AN(tl); |
| 826 |
123840 |
VTAILQ_INIT(&tl->inifin); |
| 827 |
123840 |
VTAILQ_INIT(&tl->tokens); |
| 828 |
123840 |
VTAILQ_INIT(&tl->sources); |
| 829 |
123840 |
VTAILQ_INIT(&tl->procs); |
| 830 |
123840 |
VTAILQ_INIT(&tl->sym_objects); |
| 831 |
123840 |
VTAILQ_INIT(&tl->sym_vmods); |
| 832 |
123840 |
VTAILQ_INIT(&tl->vmod_objects); |
| 833 |
|
|
| 834 |
123840 |
tl->nsources = 0; |
| 835 |
|
|
| 836 |
123840 |
tl->symtab = VSB_new_auto(); |
| 837 |
123840 |
assert(tl->symtab != NULL); |
| 838 |
123840 |
VSB_cat(tl->symtab, "[\n {\"version\": 0}"); |
| 839 |
|
|
| 840 |
123840 |
tl->fc = VSB_new_auto(); |
| 841 |
123840 |
assert(tl->fc != NULL); |
| 842 |
|
|
| 843 |
123840 |
tl->fh = VSB_new_auto(); |
| 844 |
123840 |
assert(tl->fh != NULL); |
| 845 |
|
|
| 846 |
1981440 |
for (i = 1; i < VCL_MET_MAX; i++) { |
| 847 |
3715200 |
sym = VCC_MkSym(tl, method_tab[i].name, |
| 848 |
1857600 |
SYM_MAIN, SYM_SUB, VCL_LOW, VCL_HIGH); |
| 849 |
1857600 |
p = vcc_NewProc(tl, sym); |
| 850 |
1857600 |
p->method = &method_tab[i]; |
| 851 |
|
|
| 852 |
|
// see also VCC_GlobalSymbol() |
| 853 |
1857600 |
vsb = VSB_new_auto(); |
| 854 |
1857600 |
AN(vsb); |
| 855 |
1857600 |
VSB_printf(vsb, "%s_%s", SUB->global_pfx, p->method->name); |
| 856 |
1857600 |
AZ(VSB_finish(vsb)); |
| 857 |
|
|
| 858 |
1857600 |
AZ(VSB_bcat(p->cname, VSB_data(vsb), VSB_len(vsb))); |
| 859 |
|
|
| 860 |
1857600 |
sym->lname = strdup(VSB_data(vsb)); |
| 861 |
1857600 |
AN(sym->lname); |
| 862 |
|
|
| 863 |
1857600 |
VSB_clear(vsb); |
| 864 |
1857600 |
VSB_printf(vsb, "sub_%s", sym->lname); |
| 865 |
1857600 |
AZ(VSB_finish(vsb)); |
| 866 |
|
|
| 867 |
1857600 |
sym->rname = strdup(VSB_data(vsb)); |
| 868 |
1857600 |
AN(sym->rname); |
| 869 |
1857600 |
VSB_destroy(&vsb); |
| 870 |
|
|
| 871 |
1857600 |
sym->type = SUB; |
| 872 |
1857600 |
sym->kind = VCC_HandleKind(SUB); |
| 873 |
1857600 |
AZ(VCT_invalid_name(sym->rname, NULL)); |
| 874 |
1857600 |
sym->eval = vcc_Eval_Sub; |
| 875 |
1857600 |
} |
| 876 |
123840 |
tl->sb = VSB_new_auto(); |
| 877 |
123840 |
AN(tl->sb); |
| 878 |
123840 |
return (tl); |
| 879 |
|
} |
| 880 |
|
|
| 881 |
|
/*-------------------------------------------------------------------- |
| 882 |
|
* Configure builtin VCL source code |
| 883 |
|
*/ |
| 884 |
|
|
| 885 |
|
void |
| 886 |
123840 |
VCC_Builtin_VCL(struct vcc *vcc, const char *str) |
| 887 |
|
{ |
| 888 |
|
|
| 889 |
123840 |
CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC); |
| 890 |
123840 |
REPLACE(vcc->builtin_vcl, str); |
| 891 |
123840 |
} |
| 892 |
|
|
| 893 |
|
/*-------------------------------------------------------------------- |
| 894 |
|
* Configure default VCL source path |
| 895 |
|
*/ |
| 896 |
|
|
| 897 |
|
void |
| 898 |
61920 |
VCC_VCL_path(struct vcc *vcc, const char *str) |
| 899 |
|
{ |
| 900 |
|
|
| 901 |
61920 |
CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC); |
| 902 |
61920 |
VFIL_setpath(&vcc->vcl_path, str); |
| 903 |
61920 |
} |
| 904 |
|
|
| 905 |
|
/*-------------------------------------------------------------------- |
| 906 |
|
* Configure default VMOD path |
| 907 |
|
*/ |
| 908 |
|
|
| 909 |
|
void |
| 910 |
61920 |
VCC_VMOD_path(struct vcc *vcc, const char *str) |
| 911 |
|
{ |
| 912 |
|
|
| 913 |
61920 |
CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC); |
| 914 |
61920 |
VFIL_setpath(&vcc->vmod_path, str); |
| 915 |
61920 |
} |
| 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 |
125720 |
VCC_Predef(struct vcc *vcc, const char *type, const char *name) |
| 946 |
|
{ |
| 947 |
|
|
| 948 |
125720 |
CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC); |
| 949 |
125720 |
if (!strcmp(type, "VCL_STEVEDORE")) |
| 950 |
124040 |
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 |
125720 |
} |
| 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 |
} |