varnish-cache/lib/libvcc/vcc_expr.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2011 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * 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
 */
30
31
#include "config.h"
32
33
#include <math.h>
34
#include <stdarg.h>
35
#include <stdlib.h>
36
#include <string.h>
37
38
#include "vcc_compile.h"
39
#include "vjsn.h"
40
41
struct expr {
42
        unsigned        magic;
43
#define EXPR_MAGIC      0x38c794ab
44
        vcc_type_t      fmt;
45
        struct vsb      *vsb;
46
        uint8_t         constant;
47
#define EXPR_VAR        (1<<0)
48
#define EXPR_CONST      (1<<1)
49
#define EXPR_STR_CONST  (1<<2)          // Last STRING_LIST elem is "..."
50
        struct token    *t1, *t2;
51
        int             nstr;
52
};
53
54
/*--------------------------------------------------------------------
55
 * Facility for carrying expressions around and do text-processing on
56
 * them.
57
 */
58
59
static inline int
60 1868
vcc_isconst(const struct expr *e)
61
{
62 1868
        AN(e->constant);
63 1868
        return (e->constant & EXPR_CONST);
64
}
65
66
static inline int
67 21859
vcc_islit(const struct expr *e)
68
{
69 21859
        AN(e->constant);
70 21859
        return (e->constant & EXPR_STR_CONST);
71
}
72
73
static const char *
74 52
vcc_utype(vcc_type_t t)
75
{
76 52
        if (t == STRINGS || t == STRING_LIST)
77 17
                t = STRING;
78 52
        return (t->name);
79
}
80
81
static void vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt);
82
static void vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt);
83
84
static struct expr *
85 193288
vcc_new_expr(vcc_type_t fmt)
86
{
87
        struct expr *e;
88
89 193288
        ALLOC_OBJ(e, EXPR_MAGIC);
90 193288
        AN(e);
91 193288
        e->vsb = VSB_new_auto();
92 193288
        e->fmt = fmt;
93 193288
        e->constant = EXPR_VAR;
94 193288
        return (e);
95
}
96
97
static struct expr * v_printflike_(2, 3)
98 53555
vcc_mk_expr(vcc_type_t fmt, const char *str, ...)
99
{
100
        va_list ap;
101
        struct expr *e;
102
103 53555
        e = vcc_new_expr(fmt);
104 53555
        va_start(ap, str);
105 53555
        VSB_vprintf(e->vsb, str, ap);
106 53555
        va_end(ap);
107 53555
        AZ(VSB_finish(e->vsb));
108 53555
        return (e);
109
}
110
111
static void
112 246030
vcc_delete_expr(struct expr *e)
113
{
114 246030
        if (e == NULL)
115 52808
                return;
116 193222
        CHECK_OBJ_NOTNULL(e, EXPR_MAGIC);
117 193222
        VSB_destroy(&e->vsb);
118 193222
        FREE_OBJ(e);
119
}
120
121
/*--------------------------------------------------------------------
122
 * We want to get the indentation right in the emitted C code so we have
123
 * to represent it symbolically until we are ready to render.
124
 *
125
 * Many of the operations have very schematic output syntaxes, so we
126
 * use the same facility to simplify the text-processing of emitting
127
 * a given operation on two subexpressions.
128
 *
129
 * We use '\v' as the magic escape character.
130
 *      \v1  insert subexpression 1
131
 *      \v2  insert subexpression 2
132
 *      \vS  insert subexpression 1(STRINGS) as STRING
133
 *      \vT  insert subexpression 1(STRINGS) as STRANDS
134
 *      \vt  insert subexpression 1(STRINGS) as STRANDS
135
 *      \v+  increase indentation
136
 *      \v-  decrease indentation
137
 *      anything else is literal
138
 *
139
 * When editing, we check if any of the subexpressions contain a newline
140
 * and issue it as an indented block of so.
141
 *
142
 * XXX: check line lengths in edit, should pass indent in for this
143
 */
144
145
static struct expr *
146 109781
vcc_expr_edit(struct vcc *tl, vcc_type_t fmt, const char *p, struct expr *e1,
147
    struct expr *e2)
148
{
149
        struct expr *e, *e3;
150 109781
        int nl = 1;
151
152 109781
        AN(e1);
153 109781
        e = vcc_new_expr(fmt);
154 1498175
        while (*p != '\0') {
155 1278613
                if (*p != '\v') {
156 1050259
                        if (*p != '\n' || !nl)
157 1018492
                                VSB_putc(e->vsb, *p);
158 1050259
                        nl = (*p == '\n');
159 1050259
                        p++;
160 1050259
                        continue;
161
                }
162 228354
                assert(*p == '\v');
163 228354
                switch (*++p) {
164 29818
                case '+': VSB_cat(e->vsb, "\v+"); break;
165 31780
                case '-': VSB_cat(e->vsb, "\v-"); break;
166
                case 'S':
167
                case 's':
168 9338
                        e3 = (*p == 'S' ? e1 : e2);
169 9338
                        AN(e3);
170 9338
                        assert(e1->fmt == STRINGS);
171 9338
                        if (e3->nstr > 1)
172 9
                                VSB_cat(e->vsb,
173
                                    "\nVRT_CollectString(ctx,\v+\n");
174 9338
                        VSB_cat(e->vsb, VSB_data(e3->vsb));
175 9338
                        if (e3->nstr > 1)
176 9
                                VSB_cat(e->vsb,
177
                                    ",\nvrt_magic_string_end)\v-\n");
178 9338
                        break;
179
                case 'T':
180
                case 't':
181 38
                        e3 = (*p == 'T' ? e1 : e2);
182 38
                        AN(e3);
183 38
                        VSB_printf(tl->curproc->prologue,
184
                            "  struct strands strs_%u_a;\n"
185
                            "  const char * strs_%u_s[%d];\n",
186
                            tl->unique, tl->unique, e3->nstr);
187 38
                        VSB_printf(e->vsb,
188
                            "\v+\nVRT_BundleStrands(%d, &strs_%u_a, strs_%u_s,"
189
                            "\v+\n%s,\nvrt_magic_string_end)\v-\v-",
190
                            e3->nstr, tl->unique, tl->unique,
191 38
                        VSB_data(e3->vsb));
192 38
                        tl->unique++;
193 38
                        break;
194
                case '1':
195 100424
                        VSB_cat(e->vsb, VSB_data(e1->vsb));
196 100424
                        break;
197
                case '2':
198 56956
                        AN(e2);
199 56956
                        VSB_cat(e->vsb, VSB_data(e2->vsb));
200 56956
                        break;
201
                default:
202 0
                        WRONG("Illegal edit in VCC expression");
203
                }
204 228354
                p++;
205
        }
206 109781
        AZ(VSB_finish(e->vsb));
207 109781
        e->t1 = e1->t1;
208 109781
        e->t2 = e1->t2;
209 109781
        if (e2 != NULL)
210 56975
                e->t2 = e2->t2;
211 109781
        vcc_delete_expr(e1);
212 109781
        vcc_delete_expr(e2);
213 109781
        return (e);
214
}
215
216
/*--------------------------------------------------------------------
217
 * Expand finished expression into C-source code
218
 */
