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