varnish-cache/lib/libvarnishapi/vxp_parse.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Martin Blix Grydeland <martin@varnish-software.com>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 */
31
32
#include "config.h"
33
34
#include <ctype.h>
35
#include <math.h>
36
#include <stdio.h>
37
38
#include "vdef.h"
39
#include "vas.h"
40
#include "miniobj.h"
41
42
#include "vbm.h"
43
#include "vnum.h"
44
#include "vqueue.h"
45
#include "vre.h"
46
#include "vsb.h"
47
48
#include "vapi/vsl.h"
49
50
#include "vsl_api.h"
51
#include "vxp.h"
52
53
static void vxp_expr_or(struct vxp *vxp, struct vex **pvex);
54
55
static struct vex *
56 8360
vex_alloc(const struct vxp *vxp)
57
{
58
        struct vex *vex;
59
60 8360
        ALLOC_OBJ(vex, VEX_MAGIC);
61 8360
        AN(vex);
62 8360
        vex->options = vxp->vex_options;
63 8360
        return (vex);
64
}
65
66
static void
67 7480
vxp_expr_lhs(struct vxp *vxp, struct vex_lhs **plhs)
68
{
69
        char *p;
70
        int i;
71
72 7480
        AN(plhs);
73 7480
        AZ(*plhs);
74 7480
        ALLOC_OBJ(*plhs, VEX_LHS_MAGIC);
75 7480
        AN(*plhs);
76 7480
        (*plhs)->tags = vbit_new(SLT__MAX);
77 7480
        (*plhs)->level = -1;
78
79 7480
        if (vxp->t->tok == '{') {
80
                /* Transaction level limits */
81 280
                vxp_NextToken(vxp);
82 280
                if (vxp->t->tok != VAL) {
83 80
                        VSB_printf(vxp->sb, "Expected integer got '%.*s' ",
84 40
                            PF(vxp->t));
85 40
                        vxp_ErrWhere(vxp, vxp->t, -1);
86 40
                        return;
87
                }
88 240
                (*plhs)->level = (int)strtol(vxp->t->dec, &p, 0);
89 240
                if ((*plhs)->level < 0) {
90 40
                        VSB_cat(vxp->sb, "Expected positive integer ");
91 40
                        vxp_ErrWhere(vxp, vxp->t, -1);
92 40
                        return;
93
                }
94 200
                if (*p == '-') {
95 40
                        (*plhs)->level_pm = -1;
96 40
                        p++;
97 200
                } else if (*p == '+') {
98 40
                        (*plhs)->level_pm = 1;
99 40
                        p++;
100 40
                }
101 200
                if (*p) {
102 40
                        VSB_cat(vxp->sb, "Syntax error in level limit ");
103 40
                        vxp_ErrWhere(vxp, vxp->t, -1);
104 40
                        return;
105
                }
106 160
                vxp_NextToken(vxp);
107 160
                ExpectErr(vxp, '}');
108 160
                vxp_NextToken(vxp);
109 160
        }
110
111 7480
        while (1) {
112
                /* The tags this expression applies to */
113 7480
                if (vxp->t->tok == VXID) {
114 1080
                        (*plhs)->vxid++;
115 1080
                        i = 0;
116 7480
                } else if (vxp->t->tok != VAL) {
117 80
                        VSB_printf(vxp->sb, "Expected VSL tag name got '%.*s' ",
118 40
                            PF(vxp->t));
119 40
                        vxp_ErrWhere(vxp, vxp->t, -1);
120 40
                        return;
121
                } else {
122 6360
                        (*plhs)->taglist++;
123 12720
                        i = VSL_Glob2Tags(vxp->t->dec, -1, vsl_vbm_bitset,
124 6360
                            (*plhs)->tags);
125
                }
126 7440
                if (i == -1) {
127 80
                        VSB_cat(vxp->sb, "Tag name matches zero tags ");
128 80
                        vxp_ErrWhere(vxp, vxp->t, -1);
129 80
                        return;
130
                }
131 7360
                if (i == -2) {
132 40
                        VSB_cat(vxp->sb, "Tag name is ambiguous ");
133 40
                        vxp_ErrWhere(vxp, vxp->t, -1);
134 40
                        return;
135
                }
136 7320
                if (i == -3) {
137 40
                        VSB_cat(vxp->sb, "Syntax error in tag name ");
138 40
                        vxp_ErrWhere(vxp, vxp->t, -1);
139 40
                        return;
140
                }
141 7280
                assert(i > 0 || vxp->t->tok == VXID);
142 7280
                vxp_NextToken(vxp);
143 7280
                if (vxp->t->tok != ',')
144 7160
                        break;
145 120
                vxp_NextToken(vxp);
146
        }
147
148 7160
        if (vxp->t->tok == ':') {
149
                /* Record prefix */
150 800
                vxp_NextToken(vxp);
151 800
                if (vxp->t->tok != VAL) {
152 80
                        VSB_printf(vxp->sb, "Expected string got '%.*s' ",
153 40
                            PF(vxp->t));
154 40
                        vxp_ErrWhere(vxp, vxp->t, -1);
155 40
                        return;
156
                }
157 760
                AN(vxp->t->dec);
158 760
                (*plhs)->prefix = strdup(vxp->t->dec);
159 760
                AN((*plhs)->prefix);
160 760
                (*plhs)->prefixlen = strlen((*plhs)->prefix);
161 760
                vxp_NextToken(vxp);
162 760
        }
163
164 7120
        if (vxp->t->tok == '[') {
165
                /* LHS field [] */
166 480
                vxp_NextToken(vxp);
167 480
                if (vxp->t->tok != VAL) {
168 80
                        VSB_printf(vxp->sb, "Expected integer got '%.*s' ",
169 40
                            PF(vxp->t));
170 40
                        vxp_ErrWhere(vxp, vxp->t, -1);
171 40
                        return;
172
                }
173 440
                (*plhs)->field = (int)strtol(vxp->t->dec, &p, 0);
174 440
                if (*p || (*plhs)->field <= 0) {
175 40
                        VSB_cat(vxp->sb, "Expected positive integer ");
176 40
                        vxp_ErrWhere(vxp, vxp->t, -1);
177 40
                        return;
178
                }
179 400
                vxp_NextToken(vxp);
180 400
                ExpectErr(vxp, ']');
181 400
                vxp_NextToken(vxp);
182 400
        }
183
184 7040
        if ((*plhs)->vxid == 0)
185 6000
                return;
186
187 1960
        if ((*plhs)->vxid > 1 || (*plhs)->level >= 0 ||
188 960
            (*plhs)->field > 0 || (*plhs)->prefixlen > 0 ||
189 920
            (*plhs)->taglist > 0) {
190 160
                VSB_cat(vxp->sb, "Unexpected taglist selection for vxid ");
191 160
                vxp_ErrWhere(vxp, vxp->t, -1);
192 160
        }
193 7480
}
194
195
static void
196 2920
vxp_expr_num(struct vxp *vxp, struct vex_rhs **prhs, unsigned vxid)
197
{
198
        char *endptr;
199
200 2920
        AN(prhs);
201 2920
        AZ(*prhs);
202 2920
        if (vxp->t->tok != VAL) {
203 40
                VSB_printf(vxp->sb, "Expected number got '%.*s' ", PF(vxp->t));
204 40
                vxp_ErrWhere(vxp, vxp->t, -1);
205 40
                return;
206
        }
207 2880
        AN(vxp->t->dec);
208 2880
        ALLOC_OBJ(*prhs, VEX_RHS_MAGIC);
209 2880
        AN(*prhs);
210 2880
        if (strchr(vxp->t->dec, '.')) {
211 440
                (*prhs)->type = VEX_FLOAT;
212 440
                (*prhs)->val_float = VNUM(vxp->t->dec);
213 440
                if (isnan((*prhs)->val_float)) {
214 40
                        VSB_cat(vxp->sb, "Floating point parse error ");
215 40
                        vxp_ErrWhere(vxp, vxp->t, -1);
216 40
                        return;
217
                }
218 400
        } else {
219 2440
                (*prhs)->type = VEX_INT;
220 2440
                (*prhs)->val_int = strtoll(vxp->t->dec, &endptr, 0);
221 2440
                while (isspace(*endptr))
222 0
                        endptr++;
223 2440
                if (*endptr != '\0') {
224 40
                        VSB_cat(vxp->sb, "Integer parse error ");
225 40
                        vxp_ErrWhere(vxp, vxp->t, -1);
226 40
                        return;
227
                }
228
        }
229 2800
        if (vxid && (*prhs)->type != VEX_INT) {
230 80
                VSB_printf(vxp->sb, "Expected integer got '%.*s' ",
231 40
                    PF(vxp->t));
232 40
                vxp_ErrWhere(vxp, vxp->t, 0);
233 40
                return;
234
        }
235 2760
        vxp_NextToken(vxp);
236 2920
}
237
238
static void
239 520
vxp_expr_str(struct vxp *vxp, struct vex_rhs **prhs)
240
{
241
242 520
        AN(prhs);
243 520
        AZ(*prhs);
244 520
        if (vxp->t->tok != VAL) {
245 40
                VSB_printf(vxp->sb, "Expected string got '%.*s' ", PF(vxp->t));
246 40
                vxp_ErrWhere(vxp, vxp->t, -1);
247 40
                return;
248
        }
249 480
        AN(vxp->t->dec);
250 480
        ALLOC_OBJ(*prhs, VEX_RHS_MAGIC);
251 480
        AN(*prhs);
252 480
        (*prhs)->type = VEX_STRING;
253 480
        (*prhs)->val_string = strdup(vxp->t->dec);
254 480
        AN((*prhs)->val_string);
255 480
        (*prhs)->val_stringlen = strlen((*prhs)->val_string);
256 480
        vxp_NextToken(vxp);
257 520
}
258
259
static void
260 2120
vxp_expr_regex(struct vxp *vxp, struct vex_rhs **prhs)
261
{
262
        int err, erroff;
263
264
        /* XXX: Caseless option */
265
266 2120
        AN(prhs);
267 2120
        AZ(*prhs);
268 2120
        if (vxp->t->tok != VAL) {
269 80
                VSB_printf(vxp->sb, "Expected regular expression got '%.*s' ",
270 40
                    PF(vxp->t));
271 40
                vxp_ErrWhere(vxp, vxp->t, -1);
272 40
                return;
273
        }
274 2080
        AN(vxp->t->dec);
275 2080
        ALLOC_OBJ(*prhs, VEX_RHS_MAGIC);
276 2080
        AN(*prhs);
277 2080
        (*prhs)->type = VEX_REGEX;
278 2080
        (*prhs)->val_string = strdup(vxp->t->dec);
279 2080
        (*prhs)->val_regex = VRE_compile(vxp->t->dec, vxp->vre_options,
280
            &err, &erroff, 1);
281 2080
        if ((*prhs)->val_regex == NULL) {
282 40
                VSB_cat(vxp->sb, "Regular expression error: ");
283 40
                AZ(VRE_error(vxp->sb, err));
284 40
                VSB_putc(vxp->sb, ' ');
285 40
                vxp_ErrWhere(vxp, vxp->t, erroff);
286 40
                return;
287
        }
288 2040
        vxp_NextToken(vxp);
289 2120
}
290
291
static void
292 880
vxp_vxid_cmp(struct vxp *vxp)
293
{
294
295 880
        switch (vxp->t->tok) {
296
        /* Valid operators */
297
        case T_EQ:              /* == */
298
        case '<':               /* < */
299
        case '>':               /* > */
300
        case T_GEQ:             /* >= */
301
        case T_LEQ:             /* <= */
302
        case T_NEQ:             /* != */
303 720
                break;
304
305
        /* Error */
306
        default:
307 320
                VSB_printf(vxp->sb, "Expected vxid operator got '%.*s' ",
308 160
                    PF(vxp->t));
309 160
                vxp_ErrWhere(vxp, vxp->t, -1);
310 160
        }
311 880
}
312
313
/*
314
 * SYNTAX:
315
 *   expr_cmp:
316
 *     lhs
317
 *     lhs <operator> num|str|regex
318
 */