219
220
static void
221 26466
vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1)
222
{
223
        char *p;
224
        int i;
225
226 255716
        for (i = 0; i < ind; i++)
227 229250
                VSB_cat(d, " ");
228 26466
        p = VSB_data(e1->vsb);
229 2873611
        while (*p != '\0') {
230 2820682
                if (*p == '\n') {
231 81843
                        VSB_putc(d, '\n');
232 81843
                        if (*++p == '\0')
233 3
                                break;
234 919722
                        for (i = 0; i < ind; i++)
235 837882
                                VSB_cat(d, " ");
236 2738839
                } else if (*p != '\v') {
237 2675125
                        VSB_putc(d, *p++);
238
                } else {
239 63714
                        switch (*++p) {
240 31857
                        case '+': ind += 2; break;
241 31857
                        case '-': ind -= 2; break;
242 0
                        default:  WRONG("Illegal format in VCC expression");
243
                        }
244 63714
                        p++;
245
                }
246
        }
247 26466
}
248
249
/*--------------------------------------------------------------------
250
 */
251
252
static void
253 33067
vcc_expr_tobool(struct vcc *tl, struct expr **e)
254
{
255
256 33067
        if ((*e)->fmt == BOOL)
257 27657
                return;
258 5410
        if ((*e)->fmt == BACKEND || (*e)->fmt == INT)
259 9
                *e = vcc_expr_edit(tl, BOOL, "(\v1 != 0)", *e, NULL);
260 5401
        else if ((*e)->fmt == DURATION)
261 2
                *e = vcc_expr_edit(tl, BOOL, "(\v1 > 0)", *e, NULL);
262 5399
        else if ((*e)->fmt == STRINGS)
263 5394
                *e = vcc_expr_edit(tl, BOOL, "(\vS != 0)", *e, NULL);
264
        /*
265
         * We do not provide automatic folding from REAL to BOOL
266
         * because comparing to zero is seldom an exact science
267
         * and we want to force people to explicitly get it right.
268
         */
269
}
270
271
/*--------------------------------------------------------------------
272
 */
273
274
static void
275 14491
vcc_expr_tostring(struct vcc *tl, struct expr **e, vcc_type_t fmt)
276
{
277
        const char *p;
278 14491
        uint8_t constant = EXPR_VAR;
279
280 14491
        CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC);
281 14491
        assert(fmt == STRINGS || fmt == STRING_LIST || fmt == STRING);
282 14491
        assert(fmt != (*e)->fmt);
283
284 14491
        p = (*e)->fmt->tostring;
285 14491
        if (p != NULL) {
286 14490
                AN(*p);
287 14490
                *e = vcc_expr_edit(tl, fmt, p, *e, NULL);
288 14490
                (*e)->constant = constant;
289 14490
                (*e)->nstr = 1;
290
        } else {
291 1
                if ((*e)->fmt == BLOB)
292 1
                        VSB_printf(tl->sb,
293
                            "Wrong use of BLOB value.\n"
294
                            "BLOBs can only be used as arguments to VMOD"
295
                            " functions.\n");
296
                else
297 0
                        VSB_printf(tl->sb,
298
                            "Cannot convert %s to STRING.\n",
299 0
                            vcc_utype((*e)->fmt));
300 1
                vcc_ErrWhere2(tl, (*e)->t1, tl->t);
301
        }
302 14491
}
303
304
/*--------------------------------------------------------------------
305
 */
306
307
static void v_matchproto_(sym_expr_t)
308 32
vcc_Eval_Regsub(struct vcc *tl, struct expr **e, struct token *t,
309
    struct symbol *sym, vcc_type_t fmt)
310
{
311
        struct expr *e2;
312 32
        int all = sym->eval_priv == NULL ? 0 : 1;
313
        char buf[128];
314
        struct vsb vsb;
315
316
        (void)t;
317
        (void)fmt;
318 32
        SkipToken(tl, '(');
319 32
        vcc_expr0(tl, &e2, STRING);
320 32
        ERRCHK(tl);
321 32
        SkipToken(tl, ',');
322 32
        ExpectErr(tl, CSTR);
323
324 32
        AN(VSB_new(&vsb, buf, sizeof buf, VSB_FIXEDLEN));
325 32
        VSB_printf(&vsb, "VRT_regsub(ctx, %d,\v+\n\v1,\n", all);
326 32
        vcc_regexp(tl, &vsb);
327 32
        ERRCHK(tl);
328 32
        AZ(VSB_finish(&vsb));
329 32
        *e = vcc_expr_edit(tl, STRING, VSB_data(&vsb), e2, NULL);
330 32
        SkipToken(tl, ',');
331 32
        vcc_expr0(tl, &e2, STRING);
332 32
        ERRCHK(tl);
333 32
        *e = vcc_expr_edit(tl, STRINGS, "\v1,\n\v2)\v-", *e, e2);
334 32
        (*e)->nstr = 1;
335 32
        SkipToken(tl, ')');
336
}
337
338
/*--------------------------------------------------------------------
339
 */
340
341
static void v_matchproto_(sym_expr_t)
342 1092
vcc_Eval_BoolConst(struct vcc *tl, struct expr **e, struct token *t,
343
    struct symbol *sym, vcc_type_t fmt)
344
{
345
346
        (void)t;
347
        (void)tl;
348
        (void)fmt;
349 1092
        *e = vcc_mk_expr(BOOL, "(0==%d)", sym->eval_priv == NULL ? 1 : 0);
350 1092
        (*e)->constant = EXPR_CONST;
351 1092
}
352
353
/*--------------------------------------------------------------------
354
 */
355
356
void v_matchproto_(sym_expr_t)
357 207
vcc_Eval_Handle(struct vcc *tl, struct expr **e, struct token *t,
358
    struct symbol *sym, vcc_type_t type)
359
{
360
361
        (void)t;
362
        (void)tl;
363 207
        AN(sym->rname);
364
365 207
        if (sym->type != STRING && type == STRINGS) {
366 2
                *e = vcc_mk_expr(STRINGS, "\"%s\"", sym->name);
367 2
                (*e)->nstr = 1;
368 2
                (*e)->constant |= EXPR_CONST | EXPR_STR_CONST;
369
        } else {
370 205
                *e = vcc_mk_expr(sym->type, "%s", sym->rname);
371 205
                (*e)->constant = EXPR_VAR;
372 205
                (*e)->nstr = 1;
373 205
                if ((*e)->fmt == STRING)
374 0
                        (*e)->fmt = STRINGS;
375
        }
376 207
}
377
378
/*--------------------------------------------------------------------
379
 */
380
381
void v_matchproto_(sym_expr_t)
382 39921
vcc_Eval_Var(struct vcc *tl, struct expr **e, struct token *t,
383
    struct symbol *sym, vcc_type_t type)
384
{
385
386
        (void)type;
387 39921
        assert(sym->kind == SYM_VAR);
388 39921
        vcc_AddUses(tl, t, NULL, sym->r_methods, "Not available");
389 39921
        ERRCHK(tl);
390 39921
        *e = vcc_mk_expr(sym->type, "%s", sym->rname);
391 39921
        (*e)->constant = EXPR_VAR;
392 39921
        (*e)->nstr = 1;
393 39921
        if ((*e)->fmt == STRING)
394 20086
                (*e)->fmt = STRINGS;
395
}
396
397
/*--------------------------------------------------------------------
398
 */
