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 3784
vcc_isconst(const struct expr *e)
61
{
62 3784
        AN(e->constant);
63 3784
        return (e->constant & EXPR_CONST);
64
}
65
66
static inline int
67 44332
vcc_islit(const struct expr *e)
68
{
69 44332
        AN(e->constant);
70 44332
        return (e->constant & EXPR_STR_CONST);
71
}
72
73
static const char *
74 104
vcc_utype(vcc_type_t t)
75
{
76 104
        if (t == STRINGS || t->stringform)
77 34
                t = STRING;
78 104
        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 391680
vcc_new_expr(vcc_type_t fmt)
86
{
87
        struct expr *e;
88
89 391680
        ALLOC_OBJ(e, EXPR_MAGIC);
90 391680
        AN(e);
91 391680
        e->vsb = VSB_new_auto();
92 391680
        e->fmt = fmt;
93 391680
        e->constant = EXPR_VAR;
94 391680
        return (e);
95
}
96
97
static struct expr * v_printflike_(2, 3)
98 108524
vcc_mk_expr(vcc_type_t fmt, const char *str, ...)
99
{
100
        va_list ap;
101
        struct expr *e;
102
103 108524
        e = vcc_new_expr(fmt);
104 108524
        va_start(ap, str);
105 108524
        VSB_vprintf(e->vsb, str, ap);
106 108524
        va_end(ap);
107 108524
        AZ(VSB_finish(e->vsb));
108 108524
        return (e);
109
}
110
111
static void
112 498646
vcc_delete_expr(struct expr *e)
113
{
114 498646
        if (e == NULL)
115 107094
                return;
116 391552
        CHECK_OBJ_NOTNULL(e, EXPR_MAGIC);
117 391552
        VSB_destroy(&e->vsb);
118 391552
        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 222524
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 222524
        int nl = 1;
151
152 222524
        AN(e1);
153 222524
        e = vcc_new_expr(fmt);
154 3011712
        while (*p != '\0') {
155 2566664
                if (*p != '\v') {
156 2105910
                        if (*p != '\n' || !nl)
157 2042538
                                VSB_putc(e->vsb, *p);
158 2105910
                        nl = (*p == '\n');
159 2105910
                        p++;
160 2105910
                        continue;
161
                }
162 460754
                assert(*p == '\v');
163 460754
                switch (*++p) {
164 59398
                case '+': VSB_cat(e->vsb, "\v+"); break;
165 63398
                case '-': VSB_cat(e->vsb, "\v-"); break;
166
                case 'S':
167
                case 's':
168 18918
                        e3 = (*p == 'S' ? e1 : e2);
169 18918
                        AN(e3);
170 18918
                        assert(e1->fmt == STRINGS);
171 18918
                        if (e3->nstr > 1)
172 18
                                VSB_cat(e->vsb,
173
                                    "\nVRT_CollectString(ctx,\v+\n");
174 18918
                        VSB_cat(e->vsb, VSB_data(e3->vsb));
175 18918
                        if (e3->nstr > 1)
176 18
                                VSB_cat(e->vsb,
177
                                    ",\nvrt_magic_string_end)\v-\n");
178 18918
                        break;
179
                case 'T':
180
                case 't':
181 1074
                        e3 = (*p == 'T' ? e1 : e2);
182 1074
                        AN(e3);
183 1074
                        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 1074
                        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 1074
                        VSB_data(e3->vsb));
192 1074
                        tl->unique++;
193 1074
                        break;
194
                case '1':
195 202570
                        VSB_cat(e->vsb, VSB_data(e1->vsb));
196 202570
                        break;
197
                case '2':
198 115396
                        AN(e2);
199 115396
                        VSB_cat(e->vsb, VSB_data(e2->vsb));
200 115396
                        break;
201
                default:
202 0
                        WRONG("Illegal edit in VCC expression");
203
                }
204 460754
                p++;
205
        }
206 222524
        AZ(VSB_finish(e->vsb));
207 222524
        e->t1 = e1->t1;
208 222524
        e->t2 = e1->t2;
209 222524
        if (e2 != NULL)
210 115434
                e->t2 = e2->t2;
211 222524
        vcc_delete_expr(e1);
212 222524
        vcc_delete_expr(e2);
213 222524
        return (e);
214
}
215
216
/*--------------------------------------------------------------------
217
 * Expand finished expression into C-source code
218
 */
219
220
static void
221 53590
vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1)
222
{
223
        char *p;
224
        int i;
225
226 517726
        for (i = 0; i < ind; i++)
227 464136
                VSB_cat(d, " ");
228 53590
        p = VSB_data(e1->vsb);
229 5904138
        while (*p != '\0') {
230 5796964
                if (*p == '\n') {
231 167780
                        VSB_putc(d, '\n');
232 167780
                        if (*++p == '\0')
233 6
                                break;
234 1900078
                        for (i = 0; i < ind; i++)
235 1732304
                                VSB_cat(d, " ");
236 5629184
                } else if (*p != '\v') {
237 5498092
                        VSB_putc(d, *p++);
238
                } else {
239 131092
                        switch (*++p) {
240 65546
                        case '+': ind += 2; break;
241 65546
                        case '-': ind -= 2; break;
242 0
                        default:  WRONG("Illegal format in VCC expression");
243
                        }
244 131092
                        p++;
245
                }
246
        }
247 53590
}
248
249
/*--------------------------------------------------------------------
250
 */
251
252
static void
253 66882
vcc_expr_tobool(struct vcc *tl, struct expr **e)
254
{
255
256 66882
        if ((*e)->fmt == BOOL)
257 55938
                return;
258 10944
        if ((*e)->fmt == BACKEND || (*e)->fmt == INT)
259 18
                *e = vcc_expr_edit(tl, BOOL, "(\v1 != 0)", *e, NULL);
260 10926
        else if ((*e)->fmt == DURATION)
261 4
                *e = vcc_expr_edit(tl, BOOL, "(\v1 > 0)", *e, NULL);
262 10922
        else if ((*e)->fmt == STRINGS)
263 10912
                *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 29458
vcc_expr_tostring(struct vcc *tl, struct expr **e, vcc_type_t fmt)
276
{
277
        const char *p;
278 29458
        uint8_t constant = EXPR_VAR;
279
280 29458
        CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC);
281 29458
        assert(fmt == STRINGS || fmt->stringform);
282 29458
        assert(fmt != (*e)->fmt);
283
284 29458
        p = (*e)->fmt->tostring;
285 29458
        if (p != NULL) {
286 29456
                AN(*p);
287 29456
                *e = vcc_expr_edit(tl, fmt, p, *e, NULL);
288 29456
                (*e)->constant = constant;
289 29456
                (*e)->nstr = 1;
290
        } else {
291 2
                if ((*e)->fmt == BLOB)
292 2
                        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 2
                vcc_ErrWhere2(tl, (*e)->t1, tl->t);
301
        }
302 29458
}
303
304
/*--------------------------------------------------------------------
305
 */
