• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * *****************************************************************************
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2018-2021 Gavin D. Howard and contributors.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * * Redistributions of source code must retain the above copyright notice, this
12  *   list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright notice,
15  *   this list of conditions and the following disclaimer in the documentation
16  *   and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * *****************************************************************************
31  *
32  * The parser for bc.
33  *
34  */
35 
36 #if BC_ENABLED
37 
38 #include <assert.h>
39 #include <stdbool.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 #include <setjmp.h>
44 
45 #include <bc.h>
46 #include <num.h>
47 #include <vm.h>
48 
49 static void bc_parse_else(BcParse *p);
50 static void bc_parse_stmt(BcParse *p);
51 static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
52                                        BcParseNext next);
53 
bc_parse_inst_isLeaf(BcInst t)54 static bool bc_parse_inst_isLeaf(BcInst t) {
55 	return (t >= BC_INST_NUM && t <= BC_INST_MAXSCALE) ||
56 #if BC_ENABLE_EXTRA_MATH
57 	        t == BC_INST_TRUNC ||
58 #endif // BC_ENABLE_EXTRA_MATH
59 	        t <= BC_INST_DEC;
60 }
61 
bc_parse_isDelimiter(const BcParse * p)62 static bool bc_parse_isDelimiter(const BcParse *p) {
63 
64 	BcLexType t = p->l.t;
65 	bool good = false;
66 
67 	if (BC_PARSE_DELIMITER(t)) return true;
68 
69 	if (t == BC_LEX_KW_ELSE) {
70 
71 		size_t i;
72 		uint16_t *fptr = NULL, flags = BC_PARSE_FLAG_ELSE;
73 
74 		for (i = 0; i < p->flags.len && BC_PARSE_BLOCK_STMT(flags); ++i) {
75 
76 			fptr = bc_vec_item_rev(&p->flags, i);
77 			flags = *fptr;
78 
79 			if ((flags & BC_PARSE_FLAG_BRACE) && p->l.last != BC_LEX_RBRACE)
80 				return false;
81 		}
82 
83 		good = ((flags & BC_PARSE_FLAG_IF) != 0);
84 	}
85 	else if (t == BC_LEX_RBRACE) {
86 
87 		size_t i;
88 
89 		for (i = 0; !good && i < p->flags.len; ++i) {
90 			uint16_t *fptr = bc_vec_item_rev(&p->flags, i);
91 			good = (((*fptr) & BC_PARSE_FLAG_BRACE) != 0);
92 		}
93 	}
94 
95 	return good;
96 }
97 
bc_parse_setLabel(BcParse * p)98 static void bc_parse_setLabel(BcParse *p) {
99 
100 	BcFunc *func = p->func;
101 	BcInstPtr *ip = bc_vec_top(&p->exits);
102 	size_t *label;
103 
104 	assert(func == bc_vec_item(&p->prog->fns, p->fidx));
105 
106 	label = bc_vec_item(&func->labels, ip->idx);
107 	*label = func->code.len;
108 
109 	bc_vec_pop(&p->exits);
110 }
111 
bc_parse_createLabel(BcParse * p,size_t idx)112 static void bc_parse_createLabel(BcParse *p, size_t idx) {
113 	bc_vec_push(&p->func->labels, &idx);
114 }
115 
bc_parse_createCondLabel(BcParse * p,size_t idx)116 static void bc_parse_createCondLabel(BcParse *p, size_t idx) {
117 	bc_parse_createLabel(p, p->func->code.len);
118 	bc_vec_push(&p->conds, &idx);
119 }
120 
bc_parse_createExitLabel(BcParse * p,size_t idx,bool loop)121 static void bc_parse_createExitLabel(BcParse *p, size_t idx, bool loop) {
122 
123 	BcInstPtr ip;
124 
125 	assert(p->func == bc_vec_item(&p->prog->fns, p->fidx));
126 
127 	ip.func = loop;
128 	ip.idx = idx;
129 	ip.len = 0;
130 
131 	bc_vec_push(&p->exits, &ip);
132 	bc_parse_createLabel(p, SIZE_MAX);
133 }
134 
bc_parse_operator(BcParse * p,BcLexType type,size_t start,size_t * nexprs)135 static void bc_parse_operator(BcParse *p, BcLexType type,
136                               size_t start, size_t *nexprs)
137 {
138 	BcLexType t;
139 	uchar l, r = BC_PARSE_OP_PREC(type);
140 	uchar left = BC_PARSE_OP_LEFT(type);
141 
142 	while (p->ops.len > start) {
143 
144 		t = BC_PARSE_TOP_OP(p);
145 		if (t == BC_LEX_LPAREN) break;
146 
147 		l = BC_PARSE_OP_PREC(t);
148 		if (l >= r && (l != r || !left)) break;
149 
150 		bc_parse_push(p, BC_PARSE_TOKEN_INST(t));
151 		bc_vec_pop(&p->ops);
152 		*nexprs -= !BC_PARSE_OP_PREFIX(t);
153 	}
154 
155 	bc_vec_push(&p->ops, &type);
156 }
157 
bc_parse_rightParen(BcParse * p,size_t * nexs)158 static void bc_parse_rightParen(BcParse *p, size_t *nexs) {
159 
160 	BcLexType top;
161 
162 	while ((top = BC_PARSE_TOP_OP(p)) != BC_LEX_LPAREN) {
163 		bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
164 		bc_vec_pop(&p->ops);
165 		*nexs -= !BC_PARSE_OP_PREFIX(top);
166 	}
167 
168 	bc_vec_pop(&p->ops);
169 
170 	bc_lex_next(&p->l);
171 }
172 
bc_parse_params(BcParse * p,uint8_t flags)173 static void bc_parse_params(BcParse *p, uint8_t flags) {
174 
175 	bool comma = false;
176 	size_t nparams;
177 
178 	bc_lex_next(&p->l);
179 
180 	flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
181 	flags |= (BC_PARSE_ARRAY | BC_PARSE_NEEDVAL);
182 
183 	for (nparams = 0; p->l.t != BC_LEX_RPAREN; ++nparams) {
184 
185 		bc_parse_expr_status(p, flags, bc_parse_next_param);
186 
187 		comma = (p->l.t == BC_LEX_COMMA);
188 		if (comma) bc_lex_next(&p->l);
189 	}
190 
191 	if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
192 	bc_parse_push(p, BC_INST_CALL);
193 	bc_parse_pushIndex(p, nparams);
194 }
195 
bc_parse_call(BcParse * p,const char * name,uint8_t flags)196 static void bc_parse_call(BcParse *p, const char *name, uint8_t flags) {
197 
198 	size_t idx;
199 
200 	bc_parse_params(p, flags);
201 
202 	// We just assert this because bc_parse_params() should
203 	// ensure that the next token is what it should be.
204 	assert(p->l.t == BC_LEX_RPAREN);
205 
206 	// We cannot use bc_program_insertFunc() here
207 	// because it will overwrite an existing function.
208 	idx = bc_map_index(&p->prog->fn_map, name);
209 
210 	if (idx == BC_VEC_INVALID_IDX) {
211 
212 		BC_SIG_LOCK;
213 
214 		idx = bc_program_insertFunc(p->prog, name);
215 
216 		BC_SIG_UNLOCK;
217 
218 		assert(idx != BC_VEC_INVALID_IDX);
219 
220 		// Make sure that this pointer was not invalidated.
221 		p->func = bc_vec_item(&p->prog->fns, p->fidx);
222 	}
223 	else idx = ((BcId*) bc_vec_item(&p->prog->fn_map, idx))->idx;
224 
225 	bc_parse_pushIndex(p, idx);
226 
227 	bc_lex_next(&p->l);
228 }
229 
bc_parse_name(BcParse * p,BcInst * type,bool * can_assign,uint8_t flags)230 static void bc_parse_name(BcParse *p, BcInst *type,
231                           bool *can_assign, uint8_t flags)
232 {
233 	char *name;
234 
235 	BC_SIG_LOCK;
236 
237 	name = bc_vm_strdup(p->l.str.v);
238 
239 	BC_SETJMP_LOCKED(err);
240 
241 	BC_SIG_UNLOCK;
242 
243 	bc_lex_next(&p->l);
244 
245 	if (p->l.t == BC_LEX_LBRACKET) {
246 
247 		bc_lex_next(&p->l);
248 
249 		if (p->l.t == BC_LEX_RBRACKET) {
250 
251 			if (BC_ERR(!(flags & BC_PARSE_ARRAY)))
252 				bc_parse_err(p, BC_ERR_PARSE_EXPR);
253 
254 			*type = BC_INST_ARRAY;
255 			*can_assign = false;
256 		}
257 		else {
258 
259 			uint8_t flags2 = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) |
260 			    BC_PARSE_NEEDVAL;
261 
262 			bc_parse_expr_status(p, flags2, bc_parse_next_elem);
263 
264 			if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
265 				bc_parse_err(p, BC_ERR_PARSE_TOKEN);
266 
267 			*type = BC_INST_ARRAY_ELEM;
268 			*can_assign = true;
269 		}
270 
271 		bc_lex_next(&p->l);
272 
273 		bc_parse_push(p, *type);
274 		bc_parse_pushName(p, name, false);
275 	}
276 	else if (p->l.t == BC_LEX_LPAREN) {
277 
278 		if (BC_ERR(flags & BC_PARSE_NOCALL))
279 			bc_parse_err(p, BC_ERR_PARSE_TOKEN);
280 
281 		*type = BC_INST_CALL;
282 		*can_assign = false;
283 
284 		bc_parse_call(p, name, flags);
285 	}
286 	else {
287 		*type = BC_INST_VAR;
288 		*can_assign = true;
289 		bc_parse_push(p, BC_INST_VAR);
290 		bc_parse_pushName(p, name, true);
291 	}
292 
293 err:
294 	BC_SIG_MAYLOCK;
295 	free(name);
296 	BC_LONGJMP_CONT;
297 }
298 
bc_parse_noArgBuiltin(BcParse * p,BcInst inst)299 static void bc_parse_noArgBuiltin(BcParse *p, BcInst inst) {
300 
301 	bc_lex_next(&p->l);
302 	if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
303 
304 	bc_lex_next(&p->l);
305 	if ((p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
306 
307 	bc_parse_push(p, inst);
308 
309 	bc_lex_next(&p->l);
310 }
311 
bc_parse_builtin(BcParse * p,BcLexType type,uint8_t flags,BcInst * prev)312 static void bc_parse_builtin(BcParse *p, BcLexType type,
313                              uint8_t flags, BcInst *prev)
314 {
315 	bc_lex_next(&p->l);
316 	if (BC_ERR(p->l.t != BC_LEX_LPAREN))
317 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
318 
319 	bc_lex_next(&p->l);
320 
321 	flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
322 	flags |= BC_PARSE_NEEDVAL;
323 	if (type == BC_LEX_KW_LENGTH) flags |= BC_PARSE_ARRAY;
324 
325 	bc_parse_expr_status(p, flags, bc_parse_next_rel);
326 
327 	if (BC_ERR(p->l.t != BC_LEX_RPAREN))
328 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
329 
330 	*prev = type - BC_LEX_KW_LENGTH + BC_INST_LENGTH;
331 	bc_parse_push(p, *prev);
332 
333 	bc_lex_next(&p->l);
334 }
335 
bc_parse_scale(BcParse * p,BcInst * type,bool * can_assign,uint8_t flags)336 static void bc_parse_scale(BcParse *p, BcInst *type,
337                                bool *can_assign, uint8_t flags)
338 {
339 	bc_lex_next(&p->l);
340 
341 	if (p->l.t != BC_LEX_LPAREN) {
342 		*type = BC_INST_SCALE;
343 		*can_assign = true;
344 		bc_parse_push(p, BC_INST_SCALE);
345 		return;
346 	}
347 
348 	*type = BC_INST_SCALE_FUNC;
349 	*can_assign = false;
350 	flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
351 	flags |= BC_PARSE_NEEDVAL;
352 
353 	bc_lex_next(&p->l);
354 
355 	bc_parse_expr_status(p, flags, bc_parse_next_rel);
356 	if (BC_ERR(p->l.t != BC_LEX_RPAREN))
357 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
358 
359 	bc_parse_push(p, BC_INST_SCALE_FUNC);
360 
361 	bc_lex_next(&p->l);
362 }
363 
bc_parse_incdec(BcParse * p,BcInst * prev,bool * can_assign,size_t * nexs,uint8_t flags)364 static void bc_parse_incdec(BcParse *p, BcInst *prev, bool *can_assign,
365                             size_t *nexs, uint8_t flags)
366 {
367 	BcLexType type;
368 	uchar inst;
369 	BcInst etype = *prev;
370 	BcLexType last = p->l.last;
371 
372 	assert(prev != NULL && can_assign != NULL);
373 
374 	if (BC_ERR(last == BC_LEX_OP_INC || last == BC_LEX_OP_DEC ||
375 	           last == BC_LEX_RPAREN))
376 	{
377 		bc_parse_err(p, BC_ERR_PARSE_ASSIGN);
378 	}
379 
380 	if (BC_PARSE_INST_VAR(etype)) {
381 
382 		if (!*can_assign) bc_parse_err(p, BC_ERR_PARSE_ASSIGN);
383 
384 		*prev = inst = BC_INST_INC + (p->l.t != BC_LEX_OP_INC);
385 		bc_parse_push(p, inst);
386 		bc_lex_next(&p->l);
387 		*can_assign = false;
388 	}
389 	else {
390 
391 		*prev = inst = BC_INST_ASSIGN_PLUS + (p->l.t != BC_LEX_OP_INC);
392 
393 		bc_lex_next(&p->l);
394 		type = p->l.t;
395 
396 		// Because we parse the next part of the expression
397 		// right here, we need to increment this.
398 		*nexs = *nexs + 1;
399 
400 		if (type == BC_LEX_NAME) {
401 			uint8_t flags2 = flags & ~BC_PARSE_ARRAY;
402 			bc_parse_name(p, prev, can_assign, flags2 | BC_PARSE_NOCALL);
403 		}
404 		else if (type >= BC_LEX_KW_LAST && type <= BC_LEX_KW_OBASE) {
405 			bc_parse_push(p, type - BC_LEX_KW_LAST + BC_INST_LAST);
406 			bc_lex_next(&p->l);
407 		}
408 		else if (BC_NO_ERR(type == BC_LEX_KW_SCALE)) {
409 
410 			bc_lex_next(&p->l);
411 
412 			if (BC_ERR(p->l.t == BC_LEX_LPAREN))
413 				bc_parse_err(p, BC_ERR_PARSE_TOKEN);
414 			else bc_parse_push(p, BC_INST_SCALE);
415 		}
416 		else bc_parse_err(p, BC_ERR_PARSE_TOKEN);
417 
418 		*can_assign = false;
419 
420 		bc_parse_push(p, BC_INST_ONE);
421 		bc_parse_push(p, inst);
422 	}
423 }
424 
bc_parse_minus(BcParse * p,BcInst * prev,size_t ops_bgn,bool rparen,bool binlast,size_t * nexprs)425 static void bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn,
426                            bool rparen, bool binlast, size_t *nexprs)
427 {
428 	BcLexType type;
429 
430 	bc_lex_next(&p->l);
431 
432 	type = BC_PARSE_LEAF(*prev, binlast, rparen) ? BC_LEX_OP_MINUS : BC_LEX_NEG;
433 	*prev = BC_PARSE_TOKEN_INST(type);
434 
435 	// We can just push onto the op stack because this is the largest
436 	// precedence operator that gets pushed. Inc/dec does not.
437 	if (type != BC_LEX_OP_MINUS) bc_vec_push(&p->ops, &type);
438 	else bc_parse_operator(p, type, ops_bgn, nexprs);
439 }
440 
bc_parse_str(BcParse * p,char inst)441 static void bc_parse_str(BcParse *p, char inst) {
442 	bc_parse_addString(p);
443 	bc_parse_push(p, inst);
444 	bc_lex_next(&p->l);
445 }
446 
bc_parse_print(BcParse * p)447 static void bc_parse_print(BcParse *p) {
448 
449 	BcLexType t;
450 	bool comma = false;
451 
452 	bc_lex_next(&p->l);
453 
454 	t = p->l.t;
455 
456 	if (bc_parse_isDelimiter(p)) bc_parse_err(p, BC_ERR_PARSE_PRINT);
457 
458 	do {
459 		if (t == BC_LEX_STR) bc_parse_str(p, BC_INST_PRINT_POP);
460 		else {
461 			bc_parse_expr_status(p, BC_PARSE_NEEDVAL, bc_parse_next_print);
462 			bc_parse_push(p, BC_INST_PRINT_POP);
463 		}
464 
465 		comma = (p->l.t == BC_LEX_COMMA);
466 
467 		if (comma) bc_lex_next(&p->l);
468 		else {
469 			if (!bc_parse_isDelimiter(p))
470 				bc_parse_err(p, BC_ERR_PARSE_TOKEN);
471 			else break;
472 		}
473 
474 		t = p->l.t;
475 	} while (true);
476 
477 	if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
478 }
479 
bc_parse_return(BcParse * p)480 static void bc_parse_return(BcParse *p) {
481 
482 	BcLexType t;
483 	bool paren;
484 	uchar inst = BC_INST_RET0;
485 
486 	if (BC_ERR(!BC_PARSE_FUNC(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
487 
488 	if (p->func->voidfn) inst = BC_INST_RET_VOID;
489 
490 	bc_lex_next(&p->l);
491 
492 	t = p->l.t;
493 	paren = t == BC_LEX_LPAREN;
494 
495 	if (bc_parse_isDelimiter(p)) bc_parse_push(p, inst);
496 	else {
497 
498 		BcParseStatus s;
499 
500 		s = bc_parse_expr_err(p, BC_PARSE_NEEDVAL, bc_parse_next_expr);
501 
502 		if (s == BC_PARSE_STATUS_EMPTY_EXPR) {
503 			bc_parse_push(p, inst);
504 			bc_lex_next(&p->l);
505 		}
506 
507 		if (!paren || p->l.last != BC_LEX_RPAREN) {
508 			bc_parse_err(p, BC_ERR_POSIX_RET);
509 		}
510 		else if (BC_ERR(p->func->voidfn))
511 			bc_parse_verr(p, BC_ERR_PARSE_RET_VOID, p->func->name);
512 
513 		bc_parse_push(p, BC_INST_RET);
514 	}
515 }
516 
bc_parse_noElse(BcParse * p)517 static void bc_parse_noElse(BcParse *p) {
518 	uint16_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
519 	*flag_ptr = (*flag_ptr & ~(BC_PARSE_FLAG_IF_END));
520 	bc_parse_setLabel(p);
521 }
522 
bc_parse_endBody(BcParse * p,bool brace)523 static void bc_parse_endBody(BcParse *p, bool brace) {
524 
525 	bool has_brace, new_else = false;
526 
527 	if (BC_ERR(p->flags.len <= 1)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
528 
529 	if (brace) {
530 
531 		assert(p->l.t == BC_LEX_RBRACE);
532 
533 		bc_lex_next(&p->l);
534 		if (BC_ERR(!bc_parse_isDelimiter(p)))
535 			bc_parse_err(p, BC_ERR_PARSE_TOKEN);
536 	}
537 
538 	has_brace = (BC_PARSE_BRACE(p) != 0);
539 
540 	do {
541 		size_t len = p->flags.len;
542 		bool loop;
543 
544 		if (has_brace && !brace) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
545 
546 		loop = (BC_PARSE_LOOP_INNER(p) != 0);
547 
548 		if (loop || BC_PARSE_ELSE(p)) {
549 
550 			if (loop) {
551 
552 				size_t *label = bc_vec_top(&p->conds);
553 
554 				bc_parse_push(p, BC_INST_JUMP);
555 				bc_parse_pushIndex(p, *label);
556 
557 				bc_vec_pop(&p->conds);
558 			}
559 
560 			bc_parse_setLabel(p);
561 			bc_vec_pop(&p->flags);
562 		}
563 		else if (BC_PARSE_FUNC_INNER(p)) {
564 			BcInst inst = (p->func->voidfn ? BC_INST_RET_VOID : BC_INST_RET0);
565 			bc_parse_push(p, inst);
566 			bc_parse_updateFunc(p, BC_PROG_MAIN);
567 			bc_vec_pop(&p->flags);
568 		}
569 		else if (BC_PARSE_BRACE(p) && !BC_PARSE_IF(p)) bc_vec_pop(&p->flags);
570 
571 		// This needs to be last to parse nested if's properly.
572 		if (BC_PARSE_IF(p) && (len == p->flags.len || !BC_PARSE_BRACE(p))) {
573 
574 			while (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l);
575 
576 			bc_vec_pop(&p->flags);
577 
578 			if (!BC_S) {
579 
580 				*(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_IF_END;
581 				new_else = (p->l.t == BC_LEX_KW_ELSE);
582 
583 				if (new_else) bc_parse_else(p);
584 				else if (!has_brace && (!BC_PARSE_IF_END(p) || brace))
585 					bc_parse_noElse(p);
586 			}
587 			else bc_parse_noElse(p);
588 		}
589 
590 		if (brace && has_brace) brace = false;
591 
592 	} while (p->flags.len > 1 && !new_else && (!BC_PARSE_IF_END(p) || brace) &&
593 	         !(has_brace = (BC_PARSE_BRACE(p) != 0)));
594 
595 	if (BC_ERR(p->flags.len == 1 && brace))
596 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
597 	else if (brace && BC_PARSE_BRACE(p)) {
598 
599 		uint16_t flags = BC_PARSE_TOP_FLAG(p);
600 
601 		if (!(flags & (BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_LOOP_INNER)) &&
602 		    !(flags & (BC_PARSE_FLAG_IF | BC_PARSE_FLAG_ELSE)) &&
603 		    !(flags & (BC_PARSE_FLAG_IF_END)))
604 		{
605 			bc_vec_pop(&p->flags);
606 		}
607 	}
608 }
609 
bc_parse_startBody(BcParse * p,uint16_t flags)610 static void bc_parse_startBody(BcParse *p, uint16_t flags) {
611 	assert(flags);
612 	flags |= (BC_PARSE_TOP_FLAG(p) & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP));
613 	flags |= BC_PARSE_FLAG_BODY;
614 	bc_vec_push(&p->flags, &flags);
615 }
616 
bc_parse_if(BcParse * p)617 static void bc_parse_if(BcParse *p) {
618 
619 	size_t idx;
620 	uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);
621 
622 	bc_lex_next(&p->l);
623 	if (BC_ERR(p->l.t != BC_LEX_LPAREN))
624 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
625 
626 	bc_lex_next(&p->l);
627 	bc_parse_expr_status(p, flags, bc_parse_next_rel);
628 	if (BC_ERR(p->l.t != BC_LEX_RPAREN))
629 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
630 
631 	bc_lex_next(&p->l);
632 	bc_parse_push(p, BC_INST_JUMP_ZERO);
633 
634 	idx = p->func->labels.len;
635 
636 	bc_parse_pushIndex(p, idx);
637 	bc_parse_createExitLabel(p, idx, false);
638 	bc_parse_startBody(p, BC_PARSE_FLAG_IF);
639 }
640 
bc_parse_else(BcParse * p)641 static void bc_parse_else(BcParse *p) {
642 
643 	size_t idx = p->func->labels.len;
644 
645 	if (BC_ERR(!BC_PARSE_IF_END(p)))
646 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
647 
648 	bc_parse_push(p, BC_INST_JUMP);
649 	bc_parse_pushIndex(p, idx);
650 
651 	bc_parse_noElse(p);
652 
653 	bc_parse_createExitLabel(p, idx, false);
654 	bc_parse_startBody(p, BC_PARSE_FLAG_ELSE);
655 
656 	bc_lex_next(&p->l);
657 }
658 
bc_parse_while(BcParse * p)659 static void bc_parse_while(BcParse *p) {
660 
661 	size_t idx;
662 	uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);
663 
664 	bc_lex_next(&p->l);
665 	if (BC_ERR(p->l.t != BC_LEX_LPAREN))
666 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
667 	bc_lex_next(&p->l);
668 
669 	bc_parse_createCondLabel(p, p->func->labels.len);
670 	idx = p->func->labels.len;
671 	bc_parse_createExitLabel(p, idx, true);
672 
673 	bc_parse_expr_status(p, flags, bc_parse_next_rel);
674 	if (BC_ERR(p->l.t != BC_LEX_RPAREN))
675 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
676 	bc_lex_next(&p->l);
677 
678 	bc_parse_push(p, BC_INST_JUMP_ZERO);
679 	bc_parse_pushIndex(p, idx);
680 	bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
681 }
682 
bc_parse_for(BcParse * p)683 static void bc_parse_for(BcParse *p) {
684 
685 	size_t cond_idx, exit_idx, body_idx, update_idx;
686 
687 	bc_lex_next(&p->l);
688 	if (BC_ERR(p->l.t != BC_LEX_LPAREN))
689 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
690 	bc_lex_next(&p->l);
691 
692 	if (p->l.t != BC_LEX_SCOLON)
693 		bc_parse_expr_status(p, 0, bc_parse_next_for);
694 	else bc_parse_err(p, BC_ERR_POSIX_FOR);
695 
696 	if (BC_ERR(p->l.t != BC_LEX_SCOLON))
697 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
698 	bc_lex_next(&p->l);
699 
700 	cond_idx = p->func->labels.len;
701 	update_idx = cond_idx + 1;
702 	body_idx = update_idx + 1;
703 	exit_idx = body_idx + 1;
704 
705 	bc_parse_createLabel(p, p->func->code.len);
706 
707 	if (p->l.t != BC_LEX_SCOLON) {
708 		uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);
709 		bc_parse_expr_status(p, flags, bc_parse_next_for);
710 	}
711 	else {
712 
713 		// Set this for the next call to bc_parse_number.
714 		// This is safe to set because the current token
715 		// is a semicolon, which has no string requirement.
716 		bc_vec_string(&p->l.str, sizeof(bc_parse_one) - 1, bc_parse_one);
717 		bc_parse_number(p);
718 
719 		bc_parse_err(p, BC_ERR_POSIX_FOR);
720 	}
721 
722 	if (BC_ERR(p->l.t != BC_LEX_SCOLON))
723 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
724 
725 	bc_lex_next(&p->l);
726 
727 	bc_parse_push(p, BC_INST_JUMP_ZERO);
728 	bc_parse_pushIndex(p, exit_idx);
729 	bc_parse_push(p, BC_INST_JUMP);
730 	bc_parse_pushIndex(p, body_idx);
731 
732 	bc_parse_createCondLabel(p, update_idx);
733 
734 	if (p->l.t != BC_LEX_RPAREN)
735 		bc_parse_expr_status(p, 0, bc_parse_next_rel);
736 	else bc_parse_err(p, BC_ERR_POSIX_FOR);
737 
738 	if (BC_ERR(p->l.t != BC_LEX_RPAREN))
739 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
740 	bc_parse_push(p, BC_INST_JUMP);
741 	bc_parse_pushIndex(p, cond_idx);
742 	bc_parse_createLabel(p, p->func->code.len);
743 
744 	bc_parse_createExitLabel(p, exit_idx, true);
745 	bc_lex_next(&p->l);
746 	bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
747 }
748 
bc_parse_loopExit(BcParse * p,BcLexType type)749 static void bc_parse_loopExit(BcParse *p, BcLexType type) {
750 
751 	size_t i;
752 	BcInstPtr *ip;
753 
754 	if (BC_ERR(!BC_PARSE_LOOP(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
755 
756 	if (type == BC_LEX_KW_BREAK) {
757 
758 		if (BC_ERR(!p->exits.len)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
759 
760 		i = p->exits.len - 1;
761 		ip = bc_vec_item(&p->exits, i);
762 
763 		while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--);
764 		assert(ip != NULL && (i < p->exits.len || ip->func));
765 		i = ip->idx;
766 	}
767 	else i = *((size_t*) bc_vec_top(&p->conds));
768 
769 	bc_parse_push(p, BC_INST_JUMP);
770 	bc_parse_pushIndex(p, i);
771 
772 	bc_lex_next(&p->l);
773 }
774 
bc_parse_func(BcParse * p)775 static void bc_parse_func(BcParse *p) {
776 
777 	bool comma = false, voidfn;
778 	uint16_t flags;
779 	size_t idx;
780 
781 	bc_lex_next(&p->l);
782 
783 	if (BC_ERR(p->l.t != BC_LEX_NAME))
784 		bc_parse_err(p, BC_ERR_PARSE_FUNC);
785 
786 	voidfn = (!BC_IS_POSIX && p->l.t == BC_LEX_NAME &&
787 	          !strcmp(p->l.str.v, "void"));
788 
789 	bc_lex_next(&p->l);
790 
791 	voidfn = (voidfn && p->l.t == BC_LEX_NAME);
792 
793 	if (voidfn) {
794 		bc_parse_err(p, BC_ERR_POSIX_VOID);
795 		bc_lex_next(&p->l);
796 	}
797 
798 	if (BC_ERR(p->l.t != BC_LEX_LPAREN))
799 		bc_parse_err(p, BC_ERR_PARSE_FUNC);
800 
801 	assert(p->prog->fns.len == p->prog->fn_map.len);
802 
803 	BC_SIG_LOCK;
804 
805 	idx = bc_program_insertFunc(p->prog, p->l.str.v);
806 
807 	BC_SIG_UNLOCK;
808 
809 	assert(idx);
810 	bc_parse_updateFunc(p, idx);
811 	p->func->voidfn = voidfn;
812 
813 	bc_lex_next(&p->l);
814 
815 	while (p->l.t != BC_LEX_RPAREN) {
816 
817 		BcType t = BC_TYPE_VAR;
818 
819 		if (p->l.t == BC_LEX_OP_MULTIPLY) {
820 			t = BC_TYPE_REF;
821 			bc_lex_next(&p->l);
822 			bc_parse_err(p, BC_ERR_POSIX_REF);
823 		}
824 
825 		if (BC_ERR(p->l.t != BC_LEX_NAME))
826 			bc_parse_err(p, BC_ERR_PARSE_FUNC);
827 
828 		p->func->nparams += 1;
829 
830 		bc_vec_string(&p->buf, p->l.str.len, p->l.str.v);
831 
832 		bc_lex_next(&p->l);
833 
834 		if (p->l.t == BC_LEX_LBRACKET) {
835 
836 			if (t == BC_TYPE_VAR) t = BC_TYPE_ARRAY;
837 
838 			bc_lex_next(&p->l);
839 
840 			if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
841 				bc_parse_err(p, BC_ERR_PARSE_FUNC);
842 
843 			bc_lex_next(&p->l);
844 		}
845 		else if (BC_ERR(t == BC_TYPE_REF))
846 			bc_parse_verr(p, BC_ERR_PARSE_REF_VAR, p->buf.v);
847 
848 		comma = (p->l.t == BC_LEX_COMMA);
849 		if (comma) {
850 			bc_lex_next(&p->l);
851 		}
852 
853 		bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line);
854 	}
855 
856 	if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_FUNC);
857 
858 	flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER;
859 	bc_parse_startBody(p, flags);
860 
861 	bc_lex_next(&p->l);
862 
863 	if (p->l.t != BC_LEX_LBRACE) bc_parse_err(p, BC_ERR_POSIX_BRACE);
864 }
865 
bc_parse_auto(BcParse * p)866 static void bc_parse_auto(BcParse *p) {
867 
868 	bool comma, one;
869 
870 	if (BC_ERR(!p->auto_part)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
871 	bc_lex_next(&p->l);
872 
873 	p->auto_part = comma = false;
874 	one = p->l.t == BC_LEX_NAME;
875 
876 	while (p->l.t == BC_LEX_NAME) {
877 
878 		BcType t;
879 
880 		bc_vec_string(&p->buf, p->l.str.len - 1, p->l.str.v);
881 
882 		bc_lex_next(&p->l);
883 
884 		if (p->l.t == BC_LEX_LBRACKET) {
885 
886 			t = BC_TYPE_ARRAY;
887 
888 			bc_lex_next(&p->l);
889 
890 			if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
891 				bc_parse_err(p, BC_ERR_PARSE_FUNC);
892 
893 			bc_lex_next(&p->l);
894 		}
895 		else t = BC_TYPE_VAR;
896 
897 		comma = (p->l.t == BC_LEX_COMMA);
898 		if (comma) bc_lex_next(&p->l);
899 
900 		bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line);
901 	}
902 
903 	if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_FUNC);
904 	if (BC_ERR(!one)) bc_parse_err(p, BC_ERR_PARSE_NO_AUTO);
905 	if (BC_ERR(!bc_parse_isDelimiter(p)))
906 		bc_parse_err(p, BC_ERR_PARSE_TOKEN);
907 }
908 
bc_parse_body(BcParse * p,bool brace)909 static void bc_parse_body(BcParse *p, bool brace) {
910 
911 	uint16_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
912 
913 	assert(flag_ptr != NULL);
914 	assert(p->flags.len >= 2);
915 
916 	*flag_ptr &= ~(BC_PARSE_FLAG_BODY);
917 
918 	if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) {
919 
920 		if (BC_ERR(!brace)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
921 
922 		p->auto_part = (p->l.t != BC_LEX_KW_AUTO);
923 
924 		if (!p->auto_part) {
925 
926 			// Make sure this is true to not get a parse error.
927 			p->auto_part = true;
928 
929 			bc_parse_auto(p);
930 		}
931 
932 		if (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l);
933 	}
934 	else {
935 
936 		size_t len = p->flags.len;
937 
938 		assert(*flag_ptr);
939 
940 		bc_parse_stmt(p);
941 
942 		if (!brace && !BC_PARSE_BODY(p) && len <= p->flags.len)
943 			bc_parse_endBody(p, false);
944 	}
945 }
946 
bc_parse_stmt(BcParse * p)947 static void bc_parse_stmt(BcParse *p) {
948 
949 	size_t len;
950 	uint16_t flags;
951 	BcLexType type = p->l.t;
952 
953 	if (type == BC_LEX_NLINE) {
954 		bc_lex_next(&p->l);
955 		return;
956 	}
957 	if (type == BC_LEX_KW_AUTO) {
958 		bc_parse_auto(p);
959 		return;
960 	}
961 
962 	p->auto_part = false;
963 
964 	if (type != BC_LEX_KW_ELSE) {
965 
966 		if (BC_PARSE_IF_END(p)) {
967 			bc_parse_noElse(p);
968 			if (p->flags.len > 1 && !BC_PARSE_BRACE(p))
969 				bc_parse_endBody(p, false);
970 			return;
971 		}
972 		else if (type == BC_LEX_LBRACE) {
973 
974 			if (!BC_PARSE_BODY(p)) {
975 				bc_parse_startBody(p, BC_PARSE_FLAG_BRACE);
976 				bc_lex_next(&p->l);
977 			}
978 			else {
979 				*(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_BRACE;
980 				bc_lex_next(&p->l);
981 				bc_parse_body(p, true);
982 			}
983 
984 			return;
985 		}
986 		else if (BC_PARSE_BODY(p) && !BC_PARSE_BRACE(p)) {
987 			bc_parse_body(p, false);
988 			return;
989 		}
990 	}
991 
992 	len = p->flags.len;
993 	flags = BC_PARSE_TOP_FLAG(p);
994 
995 	switch (type) {
996 
997 		case BC_LEX_OP_INC:
998 		case BC_LEX_OP_DEC:
999 		case BC_LEX_OP_MINUS:
1000 		case BC_LEX_OP_BOOL_NOT:
1001 		case BC_LEX_LPAREN:
1002 		case BC_LEX_NAME:
1003 		case BC_LEX_NUMBER:
1004 		case BC_LEX_KW_IBASE:
1005 		case BC_LEX_KW_LAST:
1006 		case BC_LEX_KW_LENGTH:
1007 		case BC_LEX_KW_OBASE:
1008 		case BC_LEX_KW_SCALE:
1009 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1010 		case BC_LEX_KW_SEED:
1011 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1012 		case BC_LEX_KW_SQRT:
1013 		case BC_LEX_KW_ABS:
1014 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1015 		case BC_LEX_KW_IRAND:
1016 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1017 		case BC_LEX_KW_READ:
1018 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1019 		case BC_LEX_KW_RAND:
1020 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1021 		case BC_LEX_KW_MAXIBASE:
1022 		case BC_LEX_KW_MAXOBASE:
1023 		case BC_LEX_KW_MAXSCALE:
1024 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1025 		case BC_LEX_KW_MAXRAND:
1026 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1027 		{
1028 			bc_parse_expr_status(p, BC_PARSE_PRINT, bc_parse_next_expr);
1029 			break;
1030 		}
1031 
1032 		case BC_LEX_KW_ELSE:
1033 		{
1034 			bc_parse_else(p);
1035 			break;
1036 		}
1037 
1038 		case BC_LEX_SCOLON:
1039 		{
1040 			// Do nothing.
1041 			break;
1042 		}
1043 
1044 		case BC_LEX_RBRACE:
1045 		{
1046 			bc_parse_endBody(p, true);
1047 			break;
1048 		}
1049 
1050 		case BC_LEX_STR:
1051 		{
1052 			bc_parse_str(p, BC_INST_PRINT_STR);
1053 			break;
1054 		}
1055 
1056 		case BC_LEX_KW_BREAK:
1057 		case BC_LEX_KW_CONTINUE:
1058 		{
1059 			bc_parse_loopExit(p, p->l.t);
1060 			break;
1061 		}
1062 
1063 		case BC_LEX_KW_FOR:
1064 		{
1065 			bc_parse_for(p);
1066 			break;
1067 		}
1068 
1069 		case BC_LEX_KW_HALT:
1070 		{
1071 			bc_parse_push(p, BC_INST_HALT);
1072 			bc_lex_next(&p->l);
1073 			break;
1074 		}
1075 
1076 		case BC_LEX_KW_IF:
1077 		{
1078 			bc_parse_if(p);
1079 			break;
1080 		}
1081 
1082 		case BC_LEX_KW_LIMITS:
1083 		{
1084 			bc_vm_printf("BC_LONG_BIT      = %lu\n", (ulong) BC_LONG_BIT);
1085 			bc_vm_printf("BC_BASE_DIGS     = %lu\n", (ulong) BC_BASE_DIGS);
1086 			bc_vm_printf("BC_BASE_POW      = %lu\n", (ulong) BC_BASE_POW);
1087 			bc_vm_printf("BC_OVERFLOW_MAX  = %lu\n", (ulong) BC_NUM_BIGDIG_MAX);
1088 			bc_vm_printf("\n");
1089 			bc_vm_printf("BC_BASE_MAX      = %lu\n", BC_MAX_OBASE);
1090 			bc_vm_printf("BC_DIM_MAX       = %lu\n", BC_MAX_DIM);
1091 			bc_vm_printf("BC_SCALE_MAX     = %lu\n", BC_MAX_SCALE);
1092 			bc_vm_printf("BC_STRING_MAX    = %lu\n", BC_MAX_STRING);
1093 			bc_vm_printf("BC_NAME_MAX      = %lu\n", BC_MAX_NAME);
1094 			bc_vm_printf("BC_NUM_MAX       = %lu\n", BC_MAX_NUM);
1095 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1096 			bc_vm_printf("BC_RAND_MAX      = %lu\n", BC_MAX_RAND);
1097 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1098 			bc_vm_printf("MAX Exponent     = %lu\n", BC_MAX_EXP);
1099 			bc_vm_printf("Number of vars   = %lu\n", BC_MAX_VARS);
1100 
1101 			bc_lex_next(&p->l);
1102 
1103 			break;
1104 		}
1105 
1106 		case BC_LEX_KW_PRINT:
1107 		{
1108 			bc_parse_print(p);
1109 			break;
1110 		}
1111 
1112 		case BC_LEX_KW_QUIT:
1113 		{
1114 			// Quit is a compile-time command. We don't exit directly,
1115 			// so the vm can clean up. Limits do the same thing.
1116 			vm.status = BC_STATUS_QUIT;
1117 			BC_VM_JMP;
1118 			break;
1119 		}
1120 
1121 		case BC_LEX_KW_RETURN:
1122 		{
1123 			bc_parse_return(p);
1124 			break;
1125 		}
1126 
1127 		case BC_LEX_KW_WHILE:
1128 		{
1129 			bc_parse_while(p);
1130 			break;
1131 		}
1132 
1133 		default:
1134 		{
1135 			bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1136 		}
1137 	}
1138 
1139 	if (len == p->flags.len && flags == BC_PARSE_TOP_FLAG(p)) {
1140 		if (BC_ERR(!bc_parse_isDelimiter(p)))
1141 			bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1142 	}
1143 
1144 	// Make sure semicolons are eaten.
1145 	while (p->l.t == BC_LEX_SCOLON) bc_lex_next(&p->l);
1146 }
1147 
bc_parse_parse(BcParse * p)1148 void bc_parse_parse(BcParse *p) {
1149 
1150 	assert(p);
1151 
1152 	BC_SETJMP(exit);
1153 
1154 	if (BC_ERR(p->l.t == BC_LEX_EOF)) bc_parse_err(p, BC_ERR_PARSE_EOF);
1155 	else if (p->l.t == BC_LEX_KW_DEFINE) {
1156 		if (BC_ERR(BC_PARSE_NO_EXEC(p)))
1157 			bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1158 		bc_parse_func(p);
1159 	}
1160 	else bc_parse_stmt(p);
1161 
1162 exit:
1163 	BC_SIG_MAYLOCK;
1164 	if (BC_ERR(((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig)))
1165 		bc_parse_reset(p);
1166 	BC_LONGJMP_CONT;
1167 }
1168 
bc_parse_expr_err(BcParse * p,uint8_t flags,BcParseNext next)1169 static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
1170                                        BcParseNext next)
1171 {
1172 	BcInst prev = BC_INST_PRINT;
1173 	uchar inst = BC_INST_INVALID;
1174 	BcLexType top, t = p->l.t;
1175 	size_t nexprs = 0, ops_bgn = p->ops.len;
1176 	uint32_t i, nparens, nrelops;
1177 	bool pfirst, rprn, done, get_token, assign, bin_last, incdec, can_assign;
1178 
1179 	assert(!(flags & BC_PARSE_PRINT) || !(flags & BC_PARSE_NEEDVAL));
1180 
1181 	pfirst = (p->l.t == BC_LEX_LPAREN);
1182 	nparens = nrelops = 0;
1183 	rprn = done = get_token = assign = incdec = can_assign = false;
1184 	bin_last = true;
1185 
1186 	// We want to eat newlines if newlines are not a valid ending token.
1187 	// This is for spacing in things like for loop headers.
1188 	if (!(flags & BC_PARSE_NOREAD)) {
1189 		while ((t = p->l.t) == BC_LEX_NLINE) bc_lex_next(&p->l);
1190 	}
1191 
1192 	for (; !done && BC_PARSE_EXPR(t); t = p->l.t)
1193 	{
1194 		switch (t) {
1195 
1196 			case BC_LEX_OP_INC:
1197 			case BC_LEX_OP_DEC:
1198 			{
1199 				if (BC_ERR(incdec)) bc_parse_err(p, BC_ERR_PARSE_ASSIGN);
1200 				bc_parse_incdec(p, &prev, &can_assign, &nexprs, flags);
1201 				rprn = get_token = bin_last = false;
1202 				incdec = true;
1203 				flags &= ~(BC_PARSE_ARRAY);
1204 				break;
1205 			}
1206 
1207 #if BC_ENABLE_EXTRA_MATH
1208 			case BC_LEX_OP_TRUNC:
1209 			{
1210 				if (BC_ERR(!BC_PARSE_LEAF(prev, bin_last, rprn)))
1211 					bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1212 
1213 				// I can just add the instruction because
1214 				// negative will already be taken care of.
1215 				bc_parse_push(p, BC_INST_TRUNC);
1216 				rprn = can_assign = incdec = false;
1217 				get_token = true;
1218 				flags &= ~(BC_PARSE_ARRAY);
1219 				break;
1220 			}
1221 #endif // BC_ENABLE_EXTRA_MATH
1222 
1223 			case BC_LEX_OP_MINUS:
1224 			{
1225 				bc_parse_minus(p, &prev, ops_bgn, rprn, bin_last, &nexprs);
1226 				rprn = get_token = can_assign = false;
1227 				bin_last = (prev == BC_INST_MINUS);
1228 				if (bin_last) incdec = false;
1229 				flags &= ~(BC_PARSE_ARRAY);
1230 				break;
1231 			}
1232 
1233 			case BC_LEX_OP_ASSIGN_POWER:
1234 			case BC_LEX_OP_ASSIGN_MULTIPLY:
1235 			case BC_LEX_OP_ASSIGN_DIVIDE:
1236 			case BC_LEX_OP_ASSIGN_MODULUS:
1237 			case BC_LEX_OP_ASSIGN_PLUS:
1238 			case BC_LEX_OP_ASSIGN_MINUS:
1239 #if BC_ENABLE_EXTRA_MATH
1240 			case BC_LEX_OP_ASSIGN_PLACES:
1241 			case BC_LEX_OP_ASSIGN_LSHIFT:
1242 			case BC_LEX_OP_ASSIGN_RSHIFT:
1243 #endif // BC_ENABLE_EXTRA_MATH
1244 			case BC_LEX_OP_ASSIGN:
1245 			{
1246 				if (!BC_PARSE_INST_VAR(prev))
1247 					bc_parse_err(p, BC_ERR_PARSE_ASSIGN);
1248 			}
1249 			// Fallthrough.
1250 			BC_FALLTHROUGH
1251 
1252 			case BC_LEX_OP_POWER:
1253 			case BC_LEX_OP_MULTIPLY:
1254 			case BC_LEX_OP_DIVIDE:
1255 			case BC_LEX_OP_MODULUS:
1256 			case BC_LEX_OP_PLUS:
1257 #if BC_ENABLE_EXTRA_MATH
1258 			case BC_LEX_OP_PLACES:
1259 			case BC_LEX_OP_LSHIFT:
1260 			case BC_LEX_OP_RSHIFT:
1261 #endif // BC_ENABLE_EXTRA_MATH
1262 			case BC_LEX_OP_REL_EQ:
1263 			case BC_LEX_OP_REL_LE:
1264 			case BC_LEX_OP_REL_GE:
1265 			case BC_LEX_OP_REL_NE:
1266 			case BC_LEX_OP_REL_LT:
1267 			case BC_LEX_OP_REL_GT:
1268 			case BC_LEX_OP_BOOL_NOT:
1269 			case BC_LEX_OP_BOOL_OR:
1270 			case BC_LEX_OP_BOOL_AND:
1271 			{
1272 				if (BC_PARSE_OP_PREFIX(t)) {
1273 					if (BC_ERR(!bin_last && !BC_PARSE_OP_PREFIX(p->l.last)))
1274 						bc_parse_err(p, BC_ERR_PARSE_EXPR);
1275 				}
1276 				else if (BC_ERR(BC_PARSE_PREV_PREFIX(prev) || bin_last))
1277 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
1278 
1279 				nrelops += (t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT);
1280 				prev = BC_PARSE_TOKEN_INST(t);
1281 				bc_parse_operator(p, t, ops_bgn, &nexprs);
1282 				rprn = incdec = can_assign = false;
1283 				get_token = true;
1284 				bin_last = !BC_PARSE_OP_PREFIX(t);
1285 				flags &= ~(BC_PARSE_ARRAY);
1286 
1287 				break;
1288 			}
1289 
1290 			case BC_LEX_LPAREN:
1291 			{
1292 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1293 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
1294 
1295 				nparens += 1;
1296 				rprn = incdec = can_assign = false;
1297 				get_token = true;
1298 				bc_vec_push(&p->ops, &t);
1299 
1300 				break;
1301 			}
1302 
1303 			case BC_LEX_RPAREN:
1304 			{
1305 				// This needs to be a status. The error
1306 				// is handled in bc_parse_expr_status().
1307 				if (BC_ERR(p->l.last == BC_LEX_LPAREN))
1308 					return BC_PARSE_STATUS_EMPTY_EXPR;
1309 
1310 				if (BC_ERR(bin_last || BC_PARSE_PREV_PREFIX(prev)))
1311 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
1312 
1313 				if (!nparens) {
1314 					done = true;
1315 					get_token = false;
1316 					break;
1317 				}
1318 
1319 				nparens -= 1;
1320 				rprn = true;
1321 				get_token = bin_last = incdec = false;
1322 
1323 				bc_parse_rightParen(p, &nexprs);
1324 
1325 				break;
1326 			}
1327 
1328 			case BC_LEX_NAME:
1329 			{
1330 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1331 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
1332 
1333 				get_token = bin_last = false;
1334 				bc_parse_name(p, &prev, &can_assign,
1335 				                  flags & ~BC_PARSE_NOCALL);
1336 				rprn = (prev == BC_INST_CALL);
1337 				nexprs += 1;
1338 				flags &= ~(BC_PARSE_ARRAY);
1339 
1340 				break;
1341 			}
1342 
1343 			case BC_LEX_NUMBER:
1344 			{
1345 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1346 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
1347 
1348 				bc_parse_number(p);
1349 				nexprs += 1;
1350 				prev = BC_INST_NUM;
1351 				get_token = true;
1352 				rprn = bin_last = can_assign = false;
1353 				flags &= ~(BC_PARSE_ARRAY);
1354 
1355 				break;
1356 			}
1357 
1358 			case BC_LEX_KW_IBASE:
1359 			case BC_LEX_KW_LAST:
1360 			case BC_LEX_KW_OBASE:
1361 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1362 			case BC_LEX_KW_SEED:
1363 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1364 			{
1365 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1366 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
1367 
1368 				prev = t - BC_LEX_KW_LAST + BC_INST_LAST;
1369 				bc_parse_push(p, prev);
1370 
1371 				get_token = can_assign = true;
1372 				rprn = bin_last = false;
1373 				nexprs += 1;
1374 				flags &= ~(BC_PARSE_ARRAY);
1375 
1376 				break;
1377 			}
1378 
1379 			case BC_LEX_KW_LENGTH:
1380 			case BC_LEX_KW_SQRT:
1381 			case BC_LEX_KW_ABS:
1382 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1383 			case BC_LEX_KW_IRAND:
1384 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1385 			{
1386 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1387 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
1388 
1389 				bc_parse_builtin(p, t, flags, &prev);
1390 				rprn = get_token = bin_last = incdec = can_assign = false;
1391 				nexprs += 1;
1392 				flags &= ~(BC_PARSE_ARRAY);
1393 
1394 				break;
1395 			}
1396 
1397 			case BC_LEX_KW_READ:
1398 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1399 			case BC_LEX_KW_RAND:
1400 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1401 			case BC_LEX_KW_MAXIBASE:
1402 			case BC_LEX_KW_MAXOBASE:
1403 			case BC_LEX_KW_MAXSCALE:
1404 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1405 			case BC_LEX_KW_MAXRAND:
1406 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1407 			{
1408 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1409 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
1410 				else if (t == BC_LEX_KW_READ && BC_ERR(flags & BC_PARSE_NOREAD))
1411 					bc_parse_err(p, BC_ERR_EXEC_REC_READ);
1412 				else {
1413 					prev = t - BC_LEX_KW_READ + BC_INST_READ;
1414 					bc_parse_noArgBuiltin(p, prev);
1415 				}
1416 
1417 				rprn = get_token = bin_last = incdec = can_assign = false;
1418 				nexprs += 1;
1419 				flags &= ~(BC_PARSE_ARRAY);
1420 
1421 				break;
1422 			}
1423 
1424 			case BC_LEX_KW_SCALE:
1425 			{
1426 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1427 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
1428 
1429 				bc_parse_scale(p, &prev, &can_assign, flags);
1430 				rprn = get_token = bin_last = false;
1431 				nexprs += 1;
1432 				flags &= ~(BC_PARSE_ARRAY);
1433 
1434 				break;
1435 			}
1436 
1437 			default:
1438 			{
1439 #ifndef NDEBUG
1440 				bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1441 				break;
1442 #endif // NDEBUG
1443 			}
1444 		}
1445 
1446 		if (get_token) bc_lex_next(&p->l);
1447 	}
1448 
1449 	while (p->ops.len > ops_bgn) {
1450 
1451 		top = BC_PARSE_TOP_OP(p);
1452 		assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN;
1453 
1454 		if (BC_ERR(top == BC_LEX_LPAREN || top == BC_LEX_RPAREN))
1455 			bc_parse_err(p, BC_ERR_PARSE_EXPR);
1456 
1457 		bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
1458 
1459 		nexprs -= !BC_PARSE_OP_PREFIX(top);
1460 		bc_vec_pop(&p->ops);
1461 
1462 		incdec = false;
1463 	}
1464 
1465 	if (BC_ERR(nexprs != 1)) bc_parse_err(p, BC_ERR_PARSE_EXPR);
1466 
1467 	for (i = 0; i < next.len && t != next.tokens[i]; ++i);
1468 	if (BC_ERR(i == next.len && !bc_parse_isDelimiter(p)))
1469 		bc_parse_err(p, BC_ERR_PARSE_EXPR);
1470 
1471 	if (!(flags & BC_PARSE_REL) && nrelops)
1472 		bc_parse_err(p, BC_ERR_POSIX_REL_POS);
1473 	else if ((flags & BC_PARSE_REL) && nrelops > 1)
1474 		bc_parse_err(p, BC_ERR_POSIX_MULTIREL);
1475 
1476 	if (!(flags & BC_PARSE_NEEDVAL) && !pfirst) {
1477 
1478 		if (assign) {
1479 			inst = *((uchar*) bc_vec_top(&p->func->code));
1480 			inst += (BC_INST_ASSIGN_POWER_NO_VAL - BC_INST_ASSIGN_POWER);
1481 			incdec = false;
1482 		}
1483 		else if (incdec && !(flags & BC_PARSE_PRINT)) {
1484 			inst = *((uchar*) bc_vec_top(&p->func->code));
1485 			incdec = (inst <= BC_INST_DEC);
1486 			inst = BC_INST_ASSIGN_PLUS_NO_VAL + (inst != BC_INST_INC &&
1487 			                                     inst != BC_INST_ASSIGN_PLUS);
1488 		}
1489 
1490 		if (inst >= BC_INST_ASSIGN_POWER_NO_VAL &&
1491 		    inst <= BC_INST_ASSIGN_NO_VAL)
1492 		{
1493 			bc_vec_pop(&p->func->code);
1494 			if (incdec) bc_parse_push(p, BC_INST_ONE);
1495 			bc_parse_push(p, inst);
1496 		}
1497 	}
1498 
1499 	if ((flags & BC_PARSE_PRINT)) {
1500 		if (pfirst || !assign) bc_parse_push(p, BC_INST_PRINT);
1501 	}
1502 	else if (!(flags & BC_PARSE_NEEDVAL) &&
1503 	         (inst < BC_INST_ASSIGN_POWER_NO_VAL ||
1504 	          inst > BC_INST_ASSIGN_NO_VAL))
1505 	{
1506 		bc_parse_push(p, BC_INST_POP);
1507 	}
1508 
1509 	// We want to eat newlines if newlines are not a valid ending token.
1510 	// This is for spacing in things like for loop headers.
1511 	for (incdec = true, i = 0; i < next.len && incdec; ++i)
1512 		incdec = (next.tokens[i] != BC_LEX_NLINE);
1513 	if (incdec) {
1514 		while (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l);
1515 	}
1516 
1517 	return BC_PARSE_STATUS_SUCCESS;
1518 }
1519 
bc_parse_expr_status(BcParse * p,uint8_t flags,BcParseNext next)1520 void bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next) {
1521 
1522 	BcParseStatus s = bc_parse_expr_err(p, flags, next);
1523 
1524 	if (BC_ERR(s == BC_PARSE_STATUS_EMPTY_EXPR))
1525 		bc_parse_err(p, BC_ERR_PARSE_EMPTY_EXPR);
1526 }
1527 
bc_parse_expr(BcParse * p,uint8_t flags)1528 void bc_parse_expr(BcParse *p, uint8_t flags) {
1529 	assert(p);
1530 	bc_parse_expr_status(p, flags, bc_parse_next_read);
1531 }
1532 #endif // BC_ENABLED
1533