varnish-cache/lib/libvcc/vcc_backend_util.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2011 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
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 <stdarg.h>
35
#include <string.h>
36
37
#include "vcc_compile.h"
38
39
/*--------------------------------------------------------------------
40
 * Helper functions to complain about duplicate and missing fields
41
 *
42
 * XXX: idea: add groups to check for exclusivity, such that
43
 * XXX:    ("!foo", "?bar", "!{", "this", "that", "}", NULL)
44
 * XXX: means exactly one of "this" or "that", and
45
 * XXX:    ("!foo", "?bar", "?{", "this", "that", "}", NULL)
46
 * XXX: means at most one of "this" or "that".
47
 */
48
49
struct fld_spec {
50
        const char      *name;
51
        struct token    *found;
52
};
53
54
static void
55 16872
vcc_ResetFldSpec(struct fld_spec *f)
56
{
57
58 234048
        for (; f->name != NULL; f++)
59 217176
                f->found = NULL;
60 16872
}
61
62
struct fld_spec *
63 16872
vcc_FldSpec(struct vcc *tl, const char *first, ...)
64
{
65
        struct fld_spec f[100], *r;
66 16872
        int n = 0;
67
        va_list ap;
68
        const char *p;
69
70 16872
        f[n++].name = first;
71 16872
        va_start(ap, first);
72 217176
        while (1) {
73 217176
                p = va_arg(ap, const char *);
74 217176
                if (p == NULL)
75 16872
                        break;
76 200304
                f[n++].name = p;
77 200304
                assert(n < 100);
78
        }
79 16872
        va_end(ap);
80 16872
        f[n++].name = NULL;
81
82 16872
        vcc_ResetFldSpec(f);
83
84 16872
        r = TlAlloc(tl, sizeof *r * n);
85 16872
        memcpy(r, f, n * sizeof *r);
86 16872
        return (r);
87
}
88
89
void
90 30336
vcc_IsField(struct vcc *tl, const struct token **t, struct fld_spec *fs)
91
{
92
        struct token *t_field;
93
94 30336
        SkipToken(tl, '.');
95 30336
        ExpectErr(tl, ID);
96 30336
        t_field = tl->t;
97 30336
        *t = t_field;
98 30336
        vcc_NextToken(tl);
99 30336
        SkipToken(tl, '=');
100
101 55320
        for (; fs->name != NULL; fs++) {
102 55308
                if (!vcc_IdIs(t_field, fs->name + 1))
103 24984
                        continue;
104 30324
                if (fs->found == NULL) {
105 30312
                        fs->found = t_field;
106 30312
                        return;
107
                }
108 12
                VSB_cat(tl->sb, "Field ");
109 12
                vcc_ErrToken(tl, t_field);
110 12
                VSB_cat(tl->sb, " redefined at:\n");
111 12
                vcc_ErrWhere(tl, t_field);
112 12
                VSB_cat(tl->sb, "\nFirst defined at:\n");
113 12
                vcc_ErrWhere(tl, fs->found);
114 12
                return;
115
        }
116 12
        VSB_cat(tl->sb, "Unknown field: ");
117 12
        vcc_ErrToken(tl, t_field);
118 12
        VSB_cat(tl->sb, " at\n");
119 12
        vcc_ErrWhere(tl, t_field);
120 30336
}
121
122
void
123 16116
vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs)
124
{
125
126 225624
        for (; fs->name != NULL; fs++) {
127 209508
                if (*fs->name == '!' && fs->found == NULL) {
128 0
                        VSB_printf(tl->sb,
129 0
                            "Mandatory field '%s' missing.\n", fs->name + 1);
130 0
                        tl->err = 1;
131 0
                }
132 209508
        }
133 16116
}