306
307
static void v_matchproto_(sym_expr_t)
308 64
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 64
        int all = sym->eval_priv == NULL ? 0 : 1;
313
        char buf[128];
314
        struct vsb vsb;
315
316
        (void)t;
317
        (void)fmt;
318 64
        SkipToken(tl, '(');
319 64
        vcc_expr0(tl, &e2, STRING);
320 64
        ERRCHK(tl);
321 64
        SkipToken(tl, ',');
322 64
        ExpectErr(tl, CSTR);
323
324 64
        AN(VSB_new(&vsb, buf, sizeof buf, VSB_FIXEDLEN));
325 64
        VSB_printf(&vsb, "VRT_regsub(ctx, %d,\v+\n\v1,\n", all);
326 64
        vcc_regexp(tl, &vsb);
327 64
        ERRCHK(tl);
328 64
        AZ(VSB_finish(&vsb));
329 64
        *e = vcc_expr_edit(tl, STRING, VSB_data(&vsb), e2, NULL);
330 64
        SkipToken(tl, ',');
331 64
        vcc_expr0(tl, &e2, STRING);
332 64
        ERRCHK(tl);
333 64
        *e = vcc_expr_edit(tl, STRINGS, "\v1,\n\v2)\v-", *e, e2);
334 64
        (*e)->nstr = 1;
335 64
        SkipToken(tl, ')');
336
}
337
338
/*--------------------------------------------------------------------
339
 */
340
341
static void v_matchproto_(sym_expr_t)
342 2208
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 2208
        *e = vcc_mk_expr(BOOL, "(0==%d)", sym->eval_priv == NULL ? 1 : 0);
350 2208
        (*e)->constant = EXPR_CONST;
351 2208
}
352
353
/*--------------------------------------------------------------------
354
 */
355
356
void v_matchproto_(sym_expr_t)
357 414
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 414
        AN(sym->rname);
364 414
        AZ(type->stringform);
365
366 414
        if (sym->type != STRING && type == STRINGS) {
367 4
                *e = vcc_mk_expr(STRINGS, "\"%s\"", sym->name);
368 4
                (*e)->nstr = 1;
369 4
                (*e)->constant |= EXPR_CONST | EXPR_STR_CONST;
370
        } else {
371 410
                *e = vcc_mk_expr(sym->type, "%s", sym->rname);
372 410
                (*e)->constant = EXPR_VAR;
373 410
                (*e)->nstr = 1;
374 410
                if ((*e)->fmt == STRING)
375 0
                        (*e)->fmt = STRINGS;
376
        }
377 414
}
378
379
/*--------------------------------------------------------------------
380
 */
381
382
void v_matchproto_(sym_expr_t)
383 80904
vcc_Eval_Var(struct vcc *tl, struct expr **e, struct token *t,
384
    struct symbol *sym, vcc_type_t type)
385
{
386
387
        (void)type;
388 80904
        assert(sym->kind == SYM_VAR);
389 80904
        vcc_AddUses(tl, t, NULL, sym->r_methods, "Not available");
390 80904
        ERRCHK(tl);
391 80904
        *e = vcc_mk_expr(sym->type, "%s", sym->rname);
392 80904
        (*e)->constant = EXPR_VAR;
393 80904
        (*e)->nstr = 1;
394 80904
        if ((*e)->fmt == STRING)
395 40628
                (*e)->fmt = STRINGS;
396
}
397
398
/*--------------------------------------------------------------------
399
 */
400
401
static struct expr *
402 378
vcc_priv_arg(struct vcc *tl, const char *p, const struct symbol *sym)
403
{
404
        char buf[64];
405
        struct inifin *ifp;
406 378
        const char *vmod, *f = NULL;
407 378
        struct procprivhead *marklist = NULL;
408
409 378
        AN(sym);
410 378
        AN(sym->vmod);
411 378
        vmod = sym->vmod;
412
413 378
        if (!strcmp(p, "PRIV_VCL")) {
414 6
                return (vcc_mk_expr(VOID, "&vmod_priv_%s", vmod));
415 372
        } else if (!strcmp(p, "PRIV_CALL")) {
416 26
                bprintf(buf, "vmod_priv_%u", tl->unique++);
417 26
                ifp = New_IniFin(tl);
418 26
                Fh(tl, 0, "static struct vmod_priv %s;\n", buf);
419 26
                VSB_printf(ifp->fin, "\tVRT_priv_fini(&%s);", buf);
420 26
                return (vcc_mk_expr(VOID, "&%s", buf));
421 346
        } else if (!strcmp(p, "PRIV_TASK")) {
422 338
                f = "task";
423 338
                marklist = &tl->curproc->priv_tasks;
424 8
        } else if (!strcmp(p, "PRIV_TOP")) {
425 8
                f = "top";
426 8
                marklist = &tl->curproc->priv_tops;
427
        } else {
428 0
                WRONG("Wrong PRIV_ type");
429
        }
430 346
        AN(f);
431 346
        AN(marklist);
432 346
        bprintf(buf, "ARG_priv_%s_%s", f, vmod);
433
434 346
        if (vcc_MarkPriv(tl, marklist, vmod) == NULL)
435 56
                VSB_printf(tl->curproc->prologue,
436
                           "  struct vmod_priv *%s = "
437
                           "VRT_priv_%s(ctx, &VGC_vmod_%s);\n"
438
                           "  if (%s == NULL) {\n"
439
                           "    VRT_fail(ctx, \"failed to get %s priv "
440
                           "for vmod %s\");\n"
441
                           "    return;\n"
442
                           "  }\n",
443
                           buf, f, vmod, buf, f, vmod);
444 346
        return (vcc_mk_expr(VOID, "%s", buf));
445
}
446
447
struct func_arg {
448
        vcc_type_t              type;
449
        const struct vjsn_val   *enums;
450
        const char              *cname;
451
        const char              *name;
452
        const char              *val;
453
        struct expr             *result;
454
        int                     avail;
455
        int                     optional;
456
        VTAILQ_ENTRY(func_arg)  list;
457
};
458
459
static void
460 3430
vcc_do_enum(struct vcc *tl, struct func_arg *fa, int len, const char *ptr)
461
{
462
        const char *r;
463
464
        (void)tl;
465 3430
        r = strchr(fa->cname, '.');
466 3430
        AN(r);
467 6860
        fa->result = vcc_mk_expr(VOID, "*%.*s.enum_%.*s",
468 3430
            (int)(r - fa->cname), fa->cname, len, ptr);
469 3430
}
470
471
static void
472 6332
vcc_do_arg(struct vcc *tl, struct func_arg *fa)
473
{
474
        struct expr *e2;
475
        struct vjsn_val *vv;
476
477 6332
        if (fa->type == ENUM) {
478 2546
                ExpectErr(tl, ID);
479 2530
                ERRCHK(tl);
480 7904
                VTAILQ_FOREACH(vv, &fa->enums->children, list)
481 7900
                        if (vcc_IdIs(tl->t, vv->value))
482 2526
                                break;
483 2530
                if (vv == NULL) {
484 4
                        VSB_printf(tl->sb, "Wrong enum value.");
485 4
                        VSB_printf(tl->sb, "  Expected one of:\n");
486 20
                        VTAILQ_FOREACH(vv, &fa->enums->children, list)
487 16
                                VSB_printf(tl->sb, "\t%s\n", vv->value);
488 4
                        vcc_ErrWhere(tl, tl->t);
489 4
                        return;
490
                }
491 2526
                vcc_do_enum(tl, fa, PF(tl->t));
492 2526
                SkipToken(tl, ID);
493
        } else {
494 3802
                vcc_expr0(tl, &e2, fa->type);
495 3802
                ERRCHK(tl);
496 3790
                assert(e2->fmt == fa->type);
497 3790
                fa->result = e2;
498
        }
499 6316
        fa->avail = 1;
500
}
501
502
static void
503 4024
vcc_func(struct vcc *tl, struct expr **e, const void *priv,
504
    const char *extra, const struct symbol *sym)