399
400
static struct expr *
401 188
vcc_priv_arg(struct vcc *tl, const char *p, const char *name, const char *vmod)
402
{
403
        struct expr *e2;
404
        char buf[32];
405
        struct inifin *ifp;
406
407
        (void)name;
408 188
        if (!strcmp(p, "PRIV_VCL")) {
409 3
                e2 = vcc_mk_expr(VOID, "&vmod_priv_%s", vmod);
410 185
        } else if (!strcmp(p, "PRIV_CALL")) {
411 13
                bprintf(buf, "vmod_priv_%u", tl->unique++);
412 13
                ifp = New_IniFin(tl);
413 13
                Fh(tl, 0, "static struct vmod_priv %s;\n", buf);
414 13
                VSB_printf(ifp->fin, "\tVRT_priv_fini(&%s);", buf);
415 13
                e2 = vcc_mk_expr(VOID, "&%s", buf);
416 172
        } else if (!strcmp(p, "PRIV_TASK")) {
417 168
                e2 = vcc_mk_expr(VOID,
418
                    "VRT_priv_task(ctx, &VGC_vmod_%s)", vmod);
419 4
        } else if (!strcmp(p, "PRIV_TOP")) {
420 4
                e2 = vcc_mk_expr(VOID,
421
                    "VRT_priv_top(ctx, &VGC_vmod_%s)", vmod);
422
        } else {
423 0
                WRONG("Wrong PRIV_ type");
424
        }
425 188
        return (e2);
426
}
427
428
struct func_arg {
429
        vcc_type_t              type;
430
        const struct vjsn_val   *enums;
431
        const char              *cname;
432
        const char              *name;
433
        const char              *val;
434
        struct expr             *result;
435
        int                     avail;
436
        int                     optional;
437
        VTAILQ_ENTRY(func_arg)  list;
438
};
439
440
static void
441 1712
vcc_do_enum(struct vcc *tl, struct func_arg *fa, int len, const char *ptr)
442
{
443
        const char *r;
444
445
        (void)tl;
446 1712
        r = strchr(fa->cname, '.');
447 1712
        AN(r);
448 3424
        fa->result = vcc_mk_expr(VOID, "*%.*s.enum_%.*s",
449 1712
            (int)(r - fa->cname), fa->cname, len, ptr);
450 1712
}
451
452
static void
453 3109
vcc_do_arg(struct vcc *tl, struct func_arg *fa)
454
{
455
        struct expr *e2;
456
        struct vjsn_val *vv;
457
458 3109
        if (fa->type == ENUM) {
459 1270
                ExpectErr(tl, ID);
460 1262
                ERRCHK(tl);
461 3949
                VTAILQ_FOREACH(vv, &fa->enums->children, list)
462 3947
                        if (vcc_IdIs(tl->t, vv->value))
463 1260
                                break;
464 1262
                if (vv == NULL) {
465 2
                        VSB_printf(tl->sb, "Wrong enum value.");
466 2
                        VSB_printf(tl->sb, "  Expected one of:\n");
467 10
                        VTAILQ_FOREACH(vv, &fa->enums->children, list)
468 8
                                VSB_printf(tl->sb, "\t%s\n", vv->value);
469 2
                        vcc_ErrWhere(tl, tl->t);
470 2
                        return;
471
                }
472 1260
                vcc_do_enum(tl, fa, PF(tl->t));
473 1260
                SkipToken(tl, ID);
474
        } else {
475 1847
                vcc_expr0(tl, &e2, fa->type);
476 1847
                ERRCHK(tl);
477 1841
                assert(e2->fmt == fa->type);
478 1841
                fa->result = e2;
479
        }
480 3101
        fa->avail = 1;
481
}
482
483
static void
484 1974
vcc_func(struct vcc *tl, struct expr **e, const void *priv,
485
    const char *extra, const struct symbol *sym)
