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