505
{
506
        vcc_type_t rfmt;
507
        const char *cfunc;
508
        struct expr *e1;
509
        struct func_arg *fa, *fa2;
510
        VTAILQ_HEAD(,func_arg) head;
511
        struct token *t1;
512
        const struct vjsn_val *vv, *vvp;
513
        const char *sa;
514
        char ssa[64];
515
        int n;
516
517 4024
        CAST_OBJ_NOTNULL(vv, priv, VJSN_VAL_MAGIC);
518 4024
        assert(vv->type == VJSN_ARRAY);
519 4024
        vv = VTAILQ_FIRST(&vv->children);
520 4024
        rfmt = VCC_Type(VTAILQ_FIRST(&vv->children)->value);
521 4024
        AN(rfmt);
522 4024
        vv = VTAILQ_NEXT(vv, list);
523 4024
        cfunc = vv->value;
524 4024
        vv = VTAILQ_NEXT(vv, list);
525 4024
        sa = vv->value;
526 4024
        if (*sa == '\0') {
527 3708
                sa = NULL;
528
        }
529 4024
        vv = VTAILQ_NEXT(vv, list);
530 4046
        SkipToken(tl, '(');
531 4024
        if (extra == NULL)
532 2456
                extra = "";
533 4024
        VTAILQ_INIT(&head);
534 13352
        for (;vv != NULL; vv = VTAILQ_NEXT(vv, list)) {
535 9328
                assert(vv->type == VJSN_ARRAY);
536 9328
                fa = calloc(1, sizeof *fa);
537 9328
                AN(fa);
538 9328
                fa->cname = cfunc;
539 9328
                VTAILQ_INSERT_TAIL(&head, fa, list);
540
541 9328
                vvp = VTAILQ_FIRST(&vv->children);
542 9328
                if (!memcmp(vvp->value, "PRIV_", 5)) {
543 378
                        fa->result = vcc_priv_arg(tl, vvp->value, sym);
544 378
                        continue;
545
                }
546 8950
                fa->type = VCC_Type(vvp->value);
547 8950
                AN(fa->type);
548 8950
                vvp = VTAILQ_NEXT(vvp, list);
549 8950
                if (vvp != NULL) {
550 8418
                        fa->name = vvp->value;
551 8418
                        vvp = VTAILQ_NEXT(vvp, list);
552 8418
                        if (vvp != NULL) {
553 5834
                                fa->val = vvp->value;
554 5834
                                vvp = VTAILQ_NEXT(vvp, list);
555 5834
                                if (vvp != NULL) {
556 4552
                                        fa->enums = vvp;
557 4552
                                        vvp = VTAILQ_NEXT(vvp, list);
558
                                }
559
                        }
560
                }
561 8950
                if (sa != NULL && vvp != NULL && vvp->type == VJSN_TRUE) {
562 1284
                        fa->optional = 1;
563 1284
                        vvp = VTAILQ_NEXT(vvp, list);
564
                }
565 8950
                AZ(vvp);
566
        }
567
568 7070
        VTAILQ_FOREACH(fa, &head, list) {
569 6384
                if (tl->t->tok == ')')
570 96
                        break;
571 6288
                if (fa->result != NULL)
572 318
                        continue;
573 5970
                if (tl->t->tok == ID) {
574 4722
                        t1 = VTAILQ_NEXT(tl->t, list);
575 4722
                        if (t1->tok == '=')
576 1376
                                break;
577
                }
578 4594
                vcc_do_arg(tl, fa);
579 4594
                ERRCHK(tl);
580 4580
                if (tl->t->tok == ')')
581 1852
                        break;
582 2728
                SkipToken(tl, ',');
583
        }
584 8386
        while (tl->t->tok == ID) {
585 5604
                VTAILQ_FOREACH(fa, &head, list) {
586 5602
                        if (fa->name == NULL)
587 94
                                continue;
588 5508
                        if (vcc_IdIs(tl->t, fa->name))
589 1740
                                break;
590
                }
591 1742
                if (fa == NULL) {
592 4
                        VSB_printf(tl->sb, "Unknown argument '%.*s'\n",
593 4
                            PF(tl->t));
594 2
                        vcc_ErrWhere(tl, tl->t);
595 2
                        return;
596
                }
597 1740
                if (fa->result != NULL) {
598 2
                        AN(fa->name);
599 2
                        VSB_printf(tl->sb, "Argument '%s' already used\n",
600
                            fa->name);
601 2
                        vcc_ErrWhere(tl, tl->t);
602 2
                        return;
603
                }
604 1738
                vcc_NextToken(tl);
605 1738
                SkipToken(tl, '=');
606 1738
                vcc_do_arg(tl, fa);
607 1738
                ERRCHK(tl);
608 1736
                if (tl->t->tok == ')')
609 1370
                        break;
610 366
                SkipToken(tl, ',');
611
        }
612
613 4004
        if (sa != NULL)
614 312
                e1 = vcc_mk_expr(rfmt, "%s(ctx%s,\v+ &(%s){\n",
615
                    cfunc, extra, sa);
616
        else
617 3692
                e1 = vcc_mk_expr(rfmt, "%s(ctx%s\v+", cfunc, extra);
618 4004
        n = 0;
619 13272
        VTAILQ_FOREACH_SAFE(fa, &head, list, fa2) {
620 9268
                n++;
621 9268
                if (fa->optional) {
622 1280
                        AN(fa->name);
623 1280
                        bprintf(ssa, "\v1.valid_%s = %d,\n",
624
                            fa->name, fa->avail);
625 1280
                        e1 = vcc_expr_edit(tl, e1->fmt, ssa, e1, NULL);
626
                }
627 9268
                if (fa->result == NULL && fa->type == ENUM && fa->val != NULL)
628 904
                        vcc_do_enum(tl, fa, strlen(fa->val), fa->val);
629 9268
                if (fa->result == NULL && fa->val != NULL)
630 892
                        fa->result = vcc_mk_expr(fa->type, "%s", fa->val);
631 9268
                if (fa->result != NULL && sa != NULL) {
632 916
                        if (fa->name)
633 736
                                bprintf(ssa, "\v1.%s = \v2,\n", fa->name);
634
                        else
635 180
                                bprintf(ssa, "\v1.arg%d = \v2,\n", n);
636 916
                        e1 = vcc_expr_edit(tl, e1->fmt, ssa, e1, fa->result);
637 8352
                } else if (fa->result != NULL) {
638 7564
                        e1 = vcc_expr_edit(tl, e1->fmt, "\v1,\n\v2",
639
                            e1, fa->result);
640 788
                } else if (!fa->optional) {
641 2
                        if (fa->name)
642 2
                                VSB_printf(tl->sb, "Argument '%s' missing\n",
643
                                    fa->name);
644
                        else
645 0
                                VSB_printf(tl->sb, "Argument %d missing\n", n);
646 2
                        vcc_ErrWhere(tl, tl->t);
647
                }
648 9268
                free(fa);
649
        }
650 4004
        if (sa != NULL) {
651 312
                *e = vcc_expr_edit(tl, e1->fmt, "\v1\n})\v-", e1, NULL);
652
        } else {
653 3692
                *e = vcc_expr_edit(tl, e1->fmt, "\v1\n)\v-", e1, NULL);
654
        }
655 4004
        SkipToken(tl, ')');
656
}
657
658
659
/*--------------------------------------------------------------------
660
 */
