varnish-cache/lib/libvcc/vcc_types.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2011 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 769750
 *
9 760750
 * Redistribution and use in source and binary forms, with or without
10 731275
 * modification, are permitted provided that the following conditions
11 691775
 * are met:
12 691775
 * 1. Redistributions of source code must retain the above copyright
13 628725
 *    notice, this list of conditions and the following disclaimer.
14 615775
 * 2. Redistributions in binary form must reproduce the above copyright
15 594125
 *    notice, this list of conditions and the following disclaimer in the
16 547250
 *    documentation and/or other materials provided with the distribution.
17 546800
 *
18 546300
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 546300
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 489250
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 475075
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22 474475
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 444300
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 441025
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 439050
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 419675
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 282950
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 282950
 * SUCH DAMAGE.
29 276700
 *
30 257650
 */
31 257650
32
#include "config.h"
33
34
#include <string.h>
35
36
#include "vcc_compile.h"
37
38
/*
39
 * A type attribute is information already existing, requiring no processing
40
 * or resource usage.
41
 *
42
 * A type method is a call and may do significant processing, change things,
43
 * eat workspace etc.
44
 *
45
 * XXX: type methods might move in a more comprehensive direction.
46
 */
47
struct vcc_method {
48
        unsigned                magic;
49
#define VCC_METHOD_MAGIC        0x594108cd
50
        vcc_type_t              type;
51
        const char              *name;
52
        const char              *impl;
53
        int                     func;
54
};
55
56
const struct type ACL[1] = {{
57
        .magic =                TYPE_MAGIC,
58
        .name =                 "ACL",
59
        .global_pfx =           "vrt_acl",
60
        .tostring =             "((\v1)->name)",
61
}};
62
63
static const struct vcc_method backend_methods[] = {
64
        { VCC_METHOD_MAGIC, BACKEND, "resolve",
65
            "VRT_DirectorResolve(ctx, \v1)", 1 },
66
        { VCC_METHOD_MAGIC, NULL },
67
};
68
69
const struct type BACKEND[1] = {{
70
        .magic =                TYPE_MAGIC,
71
        .name =                 "BACKEND",
72
        .methods =              backend_methods,
73
        .global_pfx =           "vgc_backend",
74
        .tostring =             "VRT_BACKEND_string(\v1)",
75
}};
76
77
const struct type BLOB[1] = {{
78
        .magic =                TYPE_MAGIC,
79
        .name =                 "BLOB",
80
        .bodyform =             1,
81
        .tostring =             "VRT_BLOB_string(ctx, \v1)",
82
}};
83
84
const struct type BODY[1] = {{
85
        .magic =                TYPE_MAGIC,
86
        .name =                 "BODY",
87
        .noindent =             1,
88
}};
89
90
const struct type BOOL[1] = {{
91
        .magic =                TYPE_MAGIC,
92
        .name =                 "BOOL",
93
        .tostring =             "VRT_BOOL_string(\v1)",
94
}};
95
96
const struct type BYTES[1] = {{
97
        .magic =                TYPE_MAGIC,
98
        .name =                 "BYTES",
99
        .tostring =             "VRT_INT_string(ctx, \v1)",
100
        .multype =              REAL,   // XXX: wrong
101
}};
102
103
const struct type DURATION[1] = {{
104
        .magic =                TYPE_MAGIC,
105
        .name =                 "DURATION",
106
        .tostring =             "VRT_REAL_string(ctx, \v1)", // XXX 's' suff?
107
        .multype =              REAL,
108
}};
109
110
const struct type ENUM[1] = {{
111
        .magic =                TYPE_MAGIC,
112
        .name =                 "ENUM",
113
        .tostring =             "",
114
}};
115
116
const struct type HEADER[1] = {{
117
        .magic =                TYPE_MAGIC,
118
        .name =                 "HEADER",
119
        .tostring =             "VRT_GetHdr(ctx, \v1)",
120
}};
121
122
const struct type HTTP[1] = {{
123
        .magic =                TYPE_MAGIC,
124
        .name =                 "HTTP",
125
}};
126
127
const struct type INSTANCE[1] = {{
128
        .magic =                TYPE_MAGIC,
129
        .name =                 "INSTANCE",
130
        .global_pfx =           "vo",
131
}};
132
133
const struct type INT[1] = {{
134
        .magic =                TYPE_MAGIC,
135
        .name =                 "INT",
136
        .multype =              INT,
137
        .tostring =             "VRT_INT_string(ctx, \v1)",
138
}};
139
140
const struct type IP[1] = {{
141
        .magic =                TYPE_MAGIC,
142
        .name =                 "IP",
143
        .tostring =             "VRT_IP_string(ctx, \v1)",
144
}};
145
146
const struct type PROBE[1] = {{
147
        .magic =                TYPE_MAGIC,
148
        .name =                 "PROBE",
149
        .global_pfx =           "vgc_probe",
150
}};
151
152
const struct type REAL[1] = {{
153
        .magic =                TYPE_MAGIC,
154
        .name =                 "REAL",
155
        .tostring =             "VRT_REAL_string(ctx, \v1)",
156
        .multype =              REAL,
157
}};
158
159
const struct type REGEX[1] = {{
160
        .magic =                TYPE_MAGIC,
161
        .name =                 "REGEX",
162
}};
163
164
static const struct vcc_method stevedore_methods[] = {
165
#define VRTSTVVAR(nm, vtype, ctype, dval) \
166
        { VCC_METHOD_MAGIC, vtype, #nm, "VRT_stevedore_" #nm "(\v1)", 0},
167
#include "tbl/vrt_stv_var.h"
168
        { VCC_METHOD_MAGIC, NULL },
169
};
170
171
const struct type STEVEDORE[1] = {{
172
        .magic =                TYPE_MAGIC,
173
        .name =                 "STEVEDORE",
174
        .methods =              stevedore_methods,
175
        .tostring =             "VRT_STEVEDORE_string(\v1)",
176
}};
177
178
const struct type STRING[1] = {{
179
        .magic =                TYPE_MAGIC,
180
        .name =                 "STRING",
181
        .stringform =           1,
182
}};
183
184
const struct type STRANDS[1] = {{
185
        .magic =                TYPE_MAGIC,
186
        .name =                 "STRANDS",
187
        .stringform =           1,
188
        .tostring =             "VRT_STRANDS_string(ctx,\v+\n\v1\v-\n)",
189
}};
190
191
static const struct vcc_method strings_methods[] = {
192
        { VCC_METHOD_MAGIC, STRING, "upper",
193
            "VRT_UpperLowerStrands(ctx, \vT, 1)", 1 },
194
        { VCC_METHOD_MAGIC, STRING, "lower",
195
            "VRT_UpperLowerStrands(ctx, \vT, 0)", 1 },
196
        { VCC_METHOD_MAGIC, NULL },
197
};
198
199
const struct type STRINGS[1] = {{
200
        .magic =                TYPE_MAGIC,
201
        .name =                 "STRINGS",
202
        .methods =              strings_methods,
203
        .bodyform =             1,
204
        .tostring =             "",
205
}};
206
207
const struct type SUB[1] = {{
208
        .magic =                TYPE_MAGIC,
209
        .name =                 "SUB",
210
        .global_pfx =           "VGC_function",
211
}};
212
213
const struct type TIME[1] = {{
214
        .magic =                TYPE_MAGIC,
215
        .name =                 "TIME",
216
        .tostring =             "VRT_TIME_string(ctx, \v1)",
217
}};
218
219
const struct type VCL[1] = {{
220
        .magic =                TYPE_MAGIC,
221
        .name =                 "VCL",
222
}};
223
224
const struct type VOID[1] = {{
225
        .magic =                TYPE_MAGIC,
226
        .name =                 "VOID",
227
}};
228
229
vcc_type_t
230 696775
VCC_Type(const char *p)
231
{
232
233
#define VCC_TYPE(UC, lc)        if (!strcmp(p, #UC)) return (UC);
234
#include "vcc_types.h"
235 0
        return (NULL);
236 696775
}
237
238
static void
239 1751400
vcc_type_init(struct vcc *tl, vcc_type_t type)
240
{
241
        const struct vcc_method *vm;
242
        struct symbol *sym;
243
        struct vsb *buf;
244
245
        /* NB: Don't bother even creating a type symbol if there are no
246
         * methods attached to it.
247
         */
248 1751400
        if (type->methods == NULL)
249 1532475
                return;
250
251 218925
        buf = VSB_new_auto();
252 218925
        AN(buf);
253 218925
        AN(VCC_MkSym(tl, type->name, SYM_TYPE, SYM_NONE, VCL_LOW, VCL_HIGH));
254
255 656775
        for (vm = type->methods; vm->type != NULL; vm++) {
256 437850
                VSB_printf(buf, "%s.%s", type->name, vm->name);
257 437850
                AZ(VSB_finish(buf));
258 437850
                sym = VCC_MkSym(tl, VSB_data(buf), SYM_TYPE, SYM_METHOD,
259
                    VCL_LOW, VCL_HIGH);
260 437850
                VSB_clear(buf);
261 437850
                if (tl->err)
262 0
                        break;
263 437850
                AN(sym);
264 437850
                sym->type = vm->type;
265 437850
                sym->eval = vcc_Eval_TypeMethod;
266 437850
                sym->eval_priv = vm;
267 437850
        }
268
269 218925
        VSB_destroy(&buf);
270 1751400
}
271
272
const char *
273 67725
VCC_Type_EvalMethod(struct vcc *tl, const struct symbol *sym)
274
{
275
        const struct vcc_method *vm;
276
277 67725
        AN(sym);
278 67725
        AN(sym->kind == SYM_METHOD);
279 67725
        CAST_OBJ_NOTNULL(vm, sym->eval_priv, VCC_METHOD_MAGIC);
280
281 67725
        vcc_NextToken(tl);
282 67725
        if (vm->func) {
283 67500
                Expect(tl, '(');
284 67500
                if (tl->err)
285 0
                        return (NULL);
286 67500
                vcc_NextToken(tl);
287 67500
                Expect(tl, ')');
288 67500
                if (tl->err)
289 0
                        return (NULL);
290 67500
                vcc_NextToken(tl);
291 67500
        }
292
293 67725
        return (vm->impl);
294 67725
}
295
296
void
297 72975
vcc_Type_Init(struct vcc *tl)
298
{
299
300
#define VCC_TYPE(UC, lc)        vcc_type_init(tl, UC);
301
#include "vcc_types.h"
302 72975
}