319
320
static void
321 7480
vxp_expr_cmp(struct vxp *vxp, struct vex **pvex)
322
{
323
324 7480
        AN(pvex);
325 7480
        AZ(*pvex);
326 7480
        *pvex = vex_alloc(vxp);
327 7480
        AN(*pvex);
328 7480
        vxp_expr_lhs(vxp, &(*pvex)->lhs);
329 7480
        ERRCHK(vxp);
330
331 6880
        if ((*pvex)->lhs->vxid) {
332 880
                vxp_vxid_cmp(vxp);
333 880
                ERRCHK(vxp);
334 720
        }
335
336
        /* Test operator */
337 6720
        switch (vxp->t->tok) {
338
339
        /* Single lhs expressions don't take any more tokens */
340
        case EOI:
341
        case T_AND:
342
        case T_OR:
343
        case ')':
344 1120
                (*pvex)->tok = T_TRUE;
345 1120
                return;
346
347
        /* Valid operators */
348
        case T_EQ:              /* == */
349
        case '<':               /* < */
350
        case '>':               /* > */
351
        case T_GEQ:             /* >= */
352
        case T_LEQ:             /* <= */
353
        case T_NEQ:             /* != */
354
        case T_SEQ:             /* eq */
355
        case T_SNEQ:            /* ne */
356
        case '~':               /* ~ */
357
        case T_NOMATCH:         /* !~ */
358 5560
                (*pvex)->tok = vxp->t->tok;
359 5560
                break;
360
361
        /* Error */
362
        default:
363 80
                VSB_printf(vxp->sb, "Expected operator got '%.*s' ",
364 40
                    PF(vxp->t));
365 40
                vxp_ErrWhere(vxp, vxp->t, -1);
366 40
                return;
367
        }
368 5560
        vxp_NextToken(vxp);
369 5560
        ERRCHK(vxp);
370
371
        /* Value */
372 5560
        switch ((*pvex)->tok) {
373
        case '\0':
374 0
                WRONG("Missing token");
375 0
                break;
376
        case T_EQ:              /* == */
377
        case '<':               /* < */
378
        case '>':               /* > */
379
        case T_GEQ:             /* >= */
380
        case T_LEQ:             /* <= */
381
        case T_NEQ:             /* != */
382 2920
                vxp_expr_num(vxp, &(*pvex)->rhs, (*pvex)->lhs->vxid);
383 2920
                break;
384
        case T_SEQ:             /* eq */
385
        case T_SNEQ:            /* ne */
386 520
                vxp_expr_str(vxp, &(*pvex)->rhs);
387 520
                break;
388
        case '~':               /* ~ */
389
        case T_NOMATCH:         /* !~ */
390 2120
                vxp_expr_regex(vxp, &(*pvex)->rhs);
391 2120
                break;
392
        default:
393 0
                INCOMPL();
394 0
        }
395 7480
}
396
397
/*
398
 * SYNTAX:
399
 *   expr_group:
400
 *     '(' expr_or ')'
401
 *     expr_not
402
 */