661
662
void
663 314
vcc_Eval_Func(struct vcc *tl, const struct vjsn_val *spec,
664
    const char *extra, const struct symbol *sym)
665
{
666 314
        struct expr *e = NULL;
667
668 314
        vcc_func(tl, &e, spec, extra, sym);
669 314
        ERRCHK(tl);
670 314
        vcc_expr_fmt(tl->fb, tl->indent, e);
671 314
        VSB_cat(tl->fb, ";\n");
672 314
        vcc_delete_expr(e);
673
}
674
675
/*--------------------------------------------------------------------
676
 */
677
678
void v_matchproto_(sym_expr_t)
679 2774
vcc_Eval_SymFunc(struct vcc *tl, struct expr **e, struct token *t,
680
    struct symbol *sym, vcc_type_t fmt)
681
{
682
683
        (void)t;
684
        (void)fmt;
685 2774
        assert(sym->kind == SYM_FUNC);
686 2774
        AN(sym->eval_priv);
687
688 2774
        vcc_func(tl, e, sym->eval_priv, sym->extra, sym);
689 2774
        ERRCHK(tl);
690 2756
        if ((*e)->fmt == STRING) {
691 1348
                (*e)->fmt = STRINGS;
692 1348
                (*e)->nstr = 1;
693
        }
694
}
695
696
/*--------------------------------------------------------------------
697
 * SYNTAX:
698
 *    Expr4:
699
 *      '(' ExprCor ')'
700
 *      symbol
701
 *      CNUM
702
 *      FNUM
703
 *      CSTR
704
 */
705
706
static void
707 165178
vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
708
{
709
        struct expr *e1, *e2;
710
        const char *ip, *sign;
711
        struct token *t;
712
        struct symbol *sym;
713
        double d;
714
715 165178
        sign = "";
716 165178
        *e = NULL;
717 165178
        if (tl->t->tok == '(') {
718 167016
                SkipToken(tl, '(');
719 1842
                vcc_expr_cor(tl, &e2, fmt);
720 1842
                ERRCHK(tl);
721 1842
                SkipToken(tl, ')');
722 1842
                if (e2->fmt == STRINGS)
723 4
                        *e = e2;
724
                else
725 1838
                        *e = vcc_expr_edit(tl, e2->fmt, "(\v1)", e2, NULL);
726 1842
                return;
727
        }
728 163336
        switch (tl->t->tok) {
729
        case ID:
730 86398
                if (vcc_IdIs(tl->t, "default") && fmt == PROBE) {
731 0
                        vcc_NextToken(tl);
732 0
                        *e = vcc_mk_expr(PROBE, "%s", vcc_default_probe(tl));
733 0
                        return;
734
                }
735 86398
                if (vcc_IdIs(tl->t, "default") && fmt == BACKEND) {
736 4
                        vcc_NextToken(tl);
737 4
                        *e = vcc_mk_expr(BACKEND,
738
                            "*(VCL_conf.default_director)");
739 4
                        return;
740
                }
741 86394
                t = tl->t;
742 86394
                sym = VCC_SymbolGet(tl, SYM_NONE, "Symbol not found",
743
                    XREF_REF);
744 86394
                ERRCHK(tl);
745 86370
                AN(sym);
746 86370
                if (sym->kind == SYM_FUNC && sym->type == VOID) {
747 2
                        VSB_printf(tl->sb, "Function returns VOID:\n");
748 2
                        vcc_ErrWhere(tl, tl->t);
749 2
                        return;
750
                }
751 86368
                if (sym->eval != NULL) {
752 86364
                        AN(sym->eval);
753 86364
                        AZ(*e);
754 86364
                        sym->eval(tl, e, t, sym, fmt);
755 86364
                        ERRCHK(tl);
756
                        /* Unless asked for a HEADER, fold to string here */
757 86346
                        if (*e && fmt != HEADER && (*e)->fmt == HEADER) {
758 19636
                                vcc_expr_tostring(tl, e, STRINGS);
759 19636
                                ERRCHK(tl);
760
                        }
761 86346
                        return;
762
                }
763 4
                VSB_printf(tl->sb,
764
                    "Symbol type (%s) can not be used in expression.\n",
765 4
                    sym->kind->name);
766 4
                vcc_ErrWhere(tl, tl->t);
767 4
                if (sym->def_b != NULL) {
768 4
                        VSB_printf(tl->sb, "That symbol was defined here:\n");
769 4
                        vcc_ErrWhere(tl, sym->def_b);
770
                }
771 4
                return;
772
        case CSTR:
773 60686
                assert(fmt != VOID);
774 60686
                if (fmt == IP) {
775 54
                        if (*tl->t->dec == '/') {
776
                                /*
777
                                 * On some platforms (e.g. FreeBSD),
778
                                 * getaddrinfo(3) may resolve a path to a
779
                                 * sockaddr_un if it happens to exist and
780
                                 * is a socket. So don't let that happen.
781
                                 */
782 2
                                VSB_printf(tl->sb,
783
                                        "Cannot convert to an IP address: ");
784 2
                                vcc_ErrToken(tl, tl->t);
785 2
                                vcc_ErrWhere(tl, tl->t);
786 2
                                return;
787
                        }
788 52
                        Resolve_Sockaddr(tl, tl->t->dec, "80",
789
                            &ip, NULL, &ip, NULL, NULL, 1,
790 52
                            tl->t, "IP constant");
791 52
                        ERRCHK(tl);
792 46
                        e1 = vcc_mk_expr(IP, "%s", ip);
793 46
                        ERRCHK(tl);
794
                } else {
795 60632
                        e1 = vcc_new_expr(STRINGS);
796 60632
                        EncToken(e1->vsb, tl->t);
797 60632
                        AZ(VSB_finish(e1->vsb));
798 60632
                        e1->constant |= EXPR_STR_CONST;
799 60632
                        e1->nstr = 1;
800
                }
801 60678
                e1->t1 = tl->t;
802 60678
                e1->constant |= EXPR_CONST;
803 60678
                vcc_NextToken(tl);
804 60678
                *e = e1;
805 60678
                return;
806
        case '-':
807 88
                if (fmt != INT &&
808 2
                    fmt != REAL &&
809 0
                    fmt != DURATION &&
810
                    fmt != STRINGS)
811 0
                        break;
812 88
                vcc_NextToken(tl);
813 88
                if (tl->t->tok != FNUM && tl->t->tok != CNUM)
814 0
                        break;
815 88
                sign = "-";
816
                /* FALLTHROUGH */
817
        case FNUM:
818
        case CNUM:
819 16248
                assert(fmt != VOID);
820 16248
                if (fmt == BYTES) {
821 66
                        vcc_ByteVal(tl, &d);
822 66
                        ERRCHK(tl);
823 62
                        e1 = vcc_mk_expr(BYTES, "%.1f", d);
824
                } else {
825 16182
                        t = tl->t;
826 16182
                        vcc_NextToken(tl);
827 16182
                        if (tl->t->tok == ID) {
828 15124
                                e1 = vcc_mk_expr(DURATION, "(%s%.*s) * %g",
829 7562
                                    sign, PF(t), vcc_TimeUnit(tl));
830 7562
                                ERRCHK(tl);
831 8620
                        } else if (fmt == REAL || t->tok == FNUM) {
832 250
                                e1 = vcc_mk_expr(REAL, "%s%.*s", sign, PF(t));
833
                        } else {
834 8370
                                e1 = vcc_mk_expr(INT, "%s%.*s", sign, PF(t));
835
                        }
836
                }
837 16242
                e1->constant = EXPR_CONST;
838 16242
                *e = e1;
839 16242
                return;
840
        default:
841 4
                break;
842
        }
843 4
        VSB_printf(tl->sb, "Unknown token ");
844 4
        vcc_ErrToken(tl, tl->t);
845 4
        VSB_printf(tl->sb, " when looking for %s\n\n", vcc_utype(fmt));
846 4
        vcc_ErrWhere(tl, tl->t);
847
}
848
849
/*--------------------------------------------------------------------
850
 * SYNTAX:
851
 *    ExprMul:
852
 *      Expr4 { {'*'|'/'} Expr4 } *
853
 */
