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
40
struct expr {
41
        unsigned        magic;
42
#define EXPR_MAGIC      0x38c794ab
43
        vcc_type_t      fmt;
44
        struct vsb      *vsb;
45
        uint8_t         constant;
46
#define EXPR_VAR        (1<<0)
47
#define EXPR_CONST      (1<<1)
48
#define EXPR_STR_CONST  (1<<2)          // Last STRING_LIST elem is "..."
49
        struct token    *t1, *t2;
50
        int             nstr;
51
};
52
53
/*--------------------------------------------------------------------
54
 * Facility for carrying expressions around and do text-processing on
55
 * them.
56
 */
57
58
static inline int
59 1612
vcc_isconst(const struct expr *e)
60
{
61 1612
        AN(e->constant);
62 1612
        return (e->constant & EXPR_CONST);
63
}
64
65
static inline int
66 18848
vcc_islit(const struct expr *e)
67
{
68 18848
        AN(e->constant);
69 18848
        return (e->constant & EXPR_STR_CONST);
70
}
71
72
static const char *
73 55
vcc_utype(vcc_type_t t)
74
{
75 55
        if (t == STRINGS || t == STRING_LIST)
76 19
                t = STRING;
77 55
        return (t->name);
78
}
79
80
static void vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt);
81
static void vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt);
82
83
static struct expr *
84 155096
vcc_new_expr(vcc_type_t fmt)
85
{
86
        struct expr *e;
87
88 155096
        ALLOC_OBJ(e, EXPR_MAGIC);
89 155096
        AN(e);
90 155096
        e->vsb = VSB_new_auto();
91 155096
        e->fmt = fmt;
92 155096
        e->constant = EXPR_VAR;
93 155096
        return (e);
94
}
95
96
static struct expr * v_printflike_(2, 3)
97 42591
vcc_mk_expr(vcc_type_t fmt, const char *str, ...)
98
{
99
        va_list ap;
100
        struct expr *e;
101
102 42591
        e = vcc_new_expr(fmt);
103 42591
        va_start(ap, str);
104 42591
        VSB_vprintf(e->vsb, str, ap);
105 42591
        va_end(ap);
106 42591
        AZ(VSB_finish(e->vsb));
107 42591
        return (e);
108
}
109
110
static void
111 194524
vcc_delete_expr(struct expr *e)
112
{
113 194524
        if (e == NULL)
114 234007
                return;
115 155041
        CHECK_OBJ_NOTNULL(e, EXPR_MAGIC);
116 155041
        VSB_destroy(&e->vsb);
117 155041
        FREE_OBJ(e);
118
}
119
120
/*--------------------------------------------------------------------
121
 * We want to get the indentation right in the emitted C code so we have
122
 * to represent it symbolically until we are ready to render.
123
 *
124
 * Many of the operations have very schematic output syntaxes, so we
125
 * use the same facility to simplify the text-processing of emitting
126
 * a given operation on two subexpressions.
127
 *
128
 * We use '\v' as the magic escape character.
129
 *      \v1  insert subexpression 1
130
 *      \v2  insert subexpression 2
131
 *      \vS  insert subexpression 1(STRINGS) as STRING
132
 *      \vT  insert subexpression 1(STRINGS) as STRANDS
133
 *      \vt  insert subexpression 1(STRINGS) as STRANDS
134
 *      \v+  increase indentation
135
 *      \v-  decrease indentation
136
 *      anything else is literal
137
 *
138
 * When editing, we check if any of the subexpressions contain a newline
139
 * and issue it as an indented block of so.
140
 *
141
 * XXX: check line lengths in edit, should pass indent in for this
142
 */
143
144
static struct expr *
145 86679
vcc_expr_edit(struct vcc *tl, vcc_type_t fmt, const char *p, struct expr *e1,
146
    struct expr *e2)
147
{
148
        struct expr *e, *e3;
149 86679
        int nl = 1;
150
151 86679
        AN(e1);
152 86679
        e = vcc_new_expr(fmt);
153 1190190
        while (*p != '\0') {
154 1016832
                if (*p != '\v') {
155 834525
                        if (*p != '\n' || !nl)
156 809494
                                VSB_putc(e->vsb, *p);
157 834525
                        nl = (*p == '\n');
158 834525
                        p++;
159 834525
                        continue;
160
                }
161 182307
                assert(*p == '\v');
162 182307
                switch (*++p) {
163 23387
                case '+': VSB_cat(e->vsb, "\v+"); break;
164 25043
                case '-': VSB_cat(e->vsb, "\v-"); break;
165
                case 'S':
166
                case 's':
167 6480
                        e3 = (*p == 'S' ? e1 : e2);
168 6480
                        AN(e3);
169 6480
                        assert(e1->fmt == STRINGS);
170 6480
                        if (e3->nstr > 1)
171 7
                                VSB_cat(e->vsb,
172
                                    "\nVRT_CollectString(ctx,\v+\n");
173 6480
                        VSB_cat(e->vsb, VSB_data(e3->vsb));
174 6480
                        if (e3->nstr > 1)
175 7
                                VSB_cat(e->vsb,
176
                                    ",\nvrt_magic_string_end)\v-\n");
177 6480
                        break;
178
                case 'T':
179
                case 't':
180 38
                        e3 = (*p == 'T' ? e1 : e2);
181 38
                        AN(e3);
182 38
                        VSB_printf(tl->curproc->prologue,
183
                            "  struct strands strs_%u_a;\n"
184
                            "  const char * strs_%u_s[%d];\n",
185
                            tl->unique, tl->unique, e3->nstr);
186 38
                        VSB_printf(e->vsb,
187
                            "\v+\nVRT_BundleStrands(%d, &strs_%u_a, strs_%u_s,"
188
                            "\v+\n%s,\nvrt_magic_string_end)\v-\v-",
189
                            e3->nstr, tl->unique, tl->unique,
190 38
                        VSB_data(e3->vsb));
191 38
                        tl->unique++;
192 38
                        break;
193
                case '1':
194 80180
                        VSB_cat(e->vsb, VSB_data(e1->vsb));
195 80180
                        break;
196
                case '2':
197 47179
                        AN(e2);
198 47179
                        VSB_cat(e->vsb, VSB_data(e2->vsb));
199 47179
                        break;
200
                default:
201 0
                        WRONG("Illegal edit in VCC expression");
202
                }
203 182307
                p++;
204
        }
205 86679
        AZ(VSB_finish(e->vsb));
206 86679
        e->t1 = e1->t1;
207 86679
        e->t2 = e1->t2;
208 86679
        if (e2 != NULL)
209 47198
                e->t2 = e2->t2;
210 86679
        vcc_delete_expr(e1);
211 86679
        vcc_delete_expr(e2);
212 86679
        return (e);
213
}
214
215
/*--------------------------------------------------------------------
216
 * Expand finished expression into C-source code
217
 */
