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 953
vcc_ResetFldSpec(struct fld_spec *f)
55
{
56
57 9506
        for (; f->name != NULL; f++)
58 8553
                f->found = NULL;
59 953
}
60
61
struct fld_spec *
62 953
vcc_FldSpec(struct vcc *tl, const char *first, ...)
63
{
64
        struct fld_spec f[100], *r;
65 953
        int n = 0;
66
        va_list ap;
67
        const char *p;
68
69 953
        f[n++].name = first;
70 953
        va_start(ap, first);
71
        while (1) {
72 8553
                p = va_arg(ap, const char *);
73 8553
                if (p == NULL)
74 953
                        break;
75 7600
                f[n++].name = p;
76 7600
                assert(n < 100);
77 7600
        }
78 953
        va_end(ap);
79 953
        f[n++].name = NULL;
80
81 953
        vcc_ResetFldSpec(f);
82
83 953
        r = TlAlloc(tl, sizeof *r * n);
84 953
        memcpy(r, f, n * sizeof *r);
85 953
        return (r);
86
}
87
88
void
89 1733
vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs)
90
{
91
        struct token *t_field;
92
93 1733
        SkipToken(tl, '.');
94 1733
        ExpectErr(tl, ID);
95 1733
        t_field = tl->t;
96 1733
        *t = t_field;
97 1733
        vcc_NextToken(tl);
98 1733
        SkipToken(tl, '=');
99
100 2882
        for (; fs->name != NULL; fs++) {
101 2881
                if (!vcc_IdIs(t_field, fs->name + 1))
102 1149
                        continue;
103 1732
                if (fs->found == NULL) {
104 1731
                        fs->found = t_field;
105 1731
                        return;
106
                }
107 1
                VSB_printf(tl->sb, "Field ");
108 1
                vcc_ErrToken(tl, t_field);
109 1
                VSB_printf(tl->sb, " redefined at:\n");
110 1
                vcc_ErrWhere(tl, t_field);
111 1
                VSB_printf(tl->sb, "\nFirst defined at:\n");
112 1
                vcc_ErrWhere(tl, fs->found);
113 1
                return;
114
        }
115 1
        VSB_printf(tl->sb, "Unknown field: ");
116 1
        vcc_ErrToken(tl, t_field);
117 1
        VSB_printf(tl->sb, " at\n");
118 1
        vcc_ErrWhere(tl, t_field);
119
}
120
121
void
122 917
vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs)
123
{
124
125 9170
        for (; fs->name != NULL; fs++) {
126 8253
                if (*fs->name == '!' && fs->found == NULL) {
127 1
                        VSB_printf(tl->sb,
128 1
                            "Mandatory field '%s' missing.\n", fs->name + 1);
129 1
                        tl->err = 1;
130
                }
131
        }
132 917
}