varnish-cache/lib/libvarnishapi/vxp.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Martin Blix Grydeland <martin@varnish-software.com>
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 <ctype.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <unistd.h> /* for MUSL */
37
38
#include "vdef.h"
39
#include "vas.h"
40
#include "miniobj.h"
41
42
#include "vqueue.h"
43
#include "vre.h"
44
#include "vsb.h"
45
46
#include "vxp.h"
47
48
static void
49 0
vxp_ErrToken(const struct vxp *vxp, const struct token *t)
50
{
51
52 0
        if (t->tok == EOI)
53 0
                VSB_printf(vxp->sb, "end of input");
54
        else
55 0
                VSB_printf(vxp->sb, "'%.*s'", PF(t));
56 0
}
57
58
static void
59 9
vxp_Pos(const struct vxp *vxp, struct vsb *vsb, const struct token *t,
60
    int tokoff)
61
{
62
        unsigned pos;
63
64 9
        AN(vxp);
65 9
        AN(vsb);
66 9
        AN(t);
67 9
        assert(t->b >= vxp->b);
68 9
        pos = (unsigned)(t->b - vxp->b);
69 9
        if (tokoff > 0)
70 0
                pos += tokoff;
71 9
        VSB_printf(vsb, "(Pos %u)", pos + 1);
72 9
}
73
74
static void
75 9
vxp_quote(const struct vxp *vxp, const char *b, const char *e, int tokoff)
76
{
77
        const char *p;
78
        char c;
79
80 9
        assert(b <= e);
81 9
        assert(b >= vxp->b);
82 9
        assert(e <= vxp->e);
83 132
        for (p = vxp->b; p < vxp->e; p++) {
84 123
                if (isspace(*p))
85 18
                        VSB_putc(vxp->sb, ' ');
86
                else
87 105
                        VSB_putc(vxp->sb, *p);
88
        }
89 9
        VSB_putc(vxp->sb, '\n');
90 132
        for (p = vxp->b; p < vxp->e; p++) {
91 123
                if (p >= b && p < e) {
92 38
                        if (p - b == tokoff)
93 1
                                c = '^';
94
                        else
95 18
                                c = '#';
96
                } else
97 104
                        c = '-';
98 123
                VSB_putc(vxp->sb, c);
99
        }
100 9
        VSB_putc(vxp->sb, '\n');
101 9
}
102
103
void
104 9
vxp_ErrWhere(struct vxp *vxp, const struct token *t, int tokoff)
105
{
106
107 9
        AN(vxp);
108 9
        AN(t);
109 9
        vxp_Pos(vxp, vxp->sb, t, tokoff);
110 9
        VSB_putc(vxp->sb, '\n');
111 9
        vxp_quote(vxp, t->b, t->e, tokoff);
112 9
        VSB_putc(vxp->sb, '\n');
113 9
        vxp->err = 1;
114 9
}
115
116
void
117 198
vxp_NextToken(struct vxp *vxp)
118
{
119
120 198
        AN(vxp->t);
121 198
        vxp->t = VTAILQ_NEXT(vxp->t, list);
122 198
        if (vxp->t == NULL) {
123 0
                VSB_printf(vxp->sb,
124
                    "Ran out of input, something is missing or"
125
                    " maybe unbalanced parenthesis\n");
126 0
                vxp->err = 1;
127
        }
128 198
}
129
130
void
131 65
vxp__Expect(struct vxp *vxp, unsigned tok)
132
{
133
134 65
        if (vxp->t->tok == tok)
135 65
                return;
136 0
        VSB_printf(vxp->sb, "Expected %s got ", vxp_tnames[tok]);
137 0
        vxp_ErrToken(vxp, vxp->t);
138 0
        VSB_putc(vxp->sb, ' ');
139 0
        vxp_ErrWhere(vxp, vxp->t, -1);
140
}
141
142
static void
143 403
vxp_DoFree(struct vxp *vxp, void *p)
144
{
145
        struct membit *mb;
146
147 403
        mb = calloc(1, sizeof *mb);
148 403
        AN(mb);
149 403
        mb->ptr = p;
150 403
        VTAILQ_INSERT_TAIL(&vxp->membits, mb, list);
151 403
}
152
153
void *
154 403
vxp_Alloc(struct vxp *vxp, unsigned len)
155
{
156
        void *p;
157
158 403
        p = calloc(1, len);
159 403
        AN(p);
160 403
        vxp_DoFree(vxp, p);
161 403
        return (p);
162
}
163
164
static struct vxp *
165 65
vxp_New(struct vsb *sb)
166
{
167
        struct vxp *vxp;
168
169 65
        AN(sb);
170
171 65
        ALLOC_OBJ(vxp, VXP_MAGIC);
172 65
        AN(vxp);
173 65
        VTAILQ_INIT(&vxp->membits);
174 65
        VTAILQ_INIT(&vxp->tokens);
175 65
        vxp->sb = sb;
176
177 65
        return (vxp);
178
}
179
180
static void
181 65
vxp_Delete(struct vxp **pvxp)
182
{
183
        struct vxp *vxp;
184
        struct membit *mb;
185
186 65
        TAKE_OBJ_NOTNULL(vxp, pvxp, VXP_MAGIC);
187
188 533
        while (!VTAILQ_EMPTY(&vxp->membits)) {
189 403
                mb = VTAILQ_FIRST(&vxp->membits);
190 403
                VTAILQ_REMOVE(&vxp->membits, mb, list);
191 403
                free(mb->ptr);
192 403
                free(mb);
193
        }
194
195 65
        FREE_OBJ(vxp);
196 65
}
197
198
struct vex *
199 65
vex_New(const char *query, struct vsb *sb, unsigned options)
200
{
201
        struct vxp *vxp;
202
        struct vex *vex;
203
204 65
        AN(query);
205 65
        AN(sb);
206 65
        vxp = vxp_New(sb);
207 65
        vxp->b = query;
208 65
        vxp->e = query + strlen(query);
209 65
        vxp->vex_options = options;
210 65
        if (options & VEX_OPT_CASELESS)
211 0
                vxp->vre_options |= VRE_CASELESS;
212
213 65
        vxp_Lexer(vxp);
214
215
#ifdef VXP_DEBUG
216
        vxp_PrintTokens(vxp);
217
#endif
218
219 65
        if (vxp->err) {
220 0
                vxp_Delete(&vxp);
221 0
                AZ(vxp);
222 0
                return (NULL);
223
        }
224
225 65
        vex = vxp_Parse(vxp);
226
227
#ifdef VXP_DEBUG
228
        if (vex != NULL)
229
                vex_PrintTree(vex);
230
#endif
231
232 65
        vxp_Delete(&vxp);
233 65
        AZ(vxp);
234
235 65
        return (vex);
236
}