218
219
static void
220 21164
vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1)
221
{
222
        char *p;
223
        int i;
224
225 202220
        for (i = 0; i < ind; i++)
226 181056
                VSB_cat(d, " ");
227 21164
        p = VSB_data(e1->vsb);
228 2350843
        while (*p != '\0') {
229 2308517
                if (*p == '\n') {
230 67972
                        VSB_putc(d, '\n');
231 67972
                        if (*++p == '\0')
232 2
                                break;
233 765056
                        for (i = 0; i < ind; i++)
234 697086
                                VSB_cat(d, " ");
235 2240545
                } else if (*p != '\v') {
236 2190299
                        VSB_putc(d, *p++);
237
                } else {
238 50246
                        switch (*++p) {
239 25123
                        case '+': ind += 2; break;
240 25123
                        case '-': ind -= 2; break;
241 0
                        default:  WRONG("Illegal format in VCC expression");
242
                        }
243 50246
                        p++;
244
                }
245
        }
246 21164
}
247
248
/*--------------------------------------------------------------------
249
 */
250
251
static void
252 11712
vcc_expr_tostring(struct vcc *tl, struct expr **e, vcc_type_t fmt)
253
{
254
        const char *p;
255 11712
        uint8_t constant = EXPR_VAR;
256
257 11712
        CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC);
258 11712
        assert(fmt == STRINGS || fmt == STRING_LIST || fmt == STRING);
259 11712
        assert(fmt != (*e)->fmt);
260
261 11712
        p = (*e)->fmt->tostring;
262 11712
        if (p != NULL) {
263 11711
                AN(*p);
264 11711
                *e = vcc_expr_edit(tl, fmt, p, *e, NULL);
265 11711
                (*e)->constant = constant;
266 11711
                (*e)->nstr = 1;
267
        } else {
268 1
                if ((*e)->fmt == BLOB)
269 1
                        VSB_printf(tl->sb,
270
                            "Wrong use of BLOB value.\n"
271
                            "BLOBs can only be used as arguments to VMOD"
272
                            " functions.\n");
273
                else
274 0
                        VSB_printf(tl->sb,
275
                            "Cannot convert %s to STRING.\n",
276 0
                            vcc_utype((*e)->fmt));
277 1
                vcc_ErrWhere2(tl, (*e)->t1, tl->t);
278
        }
279 11712
}
280
281
/*--------------------------------------------------------------------
282
 */
283
284
static void v_matchproto_(sym_expr_t)
285 28
vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym,
286
    vcc_type_t fmt)
287
{
288
        struct expr *e2;
289 28
        int all = sym->eval_priv == NULL ? 0 : 1;
290
        const char *p;
291
        char buf[128];
292
293
        (void)fmt;
294 28
        SkipToken(tl, ID);
295 28
        SkipToken(tl, '(');
296 28
        vcc_expr0(tl, &e2, STRING);
297 28
        ERRCHK(tl);
298 28
        SkipToken(tl, ',');
299 28
        ExpectErr(tl, CSTR);
300 28
        p = vcc_regexp(tl);
301 28
        bprintf(buf, "VRT_regsub(ctx, %d,\v+\n\v1,\n%s", all, p);
302 28
        *e = vcc_expr_edit(tl, STRING, buf, e2, NULL);
303 28
        SkipToken(tl, ',');
304 28
        vcc_expr0(tl, &e2, STRING);
305 28
        ERRCHK(tl);
306 28
        *e = vcc_expr_edit(tl, STRINGS, "\v1,\n\v2)\v-", *e, e2);
307 28
        (*e)->nstr = 1;
308 28
        SkipToken(tl, ')');
309
}
310
311
/*--------------------------------------------------------------------
312
 */
313
314
static void v_matchproto_(sym_expr_t)
315 951
vcc_Eval_BoolConst(struct vcc *tl, struct expr **e, const struct symbol *sym,
316
    vcc_type_t fmt)
317
{
318
319
        (void)fmt;
320 951
        vcc_NextToken(tl);
321 951
        *e = vcc_mk_expr(BOOL, "(0==%d)", sym->eval_priv == NULL ? 1 : 0);
322 951
        (*e)->constant = EXPR_CONST;
323 951
}
324
325
/*--------------------------------------------------------------------
326
 */
327
328
void v_matchproto_(sym_expr_t)
329 196
vcc_Eval_Handle(struct vcc *tl, struct expr **e, const struct symbol *sym,
330
    vcc_type_t fmt)
331
{
332
333 196
        AN(sym->rname);
334
335 196
        if (sym->fmt != STRING && fmt == STRINGS) {
336 2
                (void)vcc_AddRef(tl, tl->t, sym->kind);
337 2
                *e = vcc_mk_expr(STRINGS, "\"%s\"", sym->name);
338 2
                (*e)->nstr = 1;
339 2
                (*e)->constant |= EXPR_CONST | EXPR_STR_CONST;
340
        } else {
341 194
                vcc_ExpectVid(tl, "handle");
342 194
                (void)vcc_AddRef(tl, tl->t, sym->kind);
343 194
                *e = vcc_mk_expr(sym->fmt, "%s", sym->rname);
344 194
                (*e)->constant = EXPR_VAR;
345 194
                (*e)->nstr = 1;
346 194
                if ((*e)->fmt == STRING)
347 0
                        (*e)->fmt = STRINGS;
348
        }
349 196
        vcc_NextToken(tl);
350 196
}
351
352
/*--------------------------------------------------------------------
353
 */
354
355
void v_matchproto_(sym_expr_t)
356 32058
vcc_Eval_Var(struct vcc *tl, struct expr **e, const struct symbol *sym,
357
    vcc_type_t fmt)
358
{
359
360
        (void)fmt;
361 32058
        assert(sym->kind == SYM_VAR);
362 32058
        vcc_AddUses(tl, tl->t, sym->r_methods, "Not available");
363 64116
        ERRCHK(tl);
364 32058
        *e = vcc_mk_expr(sym->fmt, "%s", sym->rname);
365 32058
        (*e)->constant = EXPR_VAR;
366 32058
        (*e)->nstr = 1;
367 32058
        if ((*e)->fmt == STRING)
368 16476
                (*e)->fmt = STRINGS;
369 32058
        vcc_NextToken(tl);
370
}
371
372
/*--------------------------------------------------------------------
373
 */