854
855
static void
856 165132
vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt)
857
{
858
        struct expr *e2;
859
        vcc_type_t f2;
860
        struct token *tk;
861
862 165132
        *e = NULL;
863 165132
        vcc_expr4(tl, e, fmt);
864 165202
        ERRCHK(tl);
865 165066
        AN(*e);
866
867 330176
        while (tl->t->tok == '*' || tl->t->tok == '/') {
868 48
                f2 = (*e)->fmt->multype;
869 48
                if (f2 == NULL) {
870 6
                        VSB_printf(tl->sb,
871
                            "Operator %.*s not possible on type %s.\n",
872 6
                            PF(tl->t), vcc_utype((*e)->fmt));
873 2
                        vcc_ErrWhere(tl, tl->t);
874 2
                        return;
875
                }
876 46
                tk = tl->t;
877 46
                vcc_NextToken(tl);
878 46
                vcc_expr4(tl, &e2, f2);
879 46
                ERRCHK(tl);
880 46
                if (e2->fmt != INT && e2->fmt != f2) {
881 6
                        VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
882 6
                            vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
883 2
                        vcc_ErrWhere(tl, tk);
884 2
                        return;
885
                }
886 44
                if (tk->tok == '*')
887 24
                        *e = vcc_expr_edit(tl, (*e)->fmt, "(\v1*\v2)", *e, e2);
888
                else
889 20
                        *e = vcc_expr_edit(tl, (*e)->fmt, "(\v1/\v2)", *e, e2);
890
        }
891
}
892
893
/*--------------------------------------------------------------------
894
 * SYNTAX:
895
 *    ExprAdd:
896
 *      ExprMul { {'+'|'-'} ExprMul } *
897
 */