403
404
static void
405 7680
vxp_expr_group(struct vxp *vxp, struct vex **pvex)
406
{
407
408 7680
        AN(pvex);
409 7680
        AZ(*pvex);
410
411 7680
        if (vxp->t->tok == '(') {
412 200
                SkipToken(vxp, '(');
413 200
                vxp_expr_or(vxp, pvex);
414 200
                ERRCHK(vxp);
415 200
                SkipToken(vxp, ')');
416 200
                return;
417
        }
418
419 7480
        vxp_expr_cmp(vxp, pvex);
420 7680
}
421
422
/*
423
 * SYNTAX:
424
 *   expr_not:
425
 *     'not' expr_group
426
 *     expr_group
427
 */
428
429
static void
430 7680
vxp_expr_not(struct vxp *vxp, struct vex **pvex)
431
{
432
433 7680
        AN(pvex);
434 7680
        AZ(*pvex);
435
436 7680
        if (vxp->t->tok == T_NOT) {
437 40
                *pvex = vex_alloc(vxp);
438 40
                AN(*pvex);
439 40
                (*pvex)->tok = vxp->t->tok;
440 40
                vxp_NextToken(vxp);
441 40
                vxp_expr_group(vxp, &(*pvex)->a);
442 40
                return;
443
        }
444
445 7640
        vxp_expr_group(vxp, pvex);
446 7680
}
447
448
/*
449
 * SYNTAX:
450
 *   expr_and:
451
 *     expr_not { 'and' expr_not }*
452
 */