374
375
static struct expr *
376 179
vcc_priv_arg(struct vcc *tl, const char *p, const char *name, const char *vmod)
377
{
378
        struct expr *e2;
379
        char buf[32];
380
        struct inifin *ifp;
381
382
        (void)name;
383 179
        if (!strcmp(p, "PRIV_VCL")) {
384 3
                e2 = vcc_mk_expr(VOID, "&vmod_priv_%s", vmod);
385 176
        } else if (!strcmp(p, "PRIV_CALL")) {
386 9
                bprintf(buf, "vmod_priv_%u", tl->unique++);
387 9
                ifp = New_IniFin(tl);
388 9
                Fh(tl, 0, "static struct vmod_priv %s;\n", buf);
389 9
                VSB_printf(ifp->fin, "\tVRT_priv_fini(&%s);", buf);
390 9
                e2 = vcc_mk_expr(VOID, "&%s", buf);
391 167
        } else if (!strcmp(p, "PRIV_TASK")) {
392 163
                e2 = vcc_mk_expr(VOID,
393
                    "VRT_priv_task(ctx, &VGC_vmod_%s)", vmod);
394 4
        } else if (!strcmp(p, "PRIV_TOP")) {
395 4
                e2 = vcc_mk_expr(VOID,
396
                    "VRT_priv_top(ctx, &VGC_vmod_%s)", vmod);
397
        } else {
398 0
                WRONG("Wrong PRIV_ type");
399
        }
400 179
        return (e2);
401
}
402
403
struct func_arg {
404
        vcc_type_t              type;
405
        const char              *enum_bits;
406
        const char              *cname;
407
        const char              *name;
408
        const char              *val;
409
        struct expr             *result;
410
        VTAILQ_ENTRY(func_arg)  list;
411
};
412
413
static void
414 1664
vcc_do_enum(struct vcc *tl, struct func_arg *fa, int len, const char *ptr)
415
{
416
        const char *r;
417
418
        (void)tl;
419 1664
        r = strchr(fa->cname, '.');
420 1664
        AN(r);
421 3328
        fa->result = vcc_mk_expr(VOID, "*%.*s.enum_%.*s",
422 1664
            (int)(r - fa->cname), fa->cname, len, ptr);
423 1664
}
424
425
static void
426 2868
vcc_do_arg(struct vcc *tl, struct func_arg *fa)
427
{
428
        const char *p, *r;
429
        struct expr *e2;
430
431 2868
        if (fa->type == ENUM) {
432 1209
                ExpectErr(tl, ID);
433 1202
                ERRCHK(tl);
434 1202
                r = p = fa->enum_bits;
435
                do {
436 3793
                        if (vcc_IdIs(tl->t, p))
437 1200
                                break;
438 2593
                        p += strlen(p) + 1;
439 2593
                } while (*p != '\1');
440 1202
                if (*p == '\1') {
441 2
                        VSB_printf(tl->sb, "Wrong enum value.");
442 2
                        VSB_printf(tl->sb, "  Expected one of:\n");
443
                        do {
444 8
                                VSB_printf(tl->sb, "\t%s\n", r);
445 8
                                r += strlen(r) + 1;
446 8
                        } while (*r != '\0' && *r != '\1');
447 2
                        vcc_ErrWhere(tl, tl->t);
448 2
                        return;
449
                }
450 1200
                vcc_do_enum(tl, fa, PF(tl->t));
451 1200
                SkipToken(tl, ID);
452
        } else {
453 1666
                vcc_expr0(tl, &e2, fa->type);
454 1666
                ERRCHK(tl);
455 1661
                assert(e2->fmt == fa->type);
456 1661
                fa->result = e2;
457
        }
458
}
459
460
static void
461 1665
vcc_func(struct vcc *tl, struct expr **e, const char *spec,
462
    const char *extra, const struct symbol *sym)
463
{
464
        vcc_type_t rfmt;
465
        const char *args;
466
        const char *cfunc;
467
        const char *p;
468
        struct expr *e1;
469
        struct func_arg *fa, *fa2;
470
        VTAILQ_HEAD(,func_arg) head;
471
        struct token *t1;
472
473 1665
        rfmt = VCC_Type(spec);
474 1665
        spec += strlen(spec) + 1;
475 1665
        cfunc = spec;
476 1665
        spec += strlen(spec) + 1;
477 1665
        args = spec;
478 1675
        SkipToken(tl, '(');
479 1665
        p = args;
480 1665
        if (extra == NULL)
481 1058
                extra = "";
482 1665
        AN(rfmt);
483 1665
        VTAILQ_INIT(&head);
484 7375
        while (*p != '\0') {
485 4045
                fa = calloc(1, sizeof *fa);
486 4045
                AN(fa);
487 4045
                fa->cname = cfunc;
488 4045
                VTAILQ_INSERT_TAIL(&head, fa, list);
489 4045
                if (!memcmp(p, "PRIV_", 5)) {
490 179
                        fa->result = vcc_priv_arg(tl, p, sym->name, sym->vmod);
491 179
                        fa->name = "";
492 179
                        p += strlen(p) + 1;
493 179
                        continue;
494
                }
495 3866
                fa->type = VCC_Type(p);
496 3866
                AN(fa->type);
497 3866
                p += strlen(p) + 1;
498 3866
                if (*p == '\1') {
499 1670
                        fa->enum_bits = ++p;
500 11395
                        while (*p != '\1')
501 8055
                                p += strlen(p) + 1;
502 1670
                        p++;
503 1670
                        assert(*p == '\0');
504 1670
                        p++;
505
                }
506 3866
                if (*p == '\2') {
507 3639
                        fa->name = p + 1;
508 3639
                        p += strlen(p) + 1;
509
                }
510 3866
                if (*p == '\3') {
511 2474
                        fa->val = p + 1;
512 2474
                        p += strlen(p) + 1;
513
                }
514 3866
                assert(*p == 0 || *p > ' ');
515
        }
516
517 3118
        VTAILQ_FOREACH(fa, &head, list) {
518 2914
                if (tl->t->tok == ')')
519 46
                        break;
520 2868
                if (fa->result != NULL)
521 149
                        continue;
522 2719
                if (tl->t->tok == ID) {
523 2192
                        t1 = VTAILQ_NEXT(tl->t, list);
524 2192
                        if (t1->tok == '=')
525 625
                                break;
526
                }
527 2094
                vcc_do_arg(tl, fa);
528 2094
                ERRCHK(tl);
529 2088
                if (tl->t->tok == ')')
530 784
                        break;
531 1304
                SkipToken(tl, ',');
532
        }
533 3469
        while (tl->t->tok == ID) {
534 2485
                VTAILQ_FOREACH(fa, &head, list) {
535 2484
                        if (fa->name == NULL)
536 0
                                continue;
537 2484
                        if (vcc_IdIs(tl->t, fa->name))
538 775
                                break;
539
                }
540 776
                if (fa == NULL) {
541 2
                        VSB_printf(tl->sb, "Unknown argument '%.*s'\n",
542 2
                            PF(tl->t));
543 1
                        vcc_ErrWhere(tl, tl->t);
544 1
                        return;
545
                }
546 775
                if (fa->result != NULL) {
547 1
                        VSB_printf(tl->sb, "Argument '%s' already used\n",
548
                            fa->name);
549 1
                        vcc_ErrWhere(tl, tl->t);
550 1
                        return;
551
                }
552 774
                vcc_NextToken(tl);
553 774
                SkipToken(tl, '=');
554 774
                vcc_do_arg(tl, fa);
555 774
                ERRCHK(tl);
556 773
                if (tl->t->tok == ')')
557 622
                        break;
558 151
                SkipToken(tl, ',');
559
        }
560
561 1656
        e1 = vcc_mk_expr(rfmt, "%s(ctx%s\v+", cfunc, extra);
562 5676
        VTAILQ_FOREACH_SAFE(fa, &head, list, fa2) {
563 4020
                if (fa->result == NULL && fa->type == ENUM && fa->val != NULL)
564 464
                        vcc_do_enum(tl, fa, strlen(fa->val), fa->val);
565 4020
                if (fa->result == NULL && fa->val != NULL)
566 520
                        fa->result = vcc_mk_expr(fa->type, "%s", fa->val);
567 4020
                if (fa->result != NULL)
568 4019
                        e1 = vcc_expr_edit(tl, e1->fmt, "\v1,\n\v2",
569
                            e1, fa->result);
570
                else {
571 1
                        VSB_printf(tl->sb, "Argument '%s' missing\n",
572
                            fa->name);
573 1
                        vcc_ErrWhere(tl, tl->t);
574
                }
575 4020
                free(fa);
576
        }
577 1656
        *e = vcc_expr_edit(tl, e1->fmt, "\v1\n)\v-", e1, NULL);
578 1656
        SkipToken(tl, ')');
579
}
580
581
/*--------------------------------------------------------------------
582
 */