486
{
487
        vcc_type_t rfmt;
488
        const char *cfunc;
489
        struct expr *e1;
490
        struct func_arg *fa, *fa2;
491
        VTAILQ_HEAD(,func_arg) head;
492
        struct token *t1;
493
        const struct vjsn_val *vv, *vvp;
494
        const char *sa;
495
        char ssa[64];
496
        int n;
497
498 1974
        CAST_OBJ_NOTNULL(vv, priv, VJSN_VAL_MAGIC);
499 1974
        assert(vv->type == VJSN_ARRAY);
500 1974
        vv = VTAILQ_FIRST(&vv->children);
501 1974
        rfmt = VCC_Type(VTAILQ_FIRST(&vv->children)->value);
502 1974
        AN(rfmt);
503 1974
        vv = VTAILQ_NEXT(vv, list);
504 1974
        cfunc = vv->value;
505 1974
        vv = VTAILQ_NEXT(vv, list);
506 1974
        sa = vv->value;
507 1974
        if (*sa == '\0') {
508 1816
                sa = NULL;
509
        }
510 1974
        vv = VTAILQ_NEXT(vv, list);
511 1985
        SkipToken(tl, '(');
512 1974
        if (extra == NULL)
513 1195
                extra = "";
514 1974
        VTAILQ_INIT(&head);
515 6554
        for (;vv != NULL; vv = VTAILQ_NEXT(vv, list)) {
516 4580
                assert(vv->type == VJSN_ARRAY);
517 4580
                fa = calloc(1, sizeof *fa);
518 4580
                AN(fa);
519 4580
                fa->cname = cfunc;
520 4580
                VTAILQ_INSERT_TAIL(&head, fa, list);
521
522 4580
                vvp = VTAILQ_FIRST(&vv->children);
523 4580
                if (!memcmp(vvp->value, "PRIV_", 5)) {
524 376
                        fa->result = vcc_priv_arg(tl, vvp->value,
525 188
                            sym->name, sym->vmod);
526 188
                        fa->name = "";
527 188
                        continue;
528
                }
529 4392
                fa->type = VCC_Type(vvp->value);
530 4392
                AN(fa->type);
531 4392
                vvp = VTAILQ_NEXT(vvp, list);
532 4392
                if (vvp != NULL) {
533 4160
                        fa->name = vvp->value;
534 4160
                        vvp = VTAILQ_NEXT(vvp, list);
535 4160
                        if (vvp != NULL) {
536 2883
                                fa->val = vvp->value;
537 2883
                                vvp = VTAILQ_NEXT(vvp, list);
538 2883
                                if (vvp != NULL) {
539 2273
                                        fa->enums = vvp;
540 2273
                                        vvp = VTAILQ_NEXT(vvp, list);
541
                                }
542
                        }
543
                }
544 4392
                if (sa != NULL && vvp != NULL && vvp->type == VJSN_TRUE) {
545 642
                        fa->optional = 1;
546 642
                        vvp = VTAILQ_NEXT(vvp, list);
547
                }
548 4392
                AZ(vvp);
549
        }
550
551 3475
        VTAILQ_FOREACH(fa, &head, list) {
552 3134
                if (tl->t->tok == ')')
553 48
                        break;
554 3086
                if (fa->result != NULL)
555 158
                        continue;
556 2928
                if (tl->t->tok == ID) {
557 2314
                        t1 = VTAILQ_NEXT(tl->t, list);
558 2314
                        if (t1->tok == '=')
559 685
                                break;
560
                }
561 2243
                vcc_do_arg(tl, fa);
562 2243
                ERRCHK(tl);
563 2236
                if (tl->t->tok == ')')
564 893
                        break;
565 1343
                SkipToken(tl, ',');
566
        }
567 4117
        while (tl->t->tok == ID) {
568 2790
                VTAILQ_FOREACH(fa, &head, list) {
569 2789
                        if (fa->name == NULL)
570 0
                                continue;
571 2789
                        if (vcc_IdIs(tl->t, fa->name))
572 867
                                break;
573
                }
574 868
                if (fa == NULL) {
575 2
                        VSB_printf(tl->sb, "Unknown argument '%.*s'\n",
576 2
                            PF(tl->t));
577 1
                        vcc_ErrWhere(tl, tl->t);
578 1
                        return;
579
                }
580 867
                if (fa->result != NULL) {
581 1
                        VSB_printf(tl->sb, "Argument '%s' already used\n",
582
                            fa->name);
583 1
                        vcc_ErrWhere(tl, tl->t);
584 1
                        return;
585
                }
586 866
                vcc_NextToken(tl);
587 866
                SkipToken(tl, '=');
588 866
                vcc_do_arg(tl, fa);
589 866
                ERRCHK(tl);
590 865
                if (tl->t->tok == ')')
591 682
                        break;
592 183
                SkipToken(tl, ',');
593
        }
594
595 1964
        if (sa != NULL)
596 156
                e1 = vcc_mk_expr(rfmt, "%s(ctx%s,\v+ &(%s){\n",
597
                                 cfunc, extra, sa);
598
        else
599 1808
                e1 = vcc_mk_expr(rfmt, "%s(ctx%s\v+", cfunc, extra);
600 1964
        n = 0;
601 6514
        VTAILQ_FOREACH_SAFE(fa, &head, list, fa2) {
602 4550
                n++;
603 4550
                if (fa->optional) {
604 640
                        bprintf(ssa, "\v1.valid_%s = %d,\n",
605
                                fa->name, fa->avail);
606 640
                        e1 = vcc_expr_edit(tl, e1->fmt, ssa, e1, NULL);
607
                }
608 4550
                if (fa->result == NULL && fa->type == ENUM && fa->val != NULL)
609 452
                        vcc_do_enum(tl, fa, strlen(fa->val), fa->val);
610 4550
                if (fa->result == NULL && fa->val != NULL)
611 420
                        fa->result = vcc_mk_expr(fa->type, "%s", fa->val);
612 4550
                if (fa->result != NULL && sa != NULL) {
613 458
                        if (fa->name && *fa->name != '\0')
614 368
                                bprintf(ssa, "\v1.%s = \v2,\n", fa->name);
615
                        else
616 90
                                bprintf(ssa, "\v1.arg%d = \v2,\n", n);
617 458
                        e1 = vcc_expr_edit(tl, e1->fmt, ssa, e1, fa->result);
618 4092
                } else if (fa->result != NULL) {
619 3698
                        e1 = vcc_expr_edit(tl, e1->fmt, "\v1,\n\v2",
620
                            e1, fa->result);
621 394
                } else if (!fa->optional) {
622 1
                        VSB_printf(tl->sb, "Argument '%s' missing\n",
623
                            fa->name);
624 1
                        vcc_ErrWhere(tl, tl->t);
625
                }
626 4550
                free(fa);
627
        }
628 1964
        if (sa != NULL) {
629 156
                *e = vcc_expr_edit(tl, e1->fmt, "\v1\n})\v-", e1, NULL);
630
        } else {
631 1808
                *e = vcc_expr_edit(tl, e1->fmt, "\v1\n)\v-", e1, NULL);
632
        }
633 1964
        SkipToken(tl, ')');
634
}
635
636
637
/*--------------------------------------------------------------------
638
 */
639
640
void
641 155
vcc_Eval_Func(struct vcc *tl, const struct vjsn_val *spec,
642
    const char *extra, const struct symbol *sym)
643
{
644 155
        struct expr *e = NULL;
645
646 155
        vcc_func(tl, &e, spec, extra, sym);
647 155
        ERRCHK(tl);
648 155
        vcc_expr_fmt(tl->fb, tl->indent, e);
649 155
        VSB_cat(tl->fb, ";\n");
650 155
        vcc_delete_expr(e);
651
}
652
653
/*--------------------------------------------------------------------
654
 */
655
656
void v_matchproto_(sym_expr_t)
657 1364
vcc_Eval_SymFunc(struct vcc *tl, struct expr **e, struct token *t,
658
    struct symbol *sym, vcc_type_t fmt)
659
{
660
661
        (void)t;
662
        (void)fmt;
663 1364
        assert(sym->kind == SYM_FUNC);
664 1364
        AN(sym->eval_priv);
665
666 1364
        vcc_func(tl, e, sym->eval_priv, sym->extra, sym);
667 1364
        ERRCHK(tl);
668 1355
        if ((*e)->fmt == STRING) {
669 656
                (*e)->fmt = STRINGS;
670 656
                (*e)->nstr = 1;
671
        }
672
}
673
674
/*--------------------------------------------------------------------
675
 * SYNTAX:
676
 *    Expr4:
677
 *      '(' ExprCor ')'
678
 *      symbol
679
 *      CNUM
680
 *      CSTR
681
 */
