1 /*-
2  * Copyright (c) 2006 Verdens Gang AS
3  * Copyright (c) 2006-2015 Varnish Software AS
4  * All rights reserved.
5  *
6  * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
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 #include "config.h"
33 
34 #include <string.h>
35 
36 #include "vcc_compile.h"
37 
38 /*--------------------------------------------------------------------*/
39 
40 static void vcc_Compound(struct vcc *tl);
41 
42 /*--------------------------------------------------------------------*/
43 
44 #define L(tl, foo)	do {	\
45 	tl->indent += INDENT;	\
46 	foo;			\
47 	tl->indent -= INDENT;	\
48 } while (0)
49 
50 #define C(tl, sep)	do {					\
51 	Fb(tl, 1, "VPI_count(ctx, %u)%s\n", ++tl->cnt, sep);	\
52 	tl->t->cnt = tl->cnt;					\
53 } while (0)
54 
55 /*--------------------------------------------------------------------
56  * SYNTAX:
57  *    Conditional:
58  *	'(' Cond_0 ')'
59  */
60 
61 static void
vcc_Conditional(struct vcc * tl)62 vcc_Conditional(struct vcc *tl)
63 {
64 
65 	SkipToken(tl, '(');
66 	Fb(tl, 0, "(\n");
67 	L(tl, vcc_Expr(tl, BOOL));
68 	ERRCHK(tl);
69 	Fb(tl, 1, ")\n");
70 	SkipToken(tl, ')');
71 }
72 
73 /*--------------------------------------------------------------------
74  * SYNTAX:
75  *    IfStmt:
76  *	'if' Conditional  Compound Branch1* Branch2
77  *    Branch1:
78  *      'elseif' Conditional Compound
79  *    Branch2:
80  *      'else' Compound
81  *	null
82  */
83 
v_matchproto_(sym_act_f)84 void v_matchproto_(sym_act_f)
85 vcc_Act_If(struct vcc *tl, struct token *t, struct symbol *sym)
86 {
87 
88 	(void)t;
89 	(void)sym;
90 	Fb(tl, 1, "if ");
91 	vcc_Conditional(tl);
92 	ERRCHK(tl);
93 	L(tl, vcc_Compound(tl));
94 	ERRCHK(tl);
95 	while (tl->t->tok == ID) {
96 		if (vcc_IdIs(tl->t, "else")) {
97 			vcc_NextToken(tl);
98 			if (tl->t->tok == '{') {
99 				Fb(tl, 1, "else\n");
100 				L(tl, vcc_Compound(tl));
101 				ERRCHK(tl);
102 				return;
103 			}
104 			if (tl->t->tok != ID || !vcc_IdIs(tl->t, "if")) {
105 				VSB_printf(tl->sb,
106 				    "'else' must be followed by 'if' or '{'\n");
107 				vcc_ErrWhere(tl, tl->t);
108 				return;
109 			}
110 			Fb(tl, 1, "else if ");
111 			vcc_NextToken(tl);
112 			vcc_Conditional(tl);
113 			ERRCHK(tl);
114 			L(tl, vcc_Compound(tl));
115 			ERRCHK(tl);
116 		} else if (vcc_IdIs(tl->t, "elseif") ||
117 		     vcc_IdIs(tl->t, "elsif") ||
118 		     vcc_IdIs(tl->t, "elif")) {
119 			Fb(tl, 1, "else if ");
120 			vcc_NextToken(tl);
121 			vcc_Conditional(tl);
122 			ERRCHK(tl);
123 			L(tl, vcc_Compound(tl));
124 			ERRCHK(tl);
125 		} else {
126 			break;
127 		}
128 	}
129 	C(tl, ";");
130 }
131 
132 /*--------------------------------------------------------------------
133  * SYNTAX:
134  *    Compound:
135  *	'{' Stmt* '}'
136  *
137  *    Stmt:
138  *	Compound
139  *	IfStmt
140  *	CSRC
141  *	Id(Action) (XXX)
142  */
143 
144 static void
vcc_Compound(struct vcc * tl)145 vcc_Compound(struct vcc *tl)
146 {
147 	struct symbol *sym;
148 	struct token *t;
149 
150 	SkipToken(tl, '{');
151 	Fb(tl, 1, "{\n");
152 	tl->indent += INDENT;
153 	C(tl, ";");
154 	Fb(tl, 1, "END_;\n");
155 	while (1) {
156 		ERRCHK(tl);
157 		t = tl->t;
158 		switch (tl->t->tok) {
159 		case '{':
160 			vcc_Compound(tl);
161 			break;
162 		case '}':
163 			vcc_NextToken(tl);
164 			tl->indent -= INDENT;
165 			Fb(tl, 1, "}\n");
166 			return;
167 		case CSRC:
168 			if (tl->allow_inline_c) {
169 				Fb(tl, 1, "%.*s\n",
170 				    (int) (tl->t->e - (tl->t->b + 2)),
171 				    tl->t->b + 1);
172 				vcc_NextToken(tl);
173 			} else {
174 				VSB_printf(tl->sb,
175 				    "Inline-C not allowed\n");
176 				vcc_ErrWhere(tl, tl->t);
177 			}
178 			break;
179 		case EOI:
180 			VSB_printf(tl->sb,
181 			    "End of input while in compound statement\n");
182 			tl->err = 1;
183 			return;
184 		case ID:
185 			sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_NONE,
186 			    SYMTAB_PARTIAL, XREF_NONE);
187 			if (sym == NULL) {
188 				VSB_printf(tl->sb, "Symbol not found.\n");
189 				vcc_ErrWhere(tl, tl->t);
190 				return;
191 			}
192 			if (sym->action == NULL) {
193 				VSB_printf(tl->sb,
194 				    "Symbol cannot be used here.\n");
195 				vcc_ErrWhere(tl, tl->t);
196 				return;
197 			}
198 			if (sym->action_mask != 0)
199 				vcc_AddUses(tl, t, NULL, sym, XREF_ACTION);
200 			sym->action(tl, t, sym);
201 			break;
202 		default:
203 			/* We deliberately do not mention inline C */
204 			VSB_printf(tl->sb,
205 			    "Expected an action, 'if', '{' or '}'\n");
206 			vcc_ErrWhere(tl, tl->t);
207 			return;
208 		}
209 		Fb(tl, 1, "END_;\n");
210 	}
211 }
212 
213 /*--------------------------------------------------------------------
214  * SYNTAX:
215  *    Function:
216  *	'sub' ID(name) Compound
217  */
218 
219 static void
vcc_ParseFunction(struct vcc * tl)220 vcc_ParseFunction(struct vcc *tl)
221 {
222 	struct symbol *sym, *bsym;
223 	struct token *t;
224 	struct proc *p;
225 
226 	vcc_NextToken(tl);
227 	vcc_ExpectVid(tl, "subroutine");
228 	ERRCHK(tl);
229 
230 	t = tl->t;
231 	sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_SUB, SYMTAB_CREATE, XREF_DEF);
232 	ERRCHK(tl);
233 	AN(sym);
234 
235 	if (vcc_builtin != NULL) {
236 		vcc_builtin->t = t;
237 		bsym = VCC_SymbolGet(vcc_builtin, SYM_MAIN, SYM_SUB,
238 		    SYMTAB_NOERR, XREF_NONE);
239 		AZ(vcc_builtin->err);
240 	}
241 	else
242 		bsym = NULL;
243 
244 	p = sym->proc;
245 	if (p == NULL) {
246 		if (vcc_builtin != NULL && bsym == NULL &&
247 		    (t->b[0] == 'v'|| t->b[0] == 'V') &&
248 		    (t->b[1] == 'c'|| t->b[1] == 'C') &&
249 		    (t->b[2] == 'l'|| t->b[2] == 'L') &&
250 		    (t->b[3] == '_')) {
251 			VSB_printf(tl->sb,"The names 'vcl_*'"
252 			    " are reserved for subroutines.\n");
253 			vcc_ErrWhere(tl, t);
254 			VSB_printf(tl->sb, "Valid vcl_* subroutines are:\n");
255 			VTAILQ_FOREACH(p, &vcc_builtin->procs, list) {
256 				t = p->name;
257 				VSB_printf(tl->sb, "\t%.*s\n",
258 				    (int)pdiff(t->b, t->e), t->b);
259 			}
260 			return;
261 		}
262 		VCC_GlobalSymbol(sym, SUB, "VGC_function");
263 		p = vcc_NewProc(tl, sym);
264 		p->name = t;
265 		VSB_printf(p->cname, "%s", sym->lname);
266 	} else if (p->method == NULL && bsym == NULL) {
267 		VSB_printf(tl->sb, "Subroutine '%s' redefined\n", sym->name);
268 		vcc_ErrWhere(tl, t);
269 		VSB_printf(tl->sb, "Previously defined here:\n");
270 		vcc_ErrWhere(tl, p->name);
271 		return;
272 	} else {
273 		/* Add to VCL sub */
274 		if (p->name == NULL)
275 			p->name = t;
276 	}
277 	CHECK_OBJ_NOTNULL(p, PROC_MAGIC);
278 	tl->fb = p->body;
279 	Fb(tl, 1, "  /* ... from ");
280 	vcc_Coord(tl, p->body, NULL);
281 	Fb(tl, 0, " */\n");
282 	tl->curproc = p;
283 	tl->indent += INDENT;
284 	Fb(tl, 1, "{\n");
285 	L(tl, vcc_Compound(tl));
286 	Fb(tl, 1, "}\n");
287 	tl->indent -= INDENT;
288 	tl->fb = NULL;
289 	tl->curproc = NULL;
290 }
291 
292 /*--------------------------------------------------------------------
293  */
294 
295 static void
vcc_ParseVcl(struct vcc * tl)296 vcc_ParseVcl(struct vcc *tl)
297 {
298 	struct token *tok0;
299 	int syntax;
300 
301 	assert(vcc_IdIs(tl->t, "vcl"));
302 	tok0 = tl->t;
303 	vcc_NextToken(tl);
304 
305 	Expect(tl, FNUM);
306 	if (tl->t->e - tl->t->b != 3 || tl->t->b[1] != '.') {
307 		VSB_cat(tl->sb,
308 		    "Don't play silly buggers with VCL version numbers\n");
309 		vcc_ErrWhere(tl, tl->t);
310 		ERRCHK(tl);
311 	}
312 	syntax = (tl->t->b[0] - '0') * 10 + (tl->t->b[2] - '0');
313 	vcc_NextToken(tl);
314 
315 	if (syntax < VCL_LOW || syntax > VCL_HIGH) {
316 		VSB_printf(tl->sb, "VCL version %.1f not supported.\n",
317 		    .1 * syntax);
318 		vcc_ErrWhere2(tl, tok0, tl->t);
319 		ERRCHK(tl);
320 	}
321 
322 	if (tl->t->tok != ';') {
323 		/* Special handling, because next token might be 'vcl'
324 		 * in the built-in VCL, and that would give a very
325 		 * confusing error message
326 		 */
327 		VSB_cat(tl->sb, "Expected 'vcl N.N;' found no semi-colon\n");
328 		vcc_ErrWhere2(tl, tok0, tl->t);
329 		ERRCHK(tl);
330 	}
331 	vcc_NextToken(tl);
332 	if (tl->syntax == 0)
333 		tl->syntax = syntax;
334 	if (syntax > tl->syntax) {
335 		VSB_printf(tl->sb,
336 		    "VCL version %.1f higher than"
337 		    " the top level version %.1f\n",
338 		    .1 * syntax, .1 * tl->syntax);
339 		vcc_ErrWhere2(tl, tok0, tl->t);
340 		ERRCHK(tl);
341 	}
342 }
343 
344 /*--------------------------------------------------------------------
345  * Top level of parser, recognize:
346  *	Inline C-code
347  *	ACL definitions
348  *	Function definitions
349  *	Backend definitions
350  *	VMOD import directives
351  *	VCL version declarations
352  *	End of input
353  */
354 
355 typedef void parse_f(struct vcc *tl);
356 
357 static struct toplev {
358 	const char	*name;
359 	parse_f		*func;
360 	unsigned	vcllo;
361 	unsigned	vclhi;
362 } toplev[] = {
363 	{ "acl",		vcc_ParseAcl,		VCL_41,	VCL_HIGH },
364 	{ "sub",		vcc_ParseFunction,	VCL_41,	VCL_HIGH },
365 	{ "backend",		vcc_ParseBackend,	VCL_41,	VCL_HIGH },
366 	{ "probe",		vcc_ParseProbe,		VCL_41,	VCL_HIGH },
367 	{ "import",		vcc_ParseImport,	VCL_41,	VCL_HIGH },
368 	{ "vcl",		vcc_ParseVcl,		VCL_41,	VCL_HIGH },
369 	{ NULL, NULL }
370 };
371 
372 void
vcc_Parse(struct vcc * tl)373 vcc_Parse(struct vcc *tl)
374 {
375 	struct toplev *tp;
376 
377 	AZ(tl->indent);
378 	if (tl->t->tok != ID || !vcc_IdIs(tl->t, "vcl")) {
379 		VSB_cat(tl->sb,
380 		    "VCL version declaration missing\n"
381 		    "Update your VCL to Version 4 syntax, and add\n"
382 		    "\tvcl 4.1;\n"
383 		    "on the first line of the VCL files.\n"
384 		);
385 		vcc_ErrWhere(tl, tl->t);
386 		ERRCHK(tl);
387 	}
388 	vcc_ParseVcl(tl);
389 	ERRCHK(tl);
390 	AN(tl->syntax);
391 	while (tl->t->tok != EOI) {
392 		ERRCHK(tl);
393 		switch (tl->t->tok) {
394 		case CSRC:
395 			if (tl->allow_inline_c) {
396 				Fc(tl, 0, "%.*s\n",
397 				    (int) (tl->t->e - (tl->t->b + 4)),
398 				    tl->t->b + 2);
399 				vcc_NextToken(tl);
400 			} else {
401 				VSB_cat(tl->sb, "Inline-C not allowed\n");
402 				vcc_ErrWhere(tl, tl->t);
403 			}
404 			break;
405 		case EOI:
406 			break;
407 		case ID:
408 			for (tp = toplev; tp->name != NULL; tp++) {
409 				if (tp->func == NULL)
410 					continue;
411 				if (!vcc_IdIs(tl->t, tp->name))
412 					continue;
413 				tp->func(tl);
414 				break;
415 			}
416 			if (tp->name != NULL)
417 				break;
418 			/* FALLTHROUGH */
419 		default:
420 			/* We deliberately do not mention inline-C */
421 			VSB_cat(tl->sb, "Expected one of\n\t");
422 			for (tp = toplev; tp->name != NULL; tp++) {
423 				if (tp[1].name == NULL)
424 					VSB_cat(tl->sb, " or ");
425 				VSB_printf(tl->sb, "'%s'", tp->name);
426 				if (tp[1].name != NULL)
427 					VSB_cat(tl->sb, ", ");
428 			}
429 			VSB_cat(tl->sb, "\nFound: ");
430 			vcc_ErrToken(tl, tl->t);
431 			VSB_cat(tl->sb, " at\n");
432 			vcc_ErrWhere(tl, tl->t);
433 			return;
434 		}
435 	}
436 	AZ(tl->indent);
437 }
438 
439 void
vcc_Parse_Init(struct vcc * tl)440 vcc_Parse_Init(struct vcc *tl)
441 {
442 	struct toplev *tp;
443 
444 	for (tp = toplev; tp->name != NULL; tp++)
445 		AN(VCC_MkSym(tl, tp->name, SYM_MAIN, SYM_RESERVED,
446 		    tp->vcllo, tp->vclhi));
447 }
448