583
584
void
585 115
vcc_Eval_Func(struct vcc *tl, const char *spec,
586
    const char *extra, const struct symbol *sym)
587
{
588 115
        struct expr *e = NULL;
589
590 115
        vcc_func(tl, &e, spec, extra, sym);
591 230
        ERRCHK(tl);
592 115
        vcc_expr_fmt(tl->fb, tl->indent, e);
593 115
        VSB_cat(tl->fb, ";\n");
594 115
        vcc_delete_expr(e);
595
}
596
597
/*--------------------------------------------------------------------
598
 */
599
600
void v_matchproto_(sym_expr_t)
601 1550
vcc_Eval_SymFunc(struct vcc *tl, struct expr **e, const struct symbol *sym,
602
    vcc_type_t fmt)
603
{
604
605
        (void)fmt;
606 1550
        assert(sym->kind == SYM_FUNC);
607 1550
        AN(sym->eval_priv);
608
609 1550
        SkipToken(tl, ID);
610 1550
        assert(sym->fmt == VCC_Type(sym->eval_priv));
611 1550
        vcc_func(tl, e, sym->eval_priv, sym->extra, sym);
612 1550
        ERRCHK(tl);
613 1540
        if ((*e)->fmt == STRING) {
614 611
                (*e)->fmt = STRINGS;
615 611
                (*e)->nstr = 1;
616
        }
617
}
618
619
/*--------------------------------------------------------------------
620
 * SYNTAX:
621
 *    Expr4:
622
 *      '(' ExprCor ')'
623
 *      symbol
624
 *      CNUM
625
 *      CSTR
626
 */