682
683
static void
684 81551
vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
685
{
686
        struct expr *e1, *e2;
687
        const char *ip, *sign;
688
        struct token *t;
689
        struct symbol *sym;
690
        double d;
691
        int i;
692
693 81551
        sign = "";
694 81551
        *e = NULL;
695 81551
        if (tl->t->tok == '(') {
696 82458
                SkipToken(tl, '(');
697 909
                vcc_expr_cor(tl, &e2, fmt);
698 909
                ERRCHK(tl);
699 909
                SkipToken(tl, ')');
700 909
                if (e2->fmt == STRINGS)
701 2
                        *e = e2;
702
                else
703 907
                        *e = vcc_expr_edit(tl, e2->fmt, "(\v1)", e2, NULL);
704 909
                return;
705
        }
706 80642
        switch (tl->t->tok) {
707
        case ID:
708 42633
                if (vcc_IdIs(tl->t, "default") && fmt == PROBE) {
709 0
                        vcc_NextToken(tl);
710 0
                        *e = vcc_mk_expr(PROBE, "%s", vcc_default_probe(tl));
711 0
                        return;
712
                }
713 42633
                if (vcc_IdIs(tl->t, "default") && fmt == BACKEND) {
714 2
                        vcc_NextToken(tl);
715 2
                        *e = vcc_mk_expr(BACKEND,
716
                            "*(VCL_conf.default_director)");
717 2
                        return;
718
                }
719 42631
                t = tl->t;
720 42631
                sym = VCC_SymbolGet(tl, SYM_NONE, "Symbol not found",
721
                    XREF_REF);
722 42631
                ERRCHK(tl);
723 42619
                AN(sym);
724 42619
                if (sym->kind == SYM_FUNC && sym->type == VOID) {
725 1
                        VSB_printf(tl->sb, "Function returns VOID:\n");
726 1
                        vcc_ErrWhere(tl, tl->t);
727 1
                        return;
728
                }
729 42618
                if (sym->eval != NULL) {
730 42616
                        AN(sym->eval);
731 42616
                        AZ(*e);
732 42616
                        sym->eval(tl, e, t, sym, fmt);
733 42616
                        ERRCHK(tl);
734
                        /* Unless asked for a HEADER, fold to string here */
735 42607
                        if (*e && fmt != HEADER && (*e)->fmt == HEADER) {
736 9640
                                vcc_expr_tostring(tl, e, STRINGS);
737 9640
                                ERRCHK(tl);
738
                        }
739 42607
                        return;
740
                }
741 2
                VSB_printf(tl->sb,
742
                    "Symbol type (%s) can not be used in expression.\n",
743 2
                    sym->kind->name);
744 2
                vcc_ErrWhere(tl, tl->t);
745 2
                if (sym->def_b != NULL) {
746 2
                        VSB_printf(tl->sb, "That symbol was defined here:\n");
747 2
                        vcc_ErrWhere(tl, sym->def_b);
748
                }
749 2
                return;
750
        case CSTR:
751 29979
                assert(fmt != VOID);
752 29979
                if (fmt == IP) {
753 27
                        if (*tl->t->dec == '/') {
754
                                /*
755
                                 * On some platforms (e.g. FreeBSD),
756
                                 * getaddrinfo(3) may resolve a path to a
757
                                 * sockaddr_un if it happens to exist and
758
                                 * is a socket. So don't let that happen.
759
                                 */
760 1
                                VSB_printf(tl->sb,
761
                                        "Cannot convert to an IP address: ");
762 1
                                vcc_ErrToken(tl, tl->t);
763 1
                                vcc_ErrWhere(tl, tl->t);
764 1
                                return;
765
                        }
766 26
                        Resolve_Sockaddr(tl, tl->t->dec, "80",
767
                            &ip, NULL, &ip, NULL, NULL, 1,
768 26
                            tl->t, "IP constant");
769 26
                        ERRCHK(tl);
770 23
                        e1 = vcc_mk_expr(IP, "%s", ip);
771 23
                        ERRCHK(tl);
772
                } else {
773 29952
                        e1 = vcc_new_expr(STRINGS);
774 29952
                        EncToken(e1->vsb, tl->t);
775 29952
                        AZ(VSB_finish(e1->vsb));
776 29952
                        e1->constant |= EXPR_STR_CONST;
777 29952
                        e1->nstr = 1;
778
                }
779 29975
                e1->t1 = tl->t;
780 29975
                e1->constant |= EXPR_CONST;
781 29975
                vcc_NextToken(tl);
782 29975
                *e = e1;
783 29975
                return;
784
        case '-':
785 41
                if (fmt != INT && fmt != REAL && fmt != DURATION)
786 0
                        break;
787 41
                vcc_NextToken(tl);
788 41
                ExpectErr(tl, CNUM);
789 41
                sign = "-";
790
                /* FALLTHROUGH */
791
        case CNUM:
792
                /*
793
                 * XXX: %g may not have enough decimals by default
794
                 * XXX: but %a is ugly, isn't it ?
795
                 */
796 8028
                assert(fmt != VOID);
797 8028
                if (fmt == BYTES) {
798 33
                        vcc_ByteVal(tl, &d);
799 33
                        ERRCHK(tl);
800 31
                        e1 = vcc_mk_expr(BYTES, "%.1f", d);
801
                } else {
802 7995
                        vcc_NumVal(tl, &d, &i);
803 7995
                        ERRCHK(tl);
804 7995
                        if (tl->t->tok == ID) {
805 3735
                                e1 = vcc_mk_expr(DURATION, "%s%g",
806 3735
                                    sign, d * vcc_TimeUnit(tl));
807 3735
                                ERRCHK(tl);
808 4260
                        } else if (i || fmt == REAL)
809 125
                                e1 = vcc_mk_expr(REAL, "%s%f", sign, d);
810
                        else
811 4135
                                e1 = vcc_mk_expr(INT, "%s%jd",
812
                                    sign, (intmax_t)d);
813
                }
814 8025
                e1->constant = EXPR_CONST;
815 8025
                *e = e1;
816 8025
                return;
817
        default:
818 2
                break;
819
        }
820 2
        VSB_printf(tl->sb, "Unknown token ");
821 2
        vcc_ErrToken(tl, tl->t);
822 2
        VSB_printf(tl->sb, " when looking for %s\n\n", vcc_utype(fmt));
823 2
        vcc_ErrWhere(tl, tl->t);
824
}
825
826
/*--------------------------------------------------------------------
827
 * SYNTAX:
828
 *    ExprMul:
829
 *      Expr4 { {'*'|'/'} Expr4 } *
830
 */
831
832
static void
833 81528
vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt)
834
{
835
        struct expr *e2;
836
        vcc_type_t f2;
837
        struct token *tk;
838
839 81528
        *e = NULL;
840 81528
        vcc_expr4(tl, e, fmt);
841 81563
        ERRCHK(tl);
842 81495
        AN(*e);
843
844 163012
        while (tl->t->tok == '*' || tl->t->tok == '/') {
845 24
                f2 = (*e)->fmt->multype;
846 24
                if (f2 == NULL) {
847 3
                        VSB_printf(tl->sb,
848
                            "Operator %.*s not possible on type %s.\n",
849 3
                            PF(tl->t), vcc_utype((*e)->fmt));
850 1
                        vcc_ErrWhere(tl, tl->t);
851 1
                        return;
852
                }
853 23
                tk = tl->t;
854 23
                vcc_NextToken(tl);
855 23
                vcc_expr4(tl, &e2, f2);
856 23
                ERRCHK(tl);
857 23
                if (e2->fmt != INT && e2->fmt != f2) {
858 3
                        VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
859 3
                            vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
860 1
                        vcc_ErrWhere(tl, tk);
861 1
                        return;
862
                }
863 22
                if (tk->tok == '*')
864 12
                        *e = vcc_expr_edit(tl, (*e)->fmt, "(\v1*\v2)", *e, e2);
865
                else
866 10
                        *e = vcc_expr_edit(tl, (*e)->fmt, "(\v1/\v2)", *e, e2);
867
        }
868
}
869
870
/*--------------------------------------------------------------------
871
 * SYNTAX:
872
 *    ExprAdd:
873
 *      ExprMul { {'+'|'-'} ExprMul } *
874
 */
