| | varnish-cache/lib/libvcc/vcc_vmod_sym.c |
| 0 |
|
/*- |
| 1 |
|
* Copyright (c) 2010-2015 Varnish Software AS |
| 2 |
|
* All rights reserved. |
| 3 |
|
* |
| 4 |
|
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk> |
| 5 |
|
* |
| 6 |
|
* SPDX-License-Identifier: BSD-2-Clause |
| 7 |
|
* |
| 8 |
176920 |
* Redistribution and use in source and binary forms, with or without |
| 9 |
176920 |
* modification, are permitted provided that the following conditions |
| 10 |
176920 |
* are met: |
| 11 |
176920 |
* 1. Redistributions of source code must retain the above copyright |
| 12 |
176920 |
* notice, this list of conditions and the following disclaimer. |
| 13 |
176920 |
* 2. Redistributions in binary form must reproduce the above copyright |
| 14 |
176920 |
* notice, this list of conditions and the following disclaimer in the |
| 15 |
176920 |
* documentation and/or other materials provided with the distribution. |
| 16 |
176920 |
* |
| 17 |
176920 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 18 |
176920 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 19 |
176920 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 20 |
176920 |
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE |
| 21 |
176920 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 22 |
176920 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 23 |
176920 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 24 |
176920 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 25 |
176920 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 26 |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 27 |
|
* SUCH DAMAGE. |
| 28 |
|
* |
| 29 |
|
* Turn vmod JSON spec into symbols |
| 30 |
|
* |
| 31 |
|
*/ |
| 32 |
|
|
| 33 |
|
#include "config.h" |
| 34 |
|
|
| 35 |
|
#include <stdlib.h> |
| 36 |
|
#include <string.h> |
| 37 |
|
|
| 38 |
|
#include "vcc_compile.h" |
| 39 |
|
|
| 40 |
|
#include "libvcc.h" |
| 41 |
|
#include "vjsn.h" |
| 42 |
|
|
| 43 |
|
#include "vcc_vmod.h" |
| 44 |
|
|
| 45 |
|
struct vmod_obj { |
| 46 |
|
unsigned magic; |
| 47 |
|
#define VMOD_OBJ_MAGIC 0x349885f8 |
| 48 |
|
char *name; |
| 49 |
|
struct type type[1]; |
| 50 |
|
VTAILQ_ENTRY(vmod_obj) list; |
| 51 |
|
}; |
| 52 |
|
|
| 53 |
|
static void |
| 54 |
58880 |
vcc_VmodObject(struct vcc *tl, struct symbol *sym) |
| 55 |
|
{ |
| 56 |
|
struct vmod_obj *obj; |
| 57 |
|
struct vsb *buf; |
| 58 |
|
|
| 59 |
58880 |
buf = VSB_new_auto(); |
| 60 |
58880 |
AN(buf); |
| 61 |
|
|
| 62 |
58880 |
VSB_printf(buf, "%s.%s", sym->vmod_name, sym->name); |
| 63 |
58880 |
AZ(VSB_finish(buf)); |
| 64 |
|
|
| 65 |
58880 |
ALLOC_OBJ(obj, VMOD_OBJ_MAGIC); |
| 66 |
58880 |
AN(obj); |
| 67 |
58880 |
REPLACE(obj->name, VSB_data(buf)); |
| 68 |
|
|
| 69 |
58880 |
INIT_OBJ(obj->type, TYPE_MAGIC); |
| 70 |
58880 |
obj->type->name = obj->name; |
| 71 |
58880 |
sym->type = obj->type; |
| 72 |
58880 |
VTAILQ_INSERT_TAIL(&tl->vmod_objects, obj, list); |
| 73 |
58880 |
VSB_destroy(&buf); |
| 74 |
58880 |
} |
| 75 |
|
|
| 76 |
|
static void |
| 77 |
5080 |
alias_sym(struct vcc *tl, const struct symbol *psym, const struct vjsn_val *v) |
| 78 |
|
{ |
| 79 |
5080 |
char *alias = NULL, *func = NULL; |
| 80 |
|
struct symbol *sym; |
| 81 |
|
struct vsb *buf; |
| 82 |
|
|
| 83 |
5080 |
buf = VSB_new_auto(); |
| 84 |
5080 |
AN(buf); |
| 85 |
|
|
| 86 |
5080 |
VCC_SymName(buf, psym); |
| 87 |
5080 |
VSB_printf(buf, ".%s", v->value); |
| 88 |
5080 |
AZ(VSB_finish(buf)); |
| 89 |
5080 |
REPLACE(alias, VSB_data(buf)); |
| 90 |
|
|
| 91 |
5080 |
v = VTAILQ_NEXT(v, list); |
| 92 |
5080 |
assert(vjsn_is_string(v)); |
| 93 |
|
|
| 94 |
5080 |
VSB_clear(buf); |
| 95 |
5080 |
VCC_SymName(buf, psym); |
| 96 |
5080 |
VSB_printf(buf, ".%s", v->value); |
| 97 |
5080 |
AZ(VSB_finish(buf)); |
| 98 |
5080 |
REPLACE(func, VSB_data(buf)); |
| 99 |
|
|
| 100 |
5080 |
sym = VCC_MkSymAlias(tl, alias, func); |
| 101 |
5080 |
AN(sym); |
| 102 |
5080 |
assert(sym->kind == SYM_FUNC || sym->kind == SYM_METHOD); |
| 103 |
5080 |
VSB_destroy(&buf); |
| 104 |
5080 |
free(alias); |
| 105 |
5080 |
free(func); |
| 106 |
5080 |
} |
| 107 |
|
|
| 108 |
|
static void |
| 109 |
831040 |
func_restrict(struct vcc *tl, struct symbol *sym, vcc_kind_t kind, const struct vjsn_val *v) |
| 110 |
|
{ |
| 111 |
|
struct vjsn_val *vv; |
| 112 |
|
|
| 113 |
831040 |
AN(v); |
| 114 |
831040 |
AN(sym); |
| 115 |
|
|
| 116 |
831040 |
if (kind != SYM_FUNC && kind != SYM_METHOD) |
| 117 |
0 |
return; |
| 118 |
|
|
| 119 |
831040 |
v = VTAILQ_NEXT(v, list); |
| 120 |
831040 |
if (!v || !vjsn_is_array(v)) |
| 121 |
62840 |
return; |
| 122 |
768200 |
vv = VTAILQ_FIRST(&v->children); |
| 123 |
768200 |
AN(vv); |
| 124 |
768200 |
assert(vjsn_is_string(vv)); |
| 125 |
768200 |
if (strcmp(vv->value, "$RESTRICT")) |
| 126 |
683440 |
return; |
| 127 |
84760 |
vv = VTAILQ_NEXT(vv, list); |
| 128 |
84760 |
AN(vv); |
| 129 |
84760 |
assert(vjsn_is_array(vv)); |
| 130 |
84760 |
sym->r_methods = 0; |
| 131 |
84760 |
vv = VTAILQ_FIRST(&vv->children); |
| 132 |
|
unsigned s; |
| 133 |
261640 |
while (vv) { |
| 134 |
176920 |
s = 0; |
| 135 |
|
#define VCL_CTX(l,H) \ |
| 136 |
|
if (strcmp(vv->value, #l) == 0) s = VCL_MET_##H; |
| 137 |
|
#include "tbl/vcl_context.h" |
| 138 |
176920 |
if (!s) { |
| 139 |
40 |
VSB_printf(tl->sb, "Error in vmod \"%s\", invalid scope for $Restrict: %s\n",sym->vmod_name, vv->value); |
| 140 |
40 |
tl->err = 1; |
| 141 |
40 |
break; |
| 142 |
|
} |
| 143 |
|
sym->r_methods |= s; |
| 144 |
|
vv = VTAILQ_NEXT(vv,list); |
| 145 |
|
} |
| 146 |
831040 |
} |
| 147 |
|
|
| 148 |
|
static void |
| 149 |
895000 |
func_sym(struct vcc *tl, vcc_kind_t kind, const struct symbol *psym, |
| 150 |
|
const struct vjsn_val *v, const struct vjsn_val *vv) |
| 151 |
|
{ |
| 152 |
|
struct symbol *sym; |
| 153 |
|
struct vsb *buf; |
| 154 |
|
|
| 155 |
895000 |
if (kind == SYM_ALIAS) { |
| 156 |
5080 |
alias_sym(tl, psym, v); |
| 157 |
5080 |
return; |
| 158 |
|
} |
| 159 |
|
|
| 160 |
889920 |
buf = VSB_new_auto(); |
| 161 |
889920 |
AN(buf); |
| 162 |
|
|
| 163 |
889920 |
VCC_SymName(buf, psym); |
| 164 |
889920 |
VSB_printf(buf, ".%s", v->value); |
| 165 |
889920 |
AZ(VSB_finish(buf)); |
| 166 |
889920 |
sym = VCC_MkSym(tl, VSB_data(buf), SYM_MAIN, kind, VCL_LOW, VCL_HIGH); |
| 167 |
889920 |
AN(sym); |
| 168 |
889920 |
VSB_destroy(&buf); |
| 169 |
|
|
| 170 |
889920 |
if (kind == SYM_OBJECT) { |
| 171 |
58880 |
sym->eval_priv = v; |
| 172 |
58880 |
sym->vmod_name = psym->vmod_name; |
| 173 |
58880 |
sym->r_methods = VCL_MET_INIT; |
| 174 |
58880 |
vcc_VmodObject(tl, sym); |
| 175 |
58880 |
vcc_VmodSymbols(tl, sym); |
| 176 |
58880 |
return; |
| 177 |
|
} |
| 178 |
|
|
| 179 |
831040 |
if (kind == SYM_METHOD) |
| 180 |
185960 |
sym->extra = psym->rname; |
| 181 |
|
|
| 182 |
831040 |
v = VTAILQ_NEXT(v, list); |
| 183 |
|
|
| 184 |
831040 |
assert(vjsn_is_array(v)); |
| 185 |
831040 |
sym->action = vcc_Act_Call; |
| 186 |
831040 |
sym->vmod_name = psym->vmod_name; |
| 187 |
831040 |
sym->eval = vcc_Eval_SymFunc; |
| 188 |
831040 |
sym->eval_priv = v; |
| 189 |
831040 |
v = VTAILQ_FIRST(&v->children); |
| 190 |
831040 |
assert(vjsn_is_array(v)); |
| 191 |
831040 |
v = VTAILQ_FIRST(&v->children); |
| 192 |
831040 |
assert(vjsn_is_string(v)); |
| 193 |
831040 |
sym->type = VCC_Type(v->value); |
| 194 |
831040 |
AN(sym->type); |
| 195 |
831040 |
sym->r_methods = VCL_MET_TASK_ALL; |
| 196 |
831040 |
func_restrict(tl, sym, kind, vv); |
| 197 |
895000 |
} |
| 198 |
|
|
| 199 |
|
void |
| 200 |
82200 |
vcc_VmodSymbols(struct vcc *tl, const struct symbol *sym) |
| 201 |
|
{ |
| 202 |
|
const struct vjsn *vj; |
| 203 |
|
const struct vjsn_val *vv, *vv1, *vv2; |
| 204 |
|
vcc_kind_t kind; |
| 205 |
|
|
| 206 |
82200 |
if (sym->kind == SYM_VMOD) { |
| 207 |
23320 |
CAST_OBJ_NOTNULL(vj, sym->eval_priv, VJSN_MAGIC); |
| 208 |
23320 |
vv = VTAILQ_FIRST(&vj->value->children); |
| 209 |
82200 |
} else if (sym->kind == SYM_OBJECT) { |
| 210 |
58880 |
CAST_OBJ_NOTNULL(vv, sym->eval_priv, VJSN_VAL_MAGIC); |
| 211 |
58880 |
} else { |
| 212 |
0 |
WRONG("symbol kind"); |
| 213 |
|
} |
| 214 |
|
|
| 215 |
1408000 |
for (; vv != NULL; vv = VTAILQ_NEXT(vv, list)) { |
| 216 |
1325840 |
if (!vjsn_is_array(vv)) |
| 217 |
176640 |
continue; |
| 218 |
1149200 |
vv1 = VTAILQ_FIRST(&vv->children); |
| 219 |
1149200 |
AN(vv1); |
| 220 |
1149200 |
assert(vjsn_is_string(vv1)); |
| 221 |
1149200 |
vv2 = VTAILQ_NEXT(vv1, list); |
| 222 |
1149200 |
AN(vv2); |
| 223 |
1149200 |
if (!vjsn_is_string(vv2)) |
| 224 |
202480 |
continue; |
| 225 |
|
|
| 226 |
946720 |
kind = SYM_NONE; |
| 227 |
|
#define STANZA(UU, ll, ss) if (!strcmp(vv1->value, "$" #UU)) kind = ss; |
| 228 |
946720 |
STANZA_TBL |
| 229 |
|
#undef STANZA |
| 230 |
946720 |
if (kind != SYM_NONE) { |
| 231 |
895000 |
func_sym(tl, kind, sym, vv2, vv); |
| 232 |
895000 |
ERRCHK(tl); |
| 233 |
894960 |
} |
| 234 |
946680 |
} |
| 235 |
82200 |
} |
| 236 |
|
|
| 237 |
|
void v_matchproto_(sym_act_f) |
| 238 |
8280 |
vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym) |
| 239 |
|
{ |
| 240 |
|
struct symbol *isym, *osym; |
| 241 |
|
struct inifin *ifp; |
| 242 |
|
struct vsb *buf; |
| 243 |
|
const struct vjsn_val *vv, *vf; |
| 244 |
8280 |
int null_ok = 0; |
| 245 |
|
|
| 246 |
8280 |
(void)sym; |
| 247 |
8280 |
(void)t; |
| 248 |
|
|
| 249 |
8280 |
ExpectErr(tl, ID); |
| 250 |
8280 |
vcc_ExpectVid(tl, "VCL object"); |
| 251 |
8280 |
ERRCHK(tl); |
| 252 |
8240 |
isym = VCC_HandleSymbol(tl, INSTANCE); |
| 253 |
8240 |
ERRCHK(tl); |
| 254 |
8160 |
AN(isym); |
| 255 |
8160 |
isym->noref = 1; |
| 256 |
8160 |
isym->action = vcc_Act_Obj; |
| 257 |
|
|
| 258 |
8160 |
SkipToken(tl, '='); |
| 259 |
8160 |
ExpectErr(tl, ID); |
| 260 |
8160 |
osym = VCC_SymbolGet(tl, SYM_MAIN, SYM_OBJECT, SYMTAB_EXISTING, |
| 261 |
|
XREF_NONE); |
| 262 |
8160 |
ERRCHK(tl); |
| 263 |
8040 |
AN(osym); |
| 264 |
|
|
| 265 |
|
/* Scratch the generic INSTANCE type */ |
| 266 |
8040 |
isym->type = osym->type; |
| 267 |
|
|
| 268 |
8040 |
CAST_OBJ_NOTNULL(vv, osym->eval_priv, VJSN_VAL_MAGIC); |
| 269 |
|
// vv = object name |
| 270 |
|
|
| 271 |
8040 |
isym->vmod_name = osym->vmod_name; |
| 272 |
8040 |
isym->eval_priv = vv; |
| 273 |
|
|
| 274 |
8040 |
vv = VTAILQ_NEXT(vv, list); |
| 275 |
|
// vv = flags |
| 276 |
8040 |
assert(vjsn_is_object(vv)); |
| 277 |
16080 |
VTAILQ_FOREACH(vf, &vv->children, list) |
| 278 |
8200 |
if (!strcmp(vf->name, "NULL_OK") && vjsn_is_true(vf)) |
| 279 |
160 |
null_ok = 1; |
| 280 |
8040 |
if (!null_ok) |
| 281 |
7880 |
VTAILQ_INSERT_TAIL(&tl->sym_objects, isym, sideways); |
| 282 |
|
|
| 283 |
8040 |
vv = VTAILQ_NEXT(vv, list); |
| 284 |
|
// vv = struct name |
| 285 |
|
|
| 286 |
8040 |
Fh(tl, 0, "static %s *%s;\n\n", vv->value, isym->rname); |
| 287 |
8040 |
vv = VTAILQ_NEXT(vv, list); |
| 288 |
|
|
| 289 |
8040 |
vf = VTAILQ_FIRST(&vv->children); |
| 290 |
8040 |
vv = VTAILQ_NEXT(vv, list); |
| 291 |
8040 |
assert(vjsn_is_string(vf)); |
| 292 |
8040 |
assert(!strcmp(vf->value, "$INIT")); |
| 293 |
|
|
| 294 |
8040 |
vf = VTAILQ_NEXT(vf, list); |
| 295 |
|
|
| 296 |
8040 |
buf = VSB_new_auto(); |
| 297 |
8040 |
AN(buf); |
| 298 |
8040 |
VSB_printf(buf, "&%s, \"%s\"", isym->rname, isym->name); |
| 299 |
8040 |
AZ(VSB_finish(buf)); |
| 300 |
8040 |
vcc_Eval_Func(tl, vf, VSB_data(buf), osym); |
| 301 |
8040 |
VSB_destroy(&buf); |
| 302 |
8040 |
ERRCHK(tl); |
| 303 |
8040 |
SkipToken(tl, ';'); |
| 304 |
8040 |
isym->def_e = tl->t; |
| 305 |
|
|
| 306 |
8040 |
vf = VTAILQ_FIRST(&vv->children); |
| 307 |
8040 |
assert(vjsn_is_string(vf)); |
| 308 |
8040 |
assert(!strcmp(vf->value, "$FINI")); |
| 309 |
|
|
| 310 |
8040 |
vf = VTAILQ_NEXT(vf, list); |
| 311 |
8040 |
vf = VTAILQ_FIRST(&vf->children); |
| 312 |
8040 |
vf = VTAILQ_NEXT(vf, list); |
| 313 |
8040 |
ifp = New_IniFin(tl); |
| 314 |
8040 |
VSB_printf(ifp->fin, "\t\tif (%s)\n", isym->rname); |
| 315 |
8040 |
VSB_printf(ifp->fin, "\t\t\t\t%s(&%s);", vf->value, isym->rname); |
| 316 |
8280 |
} |