627
628
static void
629 66416
vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
630
{
631
        struct expr *e1, *e2;
632
        const char *ip, *sign;
633
        const struct symbol *sym;
634
        enum symkind kind;
635
        double d;
636
        int i;
637
638 66416
        sign = "";
639 66416
        *e = NULL;
640 66416
        if (tl->t->tok == '(') {
641 67195
                SkipToken(tl, '(');
642 781
                vcc_expr_cor(tl, &e2, fmt);
643 781
                ERRCHK(tl);
644 781
                SkipToken(tl, ')');
645 781
                if (e2->fmt == STRINGS)
646 2
                        *e = e2;
647
                else
648 779
                        *e = vcc_expr_edit(tl, e2->fmt, "(\v1)", e2, NULL);
649 781
                return;
650
        }
651 65635
        switch (tl->t->tok) {
652
        case ID:
653
                /*
654
                 * XXX: what if var and func/proc had same name ?
655
                 * XXX: look for SYM_VAR first for consistency ?
656
                 */
657 34435
                sym = NULL;
658 34435
                kind = VCC_HandleKind(fmt);
659 34435
                if (kind != SYM_NONE)
660 273
                        sym = VCC_SymbolTok(tl, NULL, tl->t, kind, 0);
661 34435
                if (sym == NULL)
662 34243
                        sym = VCC_SymbolTok(tl, NULL, tl->t, SYM_NONE, 0);
663 34435
                if (sym == NULL || sym->eval == NULL) {
664 8
                        VSB_printf(tl->sb, "Symbol not found: ");
665 8
                        vcc_ErrToken(tl, tl->t);
666 8
                        VSB_printf(tl->sb, " (expected type %s):\n",
667
                            vcc_utype(fmt));
668 8
                        vcc_ErrWhere(tl, tl->t);
669 8
                        return;
670
                }
671 34427
                AN(sym);
672 34427
                if (sym->kind == SYM_FUNC && sym->fmt == VOID) {
673 1
                        VSB_printf(tl->sb, "Function returns VOID:\n");
674 1
                        vcc_ErrWhere(tl, tl->t);
675 1
                        return;
676
                }
677 34426
                switch (sym->kind) {
678
                case SYM_VAR:
679
                case SYM_FUNC:
680
                case SYM_ACL:
681
                case SYM_BACKEND:
682
                case SYM_STEVEDORE:
683
                case SYM_PROBE:
684 34426
                        AN(sym->eval);
685 34426
                        AZ(*e);
686 34426
                        sym->eval(tl, e, sym, fmt);
687 34426
                        ERRCHK(tl);
688
                        /* Unless asked for a HEADER, fold to string here */
689 34418
                        if (*e && fmt != HEADER && (*e)->fmt == HEADER) {
690 7595
                                vcc_expr_tostring(tl, e, STRINGS);
691 7595
                                ERRCHK(tl);
692
                        }
693 34418
                        return;
694
                default:
695 0
                        break;
696
                }
697 0
                VSB_printf(tl->sb,
698
                    "Symbol type (%s) can not be used in expression.\n",
699
                    VCC_SymKind(tl, sym));
700 0
                vcc_ErrWhere(tl, tl->t);
701 0
                return;
702
        case CSTR:
703 25850
                assert(fmt != VOID);
704 25850
                if (fmt == IP) {
705 24
                        Resolve_Sockaddr(tl, tl->t->dec, "80",
706
                            &ip, NULL, &ip, NULL, NULL, 1,
707 24
                            tl->t, "IP constant");
708 24
                        ERRCHK(tl);
709 21
                        e1 = vcc_mk_expr(IP, "%s", ip);
710 21
                        ERRCHK(tl);
711
                } else {
712 25826
                        e1 = vcc_new_expr(STRINGS);
713 25826
                        EncToken(e1->vsb, tl->t);
714 25826
                        AZ(VSB_finish(e1->vsb));
715 25826
                        e1->constant |= EXPR_STR_CONST;
716 25826
                        e1->nstr = 1;
717
                }
718 25847
                e1->t1 = tl->t;
719 25847
                e1->constant |= EXPR_CONST;
720 25847
                vcc_NextToken(tl);
721 25847
                *e = e1;
722 25847
                return;
723
        case '-':
724 21
                if (fmt != INT && fmt != REAL && fmt != DURATION)
725 0
                        break;
726 21
                vcc_NextToken(tl);
727 21
                ExpectErr(tl, CNUM);
728 21
                sign = "-";
729
                /* FALLTHROUGH */
730
        case CNUM:
731
                /*
732
                 * XXX: %g may not have enough decimals by default
733
                 * XXX: but %a is ugly, isn't it ?
734
                 */
735 5348
                assert(fmt != VOID);
736 5348
                if (fmt == BYTES) {
737 31
                        vcc_ByteVal(tl, &d);
738 31
                        ERRCHK(tl);
739 29
                        e1 = vcc_mk_expr(BYTES, "%.1f", d);
740
                } else {
741 5317
                        vcc_NumVal(tl, &d, &i);
742 5317
                        ERRCHK(tl);
743 5317
                        if (tl->t->tok == ID) {
744 3213
                                e1 = vcc_mk_expr(DURATION, "%s%g",
745 3213
                                    sign, d * vcc_TimeUnit(tl));
746 3213
                                ERRCHK(tl);
747 2104
                        } else if (i || fmt == REAL)
748 103
                                e1 = vcc_mk_expr(REAL, "%s%f", sign, d);
749
                        else
750 2001
                                e1 = vcc_mk_expr(INT, "%s%ld",
751
                                    sign, (unsigned long)d);
752
                }
753 5345
                e1->constant = EXPR_CONST;
754 5345
                *e = e1;
755 5345
                return;
756
        default:
757 2
                break;
758
        }
759 2
        VSB_printf(tl->sb, "Unknown token ");
760 2
        vcc_ErrToken(tl, tl->t);
761 2
        VSB_printf(tl->sb, " when looking for %s\n\n", vcc_utype(fmt));
762 2
        vcc_ErrWhere(tl, tl->t);
763
}
764
765
/*--------------------------------------------------------------------
766
 * SYNTAX:
767
 *    ExprMul:
768
 *      Expr4 { {'*'|'/'} Expr4 } *
769
 */
770
771
static void
772 66397
vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt)
773
{
774
        struct expr *e2;
775
        vcc_type_t f2;
776
        struct token *tk;
777
778 66397
        *e = NULL;
779 66397
        vcc_expr4(tl, e, fmt);
780 66424
        ERRCHK(tl);
781 66372
        AN(*e);
782
783 132762
        while (tl->t->tok == '*' || tl->t->tok == '/') {
784 20
                f2 = (*e)->fmt->multype;
785 20
                if (f2 == NULL) {
786 3
                        VSB_printf(tl->sb,
787
                            "Operator %.*s not possible on type %s.\n",
788 3
                            PF(tl->t), vcc_utype((*e)->fmt));
789 1
                        vcc_ErrWhere(tl, tl->t);
790 1
                        return;
791
                }
792 19
                tk = tl->t;
793 19
                vcc_NextToken(tl);
794 19
                vcc_expr4(tl, &e2, f2);
795 19
                ERRCHK(tl);
796 19
                if (e2->fmt != INT && e2->fmt != f2) {
797 3
                        VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
798 3
                            vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
799 1
                        vcc_ErrWhere(tl, tk);
800 1
                        return;
801
                }
802 18
                if (tk->tok == '*')
803 10
                        *e = vcc_expr_edit(tl, (*e)->fmt, "(\v1*\v2)", *e, e2);
804
                else
805 8
                        *e = vcc_expr_edit(tl, (*e)->fmt, "(\v1/\v2)", *e, e2);
806
        }
807
}
808
809
/*--------------------------------------------------------------------
810
 * SYNTAX:
811
 *    ExprAdd:
812
 *      ExprMul { {'+'|'-'} ExprMul } *
813
 */