875
876
static const struct adds {
877
        unsigned        op;
878
        vcc_type_t      a;
879
        vcc_type_t      b;
880
        vcc_type_t      fmt;
881
} vcc_adds[] = {
882
        { '+', BYTES,           BYTES,          BYTES },
883
        { '-', BYTES,           BYTES,          BYTES },
884
        { '+', DURATION,        DURATION,       DURATION },
885
        { '-', DURATION,        DURATION,       DURATION },
886
        { '+', INT,             INT,            INT },
887
        { '-', INT,             INT,            INT },
888
        { '+', INT,             REAL,           REAL },
889
        { '-', INT,             REAL,           REAL },
890
        { '+', REAL,            INT,            REAL },
891
        { '-', REAL,            INT,            REAL },
892
        { '+', REAL,            REAL,           REAL },
893
        { '-', REAL,            REAL,           REAL },
894
        { '-', TIME,            TIME,           DURATION },
895
        { '+', TIME,            DURATION,       TIME },
896
        { '-', TIME,            DURATION,       TIME },
897
898
        { EOI, VOID,            VOID,           VOID }
899
};
900
901
static void
902 58741
vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt)
903
{
904
        const struct adds *ap;
905
        struct expr  *e2;
906
        struct token *tk;
907
        int lit, n;
908
909 58741
        *e = NULL;
910 58741
        vcc_expr_mul(tl, e, fmt);
911 58787
        ERRCHK(tl);
912
913 140188
        while (tl->t->tok == '+' || tl->t->tok == '-') {
914 22787
                tk = tl->t;
915 352487
                for (ap = vcc_adds; ap->op != EOI; ap++)
916 330646
                        if (tk->tok == ap->op && (*e)->fmt == ap->a)
917 946
                                break;
918 22787
                vcc_NextToken(tl);
919 22787
                if (ap->op == EOI && fmt == STRINGS)
920 21836
                        vcc_expr_mul(tl, &e2, STRINGS);
921
                else
922 951
                        vcc_expr_mul(tl, &e2, (*e)->fmt);
923 22787
                ERRCHK(tl);
924
925 352609
                for (ap = vcc_adds; ap->op != EOI; ap++)
926 331719
                        if (tk->tok == ap->op && (*e)->fmt == ap->a &&
927 961
                            e2->fmt == ap->b)
928 936
                                break;
929
930 22787
                if (ap->op == '+') {
931 920
                        *e = vcc_expr_edit(tl, ap->fmt, "(\v1 + \v2)", *e, e2);
932 21867
                } else if (ap->op == '-') {
933 16
                        *e = vcc_expr_edit(tl, ap->fmt, "(\v1 - \v2)", *e, e2);
934 43701
                } else if (tk->tok == '+' &&
935 21865
                    ((*e)->fmt == STRINGS || fmt == STRINGS)) {
936 21840
                        if ((*e)->fmt != STRINGS)
937 5
                                vcc_expr_tostring(tl, e, STRINGS);
938 21840
                        if (e2->fmt != STRINGS)
939 3597
                                vcc_expr_tostring(tl, &e2, STRINGS);
940 43680
                        if (vcc_islit(*e) && vcc_isconst(e2)) {
941 19
                                lit = vcc_islit(e2);
942 19
                                *e = vcc_expr_edit(tl, STRINGS,
943
                                    "\v1\n\v2", *e, e2);
944 19
                                (*e)->constant = EXPR_CONST;
945 19
                                (*e)->nstr = 1;
946 38
                                if (lit)
947 19
                                        (*e)->constant |= EXPR_STR_CONST;
948
                        } else {
949 21821
                                n = (*e)->nstr + e2->nstr;
950 21821
                                *e = vcc_expr_edit(tl, STRINGS,
951
                                    "\v1,\n\v2", *e, e2);
952 21821
                                (*e)->constant = EXPR_VAR;
953 21821
                                (*e)->nstr = n;
954
                        }
955
                } else {
956 33
                        VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
957 33
                            vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
958 11
                        vcc_ErrWhere2(tl, tk, tl->t);
959 11
                        return;
960
                }
961
        }
962
}
963
964
/*--------------------------------------------------------------------
965
 * SYNTAX:
966
 *    ExprCmp:
967
 *      ExprAdd
968
 *      ExprAdd Relation ExprAdd
969
 *      ExprAdd(STRING) '~' CString
970
 *      ExprAdd(STRING) '!~' CString
971
 *      ExprAdd(IP) '==' ExprAdd(IP)
972
 *      ExprAdd(IP) '!=' ExprAdd(IP)
973
 *      ExprAdd(IP) '~' ACL
974
 *      ExprAdd(IP) '!~' ACL
975
 */