453
454
static void
455 7360
vxp_expr_and(struct vxp *vxp, struct vex **pvex)
456
{
457
        struct vex *a;
458
459 7360
        AN(pvex);
460 7360
        AZ(*pvex);
461 7360
        vxp_expr_not(vxp, pvex);
462 7360
        ERRCHK(vxp);
463 6600
        while (vxp->t->tok == T_AND) {
464 320
                a = *pvex;
465 320
                *pvex = vex_alloc(vxp);
466 320
                AN(*pvex);
467 320
                (*pvex)->tok = vxp->t->tok;
468 320
                (*pvex)->a = a;
469 320
                vxp_NextToken(vxp);
470 320
                ERRCHK(vxp);
471 320
                vxp_expr_not(vxp, &(*pvex)->b);
472 320
                ERRCHK(vxp);
473
        }
474 7360
}
475
476
/*
477
 * SYNTAX:
478
 *   expr_or:
479
 *     expr_and { 'or' expr_and }*
480
 */
481
482
static void
483 7080
vxp_expr_or(struct vxp *vxp, struct vex **pvex)
484
{
485
        struct vex *a;
486
487 7080
        AN(pvex);
488 7080
        AZ(*pvex);
489 7080
        vxp_expr_and(vxp, pvex);
490 7080
        ERRCHK(vxp);
491 6280
        while (vxp->t->tok == T_OR) {
492 280
                a = *pvex;
493 280
                *pvex = vex_alloc(vxp);
494 280
                AN(*pvex);
495 280
                (*pvex)->tok = vxp->t->tok;
496 280
                (*pvex)->a = a;
497 280
                vxp_NextToken(vxp);
498 280
                ERRCHK(vxp);
499 280
                vxp_expr_and(vxp, &(*pvex)->b);
500 280
                ERRCHK(vxp);
501
        }
502 7080
}
503
504
/*
505
 * SYNTAX:
506
 *   expr:
507
 *     expr_or EOI { 'or' expr_or EOI }?
508
 */