814
815
static const struct adds {
816
        unsigned        op;
817
        vcc_type_t      a;
818
        vcc_type_t      b;
819
        vcc_type_t      fmt;
820
} vcc_adds[] = {
821
        { '+', BYTES,           BYTES,          BYTES },
822
        { '-', BYTES,           BYTES,          BYTES },
823
        { '+', DURATION,        DURATION,       DURATION },
824
        { '-', DURATION,        DURATION,       DURATION },
825
        { '+', INT,             INT,            INT },
826
        { '-', INT,             INT,            INT },
827
        { '+', INT,             REAL,           REAL },
828
        { '-', INT,             REAL,           REAL },
829
        { '+', REAL,            INT,            REAL },
830
        { '-', REAL,            INT,            REAL },
831
        { '+', REAL,            REAL,           REAL },
832
        { '-', REAL,            REAL,           REAL },
833
        { '-', TIME,            TIME,           DURATION },
834
        { '+', TIME,            DURATION,       TIME },
835
        { '-', TIME,            DURATION,       TIME },
836
837
        { EOI, VOID,            VOID,           VOID }
838
};
839
840
static void
841 46746
vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt)
842
{
843
        const struct adds *ap;
844
        struct expr  *e2;
845
        struct token *tk;
846
        int lit, n;
847
848 46746
        *e = NULL;
849 46746
        vcc_expr_mul(tl, e, fmt);
850 46784
        ERRCHK(tl);
851
852 113078
        while (tl->t->tok == '+' || tl->t->tok == '-') {
853 19651
                tk = tl->t;
854 303966
                for (ap = vcc_adds; ap->op != EOI; ap++)
855 285133
                        if (tk->tok == ap->op && (*e)->fmt == ap->a)
856 818
                                break;
857 19651
                vcc_NextToken(tl);
858 19651
                if (ap->op == EOI && fmt == STRINGS)
859 18828
                        vcc_expr_mul(tl, &e2, STRINGS);
860
                else
861 823
                        vcc_expr_mul(tl, &e2, (*e)->fmt);
862 19651
                ERRCHK(tl);
863
864 304088
                for (ap = vcc_adds; ap->op != EOI; ap++)
865 286078
                        if (tk->tok == ap->op && (*e)->fmt == ap->a &&
866 833
                            e2->fmt == ap->b)
867 808
                                break;
868
869 19651
                if (ap->op == '+') {
870 795
                        *e = vcc_expr_edit(tl, ap->fmt, "(\v1 + \v2)", *e, e2);
871 18856
                } else if (ap->op == '-') {
872 13
                        *e = vcc_expr_edit(tl, ap->fmt, "(\v1 - \v2)", *e, e2);
873 37685
                } else if (tk->tok == '+' &&
874 18857
                    ((*e)->fmt == STRINGS || fmt == STRINGS)) {
875 18832
                        if ((*e)->fmt != STRINGS)
876 5
                                vcc_expr_tostring(tl, e, STRINGS);
877 18832
                        if (e2->fmt != STRINGS)
878 3097
                                vcc_expr_tostring(tl, &e2, STRINGS);
879 37664
                        if (vcc_islit(*e) && vcc_isconst(e2)) {
880 16
                                lit = vcc_islit(e2);
881 16
                                *e = vcc_expr_edit(tl, STRINGS,
882
                                    "\v1\n\v2", *e, e2);
883 16
                                (*e)->constant = EXPR_CONST;
884 32
                                if (lit)
885 16
                                        (*e)->constant |= EXPR_STR_CONST;
886
                        } else {
887 18816
                                n = (*e)->nstr + e2->nstr;
888 18816
                                *e = vcc_expr_edit(tl, STRINGS,
889
                                    "\v1,\n\v2", *e, e2);
890 18816
                                (*e)->constant = EXPR_VAR;
891 18816
                                (*e)->nstr = n;
892
                        }
893
                } else {
894 33
                        VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
895 33
                            vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
896 11
                        vcc_ErrWhere2(tl, tk, tl->t);
897 11
                        return;
898
                }
899
        }
900
}
901
902
/*--------------------------------------------------------------------
903
 * SYNTAX:
904
 *    ExprCmp:
905
 *      ExprAdd
906
 *      ExprAdd Relation ExprAdd
907
 *      ExprAdd(STRING) '~' CString
908
 *      ExprAdd(STRING) '!~' CString
909
 *      ExprAdd(IP) '==' ExprAdd(IP)
910
 *      ExprAdd(IP) '!=' ExprAdd(IP)
911
 *      ExprAdd(IP) '~' ACL
912
 *      ExprAdd(IP) '!~' ACL
913
 */