976
977
struct cmps;
978
979
typedef void cmp_f(struct vcc *, struct expr **, const struct cmps *);
980
981
struct cmps {
982
        vcc_type_t              fmt;
983
        unsigned                token;
984
        cmp_f                   *func;
985
        const char              *emit;
986
};
987
988
static void v_matchproto_(cmp_f)
989 3680
cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp)
990
{
991
        struct expr *e2;
992
        struct token *tk;
993
994 3680
        tk = tl->t;
995 3680
        vcc_NextToken(tl);
996 3680
        vcc_expr_add(tl, &e2, (*e)->fmt);
997 3680
        ERRCHK(tl);
998
999 3675
        if (e2->fmt != (*e)->fmt) {
1000 6
                VSB_printf(tl->sb,
1001
                    "Comparison of different types: %s '%.*s' %s\n",
1002 6
                    vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
1003 2
                vcc_ErrWhere(tl, tk);
1004
        } else
1005 3673
                *e = vcc_expr_edit(tl, BOOL, cp->emit, *e, e2);
1006
}
1007
1008
static void v_matchproto_(cmp_f)
1009 2725
cmp_regexp(struct vcc *tl, struct expr **e, const struct cmps *cp)
1010
{
1011
        char buf[128];
1012
        struct vsb vsb;
1013
1014 2725
        *e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL);
1015 2725
        vcc_NextToken(tl);
1016 2727
        ExpectErr(tl, CSTR);
1017 2724
        AN(VSB_new(&vsb, buf, sizeof buf, VSB_FIXEDLEN));
1018 2724
        VSB_printf(&vsb, "%sVRT_re_match(ctx, \v1, ", cp->emit);
1019 2724
        vcc_regexp(tl, &vsb);
1020 2724
        ERRCHK(tl);
1021 2723
        VSB_cat(&vsb, ")");
1022 2723
        AZ(VSB_finish(&vsb));
1023 2723
        *e = vcc_expr_edit(tl, BOOL, VSB_data(&vsb), *e, NULL);
1024
}
1025
1026
static void v_matchproto_(cmp_f)
1027 25
cmp_acl(struct vcc *tl, struct expr **e, const struct cmps *cp)
1028
{
1029
        struct symbol *sym;
1030
        char buf[256];
1031
1032 25
        vcc_NextToken(tl);
1033 25
        vcc_ExpectVid(tl, "ACL");
1034 25
        sym = VCC_SymbolGet(tl, SYM_ACL, SYMTAB_CREATE, XREF_REF);
1035 25
        ERRCHK(tl);
1036 21
        AN(sym);
1037 21
        VCC_GlobalSymbol(sym, ACL, ACL_SYMBOL_PREFIX);
1038 21
        bprintf(buf, "%sVRT_acl_match(ctx, %s, \v1)", cp->emit, sym->rname);
1039 21
        *e = vcc_expr_edit(tl, BOOL, buf, *e, NULL);
1040
}
1041
1042
static void v_matchproto_(cmp_f)
1043 11983
cmp_string(struct vcc *tl, struct expr **e, const struct cmps *cp)
1044
{
1045
        struct expr *e2;
1046
        struct token *tk;
1047
        char buf[128];
1048
1049 11983
        tk = tl->t;
1050 11983
        vcc_NextToken(tl);
1051 11983
        vcc_expr_add(tl, &e2, STRINGS);
1052 11983
        ERRCHK(tl);
1053 11983
        if (e2->fmt != STRINGS) {
1054 9
                VSB_printf(tl->sb,
1055
                    "Comparison of different types: %s '%.*s' %s\n",
1056 9
                    vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
1057 3
                vcc_ErrWhere(tl, tk);
1058 11980
        } else if ((*e)->nstr == 1 && e2->nstr == 1) {
1059 11961
                bprintf(buf, "(%s VRT_strcmp(\v1, \v2))", cp->emit);
1060 11961
                *e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
1061
        } else {
1062 19
                bprintf(buf, "(%s VRT_CompareStrands(\vT, \vt))", cp->emit);
1063 19
                *e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
1064
        }
1065
}
1066
1067
#define IDENT_REL(typ)                                                  \
1068
        {typ,           T_EQ,           cmp_simple, "(\v1 == \v2)" },   \
1069
        {typ,           T_NEQ,          cmp_simple, "(\v1 != \v2)" }
1070
1071
#define NUM_REL(typ)                                                    \
1072
        IDENT_REL(typ),                                                 \
1073
        {typ,           T_LEQ,          cmp_simple, "(\v1 <= \v2)" },   \
1074
        {typ,           T_GEQ,          cmp_simple, "(\v1 >= \v2)" },   \
1075
        {typ,           '<',            cmp_simple, "(\v1 < \v2)" },    \
1076
        {typ,           '>',            cmp_simple, "(\v1 > \v2)" }
1077
1078
static const struct cmps vcc_cmps[] = {
1079
        NUM_REL(INT),
1080
        NUM_REL(DURATION),
1081
        NUM_REL(BYTES),
1082
        NUM_REL(REAL),
1083
        NUM_REL(TIME),
1084
        IDENT_REL(BACKEND),
1085
        IDENT_REL(ACL),
1086
        IDENT_REL(PROBE),
1087
        IDENT_REL(STEVEDORE),
1088
        IDENT_REL(SUB),
1089
        IDENT_REL(INSTANCE),
1090
1091
        {IP,            T_EQ,           cmp_simple, "!VRT_ipcmp(\v1, \v2)" },
1092
        {IP,            T_NEQ,          cmp_simple, "VRT_ipcmp(\v1, \v2)" },
1093
1094
        {IP,            '~',            cmp_acl, "" },
1095
        {IP,            T_NOMATCH,      cmp_acl, "!" },
1096
1097
        {STRINGS,       T_EQ,           cmp_string, "0 =="},
1098
        {STRINGS,       T_NEQ,          cmp_string, "0 !="},
1099
        {STRINGS,       '<',            cmp_string, "0 > "},
1100
        {STRINGS,       '>',            cmp_string, "0 < "},
1101
        {STRINGS,       T_LEQ,          cmp_string, "0 >="},
1102
        {STRINGS,       T_GEQ,          cmp_string, "0 <="},
1103
1104
        {STRINGS,       '~',            cmp_regexp, "" },
1105
        {STRINGS,       T_NOMATCH,      cmp_regexp, "!" },
1106
1107
        {VOID,          0,              NULL, NULL}
1108
};
1109
1110
#undef IDENT_REL
1111
#undef NUM_REL
1112
1113
static void
1114 43078
vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1115
{
1116
        const struct cmps *cp;
1117
        struct token *tk;
1118
1119 43078
        *e = NULL;
1120 43078
        vcc_expr_add(tl, e, fmt);
1121 43078
        ERRCHK(tl);
1122 43037
        tk = tl->t;
1123
1124 43037
        if ((*e)->fmt == BOOL)
1125 3031
                return;
1126
1127 1935066
        for (cp = vcc_cmps; cp->fmt != VOID; cp++) {
1128 1913473
                if ((*e)->fmt == cp->fmt && tl->t->tok == cp->token) {
1129 18413
                        AN(cp->func);
1130 18413
                        cp->func(tl, e, cp);
1131 18413
                        return;
1132
                }
1133
        }
1134
1135 21593
        switch (tk->tok) {
1136
        case T_EQ:
1137
        case T_NEQ:
1138
        case '<':
1139
        case T_LEQ:
1140
        case '>':
1141
        case T_GEQ:
1142
        case '~':
1143
        case T_NOMATCH:
1144 6
                VSB_printf(tl->sb, "Operator %.*s not possible on %s\n",
1145 6
                    PF(tl->t), vcc_utype((*e)->fmt));
1146 2
                vcc_ErrWhere(tl, tl->t);
1147 2
                return;
1148
        default:
1149 21591
                break;
1150
        }
1151
}
1152
1153
/*--------------------------------------------------------------------
1154
 * SYNTAX:
1155
 *    ExprNot:
1156
 *      '!' ExprCmp
1157
 */
1158
1159
static void
1160 43078
vcc_expr_not(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1161
{
1162
        struct token *tk;
1163
1164 43078
        *e = NULL;
1165 43078
        tk = tl->t;
1166 43078
        if (tl->t->tok == '!')
1167 1846
                vcc_NextToken(tl);
1168 43078
        vcc_expr_cmp(tl, e, fmt);
1169 43078
        ERRCHK(tl);
1170 43019
        if (tk->tok != '!')
1171 41174
                return;
1172 1845
        vcc_expr_tobool(tl, e);
1173 1845
        ERRCHK(tl);
1174 1845
        if ((*e)->fmt != BOOL) {
1175 1
                VSB_printf(tl->sb, "'!' must be followed by BOOL, found ");
1176 1
                VSB_printf(tl->sb, "%s.\n", vcc_utype((*e)->fmt));
1177 1
                vcc_ErrWhere2(tl, tk, tl->t);
1178
        } else {
1179 1844
                *e = vcc_expr_edit(tl, BOOL, "!(\v1)", *e, NULL);
1180
        }
1181
}
1182
1183
/*--------------------------------------------------------------------
1184
 * CAND and COR are identical save for a few details, but they are
1185
 * stacked so handling them in the same function is not simpler.
1186
 * Instead have them both call this helper function to do everything.
1187
 */
1188
1189
typedef void upfunc(struct vcc *tl, struct expr **e, vcc_type_t fmt);
1190
1191
static void
1192 57480
vcc_expr_bin_bool(struct vcc *tl, struct expr **e, vcc_type_t fmt,
1193
    unsigned ourtok, upfunc *up, const char *tokstr)
1194
{
1195
        struct expr *e2;
1196
        struct token *tk;
1197
        char buf[32];
1198
1199 57480
        *e = NULL;
1200 57480
        tk = tl->t;
1201 57480
        up(tl, e, fmt);
1202 109574
        ERRCHK(tl);
1203 57358
        if (tl->t->tok != ourtok)
1204 51968
                return;
1205 5390
        vcc_expr_tobool(tl, e);
1206 5390
        ERRCHK(tl);
1207 5390
        if ((*e)->fmt != BOOL) {
1208 2
                VSB_printf(tl->sb,
1209
                    "'%s' must be preceeded by BOOL,"
1210 2
                    " found %s.\n", tokstr, vcc_utype((*e)->fmt));
1211 2
                vcc_ErrWhere2(tl, tk, tl->t);
1212 2
                return;
1213
        }
1214 5388
        *e = vcc_expr_edit(tl, BOOL, "(\v+\n\v1", *e, NULL);
1215 25112
        while (tl->t->tok == ourtok) {
1216 14338
                vcc_NextToken(tl);
1217 14338
                tk = tl->t;
1218 14338
                vcc_expr_not(tl, &e2, fmt);
1219 14338
                ERRCHK(tl);
1220 14338
                vcc_expr_tobool(tl, &e2);
1221 14338
                ERRCHK(tl);
1222 14338
                if (e2->fmt != BOOL) {
1223 2
                        VSB_printf(tl->sb,
1224
                            "'%s' must be followed by BOOL,"
1225 2
                            " found %s.\n", tokstr, vcc_utype(e2->fmt));
1226 2
                        vcc_ErrWhere2(tl, tk, tl->t);
1227 2
                        return;
1228
                }
1229 14336
                bprintf(buf, "\v1\v-\n%s\v+\n\v2", tokstr);
1230 14336
                *e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
1231
        }
1232 5386
        *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n)", *e, NULL);
1233
}
1234
1235
/*--------------------------------------------------------------------
1236
 * SYNTAX:
1237
 *    ExprCand:
1238
 *      ExprNot { '&&' ExprNot } *
1239
 */
1240
1241
static void
1242 28740
vcc_expr_cand(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1243
{
1244
1245 28740
        vcc_expr_bin_bool(tl, e, fmt, T_CAND, vcc_expr_not, "&&");
1246 28740
}
1247
1248
/*--------------------------------------------------------------------
1249
 * SYNTAX:
1250
 *    ExprCOR:
1251
 *      ExprCand { '||' ExprCand } *
1252
 */
1253
1254
static void
1255 28740
vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1256
{
1257
1258 28740
        vcc_expr_bin_bool(tl, e, fmt, T_COR, vcc_expr_cand, "||");
1259 28740
}
1260
1261
/*--------------------------------------------------------------------
1262
 * This function is the entry-point for getting an expression with
1263
 * a particular type, ready for inclusion in the VGC.
1264
 */
1265
1266
static void
1267 27831
vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1268
{
1269
        struct token *t1;
1270
1271 27831
        assert(fmt != VOID);
1272 27831
        assert(fmt != STRINGS);
1273 27831
        *e = NULL;
1274 27831
        t1 = tl->t;
1275 27831
        if (fmt == STRING_LIST || fmt == STRING)
1276 11308
                vcc_expr_cor(tl, e, STRINGS);
1277
        else
1278 16523
                vcc_expr_cor(tl, e, fmt);
1279 27831
        ERRCHK(tl);
1280 27767
        assert((*e)->fmt != STRING_LIST && (*e)->fmt != STRING);
1281
1282 27767
        if ((*e)->fmt == STRINGS && fmt == STRING_LIST)
1283 8818
                (*e)->fmt = STRING_LIST;
1284 18949
        else if ((*e)->fmt == STRINGS && fmt == STRING)
1285 1219
                *e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL);
1286 17730
        else if ((*e)->fmt == STRINGS && fmt == STRANDS) {
1287 0
                *e = vcc_expr_edit(tl, STRANDS, "\vT", (*e), NULL);
1288 17730
        } else if ((*e)->fmt != STRINGS &&
1289 16806
            (fmt == STRING || fmt == STRING_LIST))
1290 1249
                vcc_expr_tostring(tl, e, fmt);
1291
1292 27767
        if ((*e)->fmt == STRING_LIST)
1293 10062
                *e = vcc_expr_edit(tl, STRING_LIST,
1294
                    "\v+\n\v1,\nvrt_magic_string_end\v-", *e, NULL);
1295
1296 27767
        if (fmt == BOOL) {
1297 11494
                vcc_expr_tobool(tl, e);
1298 11494
                ERRCHK(tl);
1299
        }
1300
1301 27767
        if (fmt != (*e)->fmt)  {
1302 8
                VSB_printf(tl->sb, "Expression has type %s, expected %s\n",
1303 4
                    vcc_utype((*e)->fmt), vcc_utype(fmt));
1304 4
                vcc_ErrWhere2(tl, t1, tl->t);
1305 4
                return;
1306
        }
1307
}
1308
1309
/*--------------------------------------------------------------------
1310
 * This function parses and emits the C-code to evaluate an expression
1311
 *
1312
 * We know up front what kind of type we want the expression to be,
1313
 * and this function is the backstop if that doesn't succeed.
1314
 */
1315
1316
void
1317 25920
vcc_Expr(struct vcc *tl, vcc_type_t fmt)
1318
{
1319 25920
        struct expr *e = NULL;
1320
1321 25920
        assert(fmt != VOID);
1322 25920
        assert(fmt != STRINGS);
1323 25920
        vcc_expr0(tl, &e, fmt);
1324 25920
        ERRCHK(tl);
1325 25858
        assert(e->fmt == fmt);
1326
1327 25858
        vcc_expr_fmt(tl->fb, tl->indent, e);
1328 25858
        VSB_printf(tl->fb, "\n");
1329 25858
        vcc_delete_expr(e);
1330
}
1331
1332
/*--------------------------------------------------------------------
1333
 */
1334
1335
void v_matchproto_(sym_act_f)
1336 455
vcc_Act_Call(struct vcc *tl, struct token *t, struct symbol *sym)
1337
{
1338
1339
        struct expr *e;
1340
1341 455
        e = NULL;
1342 455
        vcc_func(tl, &e, sym->eval_priv, sym->extra, sym);
1343 455
        if (!tl->err) {
1344 453
                vcc_expr_fmt(tl->fb, tl->indent, e);
1345 453
                SkipToken(tl, ';');
1346 453
                VSB_cat(tl->fb, ";\n");
1347 2
        } else if (t != tl->t) {
1348 2
                vcc_ErrWhere2(tl, t, tl->t);
1349
        }
1350 455
        vcc_delete_expr(e);
1351
}
1352
1353
/*--------------------------------------------------------------------
1354
 */
1355
1356
void
1357 1063
vcc_Expr_Init(struct vcc *tl)
1358
{
1359
        struct symbol *sym;
1360
1361 1063
        sym = VCC_MkSym(tl, "regsub", SYM_FUNC, VCL_LOW, VCL_HIGH);
1362 1063
        AN(sym);
1363 1063
        sym->type = STRING;
1364 1063
        sym->eval = vcc_Eval_Regsub;
1365 1063
        sym->eval_priv = NULL;
1366
1367 1063
        sym = VCC_MkSym(tl, "regsuball", SYM_FUNC, VCL_LOW, VCL_HIGH);
1368 1063
        AN(sym);
1369 1063
        sym->type = STRING;
1370 1063
        sym->eval = vcc_Eval_Regsub;
1371 1063
        sym->eval_priv = sym;
1372
1373 1063
        sym = VCC_MkSym(tl, "true", SYM_FUNC, VCL_LOW, VCL_HIGH);
1374 1063
        AN(sym);
1375 1063
        sym->type = BOOL;
1376 1063
        sym->eval = vcc_Eval_BoolConst;
1377 1063
        sym->eval_priv = sym;
1378
1379 1063
        sym = VCC_MkSym(tl, "false", SYM_FUNC, VCL_LOW, VCL_HIGH);
1380 1063
        AN(sym);
1381 1063
        sym->type = BOOL;
1382 1063
        sym->eval = vcc_Eval_BoolConst;
1383 1063
        sym->eval_priv = NULL;
1384 1063
}