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 * SPDX-License-Identifier: BSD-2-Clause
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 */
32
33 #include "config.h"
34
35 #include <ctype.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
vxp_ErrToken(const struct vxp * vxp,const struct token * t)51 vxp_ErrToken(const struct vxp *vxp, const struct token *t)
52 {
53
54 if (t->tok == EOI)
55 VSB_cat(vxp->sb, "end of input");
56 else
57 VSB_printf(vxp->sb, "'%.*s'", PF(t));
58 }
59
60 static void
vxp_Pos(const struct vxp * vxp,struct vsb * vsb,const struct token * t,int tokoff)61 vxp_Pos(const struct vxp *vxp, struct vsb *vsb, const struct token *t,
62 int tokoff)
63 {
64 unsigned pos;
65
66 AN(vxp);
67 AN(vsb);
68 AN(t);
69 assert(t->b >= vxp->b);
70 pos = (unsigned)(t->b - vxp->b);
71 if (tokoff > 0)
72 pos += tokoff;
73 VSB_printf(vsb, "(Pos %u)", pos + 1);
74 }
75
76 static void
vxp_quote(const struct vxp * vxp,const char * b,const char * e,int tokoff)77 vxp_quote(const struct vxp *vxp, const char *b, const char *e, int tokoff)
78 {
79 const char *p;
80 char c;
81
82 assert(b <= e);
83 assert(b >= vxp->b);
84 assert(e <= vxp->e);
85 for (p = vxp->b; p < vxp->e; p++) {
86 if (isspace(*p))
87 VSB_putc(vxp->sb, ' ');
88 else
89 VSB_putc(vxp->sb, *p);
90 }
91 VSB_putc(vxp->sb, '\n');
92 for (p = vxp->b; p < vxp->e; p++) {
93 if (p >= b && p < e) {
94 if (p - b == tokoff)
95 c = '^';
96 else
97 c = '#';
98 } else
99 c = '-';
100 VSB_putc(vxp->sb, c);
101 }
102 VSB_putc(vxp->sb, '\n');
103 }
104
105 void
vxp_ErrWhere(struct vxp * vxp,const struct token * t,int tokoff)106 vxp_ErrWhere(struct vxp *vxp, const struct token *t, int tokoff)
107 {
108
109 AN(vxp);
110 AN(t);
111 vxp_Pos(vxp, vxp->sb, t, tokoff);
112 VSB_putc(vxp->sb, '\n');
113 vxp_quote(vxp, t->b, t->e, tokoff);
114 VSB_putc(vxp->sb, '\n');
115 vxp->err = 1;
116 }
117
118 void
vxp_NextToken(struct vxp * vxp)119 vxp_NextToken(struct vxp *vxp)
120 {
121
122 AN(vxp->t);
123 vxp->t = VTAILQ_NEXT(vxp->t, list);
124 if (vxp->t == NULL) {
125 VSB_cat(vxp->sb,
126 "Ran out of input, something is missing or"
127 " maybe unbalanced parenthesis\n");
128 vxp->err = 1;
129 }
130 }
131
132 void
vxp__Expect(struct vxp * vxp,unsigned tok)133 vxp__Expect(struct vxp *vxp, unsigned tok)
134 {
135
136 if (vxp->t->tok == tok)
137 return;
138 VSB_printf(vxp->sb, "Expected %s got ", vxp_tnames[tok]);
139 vxp_ErrToken(vxp, vxp->t);
140 VSB_putc(vxp->sb, ' ');
141 vxp_ErrWhere(vxp, vxp->t, -1);
142 }
143
144 static void
vxp_DoFree(struct vxp * vxp,void * p)145 vxp_DoFree(struct vxp *vxp, void *p)
146 {
147 struct membit *mb;
148
149 mb = calloc(1, sizeof *mb);
150 AN(mb);
151 mb->ptr = p;
152 VTAILQ_INSERT_TAIL(&vxp->membits, mb, list);
153 }
154
155 void *
vxp_Alloc(struct vxp * vxp,unsigned len)156 vxp_Alloc(struct vxp *vxp, unsigned len)
157 {
158 void *p;
159
160 p = calloc(1, len);
161 AN(p);
162 vxp_DoFree(vxp, p);
163 return (p);
164 }
165
166 static struct vxp *
vxp_New(struct vsb * sb)167 vxp_New(struct vsb *sb)
168 {
169 struct vxp *vxp;
170
171 AN(sb);
172
173 ALLOC_OBJ(vxp, VXP_MAGIC);
174 AN(vxp);
175 VTAILQ_INIT(&vxp->membits);
176 VTAILQ_INIT(&vxp->tokens);
177 vxp->sb = sb;
178
179 return (vxp);
180 }
181
182 static void
vxp_Delete(struct vxp ** pvxp)183 vxp_Delete(struct vxp **pvxp)
184 {
185 struct vxp *vxp;
186 struct membit *mb;
187
188 TAKE_OBJ_NOTNULL(vxp, pvxp, VXP_MAGIC);
189
190 while (!VTAILQ_EMPTY(&vxp->membits)) {
191 mb = VTAILQ_FIRST(&vxp->membits);
192 VTAILQ_REMOVE(&vxp->membits, mb, list);
193 free(mb->ptr);
194 free(mb);
195 }
196
197 FREE_OBJ(vxp);
198 }
199
200 struct vex *
vex_New(const char * query,struct vsb * sb,unsigned options)201 vex_New(const char *query, struct vsb *sb, unsigned options)
202 {
203 struct vxp *vxp;
204 struct vex *vex;
205
206 AN(query);
207 AN(sb);
208 vxp = vxp_New(sb);
209 vxp->b = query;
210 vxp->e = query + strlen(query);
211 vxp->vex_options = options;
212 if (options & VEX_OPT_CASELESS)
213 vxp->vre_options |= VRE_CASELESS;
214
215 vxp_Lexer(vxp);
216
217 #ifdef VXP_DEBUG
218 vxp_PrintTokens(vxp);
219 #endif
220
221 if (vxp->err) {
222 vxp_Delete(&vxp);
223 AZ(vxp);
224 return (NULL);
225 }
226
227 vex = vxp_Parse(vxp);
228
229 #ifdef VXP_DEBUG
230 if (vex != NULL)
231 vex_PrintTree(vex);
232 #endif
233
234 vxp_Delete(&vxp);
235 AZ(vxp);
236
237 return (vex);
238 }
239