898
899
static const struct adds {
900
        unsigned        op;
901
        vcc_type_t      a;
902
        vcc_type_t      b;
903
        vcc_type_t      fmt;
904
} vcc_adds[] = {
905
        { '+', BYTES,           BYTES,          BYTES },
906
        { '-', BYTES,           BYTES,          BYTES },
907
        { '+', DURATION,        DURATION,       DURATION },
908
        { '-', DURATION,        DURATION,       DURATION },
909
        { '+', INT,             INT,            INT },
910
        { '-', INT,             INT,            INT },
911
        { '+', INT,             REAL,           REAL },
912
        { '-', INT,             REAL,           REAL },
913
        { '+', REAL,            INT,            REAL },
914
        { '-', REAL,            INT,            REAL },
915
        { '+', REAL,            REAL,           REAL },
916
        { '-', REAL,            REAL,           REAL },
917
        { '-', TIME,            TIME,           DURATION },
918
        { '+', TIME,            DURATION,       TIME },
919
        { '-', TIME,            DURATION,       TIME },
920
921
        { EOI, VOID,            VOID,           VOID }
922
};
923
924
static void
925 118920
vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt)
926
{
927
        const struct adds *ap;
928
        struct expr  *e2;
929
        struct token *tk;
930
        int lit, n;
931
932 118920
        *e = NULL;
933 118920
        vcc_expr_mul(tl, e, fmt);
934 119012
        ERRCHK(tl);
935
936 283890
        while (tl->t->tok == '+' || tl->t->tok == '-') {
937 46212
                tk = tl->t;
938 714880
                for (ap = vcc_adds; ap->op != EOI; ap++)
939 670584
                        if (tk->tok == ap->op && (*e)->fmt == ap->a)
940 1916
                                break;
941 46212
                vcc_NextToken(tl);
942 46212
                if (ap->op == EOI && fmt == STRINGS)
943 44286
                        vcc_expr_mul(tl, &e2, STRINGS);
944
                else
945 1926
                        vcc_expr_mul(tl, &e2, (*e)->fmt);
946 46212
                ERRCHK(tl);
947
948 715124
                for (ap = vcc_adds; ap->op != EOI; ap++)
949 672754
                        if (tk->tok == ap->op && (*e)->fmt == ap->a &&
950 1946
                            e2->fmt == ap->b)
951 1896
                                break;
952
953 46212
                if (ap->op == '+') {
954 1862
                        *e = vcc_expr_edit(tl, ap->fmt, "(\v1 + \v2)", *e, e2);
955 44350
                } else if (ap->op == '-') {
956 34
                        *e = vcc_expr_edit(tl, ap->fmt, "(\v1 - \v2)", *e, e2);
957 88630
                } else if (tk->tok == '+' &&
958 44344
                    ((*e)->fmt == STRINGS || fmt == STRINGS)) {
959 44294
                        if ((*e)->fmt != STRINGS)
960 10
                                vcc_expr_tostring(tl, e, STRINGS);
961 44294
                        if (e2->fmt != STRINGS)
962 7276
                                vcc_expr_tostring(tl, &e2, STRINGS);
963 88588
                        if (vcc_islit(*e) && vcc_isconst(e2)) {
964 38
                                lit = vcc_islit(e2);
965 38
                                *e = vcc_expr_edit(tl, STRINGS,
966
                                    "\v1\n\v2", *e, e2);
967 38
                                (*e)->constant = EXPR_CONST;
968 38
                                (*e)->nstr = 1;
969 76
                                if (lit)
970 38
                                        (*e)->constant |= EXPR_STR_CONST;
971
                        } else {
972 44256
                                n = (*e)->nstr + e2->nstr;
973 44256
                                *e = vcc_expr_edit(tl, STRINGS,
974
                                    "\v1,\n\v2", *e, e2);
975 44256
                                (*e)->constant = EXPR_VAR;
976 44256
                                (*e)->nstr = n;
977
                        }
978
                } else {
979 66
                        VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
980 66
                            vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
981 22
                        vcc_ErrWhere2(tl, tk, tl->t);
982 22
                        return;
983
                }
984
        }
985
}
986
987
/*--------------------------------------------------------------------
988
 * SYNTAX:
989
 *    ExprCmp:
990
 *      ExprAdd
991
 *      ExprAdd Relation ExprAdd
992
 *      ExprAdd(STRING) '~' CString
993
 *      ExprAdd(STRING) '!~' CString
994
 *      ExprAdd(IP) '==' ExprAdd(IP)
995
 *      ExprAdd(IP) '!=' ExprAdd(IP)
996
 *      ExprAdd(IP) '~' ACL
997
 *      ExprAdd(IP) '!~' ACL
998
 */