509
510
static void
511 7120
vxp_expr(struct vxp *vxp, struct vex **pvex)
512
{
513 7120
        struct vex *a = NULL, *or;
514
515 7120
        if (*pvex == NULL) {
516 6880
                vxp_expr_or(vxp, pvex);
517 6880
                ERRCHK(vxp);
518 5800
                ExpectErr(vxp, EOI);
519 5800
                return;
520
        }
521
522 240
        vxp_expr(vxp, &a);
523 240
        ERRCHK(vxp);
524
525 240
        or = vex_alloc(vxp);
526 240
        AN(or);
527 240
        or->tok = T_OR;
528 240
        or->b = *pvex;
529 240
        or->a = a;
530 240
        *pvex = or;
531 7120
}
532
533
/*
534
 * Build a struct vex tree from the token list in vxp
535
 */
536
537
struct vex *
538 6720
vxp_Parse(struct vxp *vxp)
539
{
540 6720
        struct vex *vex = NULL;
541
542 6720
        AZ(vxp->err);
543 6720
        vxp->t = VTAILQ_FIRST(&vxp->tokens);
544
545 12520
        while (vxp->t != NULL) {
546
                /* Ignore empty queries */
547 8120
                while (vxp->t != NULL && vxp->t->tok == EOI)
548 960
                        vxp->t = VTAILQ_NEXT(vxp->t, list);
549
550 7160
                if (vxp->t == NULL)
551 280
                        break;
552
553 6880
                vxp_expr(vxp, &vex);
554
555 6880
                if (vxp->err) {
556 1080
                        if (vex)
557 1080
                                vex_Free(&vex);
558 1080
                        AZ(vex);
559 1080
                        return (NULL);
560
                }
561
562 5800
                vxp->t = VTAILQ_NEXT(vxp->t, list);
563
        }
564
565 5640
        return (vex);
566 6720
}
567
568
/*
569
 * Free a struct vex tree
570
 */
