| | varnish-cache/lib/libvcc/vcc_action.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 |
288544 |
* 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 |
288544 |
* 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 |
288544 |
* 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 |
288544 |
* SUCH DAMAGE. |
| 29 |
|
* |
| 30 |
|
* This file parses the real action of the VCL code, the procedure |
| 31 |
|
* statements which do the actual work. |
| 32 |
|
*/ |
| 33 |
|
|
| 34 |
288544 |
#include "config.h" |
| 35 |
|
|
| 36 |
|
#include <string.h> |
| 37 |
|
|
| 38 |
|
#include "vcc_compile.h" |
| 39 |
|
#include "libvcc.h" |
| 40 |
|
|
| 41 |
|
/*--------------------------------------------------------------------*/ |
| 42 |
|
|
| 43 |
|
static void v_matchproto_(sym_act_f) |
| 44 |
332320 |
vcc_act_call(struct vcc *tl, struct token *t, struct symbol *sym) |
| 45 |
|
{ |
| 46 |
|
struct token *t0; |
| 47 |
|
unsigned u; |
| 48 |
|
|
| 49 |
332320 |
(void)t; |
| 50 |
332320 |
ExpectErr(tl, ID); |
| 51 |
620864 |
t0 = tl->t; |
| 52 |
332320 |
sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_NONE, SYMTAB_PARTIAL_NOERR, |
| 53 |
|
XREF_REF); |
| 54 |
332320 |
if (sym == NULL) { |
| 55 |
297432 |
sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_SUB, SYMTAB_CREATE, |
| 56 |
|
XREF_REF); |
| 57 |
585976 |
if (sym == NULL) |
| 58 |
0 |
return; |
| 59 |
297432 |
VCC_GlobalSymbol(sym, SUB); |
| 60 |
297432 |
} |
| 61 |
288544 |
|
| 62 |
332320 |
if (sym->kind == SYM_SUB) { |
| 63 |
332308 |
vcc_AddCall(tl, t0, sym); |
| 64 |
|
|
| 65 |
620852 |
Fb(tl, 1, "%s(ctx, VSUB_STATIC, NULL);\n", sym->lname); |
| 66 |
332308 |
SkipToken(tl, ';'); |
| 67 |
332308 |
return; |
| 68 |
|
} |
| 69 |
288544 |
|
| 70 |
12 |
tl->t = t0; |
| 71 |
12 |
u = tl->unique++; |
| 72 |
|
|
| 73 |
288556 |
Fb(tl, 1, "{\n"); |
| 74 |
12 |
tl->indent += INDENT; |
| 75 |
12 |
Fb(tl, 2, "VCL_SUB call_%u =\n", u); |
| 76 |
12 |
tl->indent += INDENT; |
| 77 |
12 |
vcc_Expr(tl, SUB); |
| 78 |
288556 |
Fb(tl, 2, ";\n\n"); |
| 79 |
12 |
SkipToken(tl, ';'); |
| 80 |
8 |
tl->indent -= INDENT; |
| 81 |
8 |
Fb(tl, 2, "if (call_%u == NULL) {\n", u); |
| 82 |
8 |
Fb(tl, 2, " VRT_fail(ctx, \"Tried to call NULL SUB near" |
| 83 |
|
" source %%u line %%u\",\n"); |
| 84 |
8 |
Fb(tl, 2, " VGC_ref[%u].source,\n", tl->cnt); |
| 85 |
288552 |
Fb(tl, 2, " VGC_ref[%u].line);\n", tl->cnt); |
| 86 |
8 |
Fb(tl, 2, " END_;\n"); |
| 87 |
8 |
Fb(tl, 2, "}\n"); |
| 88 |
8 |
Fb(tl, 2, "call_%u->func(ctx, VSUB_STATIC, NULL);\n", u); |
| 89 |
8 |
tl->indent -= INDENT; |
| 90 |
288552 |
Fb(tl, 1, "}\n"); |
| 91 |
332320 |
} |
| 92 |
|
|
| 93 |
|
/*--------------------------------------------------------------------*/ |
| 94 |
288544 |
|
| 95 |
|
static const struct assign { |
| 96 |
|
vcc_type_t type; |
| 97 |
|
unsigned oper; |
| 98 |
|
vcc_type_t want; |
| 99 |
|
const char *expr; |
| 100 |
|
} assign[] = { |
| 101 |
|
{ INT, T_INCR, INT, "\v + " }, |
| 102 |
|
{ INT, T_DECR, INT, "\v - " }, |
| 103 |
|
{ INT, T_MUL, INT, "\v * " }, |
| 104 |
288544 |
{ INT, T_DIV, INT, "\v / " }, |
| 105 |
|
{ INT, '=', INT }, |
| 106 |
|
{ INT, 0, INT }, |
| 107 |
|
{ TIME, T_INCR, DURATION, "\v + " }, |
| 108 |
|
{ TIME, T_DECR, DURATION, "\v - " }, |
| 109 |
|
{ TIME, T_MUL, REAL, "\v * " }, |
| 110 |
288544 |
{ TIME, T_DIV, REAL, "\v / " }, |
| 111 |
|
{ TIME, '=', TIME }, |
| 112 |
|
{ TIME, 0, TIME }, |
| 113 |
|
{ DURATION, T_INCR, DURATION, "\v + " }, |
| 114 |
|
{ DURATION, T_DECR, DURATION, "\v - " }, |
| 115 |
|
{ DURATION, T_MUL, REAL, "\v * " }, |
| 116 |
|
{ DURATION, T_DIV, REAL, "\v / " }, |
| 117 |
|
{ DURATION, '=', DURATION }, |
| 118 |
|
{ DURATION, 0, DURATION }, |
| 119 |
|
{ STRING, T_INCR, STRANDS, "\v,\n" }, |
| 120 |
288544 |
{ STRING, '=', STRANDS, "0,\n" }, |
| 121 |
|
{ HEADER, T_INCR, STRANDS, "VRT_GetHdr(ctx, \v),\n" }, |
| 122 |
|
{ HEADER, '=', STRANDS, "0,\n" }, |
| 123 |
|
{ BODY, '=', BODY, "LBODY_SET_" }, |
| 124 |
|
{ BODY, T_INCR, BODY, "LBODY_ADD_" }, |
| 125 |
|
{ VOID, '=', VOID } |
| 126 |
|
}; |
| 127 |
|
|
| 128 |
|
static void |
| 129 |
125812 |
vcc_assign_expr(struct vcc *tl, struct symbol *sym, const struct assign *ap) |
| 130 |
|
{ |
| 131 |
|
const char *e; |
| 132 |
125812 |
unsigned indent = 1; |
| 133 |
|
|
| 134 |
125812 |
e = ap->expr; |
| 135 |
125812 |
if (e == NULL) |
| 136 |
25740 |
return; |
| 137 |
|
|
| 138 |
561404 |
while (*e != '\0') { |
| 139 |
461332 |
if (*e == '\v') |
| 140 |
80 |
Fb(tl, indent, "%s", sym->rname); |
| 141 |
|
else |
| 142 |
461252 |
Fb(tl, indent, "%c", *e); |
| 143 |
461332 |
indent = 0; |
| 144 |
461332 |
e++; |
| 145 |
|
} |
| 146 |
125812 |
} |
| 147 |
|
|
| 148 |
|
/*--------------------------------------------------------------------*/ |
| 149 |
|
|
| 150 |
|
static void v_matchproto_(sym_act_f) |
| 151 |
125860 |
vcc_act_set(struct vcc *tl, struct token *t, struct symbol *sym) |
| 152 |
|
{ |
| 153 |
|
const struct assign *ap; |
| 154 |
|
vcc_type_t type; |
| 155 |
|
|
| 156 |
125860 |
(void)t; |
| 157 |
125860 |
ExpectErr(tl, ID); |
| 158 |
125860 |
t = tl->t; |
| 159 |
125860 |
sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_VAR, SYMTAB_EXISTING, XREF_NONE); |
| 160 |
125860 |
ERRCHK(tl); |
| 161 |
125828 |
AN(sym); |
| 162 |
125828 |
vcc_AddUses(tl, t, tl->t, sym, XREF_WRITE); |
| 163 |
125828 |
ERRCHK(tl); |
| 164 |
125828 |
type = sym->type; |
| 165 |
2764472 |
for (ap = assign; ap->type != VOID; ap++) { |
| 166 |
2751232 |
if (ap->type != type) |
| 167 |
2511520 |
continue; |
| 168 |
239712 |
if (ap->oper != tl->t->tok) |
| 169 |
127124 |
continue; |
| 170 |
112588 |
vcc_NextToken(tl); |
| 171 |
112588 |
type = ap->want; |
| 172 |
112588 |
break; |
| 173 |
|
} |
| 174 |
|
|
| 175 |
125828 |
if (ap->type == VOID) |
| 176 |
13240 |
SkipToken(tl, ap->oper); |
| 177 |
|
|
| 178 |
125812 |
Fb(tl, 1, "%s\n", sym->lname); |
| 179 |
125812 |
tl->indent += INDENT; |
| 180 |
125812 |
vcc_assign_expr(tl, sym, ap); |
| 181 |
125812 |
vcc_Expr(tl, type); |
| 182 |
125812 |
ERRCHK(tl); |
| 183 |
125644 |
tl->indent -= INDENT; |
| 184 |
125644 |
Fb(tl, 1, ");\n"); |
| 185 |
125644 |
SkipToken(tl, ';'); |
| 186 |
125860 |
} |
| 187 |
|
|
| 188 |
|
/*--------------------------------------------------------------------*/ |
| 189 |
|
|
| 190 |
|
static void v_matchproto_(sym_act_f) |
| 191 |
23148 |
vcc_act_unset(struct vcc *tl, struct token *t, struct symbol *sym) |
| 192 |
|
{ |
| 193 |
|
|
| 194 |
|
/* XXX: Wrong, should use VCC_Expr(HEADER) */ |
| 195 |
23148 |
ExpectErr(tl, ID); |
| 196 |
23148 |
t = tl->t; |
| 197 |
23148 |
sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_VAR, SYMTAB_EXISTING, XREF_NONE); |
| 198 |
23148 |
ERRCHK(tl); |
| 199 |
23148 |
AN(sym); |
| 200 |
23148 |
if (sym->u_methods == 0) { |
| 201 |
8 |
vcc_ErrWhere2(tl, t, tl->t); |
| 202 |
8 |
VSB_cat(tl->sb, "Variable cannot be unset.\n"); |
| 203 |
8 |
return; |
| 204 |
|
} |
| 205 |
23140 |
vcc_AddUses(tl, t, tl->t, sym, XREF_UNSET); |
| 206 |
23140 |
Fb(tl, 1, "%s;\n", sym->uname); |
| 207 |
23140 |
SkipToken(tl, ';'); |
| 208 |
23148 |
} |
| 209 |
|
|
| 210 |
|
/*--------------------------------------------------------------------*/ |
| 211 |
|
|
| 212 |
|
static void v_matchproto_(sym_act_f) |
| 213 |
60 |
vcc_act_ban(struct vcc *tl, struct token *t, struct symbol *sym) |
| 214 |
|
{ |
| 215 |
|
|
| 216 |
60 |
(void)t; |
| 217 |
60 |
(void)sym; |
| 218 |
|
|
| 219 |
60 |
SkipToken(tl, '('); |
| 220 |
|
|
| 221 |
60 |
Fb(tl, 1, "(void) VRT_ban_string(ctx, \n"); |
| 222 |
60 |
tl->indent += INDENT; |
| 223 |
60 |
vcc_Expr(tl, STRING); |
| 224 |
60 |
tl->indent -= INDENT; |
| 225 |
60 |
ERRCHK(tl); |
| 226 |
56 |
Fb(tl, 1, ");\n"); |
| 227 |
|
|
| 228 |
56 |
SkipToken(tl, ')'); |
| 229 |
56 |
SkipToken(tl, ';'); |
| 230 |
60 |
} |
| 231 |
|
|
| 232 |
|
/*--------------------------------------------------------------------*/ |
| 233 |
|
|
| 234 |
|
static void v_matchproto_(sym_act_f) |
| 235 |
34380 |
vcc_act_hash_data(struct vcc *tl, struct token *t, struct symbol *sym) |
| 236 |
|
{ |
| 237 |
|
|
| 238 |
34380 |
(void)t; |
| 239 |
34380 |
(void)sym; |
| 240 |
34380 |
SkipToken(tl, '('); |
| 241 |
|
|
| 242 |
34380 |
Fb(tl, 1, "VRT_hashdata(ctx,\n "); |
| 243 |
34380 |
vcc_Expr(tl, STRANDS); |
| 244 |
34380 |
ERRCHK(tl); |
| 245 |
34376 |
Fb(tl, 1, ");\n"); |
| 246 |
34376 |
SkipToken(tl, ')'); |
| 247 |
34376 |
SkipToken(tl, ';'); |
| 248 |
34380 |
} |
| 249 |
|
|
| 250 |
|
/*--------------------------------------------------------------------*/ |
| 251 |
|
|
| 252 |
|
static void |
| 253 |
32 |
vcc_act_return_pass(struct vcc *tl) |
| 254 |
|
{ |
| 255 |
|
|
| 256 |
32 |
SkipToken(tl, '('); |
| 257 |
32 |
Fb(tl, 1, "VRT_hit_for_pass(ctx,\n"); |
| 258 |
32 |
tl->indent += INDENT; |
| 259 |
32 |
vcc_Expr(tl, DURATION); |
| 260 |
32 |
ERRCHK(tl); |
| 261 |
32 |
SkipToken(tl, ')'); |
| 262 |
32 |
Fb(tl, 1, ");\n"); |
| 263 |
32 |
tl->indent -= INDENT; |
| 264 |
32 |
} |
| 265 |
|
/*--------------------------------------------------------------------*/ |
| 266 |
|
|
| 267 |
|
static void |
| 268 |
224 |
vcc_act_return_fail(struct vcc *tl) |
| 269 |
|
{ |
| 270 |
224 |
SkipToken(tl, '('); |
| 271 |
224 |
Fb(tl, 1, "VRT_fail(ctx, \"%%s\",\n"); |
| 272 |
224 |
tl->indent += INDENT; |
| 273 |
224 |
vcc_Expr(tl, STRING); |
| 274 |
224 |
tl->indent -= INDENT; |
| 275 |
224 |
ERRCHK(tl); |
| 276 |
224 |
SkipToken(tl, ')'); |
| 277 |
224 |
Fb(tl, 1, ");\n"); |
| 278 |
224 |
} |
| 279 |
|
|
| 280 |
|
/*--------------------------------------------------------------------*/ |
| 281 |
|
|
| 282 |
|
static void |
| 283 |
69452 |
vcc_act_return_synth(struct vcc *tl) |
| 284 |
|
{ |
| 285 |
|
|
| 286 |
69452 |
SkipToken(tl, '('); |
| 287 |
69452 |
Fb(tl, 1, "VRT_synth(ctx,\n"); |
| 288 |
69452 |
tl->indent += INDENT; |
| 289 |
69452 |
vcc_Expr(tl, INT); |
| 290 |
69452 |
ERRCHK(tl); |
| 291 |
69452 |
Fb(tl, 1, ",\n"); |
| 292 |
69452 |
if (tl->t->tok == ',') { |
| 293 |
45952 |
vcc_NextToken(tl); |
| 294 |
45952 |
vcc_Expr(tl, STRING); |
| 295 |
45952 |
ERRCHK(tl); |
| 296 |
45952 |
} else { |
| 297 |
23500 |
Fb(tl, 1, "(const char*)0\n"); |
| 298 |
|
} |
| 299 |
69452 |
tl->indent -= INDENT; |
| 300 |
69452 |
SkipToken(tl, ')'); |
| 301 |
69452 |
Fb(tl, 1, ");\n"); |
| 302 |
69452 |
} |
| 303 |
|
|
| 304 |
|
/*--------------------------------------------------------------------*/ |
| 305 |
|
|
| 306 |
|
static void |
| 307 |
96 |
vcc_act_return_vcl(struct vcc *tl) |
| 308 |
|
{ |
| 309 |
|
struct symbol *sym; |
| 310 |
|
struct inifin *p; |
| 311 |
|
char buf[1024]; |
| 312 |
|
|
| 313 |
96 |
SkipToken(tl, '('); |
| 314 |
96 |
ExpectErr(tl, ID); |
| 315 |
96 |
sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_VCL, SYMTAB_EXISTING, XREF_NONE); |
| 316 |
96 |
ERRCHK(tl); |
| 317 |
88 |
AN(sym); |
| 318 |
88 |
if (sym->eval_priv == NULL) { |
| 319 |
84 |
VSB_cat(tl->symtab, ",\n {\n"); |
| 320 |
84 |
VSB_cat(tl->symtab, "\t\"dir\": \"import\",\n"); |
| 321 |
84 |
VSB_cat(tl->symtab, "\t\"type\": \"$VCL\",\n"); |
| 322 |
84 |
VSB_printf(tl->symtab, "\t\"name\": \"%s\"\n", sym->name); |
| 323 |
84 |
VSB_cat(tl->symtab, " }"); |
| 324 |
|
|
| 325 |
84 |
bprintf(buf, "vgc_vcl_%u", tl->unique++); |
| 326 |
84 |
sym->eval_priv = strdup(buf); |
| 327 |
84 |
AN(sym->eval_priv); |
| 328 |
|
|
| 329 |
84 |
Fh(tl, 0, "static VCL_VCL %s;", buf); |
| 330 |
84 |
Fh(tl, 0, "\t/* VCL %s */\n", sym->name); |
| 331 |
|
|
| 332 |
84 |
p = New_IniFin(tl); |
| 333 |
84 |
AN(p); |
| 334 |
168 |
VSB_printf(p->ini, "\t%s = VPI_vcl_get(ctx, \"%s\");", |
| 335 |
84 |
buf, sym->name); |
| 336 |
168 |
VSB_printf(p->fin, "\tVPI_vcl_rel(ctx, %s);", |
| 337 |
84 |
buf); |
| 338 |
84 |
} |
| 339 |
176 |
Fb(tl, 1, "VPI_vcl_select(ctx, %s);\t/* %s */\n", |
| 340 |
88 |
(const char*)sym->eval_priv, sym->name); |
| 341 |
88 |
SkipToken(tl, ')'); |
| 342 |
96 |
} |
| 343 |
|
|
| 344 |
|
/*--------------------------------------------------------------------*/ |
| 345 |
|
|
| 346 |
|
static void v_matchproto_(sym_act_f) |
| 347 |
288580 |
vcc_act_return(struct vcc *tl, struct token *t, struct symbol *sym) |
| 348 |
|
{ |
| 349 |
|
unsigned hand, mask; |
| 350 |
|
const char *h; |
| 351 |
|
|
| 352 |
288580 |
(void)t; |
| 353 |
288580 |
(void)sym; |
| 354 |
288580 |
AN(tl->curproc); |
| 355 |
288580 |
if (tl->t->tok == ';' && tl->curproc->method == NULL) { |
| 356 |
32 |
SkipToken(tl, ';'); |
| 357 |
32 |
Fb(tl, 1, "return;\n"); |
| 358 |
32 |
return; |
| 359 |
|
} |
| 360 |
288548 |
SkipToken(tl, '('); |
| 361 |
288544 |
ExpectErr(tl, ID); |
| 362 |
|
|
| 363 |
288544 |
hand = VCL_RET_MAX; |
| 364 |
288544 |
h = NULL; |
| 365 |
288544 |
mask = 0; |
| 366 |
|
#define VCL_RET_MAC(l, U, B) \ |
| 367 |
|
if (vcc_IdIs(tl->t, #l)) { \ |
| 368 |
|
hand = VCL_RET_ ## U; \ |
| 369 |
|
h = #U; \ |
| 370 |
|
mask = (B); \ |
| 371 |
|
} |
| 372 |
|
#include "tbl/vcl_returns.h" |
| 373 |
288544 |
if (h == NULL) { |
| 374 |
4 |
VSB_cat(tl->sb, "Expected return action name.\n"); |
| 375 |
4 |
vcc_ErrWhere(tl, tl->t); |
| 376 |
4 |
ERRCHK(tl); |
| 377 |
0 |
} |
| 378 |
288540 |
assert(hand < VCL_RET_MAX); |
| 379 |
288540 |
AN(mask); |
| 380 |
|
|
| 381 |
|
vcc_ProcAction(tl->curproc, hand, mask, tl->t); |
| 382 |
|
vcc_NextToken(tl); |
| 383 |
288540 |
if (tl->t->tok == '(') { |
| 384 |
69808 |
if (hand == VCL_RET_SYNTH || hand == VCL_RET_ERROR) |
| 385 |
69452 |
vcc_act_return_synth(tl); |
| 386 |
356 |
else if (hand == VCL_RET_VCL) |
| 387 |
96 |
vcc_act_return_vcl(tl); |
| 388 |
260 |
else if (hand == VCL_RET_PASS) |
| 389 |
32 |
vcc_act_return_pass(tl); |
| 390 |
228 |
else if (hand == VCL_RET_FAIL) |
| 391 |
224 |
vcc_act_return_fail(tl); |
| 392 |
|
else { |
| 393 |
4 |
VSB_cat(tl->sb, "Arguments not allowed.\n"); |
| 394 |
4 |
vcc_ErrWhere(tl, tl->t); |
| 395 |
|
} |
| 396 |
69808 |
} else { |
| 397 |
218732 |
if (hand == VCL_RET_SYNTH || hand == VCL_RET_VCL) { |
| 398 |
4 |
VSB_cat(tl->sb, "Missing argument.\n"); |
| 399 |
4 |
vcc_ErrWhere(tl, tl->t); |
| 400 |
4 |
} |
| 401 |
|
} |
| 402 |
288540 |
ERRCHK(tl); |
| 403 |
|
Fb(tl, 1, "END_;\n"); |
| 404 |
288524 |
if (hand == VCL_RET_FAIL) |
| 405 |
312 |
Fb(tl, 1, "VRT_fail(ctx, \"Failed from VCL\");\n"); |
| 406 |
|
else |
| 407 |
288212 |
Fb(tl, 1, "VRT_handling(ctx, VCL_RET_%s);\n", h); |
| 408 |
288524 |
SkipToken(tl, ')'); |
| 409 |
288524 |
SkipToken(tl, ';'); |
| 410 |
|
} |
| 411 |
|
|
| 412 |
|
/*--------------------------------------------------------------------*/ |
| 413 |
|
|
| 414 |
|
static void v_matchproto_(sym_act_f) |
| 415 |
24 |
vcc_act_synthetic(struct vcc *tl, struct token *t, struct symbol *sym) |
| 416 |
|
{ |
| 417 |
|
|
| 418 |
24 |
(void)t; |
| 419 |
24 |
(void)sym; |
| 420 |
24 |
ExpectErr(tl, '('); |
| 421 |
24 |
ERRCHK(tl); |
| 422 |
24 |
vcc_NextToken(tl); |
| 423 |
|
|
| 424 |
24 |
Fb(tl, 1, "VRT_synth_strands(ctx, "); |
| 425 |
24 |
vcc_Expr(tl, STRANDS); |
| 426 |
24 |
ERRCHK(tl); |
| 427 |
20 |
Fb(tl, 1, ");\n"); |
| 428 |
|
|
| 429 |
20 |
SkipToken(tl, ')'); |
| 430 |
20 |
SkipToken(tl, ';'); |
| 431 |
24 |
} |
| 432 |
|
|
| 433 |
|
/*--------------------------------------------------------------------*/ |
| 434 |
|
|
| 435 |
|
// The pp[] trick is to make the length of #name visible to flexelint. |
| 436 |
|
#define ACT(name, func, mask) \ |
| 437 |
|
do { \ |
| 438 |
|
const char pp[] = #name; \ |
| 439 |
|
sym = VCC_MkSym(tl, pp, SYM_MAIN, SYM_ACTION, VCL_LOW, \ |
| 440 |
|
VCL_HIGH); \ |
| 441 |
|
AN(sym); \ |
| 442 |
|
sym->action = func; \ |
| 443 |
|
sym->action_mask = (mask); \ |
| 444 |
|
} while (0) |
| 445 |
|
|
| 446 |
|
void |
| 447 |
12388 |
vcc_Action_Init(struct vcc *tl) |
| 448 |
|
{ |
| 449 |
|
struct symbol *sym; |
| 450 |
|
|
| 451 |
12388 |
ACT(ban, vcc_act_ban, 0); |
| 452 |
12388 |
ACT(call, vcc_act_call, 0); |
| 453 |
12388 |
ACT(hash_data, vcc_act_hash_data, |
| 454 |
|
VCL_MET_HASH); |
| 455 |
12388 |
ACT(if, vcc_Act_If, 0); |
| 456 |
12388 |
ACT(new, vcc_Act_New, |
| 457 |
|
VCL_MET_INIT); |
| 458 |
12388 |
ACT(return, vcc_act_return, 0); |
| 459 |
12388 |
ACT(set, vcc_act_set, 0); |
| 460 |
12388 |
ACT(synthetic, vcc_act_synthetic, |
| 461 |
|
VCL_MET_SYNTH | VCL_MET_BACKEND_ERROR); |
| 462 |
12388 |
ACT(unset, vcc_act_unset, 0); |
| 463 |
12388 |
} |