varnish-cache/lib/libvcc/vcc_backend_util.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 <stdarg.h>
34
#include <string.h>
35
36
#include "vcc_compile.h"
37
38
/*--------------------------------------------------------------------
39
 * Helper functions to complain about duplicate and missing fields
40
 *
41
 * XXX: idea: add groups to check for exclusivity, such that
42
 * XXX:    ("!foo", "?bar", "!{", "this", "that", "}", NULL)
43
 * XXX: means exactly one of "this" or "that", and
44
 * XXX:    ("!foo", "?bar", "?{", "this", "that", "}", NULL)
45
 * XXX: means at most one of "this" or "that".
46
 */
47
48
struct fld_spec {
49
        const char      *name;
50
        struct token    *found;
51
};
52
53
static void
54 2390
vcc_ResetFldSpec(struct fld_spec *f)
55
{
56
57 26166
        for (; f->name != NULL; f++)
58 23776
                f->found = NULL;
59 2390
}
60
61
struct fld_spec *
62 2390
vcc_FldSpec(struct vcc *tl, const char *first, ...)
63
{
64
        struct fld_spec f[100], *r;
65 2390
        int n = 0;
66
        va_list ap;
67
        const char *p;
68
69 2390
        f[n++].name = first;
70 2390
        va_start(ap, first);
71
        while (1) {
72 45162
                p = va_arg(ap, const char *);
73 23776
                if (p == NULL)
74 2390
                        break;
75 21386
                f[n++].name = p;
76 21386
                assert(n < 100);
77
        }
78 2390
        va_end(ap);
79 2390
        f[n++].name = NULL;
80
81 2390
        vcc_ResetFldSpec(f);
82
83 2390
        r = TlAlloc(tl, sizeof *r * n);
84 2390
        memcpy(r, f, n * sizeof *r);
85 2390
        return (r);
86
}
87
88
void
89 4118
vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs)
90
{
91
        struct token *t_field;
92
93 4118
        SkipToken(tl, '.');
94 4118
        ExpectErr(tl, ID);
95 4118
        t_field = tl->t;
96 4118
        *t = t_field;
97 4118
        vcc_NextToken(tl);
98 4118
        SkipToken(tl, '=');
99
100 7102
        for (; fs->name != NULL; fs++) {
101 7100
                if (!vcc_IdIs(t_field, fs->name + 1))
102 2984
                        continue;
103 4116
                if (fs->found == NULL) {
104 4114
                        fs->found = t_field;
105 4114
                        return;
106
                }
107 2
                VSB_printf(tl->sb, "Field ");
108 2
                vcc_ErrToken(tl, t_field);
109 2
                VSB_printf(tl->sb, " redefined at:\n");
110 2
                vcc_ErrWhere(tl, t_field);
111 2
                VSB_printf(tl->sb, "\nFirst defined at:\n");
112 2
                vcc_ErrWhere(tl, fs->found);
113 2
                return;
114
        }
115 2
        VSB_printf(tl->sb, "Unknown field: ");
116 2
        vcc_ErrToken(tl, t_field);
117 2
        VSB_printf(tl->sb, " at\n");
118 2
        vcc_ErrWhere(tl, t_field);
119
}
120
121
void
122 2298
vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs)
123
{
124
125 25278
        for (; fs->name != NULL; fs++) {
126 22980
                if (*fs->name == '!' && fs->found == NULL) {
127 0
                        VSB_printf(tl->sb,
128 0
                            "Mandatory field '%s' missing.\n", fs->name + 1);
129 0
                        tl->err = 1;
130
                }
131
        }
132 2298
}