571
572
void
573 8360
vex_Free(struct vex **pvex)
574
{
575
        struct vex *vex;
576
        struct vex_lhs *lhs;
577
        struct vex_rhs *rhs;
578
579 8360
        TAKE_OBJ_NOTNULL(vex, pvex, VEX_MAGIC);
580
581 8360
        if (vex->lhs) {
582 7480
                CAST_OBJ_NOTNULL(lhs, vex->lhs, VEX_LHS_MAGIC);
583 7480
                if (lhs->tags)
584 7480
                        vbit_destroy(lhs->tags);
585 7480
                if (lhs->prefix)
586 760
                        free(lhs->prefix);
587 7480
                FREE_OBJ(lhs);
588 7480
        }
589 8360
        if (vex->rhs) {
590 5440
                CAST_OBJ_NOTNULL(rhs, vex->rhs, VEX_RHS_MAGIC);
591 5440
                if (rhs->val_string)
592 2560
                        free(rhs->val_string);
593 5440
                if (rhs->val_regex)
594 2040
                        VRE_free(&rhs->val_regex);
595 5440
                FREE_OBJ(rhs);
596 5440
        }
597 8360
        if (vex->a) {
598 880
                vex_Free(&vex->a);
599 880
                AZ(vex->a);
600 880
        }
601 8360
        if (vex->b) {
602 840
                vex_Free(&vex->b);
603 840
                AZ(vex->b);
604 840
        }
605 8360
        FREE_OBJ(vex);
606 8360
}
607
608
#ifdef VXP_DEBUG
609
610
static void
611 120
vex_print_rhs(const struct vex_rhs *rhs)
612
{
613
614 120
        CHECK_OBJ_NOTNULL(rhs, VEX_RHS_MAGIC);
615 120
        fprintf(stderr, "rhs=");
616 120
        switch (rhs->type) {
617
        case VEX_INT:
618 80
                fprintf(stderr, "INT(%jd)", (intmax_t)rhs->val_int);
619 80
                break;
620
        case VEX_FLOAT:
621 0
                fprintf(stderr, "FLOAT(%f)", rhs->val_float);
622 0
                break;
623
        case VEX_STRING:
624 0
                AN(rhs->val_string);
625 0
                fprintf(stderr, "STRING(%s)", rhs->val_string);
626 0
                break;
627
        case VEX_REGEX:
628 40
                AN(rhs->val_string);
629 40
                AN(rhs->val_regex);
630 40
                fprintf(stderr, "REGEX(%s)", rhs->val_string);
631 40
                break;
632
        default:
633 0
                WRONG("rhs type");
634 0
                break;
635
        }
636 120
}
637
638
static void
639 160
vex_print_tags(const struct vbitmap *vbm)
640
{
641
        int i;
642 160
        int first = 1;
643
644 41120
        for (i = 0; i < SLT__MAX; i++) {
645 40960
                if (VSL_tags[i] == NULL)
646 26080
                        continue;
647 14880
                if (!vbit_test(vbm, i))
648 14560
                        continue;
649 320
                if (first)
650 160
                        first = 0;
651
                else
652 160
                        fprintf(stderr, ",");
653 320
                fprintf(stderr, "%s", VSL_tags[i]);
654 320
        }
655 160
}
656
657
static void
658 240
vex_print(const struct vex *vex, int indent)
659
{
660 240
        CHECK_OBJ_NOTNULL(vex, VEX_MAGIC);
661
662 240
        fprintf(stderr, "%*s%s", indent, "", vxp_tnames[vex->tok]);
663 240
        if (vex->lhs != NULL) {
664 160
                CHECK_OBJ(vex->lhs, VEX_LHS_MAGIC);
665 160
                AN(vex->lhs->tags);
666 160
                fprintf(stderr, " lhs=");
667 160
                if (vex->lhs->level >= 0)
668 0
                        fprintf(stderr, "{%d%s}", vex->lhs->level,
669 0
                            vex->lhs->level_pm < 0 ? "-" :
670 0
                            vex->lhs->level_pm > 0 ? "+" : "");
671 160
                fprintf(stderr, "(");
672 160
                vex_print_tags(vex->lhs->tags);
673 160
                fprintf(stderr, ")");
674 160
                if (vex->lhs->prefix) {
675 80
                        assert(vex->lhs->prefixlen == strlen(vex->lhs->prefix));
676 80
                        fprintf(stderr, ":%s", vex->lhs->prefix);
677 80
                }
678 160
                if (vex->lhs->field > 0)
679 40
                        fprintf(stderr, "[%d]", vex->lhs->field);
680 160
        }
681 240
        if (vex->rhs != NULL) {
682 120
                fprintf(stderr, " ");
683 120
                vex_print_rhs(vex->rhs);
684 120
        }
685 240
        fprintf(stderr, "\n");
686 240
        if (vex->a != NULL)
687 80
                vex_print(vex->a, indent + 2);
688 240
        if (vex->b != NULL)
689 80
                vex_print(vex->b, indent + 2);
690 240
}
691
692
void
693 80
vex_PrintTree(const struct vex *vex)
694
{
695
696 80
        CHECK_OBJ_NOTNULL(vex, VEX_MAGIC);
697 80
        fprintf(stderr, "VEX tree:\n");
698 80
        vex_print(vex, 2);
699 80
}
700
701
#endif /* VXP_DEBUG */