914
915
struct cmps;
916
917
typedef void cmp_f(struct vcc *, struct expr **, const struct cmps *);
918
919
struct cmps {
920
        vcc_type_t              fmt;
921
        unsigned                token;
922
        cmp_f                   *func;
923
        const char              *emit;
924
};
925
926
static void v_matchproto_(cmp_f)
927 2400
cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp)
928
{
929
        struct expr *e2;
930
        struct token *tk;
931
932 2400
        tk = tl->t;
933 2400
        vcc_NextToken(tl);
934 2400
        vcc_expr_add(tl, &e2, (*e)->fmt);
935 4800
        ERRCHK(tl);
936
937 2395
        if (e2->fmt != (*e)->fmt) {
938 6
                VSB_printf(tl->sb,
939
                    "Comparison of different types: %s '%.*s' %s\n",
940 6
                    vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
941 2
                vcc_ErrWhere(tl, tk);
942
        } else
943 2393
                *e = vcc_expr_edit(tl, BOOL, cp->emit, *e, e2);
944
}
945
946
static void v_matchproto_(cmp_f)
947 1567
cmp_regexp(struct vcc *tl, struct expr **e, const struct cmps *cp)
948
{
949
        char buf[128];
950
        const char *re;
951
952 1567
        *e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL);
953 1567
        vcc_NextToken(tl);
954 1569
        ExpectErr(tl, CSTR);
955 1566
        re = vcc_regexp(tl);
956 1566
        ERRCHK(tl);
957 1565
        bprintf(buf, "%sVRT_re_match(ctx, \v1, %s)", cp->emit, re);
958 1565
        *e = vcc_expr_edit(tl, BOOL, buf, *e, NULL);
959
}
960
961
static void v_matchproto_(cmp_f)
962 12
cmp_acl(struct vcc *tl, struct expr **e, const struct cmps *cp)
963
{
964
        struct symbol *sym;
965
        char buf[256];
966
967 12
        vcc_NextToken(tl);
968 12
        vcc_ExpectVid(tl, "ACL");
969 12
        sym = vcc_AddRef(tl, tl->t, SYM_ACL);
970 12
        vcc_NextToken(tl);
971 12
        VCC_GlobalSymbol(sym, ACL, ACL_SYMBOL_PREFIX);
972 12
        bprintf(buf, "%sVRT_acl_match(ctx, %s, \v1)", cp->emit, sym->rname);
973 12
        *e = vcc_expr_edit(tl, BOOL, buf, *e, NULL);
974 12
}
975
976
static void v_matchproto_(cmp_f)
977 10309
cmp_string(struct vcc *tl, struct expr **e, const struct cmps *cp)
978
{
979
        struct expr *e2;
980
        struct token *tk;
981
        char buf[128];
982
983 10309
        tk = tl->t;
984 10309
        vcc_NextToken(tl);
985 10309
        vcc_expr_add(tl, &e2, STRINGS);
986 20618
        ERRCHK(tl);
987 10309
        if (e2->fmt != STRINGS) {
988 9
                VSB_printf(tl->sb,
989
                    "Comparison of different types: %s '%.*s' %s\n",
990 9
                    vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
991 3
                vcc_ErrWhere(tl, tk);
992 10306
        } else if ((*e)->nstr == 1 && e2->nstr == 1) {
993 10287
                bprintf(buf, "(%s VRT_strcmp(\v1, \v2))", cp->emit);
994 10287
                *e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
995
        } else {
996 19
                bprintf(buf, "(%s VRT_CompareStrands(\vT, \vt))", cp->emit);
997 19
                *e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
998
        }
999
}
1000
1001
#define IDENT_REL(typ)                                                  \
1002
        {typ,           T_EQ,           cmp_simple, "(\v1 == \v2)" },   \
1003
        {typ,           T_NEQ,          cmp_simple, "(\v1 != \v2)" }
1004
1005
#define NUM_REL(typ)                                                    \
1006
        IDENT_REL(typ),                                                 \
1007
        {typ,           T_LEQ,          cmp_simple, "(\v1 <= \v2)" },   \
1008
        {typ,           T_GEQ,          cmp_simple, "(\v1 >= \v2)" },   \
1009
        {typ,           '<',            cmp_simple, "(\v1 < \v2)" },    \
1010
        {typ,           '>',            cmp_simple, "(\v1 > \v2)" }
1011
1012
static const struct cmps vcc_cmps[] = {
1013
        NUM_REL(INT),
1014
        NUM_REL(DURATION),
1015
        NUM_REL(BYTES),
1016
        NUM_REL(REAL),
1017
        NUM_REL(TIME),
1018
        IDENT_REL(BACKEND),
1019
        IDENT_REL(ACL),
1020
        IDENT_REL(PROBE),
1021
        IDENT_REL(STEVEDORE),
1022
        IDENT_REL(SUB),
1023
        IDENT_REL(INSTANCE),
1024
1025
        {IP,            T_EQ,           cmp_simple, "!VRT_ipcmp(\v1, \v2)" },
1026
        {IP,            T_NEQ,          cmp_simple, "VRT_ipcmp(\v1, \v2)" },
1027
1028
        {IP,            '~',            cmp_acl, "" },
1029
        {IP,            T_NOMATCH,      cmp_acl, "!" },
1030
1031
        {STRINGS,       T_EQ,           cmp_string, "0 =="},
1032
        {STRINGS,       T_NEQ,          cmp_string, "0 !="},
1033
        {STRINGS,       '<',            cmp_string, "0 > "},
1034
        {STRINGS,       '>',            cmp_string, "0 < "},
1035
        {STRINGS,       T_LEQ,          cmp_string, "0 >="},
1036
        {STRINGS,       T_GEQ,          cmp_string, "0 <="},
1037
1038
        {STRINGS,       '~',            cmp_regexp, "" },
1039
        {STRINGS,       T_NOMATCH,      cmp_regexp, "!" },
1040
1041
        {VOID,          0,              NULL, NULL}
1042
};
1043
1044
#undef IDENT_REL
1045
#undef NUM_REL
1046
1047
static void
1048 34037
vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1049
{
1050
        const struct cmps *cp;
1051
        struct token *tk;
1052
1053 34037
        *e = NULL;
1054 34037
        vcc_expr_add(tl, e, fmt);
1055 34037
        ERRCHK(tl);
1056 34004
        tk = tl->t;
1057
1058 34004
        if ((*e)->fmt == BOOL)
1059 2596
                return;
1060
1061 1542279
        for (cp = vcc_cmps; cp->fmt != VOID; cp++) {
1062 1525159
                if ((*e)->fmt == cp->fmt && tl->t->tok == cp->token) {
1063 14288
                        AN(cp->func);
1064 14288
                        cp->func(tl, e, cp);
1065 14288
                        return;
1066
                }
1067
        }
1068
1069 17120
        switch (tk->tok) {
1070
        case T_EQ:
1071
        case T_NEQ:
1072
        case '<':
1073
        case T_LEQ:
1074
        case '>':
1075
        case T_GEQ:
1076
        case '~':
1077
        case T_NOMATCH:
1078 6
                VSB_printf(tl->sb, "Operator %.*s not possible on %s\n",
1079 6
                    PF(tl->t), vcc_utype((*e)->fmt));
1080 2
                vcc_ErrWhere(tl, tl->t);
1081 2
                return;
1082
        default:
1083 17118
                break;
1084
        }
1085 17118
        if (fmt != BOOL)
1086 13243
                return;
1087 3875
        if ((*e)->fmt == BACKEND || (*e)->fmt == INT)
1088 7
                *e = vcc_expr_edit(tl, BOOL, "(\v1 != 0)", *e, NULL);
1089 3868
        else if ((*e)->fmt == DURATION)
1090 2
                *e = vcc_expr_edit(tl, BOOL, "(\v1 > 0)", *e, NULL);
1091 3866
        else if ((*e)->fmt == STRINGS)
1092 3866
                *e = vcc_expr_edit(tl, BOOL, "(\vS != 0)", *e, NULL);
1093
        else
1094 0
                INCOMPL();
1095
}
1096
1097
/*--------------------------------------------------------------------
1098
 * SYNTAX:
1099
 *    ExprNot:
1100
 *      '!' ExprCmp
1101
 */
1102
1103
static void
1104 34037
vcc_expr_not(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1105
{
1106
        struct expr *e2;
1107
        struct token *tk;
1108
1109 34037
        *e = NULL;
1110 34037
        if (fmt != BOOL || tl->t->tok != '!') {
1111 33224
                vcc_expr_cmp(tl, e, fmt);
1112 33224
                return;
1113
        }
1114
1115 813
        vcc_NextToken(tl);
1116 813
        tk = tl->t;
1117 813
        vcc_expr_cmp(tl, &e2, fmt);
1118 813
        ERRCHK(tl);
1119 812
        if (e2->fmt != BOOL) {
1120 0
                VSB_printf(tl->sb, "'!' must be followed by BOOL, found ");
1121 0
                VSB_printf(tl->sb, "%s.\n", vcc_utype(e2->fmt));
1122 0
                vcc_ErrWhere2(tl, tk, tl->t);
1123
        } else {
1124 812
                *e = vcc_expr_edit(tl, BOOL, "!(\v1)", e2, NULL);
1125
        }
1126
}
1127
1128
/*--------------------------------------------------------------------
1129
 * SYNTAX:
1130
 *    ExprCand:
1131
 *      ExprNot { '&&' ExprNot } *
1132
 */
1133
1134
static void
1135 27100
vcc_expr_cand(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1136
{
1137
        struct expr *e2;
1138
        struct token *tk;
1139
1140 27100
        *e = NULL;
1141 27100
        vcc_expr_not(tl, e, fmt);
1142 51883
        ERRCHK(tl);
1143 27053
        if ((*e)->fmt != BOOL || tl->t->tok != T_CAND)
1144 24736
                return;
1145 2317
        *e = vcc_expr_edit(tl, BOOL, "(\v+\n\v1", *e, NULL);
1146 11571
        while (tl->t->tok == T_CAND) {
1147 6937
                vcc_NextToken(tl);
1148 6937
                tk = tl->t;
1149 6937
                vcc_expr_not(tl, &e2, fmt);
1150 6937
                ERRCHK(tl);
1151 6937
                if (e2->fmt != BOOL) {
1152 0
                        VSB_printf(tl->sb,
1153
                            "'&&' must be followed by BOOL,"
1154 0
                            " found %s.\n", vcc_utype(e2->fmt));
1155 0
                        vcc_ErrWhere2(tl, tk, tl->t);
1156 0
                        return;
1157
                }
1158 6937
                *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n&&\v+\n\v2", *e, e2);
1159
        }
1160 2317
        *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n)", *e, NULL);
1161
}
1162
1163
/*--------------------------------------------------------------------
1164
 * SYNTAX:
1165
 *    ExprCOR:
1166
 *      ExprCand { '||' ExprCand } *
1167
 */
1168
1169
static void
1170 23243
vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1171
{
1172
        struct expr *e2;
1173
        struct token *tk;
1174
1175 23243
        *e = NULL;
1176 23243
        vcc_expr_cand(tl, e, fmt);
1177 44939
        ERRCHK(tl);
1178 23196
        if ((*e)->fmt != BOOL || tl->t->tok != T_COR)
1179 21649
                return;
1180 1547
        *e = vcc_expr_edit(tl, BOOL, "(\v+\n\v1", *e, NULL);
1181 6951
        while (tl->t->tok == T_COR) {
1182 3857
                vcc_NextToken(tl);
1183 3857
                tk = tl->t;
1184 3857
                vcc_expr_cand(tl, &e2, fmt);
1185 3857
                ERRCHK(tl);
1186 3857
                if (e2->fmt != BOOL) {
1187 0
                        VSB_printf(tl->sb,
1188
                            "'||' must be followed by BOOL,"
1189 0
                            " found %s.\n", vcc_utype(e2->fmt));
1190 0
                        vcc_ErrWhere2(tl, tk, tl->t);
1191 0
                        return;
1192
                }
1193 3857
                *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n||\v+\n\v2", *e, e2);
1194
        }
1195 1547
        *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n)", *e, NULL);
1196
}
1197
1198
/*--------------------------------------------------------------------
1199
 * This function is the entry-point for getting an expression with
1200
 * a particular type, ready for inclusion in the VGC.
1201
 */
1202
1203
static void
1204 22462
vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt)
1205
{
1206
        struct token *t1;
1207
1208 22462
        assert(fmt != VOID);
1209 22462
        assert(fmt != STRINGS);
1210 22462
        *e = NULL;
1211 22462
        t1 = tl->t;
1212 22462
        if (fmt == STRING_LIST || fmt == STRING)
1213 9768
                vcc_expr_cor(tl, e, STRINGS);
1214
        else
1215 12694
                vcc_expr_cor(tl, e, fmt);
1216 22462
        ERRCHK(tl);
1217 22415
        assert((*e)->fmt != STRING_LIST && (*e)->fmt != STRING);
1218
1219 22415
        if ((*e)->fmt == STRINGS && fmt == STRING_LIST)
1220 7691
                (*e)->fmt = STRING_LIST;
1221 14724
        else if ((*e)->fmt == STRINGS && fmt == STRING)
1222 1047
                *e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL);
