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