999
1000
struct cmps;
1001
1002
typedef void cmp_f(struct vcc *, struct expr **, const struct cmps *);
1003
1004
struct cmps {
1005
        vcc_type_t              fmt;
1006
        unsigned                token;
1007
        cmp_f                   *func;
1008
        const char              *emit;
1009
};
1010
1011
static void v_matchproto_(cmp_f)
1012 7446
cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp)
1013
{
1014
        struct expr *e2;
1015
        struct token *tk;
1016
1017 7446
        tk = tl->t;
1018 7446
        vcc_NextToken(tl);
1019 7446
        vcc_expr_add(tl, &e2, (*e)->fmt);
1020 7446
        ERRCHK(tl);
1021
1022 7436
        if (e2->fmt != (*e)->fmt) {
1023 12
                VSB_printf(tl->sb,
1024
                    "Comparison of different types: %s '%.*s' %s\n",
1025 12
                    vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
1026 4
                vcc_ErrWhere(tl, tk);
1027
        } else
1028 7432
                *e = vcc_expr_edit(tl, BOOL, cp->emit, *e, e2);
1029
}
1030
1031
static void v_matchproto_(cmp_f)
1032 5510
cmp_regexp(struct vcc *tl, struct expr **e, const struct cmps *cp)
1033
{
1034
        char buf[128];
1035
        struct vsb vsb;
1036
1037 5510
        *e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL);
1038 5510
        vcc_NextToken(tl);
1039 5514
        ExpectErr(tl, CSTR);
1040 5508
        AN(VSB_new(&vsb, buf, sizeof buf, VSB_FIXEDLEN));
1041 5508
        VSB_printf(&vsb, "%sVRT_re_match(ctx, \v1, ", cp->emit);
1042 5508
        vcc_regexp(tl, &vsb);
1043 5508
        ERRCHK(tl);
1044 5506
        VSB_cat(&vsb, ")");
1045 5506
        AZ(VSB_finish(&vsb));
1046 5506
        *e = vcc_expr_edit(tl, BOOL, VSB_data(&vsb), *e, NULL);
1047
}
1048
1049
static void v_matchproto_(cmp_f)
1050 50
cmp_acl(struct vcc *tl, struct expr **e, const struct cmps *cp)
1051
{
1052
        struct symbol *sym;
1053
        char buf[256];
1054
1055 50
        vcc_NextToken(tl);
1056 50
        vcc_ExpectVid(tl, "ACL");
1057 50
        sym = VCC_SymbolGet(tl, SYM_ACL, SYMTAB_CREATE, XREF_REF);
1058 50
        ERRCHK(tl);
1059 42
        AN(sym);
1060 42
        VCC_GlobalSymbol(sym, ACL, ACL_SYMBOL_PREFIX);
1061 42
        bprintf(buf, "%sVRT_acl_match(ctx, %s, \v1)", cp->emit, sym->rname);
1062 42
        *e = vcc_expr_edit(tl, BOOL, buf, *e, NULL);
1063
}
1064
1065
static void v_matchproto_(cmp_f)
1066 24234
cmp_string(struct vcc *tl, struct expr **e, const struct cmps *cp)
1067
{
1068
        struct expr *e2;
1069
        struct token *tk;
1070
        char buf[128];
1071
1072 24234
        tk = tl->t;
1073 24234
        vcc_NextToken(tl);
1074 24234
        vcc_expr_add(tl, &e2, STRINGS);
1075 24234
        ERRCHK(tl);
1076 24234
        if (e2->fmt != STRINGS) {
1077 18
                VSB_printf(tl->sb,
1078
                    "Comparison of different types: %s '%.*s' %s\n",
1079 18
                    vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
1080 6
                vcc_ErrWhere(tl, tk);
1081 24228
        } else if ((*e)->nstr == 1 && e2->nstr == 1) {
1082 24190
                bprintf(buf, "(%s VRT_strcmp(\v1, \v2))", cp->emit);
1083 24190
                *e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
1084
        } else {
1085 38
                bprintf(buf, "(%s VRT_CompareStrands(\vT, \vt))", cp->emit);
1086 38
                *e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
1087
        }
1088
}
1089
1090
#define IDENT_REL(typ)                                                  \
1091
        {typ,           T_EQ,           cmp_simple, "(\v1 == \v2)" },   \
1092
        {typ,           T_NEQ,          cmp_simple, "(\v1 != \v2)" }
1093
1094
#define NUM_REL(typ)                                                    \
1095
        IDENT_REL(typ),                                                 \
1096
        {typ,           T_LEQ,          cmp_simple, "(\v1 <= \v2)" },   \
1097
        {typ,           T_GEQ,          cmp_simple, "(\v1 >= \v2)" },   \
1098
        {typ,           '<',            cmp_simple, "(\v1 < \v2)" },    \
1099
        {typ,           '>',            cmp_simple, "(\v1 > \v2)" }
1100
1101
static const struct cmps vcc_cmps[] = {
1102
        NUM_REL(INT),
1103
        NUM_REL(DURATION),
1104
        NUM_REL(BYTES),
1105
        NUM_REL(REAL),
1106
        NUM_REL(TIME),
1107
        IDENT_REL(BACKEND),
1108
        IDENT_REL(ACL),
1109
        IDENT_REL(PROBE),
1110
        IDENT_REL(STEVEDORE),
1111
        IDENT_REL(SUB),
1112
        IDENT_REL(INSTANCE),
1113
1114
        {IP,            T_EQ,           cmp_simple, "!VRT_ipcmp(\v1, \v2)" },
1115
        {IP,            T_NEQ,          cmp_simple, "VRT_ipcmp(\v1, \v2)" },
1116
1117
        {IP,            '~',            cmp_acl, "" },
1118
        {IP,            T_NOMATCH,      cmp_acl, "!" },
1119
1120
        {STRINGS,       T_EQ,           cmp_string, "0 =="},
1121
        {STRINGS,       T_NEQ,          cmp_string, "0 !="},
1122
        {STRINGS,       '<',            cmp_string, "0 > "},
1123
        {STRINGS,       '>',            cmp_string, "0 < "},
1124
        {STRINGS,       T_LEQ,          cmp_string, "0 >="},
1125
        {STRINGS,       T_GEQ,          cmp_string, "0 <="},
1126
1127
        {STRINGS,       '~',            cmp_regexp, "" },
1128
        {STRINGS,       T_NOMATCH,      cmp_regexp, "!" },
1129
1130
        {VOID,          0,              NULL, NULL}
1131
};
1132
1133
#undef IDENT_REL
1134
#undef NUM_REL
1135
1136
static void
1137 87240
vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1138
{
1139
        const struct cmps *cp;
1140
        struct token *tk;
1141
1142 87240
        *e = NULL;
1143 87240
        vcc_expr_add(tl, e, fmt);
1144 87240
        ERRCHK(tl);
1145 87158
        tk = tl->t;
1146
1147 87158
        if ((*e)->fmt == BOOL)
1148 6138
                return;
1149
1150 3919484
        for (cp = vcc_cmps; cp->fmt != VOID; cp++) {
1151 3875704
                if ((*e)->fmt == cp->fmt && tl->t->tok == cp->token) {
1152 37240
                        AN(cp->func);
1153 37240
                        cp->func(tl, e, cp);
1154 37240
                        return;
1155
                }
1156
        }
1157
1158 43780
        switch (tk->tok) {
1159
        case T_EQ:
1160
        case T_NEQ:
1161
        case '<':
1162
        case T_LEQ:
1163
        case '>':
1164
        case T_GEQ:
1165
        case '~':
1166
        case T_NOMATCH:
1167 12
                VSB_printf(tl->sb, "Operator %.*s not possible on %s\n",
1168 12
                    PF(tl->t), vcc_utype((*e)->fmt));
1169 4
                vcc_ErrWhere(tl, tl->t);
1170 4
                return;
1171
        default:
1172 43776
                break;
1173
        }
1174
}
1175
1176
/*--------------------------------------------------------------------
1177
 * SYNTAX:
1178
 *    ExprNot:
1179
 *      '!' ExprCmp
1180
 */
1181
1182
static void
1183 87240
vcc_expr_not(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1184
{
1185
        struct token *tk;
1186
1187 87240
        *e = NULL;
1188 87240
        tk = tl->t;
1189 87240
        if (tl->t->tok == '!')
1190 3732
                vcc_NextToken(tl);
1191 87240
        vcc_expr_cmp(tl, e, fmt);
1192 87240
        ERRCHK(tl);
1193 87122
        if (tk->tok != '!')
1194 83392
                return;
1195 3730
        vcc_expr_tobool(tl, e);
1196 3730
        ERRCHK(tl);
1197 3730
        if ((*e)->fmt != BOOL) {
1198 2
                VSB_printf(tl->sb, "'!' must be followed by BOOL, found ");
1199 2
                VSB_printf(tl->sb, "%s.\n", vcc_utype((*e)->fmt));
1200 2
                vcc_ErrWhere2(tl, tk, tl->t);
1201
        } else {
1202 3728
                *e = vcc_expr_edit(tl, BOOL, "!(\v1)", *e, NULL);
1203
        }
1204
}
1205
1206
/*--------------------------------------------------------------------
1207
 * CAND and COR are identical save for a few details, but they are
1208
 * stacked so handling them in the same function is not simpler.
1209
 * Instead have them both call this helper function to do everything.
1210
 */
1211
1212
typedef void upfunc(struct vcc *tl, struct expr **e, vcc_type_t fmt);
1213
1214
static void
1215 125548
vcc_expr_bin_bool(struct vcc *tl, struct expr **e, vcc_type_t fmt,
1216
    unsigned ourtok, upfunc *up, const char *tokstr)
1217
{
1218
        struct expr *e2;
1219
        struct token *tk;
1220
        char buf[32];
1221
1222 125548
        *e = NULL;
1223 125548
        tk = tl->t;
1224 125548
        up(tl, e, fmt);
1225 240200
        ERRCHK(tl);
1226 125304
        if (tl->t->tok != ourtok)
1227 114400
                return;
1228 10904
        vcc_expr_tobool(tl, e);
1229 10904
        ERRCHK(tl);
1230 10904
        if ((*e)->fmt != BOOL) {
1231 4
                VSB_printf(tl->sb,
1232
                    "'%s' must be preceeded by BOOL,"
1233 4
                    " found %s.\n", tokstr, vcc_utype((*e)->fmt));
1234 4
                vcc_ErrWhere2(tl, tk, tl->t);
1235 4
                return;
1236
        }
1237 10900
        *e = vcc_expr_edit(tl, BOOL, "(\v+\n\v1", *e, NULL);
1238 50796
        while (tl->t->tok == ourtok) {
1239 29000
                vcc_NextToken(tl);
1240 29000
                tk = tl->t;
1241 29000
                up(tl, &e2, fmt);
1242 29000
                ERRCHK(tl);
1243 29000
                vcc_expr_tobool(tl, &e2);
1244 29000
                ERRCHK(tl);
1245 29000
                if (e2->fmt != BOOL) {
1246 4
                        VSB_printf(tl->sb,
1247
                            "'%s' must be followed by BOOL,"
1248 4
                            " found %s.\n", tokstr, vcc_utype(e2->fmt));
1249 4
                        vcc_ErrWhere2(tl, tk, tl->t);
1250 4
                        vcc_delete_expr(e2);
1251 4
                        return;
1252
                }
1253 28996
                bprintf(buf, "\v1\v-\n%s\v+\n\v2", tokstr);
1254 28996
                *e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
1255
        }
1256 10896
        *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n)", *e, NULL);
1257
}
1258
1259
/*--------------------------------------------------------------------
1260
 * SYNTAX:
1261
 *    ExprCand:
1262
 *      ExprNot { '&&' ExprNot } *
1263
 */
1264
1265
static void
1266 67308
vcc_expr_cand(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1267
{
1268
1269 67308
        vcc_expr_bin_bool(tl, e, fmt, T_CAND, vcc_expr_not, "&&");
1270 67308
}
1271
1272
/*--------------------------------------------------------------------
1273
 * SYNTAX:
1274
 *    ExprCOR:
1275
 *      ExprCand { '||' ExprCand } *
1276
 */
1277
1278
static void
1279 58240
vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1280
{
1281
1282 58240
        vcc_expr_bin_bool(tl, e, fmt, T_COR, vcc_expr_cand, "||");
1283 58240
}
1284
1285
/*--------------------------------------------------------------------
1286
 * This function is the entry-point for getting an expression with
1287
 * a particular type, ready for inclusion in the VGC.
1288
 */
1289
1290
static void
1291 56398
vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1292
{
1293
        struct token *t1;
1294
1295 56398
        assert(fmt != VOID);
1296 56398
        assert(fmt != STRINGS);
1297 56398
        *e = NULL;
1298 56398
        t1 = tl->t;
1299 56398
        if (fmt->stringform)
1300 22978
                vcc_expr_cor(tl, e, STRINGS);
1301
        else
1302 33420
                vcc_expr_cor(tl, e, fmt);
1303 56398
        ERRCHK(tl);
1304 56270
        assert(!(*e)->fmt->stringform);
1305
1306 56270
        if ((*e)->fmt != STRINGS && fmt->stringform)
1307 2536
                vcc_expr_tostring(tl, e, STRINGS);
1308
1309 56270
        if ((*e)->fmt == STRINGS && fmt->stringform) {
1310 22932
                if (fmt == STRING_LIST)
1311 19438
                        (*e)->fmt = STRING_LIST;
1312 3494
                else if (fmt == STRING)
1313 2496
                        *e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL);
1314 998
                else if (fmt == STRANDS)
1315 998
                        *e = vcc_expr_edit(tl, STRANDS, "\vT", (*e), NULL);
1316
                else
1317 0
                        WRONG("Unhandled stringform");
1318
        }
1319
1320 56270
        if ((*e)->fmt == STRING_LIST)
1321 19438
                *e = vcc_expr_edit(tl, STRING_LIST,
1322
                    "\v+\n\v1,\nvrt_magic_string_end\v-", *e, NULL);
1323
1324 56270
        if (fmt == BOOL) {
1325 23248
                vcc_expr_tobool(tl, e);
1326 23248
                ERRCHK(tl);
1327
        }
1328
1329 56270
        if (fmt != (*e)->fmt)  {
1330 16
                VSB_printf(tl->sb, "Expression has type %s, expected %s\n",
1331 8
                    vcc_utype((*e)->fmt), vcc_utype(fmt));
1332 8
                vcc_ErrWhere2(tl, t1, tl->t);
1333 8
                return;
1334
        }
1335
}
1336
1337
/*--------------------------------------------------------------------
1338
 * This function parses and emits the C-code to evaluate an expression
1339
 *
1340
 * We know up front what kind of type we want the expression to be,
1341
 * and this function is the backstop if that doesn't succeed.
1342
 */
1343
1344
void
1345 52468
vcc_Expr(struct vcc *tl, vcc_type_t fmt)
1346
{
1347 52468
        struct expr *e = NULL;
1348
1349 52468
        assert(fmt != VOID);
1350 52468
        assert(fmt != STRINGS);
1351 52468
        vcc_expr0(tl, &e, fmt);
1352 52468
        ERRCHK(tl);
1353 52344
        assert(e->fmt == fmt);
1354
1355 52344
        vcc_expr_fmt(tl->fb, tl->indent, e);
1356 52344
        VSB_printf(tl->fb, "\n");
1357 52344
        vcc_delete_expr(e);
1358
}
1359
1360
/*--------------------------------------------------------------------
1361
 */
1362
1363
void v_matchproto_(sym_act_f)
1364 936
vcc_Act_Call(struct vcc *tl, struct token *t, struct symbol *sym)
1365
{
1366
1367
        struct expr *e;
1368
1369 936
        e = NULL;
1370 936
        vcc_func(tl, &e, sym->eval_priv, sym->extra, sym);
1371 936
        if (!tl->err) {
1372 932
                vcc_expr_fmt(tl->fb, tl->indent, e);
1373 932
                SkipToken(tl, ';');
1374 932
                VSB_cat(tl->fb, ";\n");
1375 4
        } else if (t != tl->t) {
1376 4
                vcc_ErrWhere2(tl, t, tl->t);
1377
        }
1378 936
        vcc_delete_expr(e);
1379
}
1380
1381
/*--------------------------------------------------------------------
1382
 */
1383
1384
void
1385 2144
vcc_Expr_Init(struct vcc *tl)
1386
{
1387
        struct symbol *sym;
1388
1389 2144
        sym = VCC_MkSym(tl, "regsub", SYM_FUNC, VCL_LOW, VCL_HIGH);
1390 2144
        AN(sym);
1391 2144
        sym->type = STRING;
1392 2144
        sym->eval = vcc_Eval_Regsub;
1393 2144
        sym->eval_priv = NULL;
1394
1395 2144
        sym = VCC_MkSym(tl, "regsuball", SYM_FUNC, VCL_LOW, VCL_HIGH);
1396 2144
        AN(sym);
1397 2144
        sym->type = STRING;
1398 2144
        sym->eval = vcc_Eval_Regsub;
1399 2144
        sym->eval_priv = sym;
1400
1401 2144
        sym = VCC_MkSym(tl, "true", SYM_FUNC, VCL_LOW, VCL_HIGH);
1402 2144
        AN(sym);
1403 2144
        sym->type = BOOL;
1404 2144
        sym->eval = vcc_Eval_BoolConst;
1405 2144
        sym->eval_priv = sym;
1406
1407 2144
        sym = VCC_MkSym(tl, "false", SYM_FUNC, VCL_LOW, VCL_HIGH);
1408 2144
        AN(sym);
1409 2144
        sym->type = BOOL;
1410 2144
        sym->eval = vcc_Eval_BoolConst;
1411 2144
        sym->eval_priv = NULL;
1412 2144
}