1223 13677
        else if ((*e)->fmt == STRINGS && fmt == STRANDS) {
1224 0
                *e = vcc_expr_edit(tl, STRANDS, "\vT", (*e), NULL);
1225 13677
        } else if ((*e)->fmt != STRINGS &&
1226 13670
            (fmt == STRING || fmt == STRING_LIST))
1227 1015
                vcc_expr_tostring(tl, e, fmt);
1228
1229 22415
        if ((*e)->fmt == STRING_LIST)
1230 8701
                *e = vcc_expr_edit(tl, STRING_LIST,
1231
                    "\v+\n\v1,\nvrt_magic_string_end\v-", *e, NULL);
1232
1233 22415
        if (fmt != (*e)->fmt)  {
1234 8
                VSB_printf(tl->sb, "Expression has type %s, expected %s\n",
1235 4
                    vcc_utype((*e)->fmt), vcc_utype(fmt));
1236 4
                vcc_ErrWhere2(tl, t1, tl->t);
1237 4
                return;
1238
        }
1239
}
1240
1241
/*--------------------------------------------------------------------
1242
 * This function parses and emits the C-code to evaluate an expression
1243
 *
1244
 * We know up front what kind of type we want the expression to be,
1245
 * and this function is the backstop if that doesn't succeed.
1246
 */
1247
1248
void
1249 20740
vcc_Expr(struct vcc *tl, vcc_type_t fmt)
1250
{
1251 20740
        struct expr *e = NULL;
1252
1253 20740
        assert(fmt != VOID);
1254 20740
        assert(fmt != STRINGS);
1255 20740
        vcc_expr0(tl, &e, fmt);
1256 41480
        ERRCHK(tl);
1257 20694
        vcc_expr_fmt(tl->fb, tl->indent, e);
1258 20694
        VSB_printf(tl->fb, "\n");
1259 20694
        vcc_delete_expr(e);
1260
}
1261
1262
/*--------------------------------------------------------------------
1263
 */
1264
1265
void
1266 357
vcc_Expr_Call(struct vcc *tl, const struct symbol *sym)
1267
{
1268
1269
        struct expr *e;
1270
        struct token *t1;
1271
1272 357
        t1 = tl->t;
1273 357
        e = NULL;
1274 357
        vcc_Eval_SymFunc(tl, &e, sym, VOID);
1275 357
        if (!tl->err) {
1276 355
                vcc_expr_fmt(tl->fb, tl->indent, e);
1277 355
                VSB_cat(tl->fb, ";\n");
1278 2
        } else if (t1 != tl->t) {
1279 2
                vcc_ErrWhere2(tl, t1, tl->t);
1280
        }
1281 357
        vcc_delete_expr(e);
1282 357
}
1283
1284
/*--------------------------------------------------------------------
1285
 */
1286
1287
void
1288 905
vcc_Expr_Init(struct vcc *tl)
1289
{
1290
        struct symbol *sym;
1291
1292 905
        sym = VCC_Symbol(tl, NULL, "regsub", NULL, SYM_FUNC, 1);
1293 905
        AN(sym);
1294 905
        sym->eval = vcc_Eval_Regsub;
1295 905
        sym->eval_priv = NULL;
1296
1297 905
        sym = VCC_Symbol(tl, NULL, "regsuball", NULL, SYM_FUNC, 1);
1298 905
        AN(sym);
1299 905
        sym->eval = vcc_Eval_Regsub;
1300 905
        sym->eval_priv = sym;
1301
1302 905
        sym = VCC_Symbol(tl, NULL, "true", NULL, SYM_FUNC, 1);
1303 905
        AN(sym);
1304 905
        sym->eval = vcc_Eval_BoolConst;
1305 905
        sym->eval_priv = sym;
1306
1307 905
        sym = VCC_Symbol(tl, NULL, "false", NULL, SYM_FUNC, 1);
1308 905
        AN(sym);
1309 905
        sym->eval = vcc_Eval_BoolConst;
1310 905
        sym->eval_priv = NULL;
1311 905
}